{ "info": { "author": "Travis Swicegood", "author_email": "development@domain51.com", "bugtrack_url": null, "classifiers": [], "description": "steinie\n=======\nA little framework for doing web applications\n\n\nUsage\n-----\nSteinie is built around the concept of routes. Your application is made up of\none or more routes that guide the web request through your code. Let's start\nwith the simplest of simple, the Hello World web application.\n\n.. code-block:: python\n\n from steinie import Steinie\n app = Steinie()\n\n\n @app.get(\"/\")\n def get(request, response):\n return \"Hello World, from Steinie!\\n\"\n\n\n if __name__ == \"__main__\":\n app.run()\n\n\nYou can run this directly using ``python`` if you save this to a file. This\nstarts up a simple development server on port 5151 that responds to the ``/``\nroute on your local computer. Give it a try.\n\nSteinie uses `Werkzeug`_ for handling its routes. This means all of your\nfamiliar route patterns are available to you inside Steinie.\n\nSteinie has built-in decorators for ``GET`` and ``POST`` along with ``DELETE``,\n``HEAD``, ``INFO``, ``OPTIONS``, ``PATCH``, ``PUT``, and ``TRACE``.\n\n\nDealing with Parameters\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\nAnother common need is to provide parameters to your web application. Lets say\nyou wanted to add a ``username`` to your path, but you wanted it capitalized\n(bear with me for a minute), you can do that with the ``param`` decorator like\nthis:\n\n.. code-block:: python\n\n from steinie import Steinie\n\n app = Steinie()\n\n\n @app.param(\"username\")\n def capitalize(param):\n return param.capitalize()\n\n\n @app.get(\"/\")\n def handler(request, response):\n return \"Hello, %s\\n\" % request.params[\"some_user\"]\n\n\n if __name__ == \"__main__\":\n app.run()\n\nUsing the ``param`` decorator, you specify the name of the parameter you want\nto create, then you provide a function specifying what you want to do. You can\nrun this example, then load ``http://localhost:5151/alice`` and it will respond\nwith \"Hello, Alice!\"\n\nIf you're familiar with Flask's (and by extension, Werkzeug's) converters this\nmight look very familiar. Again, building off of the Werkzeug base, much of\nwhat's provided here mimics what you might already be used to.\n\nNow that you've seen the basic example, imagine instead if your created a\nfunction that loads a user object from your database and returns that. Using\nthe ``params`` decorator, you can start to turn basic parameters from your\nincoming request into something that matches the way you've modeled your actual\napplication.\n\n\nGrouping routes and parameters\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\nYou might be wondering how this scales. A single file with a ton of decorated\nfunctions sound pretty unwieldy to me. Thankfully, Steinie provides a way to\nbreak up your functionality into logical parts through what it calls a\n``Router``.\n\nLet's enhance the example above. Most of what's there relates to users, so\nwe're going to create a new ``Route``, then mount it to ``/user``.\n\nFirst, adjust the import statement so it looks like this:\n\n.. code-block:: python\n\n from steinie import Steinie, Router\n\nNext, create a new ``route`` object from the ``Router`` and adjust your two\ndecorated functions to use that. It should look like this:\n\n.. code-block:: python\n\n route = Router()\n\n\n @route.param(\"username\")\n def capitalize(param):\n return param.capitalize()\n\n\n @route.get(\"/\")\n def handler(request, response):\n return \"Hello, %s\\n\" % request.params[\"some_user\"]\n\n\nFinally, you need to modify your ``app`` object to use this your new route.\nYou do that with the aptly named ``use`` method like this:\n\n.. code-block:: python\n\n app.use(\"/user\", route)\n\nSave your work, fire up your code, then visit your server again. If you try\nto go to ``http://localhost:5151/alice`` again you'll get a 404. Instead, you\nneed to add ``/user`` to the URL so it looks like this:\n``http://localhost:5151/user/alice``.\n\n\nDealing with Middleware\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\nThere's one more part to becoming an expert in Steine: Middleware. Middleware\ngives you a chance to modify the request or response for every incoming request.\n\nLet's continue to build on our example above. Instead of using the ``param``\ndecorator, let's create a middleware that capitalizes all ``some_user``\nparameters.\n\nFirst, let's create the middleware. Steinie expects them to be objects that can\nbe intantiated and provided a ``Router`` instance, then invoked via the\n``__call__`` method. That's it. Add this to your file and then you can say\nyou've created your very own Steinie middleware:\n\n.. code-block:: python\n\n class CapitalizeMiddleware(object):\n def __init__(self, route):\n pass\n\n def __call__(self, request, response, _next):\n if \"some_user\" in request.params:\n new = request.params[\"some_user\"].capitalize()\n request.params[\"some_user\"] = new\n return _next(request, response)\n\nThere's a couple of things to call out here. First, we don't need the ``route``\nprovided at instantiation time, so there's no need to store it. If you did, you\ncould set that as an attribute on the class.\n\nNext up, the ``__call__`` method has three arguments. ``request`` and\n``response`` are familiar from earlier, but ``_next`` is new. This is a\nfunction generated by Steinie that allows the middleware to control what happens\nwhen it's invoked. For our purposes here, we want to modify the ``some_user``\nvalue by capitalizing it when it's present, then continue on. To do that, you\nsimply return the result of ``_next(request, response)``.\n\nThe ability to control what happens here is a key part of Steinie's middleware.\nYou can capture the return value from ``_next`` and do something with it. Use\ncases that jump to mind for me are a ``CacheMiddleware`` that attempts to load\na request from cache and returns that if its found but will allow the request\nto go through if it hasn't been cached.\n\nThis simple example here is just that, pretty simple.\n\nYou're not quite finished with the middleware yet. Next you need to tell your\nrouter to use it. Enter ``router.use`` again:\n\n.. code-block:: python\n\n route.use(CapitalizeMiddleware)\n\nThis is the same method you used to attach a router to an application, but\nthis time there's no route (the first argument you used above) associated with\nit. Providing ``router.use`` with a single argument signals to Steinie that\nyou're giving it a middleware that it should execute when dealing with all\nrequests this router attempts to handle.\n\nThe final modification that you should make is to remove the params function\nand adjust your ``get`` route. When it's finished, it should look like this:\n\n.. code-block:: python\n\n @route.get(\"/\")\n def handler(request, response):\n return \"Hello, %s\\n\" % request.params[\"some_user\"]\n\nNow, re-run your code and access it. You should get the same output, but this\nis a different pattern. What makes one pattern over the other better? Funny\nyou should mention it, that's the next topic.\n\n\nMiddleware vs. Parameters\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\nBoth middleware and parameters can be used to acheive very similar goals, but\nthey have distinct roles.\n\nMiddleware\n These are global and have the chance to modify every incoming request. They\n have the full request and have the ability to circumvent the normal response.\n Use them when you need to modify *every* request that is processed for a given\n route or you need to do more than change part of the request URL to some other\n object.\n\nParameters\n These are localized to routes that have the parameter in the request URL.\n Unlike middleware, all they can do is transform part of a URL into something\n else. They're very useful when translating an ID to an object in the database\n or some other similar transformation, but they won't let you change the\n response that Steinie returns.\n\n\nInspiration\n-----------\nSteinie was inspired in heavily by `Express`_ in the server-side JavaScript\nworld. For the 4.x rewrite, Express started leaning heavily on the router based\nmodel that Steinie uses.\n\n.. _Express: http://expressjs.com/\n.. _Werkzeug: http://werkzeug.pocoo.org/", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "UNKNOWN", "keywords": null, "license": "UNKNOWN", "maintainer": null, "maintainer_email": null, "name": "steinie", "package_url": "https://pypi.org/project/steinie/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/steinie/", "project_urls": { "Download": "UNKNOWN", "Homepage": "UNKNOWN" }, "release_url": "https://pypi.org/project/steinie/1.0.1/", "requires_dist": null, "requires_python": null, "summary": "A little framework for doing web applications", "version": "1.0.1" }, "last_serial": 1498724, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "2f30eba397ff38af5d593745d70b35db", "sha256": "3538e21daca7cd3d97e1ae3c61c65cee76e4944a4b05bf6e0f6cc13361d4010b" }, "downloads": -1, "filename": "steinie-0.1.0.tar.gz", "has_sig": false, "md5_digest": "2f30eba397ff38af5d593745d70b35db", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5848, "upload_time": "2014-07-26T18:51:14", "url": "https://files.pythonhosted.org/packages/1a/69/b14df6f717583ede45afb0f8ae23aa8671e8386bed7d8281020233689155/steinie-0.1.0.tar.gz" } ], "1.0.0": [ { "comment_text": "", "digests": { "md5": "f82f03bdad28ebb16130c30d122f7318", "sha256": "0044d4a21d60217cf98384f92086fa85b535935e82b803b1c4ea450f04a305f3" }, "downloads": -1, "filename": "steinie-1.0.0.tar.gz", "has_sig": false, "md5_digest": "f82f03bdad28ebb16130c30d122f7318", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9986, "upload_time": "2015-04-10T07:03:07", "url": "https://files.pythonhosted.org/packages/2b/f3/d3974608ac89a5f772d01ea9f48d9a8aabb954ca7f25d900538f6b17c74d/steinie-1.0.0.tar.gz" } ], "1.0.1": [ { "comment_text": "", "digests": { "md5": "e169276880c689cff281b744225e0b68", "sha256": "6116e6b5674c4da71f896268f8f7d497b810fc72e3bb1bd64c0ef35eaca59307" }, "downloads": -1, "filename": "steinie-1.0.1.tar.gz", "has_sig": false, "md5_digest": "e169276880c689cff281b744225e0b68", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10006, "upload_time": "2015-04-10T07:06:32", "url": "https://files.pythonhosted.org/packages/78/dd/3b82275492a6ed6999cb0e652734f31717b1d8320185e0ea4c794725fa80/steinie-1.0.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "e169276880c689cff281b744225e0b68", "sha256": "6116e6b5674c4da71f896268f8f7d497b810fc72e3bb1bd64c0ef35eaca59307" }, "downloads": -1, "filename": "steinie-1.0.1.tar.gz", "has_sig": false, "md5_digest": "e169276880c689cff281b744225e0b68", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10006, "upload_time": "2015-04-10T07:06:32", "url": "https://files.pythonhosted.org/packages/78/dd/3b82275492a6ed6999cb0e652734f31717b1d8320185e0ea4c794725fa80/steinie-1.0.1.tar.gz" } ] }