docs: def callm(method, param_dict, POST=False, socket_timeout=None, data=None):
      """
      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:
          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] )
              elif val is not None:
                  if isinstance(val, unicode):
                      val = val.encode('utf-8')
                  param_list.append( (key,val) )
  
          params = urllib.urlencode(param_list)
  
          orig_timeout = socket.getdefaulttimeout()
          socket.setdefaulttimeout(socket_timeout)
  
          if(POST):
              if (not method == 'track/upload') or ((method == 'track/upload') and 'url' in param_dict):
                  """
                  this is a normal POST call
                  """
                  url = 'http://%s/%s/%s/%s' % (config.API_HOST, config.API_SELECTOR,
                                              config.API_VERSION, method)
  
                  if data is None:
                      data = ''
                  data = urllib.urlencode(data)
                  data = "&".join([data, params])
  
                  f = opener.open(url, data=data)
              else:
                  """
                  upload with a local file is special, as the body of the request is the content of the file,
                  and the other parameters stay on the URL
                  """
                  url = '/%s/%s/%s?%s' % (config.API_SELECTOR, config.API_VERSION,
                                              method, params)
  
                  if ':' in config.API_HOST:
                      host, port = config.API_HOST.split(':')
                  else:
                      host = config.API_HOST
                      port = 80
  
                  if config.TRACE_API_CALLS:
                      logger.info("%s/%s" % (host+':'+str(port), url,))
                  conn = httplib.HTTPConnection(host, port = port)
                  conn.request('POST', url, body = data, headers = dict([('Content-Type', 'application/octet-stream')]+headers))
                  f = conn.getresponse()
  
          else:
              """
              just a normal GET call
              """
              url = 'http://%s/%s/%s/%s?%s' % (config.API_HOST, config.API_SELECTOR, config.API_VERSION,
                                              method, params)
  
              f = opener.open(url)
  
          socket.setdefaulttimeout(orig_timeout)
  
          # try/except
          response_dict = get_successful_response(f)
          return response_dict
  
      except IOError, e:
          if hasattr(e, 'reason'):
              raise EchoNestIOError(error=e.reason)
          elif hasattr(e, 'code'):
              raise EchoNestIOError(code=e.code)
          else:
              raise