{ "info": { "author": "Che-Liang Chiou", "author_email": "clchiou@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 1 - Planning", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python :: 3 :: Only", "Topic :: Software Development :: Libraries :: Python Modules" ], "description": "startup\n=======\n\nThe ``Startup`` class implements a function-call graph dependency\nresolver for decoupling complex program initialization sequence.\n\nTo use ``startup``, you annotate functions with which variables they\nread or write (remainder: you **must** annotate **all** non-optional\nparameters). Then ``startup`` generates a dependency graph from the\nannotations, and call them in a stable and predictable order. Each\nfunction will be called exactly once, and if a function has never been\ncalled (due to unsatisfiable dependency), ``startup`` will raise a\n``StartupError``.\n\nSample usage:\n\n.. code-block:: python\n\n from startup import startup\n\n # 'argv' is the variable name that parse_argv reads from, and\n # 'args' is the variable name that parse_argv writes to.\n # NOTE: All non-optional parameters must be annotated.\n @startup\n def parse_argv(argv: 'argv') -> 'args':\n args = {'config_path': argv[1]}\n return args\n\n @startup\n def read_config(args: 'args') -> 'config':\n with open(args['config_path']) as config_file:\n return config_file.read()\n\n def main(argv):\n # You may provide variable values to startup, like argv in this\n # case, and you may read variable, like config, which will be\n # returned by startup.call().\n config = startup.call(argv=argv)['config']\n\nYou **must** annotate **all** non-optional parameters with a variable\nname, but annotating return value is optional. A parameter annotation\ncan be annotated in the form ``['var']``, and this function will read\nall values written to ``'var'`` (see below). A return value annotation\ncan be a tuple of variable names, which means unpacking return value.\n\nThe variables in function annotations are not real but merely ``dict``\nkeys that ``startup`` stores internally (``startup.call()`` will return\nthis ``dict`` so that you too may read these variables).\n\nNOTE: Currently the annotation formats are very strict: A parameter\nannotation must be either a ``str`` or an one-element list of ``str``,\nand a return value annotation must be either a ``str`` or a tuple of\n``str``. The flexibility is reserved for future extensions.\n\nThe functions that are satisfied by the same set of dependencies are\ncalled in lexicographical order by their module name and qualified name.\nThis way, even if you change code layout and/or import order, the\nfunctions would still be called in the same order, and thus ``startup``\nis stable and predictable.\n\nA variable may be written multiple times (if multiple functions are\nannotated to write to it). In this case, ``startup`` will call the\nreader functions only after all writer functions are called. The\nreader functions may choose to read the latest value or all the values\nwritten to that variable (by ``['var']`` annotation form).\n\nThe fact that all readers are blocked by all writers can be used to\nexpress common patterns of program initialization, such as joining or\nsequencing function calls.\n\n\nWhy ``startup``?\n----------------\n\nStarting up a program could be complex but should not be complicated.\nFor example, ``main.py`` imports ``orm.py`` and ``orm.py`` imports\n``db.py``. Say you want to initialize them in the order of ``db.py``,\n``main.py``, and then ``orm.py``. Then ``main.py`` has to know that it\ntransitively imports ``db.py`` and should initialize ``db.py`` before\nitself. Things get even more complex when each module requires phases\nof initialization. We usually end up with ``main.py`` importing all\nother modules and manually order the initializations. I think this kind\nof problem can be better solved with topological sort on the dependency\ngraphs. Basically you annotate each module's dependencies and then\n``startup`` will resolve a stable and predictable function-call ordering\nfor you.", "description_content_type": "", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/clchiou/startup", "keywords": "", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "startup", "package_url": "https://pypi.org/project/startup/", "platform": "*", "project_url": "https://pypi.org/project/startup/", "project_urls": { "Homepage": "https://github.com/clchiou/startup" }, "release_url": "https://pypi.org/project/startup/0.4.0/", "requires_dist": null, "requires_python": "", "summary": "A dependency graph resolver for program startup", "version": "0.4.0" }, "last_serial": 4324056, "releases": { "0.2.0": [ { "comment_text": "", "digests": { "md5": "9bc2531069fe6c156bb97242beeebb28", "sha256": "8b1c6f8c5b4f65e3d588c39e4b2e56a65eb897dfc01d6bc2c65f616452a0db21" }, "downloads": -1, "filename": "startup-0.2.0.tar.gz", "has_sig": false, "md5_digest": "9bc2531069fe6c156bb97242beeebb28", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8895, "upload_time": "2015-03-09T06:02:50", "url": "https://files.pythonhosted.org/packages/fa/dd/82a81b0aa27de26ad31cdf729bd70353dfcec5458d0768dbeeb55355e217/startup-0.2.0.tar.gz" } ], "0.2.1": [ { "comment_text": "", "digests": { "md5": "5763b1954c45052a8ddf2396a12ef424", "sha256": "9f2ef96cb46a2aa5c3685670e8d9f810bb0aa083419efa97d2cab8211f55a0ce" }, "downloads": -1, "filename": "startup-0.2.1.tar.gz", "has_sig": false, "md5_digest": "5763b1954c45052a8ddf2396a12ef424", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9362, "upload_time": "2015-03-10T05:18:06", "url": "https://files.pythonhosted.org/packages/b7/67/7e88418710ef2c5370eafd6dc982b145e106608a91666027cefc83b5e9f2/startup-0.2.1.tar.gz" } ], "0.3.0": [ { "comment_text": "", "digests": { "md5": "2dc147c4a2d85cfbf546dcb73b6dd377", "sha256": "39c0f031c3e6b20c6c15d36b704c2047447c3eae9e9afed14d6970c6fc125e41" }, "downloads": -1, "filename": "startup-0.3.0.tar.gz", "has_sig": false, "md5_digest": "2dc147c4a2d85cfbf546dcb73b6dd377", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10625, "upload_time": "2015-08-15T06:49:52", "url": "https://files.pythonhosted.org/packages/64/b8/796138d30370d2bc957b94a6003efb19a63440d0f39d236815d033dd017d/startup-0.3.0.tar.gz" } ], "0.4.0": [ { "comment_text": "", "digests": { "md5": "7c125d59d3c390d50d632fb16783c172", "sha256": "4f99c0a68140b5e361a12593140e6d4a947775691fbdda5685682d30e4ab77f9" }, "downloads": -1, "filename": "startup-0.4.0.tar.gz", "has_sig": false, "md5_digest": "7c125d59d3c390d50d632fb16783c172", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11637, "upload_time": "2018-09-30T03:25:42", "url": "https://files.pythonhosted.org/packages/54/53/f3bc6b4d5cd7a23ca9232423b8994b121adca1c026316ac54b1f676efb27/startup-0.4.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "7c125d59d3c390d50d632fb16783c172", "sha256": "4f99c0a68140b5e361a12593140e6d4a947775691fbdda5685682d30e4ab77f9" }, "downloads": -1, "filename": "startup-0.4.0.tar.gz", "has_sig": false, "md5_digest": "7c125d59d3c390d50d632fb16783c172", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11637, "upload_time": "2018-09-30T03:25:42", "url": "https://files.pythonhosted.org/packages/54/53/f3bc6b4d5cd7a23ca9232423b8994b121adca1c026316ac54b1f676efb27/startup-0.4.0.tar.gz" } ] }