{ "info": { "author": "Ross Patterson", "author_email": "me@rpatterson.net", "bugtrack_url": null, "classifiers": [ "Programming Language :: Python", "Topic :: Software Development :: Libraries :: Python Modules" ], "description": ".. -*-Doctest-*-\n\n===========\nz3c.metrics\n===========\n\nCreate two document indexes.\n\n >>> from z3c.metrics import testing\n >>> foo_doc_index = testing.Index()\n >>> bar_doc_index = testing.Index()\n\nCreate one creator index.\n\n >>> creator_index = testing.Index()\n\nSet the scales for the indexes. The defaults for scales is a half\nlife of one unit. In the case of a datetime scale, the half life is\none year.\n\n >>> from z3c.metrics import scale\n >>> one_year_scale = scale.ExponentialDatetimeScale()\n >>> foo_doc_index.scale = one_year_scale\n >>> creator_index.scale = one_year_scale\n\nSpecify a half life of two years for the second document index.\n\n >>> two_year_scale = scale.ExponentialDatetimeScale(\n ... scale_unit=scale.one_year*2)\n >>> bar_doc_index.scale = two_year_scale\n\nCreate a self metric that scores the creation dates of the object\nitself.\n\n >>> from z3c.metrics import interfaces, metric\n >>> self_metric = metric.SelfMetric(\n ... field_name=\"created\", interface=interfaces.ICreated)\n\nRegister the self metric event handlers so that they are run on\ndocuments themselves for their own scores.\n\n >>> from zope import component\n >>> component.provideHandler(\n ... factory=self_metric.initSelfScore,\n ... adapts=[testing.IDocument, interfaces.IAddValueEvent])\n >>> component.provideHandler(\n ... factory=self_metric.removeSelfScore,\n ... adapts=[testing.IDocument, interfaces.IRemoveValueEvent])\n\nCreate an other metric that scores creation dates of descendants.\n\n >>> desc_metric = metric.OtherMetric(\n ... interface=interfaces.ICreated,\n ... field_name=\"created\", field_callable=True)\n\nRegister the other metric event handlers so that they are run on\ndescendants of documents for document scores.\n\n >>> component.provideHandler(\n ... factory=desc_metric.addOtherValue,\n ... adapts=[testing.IDescendant,\n ... interfaces.IAddValueEvent,\n ... testing.IDocument])\n >>> component.provideHandler(\n ... factory=desc_metric.removeOtherValue,\n ... adapts=[testing.IDescendant,\n ... interfaces.IRemoveValueEvent,\n ... testing.IDocument])\n\nCreat an init metric that initializes the score for new creators.\n\n >>> from zope.app.security import interfaces as security_ifaces\n >>> init_metric = metric.InitMetric()\n\nRegister the init metric event handlers so that they are run when\ncreators are added and removed.\n\n >>> component.provideHandler(\n ... factory=init_metric.initSelfScore,\n ... adapts=[security_ifaces.IPrincipal,\n ... interfaces.IInitScoreEvent])\n >>> component.provideHandler(\n ... factory=init_metric.removeSelfScore,\n ... adapts=[security_ifaces.IPrincipal,\n ... interfaces.IRemoveValueEvent])\n\nRegister the other metric event handlers so that they are run on\ndocuments for creators' scores.\n\n >>> other_metric = metric.OtherMetric(\n ... field_name=\"created\", interface=interfaces.ICreated)\n\n >>> from zope.app.security import interfaces as security_ifaces\n >>> component.provideHandler(\n ... factory=other_metric.addOtherValue,\n ... adapts=[testing.IDocument,\n ... interfaces.IAddValueEvent,\n ... security_ifaces.IPrincipal])\n >>> component.provideHandler(\n ... factory=other_metric.removeOtherValue,\n ... adapts=[testing.IDocument,\n ... interfaces.IRemoveValueEvent,\n ... security_ifaces.IPrincipal])\n\nRegister the other metric event handlers so that they are run on\ndescendants of documents for creators' scores.\n\n >>> component.provideHandler(\n ... factory=desc_metric.addOtherValue,\n ... adapts=[testing.IDescendant,\n ... interfaces.IAddValueEvent,\n ... security_ifaces.IPrincipal])\n >>> component.provideHandler(\n ... factory=desc_metric.removeOtherValue,\n ... adapts=[testing.IDescendant,\n ... interfaces.IRemoveValueEvent,\n ... security_ifaces.IPrincipal])\n\nCreate a principal as a creator.\n\n >>> from z3c.metrics import testing\n >>> authentication = component.getUtility(\n ... security_ifaces.IAuthentication)\n >>> baz_creator = testing.Principal()\n >>> authentication['baz_creator'] = baz_creator\n\nCreate a root container.\n\n >>> root = testing.setUpRoot()\n\nCreate one document before any metrics are added to any indexes.\n\n >>> foo_doc = testing.Document()\n >>> foo_doc.created = scale.epoch\n >>> foo_doc.creators = ('baz_creator',)\n >>> root['foo_doc'] = foo_doc\n\nCreate a descendant of the document that will be included in the score\nfor the document.\n\n >>> now = scale.epoch+scale.one_year*2\n >>> foo_desc = testing.Descendant()\n >>> foo_desc.created = now\n >>> foo_desc.creators = ('baz_creator',)\n >>> foo_doc['foo_desc'] = foo_desc\n\nThe indexes have no metrics yet, so they have no scores for the\ndocuments.\n\n >>> foo_doc_index.getScoreFor(foo_doc)\n Traceback (most recent call last):\n KeyError: ...\n >>> bar_doc_index.getScoreFor(foo_doc)\n Traceback (most recent call last):\n KeyError: ...\n >>> creator_index.getScoreFor(baz_creator)\n Traceback (most recent call last):\n KeyError: ...\n\nAdd the self metric to the first document index with the default\nweight.\n\n >>> from z3c.metrics import subscription\n >>> foo_self_sub = subscription.LocalWeightedSubscription(\n ... foo_doc_index)\n >>> component.provideSubscriptionAdapter(\n ... factory=foo_self_sub.getChangeScoreEngine,\n ... adapts=[interfaces.IMetric, testing.IDocument,\n ... interfaces.IChangeScoreEvent])\n >>> component.provideSubscriptionAdapter(\n ... factory=foo_self_sub.getBuildScoreEngine,\n ... adapts=[interfaces.IMetric, testing.IDocument,\n ... interfaces.IBuildScoreEvent])\n\nAdd the self metric to the other document index but with a weight of\ntwo.\n\n >>> bar_self_sub = subscription.LocalWeightedSubscription(\n ... bar_doc_index)\n >>> bar_self_sub.weight = 2.0\n >>> component.provideSubscriptionAdapter(\n ... factory=bar_self_sub.getChangeScoreEngine,\n ... adapts=[interfaces.IMetric,\n ... testing.IDocument,\n ... interfaces.IChangeScoreEvent])\n >>> component.provideSubscriptionAdapter(\n ... factory=bar_self_sub.getBuildScoreEngine,\n ... adapts=[interfaces.IMetric,\n ... testing.IDocument,\n ... interfaces.IBuildScoreEvent])\n\nAlso add the other metric to this index for descendants of documents.\n\n >>> bar_desc_sub = subscription.LocalWeightedSubscription(\n ... bar_doc_index)\n >>> component.provideSubscriptionAdapter(\n ... factory=bar_desc_sub.getChangeScoreEngine,\n ... adapts=[interfaces.IMetric,\n ... testing.IDocument,\n ... interfaces.IChangeScoreEvent,\n ... testing.IDescendant])\n >>> component.provideSubscriptionAdapter(\n ... factory=bar_desc_sub.getBuildScoreEngine,\n ... adapts=[interfaces.IMetric,\n ... testing.IDocument,\n ... interfaces.IBuildScoreEvent,\n ... testing.IDescendant])\n\nAdd the init metric to the creator index for creators.\n\n >>> creator_init_sub = subscription.LocalWeightedSubscription(\n ... creator_index)\n >>> component.provideSubscriptionAdapter(\n ... factory=creator_init_sub.getChangeScoreEngine,\n ... adapts=[interfaces.IMetric,\n ... security_ifaces.IPrincipal,\n ... interfaces.IChangeScoreEvent])\n >>> component.provideSubscriptionAdapter(\n ... factory=creator_init_sub.getBuildScoreEngine,\n ... adapts=[interfaces.IMetric,\n ... security_ifaces.IPrincipal,\n ... interfaces.IBuildScoreEvent])\n\nAdd the other metric to the creator index for document creators with a\nweight of two.\n\n >>> creator_doc_sub = subscription.LocalWeightedSubscription(\n ... creator_index)\n >>> creator_doc_sub.weight = 2.0\n >>> component.provideSubscriptionAdapter(\n ... factory=creator_doc_sub.getChangeScoreEngine,\n ... adapts=[interfaces.IMetric,\n ... security_ifaces.IPrincipal,\n ... interfaces.IChangeScoreEvent,\n ... testing.IDocument])\n >>> component.provideSubscriptionAdapter(\n ... factory=creator_doc_sub.getBuildScoreEngine,\n ... adapts=[interfaces.IMetric, security_ifaces.IPrincipal,\n ... interfaces.IBuildScoreEvent, testing.IDocument])\n\nAdd the other metric to the creator index for document descendant\ncreators with the default weight.\n\n >>> creator_desc_sub = subscription.LocalWeightedSubscription(\n ... creator_index)\n >>> component.provideSubscriptionAdapter(\n ... factory=creator_desc_sub.getChangeScoreEngine,\n ... adapts=[interfaces.IMetric,\n ... security_ifaces.IPrincipal,\n ... interfaces.IChangeScoreEvent,\n ... testing.IDescendant])\n >>> component.provideSubscriptionAdapter(\n ... factory=creator_desc_sub.getBuildScoreEngine,\n ... adapts=[interfaces.IMetric,\n ... security_ifaces.IPrincipal,\n ... interfaces.IBuildScoreEvent,\n ... testing.IDescendant])\n\nBuild scores for the document.\n\n >>> foo_doc_index.buildScoreFor(foo_doc)\n >>> bar_doc_index.buildScoreFor(foo_doc)\n\nNow the document has different scores in both indexes.\n\n >>> foo_doc_index.getScoreFor(foo_doc, query=now)\n 0.25\n >>> bar_doc_index.getScoreFor(foo_doc, query=now)\n 2.0\n\nBuild the score for the creator.\n\n >>> creator_index.buildScoreFor(baz_creator)\n\nNow the creators have scores in the creator index.\n\n >>> creator_index.getScoreFor(baz_creator, query=now)\n 1.5\n\nAdd a new creator.\n\n >>> qux_creator = testing.Principal()\n >>> authentication['qux_creator'] = qux_creator\n\nThe new creator now also has the correct score\n\n >>> creator_index.getScoreFor(qux_creator, query=now)\n 0.0\n\nCreate a new document with two creators.\n\n >>> bar_doc = testing.Document()\n >>> bar_doc.created = now\n >>> bar_doc.creators = ('baz_creator', 'qux_creator')\n >>> root['bar_doc'] = bar_doc\n\nThe indexes have scores for the new document.\n\n >>> foo_doc_index.getScoreFor(bar_doc, query=now)\n 1.0\n >>> bar_doc_index.getScoreFor(bar_doc, query=now)\n 2.0\n >>> creator_index.getScoreFor(baz_creator, query=now)\n 3.5\n >>> creator_index.getScoreFor(qux_creator, query=now)\n 2.0\n\nThe scores are the same if rebuilt.\n\n >>> foo_doc_index.buildScoreFor(bar_doc)\n >>> bar_doc_index.buildScoreFor(bar_doc)\n >>> creator_index.buildScoreFor(baz_creator)\n >>> creator_index.buildScoreFor(qux_creator)\n\n >>> foo_doc_index.getScoreFor(bar_doc, query=now)\n 1.0\n >>> bar_doc_index.getScoreFor(bar_doc, query=now)\n 2.0\n >>> creator_index.getScoreFor(baz_creator, query=now)\n 3.5\n >>> creator_index.getScoreFor(qux_creator, query=now)\n 2.0\n\nLater, add two descendants for this document.\n\n >>> now = scale.epoch+scale.one_year*4\n >>> bar_desc = testing.Descendant()\n >>> bar_desc.created = now\n >>> bar_doc['bar_desc'] = bar_desc\n >>> baz_desc = testing.Descendant()\n >>> baz_desc.created = now\n >>> bar_doc['baz_desc'] = baz_desc\n\nThe scores reflect the addtions.\n\n >>> foo_doc_index.getScoreFor(bar_doc, query=now)\n 0.25\n >>> bar_doc_index.getScoreFor(bar_doc, query=now)\n 3.0\n\nThe scores for the other document also reflect the advance of time.\n\n >>> foo_doc_index.getScoreFor(foo_doc, query=now)\n 0.0625\n >>> bar_doc_index.getScoreFor(foo_doc, query=now)\n 1.0\n >>> creator_index.getScoreFor(baz_creator, query=now)\n 0.875\n >>> creator_index.getScoreFor(qux_creator, query=now)\n 0.5\n\nThe scores are the same if rebuilt.\n\n >>> foo_doc_index.buildScoreFor(foo_doc)\n >>> bar_doc_index.buildScoreFor(foo_doc)\n >>> foo_doc_index.buildScoreFor(bar_doc)\n >>> bar_doc_index.buildScoreFor(bar_doc)\n >>> creator_index.buildScoreFor(baz_creator)\n >>> creator_index.buildScoreFor(qux_creator)\n\n >>> foo_doc_index.getScoreFor(foo_doc, query=now)\n 0.0625\n >>> bar_doc_index.getScoreFor(foo_doc, query=now)\n 1.0\n >>> foo_doc_index.getScoreFor(bar_doc, query=now)\n 0.25\n >>> bar_doc_index.getScoreFor(bar_doc, query=now)\n 3.0\n >>> creator_index.getScoreFor(baz_creator, query=now)\n 0.875\n >>> creator_index.getScoreFor(qux_creator, query=now)\n 0.5\n\nRemove one of the descendants.\n\n >>> del bar_doc['bar_desc']\n\nThe scores reflect the deletion of the descendant.\n\n >>> foo_doc_index.getScoreFor(bar_doc, query=now)\n 0.25\n >>> bar_doc_index.getScoreFor(bar_doc, query=now)\n 2.0\n\nThe scores are the same if rebuilt.\n\n >>> foo_doc_index.buildScoreFor(bar_doc)\n >>> bar_doc_index.buildScoreFor(bar_doc)\n\n >>> foo_doc_index.getScoreFor(bar_doc, query=now)\n 0.25\n >>> bar_doc_index.getScoreFor(bar_doc, query=now)\n 2.0\n\nRemove one of the documents.\n\n >>> del root['bar_doc']\n\nThe document indexes no longer have scores for the document.\n\n >>> foo_doc_index.getScoreFor(bar_doc)\n Traceback (most recent call last):\n KeyError: ...\n >>> bar_doc_index.getScoreFor(bar_doc)\n Traceback (most recent call last):\n KeyError: ...\n\nThe creator indexes reflect the change.\n\n >>> creator_index.getScoreFor(baz_creator, query=now)\n 0.375\n >>> creator_index.getScoreFor(qux_creator, query=now)\n 0.0\n\nXXX\n===\n\nFor example, a metric may collect the date the object itself was\ncreated. While another metric might collect the dates certain kinds\nof descendants were created. Another yet might collect rating values\nfrom certain kinds of descendants.\n\nAn index uses one or more metrics to provide efficient lookup of\nnormailized values for objects. One common use for such values is\nsorting a set of objects. The score an index stores for an object is\nthe sum of the scores determined for each metric.\n\nXXX Metrics\n===========\n\nMetrics define the values that constitute the score for an object in a\ngiven metric index. Metrics update an object's score incrementally\nand as such can only use values whose both previous and new values can\nbe retrieved on change.\n\nFor example, one value may be the creation date of a descendant. When\nsuch a value changes, the metric can assume there was no previous\nvalue. Likewise, when such an object is deleted, the metric must be\nable to retrieve the creation date from the object before it is\ndeleted in order to make the incremental adjustment.\n\nThis is mostly a concern if a metric's values are mutable, then the\nmetric must be informed whenever that value changes in such a way that\nit has access to both the preveious and new values. This should most\ncommonly be done using events to which the metric subscribes handlers.\n\nA metric is a component that knows how to look up metric values for a\ngiven object.\n\nNote that if we don't count on event order, then building an object\nscore from scratch requires explicitly initializing the index and\nensuring that none of the event handlers will initialize the socre for\nthe build score event. Otherwise, it's possible that the initializing\nevent handler will be called after other add value events and negate\ntheir effect.\n\nChangelog\n=========\n\n0.1 - 2009-04-08\n----------------\n\n* Initial release", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "http://pypi.python.org/pypi/z3c.metrics", "keywords": "zope zop3 index", "license": "ZPL", "maintainer": null, "maintainer_email": null, "name": "z3c.metrics", "package_url": "https://pypi.org/project/z3c.metrics/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/z3c.metrics/", "project_urls": { "Download": "UNKNOWN", "Homepage": "http://pypi.python.org/pypi/z3c.metrics" }, "release_url": "https://pypi.org/project/z3c.metrics/0.1/", "requires_dist": null, "requires_python": null, "summary": "Index arbitrary values as scores for object metrics.", "version": "0.1" }, "last_serial": 802054, "releases": { "0.1": [ { "comment_text": "", "digests": { "md5": "0471c0c540488d1a2ce24c0da6c80429", "sha256": "876c2f2abc0a86b71f1f2410ecddfd45f5d3424bd943ea1a5d7fe8dab46303f1" }, "downloads": -1, "filename": "z3c.metrics-0.1.tar.gz", "has_sig": false, "md5_digest": "0471c0c540488d1a2ce24c0da6c80429", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 27148, "upload_time": "2009-04-08T20:43:10", "url": "https://files.pythonhosted.org/packages/9d/25/b0b41b5078397e8464df44490bbc51fe2d313d5660a6d4b44d50c38c1857/z3c.metrics-0.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "0471c0c540488d1a2ce24c0da6c80429", "sha256": "876c2f2abc0a86b71f1f2410ecddfd45f5d3424bd943ea1a5d7fe8dab46303f1" }, "downloads": -1, "filename": "z3c.metrics-0.1.tar.gz", "has_sig": false, "md5_digest": "0471c0c540488d1a2ce24c0da6c80429", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 27148, "upload_time": "2009-04-08T20:43:10", "url": "https://files.pythonhosted.org/packages/9d/25/b0b41b5078397e8464df44490bbc51fe2d313d5660a6d4b44d50c38c1857/z3c.metrics-0.1.tar.gz" } ] }