beanbag.v2 – REST API access

A quick example:

>>> from beanbag.v2 import BeanBag, GET
>>> gh = BeanBag("https://api.github.com/")
>>> watchers = GET(gh.repos.ajtowns.beanbag.watchers)
>>> for w in watchers:
...     print(w.login)

Setup:

>>> import beanbag.v2 as beanbag
>>> from beanbag.v2 import GET, POST, PUT, PATCH, DELETE
>>> myapi = beanbag.BeanBag("http://hostname/api/")

To constuct URLs, you can use attribute-style access or dict-style access:

>>> print(myapi.foo)
http://hostname/api/foo
>>> print(myapi["bar"])
http://hostname/api/bar

You can chain paths as well:

>>> print(myapi.foo.bar["baz"][3].xyzzy)
http://hostname/api/foo/bar/baz/3/xyzzy

To do a request on a resource that requires a trailing slash:

>>> print(myapi.foo._)
http://hostname/api/foo/
>>> print(myapi.foo[""])
http://hostname/api/foo/
>>> print(myapi.foo["/"])
http://hostname/api/foo/
>>> print(myapi["foo/"])
http://hostname/api/foo/
>>> print(myapi.foo._.x == myapi.foo.x)
True
>>> print(myapi.foo["_"])
http://hostname/api/foo/_

You can add URL parameters using function calls:

>>> print(myapi.foo(a=1, b="foo"))
http://hostname/api/foo?a=1;b=foo

Finally, to actually do REST queries on these queries you can use the GET, POST, PUT, PATCH and DELETE functions. The first argument should be a BeanBag url, and the second argument (if provided) should be the request body, which will be json encoded before being sent. The return value is the request’s response (decoded from json).

>>> res = GET( foo.resource )
>>> res = POST( foo.resource, {"a": 12} )
>>> DELETE( foo.resource )

To access REST interfaces that require authentication, you need to specify a session object when instantiating the BeanBag initially. BeanBag supplies helpers to make Kerberos and OAuth 1.0a authentication easier.

BeanBag class

The BeanBag class does all the magic described above, using beanbag.namespace.

class beanbag.v2.BeanBag(base_url, ext='', session=None, use_attrdict=True)
__init__(base_url, ext='', session=None, use_attrdict=True)

Create a BeanBag referencing a base REST path.

Parameters:
  • base_url – the base URL prefix for all resources
  • ext – extension to add to resource URLs, eg ”.json”
  • session – requests.Session instance used for this API. Useful to set an auth procedure, or change verify parameter.
  • use_attrdict – if true, decode() will wrap dicts and lists in a beanbag.attrdict.AttrDict for syntactic sugar.
__call__(*args, **kwargs)

Set URL parameters

__eq__(other)

self == other

__getattr__(attr)

self.attr

__getitem__(item)

self[attr]

__invert__()

Provide access to the base/path via the namespace object

bb = BeanBag(...)
base, path = ~bb.foo
assert isinstance(base, BeanBagBase)

This is the little bit of glue needed so that it’s possible to call methods defined in BeanBagBase directly rather than just the operators BeanBag supports.

__ne__(other)

self != other

__repr__()

Human readable representation of object

__str__()

Obtain the URL of a resource

This class can be subclassed. In particular, if you need to use something other than JSON for requests or responses, subclassing BeanBagBase and overriding the encode and decode methods is probably what you want to do. One caveat: due to the way beanbag.namespace works, if you wish to invoke the parent classes method, you’ll usually need the parent base class, accessed via ~BeanBag or super(~SubClass, self).

HTTP Verbs

Functions are provided for the standard set of HTTP verbs.

beanbag.v2.GET(url, body=None)

GET verb function

beanbag.v2.HEAD(url, body=None)

HEAD verb function

beanbag.v2.POST(url, body=None)

POST verb function

beanbag.v2.PUT(url, body=None)

PUT verb function

beanbag.v2.PATCH(url, body=None)

PATCH verb function

beanbag.v2.DELETE(url, body=None)

DELETE verb function

The verb function is used to create BeanBag compatible verbs. It is used as:

GET = verb("GET")
beanbag.v2.verb(verbname)

Construct a BeanBag compatible verb function

Parameters:verbname – verb to use (GET, POST, etc)

Request

The Request class serves as a place holder for arguments to requests.Session.request. Normally this is constructed from a dict object passed to POST or PUT via json.dumps() however a Request object can also be created by hand and passed in as the body parameter in a POST or similar BeanBag request. For example to make a POST request with a body that isn’t valid JSON:

POST(bbexample.path.to.resource, Request(body="MAGIC STRING"))

This can be useful with GET requests as well, even though GET requests don’t have a body per se:

GET(bbexample.path.to.resource, Request(headers={"X-Magic": "String"}))
class beanbag.v2.Request(**kwargs)

Bases: beanbag.attrdict.AttrDict

__init__(**kwargs)

Create a Request object

Request objects act as placeholders for the arguments to the requests() function of the requests.Session being used. They are used as the interface between the encode() and make_request() functions, and may also be used by the API caller.

NB: A Request object is only suitable for one use, as it may be modified in-place during the request. For this reason, __init__ makes a (shallow) copy of all the keyword arguments supplied rather than using them directly.

BeanBagException

exception beanbag.v2.BeanBagException(response, msg)

Exception thrown when a BeanBag request fails.

Data members:
  • msg – exception string, brief and human readable
  • response – response object

You can get the original request via bbe.response.request.

__init__(response, msg)

Create a BeanBagException