{ "info": { "author": "Daniel Furtado", "author_email": "daniel@dfurtado.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 2 - Pre-Alpha", "Environment :: Web Environment", "Intended Audience :: Developers", "License :: OSI Approved :: GNU General Public License v3 (GPLv3)", "Natural Language :: English", "Operating System :: MacOS :: MacOS X", "Operating System :: Microsoft :: Windows", "Operating System :: POSIX", "Operating System :: Unix", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3 :: Only" ], "description": "[![Build Status](https://travis-ci.org/dfurtado/pyterrier.svg?branch=master)](https://travis-ci.org/dfurtado/pyterrier)\n[![pypi](https://img.shields.io/pypi/v/pyterrier.svg)](https://pypi.python.org/pypi/pyterrier)\n\n\n# PyTerrier\n\nThis project has started out of my curiosity to understand how web frameworks work under the hood, to study\nclosely the http module and also the feel that the Python community need to have frameworks written in Python 3, so\nwe can take advantage of all its neat features. PyTerrier is highly inspired by frameworks like Flask, Django and Microsoft's Web API.\n\n## Highlight features\n\n- Written in Python 3.7\n- Favorite conventions over configuration\n- Value simple code\n- Flexible\n- Provide a clean project structure\n\n## Quick start\n\nThe quickest way to get started is to install PyTerrier on a virtual environment and use the PyTerrier CLI to create a\nnew project:\n\n1. Create a new directory for your application\n\n```shell\nmkdir myapp && cd myapp\n```\n\n2. Create a virtual environment (make sure that you have Python 3.6 or greater)\n\n```\npipenv --three\n```\n\n3. Activate the virtual environment\n\n```shell\npipenv shell\n```\n\n3. Install Pyterrier\n\n```shell\npipenv install pyterrier\n```\n\n### Creating your first application\n\nNow that the PyTerrier is installed you can use the CLI to create our first application, execute the command below:\n\n```shell\npyterrier --newapp myapp --currentdir\n```\n\nThe `--newapp` option especify the name of you application, the option `--currentdir` is used when you want the CLI to create the\napplication files in our current directory, without this option the CLI will create a directory with the same name of your application\nand create the files in there.\n\nThat's it, you done!\n\nBy default, the application will run on the port 8000. Just open up your browser and go to http://localhost:8000\n\nTo get a full description of the options available in the Pyterrier CLI you can use the `--help` option like so `pyterrier --help` and you should see the output below:\n\n```text\nUsage: pyterrier [OPTIONS]\n\nOptions:\n --currentdir Create the app on the current directory.\n --newapp NAME Name of the new app.\n --newcontroller NAME Name of the new controller.\n --help Show this message and exit.\n```\n\n## Show me some code!!\n\nPyTerrier favorite conventions over configurations, so the project need to follow a certain structure to work, for instance, a minimum bare bone PyTerrier application would have the following structure:\n\n```text\napp\n\u251c\u2500\u2500 app.py\n\u251c\u2500\u2500 controllers\n\u251c\u2500\u2500 static\n\u2514\u2500\u2500 templates\n```\n\n| Item| Description |\n|:------|:-------------|\n|app| It's the root of the application, obviously it can be any name you like|\n|app.py| This is the application's entry point, there you can initialize the application and register routes|\n|controllers| The `controllers`directory will be the place files containing your actions|\n|static| The `static`directory is where you can place all the static assets of your application. CSS, JavaScript, Images, Fonts...|\n|templates| This is the folder where Pyterrier will lookup for templates to render|\n\n\nA very simple PyTerrier application would look a bit like this:\n\n``` python\nfrom pyterrier import PyTerrier\nfrom pyterrier.http import ViewResult\n\napp = PyTerrier(port=3000)\n\n@app.get('/sayhello')\ndef sayhello(self):\n return ViewResult('index.html', { 'message': 'Hellooooo!' })\n\napp.run()\n\n```\n\nThis code will start a server running on the port 3000 and it will define a function that will be executed when a GET request to `/sayhello` is made.\n\nThe `sayhello` function will return a `ViewResult` which will get a template, the context and render it using the template engine of your choice. By default, PyTerrier uses Jinja2.\n\nLet's have a look how the template looks like.\n\nTo avoid repeating HTML code we have a base file.\n\n``` html\n\n \n \n \n

My first PyTerrier application

\n {% block content %}\n {% endblock %}\n \n\n```\n\nThen we have content html called `index.html`\n\n``` html\n{% extends \"base.html\" %}\n\n{% block content %}\n {{message}}\n{% endblock %}\n\n```\nOne thing to notice here is that every function in `PyTerrier` have a first argument `self`. Self is a reference to the\nfunction itself and expose a property called `request` which is (as the name says) information about the request that has been\nperformed. The `Request` object exposes the request path, the parameters and header values.\n\nNow let's say we want to pass a parameter in the URL, you achieve that using a parameter placeholder:\n\n``` python\nfrom pyterrier import PyTerrier\nfrom pyterrier.http import ViewResult\n\n\napp = PyTerrier(port=3000)\n\n@app.get(\"/sayhello/to/{name:str}\")\ndef sayhello(self, name):\n return ViewResult(\"index.html\", { \"message\": f\"Hellooooo, {name}!\" })\n\napp.run()\n```\nWhen a GET request is made to `/sayhello/to/daniel`, the HTML content containg the message `Hellooooo, daniel!` will be returned.\n\nAt the moment only `str` and `int` parameter placeholders are supported.\n\nTo return a HTTP/200 response with the results, you can use the `Ok` function.\n\n``` python\nfrom pyterrier import PyTerrier\nfrom pyterrier.http import Ok, NotFound\n\n\napp = PyTerrier(port=3000)\n\n@app.get('/api/user/{id:int}')\ndef get(self, id):\n user = user_repository.get(id)\n\n if user == None:\n return NotFound()\n\n return Ok(user)\n\napp.run()\n```\n\nNow, there are situations that it's not viable to keep all the api endpoints in a single file. By convention PyTerrier looks for actions registered in files inside the `controllers` folder in the application's root.\nWith that said, we can create a new folder called `controllers` and inside of that folder we can create a file called `userController.py` with the following contents:\n\n``` python\nfrom pyterrier import PyTerrier\nfrom pyterrier.http import Ok, NotFound, get\n\n\napp = PyTerrier(port=3000)\n\n@get(\"/get/{id:int}\")\ndef get(self, id):\n user = user_repository.get(id)\n\n if user == None:\n return NotFound()\n\n return Ok(user)\n\napp.run()\n```\n\nWe also need to perform some changes in the application's main file, like so:\n\n``` python\nfrom pyterrier import PyTerrier\n\n\napp = PyTerrier(port=3000)\n\napp.init_routes(prefix_routes=True)\napp.run()\n```\n\nThe code is very similar with what we had before but now we are calling the method `init_routes`. This method will lookup\nall the files in the `controllers` directory and register all the actions that it finds. Additionally, the argument `prefix_routes` is set to `True` meaning that it will prefix the route with the controller prefix. For instance, the route that we just registered in the `userController` file is `/get/{id:int}` with the `prefix_routes` set to `True` it will become `/user/get/{id:int}`.\n\n## Posting data to the server\n\nPerforming a POST request is as simple as GET. It is only needed to import the `@post` decorator and\nget the request data out of `self.request.params`:\n\n```python\nfrom pyterrier.http import Ok, post\n\n\n@post(\"/add\")\ndef add(self):\n\n id, name, email = self.request.params\n\n \"\"\" Update the user \"\"\"\n\n return Ok()\n\n```\n\n## PUT request\n```python\nfrom pyterrier.http import Ok, put\n\n\n@put(\"/update\")\ndef update(self):\n\n id, name, email = self.request.params\n\n \"\"\" Update the user \"\"\"\n\n return Ok()\n\n```\n\n## Delete request\n\n```python\nfrom pyterrier.http import Ok, delete\n\n\n@delete(\"/user/{id:int}/delete\")\ndef delete(self, id):\n deleted = user_repository.delete(id)\n return Ok()\n\n```\n\n## Contributing to the project\n\nSee [CONTRIBUTING.md](contributing.md) for more details.\n\n## Copyright and License\n\nCopyright (c) 2017 [Daniel Furtado](https://twitter.com/the8bitcoder). Code released under [BSD 3-clause license](LICENSE)\n\n## Credits\n\nThis package was created with [Cookiecutter](https://github.com/audreyr/cookiecutter) and the [audreyr/cookiecutter-pypackage](https://github.com/audreyr/cookiecutter-pypackage) project template.\n\n\n# History\n\n### 0.1.4 (2018-10-29)\n\n* Documentation fixes.\n\n### 0.1.3 (2018-10-26)\n\n* Documentation fixes.\n\n### 0.1.2 (2018-10-26)\n\n* Documentation fixes.\n\n### 0.1.0 (2018-10-26)\n\n* First release on PyPI.\n\n\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/dfurtado/pyterrier", "keywords": "pyterrier web webdevelopment rest webframework", "license": "GNU General Public License v3", "maintainer": "", "maintainer_email": "", "name": "pyterrier", "package_url": "https://pypi.org/project/pyterrier/", "platform": "", "project_url": "https://pypi.org/project/pyterrier/", "project_urls": { "Homepage": "https://github.com/dfurtado/pyterrier" }, "release_url": "https://pypi.org/project/pyterrier/0.1.4/", "requires_dist": [ "Click (>=6.0)", "jinja2 (>=2.10)" ], "requires_python": "", "summary": "The simplest web framework you will ever use", "version": "0.1.4" }, "last_serial": 4426625, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "125e12b3bd3ac20778e1fa7e8c72e632", "sha256": "869ac36517129c7429ff930c3a5c34d61bf146fedeaec452a914e520caed9492" }, "downloads": -1, "filename": "pyterrier-0.1.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "125e12b3bd3ac20778e1fa7e8c72e632", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 23313, "upload_time": "2018-10-26T11:12:42", "url": "https://files.pythonhosted.org/packages/8a/2b/78c8538ca2aa3953869d5ec942bb8b3fe8862c756a52bee56dd5e9d35e40/pyterrier-0.1.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "df6837884bbf35f0f03f25fc75561f7a", "sha256": "e15e5c02d39e6311319e5ad349ee1d37a3bdf54762891a0c36327d6dae1a96ed" }, "downloads": -1, "filename": "pyterrier-0.1.0.tar.gz", "has_sig": false, "md5_digest": "df6837884bbf35f0f03f25fc75561f7a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 19910, "upload_time": "2018-10-26T11:12:44", "url": "https://files.pythonhosted.org/packages/fe/bc/e1320b48fcf7e4bf2245d25de8a869bc06de0f35e922c063a2423d9898f0/pyterrier-0.1.0.tar.gz" } ], "0.1.2": [ { "comment_text": "", "digests": { "md5": "1a998aad9d1c53d75fdfca29f98a80cc", "sha256": "d2493b90c72d0de7f957e0e50e729c36018bfba10850d9214d2db3727751a705" }, "downloads": -1, "filename": "pyterrier-0.1.2-py3-none-any.whl", "has_sig": false, "md5_digest": "1a998aad9d1c53d75fdfca29f98a80cc", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 23447, "upload_time": "2018-10-26T18:28:32", "url": "https://files.pythonhosted.org/packages/9b/5e/d5ab42b0a9c0048a3899d152849588a25ccb40a8964768b2b530fc65dc49/pyterrier-0.1.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "d47b79723b697052738096c2daac3e7c", "sha256": "ad1c52837a8802813ea21d2340044686ca9c3f2615a4d7f173e760ba85df8c38" }, "downloads": -1, "filename": "pyterrier-0.1.2.tar.gz", "has_sig": false, "md5_digest": "d47b79723b697052738096c2daac3e7c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 20298, "upload_time": "2018-10-26T18:28:33", "url": "https://files.pythonhosted.org/packages/23/d2/0995542a577a4f65d7d862462f126ec39da8dbd2adc1f02fa9fa0533cb20/pyterrier-0.1.2.tar.gz" } ], "0.1.3": [ { "comment_text": "", "digests": { "md5": "fd21fcb3c9f67d7dfe4c50be39798076", "sha256": "dd2a8a40fb359c2bce0e4696b2d26a641625e91cf1542e3137c972b8d1f5b75c" }, "downloads": -1, "filename": "pyterrier-0.1.3-py3-none-any.whl", "has_sig": false, "md5_digest": "fd21fcb3c9f67d7dfe4c50be39798076", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 23440, "upload_time": "2018-10-26T18:40:35", "url": "https://files.pythonhosted.org/packages/73/5d/44bde5264d032b9c9d798bd993d091c8da624cd1b85213f5a6a71df8731d/pyterrier-0.1.3-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "e2b6cccee1af47f233b92e8ecae9f8bb", "sha256": "d1aa8e05bdc715b979ab8305a063bb52d4757b2da5953157fad43f990988c8a2" }, "downloads": -1, "filename": "pyterrier-0.1.3.tar.gz", "has_sig": false, "md5_digest": "e2b6cccee1af47f233b92e8ecae9f8bb", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 20296, "upload_time": "2018-10-26T18:40:37", "url": "https://files.pythonhosted.org/packages/20/b7/c6a7ea65859516cbe8cc2a5cfc09f7fb0245e5cffa78d21398996307a6fc/pyterrier-0.1.3.tar.gz" } ], "0.1.4": [ { "comment_text": "", "digests": { "md5": "a3911080b6ca7d54d450563c8e9635f7", "sha256": "0365e2e23b1b60f15c333dcf85ad02827a4f90c384056f2c28b4e600db0943c0" }, "downloads": -1, "filename": "pyterrier-0.1.4-py3-none-any.whl", "has_sig": false, "md5_digest": "a3911080b6ca7d54d450563c8e9635f7", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 23468, "upload_time": "2018-10-29T08:12:42", "url": "https://files.pythonhosted.org/packages/a3/cd/e66925a1464fc69ee71011e8a4d5d27b019a8e426786154dfd46e7cca62f/pyterrier-0.1.4-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "1693fd34a946f9c41809df820523d0b9", "sha256": "edd4fc65d6a97f6ab9914f4c1597e197a1a412e187cccf5beaea0fd22f7df687" }, "downloads": -1, "filename": "pyterrier-0.1.4.tar.gz", "has_sig": false, "md5_digest": "1693fd34a946f9c41809df820523d0b9", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 20351, "upload_time": "2018-10-29T08:12:44", "url": "https://files.pythonhosted.org/packages/21/66/bb4975c9311b97df2a0dbf0e0e7c24a11a4edacfac7cc154d59874f28378/pyterrier-0.1.4.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "a3911080b6ca7d54d450563c8e9635f7", "sha256": "0365e2e23b1b60f15c333dcf85ad02827a4f90c384056f2c28b4e600db0943c0" }, "downloads": -1, "filename": "pyterrier-0.1.4-py3-none-any.whl", "has_sig": false, "md5_digest": "a3911080b6ca7d54d450563c8e9635f7", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 23468, "upload_time": "2018-10-29T08:12:42", "url": "https://files.pythonhosted.org/packages/a3/cd/e66925a1464fc69ee71011e8a4d5d27b019a8e426786154dfd46e7cca62f/pyterrier-0.1.4-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "1693fd34a946f9c41809df820523d0b9", "sha256": "edd4fc65d6a97f6ab9914f4c1597e197a1a412e187cccf5beaea0fd22f7df687" }, "downloads": -1, "filename": "pyterrier-0.1.4.tar.gz", "has_sig": false, "md5_digest": "1693fd34a946f9c41809df820523d0b9", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 20351, "upload_time": "2018-10-29T08:12:44", "url": "https://files.pythonhosted.org/packages/21/66/bb4975c9311b97df2a0dbf0e0e7c24a11a4edacfac7cc154d59874f28378/pyterrier-0.1.4.tar.gz" } ] }