Programmer's tutorial Arjan Scherpenisse

AnyMeta.py

Interfacing to AnyMeta from Python

The most recent hackers camp exposed many eager hackers to the AnyMeta API. However, the existing documentation and tools were not up-to-date and so, during the camp, a new way of interfacing AnyMeta was born, using the Python language. Python has the advantage that it's cross-platform, easy to understand and easy to integrate into other programs (e.g. by using a shell script). The current version of the python-anymeta library is a pure python one, so, in contrast to earlier versions, the only thing that's needed is the anymeta python module, no external requirements. The library is released as open source, under the MIT license.

Enlarge

Interfacing AnyMeta from python is simple.. and clean! - Interfacing AnyMeta from python is simple.. and clean!

Installation

Get the latest version from the python-anymeta repository:

svn checkout svn://svn.mediamatic.nl/python-anymeta/ python-anymeta

Now, you have to install simplejson and pydataportability.xrds, if they're not already there:

sudo easy_install simplejson
sudo easy_install pydataportability.xrds

Then, install the module into your python system path:

sudo python setup.py install

Next, read on, and then run the examples! :-)

Usage with the AnyMetaRegistry

The AnyMeta registry is a local store for storing 'profiles', entry point + oauth key combinations, on your local computer. This functionality can be compared to anyIdentity's profile functionality, but it extends it in the sense that the registry can also help you obtaining the keys.

The example-registry.py file first registers a profile (if its not already there), and then tries some authorized calls:

from anymeta.api import AnyMetaAPI
from anymeta.api.registry import AnyMetaRegistry

#
# Interactively register an oauth key to use for picnicnetwork.org,
# and save it under the identifier key 'picnic'.
#
r = AnyMetaRegistry.getInstance()
r.register_interactive('picnic', 'http://www.picnicnetwork.org/services/rest/')

#
# Instantiate an API by using the 'picnic' registry entry
#
api = AnyMetaAPI.from_registry('picnic')

print api.anymeta.predicates.get(id=21860, field='text.title')

The first time you run this from the command prompt, the register_interactive function will pause, and show you an URL on which you have to authorize the OAuth keys it has created for you. Open this URL in a browser, log in and click the 'authorize' button. Then, return to the terminal and press 'enter' to finish the process. The registry key will be saved in your ~/.anymeta file under the name 'picnic' (in this case), and can be used by the registry for subsequent calls.

Then, an API is instantiated from the registry, using the 'picnic' key, and an example call is done using this key. Isn't it simple!

Usage without the AnyMetaRegistry

As said, for interfacing AnyMeta, you need to authorize your application first, by obtaining a set of OAuth keys. The process of obtaining these keys is beyond the scope of this article, however, and the AnyMetaRegistry can guide you through this process (see previuos section).

Look in the example-basic.py file for some example commands which direclty interface AnyMeta using OAuth. You'll see that you need to put your OAuth keys in the oauth variable for anymeta to work.

The following code creates an instance of the AnyMetaAPI class to interface with an AnyMeta site; in this case it's a site running on my local machine.

oauth = {'c_key': '514d343f54fcc5ebaee8305fcc6cc08c048c8cbbf',
         'c_sec': '01f8d7f9eff12732ca6793ea906eede3',
         't_key': '10d3935104352b6486b509901b61389f048e33533',
         't_sec': '0a3e87ac3da8e4c6bb8f58695293d5fa'
         }

api = AnyMetaAPI('http://any.local/services/rest/', oauth)

Having done this, you're all set to run some API commands. Let's look at a simple one: anymeta.predicates.get. This command fetches a specific field from a thing, and returns it. It's handy for getting just a title of a thing, for example.

r = api.anymeta.predicates.get(id=199, field='text.title')
pprint.pprint(r)

Running this will give the title of thing nr. 199:

{'result': 'Arjan Scherpenisse'}

Advanced

Another interesting thing is uploading a file to AnyMeta, for instance a JPEG image. This is done using the anymeta.attachment.create call, like this:

#
# Uploading a file and connecting it to person 199 using the ACTOR and FIGURE predicates
#
connect = [ {'subject': '199', 'predicate': 'FIGURE', 'object': 'SELF'} ]

r = api.anymeta.attachment.create(mime="image/jpeg", data="@/home/arjan/televisie.jpg", title="A nice television", connect=connect)

As you can see, this call not only uploads the file, but also connects it to user 199 using the 'figure' predicate; this means that this attachment is used as a picture of the user.

Note that the python library has a special syntax for adding files to anymeta: whenever an argument starts with a '@', and the file exists and is an absolute path, the library will read the file, encode it as base64 and use this instead in the post request. This allows for easy posting binary data to anymeta.

Error handling

Whenever the API encounters a problem with a request, either on the OAuth layer or on the API layer, it will throw an AnyMetaException. This exception contains a message indicating what went wrong. In the case of an API error, the message also includes the error number, which you can look up in the API documentation to see what the problem was, exactly.

Twisted

Since version 1.1, python-anymeta has support for using Twisted as backend for the HTTP requests. The basics remain the same, but the HTTP requests are done asynchronously, thus allowing for better integration in GUI programs, for instance. For a full example, see examples/example-twisted.py.

# Get the title of thing 22661
api.anymeta.predicates.get(id=22661, field='text.title').addCallback(printResult)

See more...

For an overview of all calls which are available in your AnyMeta system, go to the /services/rest/ url of the site you're talking to. For mediamatic.net, this is: www.mediamatic.net/services/rest/