{ "info": { "author": "Bogdan Mustiata", "author_email": "bogdan.mustiata@gmail.com", "bugtrack_url": null, "classifiers": [], "description": "MoPyX\n=====\n\nMoPyX is a MobX/Vue inspired reactive model driven UI library. UI\nToolkit independent.\n\nReactive UI is a concept of having the UI automatically update as a\nreaction to changes being done in the backend model. This happens\nwithout manually registering listeners, and the reactive framework\nkeeping track of what parts of the model affect what parts of the\napplication..\n\nDemo\n----\n\n.. figure:: https://raw.githubusercontent.com/germaniumhq/mopyx-sample/master/demo.gif\n :alt: PySide2 MoPyX Demo\n\n PySide2 MoPyX Demo\n\nFull demo project source is here:\nhttps://github.com/germaniumhq/mopyx-sample\n\n@model\n------\n\nYou decorate your model classes with ``@model``. All the properties of\nthat class will be monitored for changes. Whenever one of those\nproperties will change, the affected renderers (only the renderer\nfunctions that used that property) will be re-invoked on model changes.\n\n.. code:: py\n\n @model\n class FormModel:\n def __init__(self):\n self.first_name = \"John\"\n self.last_name \"Doe\"\n\n@render\n-------\n\nYou decorate your UI rendering functions with ``@render``, or invoke\nthem with ``render_call``. MoPyX will map what render method used what\nproperties in the model. The parameters for the function will be also\nrecorded and sent to the renderer function.\n\n.. code:: py\n\n class UiForm:\n def __init__(self):\n # ...\n self.render_things()\n\n @render\n def render_things(self):\n self.first_name_label.set_text(self.model.first_name)\n self.last_name_label.set_text(self.model.last_name)\n\nWhenever either ``first_name`` or ``last_name`` change in our model,\n``render_things`` will be invoked again.\n\nIn order to optimize the number of UI updates, only the relevant\n``@render`` functions will be called, not always the topmost one.\n\nSo you could break down the previous ``@render`` method into two\nmethods:\n\n.. code:: py\n\n @render\n def render_things(self):\n self.render_first_name()\n self.render_last_name()\n\n @render\n def render_first_name(self):\n self.first_name_label.set_text(self.model.first_name)\n\n @render\n def render_last_name(self):\n self.last_name_label.set_text(self.model.last_name)\n\nNow if only the ``first_name`` changes in the model, the set\\_text for\nthe ``last_name`` will not be invoked. This happens automatically, and\nonly the needed renderers will be invoked.\n\nTo type less, ``render_call()`` will just wrap the given callable into a\n``@render``. For example we can rewrite our renderer to be shorter:\n\n.. code:: py\n\n @render\n def render_things(self):\n render_call(lambda: self.first_name_label.set_text(self.model.first_name))\n render_call(lambda: self.last_name_label.set_text(self.model.last_name))\n\n``@render`` methods are not allowed to do model changes while running.\nIf setting an UI value will trigger a model change, read the\n``ignore_updates`` section.\n\n@action\n-------\n\nIf they're not wrapped in an action, every property is also an action,\nso after the property change, a rendering will trigger. To improve\nperformance you can wrap multiple model updates into a single\n``@action``. An action method can call other methods, including other\n``@action``\\ s.\n\nWhen when the top most ``@action`` finishes the rendering will be\ninvoked. MoPyX will find out what renderers need to be called, and what\ncomputed properties should be updated, in order to get the UI into a\nconsistent state.\n\nInternally all the properties setters in the ``@model`` classes are\nwrapped in ``@action``\\ s.\n\n.. code:: py\n\n @action # withonut this would trigger a render after each assignment\n def change_model(self):\n self.first_name = \"Jane\"\n self.last_name = \"Mary\"\n\n@computed\n---------\n\nYou can also create properties on the model using the ``@computed``\ndecorator. This works similarly with a regular python ``@property`` but\nit will be invoked only when one of the other properties it depends on\n(including from other MoPyX models) change. Otherwise calling this\nproperty will return the previously computed value.\n\nThis is great for difficult to compute properties. Have a list that must\nbe accessed as sorted, but comes from the data store as unsorted? You\ncan wrap it in a ``@computed`` method. Again, note that the\n``@computed`` method will only be invoked when the used properties by\nthat ``@computed`` method will change:\n\n.. code:: py\n\n @model\n class RootModel:\n def __init__(self):\n self.backend_data = []\n\n @action\n def fetch_data(self):\n self.backend_data = fetch_data_from_service()\n\n @computed\n def first_five_items(self):\n # will only be invoked when self.backend_data changes\n result = list(self.backend_data)\n\n result.sort()\n result = result[0:5]\n\n return result\n\n class UiRenderer:\n # ...\n @render\n def render_items(self):\n # will be invoked only when first_five_items changes\n for item in self.root_model.first_five_items:\n self.render_item(item)\n\n``@computed`` properties are not allowed to change the state of the\nobject.\n\nList\n----\n\nIf one of the properties is a list, the list will be replaced with a\nspecial implementation, that will also notify its changes on the top\nproperty.\n\n.. code:: py\n\n @model\n class RootModel:\n def __init__(self):\n self.items = []\n\n\n class UiComponent:\n @render\n def update_ui(self):\n for item in self.items:\n self.render_sub_component(item)\n\n\n model = RootModel()\n ui = UiComponent(model)\n\n\n model.items.append(\"new item\") # this will trigger the update_ui rerender.\n\nignore\\_updates\n---------------\n\nIf the renderer will call a value that sets something in the UI that\nwill make the UI trigger an event, that will in turn might land in an\naction (model updates are also actions), you can disable the rendering\nusing the ``ignore_updates`` attribute. This will suppress *all action\ninvocations* from that rendering method, including *all model updates*.\n\nThis is great for onchange events for input edits, or tree updates such\nas selected nodes that otherwise would enter an infinite recursion.\n\nDebugging\n---------\n\nTo check what goes on, you can export in your environment:\n\n- ``MOPYX_DEBUG`` - this will print the rendering process on the\n console.\n- ``MOPYX_THREAD_CHECK`` - this will throw an exception if the thread\n for ``@render`` methods change.\n", "description_content_type": "", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "", "keywords": "", "license": "BSD", "maintainer": "", "maintainer_email": "", "name": "mopyx", "package_url": "https://pypi.org/project/mopyx/", "platform": "", "project_url": "https://pypi.org/project/mopyx/", "project_urls": null, "release_url": "https://pypi.org/project/mopyx/1.1.1/", "requires_dist": null, "requires_python": "", "summary": "mopyx", "version": "1.1.1" }, "last_serial": 4503956, "releases": { "0.0.1": [ { "comment_text": "", "digests": { "md5": "4ba896674d6f556c126ca74004a62006", "sha256": "adeef4a2e5562d33d29966b46d0dd01257135ede7a7b50fcf4ba188f3307c03f" }, "downloads": -1, "filename": "mopyx-0.0.1.tar.gz", "has_sig": false, "md5_digest": "4ba896674d6f556c126ca74004a62006", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 2675, "upload_time": "2018-10-31T05:52:04", "url": "https://files.pythonhosted.org/packages/a9/d3/b5d2bd9c41796f5d9e29deed4b2cf110a52c6aab702b53bbc896511f6171/mopyx-0.0.1.tar.gz" } ], "0.0.2": [ { "comment_text": "", "digests": { "md5": "5fc510c1735ba7a4c7571431ea859216", "sha256": "93c039137aedf532a3107413653d86927f6678b3227bb870e683d2dfade60501" }, "downloads": -1, "filename": "mopyx-0.0.2.tar.gz", "has_sig": false, "md5_digest": "5fc510c1735ba7a4c7571431ea859216", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4488, "upload_time": "2018-11-01T06:42:33", "url": "https://files.pythonhosted.org/packages/cf/29/080077e9baf0d5a4c66abed105b7486cf235088922795449b6cc74a4c356/mopyx-0.0.2.tar.gz" } ], "0.1.0": [ { "comment_text": "", "digests": { "md5": "3a3fab9f601cf14fd03bdc6078b73def", "sha256": "6b7ea0afce9faae3518e35dc05301d15cebfe8249c143f177cc8d4dfdd048d02" }, "downloads": -1, "filename": "mopyx-0.1.0.tar.gz", "has_sig": false, "md5_digest": "3a3fab9f601cf14fd03bdc6078b73def", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4995, "upload_time": "2018-11-01T09:58:07", "url": "https://files.pythonhosted.org/packages/6c/d8/d4569ff98b3255389e26597b421c55b20eb099b5572d0058b3fe5843f450/mopyx-0.1.0.tar.gz" } ], "0.1.1": [ { "comment_text": "", "digests": { "md5": "39a5df59009caf891829ba7630c3762a", "sha256": "8430b58f2738912fd48b9f1ceb749b3e3c61fbb295e78d78b022bc3ce277134f" }, "downloads": -1, "filename": "mopyx-0.1.1.tar.gz", "has_sig": false, "md5_digest": "39a5df59009caf891829ba7630c3762a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5008, "upload_time": "2018-11-01T11:34:12", "url": "https://files.pythonhosted.org/packages/e1/51/ec0a221ac04cfcf7e8437d19cb1ab439148f4397d67b1c77e5839efecce4/mopyx-0.1.1.tar.gz" } ], "0.2.0": [ { "comment_text": "", "digests": { "md5": "f1aa83de719b50cb85f4b0c17c0525d5", "sha256": "fbe474b5bd7651d9ba012f9e0257817793eabae17c11064cb0230d6e47dd3711" }, "downloads": -1, "filename": "mopyx-0.2.0.tar.gz", "has_sig": false, "md5_digest": "f1aa83de719b50cb85f4b0c17c0525d5", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5665, "upload_time": "2018-11-01T21:14:05", "url": "https://files.pythonhosted.org/packages/47/b9/b1b522ebe4147666d87e233074123569e813e8431a89ba724a0db76d1b4d/mopyx-0.2.0.tar.gz" } ], "0.2.1": [ { "comment_text": "", "digests": { "md5": "0cbd726f6f43254079578a69e9b71eb9", "sha256": "d15e3103f5ed125888e8b892a96fb75cb04b371bc80a5951696e9d1aed59db61" }, "downloads": -1, "filename": "mopyx-0.2.1.tar.gz", "has_sig": false, "md5_digest": "0cbd726f6f43254079578a69e9b71eb9", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5992, "upload_time": "2018-11-01T21:48:44", "url": "https://files.pythonhosted.org/packages/0c/15/39528f0a7a33b6c443b4dc72d9f3d1242bd55e8fa398c58fd2a9677ac9cd/mopyx-0.2.1.tar.gz" } ], "0.3.0": [ { "comment_text": "", "digests": { "md5": "4caed0d892bc609ff0ad206a98c254a9", "sha256": "5a2840aa9cbe43c968883c675a402aad2fa082a2e49fd3c313b9a7e92ccde00d" }, "downloads": -1, "filename": "mopyx-0.3.0.tar.gz", "has_sig": false, "md5_digest": "4caed0d892bc609ff0ad206a98c254a9", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6181, "upload_time": "2018-11-02T03:36:21", "url": "https://files.pythonhosted.org/packages/1d/29/9789f6df47dfaf693e8bd3dd58cb98fc7b4ac3a23f87c058fd7b62216158/mopyx-0.3.0.tar.gz" } ], "0.4.0": [ { "comment_text": "", "digests": { "md5": "b6b774fe8b5c8ad4bc77f3b083cb78fe", "sha256": "1cb342e32c53a05094b8e315c94b3edefc036912dcbb208164a551638fc55626" }, "downloads": -1, "filename": "mopyx-0.4.0.tar.gz", "has_sig": false, "md5_digest": "b6b774fe8b5c8ad4bc77f3b083cb78fe", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6353, "upload_time": "2018-11-02T07:39:14", "url": "https://files.pythonhosted.org/packages/6b/43/a69dfdccc74b1e1d26f9f248c8a6831eb80874c7887a4ebe3ba1fecc7ce4/mopyx-0.4.0.tar.gz" } ], "0.4.1": [ { "comment_text": "", "digests": { "md5": "f81c9f04399c8ed5ba955501ad815982", "sha256": "af6737ec94133ec567d0fb668954e74da6fac8a3ba231fbbf72caf0dc09c1dd0" }, "downloads": -1, "filename": "mopyx-0.4.1.tar.gz", "has_sig": false, "md5_digest": "f81c9f04399c8ed5ba955501ad815982", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6350, "upload_time": "2018-11-02T07:48:02", "url": "https://files.pythonhosted.org/packages/c2/ef/337010f35c38db65f47c3b84156fe473158a1de793d456be952add009cac/mopyx-0.4.1.tar.gz" } ], "0.4.2": [ { "comment_text": "", "digests": { "md5": "41cbd4c3418487d807000a7bef2e3fc7", "sha256": "e82b21599aafbee224b59eebeeba533f14af6250cfcddfd60f76c09dae650b43" }, "downloads": -1, "filename": "mopyx-0.4.2.tar.gz", "has_sig": false, "md5_digest": "41cbd4c3418487d807000a7bef2e3fc7", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6492, "upload_time": "2018-11-06T05:38:03", "url": "https://files.pythonhosted.org/packages/91/19/84e334d2133fc5e87875cd3d6a217274269bdc5b7d74d01efdeed0b99682/mopyx-0.4.2.tar.gz" } ], "0.4.3": [ { "comment_text": "", "digests": { "md5": "ac80cf5c0906a79944efde5fcd5d69bb", "sha256": "191721fb3f73c82537dd99b2e0a6e6a5e70db35288039bbf412a88f3c8cfada6" }, "downloads": -1, "filename": "mopyx-0.4.3.tar.gz", "has_sig": false, "md5_digest": "ac80cf5c0906a79944efde5fcd5d69bb", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6990, "upload_time": "2018-11-06T08:34:34", "url": "https://files.pythonhosted.org/packages/47/77/7ca7f036fd1206009e1045cc6fc8b961637e34da61a04453386f0403fad5/mopyx-0.4.3.tar.gz" } ], "0.4.4": [ { "comment_text": "", "digests": { "md5": "b440ed7ccd1b4d98e930fe555e7c414d", "sha256": "7e0e2fddbc21e904ec2774236d49a74aa64f43b9403ea66d5e1be43a287b4a0f" }, "downloads": -1, "filename": "mopyx-0.4.4.tar.gz", "has_sig": false, "md5_digest": "b440ed7ccd1b4d98e930fe555e7c414d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7372, "upload_time": "2018-11-07T04:12:37", "url": "https://files.pythonhosted.org/packages/be/ea/1f6ad84931b3caeef4937f1d7aacb99860d76ae0659b5a28dd32a0d09e46/mopyx-0.4.4.tar.gz" } ], "0.5.0": [ { "comment_text": "", "digests": { "md5": "81b8ce3b0860d0c1d4e2fefd34ad7dff", "sha256": "76a7abeeb999fb3e99fcab960434db66c530747cfa6053086a80cffa97c159cb" }, "downloads": -1, "filename": "mopyx-0.5.0.tar.gz", "has_sig": false, "md5_digest": "81b8ce3b0860d0c1d4e2fefd34ad7dff", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9132, "upload_time": "2018-11-09T04:18:32", "url": "https://files.pythonhosted.org/packages/ee/9c/dc444177544e0293b224e544df52e57dafa0f5169b5f45c2a21dc9df0966/mopyx-0.5.0.tar.gz" } ], "0.5.1": [ { "comment_text": "", "digests": { "md5": "170e69ecd2391a3eee8da78a2e15a88e", "sha256": "4e6a90dba88d7c7c0aadb7bb71e9012c09c1c081ac366dc8f1e5c569a7e05b72" }, "downloads": -1, "filename": "mopyx-0.5.1.tar.gz", "has_sig": false, "md5_digest": "170e69ecd2391a3eee8da78a2e15a88e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9649, "upload_time": "2018-11-10T10:02:00", "url": "https://files.pythonhosted.org/packages/46/8d/e4a63e9af9811f7ecd5b6acb8c61cf481cbcea7a0120cad576ffcd11f16f/mopyx-0.5.1.tar.gz" } ], "0.5.3": [ { "comment_text": "", "digests": { "md5": "457f7e60042a2b7924cac176d292f8be", "sha256": "e3b5e4870345789e9ac06f84e583d072583ba5e24fe822682eb08110f73bee95" }, "downloads": -1, "filename": "mopyx-0.5.3.tar.gz", "has_sig": false, "md5_digest": "457f7e60042a2b7924cac176d292f8be", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10214, "upload_time": "2018-11-13T04:49:26", "url": "https://files.pythonhosted.org/packages/ea/a7/92b928a073f1d0148e9e1335beb1364a3d9baffcd0dad907ea216fa430a5/mopyx-0.5.3.tar.gz" } ], "0.5.4": [ { "comment_text": "", "digests": { "md5": "8be01e3798e73d65255af71b8b58ace1", "sha256": "6e251408428c8dc75a1a91d47a58084befb2f105f52c522addfc3a649c3abcb5" }, "downloads": -1, "filename": "mopyx-0.5.4.tar.gz", "has_sig": false, "md5_digest": "8be01e3798e73d65255af71b8b58ace1", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10679, "upload_time": "2018-11-17T05:34:38", "url": "https://files.pythonhosted.org/packages/b7/f9/21895c1c399bb9cb5419ad235d626d75890dda5194758eb2242bf361b913/mopyx-0.5.4.tar.gz" } ], "1.0.0": [ { "comment_text": "", "digests": { "md5": "0dd3f83ef5805974d6690a9e04357e56", "sha256": "c52c9c1cea01ffd422cc82d9fb2ff0c8e1893b62cd4d2d7ff84a601c385a3cd1" }, "downloads": -1, "filename": "mopyx-1.0.0.tar.gz", "has_sig": false, "md5_digest": "0dd3f83ef5805974d6690a9e04357e56", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10908, "upload_time": "2018-11-17T06:13:57", "url": "https://files.pythonhosted.org/packages/f6/60/8f6e21873ea81a8018081bcce58d25d7a99ea62a32d2f19e527fcd11f350/mopyx-1.0.0.tar.gz" } ], "1.0.1": [ { "comment_text": "", "digests": { "md5": "5082795fb2e41b966df36d4dd6535e7e", "sha256": "fd1d1762d6f3ac3b0f8b828714b20088e2b63758b12d03c38aedce6fddca0cb9" }, "downloads": -1, "filename": "mopyx-1.0.1.tar.gz", "has_sig": false, "md5_digest": "5082795fb2e41b966df36d4dd6535e7e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13310, "upload_time": "2018-11-19T04:32:26", "url": "https://files.pythonhosted.org/packages/69/dc/5276b06feb205fbaadf5e9906547b549c1c9444d5641f31f670bafd27627/mopyx-1.0.1.tar.gz" } ], "1.1.0": [ { "comment_text": "", "digests": { "md5": "c5c082b5776934550b332f4ac57b99c8", "sha256": "ffb86a6a63402a15dc480efd8617cc82b87ccebb2a9f52d0950d01bacb7ed47e" }, "downloads": -1, "filename": "mopyx-1.1.0.tar.gz", "has_sig": false, "md5_digest": "c5c082b5776934550b332f4ac57b99c8", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13346, "upload_time": "2018-11-19T04:47:59", "url": "https://files.pythonhosted.org/packages/4b/50/01283566e56819165dcde3fd6d75c49893bf54dfe2775d645dc6f465a216/mopyx-1.1.0.tar.gz" } ], "1.1.1": [ { "comment_text": "", "digests": { "md5": "e6f55c9c32a13b3cc0670986b0fd6842", "sha256": "6d04a685eae7340761ae8d12e1a1fdcf361469408be175615459c216c59e762c" }, "downloads": -1, "filename": "mopyx-1.1.1.tar.gz", "has_sig": false, "md5_digest": "e6f55c9c32a13b3cc0670986b0fd6842", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13757, "upload_time": "2018-11-19T18:25:16", "url": "https://files.pythonhosted.org/packages/d0/d4/3e986d1958191183dec2bbedea9385892a4777af0fb4ac3002dd138e9843/mopyx-1.1.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "e6f55c9c32a13b3cc0670986b0fd6842", "sha256": "6d04a685eae7340761ae8d12e1a1fdcf361469408be175615459c216c59e762c" }, "downloads": -1, "filename": "mopyx-1.1.1.tar.gz", "has_sig": false, "md5_digest": "e6f55c9c32a13b3cc0670986b0fd6842", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13757, "upload_time": "2018-11-19T18:25:16", "url": "https://files.pythonhosted.org/packages/d0/d4/3e986d1958191183dec2bbedea9385892a4777af0fb4ac3002dd138e9843/mopyx-1.1.1.tar.gz" } ] }