{"id":927,"date":"2014-03-22T18:47:44","date_gmt":"2014-03-22T08:47:44","guid":{"rendered":"http:\/\/www.erisian.com.au\/wordpress\/?p=927"},"modified":"2014-03-22T18:52:42","modified_gmt":"2014-03-22T08:52:42","slug":"beanbag-easy-access-to-rest-apis-in-python","status":"publish","type":"post","link":"https:\/\/www.erisian.com.au\/wordpress\/2014\/03\/22\/beanbag-easy-access-to-rest-apis-in-python","title":{"rendered":"BeanBag &#8212; Easy access to REST APIs in Python"},"content":{"rendered":"<p>I&#8217;ve been doing a bit of playing around with REST APIs lately, both at <a href=\"http:\/\/www.redhat.com\/\">work<\/a> and for my own amusement. One of the things that was frustrating me a bit was that actually accessing the APIs was pretty baroque &#8212; you&#8217;d have to construct urls manually with string operations, manually encode any URL parameters or POST data, then pass that to a requests call with params to specify auth and SSL validation options and possibly cookies, and then parse whatever response you get to work out if there&#8217;s an error and to get at any data. Not a great look, especially compared to XML-RPC support in python, which is what REST APIs are meant to obsolete. Compare, eg:<\/p>\n<blockquote><p>\n<code>server = xmlrpclib.Server(\"http:\/\/foo\/XML-RPC\")<br \/>\nprint server.some.function(1,2,3,{\"foo\": \"bar\"})<\/code><\/p><\/blockquote>\n<p>with:<\/p>\n<blockquote>\n<pre><code>base_url = \"https:\/\/api.github.com\/\"\r\nresp = requests.get(base_url + \"\/repos\/django\/django\")\r\nif resp.ok:\r\n    res = resp.json()\r\nelse:\r\n    raise Exception(r.json())<\/code><\/pre>\n<\/blockquote>\n<p>That&#8217;s not to say the python was is <i>bad<\/i> or anything &#8212; it&#8217;s certainly easier than trying to do it in shell, or with urllib2 or whatever. But I like using python because it makes the difference between pseudocode and real code small, and in this case, the xmlrpc approach is much closer to the pseudocode I&#8217;d write than the requests code.<\/p>\n<p>So I had a look around to see if there were any nice libraries to make REST API access easy from the client side. Ended up getting kind of distracted by reading through various arguments that the sorts of things generally called REST APIs aren&#8217;t actually &#8220;REST&#8221; at all according to the original definition of the term, which was to describe the architecture of the web as a whole. One article that gives a reasonably brief overview is <a href=\"http:\/\/martinfowler.com\/articles\/richardsonMaturityModel.html\">this take on REST maturity levels<\/a>. Otherwise doing a search for the ridiculous acronym &#8220;HATEOAS&#8221; probably works. I did some stream-of-consciousness posts on Google-Plus as well, see <a href=\"https:\/\/plus.google.com\/114454357718923611656\/posts\/WCmKwkVKogo\">here<\/a>, <a href=\"https:\/\/plus.google.com\/114454357718923611656\/posts\/T4zZ9Bw5bfC\">here<\/a> and <a href=\"https:\/\/plus.google.com\/114454357718923611656\/posts\/A7JqAqU8wuuhttps:\/\/plus.google.com\/114454357718923611656\/posts\/A7JqAqU8wuu\">here<\/a>.<\/p>\n<p>The end result was I wrote something myself, which I called <a href=\" https:\/\/github.com\/ajtowns\/beanbag\">beanbag<\/a>. I even got to do it mostly on work time and release it under the GPL. I think it&#8217;s pretty cool:<\/p>\n<blockquote><p>\n<code>github = beanbag.BeanBag(\"https:\/\/api.github.com\")<br \/>\nx = github.repos.django.django()<br \/>\nprint x[\"name\"]<\/code><\/p><\/blockquote>\n<p>As per the README in the source, you can throw in a session object to do various sorts of authentication, including Kerberos and OAuth 1.0a. I&#8217;ve tried it with github, twitter, and xero&#8217;s public APIs with decent success. It also seems to work with Magento and some of Red Hat&#8217;s internal tools without any hassle.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I&#8217;ve been doing a bit of playing around with REST APIs lately, both at work and for my own amusement. One of the things that was frustrating me a bit was that actually accessing the APIs was pretty baroque &#8212; you&#8217;d have to construct urls manually with string operations, manually encode any URL parameters or [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[30],"tags":[],"_links":{"self":[{"href":"https:\/\/www.erisian.com.au\/wordpress\/wp-json\/wp\/v2\/posts\/927"}],"collection":[{"href":"https:\/\/www.erisian.com.au\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.erisian.com.au\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.erisian.com.au\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.erisian.com.au\/wordpress\/wp-json\/wp\/v2\/comments?post=927"}],"version-history":[{"count":5,"href":"https:\/\/www.erisian.com.au\/wordpress\/wp-json\/wp\/v2\/posts\/927\/revisions"}],"predecessor-version":[{"id":932,"href":"https:\/\/www.erisian.com.au\/wordpress\/wp-json\/wp\/v2\/posts\/927\/revisions\/932"}],"wp:attachment":[{"href":"https:\/\/www.erisian.com.au\/wordpress\/wp-json\/wp\/v2\/media?parent=927"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.erisian.com.au\/wordpress\/wp-json\/wp\/v2\/categories?post=927"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.erisian.com.au\/wordpress\/wp-json\/wp\/v2\/tags?post=927"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}