{ "info": { "author": "hirokiky", "author_email": "hirokiky@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 3 - Alpha", "Environment :: Web Environment", "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.2", "Programming Language :: Python :: 3.3", "Topic :: Internet :: WWW/HTTP", "Topic :: Internet :: WWW/HTTP :: WSGI", "Topic :: Internet :: WWW/HTTP :: WSGI :: Middleware" ], "description": "======\nmatcha\n======\n\nA WSGI dispatcher.\n\n.. image:: https://travis-ci.org/hirokiky/matcha.png\n :target: https://travis-ci.org/hirokiky/matcha\n\nAt a glance\n===========\nmatcha is a dispatcher for all WSGI application\nbased on a matching pattern of PATH_INFO in environ.\n\nLet's register your WSGI applications to matchings and\ncreate WSGI application.\n\n.. code-block:: python\n\n >>> from wsgiref.simple_server import make_server\n >>> from matcha import Matching as m, bundle, make_wsgi_app\n >>>\n >>> from yourproject import home_app\n >>> from yourproject.blog import post_list_app, post_detail_app\n >>>\n >>>\n >>> matching = bundle(\n ... m('/', home_app, 'home'),\n ... m('/post/', post_list_app, 'post_list'),\n ... m('/post/{post_slug}/', post_detail_app, 'post_detail'),\n ... )\n >>>\n >>> if __name__ == '__main__':\n ... app = make_wsgi_app(matching)\n ...\n ... httpd = make_server('', 8000, app)\n ... httpd.serve_forever()\n\nNow, accessing from your browser:\n\n* http://127.0.0.1:8000/ => home_app will be called\n* http://127.0.0.1:8000/post/ => post_list_app will be called\n* http://127.0.0.1:8000/post/some_slug/ => post_detail_app will be called\n\nURL arguments\n=============\nWhen path elements covered with braces, this handled as **URL arguments**.\nThis path element can match any string and you can use that string\nin your WSGI application.\n\nThe URL arguments can get from *environ['matcha.matched_dict']*\nin your WSGI application.\nFor instance, accessing to **'/post/hello_world/'**,\nyou can get **'hello_world'** string as URL arguments like this:\n\n.. code-block:: python\n\n >>> # In post_detail_app:\n >>> environ['matcha.matched_dict']\n {'post_slug': 'hello_world'}\n\nWildcard\n=========\nIf the last element in pattern starts with '*',\nthe following string is considered as `wildcard_name`.\nAnd correspond path will always match.\n\n.. code-block:: python\n\n >>> matching = bundle(\n m('/', home_app, 'home'),\n m('/docs/*doc_tree', document_app, 'docs')\n )\n\nAnd then, you can access them:\n\n* http://127.0.0.1:8000/ => home_app\n* http://127.0.0.1:8000/docs => document_app\n* http://127.0.0.1:8000/docs/about => document_app\n* http://127.0.0.1:8000/docs/about/contributing => document_app\n\nAfter /docs/ it will match any cases.\n\nAnd getting the argument.\n\n.. code-block:: python\n\n >>> # In document_app, when accessed by '/docs/about/contributing'\n >>> environ['matcha.mathed_dict']\n {'doc_tree', ['about', 'contributing']}\n >>> environ['PATH_INFO']\n '/about/contributing'\n >>> environ['SCRIPT_NAME']\n '/docs'\n\nYou can also use this implementation to call another WSGI application\nsuch as dispatching again by using the left PATH_INFO\n\nReversing\n=========\nWeb pages usually contains some URLs for a another page.\nIn this case, post list page is for showing URLs\nto each Blog posts (to post_detail application).\n\nLet's take URL to post_detail application. You can do like this:\n\n.. code-block:: python\n\n >>> # In post_list_app\n >>> matching = environ['matcha.matching']\n >>> matching.reverse('post_detail', post_slug='about_matcha')\n '/post/about_matcha/'\n\n* The first positional argument is a signature string for applications.\n It provided as the third argument of each Matching's constructors.\n* The keyword argument is a string to fill up the URL arguments.\n* Careflly, reverse method will raise NotReverced exception when\n any URLs is not matched.\n\nOK. and then, you can provide this URL to some TemplateEngines\nto display HTML pages.\n\nIncluding another matchings\n===========================\nFor more reusability, let's separate applications for blogs\nfrom core matching.\n\n.. code-block:: python\n\n # In yourproject/blog/matching.py file\n \n from matcha import Matching as m, bundle\n \n from yourproject.blog import post_list_app, post_detail_app\n\n\n matching = bundle(\n m('/', post_list_app, 'post_list'),\n m('/{post_slug}/', post_detail_app, 'post_detail'),\n )\n\nAnd then, applying this to core by using *include* function:\n\n.. code-block:: python\n\n >>> from matcha import include\n >>> from yourproject.blog.matching import matching as blog_matching\n >>>\n >>> matching = bundle(\n ... m('/', home_app, 'home'),\n ... include('/post/', blog_matching)\n ... )\n\nMatching paths will be like this:\n\n* `/` => home application\n* `/post/` => post_list application\n* `/post/some_slug/` => post_detail application\n\nBy using *include*, you can separate paths based on each applications\nand avoid repeating of descriptions (such as '/post/').\n\nName for reverisng to childs are not affected in any way.\nThis value should be unique, even in the all of matchings\n(fixed in matcha 0.3):\n\n.. code-block:: python\n\n >>> matching.reverse('post_detail', post_slug='some_slug')\n '/post/some_slug/'\n\nSetting your 404 WSGI application\n=================================\nThe path matching failed the maked application by matcha will\nreturn a plain 404 page.\nBut most cases, you want to custorm this page more friendly\nfor users.\n\nFor solving this, *matcha.make_wsgi_app* can take `not_found_app`\nkeyword argument to provide your own WSGI application for showing\n404 page.\n\nBy default, the not_found_app is matcha.not_found_app.\n\nWhat is Matching objects\n========================\nAlmost core features provided by matcha dispatcher\nis implamented as Matching objects.\n\nNow, through above example, you recognize matching is like this:\n\n* matching is created by using bundle function and Matching class.\n* Registering WSGI apllications to matching.\n* matching can get from environ dictionaly\n\nNot wrong, but Matching class is something more flexible than\nyour recognition.\n\nCalling\n-------\nmatching is callable\n\n* taking environ dictionary\n* sideeffecting environ dictionary\n* returning matched case and dictionary\n\nThat sideeffection is for PATH_INFO and SCRIPT_NAME to tell\nwhich path elements are processed to another WSGI application.\n\n.. code-block:: python\n\n >>> environ = {'PATH_INFO': '/htt', 'SCRIPT_NAME': '/about'}\n >>> Matching('/htt', about_htt_app)(environ)\n (about_htt_app, {})\n >>> environ\n {'PATH_INFO': '', 'SCRIPT_NAME': '/about/htt'}\n\nGetitem from matching\n---------------------\ncailling of matching requires environ dictionaly, but using getitem\nyou can only apply path to get matched case and dictionaly.\n\n.. code-block:: python\n\n >>> Matching('/htt', about_htt_app)['/htt']\n (about_htt_app, {})\n\nRegistering not only WSGI app\n-----------------------------\nSecond positional argument (*case* keyword argument) of Matching class\ncan take any objects you like, not only WSGI app.\n\n.. code-block:: python\n\n >>> Matching('/home', 'home')['/home']\n ('home', {})\n \nFor instance, you can register strings and use this as signature\nfor some views. something like **route_name** on\n`Pyramid `_.\n\nAdding matchings\n----------------\nActually, *bundle* function used in above examples is just for\nadding provided positional arguments (addable objects).\nSo you can make WSGI application without this function:\n\n.. code-block:: python\n\n >>> app = make_wsgi_app(\n ... Matching('/', home_app) + \\\n ... Matching('/abount', about_app)\n ... )\n\nThanks\n======\nmatcha dispatcher has been influenced these dispatchers:\n\n* `Django `_ 's URL dispatcher\n* `WebDispatch `_\n* `gargant.dispatch `_\n\nThanks for them.\n\nResources\n=========\n* `PyPI `_\n* `Repository `_\n* `Testing `_\n\nChanges\n===========\n\n0.3\n-----\n\nUn-supporting name argument on include function\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\nBefore this change, user applied include name,\nthe reversing in included app will break, because\nthe name for reversing already changed.\n\n0.2\n-----\n* Supporting Wildcard\n\n0.1\n-----\n\nInitial release.", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/hirokiky/matcha", "keywords": null, "license": "MIT", "maintainer": null, "maintainer_email": null, "name": "matcha", "package_url": "https://pypi.org/project/matcha/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/matcha/", "project_urls": { "Download": "UNKNOWN", "Homepage": "https://github.com/hirokiky/matcha" }, "release_url": "https://pypi.org/project/matcha/0.3/", "requires_dist": null, "requires_python": null, "summary": "A WSGI dispatcher.", "version": "0.3" }, "last_serial": 894902, "releases": { "0.1": [ { "comment_text": "", "digests": { "md5": "41db88e1632510ff3fa3238665e3a784", "sha256": "5b54f49ccea67faf55d244bf5afecd66fe71e65b4aa6e59aac23ef09202dbb12" }, "downloads": -1, "filename": "matcha-0.1.tar.gz", "has_sig": false, "md5_digest": "41db88e1632510ff3fa3238665e3a784", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5289, "upload_time": "2013-10-05T17:22:48", "url": "https://files.pythonhosted.org/packages/1f/86/965a836afc89d30e509a7edf4ab03baacd42f0a2db5ed1c40b9269539dd3/matcha-0.1.tar.gz" } ], "0.2": [ { "comment_text": "", "digests": { "md5": "caa2e3b910255848df369e36619f4952", "sha256": "5cb259773c9b57c0f5d37ffaa9de59c4d892fa9821c163e6cf22b7f5e92d88d6" }, "downloads": -1, "filename": "matcha-0.2.tar.gz", "has_sig": false, "md5_digest": "caa2e3b910255848df369e36619f4952", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6193, "upload_time": "2013-10-08T14:44:17", "url": "https://files.pythonhosted.org/packages/6c/0b/05063895b90a6138910511adb4b0751d63b7b396505fe188b55ea86bf9da/matcha-0.2.tar.gz" } ], "0.3": [ { "comment_text": "", "digests": { "md5": "c157bf0ef535d5ddeff7690bfa03b720", "sha256": "f27277c7d7f21898e42c49ab7efb536e86d2cd16d417eb6eacfc686526ac50d0" }, "downloads": -1, "filename": "matcha-0.3.tar.gz", "has_sig": false, "md5_digest": "c157bf0ef535d5ddeff7690bfa03b720", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6389, "upload_time": "2013-10-15T14:33:27", "url": "https://files.pythonhosted.org/packages/cc/e7/e111d28dd0e1e70fc8a9d8a827975e0969c85b7f62ee418e86c441da346a/matcha-0.3.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "c157bf0ef535d5ddeff7690bfa03b720", "sha256": "f27277c7d7f21898e42c49ab7efb536e86d2cd16d417eb6eacfc686526ac50d0" }, "downloads": -1, "filename": "matcha-0.3.tar.gz", "has_sig": false, "md5_digest": "c157bf0ef535d5ddeff7690bfa03b720", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6389, "upload_time": "2013-10-15T14:33:27", "url": "https://files.pythonhosted.org/packages/cc/e7/e111d28dd0e1e70fc8a9d8a827975e0969c85b7f62ee418e86c441da346a/matcha-0.3.tar.gz" } ] }