def configure(): """Configure the batch environment""" global apps # we suppose that the batch addresses only one application app_name, app = apps.items()[0] local.request = local.Process() local.worker = local.Process() log.set_logger('nagare.application.' + app.name) security.set_manager(app.security) # initialize the application context app.set_base_url('http://localhost/') # dummy server host app.set_locale(i18n.Locale('en', 'US')) # Set the default Locale # install the configuration registry.configure(app.configuration) # log the start of the script logger = log.get_logger('.' + __name__) logger.debug('----') logger.debug('Running %s\n' % sys.argv[0])
def run(parser, options, args): """launch an object In: - ``parser`` -- the ``optparse.OptParser`` object used to parse the configuration file - ``options`` -- options in the command lines - ``args`` -- arguments in the command lines The unique argument is the path of the object to launch. The path syntax is described into the module ``nagare.admin.reference``. For example, ``/tmp/counter.py:Counter`` is the path to the class ``Counter`` of the module ``tmp.counter.py`` """ if len(args) != 2: parser.error('Bad number of arguments') if 'nagare_reloaded' not in os.environ: return reloader.restart_with_monitor() # With the ``serve-module`` command, the automatic reloader is always activated reloader.install(excluded_directories=(pkg_resources.get_default_cache(),)) # Load the object if os.path.sep in args[0]: path = 'file ' + args[0] else: path = 'python ' + args[0] app = reference.load_object(path)[0] # Wrap it into a WSGIApp app = wsgi.create_WSGIApp(app) # Always use the standalone publisher (Python HTTP server) publishers = dict([(entry.name, entry) for entry in pkg_resources.iter_entry_points('nagare.publishers')]) publisher = publishers['standalone'].load()() wsgi_pipe = debugged_app(app) if options.debug else app publisher.register_application(args[0], args[1], app, wsgi_pipe) app.set_config('', {'application': {'redirect_after_post': False, 'name': args[1], 'always_html': True}}, None) app.set_publisher(publisher) # Always use the standalone session manager (in memory sessions) sessions_managers = dict([(entry.name, entry) for entry in pkg_resources.iter_entry_points('nagare.sessions')]) sessions_manager = sessions_managers['standalone'].load()() app.set_sessions_manager(sessions_manager) # Set the application logger level to DEBUG log.configure({'logger': {'level': 'DEBUG'}}, args[1]) log.activate() log.set_logger('nagare.application.' + args[1]) # The static contents of the framework are served by the standalone server publisher.register_static('nagare', lambda path, r=pkg_resources.Requirement.parse('nagare'): get_file_from_package(r, path)) # Launch the object publisher.serve(None, dict(host=options.host, port=options.port), None)
def activate_applications(cfgfiles, debug, error): """Initialize applications In: - ``cfgfile`` -- paths to application configuration files or names of registered applications - ``debug`` -- enable the display of the generated SQL statements - ``error`` -- the function to call in case of configuration errors Return: - database session - {application name -> application object} """ # Configure the local service local.worker = local.Process() local.request = local.Process() configs = [] # Merge all the ``[logging]]`` section of all the applications for cfgfile in cfgfiles: # Read the configuration file of the application conffile, app, project_name, aconf = util.read_application( cfgfile, error) if conffile is None: error('Configuration file "%s" not found' % cfgfile) configs.append((conffile, app, project_name, aconf)) log.configure(aconf['logging'].dict(), aconf['application']['app']) # Configure the logging service log.activate() apps = {} # For each application given, activate its metadata and its logger for cfgfile, app, project_name, aconf in configs: name = aconf['application']['app'] log.set_logger('nagare.application.' + name) data_path = aconf['application']['data'] apps[name], databases = util.activate_WSGIApp(app, cfgfile, aconf, error, data_path=data_path, debug=debug) for database_settings, populate in databases: database.set_metadata(*database_settings) session = database.session session.begin() return session, apps
def activate_applications(cfgfiles, debug, error): """Initialize applications In: - ``cfgfile`` -- paths to application configuration files or names of registered applications - ``debug`` -- enable the display of the generated SQL statements - ``error`` -- the function to call in case of configuration errors Return: - database session - {application name -> application object} """ # Configure the local service local.worker = local.Process() local.request = local.Process() configs = [] # Merge all the ``[logging]]`` section of all the applications for cfgfile in cfgfiles: # Read the configuration file of the application conffile, app, project_name, aconf = util.read_application(cfgfile, error) if conffile is None: error('Configuration file "%s" not found' % cfgfile) configs.append((conffile, app, project_name, aconf)) log.configure(aconf['logging'].dict(), aconf['application']['app']) # Configure the logging service log.activate() apps = {} # For each application given, activate its metadata and its logger for cfgfile, app, project_name, aconf in configs: name = aconf['application']['app'] log.set_logger('nagare.application.' + name) data_path = aconf['application']['data'] apps[name], databases = util.activate_WSGIApp(app, cfgfile, aconf, error, data_path=data_path, debug=debug) for database_settings, populate in databases: database.set_metadata(*database_settings) session = database.session session.begin() return session, apps
def create_globals(cfgfiles, debug, error): """ In: - ``cfgfile`` -- paths to application configuration files or names of registered applications - ``debug`` -- enable the display of the generated SQL statements - ``error`` -- the function to call in case of configuration errors Return: - the namespace with the ``apps`` and ``session`` variables defined """ # Configure the local service local.worker = local.Process() local.request = local.Process() configs = [] # Merge all the ``[logging]]`` section of all the applications for cfgfile in cfgfiles: # Read the configuration file of the application (cfgfile, app, dist, aconf) = util.read_application(cfgfile, error) configs.append((cfgfile, app, dist, aconf)) log.configure(aconf['logging'].dict(), aconf['application']['name']) # Configure the logging service log.activate() apps = {} # For each application given, activate its metadata and its logger for (cfgfile, app, dist, aconf) in configs: name = aconf['application']['name'] log.set_logger('nagare.application.'+name) requirement = None if not dist else pkg_resources.Requirement.parse(dist.project_name) data_path = None if not requirement else pkg_resources.resource_filename(requirement, '/data') (apps[name], databases) = util.activate_WSGIApp(app, cfgfile, aconf, error, data_path=data_path, debug=debug) for (database_settings, populate) in databases: database.set_metadata(*database_settings) session = database.session session.begin() return dict(session=session, apps=apps)
def read_options(debug, args, error): """Activate all the database metadata objects of an application Several metadata objects can be activated if there are sub-sections into the [database] section. In: - ``debug`` -- flag to display the generated SQL statements - ``args`` -- arguments in the command lines: application to activate - ``error`` -- the function to call in case of configuration errors Return: - tuples (metadata object, populate function) """ # If no application name is given, display the list of the registered applications if not args: print 'Available applications:' app_names = [ entry.name for entry in pkg_resources.iter_entry_points('nagare.applications') ] for app_name in sorted(app_names): print ' -', app_name return () if len(args) != 1: error('Bad number of parameters') # Read the configuration of the application cfgfile, app, project_name, aconf = util.read_application(args[0], error) if cfgfile is None: error('Configuration file not found') # Configure the local service local.worker = local.Process() local.request = local.Process() # Configure the logging service log.configure(aconf['logging'].dict(), aconf['application']['name']) log.activate() log.set_logger('nagare.application.' + aconf['application']['name']) return util.activate_WSGIApp(app, cfgfile, aconf, error, debug=debug)[1]
def read_options(debug, args, error): """Activate all the database metadata objects of an application Several metadata objects can be activated if there are sub-sections into the [database] section. In: - ``debug`` -- flag to display the generated SQL statements - ``args`` -- arguments in the command lines: application to activate - ``error`` -- the function to call in case of configuration errors Return: - tuples (metadata object, populate function) """ # If no application name is given, display the list of the registered applications if not args: print 'Available applications:' app_names = [entry.name for entry in pkg_resources.iter_entry_points('nagare.applications')] for app_name in sorted(app_names): print ' -', app_name return () if len(args) != 1: error('Bad number of parameters') # Read the configuration of the application cfgfile, app, project_name, aconf = util.read_application(args[0], error) if cfgfile is None: error('Configuration file not found') # Configure the local service local.worker = local.Process() local.request = local.Process() # Configure the logging service log.configure(aconf['logging'].dict(), aconf['application']['name']) log.activate() log.set_logger('nagare.application.' + aconf['application']['name']) return util.activate_WSGIApp(app, cfgfile, aconf, error, debug=debug)[1]
def __call__(self, environ, start_response): """WSGI interface In: - ``environ`` -- dictionary of the received elements - ``start_response`` -- callback to send the headers to the browser Return: - the content to send back to the browser """ local.request.clear() # Create the ``WebOb`` request and response objects # ------------------------------------------------- request = webob.Request(environ, charset='utf-8') response = Response('text/html' if self.always_html else str(request.accept)) channel_id = request.params.get('_channel') nb = request.params.get('_nb') if channel_id and nb: if environ['wsgi.multiprocess']: response.status = 501 # "Not Implemented" else: comet.channels.connect(channel_id, int(nb), environ['wsgi.input'].file.fileno(), response) return response(environ, start_response) xhr_request = request.is_xhr or ('_a' in request.params) session = None self.last_exception = None log.set_logger('nagare.application.'+self.name) # Set the dedicated application logger # Create a database transaction for each request with database.session.begin(): try: # Phase 1 # ------- # Test the request validity if not request.path_info: self.on_incomplete_url(request, response) try: session = self.sessions.get(request, response, xhr_request) except ExpirationError: self.on_session_expired(request, response) if session.is_new: # A new session is created root = self.create_root() # Create a new application root component callbacks = Callbacks() # Create a new callbacks registry else: # An existing session is used, retrieve the application root component # and the callbacks registry (root, callbacks) = session.data request.method = request.params.get('_method', request.method) if not session.is_new and request.method not in ('GET', 'POST'): self.on_bad_http_method(request, response) self.start_request(root, request, response) url = request.path_info.strip('/') if session.is_new and url: # If a URL is given, initialize the objects graph with it presentation.init(root, tuple([u.decode('utf-8') for u in url.split('/')]), None, request.method, request) try: render = self._phase1(request, response, callbacks) except CallbackLookupError: render = self.on_callback_lookuperror(request, response, xhr_request) except exc.HTTPException, response: # When a ``webob.exc`` object is raised during phase 1, skip the # phase 2 and use it as the response object pass except Exception: self.last_exception = (request, sys.exc_info()) response = self.on_exception(request, response)
def __call__(self, environ, start_response): """WSGI interface In: - ``environ`` -- dictionary of the received elements - ``start_response`` -- callback to send the headers to the browser Return: - the content to send back to the browser """ local.request.clear() # Create the ``WebOb`` request and response objects # ------------------------------------------------- request = self.create_request(environ) try: request.params, request.url except UnicodeDecodeError: return exc.HTTPClientError()(environ, start_response) response = self.create_response( request, 'text/html' if self.always_html else str(request.accept)) channel_id = request.params.get('_channel') nb = request.params.get('_nb') if channel_id and nb: if environ['wsgi.multiprocess']: response.status = 501 # "Not Implemented" else: comet.channels.connect(channel_id, int(nb), environ['wsgi.input'].file.fileno(), response) return response(environ, start_response) xhr_request = request.is_xhr state = None self.last_exception = None log.set_logger('nagare.application.' + self.name) # Set the dedicated application logger # Create a database transaction for each request with database.session.begin(): try: # Phase 1 # ------- # Test the request validity if not request.path_info: self.on_incomplete_url(request, response) try: state = self.sessions.get_state(request, response, xhr_request) except ExpirationError: self.on_expired_session(request, response) except SessionSecurityError: self.on_invalid_session(request, response) state.acquire() try: root, callbacks = state.get_root() or (self.create_root(), None) except ExpirationError: self.on_expired_session(request, response) except SessionSecurityError: self.on_invalid_session(request, response) self.start_request(root, request, response) if callbacks is None: # New state request.method = request.params.get( '_method', request.method) if request.method not in ('GET', 'POST'): self.on_bad_http_method(request, response) url = request.path_info.strip('/') if url: # If a URL is given, initialize the objects graph with it presentation.init(root, tuple(url.split('/')), None, request.method, request) try: render = self._phase1(root, request, response, callbacks) except CallbackLookupError: render = self.on_callback_lookuperror( request, response, xhr_request) except exc.HTTPException, response: # When a ``webob.exc`` object is raised during phase 1, skip the # phase 2 and use it as the response object pass except Exception: self.last_exception = (request, sys.exc_info()) response = self.on_exception(request, response)
def __call__(self, environ, start_response): """WSGI interface In: - ``environ`` -- dictionary of the received elements - ``start_response`` -- callback to send the headers to the browser Return: - the content to send back to the browser """ local.request.clear() # Create the ``WebOb`` request and response objects # ------------------------------------------------- request = self.create_request(environ) try: request.params, request.url except UnicodeDecodeError: return exc.HTTPClientError()(environ, start_response) response = self.create_response(request, "text/html" if self.always_html else str(request.accept)) channel_id = request.params.get("_channel") nb = request.params.get("_nb") if channel_id and nb: if environ["wsgi.multiprocess"]: response.status = 501 # "Not Implemented" else: comet.channels.connect(channel_id, int(nb), environ["wsgi.input"].file.fileno(), response) return response(environ, start_response) xhr_request = request.is_xhr state = None self.last_exception = None log.set_logger("nagare.application." + self.name) # Set the dedicated application logger # Create a database transaction for each request with database.session.begin(): try: # Phase 1 # ------- # Test the request validity if not request.path_info: self.on_incomplete_url(request, response) try: state = self.sessions.get_state(request, response, xhr_request) except ExpirationError: self.on_expired_session(request, response) except SessionSecurityError: self.on_invalid_session(request, response) state.acquire() try: root, callbacks = state.get_root() or (self.create_root(), None) except ExpirationError: self.on_expired_session(request, response) except SessionSecurityError: self.on_invalid_session(request, response) self.start_request(root, request, response) if callbacks is None: # New state request.method = request.params.get("_method", request.method) if request.method not in ("GET", "POST"): self.on_bad_http_method(request, response) url = request.path_info.strip("/") if url: # If a URL is given, initialize the objects graph with it presentation.init(root, tuple(url.split("/")), None, request.method, request) try: render = self._phase1(root, request, response, callbacks) except CallbackLookupError: render = self.on_callback_lookuperror(request, response, xhr_request) except exc.HTTPException, response: # When a ``webob.exc`` object is raised during phase 1, skip the # phase 2 and use it as the response object pass except Exception: self.last_exception = (request, sys.exc_info()) response = self.on_exception(request, response)
def __init__(self, name, dist, _app_name, style, styles, logger, handler, formatter, exceptions, **sections): super(Logger, self).__init__(name, dist, style=style, styles=styles, logger=logger, handler=handler, formatter=formatter, exceptions=exceptions, **sections) colorama.init(autoreset=True) colors = (styles.get(style) or STYLES.get(style) or STYLES['nocolors']).copy() colors = { name: ''.join(COLORS.get(c.upper(), '') for c in color) for name, color in colors.items() } configurator = DictConfigurator() # Application logger # ------------------ logger_name = 'nagare.application.' + _app_name log.set_logger(logger_name) logger['level'] = logger['level'] or 'ERROR' if handler['class']: handler['()'] = configurator.create_handler else: handler.setdefault('stream', 'ext://sys.stderr') if 'class' not in formatter: del handler['class'] handler['()'] = lambda stream: ColorizingStreamHandler( stream, colorizer.GenericColorizer({ name: (color, COLORS['RESET_ALL']) for name, color in colors.items() })) formatter['class'] = 'chromalog.ColorizingFormatter' else: handler['class'] = 'logging.StreamHandler' loggers = {logger_name: dict(logger, handlers=[logger_name])} handlers = {logger_name: dict(handler, formatter=logger_name)} formatters = {logger_name: formatter} # Other loggers # ------------- for name, config in sections.items(): if name.startswith('logger_'): name = config.pop('qualname') if name.startswith('.'): name = logger_name + name if name == 'root': name = '' config['propagate'] = config.get('propagate', '1') == '1' handler = config.get('handlers') if handler: config['handlers'] = handler.split(',') loggers[name] = config if name.startswith('handler_'): handlers[name[8:]] = config handlers[name[8:]]['()'] = configurator.create_handler if name.startswith('formatter_'): formatters[name[10:]] = config # Root logger # ----------- root = loggers.get('', {}) root.setdefault('level', 'INFO') if 'handlers' not in root: root['handlers'] = ['_root_handler'] handlers['_root_handler'] = { 'stream': 'ext://sys.stderr', 'formatter': '_root_formatter', '()': lambda stream: ColorizingStreamHandler( stream, colorizer.GenericColorizer({ name: (color, COLORS['RESET_ALL']) for name, color in colors.items() })) } formatters['_root_formatter'] = { 'class': 'chromalog.ColorizingFormatter', 'format': '%(asctime)s - %(name)s - %(levelname)s - %(message)s' } loggers[''] = root logging_config = { 'version': 1, 'loggers': loggers, 'handlers': handlers, 'formatters': formatters } configurator.configure(logging_config) # Colorized exceptions # -------------------- exception_logger = logging.getLogger('nagare.services.exceptions') if style and not exception_logger.handlers: handler = self.create_exception_handler(colors, **exceptions) exception_logger.addHandler(handler)