You want to customize and configure certain aspects of your Quixote server.
Quixote provides a standard configuration object (class Config in module quixote.config) and a configuration file format (see file config.py in the Quixote distribution).
This recipe shows how to:
- Load the configuration information.
- Customize configuration values.
- Pass configuration values to your application code.
Reading the configuration information
This can be done in several ways:
If your driver script creates a single instance of quixote.publish.Publisher, then you can use that instance to read and initialize configuration as follows:
from quixote.publish import Publisher def start_server(): publisher = Publisher('myapplication.ui') publisher.read_config('config.py') publisher.setup_logs()
If your driver script passes the class (not an instance) Publisher (or a subclass) to your application (as do driver scripts for SCGI servers), then you can (1) implement a subclass of quixote.publish.Publisher and (2) read and initialize configuration information in the constructor of your subclass. Here is an example:
from quixote.publish import Publisher class MyPublisher(Publisher): def __init__(self, root_namespace, config=None): Publisher.__init__(self, root_namespace, config) self.read_config('config.py') self.setup_logs() self.config.dump()
Customizing the configuration
You can modify the standard configuration in several ways. Here are a few possibilities.
Modify a copy of config.py
You could make a copy of config.py, modify the values near the top of it, and then read configuration values from that.
The down-side to doing so is that, when you up-grade Quixote, you will need to patch your modifications into a new version of config.py.
Read a configuration values file
Read the configuration information in the usual way from a file that defines one or more of the configuration variables. Look near the top of config.py for an explanation and the spelling of each of the variables that can be defined. Here is an example of a configuration values file from Quixote-0.7a3/demo/demo.conf:
DEBUG_LOG = "/tmp/quixote-demo-debug.log" ERROR_LOG = "/tmp/quixote-demo-error.log" DISPLAY_EXCEPTIONS = "plain" SECURE_ERRORS = 0
Replace configuration values
After reading the configuration information, replace the values of instance variables in the publisher's config instance variable. In the following example, we change the location of the error log:
class MyPublisher(Publisher): def __init__(self, root_namespace, config=None): Publisher.__init__(self, root_namespace, config) self.read_config('config.py') self.config.error_log = '/tmp/error_log' # Change error log location. self.setup_logs() self.config.dump()
Customize the Config class
You could also implement a specialized version of class quixote.config.Config. Here is a simple example which adds a method that dumps configuration variables to a string:
from quixote.config import Config import StringIO class MyConfig(Config): def dump_to_string(self): tmpFile = StringIO.StringIO() self.dump(tmpFile) content = tmpFile.getvalue() tmpFile.close() return content
Use this subclass by passing it to the constructor of the Publisher class:
class MyPublisher(Publisher): def __init__(self, root_namespace, config=None): if config is None: config = MyConfig() Publisher.__init__(self, root_namespace, config)
Take a look at quixote.config.Config for ideas about how to customize the Config class. One idea is to implement a special way to read configuration values. Since the publisher class calls the read_file method in the configuration object to load configuration variables, overriding that method enables you to load configuration from a different source.
Passing configuration information to your application code
In some cases you may want access to configuration information from your application code.
Your application code receives an instance of the request object. So, if you want Quixote configuration variables available to your application code, do the following:
- Implement a subclass of quixote.Publisher.
In your subclass, override the start_request method.
In your start_request method, save the configuration information you need in the request object.
Here is a example:
class MyPublisher(Publisher): def __init__(self, root_namespace, config=None): Publisher.__init__(self, root_namespace, config) self.read_config('config_medusa.py') self.setup_logs() self.config.dump() def start_request(self, request): Publisher.start_request(self, request) request.myconfiguration = self.config
Note that this same technique can be used when you wish to share other kinds of resources across your application. For examples where database connections and connection proxies are shared, see ReusingConnections.
Caution: A copy of configuration information is loaded for each publisher object. Therefore, for servers that spawn processes and create a separate publisher object for each process (as the SCGI handler does), you cannot modify configuration information (the configuration object) at run-time and expect that modified version to be shared by all request handlers.
Instead of saving configuration in the request object, you can easily get reference to the Publisher object:
from quixote import get_publisher config = get_publisher().config