{ "info": { "author": "Jacob Zimmerman", "author_email": "sad2project@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: CC0 1.0 Universal (CC0 1.0) Public Domain Dedication", "Natural Language :: English", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Topic :: Software Development :: Libraries :: Python Modules" ], "description": "[![Python](https://img.shields.io/badge/Python-3.3+-brightgreen.svg)](https://www.python.org/)\n[![Edition](https://img.shields.io/badge/Edition-2-AA3333.svg)](http://amzn.to/2sd2Ubt)\n![Version](https://img.shields.io/badge/Version-1.1beta-992222.svg)\n# descriptor-tools\nA collection of classes and functions to make the creation of descriptors simpler\nand quicker. Most of the ideas present in this library were presented, but not \nfully fleshed out in my book, *[Python Descriptors](https://amzn.to/2HAL6gE)* \n(2nd Edition).\n\nThe first major contribution that this library provides is attribute binding \nsee below), along with many helpers for building descriptors that use it.\n\nThe next major contribution is a set of decorators (GoF style AND method \ndecorators) and mixins, both of which are the only modules that cannot have its \nmembers accessed directly from the descriptor_tools package. While everything \nelse that's public is available from there, the decorators have to be accessed \nfrom descriptor_tools.decorators, and the mixins have to be accessed from \ndescriptor_tools.mixins.\n\nSee the documentation of the corresponding modules to read more about them.\n\n### Attribute Binding\nAttribute binding is just like method binding in Python. When you refer to a \nmethod through its class name without calling it (e.g. `ClassName.method_name`), \nyou get a version of the method that can accept an instance (and whatever other \nnecessary arguments) when it is called, rather than being bound directly to the \ninstance. These were once called \"unbound methods\" in Python 2, but now they're \njust implemented as functions in Python 3. \n\nNevertheless, they are still unbound methods. And now it's possible to have \nunbound attributes. If an attribute is defined using a descriptor that uses \nattribute binding, you can get an unbound attribute from a class (e.g. \n`ClassName.attr_name`), which can then be called like a function which takes an \ninstance as a parameter and returns the attribute value for that instance. Check \nout the documentation on `UnboundAttribute` for benefits of this technique.\n\n### Special Accessor Types\nIn the book, there were four different special ways of accessing, and these \nideas are spread throughout this code base. \n\nThe first one is a binding descriptor, which implements attribute binding, \nmentioned above.\n\nThe other three are different ways of implementing \"read-only\" attributes: \nset-once, forced-set, and secret-set.\n\nThe set-once type only allows for `__set__()` to be called once per instance. \nIf it's ever tried again, it raises an `AttributeError`.\n\nThe forced-set method is similar to the secret-set method in that they both \nallow the attribute to be set multiple times, but it must be done in a \nroundabout way through a back door. Forced-set allows you call the usual \n`__set__()` method on the descriptor, but it must be provided with the named \nargument, `force=True` in order for it to not raise an `AttributeError`.\n\nSecret-set descriptors use a \"secret\" method to set the attribute, which is \nusually the `set()` method (as opposed to the `__set__()` method). This is \ngenerally preferred over the forced-set style because it doesn't require someone \nto explicitly call a \"magic\" method, and it doesn't alter the signature of a \nprotocol method.\n\n### New Addition: Instance Properties!\nThese aren't mentioned in the book because they're new, but if the book ever \ngets a new edition, they will certainly be added. What are instance properties? \nThey're a micro framework where you delegate to what are called 'delegated \nproperties', a term and idea I \"stole\" from the Kotlin language. \n\nDelegated properties are similar to descriptors, but because of the \n`InstanceProperty` wrapper/delegator, one exists per instance of the class \nthey're assigned to. This allows you to write a class for dealing with typical \nproperty situations in a much simpler way, only needing to care about the one \nvalue for the one instance it's associated with. Check them out! Currently the \nonly documentation on them is in doc strings found in the instance_properties \npackage. Later, more convenient documentation will be available, hopefully on \nReadTheDocs as well on the Github wiki.\n\n### New Addition: Universal Descriptor Storage\nIn the `storage` module, there is a new interface, `DescriptorStorage`. This \ninterface defines a set of methods that make it act mostly like a dictionary,\nbut it also has a few things for saving and/or looking up the name of the\nattribute the descriptor is assigned to, allowing it to provide nicer error\nmessages when raising an `AttributeError`, taking an extra little bit of the load\noff of the descriptor writer. \n\n### Other Points of Note\nThere are quite a few little helper functions and classes within the library, \nmost notably those for grabbing descriptor objects from classes (preventing the \nlookup from triggering the descriptor's `__get__()` method) and those for \nproviding universal ways to assign values to attributes when they're read-only \n(since a back door must usually be present for initializing the value).\n\nLastly, there are a few new \"property\" types: `BindingProperty`, which provides \nattribute binding to properties; constants, defined using the `withConstants()` \nfunction; and `LazyProperty`, which allows lazy instantiation of properties, \ngiven an evalutation method.", "description_content_type": "", "docs_url": null, "download_url": "https://github.com/sad2project/descriptor-tools/tarball/1.1.0", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/sad2project/descriptor-tools", "keywords": "descriptors,properties", "license": "CC0 1.0 Universal", "maintainer": "", "maintainer_email": "", "name": "descriptor-tools", "package_url": "https://pypi.org/project/descriptor-tools/", "platform": "", "project_url": "https://pypi.org/project/descriptor-tools/", "project_urls": { "Download": "https://github.com/sad2project/descriptor-tools/tarball/1.1.0", "Homepage": "https://github.com/sad2project/descriptor-tools" }, "release_url": "https://pypi.org/project/descriptor-tools/1.1.0/", "requires_dist": null, "requires_python": "", "summary": "A collection of classes and functions to make the creation of descriptors simpler and quicker", "version": "1.1.0" }, "last_serial": 5354441, "releases": { "1.0.2": [ { "comment_text": "", "digests": { "md5": "d692bc5aa3c45a41066096e2aa3e2897", "sha256": "43d510aa5fc49c0a4b1b6a50edfabe3fb1a0215138cc5924fdb82d339ef35f49" }, "downloads": -1, "filename": "descriptor_tools-1.0.2.zip", "has_sig": false, "md5_digest": "d692bc5aa3c45a41066096e2aa3e2897", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 17239, "upload_time": "2016-04-06T13:20:47", "url": "https://files.pythonhosted.org/packages/70/e0/b1d2e38d2eac478eed1a1791b1d748320ddeb12e671158f4078d5a25fe29/descriptor_tools-1.0.2.zip" } ], "1.1.0": [ { "comment_text": "", "digests": { "md5": "60c2dc27b619169e359548c558c94a1e", "sha256": "64fd1c247fdb21d14b985576abc9ec75b82187c5a54ff545c30e496c622ee25c" }, "downloads": -1, "filename": "descriptor_tools-1.1.0.tar.gz", "has_sig": false, "md5_digest": "60c2dc27b619169e359548c558c94a1e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 25214, "upload_time": "2019-06-03T20:55:40", "url": "https://files.pythonhosted.org/packages/1b/ca/d37c30eaa58b2443aac9ab0dde628eee75a0b49718dc07a2497bb413f97f/descriptor_tools-1.1.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "60c2dc27b619169e359548c558c94a1e", "sha256": "64fd1c247fdb21d14b985576abc9ec75b82187c5a54ff545c30e496c622ee25c" }, "downloads": -1, "filename": "descriptor_tools-1.1.0.tar.gz", "has_sig": false, "md5_digest": "60c2dc27b619169e359548c558c94a1e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 25214, "upload_time": "2019-06-03T20:55:40", "url": "https://files.pythonhosted.org/packages/1b/ca/d37c30eaa58b2443aac9ab0dde628eee75a0b49718dc07a2497bb413f97f/descriptor_tools-1.1.0.tar.gz" } ] }