pylons.configuration
Covered: 44 lines
Missed: 112 lines
Skipped 50 lines
Percent: 28 %

      1

    """Configuration object and defaults setup

      2

      3

    The PylonsConfig object is initialized in pylons projects inside the

      4

    :file:`config/environment.py` module. Importing the :data:`config`

      5

    object from module causes the PylonsConfig object to be created, and

      6

    setup in  app-safe manner so that multiple apps being setup avoid

      7

    conflicts.

      8

      9

    After importing :data:`config`, the project should then call

     10

    :meth:`~PylonsConfig.init_app` with the appropriate options to setup

     11

    the configuration. In the config data passed with

     12

    :meth:`~PylonsConfig.init_app`, various defaults are set use with Paste

     13

    and Routes.

     14

     15

    """

     16

    import copy

     17

    import logging

     18

    import os

     19

     20

    from paste.config import DispatchingConfig

     21

    from paste.deploy.converters import asbool

     22

    from webhelpers.mimehelper import MIMETypes

     23

     24

     25

    default_template_engine = 'mako'

     26

     27

    request_defaults = dict(charset='utf-8', errors='replace',

     28

                            decode_param_names=False, language='en-us')

     29

    response_defaults = dict(content_type='text/html',

     30

                             charset='utf-8', errors='strict',

     31

                             headers={'Cache-Control': 'no-cache',

     32

                                      'Pragma': 'no-cache'})

     33

     34

    log = logging.getLogger(__name__)

     35

     36

     37

    config = DispatchingConfig()

     38

     39

    class PylonsConfig(dict):

     40

        """Pylons configuration object

     41

     42

        The Pylons configuration object is a per-application instance

     43

        object that retains the information regarding the global and app

     44

        conf's as well as per-application instance specific data such as

     45

        the mapper, and the paths for this instance.

     46

     47

        The config object is available in your application as the Pylons

     48

        global :data:`pylons.config`. For example::

     49

     50

            from pylons import config

     51

     52

            template_paths = config['pylons.paths']['templates']

     53

     54

        There's several useful keys of the config object most people will

     55

        be interested in:

     56

     57

        ``pylons.paths``

     58

            A dict of absolute paths that were defined in the applications

     59

            ``config/environment.py`` module.

     60

        ``pylons.environ_config``

     61

            Dict of environ keys for where in the environ to pickup various

     62

            objects for registering with Pylons. If these are present then

     63

            PylonsApp will use them from environ rather than using default

     64

            middleware from Beaker. Valid keys are: ``session, cache``

     65

        ``pylons.strict_tmpl_context``

     66

            Whether or not the ``tmpl_context`` object should throw an

     67

            attribute error when access is attempted to an attribute that

     68

            doesn't exist. Defaults to True.

     69

        ``pylons.tmpl_context_attach_args``

     70

            Whethor or not Routes variables should automatically be

     71

            attached to the tmpl_context object when specified in a

     72

            controllers method.

     73

        ``pylons.request_options``

     74

            A dict of Content-Type related default settings for new

     75

            instances of :class:`~pylons.controllers.util.Request`. May

     76

            contain the values ``charset`` and ``errors`` and

     77

            ``decode_param_names``. Overrides the Pylons default values

     78

            specified by the ``request_defaults`` dict.

     79

        ``pylons.response_options``

     80

            A dict of Content-Type related default settings for new

     81

            instances of :class:`~pylons.controllers.util.Response`. May

     82

            contain the values ``content_type``, ``charset`` and

     83

            ``errors``. Overrides the Pylons default values specified by

     84

            the ``response_defaults`` dict.

     85

        ``routes.map``

     86

            Mapper object used for Routing. Yes, it is possible to add

     87

            routes after your application has started running.

     88

     89

        """

     90

        defaults = {

     91

            'debug': False,

     92

            'pylons.package': None,

     93

            'pylons.paths': {'root': None,

     94

                             'controllers': None,

     95

                             'templates': [],

     96

                             'static_files': None},

     97

            'pylons.environ_config': dict(session='beaker.session',

     98

                                          cache='beaker.cache'),

     99

            'pylons.app_globals': None,

    100

            'pylons.h': None,

    101

            'pylons.request_options': request_defaults.copy(),

    102

            'pylons.response_options': response_defaults.copy(),

    103

            'pylons.strict_tmpl_context': True,

    104

            'pylons.tmpl_context_attach_args': False,

    105

        }

    106

    107

        def init_app(self, global_conf, app_conf, package=None, paths=None):

    108

            """Initialize configuration for the application

    109

    110

            .. note

    111

                This *must* be called at least once, as soon as possible

    112

                to setup all the configuration options.

    113

    114

            ``global_conf``

    115

                Several options are expected to be set for a Pylons web

    116

                application. They will be loaded from the global_config

    117

                which has the main Paste options. If ``debug`` is not

    118

                enabled as a global config option, the following option

    119

                *must* be set:

    120

    121

                * error_to - The email address to send the debug error to

    122

    123

                The optional config options in this case are:

    124

    125

                * smtp_server - The SMTP server to use, defaults to

    126

                  'localhost'

    127

                * error_log - A logfile to write the error to

    128

                * error_subject_prefix - The prefix of the error email

    129

                  subject

    130

                * from_address - Whom the error email should be from

    131

            ``app_conf``

    132

                Defaults supplied via the [app:main] section from the Paste

    133

                config file. ``load_config`` only cares about whether a

    134

                'prefix' option is set, if so it will update Routes to

    135

                ensure URL's take that into account.

    136

            ``package``

    137

                The name of the application package, to be stored in the

    138

                app_conf.

    139

    140

            .. versionchanged:: 1.0

    141

                ``template_engine`` option is no longer supported.

    142

    143

            """

    144

            log.debug("Initializing configuration, package: '%s'", package)

    145

            conf = global_conf.copy()

    146

            conf.update(app_conf)

    147

            conf.update(dict(app_conf=app_conf, global_conf=global_conf))

    148

            conf.update(self.pop('environment_load', {}))

    149

    150

            if paths:

    151

                conf['pylons.paths'] = paths

    152

            conf['pylons.package'] = package

    153

    154

            conf['debug'] = asbool(conf.get('debug'))

    155

    156

            # Load the MIMETypes with its default types

    157

            MIMETypes.init()

    158

    159

            # Ensure all the keys from defaults are present, load them if not

    160

            for key, val in copy.deepcopy(PylonsConfig.defaults).iteritems():

    161

                conf.setdefault(key, val)

    162

    163

            # Load the errorware configuration from the Paste configuration file

    164

            # These all have defaults, and emails are only sent if configured and

    165

            # if this application is running in production mode

    166

            errorware = {}

    167

            errorware['debug'] = conf['debug']

    168

            if not errorware['debug']:

    169

                errorware['debug'] = False

    170

                errorware['error_email'] = conf.get('email_to')

    171

                errorware['error_log'] = conf.get('error_log', None)

    172

                errorware['smtp_server'] = conf.get('smtp_server',

    173

                    'localhost')

    174

                errorware['error_subject_prefix'] = conf.get(

    175

                    'error_subject_prefix', 'WebApp Error: ')

    176

                errorware['from_address'] = conf.get(

    177

                    'from_address', conf.get('error_email_from',

    178

                                             'pylons@yourapp.com'))

    179

                errorware['error_message'] = conf.get('error_message',

    180

                    'An internal server error occurred')

    181

    182

            # Copy in some defaults

    183

            if 'cache_dir' in conf:

    184

                conf.setdefault('beaker.session.data_dir',

    185

                                os.path.join(conf['cache_dir'], 'sessions'))

    186

                conf.setdefault('beaker.cache.data_dir',

    187

                                os.path.join(conf['cache_dir'], 'cache'))

    188

    189

            conf['pylons.cache_dir'] = conf.pop('cache_dir',

    190

                                                conf['app_conf'].get('cache_dir'))

    191

            # Save our errorware values

    192

            conf['pylons.errorware'] = errorware

    193

    194

            # Load conf dict into self

    195

            self.update(conf)

    196

    197

    198

    pylons_config = PylonsConfig()

    199

    200

    201

    # Push an empty config so all accesses to config at import time have something

    202

    # to look at and modify. This config will be merged with the app's when it's

    203

    # built in the paste.app_factory entry point.

    204

    pylons_config.update(copy.deepcopy(PylonsConfig.defaults))

    205

    config.push_process_config(pylons_config)

    206