Download Install Tutorial Docs FAQ Tools WikiLicense Team IRC Planet Involvement Shop Book

root/branches/cp3-wsgi-remix/__init__.py

Revision 1244 (checked in by dowski, 2 years ago)

Created a branch for some WSGI related ideas that I have implemented.

  • Property svn:eol-style set to native
Line 
1 """Global module that all modules developing with CherryPy should import."""
2
3 __version__ = '3.0.0alpha'
4
5 import logging as _logging
6
7 from _cperror import HTTPError, HTTPRedirect, InternalRedirect, NotFound
8 from _cperror import WrongConfigValue, TimeoutError
9 import config
10
11 from _cpwsgi import Application
12
13 import _cptools
14 tools = _cptools.default_toolbox
15
16 import _cptree
17 tree = _cptree.Tree()
18 import _cpengine
19 engine = _cpengine.Engine()
20 import _cpserver
21 server = _cpserver.Server()
22
23 def quickstart(root, script_name="", conf=None):
24     """Mount the given app, start the engine and builtin server, then block."""
25     tree.mount(root, script_name, conf)
26     server.quickstart()
27     engine.start()
28
29 try:
30     from threading import local as _local
31 except ImportError:
32     from cherrypy._cpthreadinglocal import local as _local
33
34 # Create a threadlocal object to hold the request, response, and other
35 # objects. In this way, we can easily dump those objects when we stop/start
36 # a new HTTP conversation, yet still refer to them as module-level globals
37 # in a thread-safe way.
38 serving = _local()
39
40 # Bind dummy instances of default request/response
41 # (in the main thread only!) to help introspection.
42 serving.request = _cprequest.Request("localhost", "11111", "localhost")
43 serving.response = _cprequest.Response()
44
45
46 class _ThreadLocalProxy(object):
47    
48     __slots__ = ['__attrname__', '__dict__']
49    
50     def __init__(self, attrname):
51         self.__attrname__ = attrname
52    
53     def __getattr__(self, name):
54         childobject = getattr(serving, self.__attrname__)
55         return getattr(childobject, name)
56    
57     def __setattr__(self, name, value):
58         if name == "__attrname__":
59             object.__setattr__(self, "__attrname__", value)
60         else:
61             childobject = getattr(serving, self.__attrname__)
62             setattr(childobject, name, value)
63    
64     def __delattr__(self, name):
65         childobject = getattr(serving, self.__attrname__)
66         delattr(childobject, name)
67    
68     def _get_dict(self):
69         childobject = getattr(serving, self.__attrname__)
70         d = childobject.__class__.__dict__.copy()
71         d.update(childobject.__dict__)
72         return d
73     __dict__ = property(_get_dict)
74    
75     def __getitem__(self, key):
76         childobject = getattr(serving, self.__attrname__)
77         return childobject[key]
78    
79     def __setitem__(self, key, value):
80         childobject = getattr(serving, self.__attrname__)
81         childobject[key] = value
82
83
84 # Create request and response object (the same objects will be used
85 #   throughout the entire life of the webserver, but will redirect
86 #   to the "serving" object)
87 request = _ThreadLocalProxy('request')
88 response = _ThreadLocalProxy('response')
89
90 # Create thread_data object as a thread-specific all-purpose storage
91 thread_data = _local()
92
93
94
95 #                                 Logging                                 #
96
97
98 def logtime():
99     import datetime
100     now = datetime.datetime.now()
101     import rfc822
102     month = rfc822._monthnames[now.month - 1].capitalize()
103     return '%02d/%s/%04d:%02d:%02d:%02d' % (
104         now.day, month, now.year, now.hour, now.minute, now.second)
105
106 def log_access():
107     """Default method for logging access"""
108     tmpl = '%(h)s %(l)s %(u)s [%(t)s] "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"'
109     s = tmpl % {'h': request.remote.name or request.remote.ip,
110                 'l': '-',
111                 'u': getattr(request, "login", None) or "-",
112                 't': logtime(),
113                 'r': request.request_line,
114                 's': response.status.split(" ", 1)[0],
115                 'b': response.headers.get('Content-Length', '') or "-",
116                 'f': request.headers.get('referer', ''),
117                 'a': request.headers.get('user-agent', ''),
118                 }
119     try:
120         request.app.access_log.log(_logging.INFO, s)
121     except:
122         log(traceback=True)
123
124
125 _error_log = _logging.getLogger("cherrypy.error")
126 _error_log.setLevel(_logging.DEBUG)
127
128 _access_log = _logging.getLogger("cherrypy.access")
129 _access_log.setLevel(_logging.INFO)
130
131 def _log_message(msg, context = '', severity = _logging.DEBUG):
132     """Default method for logging messages (error log).
133     
134     This is not just for errors! Applications may call this at any time to
135     log application-specific information.
136     """
137    
138     try:
139         log = request.app.error_log
140     except AttributeError:
141         log = _error_log
142     log.log(severity, ' '.join((logtime(), context, msg)))
143
144 def log(msg='', context='', severity=_logging.DEBUG, traceback=False):
145     """Syntactic sugar for writing to the (error) log.
146     
147     This is not just for errors! Applications may call this at any time to
148     log application-specific information.
149     """
150     if traceback:
151         import _cperror
152         msg += _cperror.format_exc()
153     logfunc = config.get('log_function', _log_message)
154     logfunc(msg, context, severity)
155
156
157
158 #                       Helper functions for CP apps                       #
159
160
161 def decorate(func, decorator):
162     """
163     Return the decorated func. This will automatically copy all
164     non-standard attributes (like exposed) to the newly decorated function.
165     """
166     newfunc = decorator(func)
167     for key in dir(func):
168         if not hasattr(newfunc, key):
169             setattr(newfunc, key, getattr(func, key))
170     return newfunc
171
172 def decorate_all(obj, decorator):
173     """
174     Recursively decorate all exposed functions of obj and all of its children,
175     grandchildren, etc. If you used to use aspects, you might want to look
176     into these. This function modifies obj; there is no return value.
177     """
178     obj_type = type(obj)
179     for key in dir(obj):
180         if hasattr(obj_type, key): # only deal with user-defined attributes
181             continue
182         value = getattr(obj, key)
183         if callable(value) and getattr(value, "exposed", False):
184             setattr(obj, key, decorate(value, decorator))
185         decorate_all(value, decorator)
186
187
188 class ExposeItems:
189     """
190     Utility class that exposes a getitem-aware object. It does not provide
191     index() or default() methods, and it does not expose the individual item
192     objects - just the list or dict that contains them. User-specific index()
193     and default() methods can be implemented by inheriting from this class.
194     
195     Use case:
196     
197     from cherrypy import ExposeItems
198     ...
199     root.foo = ExposeItems(mylist)
200     root.bar = ExposeItems(mydict)
201     """
202     exposed = True
203     def __init__(self, items):
204         self.items = items
205     def __getattr__(self, key):
206         return self.items[key]
207
208
209 def expose(func=None, alias=None):
210     """Expose the function, optionally providing an alias or set of aliases."""
211    
212     def expose_(func):
213         func.exposed = True
214         if alias is not None:
215             if isinstance(alias, basestring):
216                 parents[alias.replace(".", "_")] = func
217             else:
218                 for a in alias:
219                     parents[a.replace(".", "_")] = func
220         return func
221    
222     import sys, types
223     parents = sys._getframe(1).f_locals
224     if isinstance(func, (types.FunctionType, types.MethodType)):
225         # expose is being called directly, before the method has been bound
226         return expose_(func)
227     else:
228         # expose is being called as a decorator
229         if alias is None:
230             alias = func
231         return expose_
232
Note: See TracBrowser for help on using the browser.

Hosted by WebFaction

Log in as guest/cpguest to create tickets