API Reference¶
Application Classes¶
- class BaseApplication(version, name)¶
Base application for
ApplicationandRewrite- Parameters:
version – Application version
name – Application name
Added in version 6.4:
nameargument.Changed in version 7.0:
versionandnamearguments must be provided to create an Application.- cliarguments = None¶
A list of
easycli.Argumentoreasycli.SubCommand.
- climain(argv=None)¶
Provide a callable to call as the CLI entry point.
import sys if __name__ == '__main__': sys.exit(app.climain(sys.argv))
You can use this method as the setuptools entry point for Automatic Script Creation
setup.pyfrom setuptools import setup setup( name='foo', ... entry_points={ 'console_scripts': [ 'foo = foo:app.climain' ] } )
See also
- events = None¶
A dictionary to hold registered functions to specific hooks.
- hook(name, *a, **kw)¶
Only way to fire registered hooks.
Hooks can registered by
when()with the name.app.hook('endresponse')
Extra parameters:
*a, **kwwill be passed to event handlers.Normally, users no need to call this method.
- ready()¶
Call the
readyhook().You need to call this method before using the instance as the WSGI application.
Typical usage:
from yhttp.core import Application, text app = Application() @app.route() @text def get(req): return 'Hello World!' if __name__ != '__main__': app.ready()
- settings = None¶
Instance of
pymlconf.Rootas the global configuration instance.
- when(func)¶
Return decorator to registers the
funcintoeventsby its name.Currently these hooks are suuported:
ready
shutdown
endresponse
The hook name will be choosed by the func.__name__, so if you need to aware when
ready()is called write something like this:@app.when def ready(app): ... @app.when def shutdown(app): ... @app.when def endresponse(response): ...
- class Application(version, name)¶
Bases:
BaseApplicationWSGI Web Application.
Instance of this class can be used as a WSGI application.
- Variables:
bodyguard_factory – A factory of
Guardand or it’s subclasses to be used inApplication.bodyguard()to instantiate a new guard for a handler. default:Guard.queryguard_factory – A factory of
Guardand or it’s subclasses to be used inApplication.queryguard()to instantiate a new guard for a handler. default:Guard.routes – A dictionionary to hold the regext routes handler mappings.
- Parameters:
version – Application version
name – Application name
- bodyguard(fields=None, strict=False)¶
A decorator factory to validate HTTP request’s body.
Added in version 5.1.
from yhttp.core import guard as g @app.route() @app.bodyguard(fields=( g.String('foo', length=(1, 8), pattern=r'\d+', optional=True), g.Integer('bar', range=(0, 9), optional=True), ), strict=True) @json() def post(req): ...
This method calls the
bodyguard_factoryto intantiate aGuardclass or it’s subclasses.- Parameters:
fields – A tuple of
Gurad.Fieldsubclass instances to define the allowed fields and field attributes.strict – If
True, it raisesGuard.statuscode_unknownfieldswhen one or more fields are not in the givenfieldsargument.
- delete_route(pattern, verb, flags=0)¶
Delete a route
- Parameters:
pattern – Regular expression to match the routing table.
flags – Regular expression flags. see
re.compile().verb – The HTTP verb to match the routing table.
- queryguard(fields=None, strict=False)¶
A decorator factory to validate the URL’s query string.
Added in version 5.1.
from yhttp.core import guard as g from yhttp.core.multidict import MultiDict def bar(req, field: g.Field, values: MultiDict): return 'bar default value' @app.route() @app.queryguard(fields=( g.String( 'foo', length=(1, 8), pattern=r'\d+', optional=True, default='foo default value', ), g.Integer( 'bar', range=(0, 9), optional=True, default=bar ), ), strict=True) @json() def post(req): ...
This method calls the
queryguard_factoryto intantiate aGuardclass or it’s subclasses.- Parameters:
fields – A tuple of
Gurad.Fieldsubclass instances to define the allowed fields and field attributes.strict – If
True, it raisesGuard.statuscode_unknownfieldswhen one or more fields are not in the givenfieldsargument.
- route(pattern='/', flags=0, verb=None, insert=None, exists='error')¶
Return a decorator to register a handler for given regex pattern.
if
verbisNonethen the function name will used instead.@app.route(r'/.*') def get(req): ...
You can bypass this behavior by passing
verbkeyword argument:@app.route(r'/', verb='get') def somethingelse(req): ...
To catch any verb by the handler use
*.@app.route(r'/', verb='*') def any(req): ...
Regular expression groups will be capture and dispatched as the positional arguments of the handler after
req:@app.route(r'/(\\d+)/(\\w*)') def get(req, id, name): ...
This method returns a decorator for handler fucntions. So, you can use it like:
books = app.route(r'/books/(.*)') @books def get(req, id): ... @books def post(req, id): ...
See also
- Parameters:
pattern – Regular expression to match the request.
flags – Regular expression flags. see
re.compile().verb – If not given then
handler.__name__will be used to match HTYP verb, Use*to catch all verbs.insert – If not given, route will be appended to the end of the
routes. Otherwise it must be an integer indicating the place to insert the new route intoroutesattribute.exists – Tell what to do if route already exists, possible values:
error``(default) and ``removeto remove the existing route before appending and or inserting the new one.
Added in version 2.9:
insertAdded in version 6.1:
exists
- staticdirectory(pattern, directory, default=None, autoindex=True, fallback=None, **kw)¶
Register a directory with a regular expression pattern.
So the files inside the directory are accessible by their names:
app.staticdirectory(r'/foo/', 'physical/path/to/foo')
You you can do:
curl localhost:8080/foo/a.txtSee also
- Parameters:
pattern – Regular expression to match the requests.
directory – Static files are here.
default – if None, the
app.settings.staticdir.default(which default isindex.html) will be used as the default document.autoindex – Automatic directory indexing, default True.
fallback – if
True, theapp.settings.staticdir.fallback(which default isindex.html) will be used as the fallback document if the requested resource was not found. ifstr, the value will be used instead ofapp.settings.staticdir.fallback.
Added in version 2.13: The default and fallback keyword arguments.
Added in version 3.8: The autoindex keyword argument.
- staticfile(pattern, filename, **kw)¶
Register a filename with a regular expression pattern to be served.
app.staticfile(r'/a\.txt', 'physical/path/to/a.txt')
See also
Rewrite Class¶
- class Rewrite(default=None)¶
Bases:
BaseApplicationUseful to route specific requests to other WSGI application.
Added in version 3.2.
import yhttp.core as y root = y.Application() foo = y.Application() bar = y.Application() app = y.Rewrite(default=root) app.route(r'/foo/?', r'/', foo) app.route(r'/bar/?(.*)', r'/b/\1', bar) app.ready() @root.route() def get(req): return 'root' @foo.route() def get(req): return 'foo' @bar.route(r'/b') def get(req): return 'bar'
- Parameters:
default – Fallback application.
- ready()¶
Call the
readyhook().You need to call this method before using the instance as the WSGI application.
Typical usage:
from yhttp.core import Application, text app = Application() @app.route() @text def get(req): return 'Hello World!' if __name__ != '__main__': app.ready()
- route(pattern, repl, handler)¶
Register an application for specific url.
import yhttp.core as y root = y.Application() foo = y.Application() bar = y.Application() app = y.Rewrite(default=root) app.route(r'/foo/([a-z]+)/(\d+)', r'/books/\2/\1', foo) # Add other applications app.ready()
See
re.sub()for more info aboutpatternandreplarguments.- Parameters:
pattern – A regex pattern to match the
environ['PATH_INFO'].repl – URL Rewrite rule, See
re.sub()handler – An instance of
BaseApplication.
- shutdown()¶
Call the
shutdownhook().
Request Class¶
- class Request(app, environ, response)¶
Represent an HTTP request.
Application.__call__()instantiates this class on each call.- body()¶
Reads the request body.
- contentlength()¶
HTTP Request
Content-Lengthheader value.
- contenttype()¶
HTTP Request
Content-Typeheader value without encoding.
- cookies()¶
Return a dictionary representing the HTTP cookie data.
- environ = None¶
WSIG environ dictionary
- files()¶
Return a dictionary representing the submitted files.
Parse multipart form data from the environ dict and return a dictionary with the form-field name as a key(unicode) and
multipart.MultipartPartinstances as value, because the form-field was a file-upload or the value is too big to fit into memory limits.Note
On the first access to this attribute, the
Request.form()attribute will be initialized if any not-file fields are submitted.Added in version 4.0.
- form()¶
Return a
MultiDictrepresenting the submitted HTTP from.Parse form data from the environ dict and return a dictionary with the form-field name as a key(unicode) and lists as values (multiple values per key are possible).
Note
Both urlencoded and multipart are supported.
Note
On the first access to this attribute, the
Request.files()attribute will be initialized. if any file fields are submitted using themultipart/formcontent header.Added in version 2.6: An easy way to get form values is: .. code-block::
req[‘field-name’]
The above expression is the same as: .. code-block:
req.form['field-name']
Changed in version 4.0: The multipart files are not represented by this attribute and will be accessible by
Request.files()instead.Changed in version 4.0: You may get all values for an identical field using:
req.form.getall('field-name')
- fullpath()¶
Request full URI including query string.
- getfiles(relax=False)¶
Return the request body as a
MultiDictobject.This is actualy a wrapper around the
Request.files. but raisesstatuses.lengthrequiredandstatuses.unprocessablecontentinstead of programmatic exceptions ifrelax=False(the default behaviour).if
relax=True, it returnsNoneon any failure.
- getform(relax=False)¶
Return the request body as a
MultiDictobject.This is actualy a wrapper around the
Request.form. but raisesstatuses.lengthrequiredandstatuses.unprocessablecontentinstead of programmatic exceptions ifrelax=False(the default behaviour).if
relax=True, it returnsNoneon any failure.
- getjson(relax=False)¶
Return the request body as a decoded JSON object.
This is actualy a wrapper around the
Request.json. but raisesstatuses.lengthrequiredandstatuses.unprocessablecontentinstead of programmaticujsonexceptions ifrelax=False(the default behaviour).if
relax=True, it returnsNoneon any failure.
- headers()¶
HTTP Request headers set.
see
HeadersMaskclass to figure out how it works.
- json()¶
Return a dictionary representing the submitted JSON document.
Note
Content-Typeheader must beaplication/json.Added in version 4.0.
- path()¶
Request URL without query string and
scheme://domain.ext.
- query()¶
Return A dictionary representing the submitted query string.
- scheme()¶
Return HTTP Request Scheme (http|https).
- verb()¶
HTTP method.
HeadersMask Class¶
- class HeadersMask(environ)¶
A simple proxy over
Request.environ.Useful to get headers by their original name without the
HTTP_prefix, which is the python’s WSGI servers default behavior.@app.route() def get(req): foo = req.headers['foo'] bar = req.headers.get('bar') if 'baz' in req.headers: baz = True ...
Response Class¶
- class Response(app, environ, startresponse)¶
Represent the HTTP response.
Which accessible by
Request.responseinside handlers.- body = None¶
Response body
- charset = None¶
Response encoding,
Nonefor binary
- conclude()¶
Conclude the response.
Calls WSGI start_response callback and encode response body to transfer to the client.
- Returns:
response body
- property contenttype¶
Response content type incuding charset.
- length = None¶
Response content length
- start()¶
Start the response.
Usualy
Applicationcalls this method when response is ready to transfered to user.
- startstream()¶
Start streaming the response.
Transfer data chunk by chunk instead of what
conclude()does.
- status = '200 OK'¶
HTTP Status code
- type = None¶
Response content type without charset.
HeaderSet Class¶
- class HeaderSet(items=None)¶
A mutable case-insensitive ordered dictionary to keep HTTP headers.
@app.route() def get(req): req.response.headers.add('x-foo', 'a', 'b') req.response.headers['x-bar'] = 'bar' req.response.headers += ['x-baz: qux']
MultiDict¶
- class MultiDict(backend=None, *args, **kwargs)¶
A dict that remembers old values for each key.
HTTP headers and query strings may repeat with differing values, such as Set-Cookie. We need to remember all values.
- get(k[, d]) D[k] if k in D, else d. d defaults to None.¶
- keys() a set-like object providing a view on D's keys¶
HTTPStatus Class¶
- class HTTPStatus(code, text, keepheaders=False, headers=None, nobody=False)¶
Base class for all HTTP Exceptions.
- Parameters:
code – HTTP status code.
text – HTTP status text.
keepheaders – If set, appliation keeps the
Response.headerswhen exception is occured.headers – Some extra HTTP headers to be added to the
Response.headerswhen exception is raised.
contenttype decorators¶
- contenttype(contenttype=None, charset=None, dump=None)¶
Yield a decorator to set response content type and encoding.
import json from yhttp.core import contenttype @app.route() @contenttype('application/json', 'utf8', json.dumps) def get(req): return {'foo': 'bar'}
There are ready to use contenttype decorators which can importes from
yhttp.corepackage, like:json().You may create your very own content type decorator by calling this function with desired arguments, for example:
invoice = contenttype('application/pdf', None, dump=makeinvoicepdf) @app.route('/invoices/(\d+)') @invoice def get(req, id): ...
The
json()decorator is created with something like:json = contenttype('application/json', 'utf8', dump=json.dumps)
- Parameters:
contenttype – HTTP Content-Type, example: application/json
charset – Character set, example: utf8
dump – A
callable(body) -> bodyto transform the body to appropriate content type.
- Returns:
decorator for HTTP handlers.
- binary(handler)¶
Sets the
Response.contenttypetoapplication/octet-stream.Handlers must return
byteswhen this decorator is used.from yhttp.core import binary @app.route() @binary def get(req): return b'binarydata'
- json(handler)¶
Sets the
Response.contenttypetoapplication/json;charset=utf-8and encode the returned value by handler to json byte-string format.Handlers must return
dictwhen this decorator is used.from yhttp.core import json @app.route() @json def get(req): return {'foo': 'bar'}
- text(handler)¶
Sets the
Response.contenttypetotext/text; charset=utf-8.Handlers must return
strwhen this decorator is used.Added in version 2.8.
from yhttp.core import text @app.route() @text def get(req): return 'Unicode String'
- html(handler)¶
Sets the
Response.contenttypetotext/html; charset=utf-8.Handlers must return
strwhen this decorator is used.Added in version 2.8.
from yhttp.core import html @app.route() @html def get(req): return 'Unicode String'
gurad Module¶
- class Field(name, optional=False, default=None, callback=None)¶
Base class for all fields such as
String- Parameters:
optional – If
True, theField.statuscode_missingis not raised when the field is not submitted by the client. default:False.default – A scalar or
callable(req, field, valuesdict)as the default value for field if not submitted. this argument cannot passed withoptional. default:None.
- Variables:
statuscode_missing – int, the status code to raise when the field is not submitted by the user when
strict=True. default:400.
Added in version 5.2:
defaultargument.- __call__(*, optional=None, default=None, callback=None, **kwargs)¶
Copy and override the field.
bar = guard.String('bar') @app.route @app.queryguard(( bar, bar(name='baz', optional=True) )) def get(req, *, bar=None, baz=None): ...
- class Guard(fields=None, strict=False)¶
The
guard.Guardclass is used to validate the HTTP requests.see:
Application.bodyguard()for more info.Added in version 5.1.
- Parameters:
strict – If
True, it raisesGuard.statuscode_unknownfieldswhen one or more fields are not in the givenfieldsargument.fields – A tuple of
Gurad.Fieldsubclass instances to define the allowed fields and field attributes.
- Variables:
statuscode_unknownfields – int, the status code to raise when an unknown field(s) is/are found.
- class Integer(name, range=None, **kwargs)¶
Represent the guard for integer field.
- Parameters:
name – str, the field name.
range –
(int, int), a tuple of(min, max)to specify the minimum and maximum allowed value.
- Variables:
statuscode_badtype – int, the status code to raise when the type cast to integer
int(value)is raisesValueError. default:400.statuscode_outofrange – int, the status code to raise when value is not in specified range.
- __call__(*, range=None, **kwargs)¶
Copy and override the field.
bar = guard.String('bar') @app.route @app.queryguard(( bar, bar(name='baz', optional=True) )) def get(req, *, bar=None, baz=None): ...
- class String(name, length=None, pattern=None, **kwargs)¶
Represent the guard for string field.
- Parameters:
name – str, the field name.
length –
(int, int), a tuple of(min, max)to specify the minimum and maximum allowed length for the value.pattern – A regex pattern to specify the data format for the field.
- Variables:
statuscode_badlength – int, the status code to raise when value length is not permitted. default:
400.statuscode_badformat – int, the status code to raise when value format is not match with given pattern. default:
400.
- __call__(*, length=None, pattern=None, **kwargs)¶
Copy and override the field.
bar = guard.String('bar') @app.route @app.queryguard(( bar, bar(name='baz', optional=True) )) def get(req, *, bar=None, baz=None): ...
statuses Module¶
- exception HTTPStatus(code, text, keepheaders=False, headers=None, nobody=False)¶
Base class for all HTTP Exceptions.
- Parameters:
code – HTTP status code.
text – HTTP status text.
keepheaders – If set, appliation keeps the
Response.headerswhen exception is occured.headers – Some extra HTTP headers to be added to the
Response.headerswhen exception is raised.
- badgateway = functools.partial(<class 'yhttp.core.statuses.HTTPStatus'>, 502, 'Bad Gateway')¶
HTTP 502 Bad Gateway exception factory
- badrequest = functools.partial(<class 'yhttp.core.statuses.HTTPStatus'>, 400, 'Bad Request')¶
HTTP 400 Bad Request exception factory
- conflict = functools.partial(<class 'yhttp.core.statuses.HTTPStatus'>, 409, 'Conflict')¶
HTTP 409 Conflict exception factory
- created = functools.partial(<class 'yhttp.core.statuses.HTTPStatus'>, 201, 'Created', keepheaders=True)¶
HTTP 201 Created exception factory
- forbidden = functools.partial(<class 'yhttp.core.statuses.HTTPStatus'>, 403, 'Forbidden')¶
HTTP 403 Forbidden exception factory
- found(location, **kw)¶
HTTP 302 Found exception factory
- gatewaytimeout = functools.partial(<class 'yhttp.core.statuses.HTTPStatus'>, 504, 'Gateway Timeout')¶
HTTP 504 Gateway Timeout exception factory
- gone = functools.partial(<class 'yhttp.core.statuses.HTTPStatus'>, 410, 'Gone')¶
HTTP 410 Gone exception factory
- internalservererror = functools.partial(<class 'yhttp.core.statuses.HTTPStatus'>, 500, 'Internal Server Error')¶
HTTP 500 Internal Server Error exception factory
- lengthrequired = functools.partial(<class 'yhttp.core.statuses.HTTPStatus'>, 411, 'Length Required')¶
HTTP 411 Length Required
- methodnotallowed = functools.partial(<class 'yhttp.core.statuses.HTTPStatus'>, 405, 'Method Not Allowed')¶
HTTP 405 Method Not Allowed exception factory
- movedpermanently(location, **kw)¶
HTTP 301 Moved Permanently exception factory
- nocontent = functools.partial(<class 'yhttp.core.statuses.HTTPStatus'>, 204, 'No Content', keepheaders=True, nobody=True)¶
HTTP 204 No Content exception factory
- notfound = functools.partial(<class 'yhttp.core.statuses.HTTPStatus'>, 404, 'Not Found')¶
HTTP 404 Not Found exception factory
- notmodified = functools.partial(<class 'yhttp.core.statuses.HTTPStatus'>, 304, 'Not Modified', nobody=True)¶
HTTP 304 Not Modified exception factory
- ok = functools.partial(<class 'yhttp.core.statuses.HTTPStatus'>, 200, 'OK', keepheaders=True)¶
HTTP 200 OK
- preconditionfailed = functools.partial(<class 'yhttp.core.statuses.HTTPStatus'>, 412, 'Precondition Failed')¶
HTTP 412 Precondition Failed exception factory
HTTP 503 Service Unavailable exception factory
- status¶
Alias for
HTTPStatus
- statuscode(code)¶
Set the
Response.statustocode.@app.route() @statuscode('201 Created') def post(req): ... with Given(app, verb='POST'): assert status == '201 Created'
Added in version 2.5.
- unauthorized = functools.partial(<class 'yhttp.core.statuses.HTTPStatus'>, 401, 'Unauthorized')¶
HTTP 401 Unauthorized exception factory
- unprocessablecontent = functools.partial(<class 'yhttp.core.statuses.HTTPStatus'>, 422, 'Unprocessable Content')¶
HTTP 422 Unprocessable Content