{ "info": { "author": "Plone Foundation", "author_email": "plone-developers@lists.sourceforge.net", "bugtrack_url": null, "classifiers": [ "Development Status :: 2 - Pre-Alpha", "Environment :: Web Environment", "Intended Audience :: Developers", "Intended Audience :: Other Audience", "Intended Audience :: System Administrators", "License :: OSI Approved :: BSD License", "Operating System :: OS Independent", "Programming Language :: Python", "Topic :: Software Development :: Libraries :: Python Modules" ], "description": "*A fussy little man in impeccable black jacket and pinstripe trousers.*\n\nIntroduction\n------------\n\nMr Bent is a framework for allowing profile data to be collected in a Python\napplication and viewed at different logical levels. The three concepts\ninvolved are a *plugin*, a piece of code that profiles an application, a\n*context*, a logical block of code for which you want reporting data, and a\n*filter*, a way of getting fine-grained information on where the results for a\ncontext came from.\n\nPlugins\n-------\n\nPlugins are callables that are given to the '''mkwrapper''' function which\napplies it to a function in your application. \n\nThis looks like::\n\n mr.bent.wrapper.mkwrapper(foo.bar, plugincallable, \"myplugin\")\n\nWhich will cause '''plugincallable''' to be called on every invocation of\n'''foo.bar''' and add the results of the plugin to the current context as\n'''myplugin'''.\n\nPlugins can return either a number or an iterable. If it returns an iterable\nit must contain **either** strings or numbers. The case of returning a number\nis considered equivalent to returning an iterable of length 1 of numbers.\n\nContexts\n--------\n\nA context stores data generated by plugins. At any point a new context can be\nstarted which will be a \"sub-context\" of the currently active context. If\nthere is no currently active context a new top-level one will be created.\n\nContexts are named with the dotted name of the function that they are created\naround, and return their data to a callback.\n\nThis looks like::\n\n def mycallback(context, result, stats):\n return \"%s \" % (result, `stats`)\n \n mr.bent.wrapper.mkcontext(bar.foo, mycallback)\n\nThis example would cause invocations of bar.foo, a function that returns XML,\nto return the XML with a repr of the context dict in a following comment.\n\nWhen a context ends it returns a mapping of the data it collected. As contexts\nare nested each time parent contexts include the data of their sub-contexts.\nHence, the top level context returns the overall profiling; there is no need\nto manually aggregate data.\n\nFilters\n-------\n\nA filter is, like most things in Mr. Bent, a wrapper around a function. This\nwill default to the dotted name of the callable, but an alternative,\napplication specific name can be used instead. This is especially useful for a\nfunction that is used to render multiple different logical blocks of content.\n\nThis looks like::\n\n mr.bent.wrapper.mkfilter(take.me.to.the.foo.bar)\n\nConcrete example\n----------------\n\nIn this example we have an application that renders a page of HTML including\nfragments that are logically different files which are then included into the\nmain page.\n\nExample 1::\n\n .-------------.\n | Top level |\n `-------------' \n |\n | .--------------------.\n |---------| Left hand column |\n | `--------------------'\n | |\n | | .-------------.\n | |--------------| Login box |\n | | `-------------' \n | |\n | |\n | | .------------------. \n | `--------------| Navigation box | \n | `------------------' \n |\n | .-----------------.\n |---------| Content block |\n | `-----------------' \n |\n | \n | .---------------------.\n `---------| Right hand column | \n `---------------------'\n |\n | .----------------.\n `--------------| Calendar box |\n `----------------'\n\nIn this system we have the following notional plugins (with short names for\nbrevity):\n\n:t:\n **A timing plugin** This plugin returns the number of milliseconds \n between it being invoked and it being stopped\n\n:d:\n **A database access counting plugin** This plugin returns how many times\n data was retrieved from a database.\n\nThe return values may look something like this:: \n\n {'t': [5, 15, 85, 25], 'd': [0, 1, 2, 8]}\n .-------------.\n | Top level |\n `-------------' \n | {'t': [5, 15], 'd': [0,1]} \n | .--------------------.\n |---------| Left hand column |\n | `--------------------'\n | | {'t': [5], 'd': [0]} \n | | .-------------.\n | |--------------| Login box |\n | | `-------------' \n | |\n | | {'t': [15], 'd': [1]} \n | | .------------------. \n | `--------------| Navigation box | \n | `------------------' \n | {'t': [85], 'd': [2]} \n | .-----------------.\n |---------| Content block |\n | `-----------------' \n |\n | {'t': [25], 'd': [8]}\n | .---------------------.\n `---------| Right hand column | \n `---------------------'\n | {'t': [25], 'd': [8]} \n | .----------------.\n `--------------| Calendar box |\n `----------------' \n \n\nHence, the user has data at each level he has defined which he can then\nprocess as he likes.\n\nLets see that again as a doctest (sorry Florian!)::\n\n >>> from mr.bent.mavolio import create, destroy, current\n >>> create(\"top\") # Create the top level context\n \n \n >>> create(\"lefthand\") # Create the left hand column\n >>> create(\"login\") # and the login portlet\n >>> current() # show that it's an empty context\n {}\n >>> current()['t'] = [5] # Simulate plugin results being added to context\n >>> current()['d'] = [0]\n >>> destroy() # Leave context\n {'t': [5], 'd': [0]}\n >>> create(\"nav\") # Create nav\n >>> current()['t']=[15]\n >>> current()['d']=[1]\n >>> destroy() # Leave nav\n {'t': [15], 'd': [1]}\n >>> destroy() # Leave left hand column\n {'t': [5, 15], 'd': [0, 1]}\n \n \n >>> create(\"content\") # Enter content block\n >>> current()['t'] = [85]\n >>> current()['d'] = [2]\n >>> destroy() # Leave content block\n {'t': [85], 'd': [2]}\n \n \n >>> create(\"righthand\") # Enter right hand column\n >>> create(\"cal\") # Enter calendar box\n >>> current()['t']=[25]\n >>> current()['d']=[8]\n >>> destroy() # Leave calendar\n {'t': [25], 'd': [8]}\n >>> destroy() # Leave right hand column\n {'t': [25], 'd': [8]}\n \n \n >>> destroy() # Leave the top level context, get totals\n {'t': [5, 15, 85, 25], 'd': [0, 1, 2, 8]}\n\n\nMethod reference\n----------------\n\n**Utility Methods**\n\n:mr.bent.wrapper.mkwrapper(function, plugin, name): \n Wraps a **function** with a **plugin** which writes its data to the \n current context as **name**\n:mr.bent.wrapper.mkcontext(function, callback): \n Wraps a **function** to create a new context on invocation, and close it \n when it finishes, and give the data to **callback** to handle reporting. \n:mr.bent.wrapper.mkfilter(function): \n Wraps a **function** to be a key that context reporting data can be \n filtered on.\n\n**Low level methods**\n\n:mr.bent.mavolio.create(name): \n Creates a new context called **name**.\n:mr.bent.mavolio.destroy(): \n Ends the current context and returns the statistics.\n:mr.bent.mavolio.current(): \n Returns the current, in progress, context dict.\n\n\nChangelog\n=========\n\n1.0a1 - Unreleased\n------------------\n\n* Initial release\n [matthewwilkes, fschulze, witsch]", "description_content_type": null, "docs_url": null, "download_url": "http://cheeseshop.python.org/pypi/mr.bent/", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "http://dev.plone.org/collective/browser/mr.bent", "keywords": "statistics profiling", "license": "BSD", "maintainer": null, "maintainer_email": null, "name": "mr.bent", "package_url": "https://pypi.org/project/mr.bent/", "platform": "Any", "project_url": "https://pypi.org/project/mr.bent/", "project_urls": { "Download": "http://cheeseshop.python.org/pypi/mr.bent/", "Homepage": "http://dev.plone.org/collective/browser/mr.bent" }, "release_url": "https://pypi.org/project/mr.bent/1.0a1/", "requires_dist": null, "requires_python": null, "summary": "Mr. Bent knows his numbers.", "version": "1.0a1" }, "last_serial": 642946, "releases": { "1.0a1": [ { "comment_text": "", "digests": { "md5": "0422d8a28383df9c97ec11c6216aac3b", "sha256": "738802d4c678bc79fb3f5327ca2563c475b0948f4de20b0650c8490b2f32aea5" }, "downloads": -1, "filename": "mr.bent-1.0a1.zip", "has_sig": true, "md5_digest": "0422d8a28383df9c97ec11c6216aac3b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 22628, "upload_time": "2008-12-14T14:33:47", "url": "https://files.pythonhosted.org/packages/3c/2c/7e83ba5bfc668f9125f519129bda9024efea76faceab289707c737c531f0/mr.bent-1.0a1.zip" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "0422d8a28383df9c97ec11c6216aac3b", "sha256": "738802d4c678bc79fb3f5327ca2563c475b0948f4de20b0650c8490b2f32aea5" }, "downloads": -1, "filename": "mr.bent-1.0a1.zip", "has_sig": true, "md5_digest": "0422d8a28383df9c97ec11c6216aac3b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 22628, "upload_time": "2008-12-14T14:33:47", "url": "https://files.pythonhosted.org/packages/3c/2c/7e83ba5bfc668f9125f519129bda9024efea76faceab289707c737c531f0/mr.bent-1.0a1.zip" } ] }