neat is a WSGI micro framework that encourages API-centric development of web applications. The framework is especially compatible with REST services and APIs, though it can conceivably be used for more or less anything. Applications implemented with neat are easy to test and produce data that is easy for clients to consume.
You can install the latest stable version of neat using pip:
$ pip install neat
Public repositories for the project are hosted at github and bitbucket, so you can use either git or Mercurial to get a copy of the project’s code and history:
$ hg clone http://bitbucket.org/wcmaier/neat
$ git clone git://github.com/wcmaier/neat.git
If you notice a problem with neat, please report it using the github issue tracker (or, if you have a fix, send a pull request).
neat is developed along two branches. The first, ‘default’ (or ‘master’ in git) contains new features and possible bugs – this branch is the active development branch. The second, ‘stable’, contains releases both major and minor as well as bugfixes. If you’d like to help improve neat, take a look at default/master. Otherwise, stick with stable.
Hello world:
>>> from neat import Resource, Dispatch
>>> from webob import Request
>>> class Hello(Resource):
... collection = "hello"
...
... def retrieve(self, req):
... return "Hello, %s" % req.path_info_pop()
>>> dispatch = Dispatch(Hello())
>>> req = Request.blank("/hello/you")
>>> req.get_response(dispatch).body
'Hello, you'
Easily add support for new media types:
>>> import json
>>> class JsonHello(Hello):
...
... mimetypes = {"application/javascript": "json"}
...
... def retrieve_json(self, req):
... req.response.content_type = "application/json"
... return json.dumps({"message": self.retrieve(req)})
...
>>> dispatch = Dispatch(JsonHello("hello"))
>>> req = Request.blank("/hello/you")
>>> req.get_response(dispatch).body
'{"message": "Hello, you"}'
neat is a simple framework for modeling and representing resources via HTTP. This approach takes full advantage of the structure of the web, described by Roy Fielding in his famous REST paper. neat applications include a single Dispatch that combines any number of resources (usually subclasses of Resource). When a Dispatch receives a HTTP request, it routes the request to Resource methods using rules defined by the Resource itself. The Resource methods then interact with the data or state of the actual resource (for example, a database) and return a representation of the current state to the client. Resource can support a variety of representations (like JSON, HTML, CSV, XML), so the framework chooses the representation that best matches the HTTP request’s Content header.
Note
The rules for routing requests and choosing representation formats are all defined by the Resource, so different resources may define different rules. If the default rules don’t suit you, simply override match().
Bases: object
Maps URI file extensions to media types.
For example:
.html -> text/html .json -> application/vnd.my.resource+json
The media types should be present in media.
Maps media types to local method suffixes.
For example:
text/html -> html application/vnd.my.resource+json -> json
Maps HTTP methods to local method base names.
For example:
GET -> get POST -> post
A dictionary of ‘magic’ parameters.
These GET parameters allow less-than-perfect clients to use interesting HTTP features even if the client itself doesn’t support them at the protocol level. Keys in the dictionary represent the feature to be supported (ie “method”); the value indicates the name of the GET parameter used to signal the feature. For example, params = {“method”: “_method”} would allow clients to set the HTTP method using the “_method” get parameter. By default, no magic parameters are supported. Possible keys include:
- method (HTTP method)
- accept (desired response media type)
- content-type (request content type)
The URI space for which this resource is responsible.
A webob.Request instance.
__call__() sets this attribute before calling one of the <method>_<media> methods. It also sets the following attributes of the request object:
- response, a webob.Response instance;
- content, an object produced by a handle_<media> method.
Bases: object
A WSGI application that dispatches to other WSGI applications.
Incoming requests are passed to registered Resource subclasses. Resources can be registered by passing them as arguments on initialization or by adding them to resources later.
Return the resource that matches req.
req should be a webob.Request instance; resources should be an iterable of Resource subclasses. Returns None if no resource matches the request.
A request matches if:
- PATH_INFO ends in ‘/’ and starts with the resource’s Resource.prefix attribute; or
- PATH_INFO is the same as the resource’s Resource.prefix attribute.
The first match wins.
neat ships with a number of unit tests that help ensure that the code runs correctly. The tests live in the tests package and can be run by setup.py:
$ python setup.py test
All new code in neat should be accompanied by unit and/or functional tests. You can get a sense for how completely the unit tests exercise neat by running the coverage tool:
$ coverage run --branch setup.py test
coverage tracks the code statements and branches that the test suite touches and can generate a report listing the lines of code that are missed:
$ coverage report -m --omit "tests,/home/will/lib,lib/neat/ext,setup"
It’s useful to omit the third party code directory (ext) as well as the path to the Python standard library as well as setup.py and the tests themselves.