{ "info": { "author": "Jonathan Eunice", "author_email": "jonathan.eunice@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 3 - Alpha", "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 2.5", "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3.2", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Topic :: Software Development :: Libraries :: Python Modules" ], "description": "Intensional (rule-defined) sets for Python.\n\nOverview\n========\n\nThere are two ways of defining a set: intensional and extensional. Extensional\nsets like ``set([1,3,5,'daisy'])`` enumerate every member of the set explicitly.\n\nIntensional sets, in contrast, are defined by rules. For example \"the set of all\nprime numbers\" or \"every word beginning with ``'a'`` and ending with ``'t'``.\nIntensional sets are often infinite. It may be possible to generate a list of\ntheir members, but it's not as simple as a \"give me everything you've got!\"\n``for`` loop.\n\nOnce you know what you're looking for, intensional sets are *everywhere*.\nPython doesn't represent them directly, but regular expressions, many list\ncomprehensions, and all manner of testing and filtering operations are really\nfaces of the intensional set concept. Many functions test whether something\n'qualifies'. ``os.path.isdir(d)`` for example, tests whether ``d`` is in the set\nof legitimate directories, and ``isinstance(s, str)`` tests whether ``s`` is a\nmember of the set of ``str`` objects. Even the core ``if`` conditional can be\nconstrued as testing for membership in an intensional set--the set of all items\nthat pass the test.\n\nMany such tests have a temporal aspect--they determine whether a value is a\nmember *right now*. The answer may change in the future, if\nconditions change. Others tests are invariant over time. ``%%734`` will never be a\nvalid Python identifier, no matter how many times it's tested--unless the rules\nof the overall Python universe change, that is.\n\nIntensional sets are part and parcel of all programming, even if they're not\nexplicitly represented or called by that name.``intensional`` helps Python\nprograms represent intensional sets directly.\n\nUsage\n=====\n\n``intensional`` defines several set ``IntensionalSet`` subclasses\nsuch as ``Any``, ``Every``, ``ButNot``,\nand ``EitherOr``. These correspond roughly to set operations union, intersection,\ndifference, and symmetric difference (aka xor). Of these, ``Any`` is the most useful::\n\n from intensional import *\n \n name = 'Stephen'\n if name in Any('Steve', 'Steven', 'Stephen'):\n print 'Good name!'\n\nSo far, there's nothing here you couldn't do with standard Python ``set`` data types.\nSo let's broaden out to more generic intensional sets::\n\n if name in Test(\"x.startswith('S')\"):\n print \"Your name starts with S!\"\n\n``Test`` takes a lambda expression or string in its constructor. If it's a string, ``Test`` assumes\nthe interesting variable name is ``x`` and compiles the string expression with an automatically provided\n``lambda x:`` prefix. This makes code a bit terser and cleaner. Now the sets start getting more\ninteresting.::\n\n starts_with_S = Test(\"x.startswith('S')\")\n ends_with_n = Test(\"x.endswith('n')\")\n \n if name in Every(starts_with_S, ends_with_n):\n ... # Stephen and Steven pass, but Steve does not\n \nOf course, this could also be rendered as::\n \n if name in Test(\"x.startswith('S') and x.endswith('n')\"):\n ... # Stephen and Steven pass, but Steve does not\n \nOr even::\n\n S_something_n = starts_with_S & ends_with_n\n if name in S_something_n:\n ...\n\nString Search\n=============\n\n``intensional`` defines sets for regular expression (``Re``) and glob (``Glob``) string matching.\nFor example::\n\n name = 'Stephen'\n if name in Re(r'\\b(s\\w*)\\b', Re.I):\n print 'Good name, {}'.format(Re._[1])\n\nNote that this enables a form of (or alternative to) *en passant* assignment\nthat shortens regular expression conditionals by at least one line\ncompared to the standard ``re`` module. A spiffed-up version of the\n``re.MatchObject`` is available at ``Re._``. This object can be\nindexed to get regexp match groups. For named groups (e.g. ``(?P\\w+)``),\nthe matched value can be retrieved by attribute: ``Re._.firstname``. All of the\nother ``re.MatchObject`` methods and properties can also be accessed this way,\nsuch as ``Re._.start(1)`` and ``Re._.span(1)``.\n\nFor simple matching, the ``Glob`` class (which plays by the rules\nof Unix glob expressions) may be simpler:\n\n if name in Glob('S*'):\n ...\n \nType Membership\n===============\n\n::\n\n if x in Instances(int):\n ...\n\nis identical to::\n\n if isinstance(x, int):\n ...\n \nAn alias ``IsInstance`` exists for ``Instances`` for cases where the singular construction is more linguistically natural.\nA second alias ``Type`` is also available.\n\nSet Operations\n==============\n\n``intensional`` supports some, but not all, of Python's classic ``set`` operations.\nThere are two primary rules:\n\n * ``IntensionalSet`` attempts to supports all of the ``collections.Set`` methods like\n ``union()`` and ``intersection()``. But ``IntensionalSet`` objects are immutable, so they do not support\n self-mutating operations like ``add()``, ``pop()``, and ``|=`` defined by\n ``collections.MutableSet``.\n \n * Because they are defined by rules rather than explicit lists of members, it is\n not (in general) possible to determine the cardinality (i.e. ``len()``) of an ``IntensionalSet``,\n nor to iterate through all of its members, nor to test equality. ``IntensionalSet`` objects are\n used primarily for determining membership.\n\nBecause of an implementation detail, ``IntensionalSet`` classes are parallel to,\nbut are not true subclasses of, ``collections.Set``.\n\nExtensions\n==========\n\nIt's easy to define new ``IntensionalSet`` subclasses that define other kinds\nof logical tests in generalized, linguistically \"clean\" ways that make code\nmore readable. As an example, the ``Instances`` intensional set is defined like this::\n\n class Instances(with_metaclass(MementoMetaclass, IntensionalSet)):\n \"\"\"\n An object is in an IsInstance if it is an instance of the given types.\n \"\"\"\n def __init__(self, *args):\n self.types = tuple(args)\n \n def __contains__(self, item):\n return isinstance(item, self.types)\n\n``__init__()`` simply remembers what arguments the set is constructed with,\nwhile ``__contains__()`` implements the test, answering: Does the given item belong in a set\nconstructed with these arguments?\n\nThe only complexity here is the ``with_metaclass(MementoMetaclass, IntensionalSet)`` phrase,\nwhich is simply a compatibility mechanism to be able to define a class in either\nPython 2 or Python 3 with a given metaclass.\n\n``MementoMetaclass`` is used so that\nonce constructed, a set object is fetched from cache rather than\nredundantly reconstructed if any subsequent mentions are made. This is a useful performance\ntweak. For regular expressions, for example, it allows the ``Re.__init__()`` set constructor\nto compile the regular expression just once, even if a program contains many mentions of\n``Re()``. Even\nhigher-performance is to assign constructed sets to a name/variable and refer to them\nvia that name. This::\n\n integers = Instances(int)\n \n if x in integers:\n ...\n\nrequires less work than::\n\n if x in Instances(int):\n ...\n\nand is preferred if the test is to be executed frequently. But this pre-naming is just a tweak, and\nnot a requirement.\n\nNotes\n=====\n\n * Commenced automated multi-version testing with\n `pytest `_\n and `tox `_.\n \n * Now\n successfully packaged for, and tested against, all late-model versions\n of Python: 2.6, 2.7, 3.2, and 3.3\n plus one (2.5) that isn't so very recent,\n and one (PyPy 1.9, based on Python 2.7.2) that is differently implemented.\n \n * ``intensional`` is just one facet of a larger project to rethink how items\n are tested for membership and/or chosen from collections. Stay tuned!\n \n * The author, `Jonathan Eunice `_ or\n `@jeunice on Twitter `_\n welcomes your comments and suggestions.\n\nInstallation\n============\n\nTo install the latest version::\n\n pip install -U intensional\n\nTo ``easy_install`` under a specific Python version (3.3 in this example)::\n\n python3.3 -m easy_install --upgrade intensional\n \n(You may need to prefix these with \"sudo \" to authorize installation. If they're\nalready installed, the ``--upgrade`` flag will be helpful; add it right before the\npackage name.)", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://bitbucket.org/jeunice/intensional", "keywords": "intensional sets lambda expression list comprehension", "license": "UNKNOWN", "maintainer": null, "maintainer_email": null, "name": "intensional", "package_url": "https://pypi.org/project/intensional/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/intensional/", "project_urls": { "Download": "UNKNOWN", "Homepage": "https://bitbucket.org/jeunice/intensional" }, "release_url": "https://pypi.org/project/intensional/0.222/", "requires_dist": null, "requires_python": null, "summary": "Intensional sets in Python", "version": "0.222" }, "last_serial": 749632, "releases": { "0.102": [], "0.103": [ { "comment_text": "", "digests": { "md5": "a4083394145a140d2a40dcb733e7ee02", "sha256": "169a905bd5986d4b05ad545ac422f95852377235d2962547dc7a0d0d9d5b2582" }, "downloads": -1, "filename": "intensional-0.103.tar.gz", "has_sig": false, "md5_digest": "a4083394145a140d2a40dcb733e7ee02", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6565, "upload_time": "2012-10-19T15:29:36", "url": "https://files.pythonhosted.org/packages/f3/96/8f7c3c917198837a1a139d09dfcf895ec37d56068cce62b022ecb25159d8/intensional-0.103.tar.gz" }, { "comment_text": "", "digests": { "md5": "21bc1a4e291a45ed66dfe5b0547a1a02", "sha256": "8ab642734ef4162e543a9986232f0a123555e40686d60793d33c5fbaae7a09ec" }, "downloads": -1, "filename": "intensional-0.103.zip", "has_sig": false, "md5_digest": "21bc1a4e291a45ed66dfe5b0547a1a02", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10296, "upload_time": "2012-10-19T15:29:34", "url": "https://files.pythonhosted.org/packages/54/64/2759a4088c226736a102714bc58aca47764b89fccdf9e6ac1cff20c47586/intensional-0.103.zip" } ], "0.106": [ { "comment_text": "", "digests": { "md5": "a67fbb4a291131a185e6daa1aaffa379", "sha256": "df225a823316048bd3d14ddccdf2dd563e894b55ccdc2e70f69aa66ed15f8ce2" }, "downloads": -1, "filename": "intensional-0.106.tar.gz", "has_sig": false, "md5_digest": "a67fbb4a291131a185e6daa1aaffa379", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6802, "upload_time": "2012-10-19T18:43:13", "url": "https://files.pythonhosted.org/packages/91/93/182593cae9225585996c671b5c0a66b61da5155b98d2d11f7b5767d65325/intensional-0.106.tar.gz" }, { "comment_text": "", "digests": { "md5": "1e16b5c4a8a715956b4276c651aab3b6", "sha256": "6853cc6fceb587c9c030db67b688a8f3a7fc9f8e7d25d105947ec46943bc9715" }, "downloads": -1, "filename": "intensional-0.106.zip", "has_sig": false, "md5_digest": "1e16b5c4a8a715956b4276c651aab3b6", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10599, "upload_time": "2012-10-19T18:43:12", "url": "https://files.pythonhosted.org/packages/60/18/2cd8fa12134080a89935a61b35f6a95939595c93a58d45b1788301669d1c/intensional-0.106.zip" } ], "0.153": [ { "comment_text": "", "digests": { "md5": "b12d85e211550d1cecb94883238af830", "sha256": "d76c058d3215aff0766db8eaf0b9ccee7e5f7ddd39ee8997078efea8b56b0cc3" }, "downloads": -1, "filename": "intensional-0.153.tar.gz", "has_sig": false, "md5_digest": "b12d85e211550d1cecb94883238af830", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10586, "upload_time": "2012-10-31T21:16:10", "url": "https://files.pythonhosted.org/packages/6f/75/6261e3921a0411a820dec0a5dbd1489b89eb009781612caa8b2247a846ac/intensional-0.153.tar.gz" }, { "comment_text": "", "digests": { "md5": "dada6320bd45272ab494b32944249764", "sha256": "58b7f9c65a217afa05e6c709ba128afbc629ddc2645cb44ef0becbdaad662f24" }, "downloads": -1, "filename": "intensional-0.153.zip", "has_sig": false, "md5_digest": "dada6320bd45272ab494b32944249764", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 19543, "upload_time": "2012-10-31T21:16:09", "url": "https://files.pythonhosted.org/packages/0e/3e/678a53cc2bddb6230942224ac0ca684572abe19211aa62b011663b48de98/intensional-0.153.zip" } ], "0.154": [ { "comment_text": "", "digests": { "md5": "1941b3b748faf8992f1a056a4267cd32", "sha256": "1ea1a41b674b6a958c413b7f534145f15bfb4917e3ecce3f55e2b57d82b07481" }, "downloads": -1, "filename": "intensional-0.154.tar.gz", "has_sig": false, "md5_digest": "1941b3b748faf8992f1a056a4267cd32", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10584, "upload_time": "2012-10-31T21:20:21", "url": "https://files.pythonhosted.org/packages/04/f3/67cfed3babcfe54dd2c07287fc6cc475493cce5948d413ed58d5ae222961/intensional-0.154.tar.gz" }, { "comment_text": "", "digests": { "md5": "a087efd95385d68af9c49cd17e8b0e54", "sha256": "d74ec31e24d02af68ade68052b9dfca3bbc0849a53b2128d6680234319d92f42" }, "downloads": -1, "filename": "intensional-0.154.zip", "has_sig": false, "md5_digest": "a087efd95385d68af9c49cd17e8b0e54", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 19547, "upload_time": "2012-10-31T21:20:20", "url": "https://files.pythonhosted.org/packages/c8/14/4549385f951a7767f98471b9515561ebe6008795a7b3e01897bbb3ff26aa/intensional-0.154.zip" } ], "0.202": [ { "comment_text": "", "digests": { "md5": "d89f84ccd3a629b004d3eac456810d47", "sha256": "0ddf5df0ec86578bd4971eb5a80f68218ef34362b0c541687f85be8897384e3d" }, "downloads": -1, "filename": "intensional-0.202.tar.gz", "has_sig": false, "md5_digest": "d89f84ccd3a629b004d3eac456810d47", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10709, "upload_time": "2012-11-21T16:55:05", "url": "https://files.pythonhosted.org/packages/30/4a/abf16c86e665ee014bb9e0040b004611ddf5108a68a237dfc68fc0bc5170/intensional-0.202.tar.gz" }, { "comment_text": "", "digests": { "md5": "6ca6709ff92b9f7efd457b50c64f2bf1", "sha256": "e428e7970be081a51402b890c7ba613a856a475abcbef35abc0f209fe274a78c" }, "downloads": -1, "filename": "intensional-0.202.zip", "has_sig": false, "md5_digest": "6ca6709ff92b9f7efd457b50c64f2bf1", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 19887, "upload_time": "2012-11-21T16:55:02", "url": "https://files.pythonhosted.org/packages/2c/19/eda5696e042219f47dc6e427ad3152656bea80cf710b9f939eba1ec55a8f/intensional-0.202.zip" } ], "0.205": [ { "comment_text": "", "digests": { "md5": "c7d86a4a73a056f388738ec417d8b064", "sha256": "4677b3f7802502ba2c709deb6cec425d78da04d258aef8a80bb3f5d2359cf3b2" }, "downloads": -1, "filename": "intensional-0.205.tar.gz", "has_sig": false, "md5_digest": "c7d86a4a73a056f388738ec417d8b064", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10877, "upload_time": "2012-11-21T17:15:46", "url": "https://files.pythonhosted.org/packages/4e/2f/7ea11bf6c7fea1fdef07a248c64c2657d87041bed006be636dbe9f22a980/intensional-0.205.tar.gz" }, { "comment_text": "", "digests": { "md5": "7552071d80e4581da381600013023045", "sha256": "6436ce2700496b4034aba5e27ba3831406fe3c138fdaecdd97652d95a3597930" }, "downloads": -1, "filename": "intensional-0.205.zip", "has_sig": false, "md5_digest": "7552071d80e4581da381600013023045", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 20073, "upload_time": "2012-11-21T17:15:45", "url": "https://files.pythonhosted.org/packages/42/aa/29180294c6d909f5ff72f46a041b0c000bd9642efa5d206f5811e3fe2944/intensional-0.205.zip" } ], "0.217": [ { "comment_text": "", "digests": { "md5": "2f860f23ca704e4717ba3ad7b320224f", "sha256": "e6bee721a7262deead58f68c7e0364993a1d5cc493492d720f7ca11f0b6dd431" }, "downloads": -1, "filename": "intensional-0.217.tar.gz", "has_sig": false, "md5_digest": "2f860f23ca704e4717ba3ad7b320224f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11255, "upload_time": "2012-11-21T21:43:07", "url": "https://files.pythonhosted.org/packages/9f/21/97f736c25881aa995a56d675e506f57bd66a57a6033a77f12e2e24dbba38/intensional-0.217.tar.gz" }, { "comment_text": "", "digests": { "md5": "0ea185b586b8390cdced335b168a0e4f", "sha256": "d27a140aa9be477dcb50d64233d872fd152dc46793344ed1aeb62870da4ccf25" }, "downloads": -1, "filename": "intensional-0.217.zip", "has_sig": false, "md5_digest": "0ea185b586b8390cdced335b168a0e4f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 20670, "upload_time": "2012-11-21T21:43:06", "url": "https://files.pythonhosted.org/packages/e5/6b/f95c6b9fdf73c0b33f9fecebd05e9b085d7ec36f38d0955a5e08cfc260a9/intensional-0.217.zip" } ], "0.220": [ { "comment_text": "", "digests": { "md5": "2a3de15d50446285367083924ba0a448", "sha256": "04ec3ec47da40b5d97d53249bd9c9c9cabcef9f9407b5fa28b50736a2dfd098b" }, "downloads": -1, "filename": "intensional-0.220.tar.gz", "has_sig": false, "md5_digest": "2a3de15d50446285367083924ba0a448", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12149, "upload_time": "2012-12-01T19:29:24", "url": "https://files.pythonhosted.org/packages/c6/24/e124f6d00dcda1ccf61e228e3514d5621c6243626e0ca6ae49f5e720bbec/intensional-0.220.tar.gz" }, { "comment_text": "", "digests": { "md5": "630f4b0dc890991e184bb4fe24197768", "sha256": "d7803e584576dc640818effc8865621f6a86c93485acf7a4a9072b3db0b98639" }, "downloads": -1, "filename": "intensional-0.220.zip", "has_sig": false, "md5_digest": "630f4b0dc890991e184bb4fe24197768", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 21592, "upload_time": "2012-12-01T19:29:22", "url": "https://files.pythonhosted.org/packages/3f/38/f41ccaaa3c836eabf58d57b53f3d1d90098299e4f414050ff9ab1660872f/intensional-0.220.zip" } ], "0.222": [ { "comment_text": "", "digests": { "md5": "742e65314b26182987291033168720e1", "sha256": "258a9686d247c753bcf8e703dac4acf35a8629bce4640a28ef6c702e17e94a98" }, "downloads": -1, "filename": "intensional-0.222.tar.gz", "has_sig": false, "md5_digest": "742e65314b26182987291033168720e1", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12155, "upload_time": "2012-12-02T01:15:19", "url": "https://files.pythonhosted.org/packages/e2/74/18c62ed6f2c69580866a246124a6646f0e2f56c4438f67856333fecff79a/intensional-0.222.tar.gz" }, { "comment_text": "", "digests": { "md5": "e90e7a909f0b313b3583b274ae79ed48", "sha256": "d93be13c8b375a66f5a2d6ebc3e7826b41791cfe4d2ce78894dccfcbf32f5300" }, "downloads": -1, "filename": "intensional-0.222.zip", "has_sig": false, "md5_digest": "e90e7a909f0b313b3583b274ae79ed48", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 21602, "upload_time": "2012-12-02T01:15:17", "url": "https://files.pythonhosted.org/packages/52/45/f6fd8f32104d039fa960ab706876e727e885ce23984a87da92e80d74bbdc/intensional-0.222.zip" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "742e65314b26182987291033168720e1", "sha256": "258a9686d247c753bcf8e703dac4acf35a8629bce4640a28ef6c702e17e94a98" }, "downloads": -1, "filename": "intensional-0.222.tar.gz", "has_sig": false, "md5_digest": "742e65314b26182987291033168720e1", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12155, "upload_time": "2012-12-02T01:15:19", "url": "https://files.pythonhosted.org/packages/e2/74/18c62ed6f2c69580866a246124a6646f0e2f56c4438f67856333fecff79a/intensional-0.222.tar.gz" }, { "comment_text": "", "digests": { "md5": "e90e7a909f0b313b3583b274ae79ed48", "sha256": "d93be13c8b375a66f5a2d6ebc3e7826b41791cfe4d2ce78894dccfcbf32f5300" }, "downloads": -1, "filename": "intensional-0.222.zip", "has_sig": false, "md5_digest": "e90e7a909f0b313b3583b274ae79ed48", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 21602, "upload_time": "2012-12-02T01:15:17", "url": "https://files.pythonhosted.org/packages/52/45/f6fd8f32104d039fa960ab706876e727e885ce23984a87da92e80d74bbdc/intensional-0.222.zip" } ] }