Changeset 1261
- Timestamp:
- 04/27/06 11:37:50 (3 years ago)
- Files:
-
- branches/1.0/CHANGELOG.txt (modified) (1 diff)
- branches/1.0/setup.py (modified) (1 diff)
- branches/1.0/turbogears/config.py (modified) (3 diffs)
- branches/1.0/turbogears/controllers.py (modified) (1 diff)
- branches/1.0/turbogears/qstemplates/quickstartbig/+package+/controllers/root.py_tmpl (modified) (1 diff)
- branches/1.0/turbogears/qstemplates/quickstart/dev.cfg_tmpl (modified) (1 diff)
- branches/1.0/turbogears/qstemplates/quickstart/+package+/controllers.py_tmpl (modified) (2 diffs)
- branches/1.0/turbogears/qstemplates/quickstart/sample-prod.cfg_tmpl (modified) (1 diff)
- branches/1.0/turbogears/startup.py (modified) (2 diffs)
- branches/1.0/turbogears/tests/config.cfg (modified) (1 diff)
- branches/1.0/turbogears/tests/test_config.py (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
branches/1.0/CHANGELOG.txt
r1252 r1261 16 16 permissionId to be user\_name, group\_name, and permission_name. 17 17 * visit\_id has been deprecated in favor of visit_key 18 19 *Features* 20 21 * Dramatically improved and unified logging configuration. Config files 22 can now use the options in Python's logging module for log formats 23 and output. 18 24 19 25 *Changes* branches/1.0/setup.py
r1214 r1261 42 42 "cElementTree >= 1.0.5", "FormEncode >= 0.5.1", 43 43 "setuptools >= 0.6a11", 44 "RuleDispatch", " nose >= 0.8"],44 "RuleDispatch", "ConfigObj >= 4.3.0", "nose >= 0.8"], 45 45 packages=find_packages(), 46 46 include_package_data=True, branches/1.0/turbogears/config.py
r1025 r1261 2 2 3 3 from cherrypy import config 4 from configobj import ConfigObj 4 5 import pkg_resources 5 from cStringIO import StringIO 6 import logging 6 7 7 8 __all__ = ["update_config", "get", "update"] … … 12 13 from sets import Set as set 13 14 15 class ConfigError(Exception): 16 pass 17 18 def _get_formatters(formatters): 19 for key, formatter in formatters.items(): 20 kw = {} 21 fmt = formatter.get("format", None) 22 if fmt: 23 fmt = fmt.replace("*(", "%(") 24 kw["fmt"] = fmt 25 datefmt = formatter.get("datefmt", None) 26 if datefmt: 27 kw["datefmt"] = datefmt 28 formatter = logging.Formatter(**kw) 29 formatters[key] = formatter 30 31 def _get_handlers(handlers, formatters): 32 for key, handler in handlers.items(): 33 kw = {} 34 cls = handler.get("class", None) 35 if not cls: 36 raise ConfigError("No class specified for logging handler %s" 37 % key) 38 cls = eval(cls, logging.__dict__) 39 args = handler.get("args", tuple()) 40 if args: 41 args = eval(args, logging.__dict__) 42 handler_obj = cls(*args) 43 level = handler.get("level", None) 44 if level: 45 level = eval(level, logging.__dict__) 46 handler_obj.setLevel(level) 47 formatter = handler.get("formatter", None) 48 if formatter: 49 try: 50 formatter = formatters[formatter] 51 except KeyError: 52 raise ConfigError("Handler %s references unknown " 53 "formatter %s" % (key, formatter)) 54 handler_obj.setFormatter(formatter) 55 handlers[key] = handler_obj 56 57 def _get_loggers(loggers, handlers): 58 for key, logger in loggers.items(): 59 qualname = logger.get("qualname", None) 60 if qualname: 61 log = logging.getLogger(qualname) 62 else: 63 log = logging.getLogger() 64 65 level = logger.get("level", None) 66 if level: 67 level = eval(level, logging.__dict__) 68 else: 69 level = logging.NOTSET 70 log.setLevel(level) 71 72 propagate = logger.get("propagate", None) 73 if propagate is not None: 74 log.propagate = propagate 75 76 cfghandlers = logger.get("handlers", None) 77 if cfghandlers: 78 if isinstance(cfghandlers, basestring): 79 cfghandlers = [cfghandlers] 80 for handler in cfghandlers: 81 try: 82 handler = handlers[handler] 83 except KeyError: 84 raise ConfigError("Logger %s references unknown " 85 "handler %s" % (key, handler)) 86 log.addHandler(handler) 87 88 def configure_loggers(config): 89 """Configures the Python logging module, using options that are very 90 similar to the ones listed in the Python documentation. This also 91 removes the logging configuration from the configuration dictionary 92 because CherryPy doesn't like it there. Here are some of the Python 93 examples converted to the format used here: 94 95 [logging] 96 [[loggers]] 97 [[[parser]]] 98 [logger_parser] 99 level="DEBUG" 100 handlers="hand01" 101 propagate=1 102 qualname="compiler.parser" 103 104 [[handlers]] 105 [[[hand01]]] 106 class="StreamHandler" 107 level="NOTSET" 108 formatter="form01" 109 args="(sys.stdout,)" 110 111 [[formatters]] 112 [[[form01]]] 113 format="F1 *(asctime)s *(levelname)s *(message)s" 114 datefmt= 115 116 117 One notable format difference is that *() is used in the formatter 118 instead of %() because %() is already used for config file 119 interpolation. 120 """ 121 if not config.has_key("logging"): 122 config["global"]["tg.new_style_logging"] = False 123 return 124 logcfg = config["logging"] 125 formatters = logcfg.get("formatters", {}) 126 _get_formatters(formatters) 127 128 handlers = logcfg.get("handlers", {}) 129 _get_handlers(handlers, formatters) 130 131 loggers = logcfg.get("loggers", {}) 132 _get_loggers(loggers, handlers) 133 134 del config["logging"] 135 config["global"]["tg.new_style_logging"] = True 14 136 15 137 def update_config(configfile = None, modulename = None): … … 33 155 package_dir = pkg_resources.resource_filename( 34 156 packagename, "")[:-1].replace("\\", "/") 35 modconfig = config.dict_from_config_file(modfile, 36 vars=dict(top_level_dir=top_level_dir, 37 package_dir=package_dir)) 38 config.update(modconfig) 157 configdata = ConfigObj(modfile, unrepr=True) 158 configdata.merge(dict(DEFAULT= dict(top_level_dir=top_level_dir, 159 package_dir=package_dir))) 39 160 40 161 if configfile: 41 162 if modulename: 42 fileconfig = config.dict_from_config_file(configfile, 43 vars=dict(top_level_dir=top_level_dir, 44 package_dir=package_dir)) 45 config.update(fileconfig) 163 configdata2 = ConfigObj(configfile, unrepr=True) 164 configdata2['DEFAULT'] = configdata['DEFAULT'] 165 configdata.merge(configdata2) 46 166 else: 47 config.update(file=configfile) 167 configdata = ConfigObj(configfile, unrepr=True) 168 configdict = configdata.dict() 169 configure_loggers(configdict) 170 config.update(configdict) 48 171 49 172 def get(key, default_value=None, return_section=False, path = None): branches/1.0/turbogears/controllers.py
r1136 r1261 307 307 """ 308 308 is_app_root = True 309 310 msglog = logging.getLogger('cherrypy.msg') 311 msglogfunc = {0: msglog.info, 1: msglog.warning, 2: msglog.error} 312 def _cp_log_message(self, msg, context = 'nocontext', severity = 0): 313 log = self.msglogfunc[severity] 314 text = ''.join((context, ': ', msg)) 315 log(text) 316 317 accesslog = logging.getLogger("turbogears.access") 318 def _cp_log_access(self): 319 tmpl = '%(h)s %(l)s %(u)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"' 320 identity = getattr(cherrypy.request, "identity", None) 321 if not identity: 322 username = "-" 323 else: 324 username = identity.user_name 325 s = tmpl % {'h': cherrypy.request.remoteHost, 326 'l': '-', 327 'u': username, 328 'r': cherrypy.request.requestLine, 329 's': cherrypy.response.status.split(" ", 1)[0], 330 'b': cherrypy.response.headers.get('Content-Length', 331 '') or "-", 332 'f': cherrypy.request.headers.get('referer', ''), 333 'a': cherrypy.request.headers.get('user-agent', ''), 334 } 335 self.accesslog.info(s) 309 336 310 337 Root = RootController branches/1.0/turbogears/qstemplates/quickstartbig/+package+/controllers/root.py_tmpl
r996 r1261 1 import logging 2 1 3 import cherrypy 4 2 5 import turbogears 3 from turbogears import controllers 6 from turbogears import controllers, expose, redirect 7 #if $identity != "none" 4 8 from turbogears import identity 9 #end if 10 11 from ${package} import json 12 13 log = logging.getLogger("${package}.controllers") 5 14 6 15 class Root(controllers.RootController): 7 @ turbogears.expose(template="${package}.templates.welcome")16 @expose(template="${package}.templates.welcome") 8 17 def index(self): 9 18 import time 19 log.debug("Happy TurboGears Controller Responding For Duty") 10 20 return dict(now=time.ctime()) 11 12 @turbogears.expose(html="${package}.templates.login") 13 def login(self, *args, **kw): 14 if hasattr(cherrypy.request, "identity_errors"): 15 msg= _("You must provide your credentials before accessing this resource.") 16 previous_url= cherrypy.request.path 21 #if $identity != "none" 22 23 @expose(template="${package}.templates.login") 24 def login(self, forward_url=None, previous_url=None, *args, **kw): 25 26 if not identity.current.anonymous and identity.was_login_attempted(): 27 raise redirect(forward_url) 28 29 forward_url=None 30 previous_url= cherrypy.request.path 31 32 if identity.was_login_attempted(): 33 msg=_("The credentials you supplied were not correct or " 34 "did not grant access to this resource.") 35 elif identity.get_identity_errors(): 36 msg=_("You must provide your credentials before accessing " 37 "this resource.") 17 38 else: 18 msg= _("Please log in.")19 previous_url= cherrypy.request.headers.get("Referer", "/")39 msg=_("Please log in.") 40 forward_url= cherrypy.request.headers.get("Referer", "/") 20 41 cherrypy.response.status=403 21 42 return dict(message=msg, previous_url=previous_url, logging_in=True, 22 original_parameters=cherrypy.request.params) 43 original_parameters=cherrypy.request.params, 44 forward_url=forward_url) 23 45 24 @ turbogears.expose()46 @expose() 25 47 def logout(self): 26 48 identity.current.logout() 27 raise cherrypy.HTTPRedirect(turbogears.url("/")) 49 raise redirect("/") 50 #end if branches/1.0/turbogears/qstemplates/quickstart/dev.cfg_tmpl
r1073 r1261 36 36 tg.strict_parameters = True 37 37 38 # LOGGING 39 # Logging configuration generally follows the style of the standard 40 # Python logging module configuration. Note that when specifying 41 # log format messages, you need to use *() for formatting variables. 42 [logging] 43 44 [[formatters]] 45 [[[messageonly]]] 46 format='*(message)s' 47 48 [[[fullcontent]]] 49 format='*(asctime)s *(name)s *(levelname)s *(message)s' 50 51 [[handlers]] 52 [[[debugout]]] 53 class='StreamHandler' 54 level='DEBUG' 55 args='(sys.stdout,)' 56 formatter='fullcontent' 57 58 [[[accessout]]] 59 class='StreamHandler' 60 level='INFO' 61 args='(sys.stdout,)' 62 formatter='messageonly' 63 64 [[loggers]] 65 [[[yourproject]]] 66 level='DEBUG' 67 qualname='${package}' 68 handlers=['debugout'] 69 70 [[[cherrymsg]]] 71 level='INFO' 72 qualname='cherrypy.msg' 73 handlers=['debugout'] 74 75 [[[access]]] 76 level='INFO' 77 qualname='turbogears.access' 78 handlers=['accessout'] 79 propagate=0 branches/1.0/turbogears/qstemplates/quickstart/+package+/controllers.py_tmpl
r1252 r1261 1 import logging 2 1 3 import cherrypy 4 2 5 import turbogears 3 6 from turbogears import controllers, expose, redirect 7 #if $identity != "none" 4 8 from turbogears import identity 9 #end if 5 10 6 11 from ${package} import json 12 13 log = logging.getLogger("${package}.controllers") 7 14 8 15 class Root(controllers.RootController): … … 10 17 def index(self): 11 18 import time 19 log.debug("Happy TurboGears Controller Responding For Duty") 12 20 return dict(now=time.ctime()) 13 21 #if $identity != "none" branches/1.0/turbogears/qstemplates/quickstart/sample-prod.cfg_tmpl
r1233 r1261 40 40 # tg.strict_parameters = False 41 41 42 # LOGGING 43 # Logging configuration generally follows the style of the standard 44 # Python logging module configuration. Note that when specifying 45 # log format messages, you need to use *() for formatting variables. 46 [logging] 47 48 [[formatters]] 49 [[[messageonly]]] 50 format='*(message)s' 51 52 [[handlers]] 53 [[[errorout]]] 54 class='StreamHandler' 55 level='ERROR' 56 args='(sys.stdout,)' 57 58 [[[accessout]]] 59 class='StreamHandler' 60 level='INFO' 61 args="('server.log',)" 62 formatter='messageonly' 63 64 [[loggers]] 65 [[[yourproject]]] 66 level='ERROR' 67 qualname='${package}' 68 handlers=['errorout'] 69 70 [[[access]]] 71 level='INFO' 72 qualname='turbogears.access' 73 handlers=['accessout'] 74 propagate=0 branches/1.0/turbogears/startup.py
r1087 r1261 184 184 webpath = webpath + "/" 185 185 isdev = turbogears.config.get('server.environment') == 'development' 186 if turbogears.config.get('server.log_to_screen'): 186 if not turbogears.config.get("tg.new_style_logging") \ 187 and turbogears.config.get('server.log_to_screen'): 188 187 189 log = logging.getLogger() 188 190 log.setLevel(logging.DEBUG) … … 190 192 handler = logging.StreamHandler(sys.stdout) 191 193 handler.setLevel(logging.DEBUG) 194 handler.setFormatter(fmt) 195 log.addHandler(handler) 196 197 log = logging.getLogger("turbogears.access") 198 log.propagate = 0 199 fmt = logging.Formatter("%(message)s") 200 handler = logging.StreamHandler(sys.stdout) 201 handler.setLevel(logging.INFO) 192 202 handler.setFormatter(fmt) 193 203 log.addHandler(handler) branches/1.0/turbogears/tests/config.cfg
r961 r1261 7 7 [/static] 8 8 static_filter.on = True 9 10 [logging] 11 [[formatters]] 12 [[[coolformat]]] 13 format="F1 *(asctime)s *(levelname)s *(message)s" 14 datefmt= 15 16 [[handlers]] 17 [[[mystream]]] 18 class='StreamHandler' 19 level='NOTSET' 20 formatter='coolformat' 21 args='(logout,)' 22 23 [[loggers]] 24 [[[tester]]] 25 level='DEBUG' 26 handlers=['mystream'] 27 propogate=1 28 qualname="turbogears.tests.test_config.logconfig" branches/1.0/turbogears/tests/test_config.py
r1025 r1261 1 1 import turbogears 2 2 import pkg_resources 3 import sys 4 from cStringIO import StringIO 5 import logging 6 import re 3 7 4 8 testfile = pkg_resources.resource_filename(__name__, "configfile.cfg") 5 9 6 10 rfn = pkg_resources.resource_filename 11 12 logout = StringIO() 13 logging.logout = logout 7 14 8 15 def test_update_from_package(): … … 17 24 turbogears.update_config(configfile = testfile, 18 25 modulename="turbogears.tests.config") 26 print turbogears.config.get("foo.bar") 19 27 assert turbogears.config.get("foo.bar") == "blurb" 20 28 assert turbogears.config.get("tg.something") == 10 … … 39 47 print testdir 40 48 assert testdir == "c:/foo/bar" 49 50 def test_logging_config(): 51 logout.truncate(0) 52 log = logging.getLogger("turbogears.tests.test_config.logconfig") 53 log.info("Testing") 54 logged = logout.getvalue() 55 print "Logged: %s" % logged 56 assert re.match(r'F1 \d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d,\d\d\d INFO ' 57 'Testing', logged) 58 assert turbogears.config.get("tg.new_style_logging", False) 41 59 42 60 def teardown_module():