Searching with the Sonatype Nexus REST API: Python


November 24, 2008 By Tim O'Brien

This post is a follow-up to the two previous posts on Ruby and Groovy which provided some sample Ruby and Groovy scripts that can be used to list repositories and search for artifacts in a Nexus instance. Today, we’re going to see how to complete the same tasks using the Python scripting language.

The following scripts are in Python and they can be invoked from the command line using python (or jython). For example, if you want to run the quick-search.py script, you would run “jython quick-search.py activemq” to search for artfiacts that contain the string “activemq”. I tested these Python scripts using the latest Jython 2.5b0 distribution with version 1.2.6 of the jython-elementtree project at Google Code.  Go to the Jython page, download Jython 2.5b0, and then following the instructions on the jython-elementtree project list to check out the ElementTree library from source control and install it in your own Jython installation.  These scripts don’t require Jython, the could run in any Python 2.5 implementation.

The Nexus REST API

The UI of Nexus is written in ExtJS and it makes heavy use of AJAX callbacks to REST services. In fact, if you load up Nexus in a tool like Firebug, an extension for Firefox which allows you to trace all network activity, you will see that almost every action in Nexus triggers a call to a REST service. For more details about the Nexus REST services and for a pointer to the documentation, read the previous blog post in this series which was focused on a similar set of Ruby scripts.

If you would like to download the sample scripts in this blog post, you can download this ZIP file which contains four Python scripts: http://books.sonatype.com/tutorial-files/nexus-rest-python.zip

Listing Repositories

The first script simply lists all of the repositories in a Nexus installation. Here it is:

import urllib,sys
from xml.etree import ElementTree
from xml.etree import ElementPath
 
url = 'http://repository.sonatype.org/service/local/repositories'
data = urllib.urlopen( url ).read()
 
doc = ElementTree.XML( data )
 
for a in ElementPath.findall(doc, ".//repositories-item"):
  print ( a.find("name").text + " (" +
        a.find("id").text + ")\n\t" +
        a.find("resourceURI").text ) + "\n"

This script sets the pattern for the scripts to follow. We construct a URL, then we call urlopen and read the response body into a String. Then we use ElementTree to parse the XML document. Once the document is parsed, we use ElementPath to apply our XPath expression to the document. Finally the repository, the repository id, and the repository URL is printed out. This script could not be more straightforward. This post is simply a pointer to the service and a quick demonstration so I’m not going to dive into the meaning of every single element in the XML document returned by the repositories service. If you are interested in see the full set of elements that are available, load up the results of this service in a web browser by click on this: http://repository.sonatype.org/service/local/repositories.

Performing a “Quick Search”

import urllib,sys
from xml.etree import ElementTree
from xml.etree import ElementPath
 
url = 'http://repository.sonatype.org/service/local/data_index?q='
data = urllib.urlopen( url + sys.argv[1] ).read()
 
doc = ElementTree.XML( data )
 
for a in ElementPath.findall(doc, ".//artifact"):
  print ( a.find("groupId").text + ":" +
        a.find("artifactId").text + ":" +
        a.find("version").text )

This script follows the pattern of the previous script to list all repositories with the exception that it reads an argument from the command line. This script performs a quick search by hitting the data_index service and passing in the q parameter. This script simply prints out the groupId:artifactId:version of all the artifacts located.

If you would like to see an example of the XML that this service produces click here: http://repository.sonatype.org/service/local/data_index?q=activemq. In the full results, you’ll see more information such as the number of search hits available, the resource URL for each artifact found, and the context (or repository) in which the artifact is available.

Searching by Class Name

import urllib,sys
from xml.etree import ElementTree
from xml.etree import ElementPath
 
url = 'http://repository.sonatype.org/service/local/data_index?cn='
data = urllib.urlopen( url + sys.argv[1] ).read()
 
doc = ElementTree.XML( data )
 
for a in ElementPath.findall(doc, ".//artifact"):
  print ( a.find("groupId").text + ":" +
        a.find("artifactId").text + ":" +
        a.find("version").text )

This script is almost exactly the same as the prior script that performed a quick search. The difference in this script is that instead of passing the q parameter, this script passes the cn parameter. Passing the cn parameter causes Nexus to search for artifacts which contain classes that match the given value. The results are going to look the same as the quick search query script. To see the XML yourself, search for all artifacts which contain a class named HibernateDaoSupport: http://repository.sonatype.org/service/local/data_index?cn=HibernateDaoSupport.

Performing a GAV Search

import urllib,sys
from xml.etree import ElementTree
from xml.etree import ElementPath
 
url = 'http://repository.sonatype.org/service/local/data_index?'
url = url + "g=" + sys.argv[1] + "&a=" + sys.argv[2] + "&v=" + sys.argv[3]
data = urllib.urlopen( url ).read()
 
doc = ElementTree.XML( data )
 
for a in ElementPath.findall(doc, ".//artifact"):
  print ( a.find("groupId").text + ":" +
        a.find("artifactId").text + ":" +
        a.find("version").text )

This final script takes three command line arguments: groupId, artifactId, version, and it performs a GAV (groupId, artifactId, version) coordinate search over the repository.