diff options
Diffstat (limited to 'vendor/CherryPy-3.2.0/sphinx/source/progguide/extending')
3 files changed, 0 insertions, 428 deletions
diff --git a/vendor/CherryPy-3.2.0/sphinx/source/progguide/extending/customplugins.rst b/vendor/CherryPy-3.2.0/sphinx/source/progguide/extending/customplugins.rst deleted file mode 100644 index 609f5c5..0000000 --- a/vendor/CherryPy-3.2.0/sphinx/source/progguide/extending/customplugins.rst +++ /dev/null @@ -1,131 +0,0 @@ -************** -Custom Plugins -************** - -CherryPy allows you to extend startup, shutdown, and other behavior outside the -request process via *Listeners* and *Plugins*. The -:class:`cherrypy.engine<cherrypy.process.wspbus.Bus>` object controls -these behaviors; to extend them, you subscribe listeners to the engine. -These allow you to run functions at a particular point in the -*site* process; for the *request* process, see :doc:`customtools` instead. - -Listeners -========= - -The engine is a publish-subscribe service; event handlers publish to various -*channels*, like "start", "stop", "exit", "graceful", or "log", and both -CherryPy and you can subscribe *listeners* for those messages:: - - engine.subscribe(channel, callback[, priority]) - -channel -------- - -The channel is an event name: - - * start: the Engine is starting for the first time, or has been stopped and is - now restarting; listeners here should start up sockets, files, or other - services and not return until they are ready to be used by clients or - other parts of the site. - * stop: the Engine is stopping; plugins should cleanly stop what they are - doing and not return until they have finished cleaning up. This is called - by :func:`cherrypy.engine.stop<cherrypy.process.wspbus.Bus.stop>`, and - plugins should make every effort to stop and clean up in a fashion that - permits them to be restarted via a "start" listener. - * graceful: advises all listeners to reload, e.g. by closing any open files - and reopening them. - * exit: this is called by - :func:`cherrypy.engine.exit<cherrypy.process.wspbus.Bus.exit>`, - and advises plugins to prepare for process termination. Note that - :func:`cherrypy.engine.exit<cherrypy.process.wspbus.Bus.exit>` first calls - :func:`cherrypy.engine.stop<cherrypy.process.wspbus.Bus.stop>`, so Plugins - may expect to stop first, then exit in a separate step. - * log(msg, level): in general, :class:`cherrypy.log<cherrypy._cplogging.LogManager>` - listens on this channel. Plugins, however, should make every effort to - publish to this channel verbosely to aid process event debugging. See the - builtin Plugins for good examples. - * main: New in 3.2. All Engine tasks run in threads other than the main thread; - the main thread usually calls - :func:`cherrypy.engine.block<cherrypy.process.wspbus.Bus.block>` to wait - for KeyboardInterrupt and other signals. While blocked, it loops - (every 1/10th of a second, by default), and publishes a message on the - "main" channel each time. Listeners subscribed to this channel, therefore, - are called at every interval. - -callback --------- - -The functionality you wish to run; this can be any function, class, or other -callable. Each channel defines the arguments; currently, however, only the "log" -channel defines any ('msg', the string message to log, and 'level', an int -following the levels defined in the stdlib's :mod:`logging <logging>` module). - -priority --------- - -The optional priority (0 - 100) allows multiple listeners to run in the correct -order. Lower numbers run first. The default is 50. - -If you omit the priority argument to engine.subscribe (or pass ``None``), -you can instead set it as an attribute on the callback function:: - - def setup_db(): - .... - setup_db.priority = 90 - engine.subscribe('start', setup_db) - - -Plugins -======= - -You can manually subscribe bus listeners, but you probably shouldn't. -*Plugins* allow your function to be subscribed and configured both -via the CherryPy config system and via the Plugin itself. Plugins also allow -you to write a single class that listens on multiple channels. - -Most of the built-in plugins have their own ``subscribe`` method, -so that instead of writing ``engine.subscribe``, you write: -``p = Plugin(engine).subscribe()``. If you want to turn off a plugin, -call ``p.unsubscribe()``. The plugin already knows the correct channel, -callback, and priority. - -You can run arbitrary code at any of the events by creating a -SimplePlugin object, with one method for each *channel* you wish to handle:: - - class ScratchDB(plugins.SimplePlugin): - - def start(self): - self.fname = 'myapp_%d.db' % os.getpid() - self.db = sqlite.connect(database=self.fname) - start.priority = 80 - - def stop(self): - self.db.close() - os.remove(self.fname) - cherrypy.engine.scratchdb = ScratchDB(cherrypy.engine) - -...then, once you've authored your Plugin, turn it on by calling its -``subscribe`` method:: - - cherrypy.engine.scratchdb.subscribe() - -...or, in CherryPy 3.2 and above, in site config:: - - [global] - engine.scratchdb.on = True - - -Priorities of the built-in "start" listeners: - -====================================================================== ================ - Listener Priority -====================================================================== ================ - default 50 - :doc:`Daemonizer </refman/process/plugins/daemonizer>` 65 - :doc:`Timeout Monitor </progguide/responsetimeouts>` 70 - :class:`Autoreloader <cherrypy.process.plugins.Autoreloader>` 70 - :doc:`PID File </refman/process/plugins/pidfile>` 70 - :doc:`HTTP Servers </refman/process/servers>` 75 - :doc:`Drop Privileges </refman/process/plugins/dropprivileges>` 77 -====================================================================== ================ - diff --git a/vendor/CherryPy-3.2.0/sphinx/source/progguide/extending/customtools.rst b/vendor/CherryPy-3.2.0/sphinx/source/progguide/extending/customtools.rst deleted file mode 100644 index 3d59a30..0000000 --- a/vendor/CherryPy-3.2.0/sphinx/source/progguide/extending/customtools.rst +++ /dev/null @@ -1,282 +0,0 @@ -************ -Custom Tools -************ - -CherryPy is an extremely capable platform for web application and framework -development. One of the strengths of CherryPy is its modular design; CherryPy -separates key-but-not-core functionality out into "tools". This provides two -benefits: a slimmer, faster core system and a supported means of tying -additional functionality into the framework. - -Tools can be enabled for any point of your CherryPy application: a certain -path, a certain class, or even individual methods using the -:ref:`_cp_config <cp_config>` dictionary. Tools can also be used as decorators -which provide syntactic sugar for configuring a tool for a specific callable. -See :doc:`/concepts/tools` for more information on how to use Tools. -This document will show you how to make your own. - -Your First Custom Tool -====================== - -Let's look at a very simple authorization tool:: - - import cherrypy - - def protect(users): - if cherrypy.request.login not in users: - raise cherrypy.HTTPError("401 Unauthorized") - - cherrypy.tools.protect = Tool('on_start_resource', protect) - -We can now enable it in the standard ways: a config file or dict passed to an -application, a :ref:`_cp_config<cp_config>` dict on a particular class or -callable or via use of the tool as a decorator. Here's how to turn it on in -a config file:: - - [/path/to/protected/resource] - tools.protect.on = True - tools.protect.users = ['me', 'myself', 'I'] - -Now let's look at the example tool a bit more closely. -Working from the bottom up, the :class:`cherrypy.Tool<cherrypy._cptools.Tool>` -constructor takes 2 required and 2 optional arguments. - -point ------ - -First, we need to declare the point in the CherryPy request/response -handling process where we want our tool to be triggered. Different request -attributes are obtained and set at different points in the request process. -In this example, we'll run at the first *hook point*, called "on_start_resource". - -.. _hooks: - -Hooks -^^^^^ - -Tools package up *hooks*. When we created a Tool instance above, the Tool -class registered our `protect` function to run at the 'on_start_resource' -*hookpoint*. You can write code that runs at hookpoints without using a Tool -to help you, but you probably shouldn't. The Tool system allows your function -to be turned on and configured both via the CherryPy config system and via the -Tool itself as a decorator. You can also write a Tool that runs code at multiple -hook points. - -Here is a quick rundown of the "hook points" that you can hang your tools on: - - * on_start_resource - The earliest hook; the Request-Line and request headers - have been processed and a dispatcher has set request.handler and request.config. - * before_request_body - Tools that are hooked up here run right before the - request body would be processed. - * before_handler - Right before the request.handler (the "exposed" callable - that was found by the dispatcher) is called. - * before_finalize - This hook is called right after the page handler has been - processed and before CherryPy formats the final response object. It helps - you for example to check for what could have been returned by your page - handler and change some headers if needed. - * on_end_resource - Processing is complete - the response is ready to be - returned. This doesn't always mean that the request.handler (the exposed - page handler) has executed! It may be a generator. If your tool absolutely - needs to run after the page handler has produced the response body, you - need to either use on_end_request instead, or wrap the response.body in a - generator which applies your tool as the response body is being generated - (what a mouthful--see - `caching tee.output <http://www.cherrypy.org/browser/trunk/cherrypy/lib/caching.py>`_ - for an example). - * before_error_response - Called right before an error response - (status code, body) is set. - * after_error_response - Called right after the error response - (status code, body) is set and just before the error response is finalized. - * on_end_request - The request/response conversation is over, all data has - been written to the client, nothing more to see here, move along. - - -callable --------- - -Second, we need to provide the function that will be called back at that -hook point. Here, we provide our ``protect`` callable. The Tool -class will find all config entries related to our tool and pass them as -keyword arguments to our callback. Thus, if:: - - 'tools.protect.on' = True - 'tools.protect.users' = ['me', 'myself', 'I'] - -is set in the config, the users list will get passed to the Tool's callable. -[The 'on' config entry is special; it's never passed as a keyword argument.] - -The tool can also be invoked as a decorator like this:: - - @cherrypy.expose - @cherrypy.tools.protect(users=['me', 'myself', 'I']) - def resource(self): - return "Hello, %s!" % cherrypy.request.login - -name ----- - -This argument is optional as long as you set the Tool onto a Toolbox. That is:: - - - def foo(): - cherrypy.request.foo = True - cherrypy.tools.TOOLNAME = cherrypy.Tool('on_start_resource', foo) - -The above will set the 'name' arg for you (to 'TOOLNAME'). The only time you -would need to provide this argument is if you're bypassing the toolbox in some way. - -priority --------- - -This specifies a priority order (from 0 - 100) that determines the order in -which callbacks in the same hook point are called. The lower the priority -number, the sooner it will run (that is, we call .sort(priority) on the list). -The default priority for a tool is set to 50 and most built-in tools use that -default value. - -Custom Toolboxes -================ - -All of the builtin CherryPy tools are collected into a Toolbox called -:attr:`cherrypy.tools`. It responds to config entries in the "tools" -:ref:`namespace<namespaces>`. You can add your own Tools to this Toolbox -as described above. - -You can also make your own Toolboxes if you need more modularity. For example, -you might create multiple Tools for working with JSON, or you might publish -a set of Tools covering authentication and authorization from which everyone -could benefit (hint, hint). Creating a new Toolbox is as simple as:: - - # cpstuff/newauth.py - import cherrypy - - # Create a new Toolbox. - newauthtools = cherrypy._cptools.Toolbox("newauth") - - # Add a Tool to our new Toolbox. - def check_access(default=False): - if not getattr(cherrypy.request, "userid", default): - raise cherrypy.HTTPError(401) - newauthtools.check_access = cherrypy.Tool('before_request_body', check_access) - -Then, in your application, use it just like you would use ``cherrypy.tools``, -with the additional step of registering your toolbox with your app. -Note that doing so automatically registers the "newauth" config namespace; -you can see the config entries in action below:: - - import cherrypy - from cpstuff import newauth - - - class Root(object): - def default(self): - return "Hello" - default.exposed = True - - conf = {'/demo': { - 'newauth.check_access.on': True, - 'newauth.check_access.default': True, - }} - - app = cherrypy.tree.mount(Root(), config=conf) - if hasattr(app, 'toolboxes'): - # CherryPy 3.1+ - app.toolboxes['newauth'] = newauth.newauthtools - -Just the Beginning -================== - -Hopefully that information is enough to get you up and running and create some -simple but useful CherryPy tools. Much more than what you have seen in this -tutorial is possible. Also, remember to take advantage of the fact that CherryPy -is open source! Check out :doc:`/progguide/builtintools` and the -:doc:`libraries</refman/lib/index>` that they are built upon. - -In closing, here is a slightly more complicated tool that acts as a -"traffic meter" and triggers a callback if a certain traffic threshold is -exceeded within a certain time frame. It should probably launch its own -watchdog thread that actually checks the log and triggers the alerts rather -than waiting on a request to do so, but I wanted to -keep it simple for the purpose of example:: - - # traffictool.py - import time - - import cherrypy - - - class TrafficAlert(cherrypy.Tool): - - def __init__(self, listclass=list): - """Initialize the TrafficAlert Tool with the given listclass.""" - - # A ring buffer subclass of list would probably be a more robust - # choice than a standard Python list. - - self._point = "on_start_resource" - self._name = None - self._priority = 50 - # set the args of self.callable as attributes on self - self._setargs() - # a log for storing our per-path traffic data - self._log = {} - # a history of the last alert for a given path - self._history = {} - self.__doc__ = self.callable.__doc__ - self._struct = listclass - - def log_hit(self, path): - """Log the time of a hit to a unique sublog for the path.""" - log = self._log.setdefault(path, self._struct()) - log.append(time.time()) - - def last_alert(self, path): - """Returns the time of the last alert for path.""" - return self._history.get(path, 0) - - def check_alert(self, path, window, threshhold, delay, callback=None): - # set the bar - now = time.time() - bar = now - window - hits = [t for t in self._log[path] if t > bar] - num_hits = len(hits) - if num_hits > threshhold: - if self.last_alert(path) + delay < now: - self._history[path] = now - if callback: - callback(path, window, threshhold, num_hits) - else: - msg = '%s - %s hits within the last %s seconds.' - msg = msg % (path, num_hits, window) - cherrypy.log.error(msg, 'TRAFFIC') - - def callable(self, window=60, threshhold=100, delay=30, callback=None): - """Alert when traffic thresholds are exceeded. - - window: the time frame within which the threshhold applies - threshhold: the number of hits within the window that will trigger - an alert - delay: the delay between alerts - callback: a callback that accepts(path, window, threshhold, num_hits) - """ - - path = cherrypy.request.path_info - self.log_hit(path) - self.check_alert(path, window, threshhold, delay, callback) - - - cherrypy.tools.traffic_alert = TrafficAlert() - - if __name__ == '__main__': - class Root(object): - @cherrypy.expose - def index(self): - return "Hi!!" - - @cherrypy.expose - @cherrypy.tools.traffic_alert(threshhold=5) - def popular(self): - return "A popular page." - - cherrypy.quickstart(Root()) - diff --git a/vendor/CherryPy-3.2.0/sphinx/source/progguide/extending/index.rst b/vendor/CherryPy-3.2.0/sphinx/source/progguide/extending/index.rst deleted file mode 100644 index dd5fac5..0000000 --- a/vendor/CherryPy-3.2.0/sphinx/source/progguide/extending/index.rst +++ /dev/null @@ -1,15 +0,0 @@ -****************** -Extending CherryPy -****************** - -If you need to perform some work that doesn't fit in a page handler, there are -two ways to do it depending on the scope of the task. If your code needs to run -on each request, or for only some URL's in your application, use a Tool. If your -code needs to run elsewhere, such as process start/stop/restart/exit, or thread -start/stop, use an Engine Plugin. - -.. toctree:: - - customtools - customplugins - |