"""Global module that all modules developing with CherryPy should import."""__version__='2.3'importdatetimeimportsysimporttypesfrom_cperrorimport*importconfigimport_cptreetree=_cptree.Tree()# Legacy code may clobber this.root=Nonelowercase_api=Falseimport_cpserverserver=_cpserver.Server()codecoverage=Falsetry:fromthreadingimportlocalexceptImportError:fromcherrypy._cpthreadinglocalimportlocal# Create a threadlocal object to hold the request and response# objects. In this way, we can easily dump those objects when# we stop/start a new HTTP conversation, yet still refer to# them as module-level globals in a thread-safe way.serving=local()class_ThreadLocalProxy:def__init__(self,attrname):self.__dict__["__attrname__"]=attrnamedef__getattr__(self,name):try:childobject=getattr(serving,self.__attrname__)exceptAttributeError:raiseAttributeError("cherrypy.%s has no properties outside of ""an HTTP request."%self.__attrname__)returngetattr(childobject,name)def__setattr__(self,name,value):try:childobject=getattr(serving,self.__attrname__)exceptAttributeError:raiseAttributeError("cherrypy.%s has no properties outside of ""an HTTP request."%self.__attrname__)setattr(childobject,name,value)def__delattr__(self,name):try:childobject=getattr(serving,self.__attrname__)exceptAttributeError:raiseAttributeError("cherrypy.%s has no properties outside of ""an HTTP request."%self.__attrname__)delattr(childobject,name)# Create request and response object (the same objects will be used# throughout the entire life of the webserver, but will redirect# to the "serving" object)request=_ThreadLocalProxy('request')response=_ThreadLocalProxy('response')# Create thread_data object as a thread-specific all-purpose storagethread_data=local()threadData=thread_data# Backward compatibility# Create variables needed for session (see lib/sessionfilter.py for more info)fromfiltersimportsessionfiltersession=sessionfilter.SessionWrapper()_session_data_holder={}# Needed for RAM sessions only_session_lock_dict={}# Needed for RAM sessions only_session_last_clean_up_time=datetime.datetime.now()defexpose(func=None,alias=None):"""Expose the function, optionally providing an alias or set of aliases."""defexpose_(func):func.exposed=TrueifaliasisnotNone:ifisinstance(alias,basestring):parents[alias.replace(".","_")]=funcelse:forainalias:parents[a.replace(".","_")]=funcreturnfuncparents=sys._getframe(1).f_localsifisinstance(func,(types.FunctionType,types.MethodType)):# expose is being called directly, before the method has been boundreturnexpose_(func)else:# expose is being called as a decoratorifaliasisNone:alias=funcreturnexpose_deflog(msg='',context='',severity=0,traceback=False):"""Syntactic sugar for writing to the (error) log."""# Load _cputil lazily to avoid circular references, and# to allow profiler and coverage tools to work on it.import_cputillogfunc=_cputil.get_special_attribute('_cp_log_message','_cpLogMessage')iftraceback:msg+=_cputil.formatExc()logfunc(msg,context,severity)