1 """Various utilities to simplify common tasks.
2
3 This module contains helper functions to make common tasks easier.
4
5 @author: Matthias Friedrich <matt@mafr.de>
6 """
7 __revision__ = '$Id: utils.py 13322 2011-11-03 13:38:06Z luks $'
8
9 import re
10 import urlparse
11
12 __all__ = [
13 'extractUuid', 'extractFragment', 'extractEntityType',
14 'getReleaseTypeName', 'getCountryName', 'getLanguageName',
15 'getScriptName',
16 ]
17
18
19
20 PATH_PATTERN = '^/(artist|release|track|label|release-group)/([^/]*)$'
21
22
24 """Extract the UUID part from a MusicBrainz identifier.
25
26 This function takes a MusicBrainz ID (an absolute URI) as the input
27 and returns the UUID part of the URI, thus turning it into a relative
28 URI. If C{uriStr} is None or a relative URI, then it is returned
29 unchanged.
30
31 The C{resType} parameter can be used for error checking. Set it to
32 'artist', 'release', or 'track' to make sure C{uriStr} is a
33 syntactically valid MusicBrainz identifier of the given resource
34 type. If it isn't, a C{ValueError} exception is raised.
35 This error checking only works if C{uriStr} is an absolute URI, of
36 course.
37
38 Example:
39
40 >>> from musicbrainz2.utils import extractUuid
41 >>> extractUuid('http://musicbrainz.org/artist/c0b2500e-0cef-4130-869d-732b23ed9df5', 'artist')
42 'c0b2500e-0cef-4130-869d-732b23ed9df5'
43 >>>
44
45 @param uriStr: a string containing a MusicBrainz ID (an URI), or None
46 @param resType: a string containing a resource type
47
48 @return: a string containing a relative URI, or None
49
50 @raise ValueError: the given URI is no valid MusicBrainz ID
51 """
52 if uriStr is None:
53 return None
54
55 (scheme, netloc, path) = urlparse.urlparse(uriStr)[:3]
56
57 if scheme == '':
58 return uriStr
59
60 if scheme != 'http' or netloc != 'musicbrainz.org':
61 raise ValueError('%s is no MB ID.' % uriStr)
62
63 m = re.match(PATH_PATTERN, path)
64
65 if m:
66 if resType is None:
67 return m.group(2)
68 else:
69 if m.group(1) == resType:
70 return m.group(2)
71 else:
72 raise ValueError('expected "%s" Id' % resType)
73 else:
74 raise ValueError('%s is no valid MB ID.' % uriStr)
75
76
78 """Extract the fragment part from a URI.
79
80 If C{uriStr} is None or no absolute URI, then it is returned unchanged.
81
82 The C{uriPrefix} parameter can be used for error checking. If C{uriStr}
83 is an absolute URI, then the function checks if it starts with
84 C{uriPrefix}. If it doesn't, a C{ValueError} exception is raised.
85
86 @param uriStr: a string containing an absolute URI
87 @param uriPrefix: a string containing an URI prefix
88
89 @return: a string containing the fragment, or None
90
91 @raise ValueError: the given URI doesn't start with C{uriPrefix}
92 """
93 if uriStr is None:
94 return None
95
96 (scheme, netloc, path, params, query, frag) = urlparse.urlparse(uriStr)
97 if scheme == '':
98 return uriStr
99
100 if uriPrefix is None or uriStr.startswith(uriPrefix):
101 return frag
102 else:
103 raise ValueError("prefix doesn't match URI %s" % uriStr)
104
105
107 """Returns the entity type an entity URI is referring to.
108
109 @param uriStr: a string containing an absolute entity URI
110
111 @return: a string containing 'artist', 'release', 'track', or 'label'
112
113 @raise ValueError: if the given URI is no valid MusicBrainz ID
114 """
115 if uriStr is None:
116 raise ValueError('None is no valid entity URI')
117
118 (scheme, netloc, path) = urlparse.urlparse(uriStr)[:3]
119
120 if scheme == '':
121 raise ValueError('%s is no absolute MB ID.' % uriStr)
122
123 if scheme != 'http' or netloc != 'musicbrainz.org':
124 raise ValueError('%s is no MB ID.' % uriStr)
125
126 m = re.match(PATH_PATTERN, path)
127
128 if m:
129 return m.group(1)
130 else:
131 raise ValueError('%s is no valid MB ID.' % uriStr)
132
133
135 """Returns the name of a release type URI.
136
137 @param releaseType: a string containing a release type URI
138
139 @return: a string containing a printable name for the release type
140
141 @see: L{musicbrainz2.model.Release}
142 """
143 from musicbrainz2.data.releasetypenames import releaseTypeNames
144 return releaseTypeNames.get(releaseType)
145
146
148 """Returns a country's name based on an ISO-3166 country code.
149
150 The country table this function is based on has been modified for
151 MusicBrainz purposes by using the extension mechanism defined in
152 ISO-3166. All IDs are still valid ISO-3166 country codes, but some
153 IDs have been added to include historic countries and some of the
154 country names have been modified to make them better suited for
155 display purposes.
156
157 If the country ID is not found, None is returned. This may happen
158 for example, when new countries are added to the MusicBrainz web
159 service which aren't known to this library yet.
160
161 @param id_: a two-letter upper case string containing an ISO-3166 code
162
163 @return: a string containing the country's name, or None
164
165 @see: L{musicbrainz2.model}
166 """
167 from musicbrainz2.data.countrynames import countryNames
168 return countryNames.get(id_)
169
170
172 """Returns a language name based on an ISO-639-2/T code.
173
174 This function uses a subset of the ISO-639-2/T code table to map
175 language IDs (terminologic, not bibliographic ones!) to names.
176
177 @param id_: a three-letter upper case string containing an ISO-639-2/T code
178
179 @return: a string containing the language's name, or None
180
181 @see: L{musicbrainz2.model}
182 """
183 from musicbrainz2.data.languagenames import languageNames
184 return languageNames.get(id_)
185
186
188 """Returns a script name based on an ISO-15924 code.
189
190 This function uses a subset of the ISO-15924 code table to map
191 script IDs to names.
192
193 @param id_: a four-letter string containing an ISO-15924 script code
194
195 @return: a string containing the script's name, or None
196
197 @see: L{musicbrainz2.model}
198 """
199 from musicbrainz2.data.scriptnames import scriptNames
200 return scriptNames.get(id_)
201
202
203
204