Created
September 11, 2012 20:05
-
-
Save alejandrobernardis/3701626 to your computer and use it in GitHub Desktop.
Run!, tornado projects!
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| - mongodb/bson // https://github.com/mongodb/mongo-python-driver | |
| - mongoengine // https://github.com/mongoengine/mongoengine | |
| - prettytable // http://code.google.com/p/prettytable/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python | |
| # -*- coding: utf-8 -*- | |
| import os, sys | |
| pkg = '/src/com/ak' | |
| root_path = os.path.dirname(__file__) | |
| sys.path.insert(0, root_path.replace(pkg, '/src')) | |
| sys.path.insert(0, root_path.replace(pkg, '/lib')) | |
| sys.path.insert(0, root_path.replace(pkg, '/libs')) | |
| sys.path.insert(0, '/Volumes/Amelie/alejandro/development/library/python') | |
| # Copyright (c) 2012 Asumi Kamikaze Inc. | |
| # Copyright (c) 2012 The Octopus Apps Inc. | |
| # Licensed under the Apache License, Version 2.0 (the "License") | |
| # Author: Alejandro M. Bernardis | |
| # Email: alejandro.m.bernardis at gmail.com | |
| # Created: Sep 10, 2012 4:52:03 PM | |
| #: PATH: /Volumes/Amelie/alejandro/development/projects/eclipse/com-ak-test/src/com/ak | |
| from tornado.httpserver import HTTPServer | |
| from tornado.ioloop import IOLoop | |
| from tornado.web import Application, RequestHandler | |
| from tornado.options import define, options, parse_command_line | |
| define("debug", default=True) | |
| define("port", default=8000, type=int) | |
| define("database_ddbb", default="database_name") | |
| class MainHandler(RequestHandler): | |
| def get(self): | |
| self.write(u'hi mike!') | |
| self.finish() | |
| class MainApplication(Application): | |
| def __init__(self): | |
| handlers = [(r'/', MainHandler)] | |
| settings = dict(debug=options.debug) | |
| Application.__init__(self, handlers, **settings) | |
| if __name__ == "__main__": | |
| try: | |
| parse_command_line() | |
| app = MainApplication() | |
| http_server = HTTPServer(app, xheaders=True) | |
| http_server.listen(options.port) | |
| IOLoop.instance().start() | |
| except KeyboardInterrupt: | |
| print "::: Server Stop :::" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python | |
| # -*- coding: utf-8 -*- | |
| # | |
| # Copyright (c) 2012 Asumi Kamikaze Inc. | |
| # Copyright (c) 2012 The Octopus Apps Inc. | |
| # Licensed under the Apache License, Version 2.0 (the "License") | |
| # | |
| # Author: Alejandro M. Bernardis | |
| # Email: alejandro.m.bernardis at gmail.com | |
| # Created: Sep 10, 2012 4:52:03 PM | |
| import os, subprocess #, logging | |
| from bson.objectid import ObjectId | |
| from datetime import date, datetime, timedelta | |
| from mongoengine import connect as mongo_connect, Document, Q | |
| from mongoengine import StringField, IntField, BooleanField, DateTimeField | |
| from optparse import OptionParser | |
| from prettytable import PrettyTable | |
| #: -- config ------------------------------------------------------------------- | |
| class ScriptConfig(): | |
| path_dir = '/Volumes/Amelie/alejandro/development/projects/eclipse' | |
| path_source_dir = 'src' | |
| path_library_dir = 'lib' | |
| script_filename = 'main.py' | |
| port = 8000 | |
| #: -- helpers -------------------------------------------------------------------- | |
| def swallow_args(func): | |
| def Decorator(arg, *unused_args): | |
| if not arg: | |
| return None | |
| return func(arg) | |
| return Decorator | |
| @swallow_args | |
| def datetime_to_str(arg): | |
| return '%d-%02d-%02d %02d:%02d:%02d' %\ | |
| (arg.year, arg.month, arg.day, | |
| arg.hour, arg.minute, arg.second) | |
| def is_primitive(value): | |
| return type(value) in [complex, int, float, long, bool, str, basestring, | |
| unicode, tuple, list] | |
| #: -- DateCompare -------------------------------------------------------------- | |
| class DateCompare(object): | |
| def __init__(self, date=None, date_min=-1, date_max=1): | |
| self.date = date or datetime.now() | |
| compare_min = datetime(self.date.year, self.date.month, self.date.day, | |
| 23, 59, 59) | |
| self.min = timedelta(days=date_min) + compare_min | |
| compare_max = datetime(self.date.year, self.date.month, self.date.day, | |
| 0, 0, 0) | |
| self.max = timedelta(days=date_max) + compare_max | |
| #: -- ControlDocument ---------------------------------------------------------- | |
| class ControlDocument(Document): | |
| meta = { | |
| 'abstract': True | |
| } | |
| #: fields | |
| availabled = BooleanField(default=False) | |
| enabled = BooleanField(default=False) | |
| created = DateTimeField(default=datetime.now()) | |
| modified = DateTimeField(default=datetime.now()) | |
| #: methods | |
| def get_date_compare(self, date=None, date_min=-1, date_max=1): | |
| return DateCompare(date, date_min, date_max) | |
| def _datetime_update(self, key, value=None, update_data=None): | |
| try: | |
| if not value: | |
| value = datetime.now() | |
| if not update_data: | |
| update_data = dict() | |
| update_data['set__'+key] = value | |
| self.update(**update_data) | |
| self.reload() | |
| return True | |
| except: | |
| return False | |
| def set_modified(self, value=None): | |
| return self._datetime_update('modified', value) | |
| def set_modified_with_data(self, update_data, value=None): | |
| return self._datetime_update('modified', value, update_data) | |
| def _status_update(self, key, value=False): | |
| try: | |
| update_data = dict() | |
| update_data['set__'+key] = value | |
| return self.set_modified_with_data(update_data) | |
| except: | |
| return False | |
| def set_availabled(self, value=False): | |
| return self._status_update('availabled', value) | |
| def set_enabled(self, value=False): | |
| return self._status_update('enabled', value) | |
| def to_object(self, ignore=[]): | |
| data = {} | |
| for field_name, _ in self._fields.items(): | |
| value = getattr(self, field_name, None) | |
| try: | |
| if not value: | |
| raise | |
| elif is_primitive(value): | |
| value = value | |
| elif isinstance(value, ObjectId): | |
| value = value.__str__() | |
| elif isinstance(value, datetime) or \ | |
| isinstance(value, date): | |
| value = datetime_to_str(value) | |
| else: | |
| value = value.to_object() | |
| except Exception: | |
| value = None | |
| if not field_name in ignore: | |
| data[field_name] = value | |
| return data | |
| def _get_status_query(self, enabled=True, availabled=True): | |
| return ControlDocument.get_status_query(enabled, availabled) | |
| @staticmethod | |
| def get_status_query(enabled=True, availabled=True): | |
| return Q(enabled=enabled)&Q(availabled=availabled) | |
| #: -- Project ------------------------------------------------------------------ | |
| class Project(ControlDocument): | |
| meta = { | |
| 'collection': 'projects', | |
| 'indexes': ['name', 'port'] | |
| } | |
| #: fields | |
| name = StringField(unique=True) | |
| alias = StringField(unique=True) | |
| port = IntField(unique=True) | |
| path = StringField() | |
| script = StringField() | |
| module = StringField() | |
| last_exec = DateTimeField() | |
| #: methods | |
| def set_last_exec(self): | |
| return self._status_update('last_exec', datetime.now()) | |
| @staticmethod | |
| def _get_by__first(query, enabled=True, availabled=True): | |
| try: | |
| if not query: | |
| raise | |
| _Q = ControlDocument.get_status_query(enabled, availabled)&query | |
| return Project.objects(_Q).first() | |
| except: | |
| return None | |
| @staticmethod | |
| def get_by_complex(value): | |
| try: | |
| _Q = Q(name=value)|Q(alias=value) | |
| return Project._get_by__first(_Q) | |
| except: | |
| return None | |
| @staticmethod | |
| def get_by_name(name): | |
| try: | |
| _Q = Q(name=name) | |
| return Project._get_by__first(_Q) | |
| except: | |
| return None | |
| @staticmethod | |
| def get_by_alias(alias): | |
| try: | |
| _Q = Q(alias=alias) | |
| return Project._get_by__first(_Q) | |
| except: | |
| return None | |
| @staticmethod | |
| def get_last_port(port): | |
| try: | |
| _Q = ControlDocument.get_status_query() | |
| if port and port >= cfg.port: | |
| port = Project.objects(_Q&Q(port=port)).first() | |
| if not port: | |
| return port | |
| port = Project.objects(_Q).order_by("-port").first() | |
| return cfg.port if not port else port.port + 1 | |
| except Exception: | |
| return None | |
| #: -- do_validate -------------------------------------------------------------- | |
| def do_validate(): | |
| parser = OptionParser() | |
| parser.add_option('-l', '--list', action='store_true', dest='list', default=False) | |
| parser.add_option('-i', '--info', action='store_true', dest='info', default=False) | |
| parser.add_option('--name', dest='name', default=None, type='string') | |
| parser.add_option('--alias', dest='alias', default=None, type='string') | |
| parser.add_option('--script', dest='script', default=None, type='string') | |
| parser.add_option('--port', dest='port', default=None, type='int') | |
| parser.add_option('--debug', dest='debug', default=True) | |
| parser.add_option('--database', dest='database', default=None, type='string') | |
| return parser.parse_args() | |
| #: -- do_create_project -------------------------------------------------------- | |
| def do_create_project(name, path, alias, script, module, port): | |
| try: | |
| project = Project() | |
| project.name = name | |
| project.alias = alias | |
| project.port = Project.get_last_port(port) | |
| project.path = path | |
| project.script = script | |
| project.module = module | |
| project.availabled = True | |
| project.enabled = True | |
| project.created = datetime.now() | |
| project.modified = datetime.now() | |
| project.last_exec = datetime.now() | |
| project.save() | |
| return project | |
| except Exception: # as E: | |
| #print logging.error(str(E)) | |
| return None | |
| #: -- do_find_name ------------------------------------------------------------- | |
| def do_find_name(name, path=None): | |
| if not path: | |
| path = cfg.path_dir | |
| cmd = subprocess.Popen('find . -iname \*%s\* -type d -maxdepth 1' % name, | |
| stdout=subprocess.PIPE, stderr=subprocess.PIPE, | |
| shell=True, cwd=path, universal_newlines=True) | |
| elements = cmd.communicate()[0].split('\n')[:-1] | |
| elements_quantity = len(elements) | |
| if elements_quantity == 0: | |
| return None | |
| print u'' | |
| print u'Lista de Proyectos:' | |
| tmpl = PrettyTable(['x', 'Proyecto', 'Alias']) | |
| tmpl.align = "l" | |
| tmpl.reversesort = True | |
| for a in range(elements_quantity): | |
| ref = elements[a] | |
| if not ref: | |
| continue | |
| ref = ref.replace('./','') | |
| prj = Project.get_by_name(ref) | |
| alias = '' if not prj else prj.alias | |
| tmpl.add_row([a + 1, ref, alias]) | |
| print tmpl | |
| action = raw_input(u'\nSeleccione una opción --> '.encode('utf-8')) | |
| try: | |
| element = elements[int(action)-1] | |
| return element.replace('./','') | |
| except Exception: # as E: | |
| #print logging.error(str(E)) | |
| return None | |
| #: -- do_find_script ----------------------------------------------------------- | |
| def do_find_script(name=None, path=None): | |
| if not name: | |
| name = cfg.script_filename | |
| if not path: | |
| path = cfg.path_dir | |
| path = '%s/%s' % (path, cfg.path_source_dir) | |
| cmd = subprocess.Popen('find . -iname "%s"' % name, | |
| stdout=subprocess.PIPE, stderr=subprocess.PIPE, | |
| shell=True, cwd=path, universal_newlines=True) | |
| elements = cmd.communicate()[0].split('\n')[:-1] | |
| elements_quantity = len(elements) | |
| if elements_quantity == 0: | |
| return None, None | |
| print u'' | |
| print u'Lista de Archivos:' | |
| tmpl = PrettyTable(['x', 'Value']) | |
| tmpl.align = "l" | |
| tmpl.reversesort = True | |
| for a in range(elements_quantity): | |
| ref = elements[a] | |
| if not ref: | |
| continue | |
| tmpl.add_row([a + 1, ref.replace('./','')]) | |
| print tmpl | |
| action = raw_input(u'\nSeleccione una opción --> '.encode('utf-8')) | |
| try: | |
| element = elements[int(action)-1].replace('./','') | |
| script = '%s/%s' % (path, element) | |
| module = '.'.join([a for a in element.replace('.py','').split('/')]) | |
| return script, module | |
| except Exception: # as E: | |
| #print logging.error(str(E)) | |
| return None, None | |
| #: -- do_main ------------------------------------------------------------------ | |
| def do_run(project, opts, args): | |
| if not project or not isinstance(project, Project): | |
| raise Exception(u'El objeto project esta corrupto.') | |
| print u'' | |
| print u'Proyecto:' | |
| tmpl = PrettyTable(['Key', 'Value']) | |
| tmpl.align = "l" | |
| tmpl.reversesort = True | |
| tmpl.add_row(['name', project.name]) | |
| tmpl.add_row(['alias', project.alias]) | |
| tmpl.add_row(['host', 'http://localhost:%s' % project.port]) | |
| tmpl.add_row(['last execution', datetime_to_str(project.last_exec)]) | |
| tmpl.add_row(['execution', datetime_to_str(datetime.now())]) | |
| print tmpl | |
| print u'-' | |
| print u'' | |
| project.set_last_exec() | |
| params = [] | |
| params.append('/usr/bin/python') | |
| params.append(project.script) | |
| params.append('--port=%s' % project.port) | |
| params.append('--debug=%s' % opts.debug) | |
| if opts.database: | |
| params.append('--database_ddbb=%s' % opts.database) | |
| subprocess.call(params) | |
| #: -- do_get_info -------------------------------------------------------------- | |
| def do_get_info(project): | |
| print u'' | |
| print u'Información:' | |
| tmpl = PrettyTable(['Key', 'Value']) | |
| tmpl.align = "l" | |
| tmpl.reversesort = True | |
| data = project.to_object() | |
| for a in ['name','alias','port','path','script','created','modified','last_exec']: | |
| tmpl.add_row([a, data[a]]) | |
| print tmpl | |
| return '\nau revoir...' | |
| #: -- do_get_list -------------------------------------------------------------- | |
| def do_get_list(): | |
| if Project.objects().count() < 1: | |
| return u'No hay proyectos disponibles.' | |
| print u'' | |
| print u'Proyectos:' | |
| tmpl = PrettyTable(['Port', 'Name', 'Alias']) | |
| tmpl.align = "l" | |
| tmpl.reversesort = True | |
| for a in Project.objects: | |
| tmpl.add_row([a.port, a.name, a.alias]) | |
| print tmpl | |
| return '\nau revoir...' | |
| #: -- do_exit ------------------------------------------------------------------ | |
| def do_exit(message): | |
| return exit(u'\x1b[1;31m[ERROR]\x1b[0m :: %s' % message) | |
| #: -- do_main ------------------------------------------------------------------ | |
| def do_main(): | |
| opts, args = do_validate() | |
| if not opts.name and not len(args) and not opts.list: | |
| return do_exit(u'El nombre del proyecto no fue definido.') | |
| try: | |
| settings = dict(host='127.0.0.1', port=27017) | |
| mongo_connect('com_ak_local_projects', **settings) | |
| except Exception: | |
| return do_exit(u'No se pudo establecer la conexión a la base de datos.') | |
| if opts.list: | |
| exit(do_get_list()) | |
| project_name = opts.name or args[0] | |
| project = Project.get_by_complex(project_name) | |
| if project and opts.info: | |
| exit(do_get_info(project)) | |
| if not project: | |
| name = do_find_name(project_name) | |
| if not name: | |
| return do_exit(u'El nombre de proyecto "%s" no existe.' % project_name) | |
| project = Project.get_by_name(name) | |
| if not project: | |
| path = '%s/%s' % (cfg.path_dir, name) | |
| if not os.path.exists(path): | |
| return do_exit(u'El proyecto "%s" no existe fisicamente.' % name) | |
| script_name = opts.script or cfg.script_filename | |
| script, module = do_find_script(script_name, path) | |
| if not script: | |
| return do_exit(u'El script de proyecto "%s" no existe.' % script_name) | |
| alias = opts.alias or raw_input(u'Escriba un alias de proyecto --> ') | |
| project = do_create_project(name, path, alias, script, module, opts.port) | |
| try: | |
| do_run(project, opts, args) | |
| except Exception as E: | |
| return do_exit(str(E)) | |
| #: -- main --------------------------------------------------------------------- | |
| if __name__ == '__main__': | |
| try: | |
| cfg = ScriptConfig() | |
| do_main() | |
| except KeyboardInterrupt: | |
| exit('\nau revoir...') |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Sofias-iMac:~ amelie$ run ak | |
| Lista de Proyectos: | |
| +---+--------------------+-------+ | |
| | x | Proyecto | Alias | | |
| +---+--------------------+-------+ | |
| | 1 | com-ak-python | | | |
| | 2 | com-ak-test | | | |
| | 3 | com-ak-test copy | | | |
| | 4 | com-ak-test copy 2 | | | |
| | 5 | com-ak-test copy 3 | | | |
| +---+--------------------+-------+ | |
| Seleccione una opción --> 2 | |
| Lista de Archivos: | |
| +---+----------------+ | |
| | x | Value | | |
| +---+----------------+ | |
| | 1 | com/ak/main.py | | |
| +---+----------------+ | |
| Seleccione una opción --> 1 | |
| Escriba un alias de proyecto --> test | |
| Proyecto: | |
| +----------------+-----------------------+ | |
| | Key | Value | | |
| +----------------+-----------------------+ | |
| | name | com-ak-test | | |
| | alias | test | | |
| | host | http://localhost:8000 | | |
| | last execution | 2012-09-12 08:30:09 | | |
| | execution | 2012-09-12 08:30:09 | | |
| +----------------+-----------------------+ | |
| - | |
| ^C | |
| ::: Server Stop ::: | |
| au revoir... | |
| Sofias-iMac:~ amelie$ run -l | |
| Proyectos: | |
| +------+-------------+-------+ | |
| | Port | Name | Alias | | |
| +------+-------------+-------+ | |
| | 8000 | com-ak-test | test | | |
| +------+-------------+-------+ | |
| au revoir... | |
| Sofias-iMac:~ amelie$ run -i test | |
| Información: | |
| +-----------+---------------------------------------------------------------------------------------+ | |
| | Key | Value | | |
| +-----------+---------------------------------------------------------------------------------------+ | |
| | name | com-ak-test | | |
| | alias | test | | |
| | port | 8000 | | |
| | path | /Volumes/Amelie/alejandro/development/projects/eclipse/com-ak-test | | |
| | script | /Volumes/Amelie/alejandro/development/projects/eclipse/com-ak-test/src/com/ak/main.py | | |
| | created | 2012-09-12 08:30:09 | | |
| | modified | 2012-09-12 08:30:09 | | |
| | last_exec | 2012-09-12 08:30:09 | | |
| +-----------+---------------------------------------------------------------------------------------+ | |
| au revoir... | |
| Sofias-iMac:~ amelie$ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment