{ "info": { "author": "Theron Luhn", "author_email": "theron@luhn.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Framework :: Pyramid", "License :: OSI Approved :: MIT License", "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": "# pyramid-resource\n\nPyramid's URL traversal is a powerful tool and personally one of my favorite\nfeatures of the framework. Unfortunately, Pyramid doesn't provide any\nframework or utilities for implementing resource trees. This project aims to\nreduce the boilerplate necessary for creating feature-full resource trees.\n\n## Basic usage\n\nFirst, of course, you need to add `pyramid-resource` to your project using your\npackage manager of choice. e.g.: `pip install pyramid-resource`\n\nMake sure you're familiar with Pyramid's\n[URL traversal](https://docs.pylonsproject.org/projects/pyramid/en/latest/narr/traversal.html).\n\nYou can create a new resource by subclassing `pyramid_resource.Resource`. For\nexample, here's a simple application that has a resource tree with only a root\nresource.\n\n```python\nfrom wsgiref.simple_server import make_server\nfrom pyramid.config import Configurator\nfrom pyramid.response import Response\nfrom pyramid_resource import Resource\n\n\nclass Root(Resource):\n pass\n\n\ndef hello_world(request):\n return Response('Hello!\\n')\n\n\nif __name__ == '__main__':\n with Configurator() as config:\n config.set_root_factory(Root)\n config.add_view(hello_world, context=Root)\n app = config.make_wsgi_app()\n server = make_server('0.0.0.0', 8080, app)\n server.serve_forever()\n```\n\nYou can define child resources by setting the `__children__` property to a\ndictionary. The key corresponds the URL segment and the value should be a\nresource subclass. pyramid-resource will automatically make the resources\nlocation-aware.\n\n```python\nclass Child(Resource):\n pass\n\n\nclass Root(Resource):\n __children__ = {\n 'child': Child,\n }\n```\n\nYou can see the full example\n[here](https://github.com/luhn/pyramid-resource/blob/master/examples/02_children.py).\n\n### Name Resolution\n\nFor convenience, you can reference children with dotted Python names. This is\nmost useful for referencing child resources that may be defined further down\nthe document. If you use this functionality, **you must run\n`Configurator.scan()` to trigger the resolution.**\n\n```python\nclass Root(Resource):\n __children__ = {\n 'child': '.Child',\n }\n\n\nclass Child(Resource):\n pass\n```\n\n## Dynamic resource trees\n\nOne of the more interesting features of URL traversal is that trees can be\ncreated on the fly. This allows for dynamic resource trees that can mirror the\napplication state, such as objects in a database.\n\nDynamic resource trees can be created by implementing a `get_child` method on\na resource class. This method should accept a single argument of a URL\nsegment and will be called if no child is found in the `__children__` property.\nIf the URL segment corresponds to a valid child resource, `get_child` should\nreturn a resource class and the child resource will be instanciated from that.\nIf no corresponding child is found, `None` should be returned or `KeyError`\nraised, and traversal will be halted.\n\n```python\nclass Root(Resource):\n def get_child(self, key):\n if exists_in_db(key):\n return Child\n else:\n return None\n\n\nclass Child(Resource):\n pass\n```\n\nOf course, this isn't particularly useful if you can't attach information to\nthe child resource. `get_child` can also return a two-tuple of a resource\nclass and a dictionary of attributes that will be attached to the resulting\nchild.\n\n```python\nclass Root(Resource):\n def get_child(self, key):\n if exists_in_db(key):\n return Child, {'id': key}\n\n\nclass Child(Resource):\n pass\n```\n\nThe object ID will now be accessible via `context.id` in views on the child\nresource. **Resources will proxy the attributes of their parent**, so\n`context.id` will also be accessible in views further down the tree.\n\nIf you need to access the current request in your `get_child` implementations,\nit's available via `self.request`.\n\n## An example\n\nHere's an example that demonstrates how a real application might utilize\npyramid-resource.\n\n```python\nfrom wsgiref.simple_server import make_server\nfrom pyramid.decorator import reify\nfrom pyramid.config import Configurator\nfrom pyramid.view import view_config\nfrom pyramid_resource import Resource\n\n\nclass Root(Resource):\n __children__ = {\n 'widget': '.WidgetContainer',\n }\n\n\nclass WidgetContainer(Resource):\n \"\"\"\n A resource containing the Widget resources.\n\n \"\"\"\n def get_child(self, key):\n \"\"\"\n Return a child resource if the widget exists in the database.\n\n \"\"\"\n try:\n id = int(key)\n except ValueError:\n raise KeyError\n\n if self.request.widget_db.exists(id):\n return Widget, {'widget_id': id}\n\n\nclass Widget(Resource):\n \"\"\"\n A resource representing a widget in the mock database.\n\n \"\"\"\n @reify\n def widget(self):\n \"\"\"\n Lookup the widget from the database.\n\n \"\"\"\n return self.request.widget_db.find(self.widget_id)\n\n\n@view_config(context=WidgetContainer, renderer='string')\ndef list_widgets(context, request):\n \"\"\"\n GET /widget/\n\n List the URLs of all widgets.\n\n \"\"\"\n urls = []\n for widget_id in request.widget_db:\n urls.append(request.resource_path(context[widget_id]))\n return '\\n'.join(urls) + '\\n'\n\n\n@view_config(context=Widget, renderer='string')\ndef get_widget(context, request):\n \"\"\"\n GET /widget/{id}/\n\n Greet the current widget.\n\n \"\"\"\n return 'Hello {}!\\n'.format(context.widget)\n\n\nclass MockDatabase:\n \"\"\"\n An imitation of a widget database.\n\n \"\"\"\n DATA = {\n 1: 'Widget 1',\n 2: 'Widget 2',\n }\n\n def exists(self, id):\n return id in self.DATA\n\n def find(self, id):\n return self.DATA[id]\n\n def __iter__(self):\n return iter(self.DATA.keys())\n\n\nif __name__ == '__main__':\n with Configurator() as config:\n config.set_root_factory(Root)\n config.add_request_method(\n lambda _: MockDatabase(),\n 'widget_db',\n property=True,\n )\n config.scan()\n app = config.make_wsgi_app()\n server = make_server('0.0.0.0', 8080, app)\n server.serve_forever()\n```\n\nThe resulting application will behave like this:\n\n```\n>>> curl localhost:8080/widget/\n> /widget/1/\n> /widget/2/\n\n>>> curl localhost:8080/widget/1/\n> Hello Widget 1!\n\n>>> curl localhost:8080/widget/2/\n> Hello Widget 2!\n```\n\n## Hacking\n\nDeveloping against pyramid-resource is simple, thanks to Poetry:\n\n* [Install Poetry](https://poetry.eustace.io/docs/#installation) if you haven't\n done so already\n* Clone the repository\n* Run `poetry install`\n* Run the test suite with `make test`\n\n## Prior art\n\nThe\n[pyramid_traversalwrapper](https://github.com/Pylons/pyramid_traversalwrapper)\nproject proxies a location-ignorant resource tree to make it location-aware.\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/luhn/pyramid-resource", "keywords": "", "license": "MIT", "maintainer": "Theron Luhn", "maintainer_email": "theron@luhn.com", "name": "pyramid-resource", "package_url": "https://pypi.org/project/pyramid-resource/", "platform": "", "project_url": "https://pypi.org/project/pyramid-resource/", "project_urls": { "Homepage": "https://github.com/luhn/pyramid-resource", "Repository": "https://github.com/luhn/pyramid-resource" }, "release_url": "https://pypi.org/project/pyramid-resource/0.3.0/", "requires_dist": [ "pyramid (>=1.7,<2.0)" ], "requires_python": ">=3.4,<4.0", "summary": "A simple base resource class for Pyramid traversal.", "version": "0.3.0" }, "last_serial": 5732369, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "1ac8cc9ea677e14d195e670c1fb191a3", "sha256": "1171146c07384e69533671e8a5cca03736751bb1be2e493b23b2de18c76ede8a" }, "downloads": -1, "filename": "pyramid_resource-0.1.0-py3-none-any.whl", "has_sig": false, "md5_digest": "1ac8cc9ea677e14d195e670c1fb191a3", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.4,<4.0", "size": 4325, "upload_time": "2018-12-14T21:40:15", "url": "https://files.pythonhosted.org/packages/9f/60/b4a94ebb1a7ca7b3906c5f70fdc5015f2548debf19f81365fe108b1ee81e/pyramid_resource-0.1.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "3d52c3d9c86652fa7590bc182c6db813", "sha256": "44c8f534f6c28bc6537a2e22ba99f20fc2015fdb01ef6016aac71a36388c56e9" }, "downloads": -1, "filename": "pyramid-resource-0.1.0.tar.gz", "has_sig": false, "md5_digest": "3d52c3d9c86652fa7590bc182c6db813", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.4,<4.0", "size": 2418, "upload_time": "2018-12-14T21:40:13", "url": "https://files.pythonhosted.org/packages/04/0e/ea02da971d76471c39400677be8b2b190ecbe7d4821e21736aa9699d1ac4/pyramid-resource-0.1.0.tar.gz" } ], "0.2.0": [ { "comment_text": "", "digests": { "md5": "249d30a1b584c93048422fd47c9c9209", "sha256": "03f52e578fa58c8ffd4f08478e262ad3ba0574937c60ddbe7f654d160ee32ad2" }, "downloads": -1, "filename": "pyramid_resource-0.2.0-py3-none-any.whl", "has_sig": false, "md5_digest": "249d30a1b584c93048422fd47c9c9209", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.4,<4.0", "size": 6224, "upload_time": "2018-12-14T23:52:14", "url": "https://files.pythonhosted.org/packages/6a/0c/9288979d351ba668cf6714e824a6693501a9208ed450f9ead8446336a461/pyramid_resource-0.2.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "649b444ab143a1ae1cea5196f5f08eda", "sha256": "74d2f37931db6198be736d7e68aae76909f135d0bf4121c092e959703b9b3915" }, "downloads": -1, "filename": "pyramid-resource-0.2.0.tar.gz", "has_sig": false, "md5_digest": "649b444ab143a1ae1cea5196f5f08eda", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.4,<4.0", "size": 5262, "upload_time": "2018-12-14T23:52:13", "url": "https://files.pythonhosted.org/packages/0f/86/fdf88580f7c2913e96742f15a540f8fb6c4bbcdd12bb7901c2b1a9fe896d/pyramid-resource-0.2.0.tar.gz" } ], "0.3.0": [ { "comment_text": "", "digests": { "md5": "e8d4180256b21eb0dc18ee161787d1dc", "sha256": "8df5c91a26d18ec311e30033918ac0f813d388744edd4d92675d5dc362034720" }, "downloads": -1, "filename": "pyramid_resource-0.3.0-py3-none-any.whl", "has_sig": false, "md5_digest": "e8d4180256b21eb0dc18ee161787d1dc", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.4,<4.0", "size": 5356, "upload_time": "2019-08-26T18:19:30", "url": "https://files.pythonhosted.org/packages/38/21/0b804bfa820446d2c010a32e31a6006af8e7492e281d82a3758c451c9382/pyramid_resource-0.3.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "9233b745a1447f121038265dacf375c7", "sha256": "ce44e32922f3c832185b4e67a24cf381610baf40cbe5336bd4d522812bf1a557" }, "downloads": -1, "filename": "pyramid-resource-0.3.0.tar.gz", "has_sig": false, "md5_digest": "9233b745a1447f121038265dacf375c7", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.4,<4.0", "size": 5923, "upload_time": "2019-08-26T18:19:28", "url": "https://files.pythonhosted.org/packages/1c/67/702ebfa5e97fb2e59ce1fd1d830f92737f49422ac4567131213101ad28fe/pyramid-resource-0.3.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "e8d4180256b21eb0dc18ee161787d1dc", "sha256": "8df5c91a26d18ec311e30033918ac0f813d388744edd4d92675d5dc362034720" }, "downloads": -1, "filename": "pyramid_resource-0.3.0-py3-none-any.whl", "has_sig": false, "md5_digest": "e8d4180256b21eb0dc18ee161787d1dc", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.4,<4.0", "size": 5356, "upload_time": "2019-08-26T18:19:30", "url": "https://files.pythonhosted.org/packages/38/21/0b804bfa820446d2c010a32e31a6006af8e7492e281d82a3758c451c9382/pyramid_resource-0.3.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "9233b745a1447f121038265dacf375c7", "sha256": "ce44e32922f3c832185b4e67a24cf381610baf40cbe5336bd4d522812bf1a557" }, "downloads": -1, "filename": "pyramid-resource-0.3.0.tar.gz", "has_sig": false, "md5_digest": "9233b745a1447f121038265dacf375c7", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.4,<4.0", "size": 5923, "upload_time": "2019-08-26T18:19:28", "url": "https://files.pythonhosted.org/packages/1c/67/702ebfa5e97fb2e59ce1fd1d830f92737f49422ac4567131213101ad28fe/pyramid-resource-0.3.0.tar.gz" } ] }