Example #1
0
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])
Example #2
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)
Example #3
0
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
Example #4
0
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
Example #5
0
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)
Example #6
0
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]
Example #7
0
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]
Example #8
0
    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)
Example #9
0
    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)
Example #10
0
    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)
Example #11
0
    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)