API¶
Gate¶
-
class
poort.
Gate
¶ Gate is a local storage container (DI of some sorts).
You should extend this class and provide extra methods and properties that you use throughout your application.
import poort gate = poort.Gate() def application(environ, start_response): with gate(environ): request = gate.request if request.path == '/': response = poort.Response('Hallo world!') else: response = poort.Response('Not found.', status_code=404) return response(request, start_response)
How to extend poort.Gate
import poort class Gate(poort.Gate): def setup(self, environ, *args, **kwargs): super(Gate, self).setup(environ, *args, **kwargs) dbname = 'test-app' self.attach('database', Database(dbname)) @property def database(self): ''':rtype: Database''' return self.retrieve('database') gate = Gate() def application(environ, start_response): with gate(environ): request = gate.request database = gate.database if request.path == '/': response = poort.Response('Hallo world!') else: response = poort.Response('Not found.', status_code=404) return response(request, start_response)
Request¶
-
class
poort.
Request
(environ)¶ A request wrapper.
Parameters: - host (str) – Hostname of the request.
- path (str) – Request part of the URI.
- method (str) – Request method (like GET, POST, PUT).
- ssl (bool) – Check if the request was made over HTTPS.
- ip_address (str | None) – IPAddress of the remote user.
- accept_type (str) – Accept header (eg. application/json).
- content_type (str) – Content-Type header (eg. multipart/form-data).
- query (dict) – Query part of the URI (?foo=bar).
- form (dict) – Form part of the Request (foo=bar).
- files (dict[str, poort.utils.FileStorage]) – Files part of the Request, removed from form.
- cookies (dict) – Cookies of the Request.
- json (dict | None) – JSON part of the Request (content_type is application/json).
- params (dict) – All params (query, form, files, cookies, json) combined.
- environ (dict) – The original environ.
import poort def application(environ, start_response): request = poort.Request(environ) if request.path == '/': response = poort.Response('Hallo world!') else: response = poort.Response('Not found.', status_code=404) return response(request, start_response)
Retrieve cookie from the request.
This matches with the api of poort.Response, this provides response.set_cookie and response.del_cookie.
Parameters: - name (str) – Name of the cookie.
- default (str | None) – Default when the cookie is not set.
Return type: str | None
Response¶
-
class
poort.
Response
(body='', headers=None, status_code=200)¶ A response wrapper.
Parameters: import poort def application(environ, start_response): request = poort.Request(environ) response = poort.Response('Hallo world!') return response(request, start_response)
Add a cookie to the response.
Parameters: - name (str) – Name of the cookie.
- value (str) – Value of the cookie (should always be a string).
- max_age (int | None) – Maximum age (leave None for “browser session”).
- path (str) – Path to bind the cookie to [default ‘/’].
- domain (str | None) – Domain to bind the cookie to [default None].
- secure (bool) – Secure the cookie [default False], handy: request.ssl.
- httponly (bool) – Cookie not accessable by JavaScript [default true].
Delete a cookie from the browser.
Parameters: Note
Take note that you must match the original settings of the cookie. Deleting a cookie with a non-matching path will not work.
-
__call__
(request, start_response)¶ Respond to WSGI with the current settings.
Parameters: - request (poort.Request) – Request that was made, None is allowed.
- start_response (callable) – Handler provided by WSGI.
-
get_body
()¶ Retrieve the body of the response.
You can override this method to serialize JSON, for example, and return this as the body.
Return type: str
-
prepare_response
(request=None)¶ Prepare the response.
This prepares (encodes) the body, you can override this method to add/override headers when the response is being prepared.
To yield other content, you should look at get_body.
Parameters: request (poort.Request) – Request that was made, None is allowed. Return type: str
-
respond
(request)¶ Prepare a tuple to respond with.
Parameters: request (poort.Request) – Request that was made, None is allowed. Return type: tuple[str, list[str], str]
-
class
poort.
JsonResponse
(data, headers=None, status_code=200)¶ A response wrapper for JSON results.
Automaticly sets the Content-Type to application/json and transforms your data when the response is prepared. Override json_default to provide your own default transformations.
It automaticly handles datetime, date,, Decimal, FileStorage, items with .to_dict(), items that can be iterated and items with __str__. When this fails, it simple calls repr on the item, it will not raise an Exception when it cannot handle formatting the item.
Parameters: import poort def get_some_information(): return poort.JsonResponse({ 'status': 'ok', 'data': { 'some': 'Data here.' } })
-
class
poort.
HtmlResponse
(body, headers=None, status_code=200)¶ A response wrapper for HTML results.
Automaticly sets the Content-Type to text/html
Parameters: import poort def get_some_information(): return poort.HtmlResponse(''' <html> <head> <title>Hello</title> </head> <body> <p>Hello, this is some HTML.</p> </body> </html> ''')
-
class
poort.
TemplateResponse
(filename, context, headers=None, status_code=200)¶ A templated wrapper for HTML results.
Automaticly sets the Content-Type to text/html. This uses the staticly bound renderer (a Jinja2 environment by default) to render your HTML.
Parameters: Variables: renderer (jinja2.Environment) – Template renderer.
import poort poort.TemplateResponse.configure('./templates') def get_some_information(): return poort.TemplateResponse('index.html', {'name': 'World'})
<!-- templates/index.html --> <html> <head> <title>Hallo</title> </head> <body> <p>Hallo {{ name }}!</p> </body> </html>
-
class
poort.
WrappedTemplateResponse
(template, context, headers=None, status_code=200, base_template=None)¶ A wrapping templated wrapper for HTML results.
Automaticly sets the Content-Type to text/html. You can use this class to have a wrapper around your template. It extends TemplateResponse and works in the same manner, except it also renders a base_template and injects the rendered template into it as the body.
Parameters: import poort poort.WrappedTemplateResponse.configure('./templates') poort.WrappedTemplateResponse.BASE_TEMPLATE = 'base.html' def get_some_information(): return poort.TemplateResponse('index.html', { 'name': 'World', 'scripts': ['/assets/scripts/jquery.min.js', '/assets/scripts/bootstrap.min.js'], 'styles': ['/assets/styles/bootstrap.min.css'], })
<!-- templates/index.html --> {% do scripts.append('/assets/scripts/index.js') %} <p>Hallo {{ name }}!</p>
<!-- templates/base.html --> <html> <head> <title>Hallo</title> {% for style in context.styles %} <link href="{{ style }}" rel="stylesheet"> {% endfor %} </head> <body> {{ body }} {% for script in context.scripts %} <script src="{{ script }}"> {% endfor %} </body> </html>
Note
This is a work-around for mutating scripts and styles (among other things) while rendering a page. By mutating the original context, the base template can use the updated variables. If you simply want to render templates without this functionality, simply use TemplateResponse as the simple extending result can be achieved using {% extend ‘base.html’ %}.
-
class
poort.
FileResponse
(filename, as_attachment=False, cache_timeout=43200, headers=None, status_code=200)¶ A file wrapper response.
This will send a file to the requester. The Content-Type will be guessed, it will also set the Content-Length and Last-Modified information based on the file.
You can enable caching by providing the request when delivering the response and by setting the cache_timeout.
Parameters: - filename (str) – Filename you want to sent, absolute is preferred.
- as_attachment (bool | str) – Send the file as an attachment, True will use the basename of filename, set it to a str (‘download.csv’) to determine the attachment name yourself.
- cache_timeout (int) – How long should the result be cached [default 43200, 12 hours).
- headers (werkzeug.datastructures.Headers | list) – A list of extra headers, be warned that some headers may be overridden.
- status_code (int) – Status-Code of the response [default 200].
Variables: attachment_filename (str) – Name of the attachment.
import poort def get_some_information(): return poort.FileResponse('cached-123456789-download.csv', 'download-name-here.csv') def application(environ, start_response): request = poort.Request(environ) response = get_some_information() return response(request, start_response)
See also
For passing the request variable:
Response.__call__()
-
mtime
¶ Modified datetime of the file.
Return type: datetime.datetime
-
poort.
template_or_json_response
(request, template, context, headers=None, status_code=200, template_response_class=None, json_response_class=None)¶ Return a JSON or HTML response, based on the request.
When called, it checks the Request.want_json variable. Based on this outcome a template_response_class or a json_response_class is spawned.
Parameters: - request (poort.Request) – Request of the caller.
- template (str) – The filename of the template.
- context (dict) – Context that should be passed.
- headers (werkzeug.datastructures.Headers | list) – A list of extra headers, be warned that some headers may be overridden.
- status_code (int) – Status-Code of the response [default 200].
- template_response_class (callable | None) – Which template response class should be
used [default
TemplateResponse
]. - json_response_class (callable | None) – Which JSON response class should be
used [default
JsonResponse
].
import poort import poort.template_or_json_response as toj def get_some_information(request): return toj(request, 'user.html', { 'id': 44, 'email': 'j.doe@example.com', 'first': 'John', 'last': 'Doe', }) def application(environ, start_response): request = poort.Request(environ) response = get_some_information(request) return response(request, start_response)
-
poort.
wrapped_template_or_json_response
(request, template, context, headers=None, status_code=200, template_response_class=None, json_response_class=None)¶ Return a JSON or HTML response, based on the request.
When called, it checks the Request.want_json variable. Based on this outcome a template_response_class or a json_response_class is spawned.
Parameters: - request (poort.Request) – Request of the caller.
- template (str) – The filename of the template.
- context (dict) – Context that should be passed.
- headers (werkzeug.datastructures.Headers | list) – A list of extra headers, be warned that some headers may be overridden.
- status_code (int) – Status-Code of the response [default 200].
- template_response_class (callable | None) – Which template response class should be
used [default
WrappedTemplateResponse
]. - json_response_class (callable | None) – Which JSON response class should be
used [default
JsonResponse
].
import poort import poort.wrapper_template_or_json_response as wtoj def get_some_information(request): return wtoj(request, 'user.html', { 'id': 44, 'email': 'j.doe@example.com', 'first': 'John', 'last': 'Doe', }) def application(environ, start_response): request = poort.Request(environ) response = get_some_information(request) return response(request, start_response)
CLI¶
-
poort.cli.
start
()¶ Start a server for your app.
Parameters: poort start --environ production poort status
-
poort.cli.
stop
()¶ Stop the server.
Parameters: graceful (bool) – Graceful or forceful (–quick). poort stop
-
poort.cli.
reload
()¶ Reload the server.
poort reload
-
poort.cli.
scale
()¶ Scale the workers of server up or down.
Parameters: poort scale --way up --amount 2
-
poort.cli.
status
()¶ Show a status screen (refreshing) of the server.
The status screen shows information about the workers and gives you some shortcut keys to handle the server (quit, upscale, download, reload). It also shows the last couple of lines from the server error log.
Parameters: - watch – Keep watching
- amount (int) – The amount of workers to scale.
poort status
Output example:
test-poort-two Running with 2 workers (default is 2) Name PID CPU Mem ---------------------------------------- Master 27309 0.0% 8.1M Worker 1 27316 0.3% 36.8M Worker 2 27319 0.3% 36.6M Waiting... -- (q)uit (u)pscale (d)ownscale (r)eload [2016-06-30 13:54:13] [26806] [INFO] Worker exiting (pid: 26806) [2016-06-30 13:54:13] [26805] [INFO] Worker exiting (pid: 26805) [2016-06-30 13:54:13] [26831] [INFO] Booting worker with pid: 26831 [2016-06-30 13:54:13] [26832] [INFO] Booting worker with pid: 26832
Warning
This is a very curde program, do not mash a key!