{ "info": { "author": "Andrew Kubera", "author_email": "andrew.kubera@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 3 - Alpha", "Environment :: Web Environment", "License :: OSI Approved :: Apache Software License", "Natural Language :: English", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Topic :: Internet :: WWW/HTTP" ], "description": "=======\nGrowler\n=======\n\nmaster\n |travis-master| |coveralls-master| ' |version-master|\n\ndev\n |travis-dev| |coveralls-dev|\n\nGrowler is a web framework built atop asyncio, the asynchronous library described in `PEP\n3156`_ and added to the standard library in python 3.4.\nIt takes a cue from the `Connect`_ & `Express`_ frameworks in the `nodejs`_ ecosystem, using a\nsingle application object and series of middleware to process HTTP requests.\nThe custom chain of middleware provides an easy way to implement complex applications.\n\nInstallation\n------------\n\nGrowler is installable via pip:\n\n.. code:: bash\n\n $ pip install growler\n\nThe source can be downloaded/cloned from github at http://github.com/pyGrowler/Growler.\n\nExtras\n~~~~~~\n\nThe pip utility allows packages to provide optional requirements, so features may be installed\nonly upon request.\nThis meshes well with the minimal nature of the Growler project: don't install anything the\nuser doesn't need.\nThat being said, there are (will be) community packages that are *blessed* by the growler\ndevelopers (after ensuring they work as expected and are well tested with each version of\ngrowler) that will be available as extras directly from the growler package.\n\nFor example, if you want to use the popular `mako`_ html\ntemplate engine, you can add support easily by adding it to the list of optionals:\n\n.. code:: bash\n\n $ pip install growler[mako]\n\nThis will automatically install the mako-growler packge, or growler-mako, or whatever it is\nnamed - you don't care, it's right there, and it works! Very easy!\n\nThe goal here is to provide a super simple method for adding middleware packages that the user\ncan be sure works with that version of growler (i.e. has been tested), and has the blessing of\nthe growler developer(s).\n\nThe coolest thing would be to describe your web stack via this command, so if you want mako,\ncoffeescript, and some postgres ORM, your install command would look like\n:code:`growler[mako,coffee,pgorm]`; anybody could look at that string and get the birds-eye\nview of your project.\n\nWhen multiple extras are available, they will be listed here.\n\nUsage\n-----\n\nThe core of the framework is the ``growler.App`` class, which links the asyncio server to your\nproject's middleware.\nMiddeware can be any callable or coroutine.\nThe App object creates a request and a response object when a client connects and passes the\npair to this middleware chain.\nNote: The middleware are processed in the *same order* they are specified - this could cause\nunexpected behavior (errors) if a developer is not careful, so be careful!\nThe middleware can manipulate the request and response, adding features or checking state.\nIf any respond to the client, the middleware chain is finished.\nThis stream/filter model makes it very easy to modularize and extend web applications with many\nfeatures, backed by the power of python.\n\nExample Usage\n-------------\n\n.. code:: python\n\n import asyncio\n\n from growler import App\n from growler.middleware import (Logger, Static, StringRenderer)\n\n loop = asyncio.get_event_loop()\n\n # Construct our application with name GrowlerServer\n app = App('GrowlerServer', loop=loop)\n\n # Add some growler middleware to the application\n app.use(Logger())\n app.use(Static(path='public'))\n app.use(StringRenderer(\"views/\"))\n\n # Add some routes to the application\n @app.get('/')\n def index(req, res):\n res.render(\"home\")\n\n @app.get('/hello')\n def hello_world(req, res):\n res.send_text(\"Hello World!!\")\n\n # Create the server - this automatically adds it to the asyncio event loop\n Server = app.create_server(host='127.0.0.1', port=8000)\n\n # Tell the event loop to run forever - this will listen to the server's\n # socket and wake up the growler application upon each connection\n loop.run_forever()\n\n\nThis code creates an application which is identified by 'GrowlerServer' (this name does nothing\nat this point), and a reference to the event loop.\nRequests are passed to some middleware provided by the Grower package: Logger, Static, and\nStringRenderer.\nLogger simply prints the ip address of the connecting client to stdout.\nStatic will check a request url path against files in views/, if one of the files match, the\nfile type is determined, proper content-type header is set, and the file content is sent.\nRenderer adds the 'render' method to the response object, allowing any following function to\ncall res.render('/filename'), where filename exists in the \"views\" directory.\n\nDecorators are used to add endpoints to the application, so requests with path matching '/'\nwill call ``index(req, res)`` and requests matching '/hello' will call ``hello_world(req,\nres)``.\nBecause 'app.get' is used, only HTTP ``GET`` requests will match these endpoints.\nOther HTTP 'verbs' (post, put, delete, etc) are available as well as 'all', which matches any\nmethod.\nVerb methods must match a path in full.\n\nThe 'use' method takes an optional path parameter (e.g.\n``app.use(Static(\"public\"), '/static'))``, which calls the middleware anytime the request path\n*begins* with the parameter.\n\nThe asyncio package provides a Server class which does the low-level socket handling for the\ndeveloper, this is how your application should be hosted.\nCalling ``app.create_server(...)`` creates an asyncio Server object with the event loop given\nin app's constructor, and the app as the target for incomming connections; this is the\nrecommended way to setup a server.\nYou can't do much with the server directly, so after creation the event loop must be given\ncontrol of the thread\nThe easiest way to do this is to use ``loop.run_forever()`` after ``app.create_server(...)``.\nOr do it in one line with ``app.create_server_and_run_forever(...)``.\n\nExtensions\n----------\n\nGrowler introduces the virtual namespace ``growler_ext`` to which other projects may add their\nown growler-specific code.\nOf course, these packages may be imported in the standard way, but Growler provides an\nautoloading feature via the growler.ext module (note the '.' in place of '_') which will\nautomatically import any packages found in the growler_ext namespace.\nThis not only provides a standard interface for extensions, but allows for different\nimplementations of an interface to be chosen by the environment, rather than hard-coded in.\nIt also can reduce the number of import statements at the beginning of the file.\nThis specialized importer may be imported as a standalone module:\n\n.. code:: python\n\n from growler import App, ext\n\n app = App()\n app.use(ext.MyGrowlerExtension())\n ...\n\n\nor a module to import 'from':\n\n.. code:: python\n\n from growler import App\n from growler.ext import MyGrowlerExtension\n\n app = App()\n app.use(MyGrowlerExtension())\n ...\n\nThis works by replacing the 'real' ext module with an object that will import submodules in the\ngrowler_ext namespace automatically.\nPerhaps unfortunately, because of this there is no way I know of to allow the\n``import growler.ext.my_extension`` syntax, as this skips the importer object and raises an\nimport error.\nUsers **must** use the ``from growler.ext import ...`` syntax instead.\n\nThe best practice for developers to add their middleware to growler is now to put their code in\nthe python module growler_ext/my_extension.\nThis will allow your code to be imported by others via ``from growler.ext import my_extension``\nor the combination of ``from growler import ext`` and ``ext.my_extension``.\n\nAn example of an extension is the `indexer`_ packge, which hosts an automatically generated\nindex of a filesystem directory.\nIt should implement the best practices of how to write extensions.\n\nMore\n----\n\nAs it stands, Growler is single threaded, partially implemented, and not fully tested.\nAny submissions, comments, and issues are greatly appreciated, but I request that you please\nfollow the Growler `contributing`_ guide.\n\nThe name Growler comes from the `beer bottle`_ keeping in line with the theme of giving\npython micro-web-frameworks fluid container names.\n\nLicense\n-------\n\nGrowler is licensed under `Apache 2.0`_.\n\n\n.. _PEP 3156: https://www.python.org/dev/peps/pep-3156/\n.. _NodeJS: https://nodejs.org\n.. _express: http://expressjs.com\n.. _connect: https://github.com/senchalabs/connect\n.. _indexer: https://github.com/pyGrowler/growler-indexer\n.. _beer bottle: https://en.wikipedia.org/wiki/Growler_%28jug%29\n.. _Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0.html\n.. _mako: http://www.makotemplates.org/\n.. _contributing: https://github.com/pyGrowler/Growler/blob/dev/CONTRIBUTING.rst\n\n\n.. |version-master| image:: https://img.shields.io/pypi/v/growler.svg\n :target: https://pypi.python.org/pypi/growler/\n :alt: Latest PyPI version\n\n\n.. |travis-master| image:: https://travis-ci.org/pyGrowler/Growler.svg?branch=master\n :target: https://travis-ci.org/pyGrowler/Growler/branches?branch=master\n :alt: Testing Report (Master Branch)\n\n.. |travis-dev| image:: https://travis-ci.org/pyGrowler/Growler.svg?branch=dev\n :target: https://travis-ci.org/pyGrowler/Growler/branches?branch=dev\n :alt: Testing Report (Development Branch)\n\n.. |coveralls-master| image:: https://coveralls.io/repos/github/pyGrowler/Growler/badge.svg?branch=master\n :target: https://coveralls.io/github/pyGrowler/Growler?branch=master\n :alt: Coverage Report (Master Branch)\n\n.. |coveralls-dev| image:: https://coveralls.io/repos/github/pyGrowler/Growler/badge.svg?branch=dev\n :target: https://coveralls.io/github/pyGrowler/Growler?branch=dev\n :alt: Coverage Report (Development Branch)\n", "description_content_type": null, "docs_url": null, "download_url": "https://github.com/pyGrowler/growler/archive/v0.8.0.tar.gz", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/pyGrowler/Growler", "keywords": null, "license": "Apache v2.0", "maintainer": null, "maintainer_email": null, "name": "growler", "package_url": "https://pypi.org/project/growler/", "platform": "all", "project_url": "https://pypi.org/project/growler/", "project_urls": { "Download": "https://github.com/pyGrowler/growler/archive/v0.8.0.tar.gz", "Homepage": "https://github.com/pyGrowler/Growler" }, "release_url": "https://pypi.org/project/growler/0.8.0/", "requires_dist": null, "requires_python": null, "summary": "A micro web-framework using asyncio coroutines and chained middleware.", "version": "0.8.0" }, "last_serial": 2402449, "releases": { "0.5.0": [ { "comment_text": "", "digests": { "md5": "e6695e99db9dfbae694aac80d349b155", "sha256": "c80b2fd402b50087b08f6b606cabf3c8a4e06e8680aefaa86836e4ef49c86357" }, "downloads": -1, "filename": "growler-0.5.0.tar.gz", "has_sig": false, "md5_digest": "e6695e99db9dfbae694aac80d349b155", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 26932, "upload_time": "2015-05-22T18:43:54", "url": "https://files.pythonhosted.org/packages/41/28/927f89c15f108f3a43251092a41b8408fdfd3cd18101bcf0ab37b424c889/growler-0.5.0.tar.gz" } ], "0.5.5": [ { "comment_text": "", "digests": { "md5": "cc3a391b743a37a5b639d52f353945f0", "sha256": "eb25fff9c33dc55af5781229fd9a75ab6b413d67d48627e7c10ef633e55cb01e" }, "downloads": -1, "filename": "growler-0.5.5.tar.gz", "has_sig": false, "md5_digest": "cc3a391b743a37a5b639d52f353945f0", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 29795, "upload_time": "2015-07-24T05:54:01", "url": "https://files.pythonhosted.org/packages/3d/83/801af1f5567fd4312fac0a3790a4c37256c8b8218e4f4224ba0d37cdc5bd/growler-0.5.5.tar.gz" } ], "0.6.1": [ { "comment_text": "", "digests": { "md5": "2ddfec6638bd9b1f3ca55cf69aacec4e", "sha256": "1ab92c4f7004a4b54024aa9dba6b39f9c50927e5c12e1c115052f3462975d41c" }, "downloads": -1, "filename": "growler-0.6.1.tar.gz", "has_sig": false, "md5_digest": "2ddfec6638bd9b1f3ca55cf69aacec4e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 58084, "upload_time": "2015-09-01T16:30:17", "url": "https://files.pythonhosted.org/packages/3a/93/6c4dac288ec1308d2004528d9f360be3500199cd45046e4c544c94dfaebb/growler-0.6.1.tar.gz" } ], "0.6.5": [ { "comment_text": "", "digests": { "md5": "16f4ba340f11dd0adf6e294225704ec1", "sha256": "8718b257624d18a82ebd464b051ef64327b08615e7727fcaddd8c11099f7fe7d" }, "downloads": -1, "filename": "growler-0.6.5-py3-none-any.whl", "has_sig": false, "md5_digest": "16f4ba340f11dd0adf6e294225704ec1", "packagetype": "bdist_wheel", "python_version": "3.4", "requires_python": null, "size": 39875, "upload_time": "2015-12-15T09:55:39", "url": "https://files.pythonhosted.org/packages/ed/8e/58ea7deb0a7bd30b2fe563f1900478b0f27425c4138d85379ded70fbf67d/growler-0.6.5-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "5bfeea8f2a27b6f0ef3f7de289a04a50", "sha256": "c60122c2938d4649fb346a17efaeefb114c7b3799fc48461414ee061ad01d8f4" }, "downloads": -1, "filename": "growler-0.6.5.tar.gz", "has_sig": false, "md5_digest": "5bfeea8f2a27b6f0ef3f7de289a04a50", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 31306, "upload_time": "2015-12-15T09:55:33", "url": "https://files.pythonhosted.org/packages/2c/9d/28880f66d37e5df8ac80735313f6ec16dd01a831e40b6964c3454e34ce93/growler-0.6.5.tar.gz" } ], "0.7.0": [ { "comment_text": "", "digests": { "md5": "f228df37a7f2f47300d19bf2f8f9d73c", "sha256": "c784cd69aeb50811f75b3382e98713ff5c1f044409045d72b2504e1f762ee523" }, "downloads": -1, "filename": "growler-0.7.0-py3-none-any.whl", "has_sig": false, "md5_digest": "f228df37a7f2f47300d19bf2f8f9d73c", "packagetype": "bdist_wheel", "python_version": "3.5", "requires_python": null, "size": 44861, "upload_time": "2016-04-14T19:20:52", "url": "https://files.pythonhosted.org/packages/54/a7/d064962683384a02cca86d8e49ce162c9d31f8dac5122641b501d42b3bc7/growler-0.7.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "c62d98ec1c2416fb546fa28cd4b87282", "sha256": "d8fde3e7d98f81c31f83bda29884a8e00f88846979a86fd24439423312727f5e" }, "downloads": -1, "filename": "growler-0.7.0.tar.gz", "has_sig": false, "md5_digest": "c62d98ec1c2416fb546fa28cd4b87282", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 70715, "upload_time": "2016-04-14T19:20:38", "url": "https://files.pythonhosted.org/packages/26/de/2aca8a267e2d372683f4071d19e3d4992774e280682a52b8b43586f3e698/growler-0.7.0.tar.gz" } ], "0.7.1": [ { "comment_text": "", "digests": { "md5": "21487058205d1bf187ca439c24ac8eba", "sha256": "04c642d8743ea253b4d9c6057a3d541ca7c5ecd10aa68bed046316f844783612" }, "downloads": -1, "filename": "growler-0.7.1-py3-none-any.whl", "has_sig": false, "md5_digest": "21487058205d1bf187ca439c24ac8eba", "packagetype": "bdist_wheel", "python_version": "3.5", "requires_python": null, "size": 45136, "upload_time": "2016-04-19T00:15:26", "url": "https://files.pythonhosted.org/packages/7e/15/d524175556ef5898990ffe288753ee65b29b2af028dbce1d3a12cdc0d929/growler-0.7.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "b23db285e5a5981d29b7016b971781fa", "sha256": "2113c379a7cd5db1b6294e7b9596defc9556b11c50e57077fe2545b006cd1773" }, "downloads": -1, "filename": "growler-0.7.1.tar.gz", "has_sig": false, "md5_digest": "b23db285e5a5981d29b7016b971781fa", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 71052, "upload_time": "2016-04-19T00:15:21", "url": "https://files.pythonhosted.org/packages/1e/ec/79baae18e977e1d42e9e5768c69aa47b9f10e105cbe1a90bdc44362e2b88/growler-0.7.1.tar.gz" } ], "0.7.2": [ { "comment_text": "", "digests": { "md5": "7f4afd3d9176e86dcef165d1de9a5817", "sha256": "8000556031d64037094f6b63b5bc22b8a89d401963ce11ae84e3843cf80d66fc" }, "downloads": -1, "filename": "growler-0.7.2-py3-none-any.whl", "has_sig": false, "md5_digest": "7f4afd3d9176e86dcef165d1de9a5817", "packagetype": "bdist_wheel", "python_version": "3.5", "requires_python": null, "size": 45423, "upload_time": "2016-05-04T20:06:01", "url": "https://files.pythonhosted.org/packages/9c/c0/75ef458c2ec47137b934cb516cd3d40c21d68d8806ea04c3d728189eeeb5/growler-0.7.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "18cc85d8545f48c4ff79b2c2e75771c9", "sha256": "11611ea517d7383ea6c795dd4108688217bfd11c5161e7e0b0127617b1c78131" }, "downloads": -1, "filename": "growler-0.7.2.tar.gz", "has_sig": false, "md5_digest": "18cc85d8545f48c4ff79b2c2e75771c9", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 65714, "upload_time": "2016-05-04T17:49:27", "url": "https://files.pythonhosted.org/packages/3a/b7/5f6a1b6ce91ee3b849ab1554eaa1466a20d7c4857011495de764c416e7ff/growler-0.7.2.tar.gz" } ], "0.7.4": [ { "comment_text": "", "digests": { "md5": "c307e8b22b08cfbaee5868dc35788bd6", "sha256": "45d37ff2269ba08facd2e56440432bd0f3f005925a86497d2310161878b70d7a" }, "downloads": -1, "filename": "growler-0.7.4-py3-none-any.whl", "has_sig": false, "md5_digest": "c307e8b22b08cfbaee5868dc35788bd6", "packagetype": "bdist_wheel", "python_version": "3.4", "requires_python": null, "size": 45740, "upload_time": "2016-05-24T03:59:52", "url": "https://files.pythonhosted.org/packages/6a/be/8081cfd25be771b434fd4cb3e8001e17aee029736f39a964086b99d5437c/growler-0.7.4-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "b72acbdf1599311c52336b32070b5968", "sha256": "3b3e5d4675b1fd91af374c7f3f5a5c307453f74df75e4442c5da65f6076189ef" }, "downloads": -1, "filename": "growler-0.7.4.tar.gz", "has_sig": false, "md5_digest": "b72acbdf1599311c52336b32070b5968", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 70256, "upload_time": "2016-05-24T03:58:31", "url": "https://files.pythonhosted.org/packages/b4/fb/bd5c2263449c4c55f325e89bea94d3c315d9c1b28063ca568ab92045cc94/growler-0.7.4.tar.gz" } ], "0.7.5": [ { "comment_text": "", "digests": { "md5": "cac135400d2da5940aa6332741155e54", "sha256": "2e169b2b178e31f5f37ca67231473bc8895fd1ff680d8eb740b088287b4ff586" }, "downloads": -1, "filename": "growler-0.7.5-py3-none-any.whl", "has_sig": false, "md5_digest": "cac135400d2da5940aa6332741155e54", "packagetype": "bdist_wheel", "python_version": "3.5", "requires_python": null, "size": 47702, "upload_time": "2016-07-22T02:59:10", "url": "https://files.pythonhosted.org/packages/4f/63/f3d1a83df2c357db3f4def01a3b4995a8c9b85c05204cd6d76f346d17ba2/growler-0.7.5-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "0b6ea0da800c29d38fbfb3e7825625d3", "sha256": "87379debad9e20135343aa46deffb071b8134a3565fcff18cf9d0cd229b2889d" }, "downloads": -1, "filename": "growler-0.7.5.tar.gz", "has_sig": false, "md5_digest": "0b6ea0da800c29d38fbfb3e7825625d3", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 75225, "upload_time": "2016-07-22T02:58:24", "url": "https://files.pythonhosted.org/packages/71/5a/d31e87d146cc9badb628cb375432269318bed6f522180f7846108e2249c5/growler-0.7.5.tar.gz" } ], "0.8.0": [ { "comment_text": "", "digests": { "md5": "5ffb62ab7e88461428cab99947f54209", "sha256": "9708cf839ec901a97d694b25bdb784323fb73c1f53de6019b35173e110104a23" }, "downloads": -1, "filename": "growler-0.8.0-py3-none-any.whl", "has_sig": false, "md5_digest": "5ffb62ab7e88461428cab99947f54209", "packagetype": "bdist_wheel", "python_version": "3.5", "requires_python": null, "size": 50692, "upload_time": "2016-10-16T15:29:10", "url": "https://files.pythonhosted.org/packages/ef/3a/1f6ed152d483351c03f8613884c043ac9da1ce97dd3fd8c0bad2b5758f00/growler-0.8.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "bb1308d34c797b72aad4b218d55edbc6", "sha256": "01962948788cf665d8e2a1c65a77b278e5c0074a9584823edd15b2335ae5ecc1" }, "downloads": -1, "filename": "growler-0.8.0.tar.gz", "has_sig": false, "md5_digest": "bb1308d34c797b72aad4b218d55edbc6", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 79469, "upload_time": "2016-10-16T15:29:08", "url": "https://files.pythonhosted.org/packages/c5/68/2113dd9e7187ecb50a81f5a206c4aec7ed7093f3f3b76c529a232a7a9ce0/growler-0.8.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "5ffb62ab7e88461428cab99947f54209", "sha256": "9708cf839ec901a97d694b25bdb784323fb73c1f53de6019b35173e110104a23" }, "downloads": -1, "filename": "growler-0.8.0-py3-none-any.whl", "has_sig": false, "md5_digest": "5ffb62ab7e88461428cab99947f54209", "packagetype": "bdist_wheel", "python_version": "3.5", "requires_python": null, "size": 50692, "upload_time": "2016-10-16T15:29:10", "url": "https://files.pythonhosted.org/packages/ef/3a/1f6ed152d483351c03f8613884c043ac9da1ce97dd3fd8c0bad2b5758f00/growler-0.8.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "bb1308d34c797b72aad4b218d55edbc6", "sha256": "01962948788cf665d8e2a1c65a77b278e5c0074a9584823edd15b2335ae5ecc1" }, "downloads": -1, "filename": "growler-0.8.0.tar.gz", "has_sig": false, "md5_digest": "bb1308d34c797b72aad4b218d55edbc6", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 79469, "upload_time": "2016-10-16T15:29:08", "url": "https://files.pythonhosted.org/packages/c5/68/2113dd9e7187ecb50a81f5a206c4aec7ed7093f3f3b76c529a232a7a9ce0/growler-0.8.0.tar.gz" } ] }