{ "info": { "author": "hyw208", "author_email": "hyw208@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: Apache Software License", "Natural Language :: English", "Programming Language :: Python", "Programming Language :: Python :: 2.7" ], "description": "########################################\nBoolean expression evaluator\n########################################\nThe utility is designed to capture bool expressions as criteria objects and perform evaluations against one to many in-memory objects. For example, given an instance or a list of objects of type Car or dict or basically any type containing the info below. See tests.test_helper for a list of car objects.\n\n+---------+----------+-----------+-----------+-------------+-----------+--------------+\n| make | type | maxprice | mpgcity | mpghiway | airbags | drivetrain |\n+=========+==========+===========+===========+=============+===========+==============+\n| Acura | Small | 18.8 | 25 | 31 | None | Front |\n+---------+----------+-----------+-----------+-------------+-----------+--------------+\n| Ford | Compact | 12.2 | 22 | 27 | None | Front |\n+---------+----------+-----------+-----------+-------------+-----------+--------------+\n| Subaru | Compact | 22.7 | 23 | 30 | Driver | All |\n+---------+----------+-----------+-----------+-------------+-----------+--------------+\n\n\n===========================\nTo define a simple criteria\n===========================\nTo define an \"Eq\" criteria and evaluate against a car object of type dict. Object to be evaluated can be of any type as long as it has the property or method.\n\n >>> subaru = {\"make\": \"Subaru\", \"type\": \"Compact\", \"mpgcity\": 30} <-- define a simple car of type dict\n >>> acura = {\"make\": \"Acura\", \"type\": \"Small\", \"mpgcity\": 25}\n >>> from beval.criteria import Eq, Between\n >>> eq = Eq(\"make\", \"Subaru\")\n >>> eq(subaru)\n (True, None)\n >>> eq(acura)\n (False, None)\n\nTo define a \"Between\" criteria,\n\n >>> btw = Between(28, \"mpgcity\", 32)\n >>> btw(subaru)\n (True, None)\n >>> btw(acura)\n (False, None)\n\n===========================\nMore on defining a criteria\n===========================\nTo define a search criteria for cars where \"make\" is \"Acura\", \"type\" is \"Small\" and \"drivetrain\" is \"Front\", there are 3 options,\n\noption 1, type a string boolean expression and convert it to a criteria object\n\n >>> from beval.criteria import Const, Criteria, to_criteria, Eq, All\n >>> search_criteria = to_criteria( \"make == 'Acura' and type == 'Small' and drivetrain == 'Front'\" )\n\noption 2, create a criteria in polish notation, sort of\n\n >>> search_criteria = Criteria().Eq(\"make\", \"Acura\").Eq(\"type\", \"Small\").Eq(\"drivetrain\", \"Front\").All().Done()\n\noption 3, or simply compose a criteria object\n\n >>> search_criteria = All(Eq(\"make\", \"Acura\"), Eq(\"type\", \"Small\"), Eq(\"drivetrain\", \"Front\"))\n\n\n===========================\nMore on evaluating against an object\n===========================\nTo evaluate a search criteria, there are also a few options available,\n\noption 1, invoke the __call__ method with an underlying object or a ctx object wrapping around the underlying\n\n >>> (ans, err) = search_criteria(acura_small)\n (True, None)\n >>> (ans, err) = search_criteria(Ctx(acura_small, False))\n (True, None)\n\noption 2, call the eval method, with a ctx object\n\n >>> (ans, err) = search_criteria.eval(Ctx(acura_small, fuzzy=False))\n (True, None)\n\noption 3, define a simple function in order to change the return type and behavior\n\n >>> def evaluate(criteria, obj, fuzzy=False):\n (ans, err) = criteria(obj, fuzzy)\n if ans in (Const.UNKNOWN, Const.ERROR,):\n raise err\n else:\n return ans\n >>> evaluate(search_criteria, acura_small)\n True\n\n\n===========================\nTo transform the representation of a criteria\n===========================\nA criteria object can be serialized to a string and de-serialized back to an object,\n\n >>> expr = \"make == 'Acura' and type == 'Small' and drivetrain == 'Front'\"\n >>> expr\n \"make == 'Acura' and type == 'Small' and drivetrain == 'Front'\"\n >>> search_criteria = to_criteria(expr)\n >>> str(search_criteria)\n \"make == 'Acura' and type == 'Small' and drivetrain == 'Front'\"\n\n\n===========================\nTo change the evaluation behavior of a criteria\n===========================\nWhen dealing with a bag of objects with inconsistent api or various data quality, the fuzzy search option can be turned on. When the flag is on, evaluator continues to evaluate the next criteria despite error accessing non-existent property or exception thrown during comparison. For instance, given an expression with an non-existent property 'cpu':\n\n >>> search_criteria = to_criteria( \"cpu == 'Intel' and make == 'Acura' and type == 'Small' and drivetrain == 'Front'\" )\n >>> type(search_criteria)\n beval.criteria.All\n >>> str(search_criteria.many[0]) <-- check the 1st criteria inside\n \"cpu == 'Intel'\"\n >>> str(search_criteria.many[1]) <-- check the 2nd criteria inside\n \"make == 'Acura'\"\n >>> search_criteria(acura_small, fuzzy=False)\n ('__ERROR__', KeyError('cannot find item cpu'))\n >>> search_criteria(acura_small, fuzzy=True)\n (True, KeyError('cannot find item cpu'))\n\nDuring evaluation of the \"All\" criteria, evaluator starts with the 1st \"Eq\" criteria where cpu == 'Intel'. For the car object, acura_small, it doesn't have a 'cpu' property, therefore a KeyError is raised and captured. \"All\" criteria evaluator then continues to check the next \"Eq\" criteria where type == 'Small' and so on. The resulting err object, if any, is the very first error/exception encountered.\n\n\n===========================\nTo filter a list of objects\n===========================\nA simple way with list comprehension,\n\n >>> cars = [{\"make\": \"Subaru\", \"drivetrain\": \"All\"}, {\"make\": \"Acura\", \"drivetrain\": \"Front\"}, {\"make\": \"Ford\", \"drivetrain\": \"Front\"}]\n >>> search_criteria = to_criteria( \"make == 'Acura' and drivetrain == 'Front'\" )\n >>> matched = [car for car in cars if True in search_criteria(car)]\n >>> len(matched)\n 1\n >>> matched[0]\n {'drivetrain': 'Front', 'make': 'Acura'}\n\nOr use the built-in filter, create a predicate function that returns True or False,\n\n >>> def predicate(obj):\n (ans, err) = search_criteria(obj)\n if ans in (Const.UNKNOWN, Const.ERROR,):\n raise err\n else:\n return ans\n >>> matched = filter(predicate, cars)\n >>> len(matched)\n 1\n >>> matched[0]\n {'drivetrain': 'Front', 'make': 'Acura'}\n\nOr create a generic predicate function and use functools.partial to bind arguments,\n\n >>> from functools import partial\n >>> def predicate(criteria, fuzzy, obj):\n (ans, err) = criteria(obj, fuzzy)\n if ans in (Const.UNKNOWN, Const.ERROR,):\n raise err\n else:\n return ans\n >>> predicate2 = partial(predicate, search_criteria, False)\n >>> matched = filter(predicate2, cars)\n >>> len(matched)\n 1\n >>> matched[0]\n {'drivetrain': 'Front', 'make': 'Acura'}\n\n\n===========================\nA bit of info on Ctx\n===========================\nTBA\n\n\n===========================\nList of available criteria classes\n===========================\n* Bool\n* Eq\n* NotEq\n* Between\n* Gt\n* GtE\n* Lt\n* LtE\n* In\n* NotIn\n* And\n* All\n* Or\n* Any\n* Not", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/hyw208/beval", "keywords": "boolean expression evaluator util", "license": "Apache License, Version 2.0", "maintainer": null, "maintainer_email": null, "name": "beval", "package_url": "https://pypi.org/project/beval/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/beval/", "project_urls": { "Download": "UNKNOWN", "Homepage": "https://github.com/hyw208/beval" }, "release_url": "https://pypi.org/project/beval/1.0.7/", "requires_dist": null, "requires_python": null, "summary": "boolean expression evaluator", "version": "1.0.7" }, "last_serial": 2497616, "releases": { "1.0.1": [ { "comment_text": "", "digests": { "md5": "7f8c3da500039476d4da4c1268f87005", "sha256": "8b320ae0909ec3c51cf209220b7dbd69039622477b82962030999ecac1dcef34" }, "downloads": -1, "filename": "beval-1.0.1.tar.gz", "has_sig": false, "md5_digest": "7f8c3da500039476d4da4c1268f87005", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5817, "upload_time": "2016-11-22T04:53:43", "url": "https://files.pythonhosted.org/packages/f9/ea/6f414970c0b625769b907a3769c7a9eb2bdd90d0090112c33cdfd55bcc2c/beval-1.0.1.tar.gz" } ], "1.0.2": [ { "comment_text": "", "digests": { "md5": "e2799448dda711520af613e0e3abb6c0", "sha256": "0818697ab736d1ed422bb9f110d1993467235176ce12a3df08aee394ffff11ff" }, "downloads": -1, "filename": "beval-1.0.2.tar.gz", "has_sig": false, "md5_digest": "e2799448dda711520af613e0e3abb6c0", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8036, "upload_time": "2016-11-25T02:47:21", "url": "https://files.pythonhosted.org/packages/0f/8c/f278bfeaddbb1b6702df33429ba93ed73efe1b7f1863fc708de4994036f4/beval-1.0.2.tar.gz" } ], "1.0.3": [ { "comment_text": "", "digests": { "md5": "d2cd30f0dc43190a43e6406ab53dadfe", "sha256": "dec213b48bce43e8cef83d20a8cf85b83136afdcfe2cf8a7d54a7aaf8143b6c7" }, "downloads": -1, "filename": "beval-1.0.3.tar.gz", "has_sig": false, "md5_digest": "d2cd30f0dc43190a43e6406ab53dadfe", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8125, "upload_time": "2016-11-26T05:46:15", "url": "https://files.pythonhosted.org/packages/2a/17/21a3f71acf8e7b2d827177907efc1d7ff39a17841fe0f77466b1bc4c0b28/beval-1.0.3.tar.gz" } ], "1.0.4": [ { "comment_text": "", "digests": { "md5": "86f6caa0e17a50a167ccf5ea1c105396", "sha256": "42c9933bd03db29d7e1f17e25de72267ea76d467c4d5a02098de0b01e8715eda" }, "downloads": -1, "filename": "beval-1.0.4.tar.gz", "has_sig": false, "md5_digest": "86f6caa0e17a50a167ccf5ea1c105396", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8048, "upload_time": "2016-12-01T20:44:51", "url": "https://files.pythonhosted.org/packages/62/79/a8afac0b1cd1d6864b6dacfb9e19eee33f17e1855c2c3e3ab3c1381a6d7b/beval-1.0.4.tar.gz" } ], "1.0.5": [ { "comment_text": "", "digests": { "md5": "450e23f21c0b84bf244ef8ce3b686b1e", "sha256": "866bb18ddfd8f08676a1582f12122ead95235a5dcd3783016b29150e0a4fd759" }, "downloads": -1, "filename": "beval-1.0.5.tar.gz", "has_sig": false, "md5_digest": "450e23f21c0b84bf244ef8ce3b686b1e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8151, "upload_time": "2016-12-01T23:23:11", "url": "https://files.pythonhosted.org/packages/54/96/bf9dadf7136f72df077d63df533d7de6b63e953c649a95e515c0d4fceb39/beval-1.0.5.tar.gz" } ], "1.0.6": [ { "comment_text": "", "digests": { "md5": "0a0f28d9461cd1b3c8072e2dcdb9cd99", "sha256": "6f684e251198f2d7edc55105e6c8a5282798bbe068a726d198e3c76faf2ce83b" }, "downloads": -1, "filename": "beval-1.0.6.tar.gz", "has_sig": false, "md5_digest": "0a0f28d9461cd1b3c8072e2dcdb9cd99", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8163, "upload_time": "2016-12-03T15:23:43", "url": "https://files.pythonhosted.org/packages/c6/08/80e460b784f39c2b795a74869cf0c7bd557cd712fcdff0d4e253dc9996dd/beval-1.0.6.tar.gz" } ], "1.0.7": [ { "comment_text": "", "digests": { "md5": "c846cb7e9b9adf71b8186e857b0aee35", "sha256": "140f457d9ff0105652caa8a9ac5e19ff24f7d87ab17bd85a1592a157617e0932" }, "downloads": -1, "filename": "beval-1.0.7.tar.gz", "has_sig": false, "md5_digest": "c846cb7e9b9adf71b8186e857b0aee35", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8221, "upload_time": "2016-12-03T17:57:00", "url": "https://files.pythonhosted.org/packages/11/73/ef0b12d50ee19d433f42b8391f6de337546870c594e84651c90fef9d6de4/beval-1.0.7.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "c846cb7e9b9adf71b8186e857b0aee35", "sha256": "140f457d9ff0105652caa8a9ac5e19ff24f7d87ab17bd85a1592a157617e0932" }, "downloads": -1, "filename": "beval-1.0.7.tar.gz", "has_sig": false, "md5_digest": "c846cb7e9b9adf71b8186e857b0aee35", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8221, "upload_time": "2016-12-03T17:57:00", "url": "https://files.pythonhosted.org/packages/11/73/ef0b12d50ee19d433f42b8391f6de337546870c594e84651c90fef9d6de4/beval-1.0.7.tar.gz" } ] }