{ "info": { "author": "Tschijnmo TSCHAU", "author_email": "tschijnmotschau@gmail.com", "bugtrack_url": null, "classifiers": [ "License :: OSI Approved :: MIT License", "Programming Language :: Python", "Programming Language :: Python :: 3", "Topic :: Software Development :: Libraries :: Python Modules" ], "description": "programmabletuple\n=================\n\nAdding the programmability of normal classes to named tuples\n\n.. image:: https://travis-ci.org/tschijnmo/programmabletuple.svg?branch=master\n :target: https://travis-ci.org/tschijnmo/programmabletuple\n\n.. image:: https://coveralls.io/repos/tschijnmo/programmabletuple/badge.png\n :target: https://coveralls.io/r/tschijnmo/programmabletuple \n\n.. image:: https://badge.fury.io/py/programmabletuple.svg\n :target: http://badge.fury.io/py/programmabletuple\n\nIn essence, the programmable tuple base in this module is able to make\nuser-defined classes in Python has got the immutability of named tuple, while\nretaining the programmability of user-defined classes at the same time. Merely\nminimal change to the code for class definition is needed, and a lot features\nfor normal classes definition, like methods and inheritance, are supported.\n\nThe basic motivation for this is to make code more secure and less error-prone\nfor objects that does not frequently need to be mutated during its life time,\nespecially when we do not want to relinquish the extensibility and\nprogrammability of normal classes by changing to use the austere tuples.\n\nBasic usage\n-----------\n\nFields\n^^^^^^\n\nThe programmable tuple is directly modelled after the named tuple class in the\nstandard library. So unlike plain user-defined classes with an extensible\n``__dict__``, the instances could only have a set of pre-defined fields for\neach class. Since instances cannot be changed after the initialization, all\nthe information about an instance needs to be given to the initializer. So the\narguments to the initializer uniquely define values of the programmable tuple.\nHence they are called the defining fields of the class. Besides the defining\nfields, additional fields can be added to the class instances to hold some\nother essential data. These fields are going to be termed the data fields.\nThis can be achieved by assigning a list of names to the ``__data_fields__``\nattribute of the class, in the same way as the ``__slots__`` attribute is\nused. And the actual value for the data fields can be set in the initializer\nin the same way as normal. For example, to define an programmable tuple for\npeople to store their first and last name, and we would like the instances to\ncarry the full name with comma separation for alphabetization, we can just\ndefine\n\n.. code:: python\n\n class Person(ProgrammableTuple):\n __data_fields__ = ['full_name']\n def __init__(self, first_name, last_name):\n self.full_name = ', '.join([last_name, first_name])\n\nThen in this way, if we make an instance by running ``Person('John',\n'Smith')``, the values of all the fields, defining fields and data fields, can\nall be able to be retrieved by using the dot notation, like ``p.full_name``.\nNote that if some fields are desired to be hold private, the same underscore\nconvention of python could be used. Just it is not advised to keep defining\nattributes private.\n\nFor the fields, there are two keyword arguments that can be used for the class\ncreation. The ``auto_defining`` argument, which is True by default, controls\nthe automatic assignment of the defining fields to the ``self`` object in the\ninitializer before the actual invocation of the user-defined initializer. For\nfields that is not explicitly given a value in the initializer,\n``default_attr`` argument can be set to a function that returns the default\nvalue to set when given the name of the field as a string.\n\nNote that although there is no compulsory requirement that the values set to\nthe defining fields should match the argument that is given to the initializer,\nit is advised that at least the defining fields can be used to reproduce the\nobject. For instance, for a class named ``A`` with fields ``a`` and ``b``, it\nis a good practice to keep ``A(spam.a, spam.b) == spam`` for any instance\n``spam`` of the class ``A``, while ``spam.a`` does not need to match the\nargument ``a`` that was used for creating ``spam``. Frequently the argument\nwill accept a wide range of types for the argument, but a specific form is\ngoing to be stored as the attribute. This form can be termed the canonical form\nfor that argument. For example, the initializer could allow any iterator for a\ndefining field, but it is better to cast it to a tuple to be stored in the\nimmutable object. Then the tuple form of the elements is the canonical form of\nthat argument. It does not need to match that actual argument used for its\ncreation but it is always able to reproduce the value. For cases where most of\nthe defining fields are just taken to be the value from the argument, the\n``auto_defining`` option can be set to ``True`` to save the lines of code. But\nfor cases where almost all arguments need to be cast and specifically assigned,\nthat option can be turned off to save of overhead of the automatic assignments.\n\nMethods\n^^^^^^^\n\nMethods can also be defined for programmable tuples with exactly the same\nsyntax as the normal user-defined classes. Just here the only place where\n``self`` could be mutated is in the ``__init__`` method, any attempt to mutate\n``self`` would cause an error in any other method. So the methods here should\nbe ones that concentrates more on the return value rather than mutating the\nstate of the object. Due to this apparent deviation from the classical\nSmalltalk-style object-orientated programming, the methods normally could be\nclearly defined outside the class as a normal function, and then then we can\nforward them into the class for convenience. For instance, if we have got a\nclass for symbolic mathematical expressions and a function to compute the\nderivative with respect to a symbol, we could do\n\n.. code:: python\n\n def diff_expr(expr, symb):\n \"\"\"Compute the derivative w.r.t. a symbol\"\"\"\n ... ...\n\n class Expr(ProgrammableTuple):\n ... ...\n diff = diff_expr\n ... ...\n\nIn this way, to differentiate an expression ``e`` with respect to a symbol\n``x``, we could do both ``e.diff(x)`` and ``diff_expr(e, x)``. It only needs to\nbe noted that for functions that is intended to be used as a method as well,\nthe argument to be used as ``self`` needs to be put in the first slot. Of\ncourse methods can be kept in the class only as normal if it is desirable.\n\nNon-destructive update\n^^^^^^^^^^^^^^^^^^^^^^\n\nFrequently we need values of user-defined class that is different from an\nexisting value by relatively small amount. With mutable class, frequently this\nis achieved by mutating the instance. However, here the instances are no\nlonger mutable. So methods to update instances non-destructively are provided.\nNote that these methods will return new instances with the field updated and\nleave the original value intact, in the same way as the Haskell records works.\n\nBasically two methods are provided for this purpose, ``_update`` and\n``_replace``. Both of them takes keyword arguments with the keys being the name\nof the field to be updated and values being the new value. But for the\n``_update`` method, only defining fields are able to be updated, and more\nimportantly, a new instance will be created **by using the updated defining\nfields through the initializer**. At the same time, the ``_replace`` method\nwill just perform a plain replacement of a particular field without going\nthrough the initializer again, and it works for both defining and data fields.\n\nBoth of these two methods are named with an initial underscore, this is not\nonly an attempt to be consistent with the named tuple in the standard library,\nbut an encourage to use them only in methods as well. Then then wrapping\nmethods could carry the actual semantics of the update operation.\n\nInheritance\n^^^^^^^^^^^\n\nProgrammable tuple classes can inherit from other programmable tuple classes.\nAnd this inheritance has been made to be as similar to the plain mutable\nclasses as possible. Instances of subclass are instances of the corresponding\nsuperclass and has access to all the methods of the superclass. There is just\none notable difference, in the initializer, the built-in ``super`` function is\nnot working as before. To call the initializer of superclass, we can either\nuse ``self.super().__init__`` instead, or we can name the superclass\nexplicitly, like ``SuperClass.__init__(self, args)``.\n\nMiscellaneous\n^^^^^^^^^^^^^\n\nInstances of an programmable tuples with all the defining fields hashable are\nhashable. The default hashing function is the default hashing of the tuple\nformed by the class identity and the defining fields.\n\nInstances are all picklable.\n\nAs the named tuple, classes of this metaclass will carry an ``_asdict`` method\nto convert the instance to dictionary. The method comes with two keyword\narguments, ``full`` can be used to make the dictionary contain the data fields\nas well, and ``ordered`` can be used to return an ordered dictionary instead.\nBoth of the two default to false.", "description_content_type": null, "docs_url": null, "download_url": null, "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/tschijnmo/programmabletuple", "keywords": null, "license": "MIT", "maintainer": null, "maintainer_email": null, "name": "programmabletuple", "package_url": "https://pypi.org/project/programmabletuple/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/programmabletuple/", "project_urls": { "Homepage": "https://github.com/tschijnmo/programmabletuple" }, "release_url": "https://pypi.org/project/programmabletuple/0.5.0/", "requires_dist": null, "requires_python": null, "summary": "Python metaclass for making named tuples with programmability", "version": "0.5.0" }, "last_serial": 1697261, "releases": { "0.1": [ { "comment_text": "", "digests": { "md5": "cf7730434dc9a792591d834661c2e1d1", "sha256": "8954e4b9cd970ebf88b09c9af504e56e8898b29001e1302a01b3c2a4de8ba041" }, "downloads": -1, "filename": "programmabletuple-0.1.linux-x86_64.tar.gz", "has_sig": false, "md5_digest": "cf7730434dc9a792591d834661c2e1d1", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10071, "upload_time": "2014-12-21T11:50:50", "url": "https://files.pythonhosted.org/packages/ad/6e/22f87e1e46edb68258d7a431515b9b2cf03dfe7439f6bfeedafe4e4c2782/programmabletuple-0.1.linux-x86_64.tar.gz" }, { "comment_text": "", "digests": { "md5": "575a15b02441ed810dc16ddd2c81fe73", "sha256": "8523d09cf4888ab059be32e9a169e2951d3b07a83f78d4c13ef2ab72310db9db" }, "downloads": -1, "filename": "programmabletuple-0.1.tar.gz", "has_sig": false, "md5_digest": "575a15b02441ed810dc16ddd2c81fe73", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7397, "upload_time": "2014-12-21T11:50:53", "url": "https://files.pythonhosted.org/packages/15/3d/64a28b7c58130e782dfc7802d8db9fe42252c18d4a7c941f5d58c34eebc2/programmabletuple-0.1.tar.gz" } ], "0.2.0": [ { "comment_text": "", "digests": { "md5": "4a5e79c1dfc233318facf7eff9725a6d", "sha256": "725d558dc95c3c03cfd8089f0658f173594f7295b00b5becc0fd6dd0197de098" }, "downloads": -1, "filename": "programmabletuple-0.2.0.linux-x86_64.tar.gz", "has_sig": false, "md5_digest": "4a5e79c1dfc233318facf7eff9725a6d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12890, "upload_time": "2014-12-21T13:05:12", "url": "https://files.pythonhosted.org/packages/ce/3d/09d8ece628644d065170a72efef52ef4b7d342e2fe6250fd9b70de4078d0/programmabletuple-0.2.0.linux-x86_64.tar.gz" }, { "comment_text": "", "digests": { "md5": "11f69abd737109e2d2a224f35d8e173a", "sha256": "479dffcd38e973dc2fc967b34fdb239e5aa0fa84a1dba9aefeaca0306aeb7548" }, "downloads": -1, "filename": "programmabletuple-0.2.0-py3.3.egg", "has_sig": false, "md5_digest": "11f69abd737109e2d2a224f35d8e173a", "packagetype": "bdist_egg", "python_version": "3.3", "requires_python": null, "size": 19808, "upload_time": "2014-12-21T13:05:14", "url": "https://files.pythonhosted.org/packages/0a/8f/51d3b18a70a0a7327f7f4fcbe813cc0c35273cff4293c2086daa0b3195d2/programmabletuple-0.2.0-py3.3.egg" }, { "comment_text": "", "digests": { "md5": "286a32ef27f5f0eb11dab59e2e11754e", "sha256": "26ff8b555a736dc102c256a22c2fee65dd466ba21009fdb62a2fd626c22d9dad" }, "downloads": -1, "filename": "programmabletuple-0.2.0.tar.gz", "has_sig": false, "md5_digest": "286a32ef27f5f0eb11dab59e2e11754e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7694, "upload_time": "2014-12-21T13:05:18", "url": "https://files.pythonhosted.org/packages/35/ce/0c69670a8fb05733f8ed3812c591ba63fb4f81050bc03999ad318df4825e/programmabletuple-0.2.0.tar.gz" } ], "0.3.0": [ { "comment_text": "", "digests": { "md5": "985194e4dce1f5261397a56bee778a06", "sha256": "6aa57cd47bccc6420934cea2ae7d1fca0948b383726884cddfa73158a4fe29bb" }, "downloads": -1, "filename": "programmabletuple-0.3.0.linux-x86_64.tar.gz", "has_sig": false, "md5_digest": "985194e4dce1f5261397a56bee778a06", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13130, "upload_time": "2014-12-26T06:33:03", "url": "https://files.pythonhosted.org/packages/a4/b8/40a3a05a471592c9ee399e4e5a7d9d14ec279c83a810f5b1192bf7df8d7b/programmabletuple-0.3.0.linux-x86_64.tar.gz" }, { "comment_text": "", "digests": { "md5": "162e4312b904dc1a88f408d109aeafe7", "sha256": "1c7d65ad34a8ce2328d0f6285fe237afd884cce52fd429f77a7196e6158b9580" }, "downloads": -1, "filename": "programmabletuple-0.3.0-py2.7.egg", "has_sig": false, "md5_digest": "162e4312b904dc1a88f408d109aeafe7", "packagetype": "bdist_egg", "python_version": "2.7", "requires_python": null, "size": 19394, "upload_time": "2014-12-26T06:33:06", "url": "https://files.pythonhosted.org/packages/00/40/c16291cfa76fadf9be234da3d4bab42e645d0afa9c23c14c2bbb6e225f1e/programmabletuple-0.3.0-py2.7.egg" }, { "comment_text": "", "digests": { "md5": "faf95fdaee27b2a2eb51b27b5807f9de", "sha256": "496471d8e2b58a9aa1552566ba58657b7d8e16b78ce6ab3426987454df9e0585" }, "downloads": -1, "filename": "programmabletuple-0.3.0-py3.3.egg", "has_sig": false, "md5_digest": "faf95fdaee27b2a2eb51b27b5807f9de", "packagetype": "bdist_egg", "python_version": "3.3", "requires_python": null, "size": 19962, "upload_time": "2014-12-26T06:33:10", "url": "https://files.pythonhosted.org/packages/3d/a9/6a7d96baca8dd6c59e2cb7e670a76e4491191f2fb33d84fd712e8c06757f/programmabletuple-0.3.0-py3.3.egg" }, { "comment_text": "", "digests": { "md5": "8c9adaebb9ef4c09558baf47c6578cf5", "sha256": "c56870a8d5bb34b7c75f1d44336368512fc12237b653614a1ed035d7821df62f" }, "downloads": -1, "filename": "programmabletuple-0.3.0.tar.gz", "has_sig": false, "md5_digest": "8c9adaebb9ef4c09558baf47c6578cf5", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7802, "upload_time": "2014-12-26T06:33:12", "url": "https://files.pythonhosted.org/packages/b6/ca/9b1e4780855cfc3148d93163bef5472b63aeb357c1a45a14c8933a196c95/programmabletuple-0.3.0.tar.gz" } ], "0.4.0": [ { "comment_text": "", "digests": { "md5": "abe5be1c08a3eb17823364d36eb44319", "sha256": "ddc696039df88073bfcdb8dd86b9c0723e4d98ed92c66ebb8dc06dcc95b79b4e" }, "downloads": -1, "filename": "programmabletuple-0.4.0.linux-x86_64.tar.gz", "has_sig": false, "md5_digest": "abe5be1c08a3eb17823364d36eb44319", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 14241, "upload_time": "2015-01-05T21:30:31", "url": "https://files.pythonhosted.org/packages/6b/3d/d0b28953c3373cf81fcf09b7e0c59b7f630ce19b12053d09d31f7736f20a/programmabletuple-0.4.0.linux-x86_64.tar.gz" }, { "comment_text": "", "digests": { "md5": "3c82c7903a8813247c31f6336dbba49f", "sha256": "64335618f510755e83a0ade1ee7a569e274aa47357d939bbac15c538f5e98611" }, "downloads": -1, "filename": "programmabletuple-0.4.0-py3.4.egg", "has_sig": false, "md5_digest": "3c82c7903a8813247c31f6336dbba49f", "packagetype": "bdist_egg", "python_version": "3.4", "requires_python": null, "size": 20577, "upload_time": "2015-01-05T21:30:34", "url": "https://files.pythonhosted.org/packages/a6/3c/2fc0529be9186441c58af5259246d4bb60c37d7059605ef81f309e1046d7/programmabletuple-0.4.0-py3.4.egg" }, { "comment_text": "", "digests": { "md5": "f4d7ca58cce22c51857fd331ce0063e4", "sha256": "7aa23a8bd694ca12749b1a87974e595940202293f242aa5b587eedef74aade69" }, "downloads": -1, "filename": "programmabletuple-0.4.0-py3-none-any.whl", "has_sig": false, "md5_digest": "f4d7ca58cce22c51857fd331ce0063e4", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 16040, "upload_time": "2015-08-27T23:51:28", "url": "https://files.pythonhosted.org/packages/af/63/30fc8526e00713c9f603b494cf8088e4696e69f4db9aea2b1d844d1592cd/programmabletuple-0.4.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "dc91c961684df9f5e1d2536e79a06c6d", "sha256": "9df4bce6f12fe81a5047933a1a0ea71392a6707a0d3e78a01d1612f212d59127" }, "downloads": -1, "filename": "programmabletuple-0.4.0.tar.gz", "has_sig": false, "md5_digest": "dc91c961684df9f5e1d2536e79a06c6d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8660, "upload_time": "2015-01-05T21:30:36", "url": "https://files.pythonhosted.org/packages/d2/82/e515d400c5dca1121ebf1ca7c567475e831126dd8f18083b4e0f4e7aeb64/programmabletuple-0.4.0.tar.gz" } ], "0.5.0": [ { "comment_text": "", "digests": { "md5": "1cbba128707474cd3ef4c4e4fb586d93", "sha256": "f2e578514723aea911872701f104a034445abedd32e9a155a6d6237b362b9561" }, "downloads": -1, "filename": "programmabletuple-0.5.0-py3.4.egg", "has_sig": false, "md5_digest": "1cbba128707474cd3ef4c4e4fb586d93", "packagetype": "bdist_egg", "python_version": "3.4", "requires_python": null, "size": 19946, "upload_time": "2015-08-27T23:52:54", "url": "https://files.pythonhosted.org/packages/25/e6/81bc088bf4e722fa9122d5e1e5e019aa3b39e40ae31d3e00dd88581e5327/programmabletuple-0.5.0-py3.4.egg" }, { "comment_text": "", "digests": { "md5": "71d10906b09605047bd13fabea33dc92", "sha256": "dc1552d03c262b273555bbffcf78747b3dfad89fd957ce679a194b6dc43aeaa6" }, "downloads": -1, "filename": "programmabletuple-0.5.0-py3-none-any.whl", "has_sig": false, "md5_digest": "71d10906b09605047bd13fabea33dc92", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 16044, "upload_time": "2015-08-27T23:52:51", "url": "https://files.pythonhosted.org/packages/10/1b/4a21e9918a8e2730ca0a5eb525a3221784c9407506386e9162ef037c173e/programmabletuple-0.5.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "d3769aaad15713d71c30840e140f2842", "sha256": "23913504a8dfca1ad7bb18dd02727eb931b3038b63f54b43d56ce7af3fb048df" }, "downloads": -1, "filename": "programmabletuple-0.5.0.tar.gz", "has_sig": false, "md5_digest": "d3769aaad15713d71c30840e140f2842", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 14711, "upload_time": "2015-08-27T23:52:58", "url": "https://files.pythonhosted.org/packages/1d/5d/30facb8ad3f3f6cb05b5a66b106aae7e07ce4625ba1e9b28bb675c861d14/programmabletuple-0.5.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "1cbba128707474cd3ef4c4e4fb586d93", "sha256": "f2e578514723aea911872701f104a034445abedd32e9a155a6d6237b362b9561" }, "downloads": -1, "filename": "programmabletuple-0.5.0-py3.4.egg", "has_sig": false, "md5_digest": "1cbba128707474cd3ef4c4e4fb586d93", "packagetype": "bdist_egg", "python_version": "3.4", "requires_python": null, "size": 19946, "upload_time": "2015-08-27T23:52:54", "url": "https://files.pythonhosted.org/packages/25/e6/81bc088bf4e722fa9122d5e1e5e019aa3b39e40ae31d3e00dd88581e5327/programmabletuple-0.5.0-py3.4.egg" }, { "comment_text": "", "digests": { "md5": "71d10906b09605047bd13fabea33dc92", "sha256": "dc1552d03c262b273555bbffcf78747b3dfad89fd957ce679a194b6dc43aeaa6" }, "downloads": -1, "filename": "programmabletuple-0.5.0-py3-none-any.whl", "has_sig": false, "md5_digest": "71d10906b09605047bd13fabea33dc92", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 16044, "upload_time": "2015-08-27T23:52:51", "url": "https://files.pythonhosted.org/packages/10/1b/4a21e9918a8e2730ca0a5eb525a3221784c9407506386e9162ef037c173e/programmabletuple-0.5.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "d3769aaad15713d71c30840e140f2842", "sha256": "23913504a8dfca1ad7bb18dd02727eb931b3038b63f54b43d56ce7af3fb048df" }, "downloads": -1, "filename": "programmabletuple-0.5.0.tar.gz", "has_sig": false, "md5_digest": "d3769aaad15713d71c30840e140f2842", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 14711, "upload_time": "2015-08-27T23:52:58", "url": "https://files.pythonhosted.org/packages/1d/5d/30facb8ad3f3f6cb05b5a66b106aae7e07ce4625ba1e9b28bb675c861d14/programmabletuple-0.5.0.tar.gz" } ] }