2

I've been using Python to access the Rdio API a fair bit so decided to add a couple methods to the Rdio module to make life easier. I keep getting stymied.

Here, as background, is some of the Rdio Python module provided by the company:

class Rdio:
  def __init__(self, consumer, token=None):
    self.__consumer = consumer
    self.token = token

  def __signed_post(self, url, params):
    auth = om(self.__consumer, url, params, self.token)
    req = urllib2.Request(url, urllib.urlencode(params), {'Authorization': auth})
    res = urllib2.urlopen(req)
    return res.read()

  def call(self, method, params=dict()):
    # make a copy of the dict
    params = dict(params)
    # put the method in the dict
    params['method'] = method
    # call to the server and parse the response
    return json.loads(self.__signed_post('http://api.rdio.com/1/', params))

Okay, all well and good. Those functions work fine. So I decided to create a method that would copy a playlist with key1 into a playlist with key2. Here's the code:

def copy_playlist(self, key1, key2):
  #get track keys from first playlist
  playlist = self.call('get', {'keys': key1, 'extras' : 'tracks'})

  track_keys = []   

  for track in tracks:
      key = track['key']
      track_keys.append(key)

  #convert track list into single, comma-separated string (which the API requires)
  keys_string = ', '.join(track_keys)

  #add the tracks to the second playlist
  self.call('addToPlaylist', {'playlist' : key2, 'tracks' : keys_string})

This code works fine if I do it from the terminal or in an external Python file, but for some reason when I include it as part of the Rdio class, then initiate the Rdio object as rdio and call the playlist method, I always get the following error:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "rdio_extended.py", line 83, in copy_playlist

NameError: global name 'rdio' is not defined

I can't seem to get around this. There's probably a simple answer - I'm pretty new to programming - but I'm stumped.

UPDATE: Updated code formatting, and here's the actual code that creates the Rdio object:

rdio = Rdio((RDIO_CONSUMER_KEY, RDIO_CONSUMER_SECRET), (RDIO_TOKEN, RDIO_TOKEN_SECRET))

And then this is the line to call the playlist-copying function:

rdio.copy_playlist(key1, key2)

That results in the NameError described above.

devin_s
  • 3,345
  • 1
  • 27
  • 32
Barrett
  • 161
  • 1
  • 1
  • 9
  • 4
    You are not showing us the code which generated the error, because none of the code you show refers to a variable named `rdio`. We cannot help you with invisible code. Please show us your actual code, and somebody will no doubt be able to help. However, I have voted your question up for trying to show us the relevant code. – Marcin Nov 13 '12 at 18:44
  • Is this the actual indentation in the file? So there's a class `Rdio`, and then a free function `__signed_post` that happens to take a `self` parameter, as opposed to a method `__signed_post` of the class `Rdio`? – abarnert Nov 13 '12 at 20:27
  • Sorry, I was trying to describe it in the text but guess I wasn't clear enough. I'll amend the post to reflect the actual code. – Barrett Nov 14 '12 at 02:52
  • @abarnert You're right, I screwed up the formatting. The `__signed_post` is indeed a method of the class `Rdio`, not a free function. – Barrett Nov 14 '12 at 02:58
  • 1
    Do not show random lines. Show the code as a whole. – Marcin Nov 14 '12 at 03:02
  • @Marcin that's honestly it. I was just using the Python interpreter to test the new function, so merely initialized the object (which worked fine) then tried calling the new method on it (which didn't). Other methods (like the call() request) still work fine. – Barrett Nov 14 '12 at 14:06
  • 1
    The problem is obviously that the scope you define `rdio` in and the scope you try to use it in are not the same. But until you show us the complete example, or at least enough of it to see the scope of those two lines, nobody can tell you what you got wrong. Maybe you're assigning a local `rdio` inside a function call and expecting it to modify a global variable. Maybe you're calling the method before the assignment happens. Or a hundred other possibilities. You've shown us a whole lot of completely irrelevant code, and then two bare lines without their context. – abarnert Nov 14 '12 at 18:59
  • @abarnert I appreciate your guys' perseverance. I wrote all the code into a single file in order to post here so you could see all the relevant info at once, and voila, it worked. Not sure why, but so it goes. Thanks. – Barrett Nov 14 '12 at 19:20
  • That's another good reason to write a http://sscce.org. Besides the fact that you can get answers instead of comments complaining about your question, half the time you solve the problem for yourself while building the example. However, in this case, I have a guess as to what happened: You had a `foo.py` that created a `foo.rdio` variable, and another `bar.py` that did `import foo` and tried to just use `rdio` instead of `foo.rdio`, hence the `NameError`, which will go away if `foo.py` is just copied and pasted into `bar.py`. – abarnert Nov 14 '12 at 19:32

0 Answers0