{ "info": { "author": "Csaba Palankai", "author_email": "csaba.palankai@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 3 - Alpha", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Natural Language :: English", "Operating System :: OS Independent", "Programming Language :: Python :: 3.6" ], "description": "==================================\nBaluster - Python Composition tool\n==================================\n\n.. image:: https://travis-ci.org/palankai/baluster.svg?branch=master\n :target: https://travis-ci.org/palankai/baluster\n\n| Project homepage: ``_\n| Issues: ``_\n|\n\nWhat is this package for\n------------------------\n\nThis package provides a simple way to build back structure of application.\nCan be used building composite root as acting a factory for resources,\nbuilding a fixture factory for tests.\n\nFeatures\n--------\n\n - Lazy initialisation\n - Simple composition and dependency handling\n\n\nExample - composie root\n-----------------------\n\n.. code:: python\n\n from baluster import Baluster, placeholders\n import psycopg2\n\n class ApplicationRoot(Baluster):\n @placeholders.factory\n def db(self, root):\n # Will be called at the first use\n # Will be cached so won't be called again\n return psycopg2.connect(\"dbname=test user=postgres\")\n\n @db.close\n def _close_db(self, root, db):\n db.close()\n\n @placeholders.factory\n def cr(self, root):\n return self.db.cursor()\n\n @cr.close\n def _close_cr(self, root, cr):\n cr.close()\n\n\n def main():\n approot = ApplicationRoot()\n with approot:\n approot.cr.execute('SELECT * FROM user')\n\n # at this point the connection and the cursor has already been closed\n\n\nExample - async composie root\n-----------------------------\n\n.. code:: python\n\n from baluster import Baluster, placeholders\n\n class AsyncApplicationRoot(Baluster):\n\n @placeholders.factory\n async def resource(self, root):\n # Will be called at the first use\n # Will be cached so won't be called again\n return await some_aync_resource()\n\n @db.close\n async def _close_resource(self, root, resource):\n await resource.close()\n\n\n def main():\n approot = AsyncApplicationRoot()\n async with approot:\n conn = await approot.resource\n await conn.operation(...)\n\n # at this point the resource has already been closed\n\n\nExample - fixture factory for tests\n-----------------------------------\n\n.. code:: python\n\n from baluster import Baluster, placeholders\n import psycopg2\n\n class Fixtures(Baluster):\n\n @placeholders.factory\n def cr(self, root):\n conn = psycopg2.connect(\"dbname=test user=postgres\")\n return conn.cursor()\n\n class users(Baluster):\n\n @placeholders.factory\n def user(self, root):\n root.cr.execute('SELECT * FROM user WHERE id=1')\n return User(root.cr.fetchone())\n\n @placeholders.factory\n def customer(self, root):\n root.cr.execute('SELECT * FROM customer WHERE id=1')\n return Customer(root.cr.fetchone())\n\n class orders(Baluster):\n\n @placeholders.factory\n def amount(self, root):\n return 100\n\n @placeholders.factory\n def quantity(self, root):\n return 1\n\n @placeholders.factory\n def order(self, root):\n customer = root.users.customer\n created_by = root.users.user\n amount = self.amount\n # Fictive order object...\n return Order(\n customer=customer, created_by=created_by,\n amount=amount, quantity=quantity\n )\n\n @placeholders.factory\n def shipped_order(self, root):\n order = self.order\n order.mark_shipped()\n return order\n\n\n def test_order():\n # Demonstrate a few use fictive usecase\n\n # Creating order with defaults\n f = Fixtures()\n assert f.order.calculated_total_value == 100\n assert f.order.shipping_address == f.users.customer.address\n\n # Create new fixtures, but keep some cached data\n f2 = f.copy('cr', 'users')\n\n # Set some value\n f2.order.amount = 50\n f2.order.quantity = 3\n assert f2.order.calculated_total_value == 150\n\n # Manage different stage of object life\n f3 = f.copy('cr', 'users')\n order = f3.shipped_order\n\n with pytest.raises(OrderException):\n order.cancel()\n # as it is shipped\n\n\nInstallation\n------------\n\nPython target: >=3.6\n\n.. code::\n\n $ pip install baluster\n\nDependencies\n------------\n\nThe package is independent, using only the python standard library.\n\n\nDevelopment\n-----------\n\n.. code::\n\n pip install -r requirements-dev.txt\n\nThis installs the package in development mode (`setup.py develop`)\nand the testing packages.\nI would like to achive nearly 100% test coverage.\n\nTest\n~~~~\n.. code::\n\n pytest\n\n\nContribution\n------------\n\nI really welcome any comments!\nI would be happy if you fork my code and create pull requests.\nFor an approved pull request flake8 have to pass just as all of tests.", "description_content_type": null, "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://gitlab.com/palankai/baluster", "keywords": "context,context manager,async", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "Baluster", "package_url": "https://pypi.org/project/Baluster/", "platform": "", "project_url": "https://pypi.org/project/Baluster/", "project_urls": { "Homepage": "https://gitlab.com/palankai/baluster" }, "release_url": "https://pypi.org/project/Baluster/0.2.1/", "requires_dist": null, "requires_python": ">=3.6", "summary": "Provides hierarchical factory", "version": "0.2.1" }, "last_serial": 3370189, "releases": { "0.1": [ { "comment_text": "", "digests": { "md5": "effdb00c0764b9d826a6abd5a1a72e3c", "sha256": "8bb81d4c503023dfb2e9cfa9f230a0cd61854d4488004e0205210d01431298e1" }, "downloads": -1, "filename": "Baluster-0.1.tar.gz", "has_sig": false, "md5_digest": "effdb00c0764b9d826a6abd5a1a72e3c", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 5279, "upload_time": "2017-05-22T21:21:11", "url": "https://files.pythonhosted.org/packages/bc/fa/7be8565a13457fcb62ba0e24f8f3fa3e5b959e6b506d75571c9a239b5d41/Baluster-0.1.tar.gz" } ], "0.2": [ { "comment_text": "", "digests": { "md5": "6f46b016745c13e7d85398f17d5b1188", "sha256": "64aef13ed91118934752792659d3f33746e63f6f77d7e1d03bba9b2ddfae9920" }, "downloads": -1, "filename": "Baluster-0.2.tar.gz", "has_sig": false, "md5_digest": "6f46b016745c13e7d85398f17d5b1188", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 8793, "upload_time": "2017-05-28T09:47:05", "url": "https://files.pythonhosted.org/packages/57/c7/b7864494fae91a23808a16cf112ea9c0e6b4b1d1c4d748e3bdc58b7fccb0/Baluster-0.2.tar.gz" } ], "0.2.1": [ { "comment_text": "", "digests": { "md5": "55ab55d6661917446e84a38295ab4366", "sha256": "5bbfee5bf113eb1c7285c4445bc9bf5de9b2e7e0595975423b062f6301971edd" }, "downloads": -1, "filename": "Baluster-0.2.1.tar.gz", "has_sig": false, "md5_digest": "55ab55d6661917446e84a38295ab4366", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 8937, "upload_time": "2017-11-28T06:45:26", "url": "https://files.pythonhosted.org/packages/89/7f/f25028e9b2ab6a830222562c826a19ac4906ddab82a2246b4b0e3f799632/Baluster-0.2.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "55ab55d6661917446e84a38295ab4366", "sha256": "5bbfee5bf113eb1c7285c4445bc9bf5de9b2e7e0595975423b062f6301971edd" }, "downloads": -1, "filename": "Baluster-0.2.1.tar.gz", "has_sig": false, "md5_digest": "55ab55d6661917446e84a38295ab4366", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 8937, "upload_time": "2017-11-28T06:45:26", "url": "https://files.pythonhosted.org/packages/89/7f/f25028e9b2ab6a830222562c826a19ac4906ddab82a2246b4b0e3f799632/Baluster-0.2.1.tar.gz" } ] }