Example #1
0
    def __init__(self, root_directory, logger=None, session_manager=None,
                 config=None, **kwargs):
        global _publisher
        if config is None:
            self.config = Config(**kwargs)
        else:
            if kwargs:
                raise ValueError("cannot provide both 'config' object and"
                                 " config arguments")
            self.config = config
        if logger is None:
            self.logger = DefaultLogger(error_log=self.config.error_log,
                                        access_log=self.config.access_log,
                                        error_email=self.config.error_email)
        else:
            self.logger = logger
        if session_manager is not None:
            self.session_manager = session_manager
        else:
            from quixote.session import NullSessionManager
            self.session_manager = NullSessionManager()

        if _publisher is not None:
            raise RuntimeError, "only one instance of Publisher allowed"
        _publisher = self

        if not callable(getattr(root_directory, '_q_traverse')):
            raise TypeError(
                'Expected something with a _q_traverse method, got %r' %
                root_directory)
        self.root_directory = root_directory
        self._request = None
Example #2
0
def get_publisher():
    quixote.enable_ptl()
    from lap.web.site import root
    if DEBUG:
        config = Config(display_exceptions='html')
    else:
        config = None
    return DatabasePublisher(root.index(), config)
Example #3
0
 def __init__(self, root_namespace, config=None):
     from quixote.config import Config
     if type(root_namespace) is types.StringType:
         root_namespace = _get_module(root_namespace)
     self.namespace_stack = [root_namespace]
     if config is None:
         config = Config()
     directory = RootDirectory(root_namespace, self.namespace_stack)
     _Publisher.__init__(self, directory, config=config)
Example #4
0
def run(server_start, quixote_conf, app_conf):
    """
    Run this application.
    
    server_start -- a function that starts a particular type of server.
                    Specifically, a quixote.server.xxx_server.run function.
    quixote_conf -- a string of path to the Quixote configuration file.
    app_conf -- a string of path to the application configuration file.
    """

    app_options = configure(app_conf, schema)

    ctx = Context()
    ctx.app_options = app_options
    ctx.user_mgr = UserManager(
        CachingDirStore(app_options.get("bookie", "user_store")))
    ctx.bookmarksdb = CachingDirStore(
        app_options.get("bookie", "bookmarks_store"))

    # Sessions will timed out after 2 days.
    session_mgr = FixedTimeoutSessionManager(Session, {})
    session_mgr.timeout_in_min = 2880

    config_obj = Config()
    config_obj.read_file(quixote_conf)

    # A background thread to clean up expired session
    # every 60 mins.
    SessionReaper(60, session_mgr).start()

    # The publisher factory function.
    def create_publisher():
        publisher = ThreadedPublisher(RootDirectory(),
                                      session_manager=session_mgr,
                                      config=config_obj)
        publisher.context = ctx
        return publisher

    server_start(create_publisher,
                 host=app_options.get("server", "host"),
                 port=app_options.get("server", "port"))
Example #5
0
def handler(req):
    opts = req.get_options()
    try:
        package = opts['quixote-root-namespace']
    except KeyError:
        package = None

    try:
        configfile = opts['quixote-config-file']
        config = Config()
        config.read_file(configfile)
    except KeyError:
        config = None

    if not package:
        return apache.HTTP_INTERNAL_SERVER_ERROR

    pub = name2publisher.get(package)
    if pub is None:
        pub = ModPythonPublisher(package, config)
        name2publisher[package] = pub
    return pub.publish_modpython(req)
Example #6
0
    def __init__(self, root_namespace, config=None):
        from quixote.config import Config

        # if more than one publisher in app, need to set_publisher per request
        set_publisher(self)

        if type(root_namespace) is types.StringType:
            self.root_namespace = _get_module(root_namespace)
        else:
            # Should probably check that root_namespace is really a
            # namespace, ie. a module, class, or instance -- but it's
            # tricky to know if something is really a class or instance
            # (because of ExtensionClass), and who knows what other
            # namespaces are lurking out there in the world?
            self.root_namespace = root_namespace

        # for PublishError exception handling
        self.namespace_stack = [self.root_namespace]

        self.exit_now = 0
        self.access_log = None
        self.error_log = sys.stderr  # possibly overridden in setup_logs()
        sys.stdout = self.error_log  # print is handy for debugging

        # Initialize default config object with all the default values from
        # the config variables at the top of the config module, ie. if
        # ERROR_LOG is set to "/var/log/quxiote-error.log", then
        # config.ERROR_LOG will also be "/var/log/quixote-error.log".  If
        # application FCGI/CGI scripts need to override any of these
        # defaults, they can do so by direct manipulation of the config
        # object, or by reading a config file:
        #   app.read_config("myapp.conf")
        if config is None:
            self.config = Config()
        else:
            self.set_config(config)

        self._local = threading.local()
