{ "info": { "author": "David Buckley", "author_email": "buckley.w.david@gmail.com", "bugtrack_url": null, "classifiers": [ "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7" ], "description": "# keyed-classes\n\nCreate pseudo-singleton key based objects like those generated by `logging.getLogger`\n\n```python\n>>> from keyed_classes import KeyedClass\n>>> class MyClass(KeyedClass)\n... def __init__(self, key):\n... self.key = key\n...\n>>> instance_one = MyClass('this is a key')\n>>> instance_two = MyClass('this is a key')\n>>> instance_three = MyClass('this is a different key')\n>>> instance_one is instance_two\nTrue\n>>> instance_one is instance_three\nFalse\n```\n\n*Note*: Some thought needs to be put into the `__init__` method of a `KeyedClass`. If attempting to create a new instance may or may not just return a previously created instance instead, what does that mean for code in `__init__`, and instance variables (and whatever else) created there-in?\n\nThis is getting a bit implementation detail-y, but in every time you try to create a new instance the code in `__init__` will be run, `self` either referring to the newly created instance if the key did not previously exist, and referring to the original instance created from the key if it has been used before.\n\n---\n\nIf you'd like to avoid subclassing `KeyedClass` but still want something like this for whatever reason, there is also a metaclass version `keyed_classes.KeyedClassMeta`, but I would recommend against using it, as it's not quite as friendly as `keyed_classes.KeyedClass`.\n\n```python\n>>> from keyed_classes import KeyedClassMeta\n>>> class MyClass(metaclass=KeyedClassMeta)\n... def __init__(self, key):\n... self.key = key\n...\n>>> instance_one = MyClass('this is a key')\n>>> instance_two = MyClass('this is a key')\n>>> instance_three = MyClass('this is a different key')\n>>> instance_one is instance_two\nTrue\n>>> instance_one is instance_three\nFalse\n```\n\n*Note*: The behavior is not exactly the same between the two implementations. `keyed_classes.KeyedClassMeta` classes actually do create a new instance every time one is requested (and the `__init__` method is run on this new instance), but this object is essentially just thrown away before it gets back to the user and the originally created object is returned back to the user.\n\n## Why do I want this?\n\nYou probably don't!\n\nGenerally this is a bit of a cludgy solution, it is effectivly just cleverly using (and hiding from the user) global state, which we all know is something approximating the root of all evil.\n\nI came up with this as a solution to the issue of mutually exclusive groups of options in [`Click`](https://click.palletsprojects.com/en/7.x/), which does not support that feature itself.\n\n```python\nimport click\nfrom keyed_classes import KeyedClass\n\nclass MutuallyExclusiveOptionGroup(KeyedClass):\n def __init__(self, key):\n self.key = key\n self.tripped = False\n\n def __call__(self, ctx, param, value):\n if value is None:\n return\n\n if self.tripped:\n op, _ = self.option\n raise click.BadParameter(f\"'{op.name}' already specified, only one '{self.key}' option allowed in one invocation.\")\n else:\n self.tripped = True\n self.option = (param, value)\n return value\n\n\n@click.command()\n@click.option(\"--op1\", callback=MutuallyExclusiveOptionGroup('method'))\n@click.option(\"--op2\", callback=MutuallyExclusiveOptionGroup('method'))\n...\ndef main(op1, op2, ...):\n ...\n```\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/buckley-w-david/keyed-classes/", "keywords": "", "license": "MIT", "maintainer": "David Buckley", "maintainer_email": "buckley.w.david@gmail.com", "name": "keyed-classes", "package_url": "https://pypi.org/project/keyed-classes/", "platform": "", "project_url": "https://pypi.org/project/keyed-classes/", "project_urls": { "Homepage": "https://github.com/buckley-w-david/keyed-classes/" }, "release_url": "https://pypi.org/project/keyed-classes/0.1.0/", "requires_dist": null, "requires_python": "", "summary": "Create pseudo-singleton key based objects like those generated by logging.getLogger", "version": "0.1.0" }, "last_serial": 4421541, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "cce918a2c726bb77c30285868c74bf2c", "sha256": "25fe8944f7b2a168ed53617491db4dadef97634a71b7b463c62dda344a573b3a" }, "downloads": -1, "filename": "keyed_classes-0.1.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "cce918a2c726bb77c30285868c74bf2c", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 2866, "upload_time": "2018-10-27T06:58:26", "url": "https://files.pythonhosted.org/packages/7b/2c/50ce24714067c7153cfd7a50f06ea195dc2bd850f9c1d1acc773decc4080/keyed_classes-0.1.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "bbc917c4fbc86063513c51ae5ea6475a", "sha256": "777e309bc74c2b82bf532bb6713d73874f896ecfa84181f5aec925b688326efc" }, "downloads": -1, "filename": "keyed-classes-0.1.0.tar.gz", "has_sig": false, "md5_digest": "bbc917c4fbc86063513c51ae5ea6475a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 2603, "upload_time": "2018-10-27T06:58:24", "url": "https://files.pythonhosted.org/packages/29/60/b02f0b21cfd2dfb13299c1f86f893e97ed04237793765487ac0af967544f/keyed-classes-0.1.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "cce918a2c726bb77c30285868c74bf2c", "sha256": "25fe8944f7b2a168ed53617491db4dadef97634a71b7b463c62dda344a573b3a" }, "downloads": -1, "filename": "keyed_classes-0.1.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "cce918a2c726bb77c30285868c74bf2c", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 2866, "upload_time": "2018-10-27T06:58:26", "url": "https://files.pythonhosted.org/packages/7b/2c/50ce24714067c7153cfd7a50f06ea195dc2bd850f9c1d1acc773decc4080/keyed_classes-0.1.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "bbc917c4fbc86063513c51ae5ea6475a", "sha256": "777e309bc74c2b82bf532bb6713d73874f896ecfa84181f5aec925b688326efc" }, "downloads": -1, "filename": "keyed-classes-0.1.0.tar.gz", "has_sig": false, "md5_digest": "bbc917c4fbc86063513c51ae5ea6475a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 2603, "upload_time": "2018-10-27T06:58:24", "url": "https://files.pythonhosted.org/packages/29/60/b02f0b21cfd2dfb13299c1f86f893e97ed04237793765487ac0af967544f/keyed-classes-0.1.0.tar.gz" } ] }