Package: pyterrier
PyTerrierThis project has started out of my curiosity to understand how web frameworks work under the hood, to study
closely the http module and also the feel that the Python community need to have frameworks written in Python 3, so
we can take advantage of all its neat features. PyTerrier is highly inspired by frameworks like Flask, Django and Microsoft's Web API.Highlight featuresWritten in Python 3.7Favorite conventions over configurationValue simple codeFlexibleProvide a clean project structureQuick startThe quickest way to get started is to install PyTerrier on a virtual environment and use the PyTerrier CLI to create a
new project:Create a new directory for your applicationmkdirmyapp&&cdmyappCreate a virtual environment (make sure that you have Python 3.6 or greater)pipenv --threeActivate the virtual environmentpipenvshellInstall PyterrierpipenvinstallpyterrierCreating your first applicationNow that the PyTerrier is installed you can use the CLI to create our first application, execute the command below:pyterrier--newappmyapp--currentdirThe--newappoption especify the name of you application, the option--currentdiris used when you want the CLI to create the
application files in our current directory, without this option the CLI will create a directory with the same name of your application
and create the files in there.That's it, you done!By default, the application will run on the port 8000. Just open up your browser and go tohttp://localhost:8000To get a full description of the options available in the Pyterrier CLI you can use the--helpoption like sopyterrier --helpand you should see the output below:Usage: pyterrier [OPTIONS]

Options:
  --currentdir          Create the app on the current directory.
  --newapp NAME         Name of the new app.
  --newcontroller NAME  Name of the new controller.
  --help                Show this message and exit.Show me some code!!PyTerrier 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:app
├── app.py
├── controllers
├── static
└── templatesItemDescriptionappIt's the root of the application, obviously it can be any name you likeapp.pyThis is the application's entry point, there you can initialize the application and register routescontrollersThecontrollersdirectory will be the place files containing your actionsstaticThestaticdirectory is where you can place all the static assets of your application. CSS, JavaScript, Images, Fonts...templatesThis is the folder where Pyterrier will lookup for templates to renderA very simple PyTerrier application would look a bit like this:frompyterrierimportPyTerrierfrompyterrier.httpimportViewResultapp=PyTerrier(port=3000)@app.get('/sayhello')defsayhello(self):returnViewResult('index.html',{'message':'Hellooooo!'})app.run()This 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/sayhellois made.Thesayhellofunction will return aViewResultwhich will get a template, the context and render it using the template engine of your choice. By default, PyTerrier uses Jinja2.Let's have a look how the template looks like.To avoid repeating HTML code we have a base file.<html><head></head><body><h1>My first PyTerrier application</h1>{% block content %}
        {% endblock %}</body></html>Then we have content html calledindex.html{% extends "base.html" %}

{% block content %}
    {{message}}
{% endblock %}One thing to notice here is that every function inPyTerrierhave a first argumentself. Self is a reference to the
function itself and expose a property calledrequestwhich is (as the name says) information about the request that has been
performed. TheRequestobject exposes the request path, the parameters and header values.Now let's say we want to pass a parameter in the URL, you achieve that using a parameter placeholder:frompyterrierimportPyTerrierfrompyterrier.httpimportViewResultapp=PyTerrier(port=3000)@app.get("/sayhello/to/{name:str}")defsayhello(self,name):returnViewResult("index.html",{"message":f"Hellooooo,{name}!"})app.run()When a GET request is made to/sayhello/to/daniel, the HTML content containg the messageHellooooo, daniel!will be returned.At the moment onlystrandintparameter placeholders are supported.To return a HTTP/200 response with the results, you can use theOkfunction.frompyterrierimportPyTerrierfrompyterrier.httpimportOk,NotFoundapp=PyTerrier(port=3000)@app.get('/api/user/{id:int}')defget(self,id):user=user_repository.get(id)ifuser==None:returnNotFound()returnOk(user)app.run()Now, 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 thecontrollersfolder in the application's root.
With that said, we can create a new folder calledcontrollersand inside of that folder we can create a file calleduserController.pywith the following contents:frompyterrierimportPyTerrierfrompyterrier.httpimportOk,NotFound,getapp=PyTerrier(port=3000)@get("/get/{id:int}")defget(self,id):user=user_repository.get(id)ifuser==None:returnNotFound()returnOk(user)app.run()We also need to perform some changes in the application's main file, like so:frompyterrierimportPyTerrierapp=PyTerrier(port=3000)app.init_routes(prefix_routes=True)app.run()The code is very similar with what we had before but now we are calling the methodinit_routes. This method will lookup
all the files in thecontrollersdirectory and register all the actions that it finds. Additionally, the argumentprefix_routesis set toTruemeaning that it will prefix the route with the controller prefix. For instance, the route that we just registered in theuserControllerfile is/get/{id:int}with theprefix_routesset toTrueit will become/user/get/{id:int}.Posting data to the serverPerforming a POST request is as simple as GET. It is only needed to import the@postdecorator and
get the request data out ofself.request.params:frompyterrier.httpimportOk,post@post("/add")defadd(self):id,name,email=self.request.params""" Update the user """returnOk()PUT requestfrompyterrier.httpimportOk,put@put("/update")defupdate(self):id,name,email=self.request.params""" Update the user """returnOk()Delete requestfrompyterrier.httpimportOk,delete@delete("/user/{id:int}/delete")defdelete(self,id):deleted=user_repository.delete(id)returnOk()Contributing to the projectSeeCONTRIBUTING.mdfor more details.Copyright and LicenseCopyright (c) 2017Daniel Furtado. Code released underBSD 3-clause licenseCreditsThis package was created withCookiecutterand theaudreyr/cookiecutter-pypackageproject template.History0.1.5 (2021-04-26)Added warning message when executing the pyterrier.init()0.1.4 (2018-10-29)Documentation fixes.0.1.3 (2018-10-26)Documentation fixes.0.1.2 (2018-10-26)Documentation fixes.0.1.0 (2018-10-26)First release on PyPI.