{ "info": { "author": "Sam Briesemeister", "author_email": "sam.briesemeister@gmail.com", "bugtrack_url": null, "classifiers": [], "description": "WSGI Tackle\n===========\n\nThis is a WSGI framework originated by Sam Briesemeister, derived from\nwork in personal projects and products still in development, which\nneeded a very light WSGI abstraction.\n\nIt adopts some inspiration, paradigms and design components from other\nWSGI environments, including webapp2 (Google AppEngine), but aims to\nmaintain a degree of compatibility with core WSGI architecture.\n\nIt's currently tested and working in combination with Flask. No\ndependencies on a particular WSGI server, e.g. ``gevent``, are currently\nrequired.\n\nWhy does the world need another WSGI framework?\n-----------------------------------------------\n\nFrankly *the world* probably doesn't, but in spite of the `abundance of\navailable\nframeworks `__,\nnone quite fit my taste.\n\nThe name: tackle, `the equipment used to in a particular\nsport `__.\n\nDependencies\n------------\n\n- webob\n\nFeatures\n========\n\n- `Virtual Host Routing <#virtualhost>`__ based on hostname\n- `URL Routing <#routing>`__ with regular expressions to simplify\n RESTful interface design (which most modern WSGI frameworks also\n claim)\n- `Middleware Class <#middleware>`__ for easily mixing features, in\n generic fashion, with existing WSGI applications.\n- `Static File Preemptive Route <#staticfiles-middleware>`__\n- `Rule-based Redirection <#redirection-middleware>`__\n\nVirtual Host Routing \n---------------------\n\nIn case you're using a very simplistic hosting environment which offers\nyou a single WSGI instance, such as Gandi's Simple Hosting, you may need\nto integrate multiple WSGI applications from several domains.\n\n.. code:: python\n\n from tackle import WSGIService\n from myapp import example_com\n from myapp import otherhost_com\n\n # Pass any WSGI-compliant callable as a hander for any host.\n\n service = WSGIService(\n ('www.example.com', example_com)\n ('www.otherhost.com', otherhost_com)\n )\n\n # Register a single WSGI callable for multiple hosts\n service.register(another_app, 'abc.com', 'xyz.com')\n\nURL Routing \n------------\n\n| This model probably isn't new to you, it's echoed in many frameworks,\n in various styles.\n| Register a RequestHandler for a particular URL pattern.\n\n.. code:: python\n\n from tackle import WSGIApplication, WSGIRequestHandler\n\n app = WSGIApplication()\n\n @app.route('/resource/')\n class ResourceHandler(WSGIHandler):\n\n def get(self, resource_id):\n \"\"\" retrieve the resource's content \"\"\"\n # self.response is a webob.Response\n self.response.headers['Content-Type'] = 'text/plain'\n return \"Looking for resource %r\" % resource_id\n\n def post(self, resource_id):\n \"\"\" update the resource based on request body \"\"\"\n # self.request is a webob.Request\n update_prop = self.request.params.get('resource_name')\n pass\n\nCurrently there are no artificial constraints on HTTP verbs that will be\nattempted as methods on the request handler.\n\nMiddleware \n-----------\n\nA simple, generic Middleware model is provided. Any middleware derived\nfrom this class can implement one or both of the methods illustrated\nbelow, ``run_before`` or ``run_after``.\n\n.. code:: python\n\n from tackle import Middleware, WSGIApplication\n\n class CustomMiddleware(Middleware):\n\n def run_before(self, environ, start_response):\n # any aspects accessible to downstream applications need to be added to environ.\n # a return value from this method will override (prevent) the downstream app from handling the request.\n pass\n\n def run_after(self, environ, start_response, previous_result):\n # `previous_result` is the return value from the app, or any intervening Middleware.\n # this method should return previous_result, if unmodified, or return a modified form of it (a replacement).\n return previous_result\n\n \n # Prepare your core WSGI application.\n myapp = WSGIApplication(...)\n\n # Constructs a new WSGI callable. \n # If you reassign `app` with this value, you may lose reference to your original app's properties. \n wrapped_app = CustomMiddleware(option = \"value\").wsgi(myapp)\n\nStatic File Preemptive Route \n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nThis middleware acts as a preemptor to a primary application. When a\nrequest matches the given URL prefix, the remaining URL path is resolved\nwithin a given local directory, and served directly with a simple\ncaching directive.\n\n.. code:: python\n\n from tackle import WSGIApplication, StaticFileMiddleware\n\n # All requests in \"/static/\" should resolve within \"./local/app/static\"\n # e.g. GET /static/site.css will resolve to \"local/app/static/site.css\"\n static = StaticFileMiddleware('local/app/static', '/static/')\n\n app = WSGIApplication()\n app = static.wsgi(app)\n\nRule-Based Redirection \n~~~~~~~~~~~~~~~~~~~~~~~\n\nThe Redirection middleware operates preemptively, intercepting requests\nto matched URLs and responding with HTTP 301 or 302 redirects.\n\n| Two options are provided to incorporate common behaviors;\n ``retain_path`` will first copy the path from the original request\n into the redirect's destination; and ``retain_query`` will first copy\n the query from the original request into the redirect's destination.\n| These options will override statically-defined path or query\n components of the configured target. Variations can be achieved using\n regular expressions and destination templates.\n\n.. code:: python\n\n from tackle import WSGIApplication, RedirectionMiddleware\n\n app = WSGIApplication()\n\n redir = RedirectionMiddleware(retain_path = False, retain_query = True) # defaults\n redir.redirect(\"/help/(.*)\", \"http://help.mysite.com/{1}\")\n\n # named captures are also supported.\n redir.redirect(\"/help/(?P
.*)\", \"http://help.mysite.com/{article}\")\n\n app = redir.wsgi(app)\n\n", "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/samba/tackle-wsgi/", "keywords": null, "license": "Copyright Sam Briesemeister, 2015", "maintainer": null, "maintainer_email": null, "name": "tackle", "package_url": "https://pypi.org/project/tackle/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/tackle/", "project_urls": { "Download": "UNKNOWN", "Homepage": "https://github.com/samba/tackle-wsgi/" }, "release_url": "https://pypi.org/project/tackle/0.0.1/", "requires_dist": null, "requires_python": null, "summary": "Another WSGI framework aiming for simplicity and flexibility", "version": "0.0.1" }, "last_serial": 1952153, "releases": { "0.0.1": [ { "comment_text": "built for Darwin-15.2.0", "digests": { "md5": "80beb50df86ca3171015823c2ac0bcd8", "sha256": "3b4cb77fb2366732d7068ed44fb00927410100e3f9fe006923307eaae0a470d5" }, "downloads": -1, "filename": "tackle-0.0.1.macosx-10.11-intel.tar.gz", "has_sig": false, "md5_digest": "80beb50df86ca3171015823c2ac0bcd8", "packagetype": "bdist_dumb", "python_version": "any", "requires_python": null, "size": 12014, "upload_time": "2016-02-12T00:40:18", "url": "https://files.pythonhosted.org/packages/c8/6d/43b21e92fea660410264e5f1c07af7bf4609215567f145354f3093744290/tackle-0.0.1.macosx-10.11-intel.tar.gz" }, { "comment_text": "", "digests": { "md5": "b0d0affc32ef9c07d2626d7081c81582", "sha256": "909636d6755a6aa6c30d9496bd1beef30ffdef3a008fa81ee59d3fde0bb9eedc" }, "downloads": -1, "filename": "tackle-0.0.1-py2.7.egg", "has_sig": false, "md5_digest": "b0d0affc32ef9c07d2626d7081c81582", "packagetype": "bdist_egg", "python_version": "2.7", "requires_python": null, "size": 15507, "upload_time": "2016-02-12T00:40:25", "url": "https://files.pythonhosted.org/packages/f0/ae/bb89e7ec484fa2154594297e357306fe4fcd497ca2d2c6621934c890d217/tackle-0.0.1-py2.7.egg" }, { "comment_text": "", "digests": { "md5": "342adfa45c9736e73b06c1efa777c79d", "sha256": "4ac0a01afdcc5623513c2a77d8552704b666d106f0e920b1bc7ae3176ae0091d" }, "downloads": -1, "filename": "tackle-0.0.1.tar.gz", "has_sig": false, "md5_digest": "342adfa45c9736e73b06c1efa777c79d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8010, "upload_time": "2016-02-12T00:40:09", "url": "https://files.pythonhosted.org/packages/bc/fb/b5fb717c39252d022fa9e288db0c6d8a728c0260775d82e15942b640c278/tackle-0.0.1.tar.gz" } ], "0.0.1b0": [ { "comment_text": "built for Darwin-15.2.0", "digests": { "md5": "f6c80a1301e6d8add71b045d372b45d8", "sha256": "2713f7df1b4adcc8f462ae29e8880a19cd8c40f8dedec4a00fac86cbb425229c" }, "downloads": -1, "filename": "tackle-0.0.1b0.macosx-10.11-intel.tar.gz", "has_sig": false, "md5_digest": "f6c80a1301e6d8add71b045d372b45d8", "packagetype": "bdist_dumb", "python_version": "any", "requires_python": null, "size": 12033, "upload_time": "2016-02-12T00:50:33", "url": "https://files.pythonhosted.org/packages/6c/5f/855727959de2a805f6363e049e98932f1216a225646e1b0133f5d8f28bfd/tackle-0.0.1b0.macosx-10.11-intel.tar.gz" }, { "comment_text": "", "digests": { "md5": "82ef860bf972bd4578ac2a6ee6fcdce3", "sha256": "76bccedbb4affa91a3fe74eac9b21765c2ff6f8867189cde861248418aae9753" }, "downloads": -1, "filename": "tackle-0.0.1b0-py2.7.egg", "has_sig": false, "md5_digest": "82ef860bf972bd4578ac2a6ee6fcdce3", "packagetype": "bdist_egg", "python_version": "2.7", "requires_python": null, "size": 15511, "upload_time": "2016-02-12T00:50:38", "url": "https://files.pythonhosted.org/packages/94/1b/5e2e1e7c8f24f14b4df7a3403561ea0df73fc9b102fcc7d410f50a5c0052/tackle-0.0.1b0-py2.7.egg" }, { "comment_text": "", "digests": { "md5": "eb3cbb3e0ce3be93693330deda9fe714", "sha256": "f3f78057531b808446c8dbcd9248f7f6f3ffb9067298ce6e4361f4e4f0ced9a8" }, "downloads": -1, "filename": "tackle-0.0.1b0.tar.gz", "has_sig": false, "md5_digest": "eb3cbb3e0ce3be93693330deda9fe714", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8018, "upload_time": "2016-02-12T00:50:26", "url": "https://files.pythonhosted.org/packages/4f/04/91837a91d230acd41d7dd9d0fc6da2ff1b950382d3aa6c1f3ecf2c7b0434/tackle-0.0.1b0.tar.gz" } ] }, "urls": [ { "comment_text": "built for Darwin-15.2.0", "digests": { "md5": "80beb50df86ca3171015823c2ac0bcd8", "sha256": "3b4cb77fb2366732d7068ed44fb00927410100e3f9fe006923307eaae0a470d5" }, "downloads": -1, "filename": "tackle-0.0.1.macosx-10.11-intel.tar.gz", "has_sig": false, "md5_digest": "80beb50df86ca3171015823c2ac0bcd8", "packagetype": "bdist_dumb", "python_version": "any", "requires_python": null, "size": 12014, "upload_time": "2016-02-12T00:40:18", "url": "https://files.pythonhosted.org/packages/c8/6d/43b21e92fea660410264e5f1c07af7bf4609215567f145354f3093744290/tackle-0.0.1.macosx-10.11-intel.tar.gz" }, { "comment_text": "", "digests": { "md5": "b0d0affc32ef9c07d2626d7081c81582", "sha256": "909636d6755a6aa6c30d9496bd1beef30ffdef3a008fa81ee59d3fde0bb9eedc" }, "downloads": -1, "filename": "tackle-0.0.1-py2.7.egg", "has_sig": false, "md5_digest": "b0d0affc32ef9c07d2626d7081c81582", "packagetype": "bdist_egg", "python_version": "2.7", "requires_python": null, "size": 15507, "upload_time": "2016-02-12T00:40:25", "url": "https://files.pythonhosted.org/packages/f0/ae/bb89e7ec484fa2154594297e357306fe4fcd497ca2d2c6621934c890d217/tackle-0.0.1-py2.7.egg" }, { "comment_text": "", "digests": { "md5": "342adfa45c9736e73b06c1efa777c79d", "sha256": "4ac0a01afdcc5623513c2a77d8552704b666d106f0e920b1bc7ae3176ae0091d" }, "downloads": -1, "filename": "tackle-0.0.1.tar.gz", "has_sig": false, "md5_digest": "342adfa45c9736e73b06c1efa777c79d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8010, "upload_time": "2016-02-12T00:40:09", "url": "https://files.pythonhosted.org/packages/bc/fb/b5fb717c39252d022fa9e288db0c6d8a728c0260775d82e15942b640c278/tackle-0.0.1.tar.gz" } ] }