{ "info": { "author": "CNLambda", "author_email": "dodo2998@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", "License :: Freely Distributable", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.5" ], "description": "Linked Properties\n#################\n\nThis is a python library that allows you to link properties together, so\nif one is changed the others change accordingly.\n\nYou can use this library everywhere, I don't care. Giving credit would\nbe nice, but is optional.\n\nInstalling\n==========\n\n.. code-block:: bash\n\n $ pip install linked_properties\n\nUsing\n=====\n\nThe library consists of two important parts: ``WatchableProperty`` and\n``LinkableProperty``.\n\nA class named ``ComplexLinkedProperty`` or something like that may be\nadded in the future, it would combine both concepts; but it would need\nadditional work. I added the documentation anyways.\n\n``WatchableProperty``\n---------------------\n\nAs the docstring states:\n\n::\n\n WatchableProperty is a class that is used to create a property that can be submitted to a LinkableProperty.\n\n It works exactly the same as \"property\", except for the name.\n\n If a linked property is reading from another one, than this object may be blocked for writing for the instance in question.\n To get around this, you may define an \"at_blocked_set\" function, that unlocks the linked property by setting it to None. It may return true or false, if it is true, the __set__ function is called another time.\n\n Note: the at_blocked_set function can invoke the __set__ function again only once per tried write access!\n\nYou *cannot* use normal properties to make LinkableProperties work.\n\nHere's how you can use them (Spoiler Alert: It's (almost) exactly the same as\nwith the builtin properties):\n* 1st option: Replace the builtin property (kind of). This *should generally not be used*, although it can be used if you are updating an old project to fit the requirements automatically.\n\n.. code-block:: python\n\n import linked_properties\n property = linked_properties.WatchableProperty\n # ... (Your own code)\n\n* 2nd option: Using them with function decorators. This *should* be the preferred way, but some (or just this one, i don't know) editors like PyCharm think you are working with the builtin properties. This may lead to warnings that shouldn't exist.\n\n.. code-block:: python\n\n import linked_properties\n # ... (Your own code)\n\n class SomeName(object): # ... (Your own code)\n @linked_properties.WatchableProperty\n def x(self) -> int:\n return self._x\n\n @x.setter\n def x(self, value: int) -> None:\n self._x = int(value)\n\n # ... (Your own code)\n\n # ... (Your own code)\n\n* 3rd option: Using them the ugly way.\n This is still better than the first one,\n and it's the only one to make PyCharm stop spawning warnings because of types all over the place.\n\n.. code-block:: python\n\n import linked_properties\n # ... (Your own code)\n\n class SomeName(object): # ... (Your own code)\n # ... (Your own code)\n\n def _get_x(self) -> int:\n return self._x\n\n def _set_x(self, value: int) -> None:\n self._x = value\n\n x = linked_properties.WatchableProperty(_get_x, _set_x)\n\n # ... (Your own code)\n\n # ... (Your own code)\n\n\nBut be aware of this: Two things is different.\n\nWhile ``@property_name.setter`` **returns a new instance** for a builtin property because they are **immutable**, a WatchableProperty **returns itself and changes accordingly** because it is **mutable**.\n\nJust try to avoid situations where you need mutable or immutable descriptors, because this behaviour can change in future versions. (I can't even think of a situation where this would help)\n\nAnd you **cannot** define a deleter, although that may change in the future as well.\n\n``LinkableProperty``\n--------------------\n\nAs the docstring states:\n\n::\n\n The main functionality[.] [...]\n\n\nYou cannot define any getter, setter or deleter. The init function takes a ``WatchableProperty``.\n\nThe definition is simple, and the usage is as well:\n\nIf you have two LinkedProperties, you can set one to be the other (``obj1.l_x = obj2.l_x``). This results in following behaviour:\n\nYou can't set the associated ``WatchableProperty`` of the receiving ``LinkableProperty`` anymore (at least not by ``obj1.x = ...``), and if the associated ``WatchableProperty`` of the sending ``LinkableProperty`` gets changed, the setter of the other ``WatchableProperty`` gets called.\n\nIf you want to unlink them, set the receiving ``LinkableProperty`` to ``None``. (``obj1.l_x = None``)\n\n**Be aware of this:** You should *only* use LinkedProperties if your property *makes sense to be able to get linked*. This excludes properties that count how often something was written to or read, and everything that *changes behaviour after writing the same value or reading twice*.\n\n``LinkableTransmission``\n------------------------\n\nThis is the object the getter of a ``LinkableProperty`` returns, to be able to connect with other LinkedProperties.\n\nYou don't have to care about this one, if you don't want to change how the library works.\nI put this in anyway, because this will be expanded in the next version; allowing you to interact with it like you would interact with the underlying value.\n(-> ``obj1.l_x = obj2.l_x * 2``)\n\nIf the ``ComplexLinkableProperty`` is implemented, using ``transmission.value`` may be important to let it be used by other libraries.\nUsing this technique is also important if you want to set the new value only once, and don't want those two properties to be linked.\n\n``ComplexLinkableProperty``\n---------------------------\n\n***This is not implemented yet.***\n\nThis LinkableProperty will be a ``LinkableProperty``, with a getter and setter that you define,\nand you can assign values to this properties, and not just transmissions.\nIf you want to be able to set the property to a transmission, you have to use the current way of dealing with LinkedProperties.\n\nThis returns a LinkableTransmission if you are receiving, with a ``transmission.value`` gathered by the getter. If you are trying to set the attribute, one of two things will happen:\n\n* If the value is a ``LinkableTransmission`` or a subclass: The property gets linked by the transmission.\n\n* If it isn't: Run the setter with the new value.\n\nThe setter will also run when the value of the linked property changes, or if they are linked.\n\nExample\n-------\n\nI personally can learn better from examples. So here is one:\n\n.. code-block:: python\n\n import linked_properties\n\n class Widget(object):\n def __init__(self, width: int, height: int) -> None:\n self._width = 0 # type: int\n self._height = 0 # type: int\n\n self.width = width\n self.height = height\n\n @linked_property.WatchableProperty\n def width(self) -> int:\n return self._width\n\n @width.setter\n def width(self, new_value: int) -> None:\n assert isinstance(new_value, int)\n self._width = new_value\n\n l_width = linked_properties.LinkableProperty(width)\n\n # ... (height; see width)\n\nOr after the ``ComplexLinkableProperty`` arrived:\n\n.. code-block:: python\n\n import linked_properties\n\n class Widget(object):\n def __init__(self, width: int, height: int) - None:\n self._width = 0 # type: int\n self._height = 0 # type: int\n\n self.width = width\n self.height = height\n\n @linked_property.ComplexLinkableProperty\n def width(self) -> int:\n return self._width\n\n @width.setter\n def width(self, new_value: int) -> None:\n assert isinstance(new_value, int)\n self._width = new_value\n\nContributing\n============\n\nIf you want to contribute, just email me: dodo2998@gmail.com", "description_content_type": null, "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/CNLambda/linked_properties/", "keywords": "linking properties", "license": "UNLICENSE", "maintainer": "", "maintainer_email": "", "name": "linked-properties", "package_url": "https://pypi.org/project/linked-properties/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/linked-properties/", "project_urls": { "Homepage": "https://github.com/CNLambda/linked_properties/" }, "release_url": "https://pypi.org/project/linked-properties/1.0.0b1/", "requires_dist": null, "requires_python": "", "summary": "This library allows you to link properties, so if one is changed the others change accordingly.", "version": "1.0.0b1" }, "last_serial": 2080939, "releases": { "1.0.0b1": [ { "comment_text": "", "digests": { "md5": "6dd9a9c5689492397697203457d9db49", "sha256": "66801798f58e64508c9544fa644cc6e090fcdc5df9bdc5a4199c9de0099c19c0" }, "downloads": -1, "filename": "linked_properties-1.0.0b1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "6dd9a9c5689492397697203457d9db49", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 11235, "upload_time": "2016-04-24T11:48:01", "url": "https://files.pythonhosted.org/packages/2d/66/825a314847aeb7e71b8d703234e697d83f41cabddb51ff92e78469660863/linked_properties-1.0.0b1-py2.py3-none-any.whl" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "6dd9a9c5689492397697203457d9db49", "sha256": "66801798f58e64508c9544fa644cc6e090fcdc5df9bdc5a4199c9de0099c19c0" }, "downloads": -1, "filename": "linked_properties-1.0.0b1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "6dd9a9c5689492397697203457d9db49", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 11235, "upload_time": "2016-04-24T11:48:01", "url": "https://files.pythonhosted.org/packages/2d/66/825a314847aeb7e71b8d703234e697d83f41cabddb51ff92e78469660863/linked_properties-1.0.0b1-py2.py3-none-any.whl" } ] }