Example #7
0
class Publisher:
    """
    The core of Quixote and of any Quixote application.  This class is
    responsible for converting each HTTP request into a search of
    Python's package namespace and, ultimately, a call of a Python
    function/method/callable object.

    Each invocation of a driver script should have one Publisher
    instance that lives for as long as the driver script itself.  Eg. if
    your driver script is plain CGI, each Publisher instance will handle
    exactly one HTTP request; if you have a FastCGI driver, then each
    Publisher will handle every HTTP request handed to that driver
    script process.

    Instance attributes:
      root_namespace : module | instance | class
        the Python namespace that will be searched for objects to
        fulfill each HTTP request
      exit_now : boolean
        used for internal state management.  If true, the loop in
        publish_cgi() will terminate at the end of the current request.
      access_log : file
        file to which every access will be logged; set by
        setup_logs() (None if no access log)
      error_log : file
        file to which application errors (exceptions caught by Quixote,
        as well as anything printed to stderr by application code) will
        be logged; set by setup_logs().  Set to sys.stderr if no
        ERROR_LOG setting in the application config file.
      config : Config
        holds all configuration info for this application.  If the
        application doesn't have a config file, uses the default values
        from the quixote.config module.
      _request : HTTPRequest
        the HTTP request currently being processed.
      namespace_stack : [ module | instance | class ]
    """
    def __init__(self, root_namespace, config=None):
        from quixote.config import Config

        # if more than one publisher in app, need to set_publisher per request
        set_publisher(self)

        if type(root_namespace) is types.StringType:
            self.root_namespace = _get_module(root_namespace)
        else:
            # Should probably check that root_namespace is really a
            # namespace, ie. a module, class, or instance -- but it's
            # tricky to know if something is really a class or instance
            # (because of ExtensionClass), and who knows what other
            # namespaces are lurking out there in the world?
            self.root_namespace = root_namespace

        # for PublishError exception handling
        self.namespace_stack = [self.root_namespace]

        self.exit_now = 0
        self.access_log = None
        self.error_log = sys.stderr  # possibly overridden in setup_logs()
        sys.stdout = self.error_log  # print is handy for debugging

        # Initialize default config object with all the default values from
        # the config variables at the top of the config module, ie. if
        # ERROR_LOG is set to "/var/log/quxiote-error.log", then
        # config.ERROR_LOG will also be "/var/log/quixote-error.log".  If
        # application FCGI/CGI scripts need to override any of these
        # defaults, they can do so by direct manipulation of the config
        # object, or by reading a config file:
        #   app.read_config("myapp.conf")
        if config is None:
            self.config = Config()
        else:
            self.set_config(config)

        self._local = threading.local()

    @property
    def _request(self):
        warnings.warn("use get_request instead of _request")
        return self.get_request()

    def configure(self, **kwargs):
        self.config.set_from_dict(kwargs)

    def read_config(self, filename):
        self.config.read_file(filename)

    def set_config(self, config):
        from quixote.config import Config
        if not isinstance(config, Config):
            raise TypeError, "'config' must be a Config instance"
        self.config = config

    def setup_logs(self):
        """
         Open all log files specified in the config file. Reassign
        sys.stderr to go to the error log, and sys.stdout to go to
        the debug log.
        """

        if self.config.access_log is not None:
            try:
                self.access_log = open(self.config.access_log, 'a', 1)
            except IOError, exc:
                sys.stderr.write("error opening access log %s: %s\n" %
                                 ( ` self.config.access_log `, exc.strerror))

        if self.config.error_log is not None:
            try:
                self.error_log = open(self.config.error_log, 'a', 1)
                sys.stderr = self.error_log
            except IOError, exc:
                # leave self.error_log as it was, most likely sys.stderr
                sys.stderr.write("error opening error log %s: %s\n" %
                                 ( ` self.config.error_log `, exc.strerror))