Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Initial commit

  • Loading branch information...
commit 4bacfdf01b4d7a5a82c9153357bbd6e21e8d7170 0 parents
Alastair Porter authored
Showing with 229 additions and 0 deletions.
  1. +1 −0  .gitignore
  2. +113 −0 mbxml.py
  3. +105 −0 musicbrainz.py
  4. +10 −0 query.py
1  .gitignore
@@ -0,0 +1 @@
+*.pyc
113 mbxml.py
@@ -0,0 +1,113 @@
+import xml.etree.ElementTree
+import string
+import StringIO
+try:
+ from xml.etree.ElementTree import fixtag
+except:
+ # Python < 2.7
+ def fixtag(tag, namespaces):
+ # given a decorated tag (of the form {uri}tag), return prefixed
+ # tag and namespace declaration, if any
+ if isinstance(tag, QName):
+ tag = tag.text
+ namespace_uri, tag = string.split(tag[1:], "}", 1)
+ prefix = namespaces.get(namespace_uri)
+ if prefix is None:
+ prefix = _namespace_map.get(namespace_uri)
+ if prefix is None:
+ prefix = "ns%d" % len(namespaces)
+ namespaces[namespace_uri] = prefix
+ if prefix == "xml":
+ xmlns = None
+ else:
+ xmlns = ("xmlns:%s" % prefix, namespace_uri)
+ else:
+ xmlns = None
+ return "%s:%s" % (prefix, tag), xmlns
+
+NS_MAP = {"http://musicbrainz.org/ns/mmd-2.0#": "ws2"}
+
+def parse_elements(valid_els, element):
+ """ Extract single level subelements from an element.
+ For example, given the element:
+ <element>
+ <subelement>Text</subelement>
+ </element>
+ and a list valid_els that contains "subelement",
+ return a dict {'subelement': 'Text'}
+ """
+ result = {}
+ for sub in element:
+ t = fixtag(sub.tag, NS_MAP)[0]
+ if ":" in t:
+ t = t.split(":")[1]
+ if t in valid_els:
+ result[t] = sub.text
+ return result
+
+def parse_attributes(attributes, element):
+ """ Extract attributes from an element.
+ For example, given the element:
+ <element type="Group" />
+ and a list attributes that contains "type",
+ return a dict {'type': 'Group'}
+ """
+ result = {}
+ for attr in attributes:
+ if attr in element.attrib:
+ result[attr] = element.attrib[attr]
+ return result
+
+def parse_inner(inner_els, element):
+ """ Delegate the parsing of a subelement to another function.
+ For example, given the element:
+ <element>
+ <subelement>
+ <a>Foo</a><b>Bar</b>
+ </subelement>
+ </element>
+ and a dictionary {'subelement': parse_subelement},
+ call parse_subelement(<subelement>) and
+ return a dict {'subelement': <result>}
+ """
+ result = {}
+ for sub in element:
+ t = fixtag(sub.tag, NS_MAP)[0]
+ if ":" in t:
+ t = t.split(":")[1]
+ if t in inner_els.keys():
+ result[t] = inner_els[t](sub)
+ return result
+
+def parse_message(message):
+ s = message.read()
+ print s
+ f = StringIO.StringIO(s)
+ tree = xml.etree.ElementTree.ElementTree(file=f)
+ root = tree.getroot()
+ result = {}
+ for element in root:
+ t = fixtag(element.tag, NS_MAP)[0]
+ if t == "ws2:artist":
+ result["artist"] = parse_artist(element)
+
+ return result
+
+def parse_artist_lifespan(lifespan):
+ parts = parse_elements(["begin", "end"], lifespan)
+ beginval = parts.get("begin", "")
+ endval = parts.get("end", "")
+
+ return (beginval, endval)
+
+def parse_artist(artist):
+ result = {}
+ attribs = ["id", "type"]
+ elements = ["name", "sort-name"]
+ inner_els = {"life-span": parse_artist_lifespan}
+
+ result.update(parse_attributes(attribs, artist))
+ result.update(parse_elements(elements, artist))
+ result.update(parse_inner(inner_els, artist))
+
+ return result
105 musicbrainz.py
@@ -0,0 +1,105 @@
+import sys
+import urlparse
+import urllib2
+import urllib
+import mbxml
+
+def do_mb_query(entity, id, includes=[]):
+ # XXX: Paging
+ args = {}
+ if len(includes) > 1:
+ inc = " ".join(includes)
+ args["inc"] = inc
+ url = urlparse.urlunparse(('http',
+ 'test.musicbrainz.org',
+ '/ws/2/%s/%s' % (entity, id),
+ '',
+ urllib.urlencode(args),
+ ''))
+ print url
+ f = urllib2.Request(url)
+ f.add_header('User-Agent','pymb3')
+ try:
+ f = urllib2.urlopen(f)
+ except urllib2.URLError, e:
+ print "error"
+ raise
+ print mbxml.parse_message(f)
+
+class InvalidIncludeError(Exception):
+ def __init__(self, msg='Invalid Includes', reason=None):
+ Exception.__init__(self)
+ self.msg = msg
+ self.reason = reason
+
+ def __str__(self):
+ return self.msg
+
+def check_includes(valid_inc, inc):
+ for i in inc:
+ if i not in valid_inc:
+ print i
+ raise InvalidIncludeError("Bad includes", "%s is not a valid include" % i)
+
+def get_artist_by_id(id, includes=[]):
+ valid_inc = ["recordings", "releases", "release-groups", "works"]
+ check_includes(valid_inc, includes)
+ do_mb_query("artist", id, includes)
+
+def search_artist(query, includes):
+ pass
+
+def browse_artist(filters, includes):
+ pass
+
+def get_label_by_id(id, includes=[]):
+ valid_inc = ["releases"]
+ check_includes(valid_inc, includes)
+ do_mb_query("label", id, includes)
+
+def search_label(query, includes):
+ pass
+
+def browse_releases(includes, status, typ):
+ pass
+
+def browse_release_groups(includes, status, typ):
+ pass
+
+def get_recording_by_id(id, includes=[]):
+ valid_inc = ["artists", "releases"]
+ check_includes(valid_inc, includes)
+ do_mb_query("recording", id, includes)
+
+def get_release_by_id(id, includes=[]):
+ valid_inc = ["artists", "labels", "recordings", "release-groups"]
+ check_includes(valid_inc, includes)
+ do_mb_query("release", id, includes)
+
+def get_release_group_by_id(id, includes=[]):
+ valid_inc = ["artists", "releases"]
+ check_includes(valid_inc, includes)
+ do_mb_query("release-group", id, includes)
+
+def get_work_by_id(id, includes=[]):
+ valid_inc = ["artists"]
+ check_includes(valid_inc, includes)
+ do_mb_query("work", id, includes)
+
+###
+
+def submit_barcode():
+ pass
+
+def submit_puid():
+ pass
+
+def submit_isrc():
+ pass
+
+def submit_tags():
+ pass
+
+def submit_rating():
+ pass
+
10 query.py
@@ -0,0 +1,10 @@
+import sys
+
+import musicbrainz as m
+
+def main():
+ m.get_artist_by_id("952a4205-023d-4235-897c-6fdb6f58dfaa",
+ [])
+
+if __name__ == "__main__":
+ main()
Please sign in to comment.
Something went wrong with that request. Please try again.