diff --git a/pyechonest/track.py b/pyechonest/track.py index 6483a17..fdb2b71 100644 --- a/pyechonest/track.py +++ b/pyechonest/track.py @@ -1,4 +1,7 @@ -import urllib2 +try: + import urllib.request as urllib2 +except ImportError: + import urllib2 try: import json except ImportError: @@ -43,7 +46,7 @@ class Track(TrackProxy): valence float: a range from negative to positive emotional content (0.0 to 1.0) The following attributes are available only after calling Track.get_analysis(): - + analysis_channels int: the number of audio channels used during analysis analysis_sample_rate int: the sample rate used during analysis bars list of dicts: timing of each measure @@ -69,7 +72,7 @@ class Track(TrackProxy): tatums list of dicts: the smallest metrical unit (subdivision of a beat) tempo_confidence float: confidence that tempo detection was accurate time_signature_confidence float: confidence that time_signature detection was accurate - + Each bar, beat, section, segment and tatum has a start time, a duration, and a confidence, in addition to whatever other data is given. @@ -113,9 +116,9 @@ def __repr__(self): def __str__(self): return self.title.encode('utf-8') - + def get_analysis(self): - """ Retrieve the detailed analysis for the track, if available. + """ Retrieve the detailed analysis for the track, if available. Raises Exception if unable to create the detailed analysis. """ if self.analysis_url: try: diff --git a/pyechonest/util.py b/pyechonest/util.py index 7198ae8..1d6f390 100644 --- a/pyechonest/util.py +++ b/pyechonest/util.py @@ -8,7 +8,6 @@ Utility functions to support the Echo Nest web API interface. """ import urllib -import urllib2 import httplib import config import logging @@ -24,6 +23,10 @@ import json except ImportError: import simplejson as json +try: + import urllib.request as urllib2 +except ImportError: + import urllib2 logger = logging.getLogger(__name__) TYPENAMES = ( @@ -49,7 +52,7 @@ def default_open(self, request): logger.info("%s" % (request.get_full_url(),)) request.start_time = time.time() return None - + class MyErrorProcessor(urllib2.HTTPErrorProcessor): def http_response(self, request, response): code = response.code @@ -129,10 +132,10 @@ def get_successful_response(raw_json): def callm(method, param_dict, POST=False, socket_timeout=None, data=None): """ - Call the api! + Call the api! Param_dict is a *regular* *python* *dictionary* so if you want to have multi-valued params put them in a list. - + ** note, if we require 2.6, we can get rid of this timeout munging. """ try: @@ -218,10 +221,10 @@ def oauthgetm(method, param_dict, socket_timeout=None): raise Exception("You must install the python-oauth2 library to use this method.") """ - Call the api! With Oauth! + Call the api! With Oauth! Param_dict is a *regular* *python* *dictionary* so if you want to have multi-valued params put them in a list. - + ** note, if we require 2.6, we can get rid of this timeout munging. """ def build_request(url): @@ -232,17 +235,17 @@ def build_request(url): } consumer = oauth2.Consumer(key=config.ECHO_NEST_CONSUMER_KEY, secret=config.ECHO_NEST_SHARED_SECRET) params['oauth_consumer_key'] = config.ECHO_NEST_CONSUMER_KEY - + req = oauth2.Request(method='GET', url=url, parameters=params) signature_method = oauth2.SignatureMethod_HMAC_SHA1() req.sign_request(signature_method, consumer, None) return req - + param_dict['api_key'] = config.ECHO_NEST_API_KEY param_list = [] if not socket_timeout: socket_timeout = config.CALL_TIMEOUT - + for key,val in param_dict.iteritems(): if isinstance(val, list): param_list.extend( [(key,subval) for subval in val] ) @@ -252,19 +255,19 @@ def build_request(url): param_list.append( (key,val) ) params = urllib.urlencode(param_list) - + orig_timeout = socket.getdefaulttimeout() socket.setdefaulttimeout(socket_timeout) """ just a normal GET call """ - url = 'http://%s/%s/%s/%s?%s' % (config.API_HOST, config.API_SELECTOR, config.API_VERSION, + url = 'http://%s/%s/%s/%s?%s' % (config.API_HOST, config.API_SELECTOR, config.API_VERSION, method, params) req = build_request(url) f = opener.open(req.to_url()) - + socket.setdefaulttimeout(orig_timeout) - + # try/except response_dict = get_successful_response(f) return response_dict @@ -274,14 +277,14 @@ def postChunked(host, selector, fields, files): """ Attempt to replace postMultipart() with nearly-identical interface. (The files tuple no longer requires the filename, and we only return - the response body.) - Uses the urllib2_file.py originally from - http://fabien.seisen.org which was also drawn heavily from + the response body.) + Uses the urllib2_file.py originally from + http://fabien.seisen.org which was also drawn heavily from http://code.activestate.com/recipes/146306/ . - - This urllib2_file.py is more desirable because of the chunked - uploading from a file pointer (no need to read entire file into - memory) and the ability to work from behind a proxy (due to its + + This urllib2_file.py is more desirable because of the chunked + uploading from a file pointer (no need to read entire file into + memory) and the ability to work from behind a proxy (due to its basis on urllib2). """ params = urllib.urlencode(fields) diff --git a/setup.py b/setup.py index 2a0c525..bc96b5a 100644 --- a/setup.py +++ b/setup.py @@ -12,6 +12,8 @@ requires=['urllib', 'urllib2', 'simplejson'] elif version >= '2.6': requires=['urllib', 'urllib2', 'json'] +elif version >= '3.0': + requires=['urllib', 'json'] else: #unknown version? requires=['urllib', 'urllib2']