Package: mawac
To write a friendly client for a RESTful API you typically end up doing the
following:Write HTTP client commands for communicating with the server. These commands
do things like marshal payloads, convert errors, invoke request hooks, etc.Turn responses deserialized by your client into resource objects (i.e.
objectify the response).Build up queries (e.g. filter, sort) to access resources matching some
criteria in perhaps a particular order.In the ideal case the client gives your users something approximating an ORM
for your resources. This library is intended to assist you in writing such a
client provided the API you are consuming complies with some basic
expectations:Uses HTTP properly.Identifies resources using URIs.Names nested resources consistently.InstallationSimply:$ pip install wacor if you prefer:$ easy_install wacRequirementsPython>= 2.6, < 3.0Requests>= 0.11.1UsageLets work through an example. The code for this example is inexample.py.First you import wac:import wacNext define the version of your client:__version__ = '1.0'Also define the configuration which allClients will use by default:default_config = wac.Config(None)Now be nice and define a function for updating the configuration(s):def configure(root_url, **kwargs):
    default = kwargs.pop('default', True)
    kwargs['client_agent'] = 'example-client/' + __version__
    if 'headers' not in kwargs:
        kwargs['headers'] = {}
    kwargs['headers']['Accept-Type'] = 'application/json'
    if default:
        default_config.reset(root_url, **kwargs)
    else:
        Client.config = wac.Config(root_url, **kwargsNow the big one, define yourClientwhich is what will be used to talk to
a server:class Client(wac.Client):

    config = default_config

    def _serialize(self, data):
        data = json.dumps(data, default=self._default_serialize)
        return 'application/json', data

    def _deserialize(self, response):
        if response.headers['Content-Type'] != 'application/json':
            raise Exception("Unsupported content-type '{}'"
                .format(response.headers['Content-Type']))
        data = json.loads(response.content)
        return dataThen define your baseResource:class Resource(wac.Resource):

    client = Client()
    registry = wac.ResourceRegistry()And finally your actual resources:class Playlist(Resource):

    uri_spec = wac.URISpec('playlists', 'guid', root='/v1')


class Song(Resource):

    uri_spec = wac.URISpec('songs', 'guid')Done! Now you can do crazy stuff like this:import example

example.configure('https://api.example.com', auth=('user', 'passwd'))

q = (example.Playlist.query()
    .filter(Playlist.f.tags.contains('nuti'))
    .filter(~Playlist.f.tags.contains('sober'))
    .sort(Playlist.f.created_at.desc()))
for playlist in q:
    song = playlist.songs.create(
        name='Flutes',
        length=1234,
        tags=['nuti', 'fluti'])
    song.length += 101
    song.save()ContributingFork itCreate your feature branch (git checkout -b my-new-feature)Write your codeand testsEnsure all tests still pass (nosetests -svx tests)Commit your changes (git commit -am ‘Add some feature’)Push to the branch (git push origin my-new-feature)Create new pull requestHistory0.14 (2013-01-29)Pin requests version to less than 1.0 until we test it with requests > 1.00.12 (2012-10-02)Fix ResourceCollection.filter.Add like and ilike filters.Minor pep8/formatting changes.0.11 (2012-09-11)Fix config copy.0.10 (2012-07-27)Python 2.6 compatibility.0.9 (2012-07-25)Save serialization fix.0.8 (2012-07-25)Pagination fixes.0.7 (2012-07-20)Misc fixes.0.3 (2012-05-28)Hope you like it.0.2 (2012-05-01)Growing pains.0.1 (2012-04-01)Its alive!