From ec13f2d15f02b94e129340c83f092ac2e8df9fb9 Mon Sep 17 00:00:00 2001 From: Martijn Vermaat <martijn@vermaat.name> Date: Thu, 12 Dec 2013 15:30:29 +0100 Subject: [PATCH] Use entrypoints instead of bin scripts --- bin/mutalyzer-cache-sync | 49 ---------- bin/mutalyzer-json-service.wsgi | 45 --------- bin/mutalyzer-mapping-import | 89 ----------------- bin/mutalyzer-mapping-update | 56 ----------- bin/mutalyzer-soap-service.wsgi | 46 --------- bin/mutalyzer-website.wsgi | 56 ----------- mutalyzer/entrypoints/__init__.py | 3 + .../entrypoints/batch_processor.py | 43 +++++--- mutalyzer/entrypoints/cache_sync.py | 52 ++++++++++ mutalyzer/entrypoints/mapping_import.py | 97 +++++++++++++++++++ mutalyzer/entrypoints/mapping_update.py | 56 +++++++++++ .../entrypoints/mutalyzer.py | 58 +++++------ mutalyzer/entrypoints/service_json.py | 52 ++++++++++ mutalyzer/entrypoints/service_soap.py | 53 ++++++++++ mutalyzer/entrypoints/website.py | 72 ++++++++++++++ setup.py | 22 +++-- 16 files changed, 451 insertions(+), 398 deletions(-) delete mode 100755 bin/mutalyzer-cache-sync delete mode 100755 bin/mutalyzer-json-service.wsgi delete mode 100755 bin/mutalyzer-mapping-import delete mode 100755 bin/mutalyzer-mapping-update delete mode 100755 bin/mutalyzer-soap-service.wsgi delete mode 100755 bin/mutalyzer-website.wsgi create mode 100644 mutalyzer/entrypoints/__init__.py rename bin/mutalyzer-batchd => mutalyzer/entrypoints/batch_processor.py (61%) mode change 100755 => 100644 create mode 100644 mutalyzer/entrypoints/cache_sync.py create mode 100644 mutalyzer/entrypoints/mapping_import.py create mode 100644 mutalyzer/entrypoints/mapping_update.py rename bin/mutalyzer => mutalyzer/entrypoints/mutalyzer.py (76%) mode change 100755 => 100644 create mode 100644 mutalyzer/entrypoints/service_json.py create mode 100644 mutalyzer/entrypoints/service_soap.py create mode 100644 mutalyzer/entrypoints/website.py diff --git a/bin/mutalyzer-cache-sync b/bin/mutalyzer-cache-sync deleted file mode 100755 index 5e012949..00000000 --- a/bin/mutalyzer-cache-sync +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/env python -""" -Synchronize the database cache with other Mutalyzer instances. - -Usage: - {command} remote_wsdl url_template days - - remote_wsdl: Location of the remote WSDL description. - url_template: URL to remote downloads, where {{file}} is to be substituted - by the filename. - days: Number of days to go back in the remote cache. - - -This program is intended to be run daily from cron. Example: - - 25 5 * * * mutalyzer-cache-sync 'http://dom1/?wsdl' 'http://dom1/{file}' 7 - 55 5 * * * mutalyzer-cache-sync 'http://dom2/?wsdl' 'http://dom2/{file}' 7 -""" - - -import sys - -from mutalyzer.output import Output -from mutalyzer.sync import CacheSync -from mutalyzer import Db -from mutalyzer.util import format_usage - - -def cache_sync(remote_wsdl, url_template, days): - """ - Synchronize the database cache with other Mutalyzer instances. - """ - output = Output(__file__) - database = Db.Cache() - - sync = CacheSync(output, database) - sync.sync_with_remote(remote_wsdl, url_template, days) - - -if __name__ == '__main__': - if len(sys.argv) < 4: - print format_usage() - sys.exit(1) - try: - days = int(sys.argv[3]) - except ValueError: - print 'Last argument must be an integer.' - sys.exit(1) - cache_sync(sys.argv[1], sys.argv[2], int(sys.argv[3])) diff --git a/bin/mutalyzer-json-service.wsgi b/bin/mutalyzer-json-service.wsgi deleted file mode 100755 index bb7dc7d9..00000000 --- a/bin/mutalyzer-json-service.wsgi +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/env python -""" -WSGI interface to the Mutalyzer HTTP/RPC+JSON web service. - -The WSGI interface is exposed through the module variable 'application'. - -Example Apache/mod_wsgi configuration: - - WSGIScriptAlias /json /usr/local/bin/mutalyzer-json-service.wsgi - -Be sure to have this line first if you also define a / alias, like this: - - WSGIScriptAlias /services /usr/local/bin/mutalyzer-json-service.wsgi - WSGIScriptAlias / /usr/local/bin/mutalyzer-website.wsgi - -You can also use the built-in HTTP server by running this file directly. - -To start the built-in HTTP server on port 8082: - - /usr/local/bin/mutalyzer-json-service.wsgi 8082 -""" - - -import sys -from wsgiref.simple_server import make_server -from spyne.server.wsgi import WsgiApplication -from mutalyzer.services import json - - -DEFAULT_PORT = 8082 - - -application = WsgiApplication(json.application) - - -if __name__ == '__main__': - port = DEFAULT_PORT - if len(sys.argv) > 1: - try: - port = int(sys.argv[1]) - except ValueError: - print 'Not a valid port number: %s' % sys.argv[1] - sys.exit(1) - print 'Listening at http://localhost:%d/' % port - make_server('localhost', port, application).serve_forever() diff --git a/bin/mutalyzer-mapping-import b/bin/mutalyzer-mapping-import deleted file mode 100755 index e680dc10..00000000 --- a/bin/mutalyzer-mapping-import +++ /dev/null @@ -1,89 +0,0 @@ -#!/usr/bin/env python -""" -Update the database with mapping information for the given gene or genomic -reference. - -Usage: - {command} source database gene|reference - - source: Import source, 'gene' for importing a specific gene from the UCSC - or 'reference' for importing from genomic reference. - database: Database to update (i.e. 'hg18' or 'hg19'). - gene: Name of gene to import all transcripts mappings for from the UCSC - database (e.g. 'TTN'). - reference: Genomic reference to import all genes from (e.g. 'NC_012920.1'). - Not that currently no exon locations are supported, this has only - been tested on mtDNA. - - -This program is intended to be run manually whenever transcript mappings for -specific genes are required that are not yet in our database (i.e. they are -not yet available from the NCBI, or they are mtDNA genes). It will not -overwrite transcript/version entries that are already in our database. -""" - - -import sys - -from mutalyzer.output import Output -from mutalyzer.mapping import UCSCUpdater, ReferenceUpdater -from mutalyzer.util import format_usage - - -def import_gene(database, gene): - """ - Update the database with information from the UCSC. - - @arg database: Database to update (i.e. 'hg18' or 'hg19'). - @type database: string - @arg gene: Gene name to get transcript mapping info for. - @type gene: string - - @todo: Also report how much was added/updated. - """ - output = Output(__file__) - output.addMessage(__file__, -1, 'INFO', - 'Starting UCSC mapping data update (gene: %s)' % gene) - - updater = UCSCUpdater(database) - updater.load(gene) - updater.merge() - - output.addMessage(__file__, -1, 'INFO', - 'UCSC mapping data update end (gene: %s)' % gene) - - -def import_reference(database, reference): - """ - Update the database with information from the given reference. - - @arg database: Database to update (i.e. 'hg18' or 'hg19'). - @type database: string - @arg reference: Reference to get gene mappings from. - @type reference: string - - @todo: Also report how much was added/updated. - """ - output = Output(__file__) - output.addMessage(__file__, -1, 'INFO', - 'Starting reference mapping data update (reference: %s)' % reference) - - updater = ReferenceUpdater(database) - updater.load(reference, output) - updater.merge() - - output.addMessage(__file__, -1, 'INFO', - 'Reference mapping data update end (reference: %s)' % reference) - - -if __name__ == '__main__': - if len(sys.argv) != 4: - print format_usage() - sys.exit(1) - if sys.argv[1] == 'gene': - import_gene(*sys.argv[2:]) - elif sys.argv[1] == 'reference': - import_reference(*sys.argv[2:]) - else: - print format_usage() - sys.exit(1) diff --git a/bin/mutalyzer-mapping-update b/bin/mutalyzer-mapping-update deleted file mode 100755 index 8fe6bb35..00000000 --- a/bin/mutalyzer-mapping-update +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/env python -""" -Update the database with mapping information from the NCBI. - -Usage: - {command} database mapping_file assembly - - database: Database to update (i.e. 'hg18' or 'hg19'). - mapping_file: Path to the NCBI mapping information. - assembly: Use only entries from this assembly (this is the 'group_name' - column in the NCBI mapping file). - - -This program is intended to be run daily from cron. Example: - - 25 6 * * * mutalyzer-mapping-update hg19 /tmp/seq_gene.md reference -""" - - -import sys - -from mutalyzer.output import Output -from mutalyzer.mapping import NCBIUpdater -from mutalyzer.util import format_usage - - -def main(database, mapping_file, assembly): - """ - Update the database with information from the NCBI. - - @arg database: Database to update (i.e. 'hg18' or 'hg19'). - @type database: string - @arg mapping_file: Path to NCBI mapping information. - @type mapping_file: string - @arg assembly: Use only entries from this assembly (this is the - 'group_name' column in the NCBI mapping file). - @type assembly: string - - @todo: Also report how much was added/updated. - """ - output = Output(__file__) - output.addMessage(__file__, -1, 'INFO', - 'Starting NCBI mapping data update') - - updater = NCBIUpdater(database) - updater.load(mapping_file, assembly) - updater.merge() - - output.addMessage(__file__, -1, 'INFO', 'NCBI mapping data update end') - - -if __name__ == '__main__': - if len(sys.argv) != 4: - print format_usage() - sys.exit(1) - main(*sys.argv[1:]) diff --git a/bin/mutalyzer-soap-service.wsgi b/bin/mutalyzer-soap-service.wsgi deleted file mode 100755 index 31f7b797..00000000 --- a/bin/mutalyzer-soap-service.wsgi +++ /dev/null @@ -1,46 +0,0 @@ -#!/usr/bin/env python -""" -WSGI interface to the Mutalyzer SOAP web service. - -The WSGI interface is exposed through the module variable 'application'. - -Example Apache/mod_wsgi configuration: - - WSGIScriptAlias /services /usr/local/bin/mutalyzer-soap-service.wsgi - -Be sure to have this line first if you also define a / alias, like this: - - WSGIScriptAlias /services /usr/local/bin/mutalyzer-soap-service.wsgi - WSGIScriptAlias / /usr/local/bin/mutalyzer-website.wsgi - -You can also use the built-in HTTP server by running this file directly. - -To start the built-in HTTP server on port 8081: - - /usr/local/bin/mutalyzer-soap-service.wsgi 8081 -""" - - -import sys -from wsgiref.simple_server import make_server -from spyne.server.wsgi import WsgiApplication -from mutalyzer.services import soap - - -DEFAULT_PORT = 8081 - - -application = WsgiApplication(soap.application) - - -if __name__ == '__main__': - port = DEFAULT_PORT - if len(sys.argv) > 1: - try: - port = int(sys.argv[1]) - except ValueError: - print 'Not a valid port number: %s' % sys.argv[1] - sys.exit(1) - print 'Listening at http://localhost:%d/' % port - print 'WDSL file is at http://localhost:%d/?wsdl' % port - make_server('localhost', port, application).serve_forever() diff --git a/bin/mutalyzer-website.wsgi b/bin/mutalyzer-website.wsgi deleted file mode 100755 index 237e7279..00000000 --- a/bin/mutalyzer-website.wsgi +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/env python -""" -WSGI interface to the Mutalyzer website. - -The WSGI interface is exposed through the module variable 'application'. -Static files are not handled by this interface and should be served through -the '/static' url prefix separately. - -Example Apache/mod_wsgi configuration: - - Alias /static /var/www/mutalyzer/static - WSGIScriptAlias / /usr/local/bin/mutalyzer-website.wsgi - -You can also use the built-in HTTP server by running this file directly. -Note, however, that static files are only found by this server in a 'static' -subdirectory of the current working directory. If you're running Mutalyzer -from its source code directory, you can satisfy this by creating a quick -symbolic link: - - ln -s mutalyzer/templates/static - -Another common practice is to use Nginx to directly serve the static files -and act as a reverse proxy server to the Mutalyzer HTTP server. - -Example Nginx configuration: - - server { - listen 80; - location /static/ { - root /var/www/mutalyzer/static; - if (-f $request_filename) { - rewrite ^/static/(.*)$ /static/$1 break; - } - } - location / { - proxy_read_timeout 300; # 5 minutes - proxy_pass http://127.0.0.1:8080; - } - } - -Now start the built-in HTTP server on port 8080: - - mutalyzer-website.wsgi 8080 - -@todo: Integrate webservice.py (http://webpy.org/cookbook/webservice/). -""" - - -from mutalyzer import website - - -application = website.app.wsgifunc() - - -if __name__ == '__main__': - website.app.run() diff --git a/mutalyzer/entrypoints/__init__.py b/mutalyzer/entrypoints/__init__.py new file mode 100644 index 00000000..9644b1aa --- /dev/null +++ b/mutalyzer/entrypoints/__init__.py @@ -0,0 +1,3 @@ +""" +Entry points to Mutalyzer. +""" diff --git a/bin/mutalyzer-batchd b/mutalyzer/entrypoints/batch_processor.py old mode 100755 new mode 100644 similarity index 61% rename from bin/mutalyzer-batchd rename to mutalyzer/entrypoints/batch_processor.py index 84f7869f..18cffd72 --- a/bin/mutalyzer-batchd +++ b/mutalyzer/entrypoints/batch_processor.py @@ -1,39 +1,37 @@ -#!/usr/bin/env python """ -Daemon for processing scheduled batch jobs. +Mutalyzer batch processor. -The process can be shutdown gracefully by sending a SIGINT (Ctrl+C) or SIGTERM -signal. - -@todo: Get rid of ugly exception logging. -@todo: Reload configuration without restarting (for example, on SIGHUP). +.. todo: Get rid of ugly exception logging. +.. todo: Reload configuration without restarting (for example, on SIGHUP). """ +import argparse import signal import sys import time import traceback -from mutalyzer import config -from mutalyzer.Db import Batch, Counter -from mutalyzer.Scheduler import Scheduler +from .. import config +from .. import Db +from .. import Scheduler -def daemonize(): +def process(): """ Run forever in a loop processing scheduled batch jobs. """ - database = Batch() - counter = Counter() - scheduler = Scheduler(database) + database = Db.Batch() + counter = Db.Counter() + scheduler = Scheduler.Scheduler(database) def handle_exit(signum, stack_frame): if scheduler.stopped(): sys.stderr.write('mutalyzer-batchd: Terminated\n') sys.exit(1) if signum == signal.SIGINT: - sys.stderr.write('mutalyzer-batchd: Hitting Ctrl+C again will terminate any running job!\n') + sys.stderr.write('mutalyzer-batchd: Hitting Ctrl+C again will ' + 'terminate any running job!\n') scheduler.stop() signal.signal(signal.SIGTERM, handle_exit) @@ -59,5 +57,18 @@ def daemonize(): sys.exit(0) +def main(): + """ + Command line interface to the batch processor. + """ + parser = argparse.ArgumentParser( + description='Mutalyzer batch processor.', + epilog='The process can be shutdown gracefully by sending a SIGINT ' + '(Ctrl+C) or SIGTERM signal.') + + parser.parse_args() + process() + + if __name__ == '__main__': - daemonize() + main() diff --git a/mutalyzer/entrypoints/cache_sync.py b/mutalyzer/entrypoints/cache_sync.py new file mode 100644 index 00000000..f238ce62 --- /dev/null +++ b/mutalyzer/entrypoints/cache_sync.py @@ -0,0 +1,52 @@ +""" +Synchronize the database cache with other Mutalyzer instances. + +This program is intended to be run daily from cron. Example: + + 25 5 * * * mutalyzer-cache-sync 'http://dom1/?wsdl' 'http://dom1/{file}' -H 7 + 55 5 * * * mutalyzer-cache-sync 'http://dom2/?wsdl' 'http://dom2/{file}' -H 7 +""" + + +import argparse + +from .. import Db +from .. import output +from .. import sync + + +def sync_cache(remote_wsdl, url_template, history=7): + """ + Synchronize the database cache with other Mutalyzer instances. + """ + output = output.Output(__file__) + database = Db.Cache() + + cache_sync = sync.CacheSync(output, database) + cache_sync.sync_with_remote(remote_wsdl, url_template, history) + + +def main(): + """ + Command-line interface to the cache synchronizer. + """ + parser = argparse.ArgumentParser( + description='Mutalyzer cache synchronizer.') + parser.add_argument( + 'wsdl', metavar='WSDL', + help='location of the remote WSDL description') + parser.add_argument( + 'url_template', metavar='URL_TEMPLATE', + help='URL for remote downloads, in which the filename is to be ' + 'substituted for {{file}}') + parser.add_argument( + '-H', '--history', metavar='DAYS', dest='history', type=int, + default=7, help='number of days to go back in the remote cache ' + '(default: 7)') + + args = parser.parse_args() + sync_cache(args.wsdl, args.url_template, history=args.history) + + +if __name__ == '__main__': + main() diff --git a/mutalyzer/entrypoints/mapping_import.py b/mutalyzer/entrypoints/mapping_import.py new file mode 100644 index 00000000..4982ad1a --- /dev/null +++ b/mutalyzer/entrypoints/mapping_import.py @@ -0,0 +1,97 @@ +""" +Update the database with mapping information for the given gene or genomic +reference. +""" + + +import argparse + +from .. import output +from .. import mapping + + +def import_gene(database, gene): + """ + Update the database with information from the UCSC. + + .. todo: Also report how much was added/updated. + """ + o = output.Output(__file__) + o.addMessage(__file__, -1, 'INFO', + 'Starting UCSC mapping data update (gene: %s)' % gene) + + updater = mapping.UCSCUpdater(database) + updater.load(gene) + updater.merge() + + o.addMessage(__file__, -1, 'INFO', + 'UCSC mapping data update end (gene: %s)' % gene) + + +def import_reference(database, reference): + """ + Update the database with information from the given reference. + + .. todo: Also report how much was added/updated. + + .. note: Currently no exon locations are supported, this has only been + tested on mtDNA. + """ + o = output.Output(__file__) + o.addMessage(__file__, -1, 'INFO', + 'Starting reference mapping data update (reference: %s)' % reference) + + updater = mapping.ReferenceUpdater(database) + updater.load(reference, o) + updater.merge() + + o.addMessage(__file__, -1, 'INFO', + 'Reference mapping data update end (reference: %s)' % reference) + + +def main(): + """ + Command-line interface to the mapping importer. + """ + database_parser = argparse.ArgumentParser(add_help=False) + database_parser.add_argument( + '-d', '--database', metavar='DATABASE', dest='database', + default='hg19', help='database to import to (default: hg19)') + + parser = argparse.ArgumentParser( + description='Mutalyzer mapping importer.', + epilog='This program is intended to be run manually whenever ' + 'transcript mappings for specific genes are required that are not ' + 'yet in our database (i.e., they are not yet available from the ' + 'NCBI, or they are mtDNA genes). It will not overwrite ' + 'transcript/version entries that are already in our database.', + parents=[database_parser]) + + subparsers = parser.add_subparsers( + title='subcommands', dest='subcommand', help='subcommand help') + + p = subparsers.add_parser( + 'gene', help='import gene', parents=[database_parser], + description='Import gene mapping from the UCSC.') + p.add_argument( + 'gene', metavar='GENE_SYMBOL', + help='gene to import all transcript mappings for from the UCSC ' + 'database (example: TTN)') + + p = subparsers.add_parser( + 'reference', help='import reference', parents=[database_parser], + description='Import genomic reference file') + p.add_argument( + 'reference', metavar='FILE', + help='genomic reference to import all genes from (example: ' + 'NC_012920.1)') + + args = parser.parse_args() + if args.subcommand == 'gene': + import_gene(args.database, args.gene) + if args.subcommand == 'reference': + import_reference(args.database, args.reference) + + +if __name__ == '__main__': + main() diff --git a/mutalyzer/entrypoints/mapping_update.py b/mutalyzer/entrypoints/mapping_update.py new file mode 100644 index 00000000..d63fbe7b --- /dev/null +++ b/mutalyzer/entrypoints/mapping_update.py @@ -0,0 +1,56 @@ +""" +Update the database with mapping information from the NCBI. + +This program is intended to be run daily from cron. Example: + + 25 6 * * * mutalyzer-mapping-update hg19 /tmp/seq_gene.md reference +""" + + +import argparse + +from .. import output +from .. import mapping + + +def update_mapping(database, mapping_file, assembly): + """ + Update the database with information from the NCBI. + + .. todo: Also report how much was added/updated. + """ + o = output.Output(__file__) + o.addMessage(__file__, -1, 'INFO', + 'Starting NCBI mapping data update') + + updater = mapping.NCBIUpdater(database) + updater.load(mapping_file, assembly) + updater.merge() + + o.addMessage(__file__, -1, 'INFO', 'NCBI mapping data update end') + + +def main(): + """ + Command-line interface to the mapping updater. + """ + parser = argparse.ArgumentParser( + description='Mutalyzer mapping updater.') + + parser.add_argument( + 'mapping', metavar='FILE', + help='Path to the NCBI mapping information (example: seq_gene.md)') + parser.add_argument( + 'assembly', metavar='ASSEMBLY', + help='use only entries from this assembly (this is the group_name ' + 'column in the NCBI mapping file)') + parser.add_argument( + '-d', '--database', metavar='DATABASE', dest='database', + default='hg19', help='database to update (default: hg19)') + + args = parser.parse_args() + update_mapping(args.database, args.mapping, args.assembly) + + +if __name__ == '__main__': + main() diff --git a/bin/mutalyzer b/mutalyzer/entrypoints/mutalyzer.py old mode 100755 new mode 100644 similarity index 76% rename from bin/mutalyzer rename to mutalyzer/entrypoints/mutalyzer.py index 67c4e33f..d123482f --- a/bin/mutalyzer +++ b/mutalyzer/entrypoints/mutalyzer.py @@ -1,38 +1,28 @@ -#!/usr/bin/env python """ -Command-line interface to the nomenclature checker. +Mutalyzer command-line name checker. -Usage: - {command} variant - - variant: The variant description to check. - - -@todo: Refactor this file. +.. todo: Refactor this file. """ -import sys -import os +import argparse -from mutalyzer import variantchecker -from mutalyzer.output import Output -from mutalyzer.util import format_usage -from mutalyzer import describe +from .. import describe +from .. import output +from .. import variantchecker -def main(cmd): - """ - Command line interface to the name checker. - @todo: documentation +def check_name(description): + """ + Run the name checker. """ - O = Output(__file__) + O = output.Output(__file__) - O.addMessage(__file__, -1, "INFO", "Received variant " + cmd) + O.addMessage(__file__, -1, "INFO", "Received variant " + description) - RD = variantchecker.check_variant(cmd, O) + RD = variantchecker.check_variant(description, O) - O.addMessage(__file__, -1, "INFO", "Finished processing variant " + cmd) + O.addMessage(__file__, -1, "INFO", "Finished processing variant " + description) ### OUTPUT BLOCK ### gn = O.getOutput("genename") @@ -116,16 +106,20 @@ def main(cmd): print extractedProt #print "+++ %s" % O.getOutput("myTranscriptDescription") - #if - ### OUTPUT BLOCK ### - del O -#main +def main(): + """ + Command-line interface to the name checker. + """ + parser = argparse.ArgumentParser( + description='Mutalyzer command-line name checker.') + parser.add_argument( + 'description', metavar='DESCRIPTION', + help='variant description to run the name checker on') -if __name__ == '__main__': + args = parser.parse_args() + check_name(args.description) - if len(sys.argv) < 2: - print format_usage() - sys.exit(1) - main(sys.argv[1]) +if __name__ == '__main__': + main() diff --git a/mutalyzer/entrypoints/service_json.py b/mutalyzer/entrypoints/service_json.py new file mode 100644 index 00000000..9dd1952e --- /dev/null +++ b/mutalyzer/entrypoints/service_json.py @@ -0,0 +1,52 @@ +""" +WSGI interface to the Mutalyzer HTTP/RPC+JSON webservice. + +Example Apache/mod_wsgi configuration: + + WSGIScriptAlias /json /usr/local/bin/mutalyzer-service-json + +Be sure to have this line first if you also define a / alias, like this: + + WSGIScriptAlias /json /usr/local/bin/mutalyzer-service-json + WSGIScriptAlias / /usr/local/bin/mutalyzer-website + +You can also use the built-in HTTP server by running this file directly. +""" + + +import argparse +import sys + +from wsgiref.simple_server import make_server +from spyne.server.wsgi import WsgiApplication + +from ..services import json + + +application = WsgiApplication(json.application) + + +def debugserver(port): + """ + Run the webservice with the Python built-in HTTP server. + """ + sys.stderr.write('Listening on http://localhost:%d/\n' % port) + make_server('localhost', port, application).serve_forever() + + +def main(): + """ + Command-line interface to the HTTP/RPC+JSON webservice. + """ + parser = argparse.ArgumentParser( + description='Mutalyzer HTTP/RPC+JSON webservice.') + parser.add_argument( + '-p', '--port', metavar='NUMBER', dest='port', type=int, + default=8082, help='port to run the webservice on (default: 8082)') + + args = parser.parse_args() + debugserver(args.port) + + +if __name__ == '__main__': + main() diff --git a/mutalyzer/entrypoints/service_soap.py b/mutalyzer/entrypoints/service_soap.py new file mode 100644 index 00000000..eb91a82e --- /dev/null +++ b/mutalyzer/entrypoints/service_soap.py @@ -0,0 +1,53 @@ +""" +WSGI interface to the Mutalyzer SOAP webservice. + +Example Apache/mod_wsgi configuration: + + WSGIScriptAlias /soap /usr/local/bin/mutalyzer-service-soap + +Be sure to have this line first if you also define a / alias, like this: + + WSGIScriptAlias /soap /usr/local/bin/mutalyzer-service-soap + WSGIScriptAlias / /usr/local/bin/mutalyzer-website + +You can also use the built-in HTTP server by running this file directly. +""" + + +import argparse +import sys + +from wsgiref.simple_server import make_server +from spyne.server.wsgi import WsgiApplication + +from ..services import soap + + +application = WsgiApplication(soap.application) + + +def debugserver(port): + """ + Run the webservice with the Python built-in HTTP server. + """ + sys.stderr.write('Listening on http://localhost:%d/\n' % port) + sys.stderr.write('WDSL file is at http://localhost:%d/?wsdl\n' % port) + make_server('localhost', port, application).serve_forever() + + +def main(): + """ + Command-line interface to the SOAP webservice. + """ + parser = argparse.ArgumentParser( + description='Mutalyzer SOAP webservice.') + parser.add_argument( + '-p', '--port', metavar='NUMBER', dest='port', type=int, + default=8081, help='port to run the webservice on (default: 8081)') + + args = parser.parse_args() + debugserver(args.port) + + +if __name__ == '__main__': + main() diff --git a/mutalyzer/entrypoints/website.py b/mutalyzer/entrypoints/website.py new file mode 100644 index 00000000..3a16feff --- /dev/null +++ b/mutalyzer/entrypoints/website.py @@ -0,0 +1,72 @@ +""" +WSGI interface to the Mutalyzer website. + +The WSGI interface is exposed through the module variable 'application'. +Static files are not handled by this interface and should be served through +the '/static' url prefix separately. + +Example Apache/mod_wsgi configuration: + + Alias /static /var/www/mutalyzer/static + WSGIScriptAlias / /usr/local/bin/mutalyzer-website + +You can also use the built-in HTTP server by running this file directly. +Note, however, that static files are only found by this server in a 'static' +subdirectory of the current working directory. If you're running Mutalyzer +from its source code directory, you can satisfy this by creating a quick +symbolic link: + + ln -s mutalyzer/templates/static + +Another common practice is to use Nginx to directly serve the static files +and act as a reverse proxy server to the Mutalyzer HTTP server. + +Example Nginx configuration: + + server { + listen 80; + location /static/ { + root /var/www/mutalyzer/static; + if (-f $request_filename) { + rewrite ^/static/(.*)$ /static/$1 break; + } + } + location / { + proxy_read_timeout 300; # 5 minutes + proxy_pass http://127.0.0.1:8080; + } + } +""" + + +import argparse + +from .. import website + + +application = website.app.wsgifunc() + + +def debugserver(): + """ + Run the website with the Python built-in HTTP server. + """ + website.app.run() + + +def main(): + """ + Command-line interface to the website. + """ + parser = argparse.ArgumentParser( + description='Mutalyzer website.') + parser.add_argument( + 'port', metavar='NUMBER', type=int, nargs='?', default=8080, + help='port to run the website on (default: 8080)') + + args = parser.parse_args() + debugserver() + + +if __name__ == '__main__': + main() diff --git a/setup.py b/setup.py index 707c8b0f..d7f16f16 100644 --- a/setup.py +++ b/setup.py @@ -40,16 +40,20 @@ setup( license='Not distributable', platforms=['any'], install_requires=install_requires, - packages=['mutalyzer', 'mutalyzer.parsers', 'mutalyzer.services'], + packages=['mutalyzer', + 'mutalyzer.entrypoints', + 'mutalyzer.parsers', + 'mutalyzer.services'], include_package_data=True, - scripts=['bin/mutalyzer', - 'bin/mutalyzer-batchd', - 'bin/mutalyzer-cache-sync', - 'bin/mutalyzer-mapping-update', - 'bin/mutalyzer-mapping-import', - 'bin/mutalyzer-soap-service.wsgi', - 'bin/mutalyzer-json-service.wsgi', - 'bin/mutalyzer-website.wsgi'], + entry_points = {'console_scripts': [ + 'mutalyzer = mutalyzer.entrypoints.mutalyzer:main', + 'mutalyzer-batch-processor = mutalyzer.entrypoints.batch_processor:main', + 'mutalyzer-cache-sync = mutalyzer.entrypoints.cache_sync:main', + 'mutalyzer-mapping-import = mutalyzer.entrypoints.mapping_import:main', + 'mutalyzer-mapping-update = mutalyzer.entrypoints.mapping_update:main', + 'mutalyzer-service-json = mutalyzer.entrypoints.service_json:main', + 'mutalyzer-service-soap = mutalyzer.entrypoints.service_soap:main', + 'mutalyzer-website = mutalyzer.entrypoints.website:main']}, zip_safe=False ) -- GitLab