Skip to content

Commit

Permalink
Merge branch 'release/0.7.1-beta'
Browse files Browse the repository at this point in the history
  • Loading branch information
fuzeman committed Jul 1, 2014
2 parents 98d0181 + d2cb44a commit 611b7b1
Show file tree
Hide file tree
Showing 11 changed files with 79 additions and 32 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
*.pyc

/virtualenv
2 changes: 1 addition & 1 deletion spotify/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__version__ = '0.7.0-beta'
__version__ = '0.7.1-beta'

try:
from spotify.client import Spotify
Expand Down
6 changes: 4 additions & 2 deletions spotify/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ def __init__(self, user_agent=None):
self.create_session(user_agent)

# Construct modules
self.commands = CommandManager(self)
self.commands = CommandManager(self)\
.pipe('error', self)

self.components = ComponentManager(self)

# Session data
Expand Down Expand Up @@ -112,7 +114,7 @@ def on_command(self, name, *args):
if name == 'login_complete':
return self.on_login_complete()

return self.emit('error', 'Unhandled command with name "%s"' % name)
log.warn('Unhandled command with name "%s"', name)

def on_login_complete(self):
self.send('sp/log', 41, 1, 1656, 951, 0, 0)
Expand Down
3 changes: 2 additions & 1 deletion spotify/commands/base.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from spotify.components.base import Component
from pyemitter import Emitter


class Command(Component):
class Command(Component, Emitter):
pass
22 changes: 21 additions & 1 deletion spotify/commands/manager.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,36 @@
from spotify.commands import DoWork, PingFlash2

from pyemitter import Emitter
import logging

class CommandManager(object):
log = logging.getLogger(__name__)


class CommandManager(Emitter):
def __init__(self, sp):
self.sp = sp

self.handlers = {
'do_work': DoWork(sp),
'ping_flash2': PingFlash2(sp)
}

# Attach 'error' listeners
for command in self.handlers.values():
command.on('error', self.on_error)

def process(self, name, *args):
if name in self.handlers:
self.handlers[name].process(*args)
return True

return False

def on_error(self, message):
log.warn('Error returned from command handler, disconnecting...')

# Trigger disconnection
self.sp.components.connection.disconnect()

# Fire 'error'
self.emit('error', message)
12 changes: 10 additions & 2 deletions spotify/commands/work.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import execjs
import logging
import traceback

log = logging.getLogger(__name__)

Expand All @@ -26,8 +27,15 @@ class DoWork(Command):
def process(self, payload):
log.debug("got work, payload: %s", payload)

ctx = execjs.compile(WORK_RUNNER % payload)
result = ctx.eval('main.run.call(main)')
try:
ctx = execjs.compile(WORK_RUNNER % payload)
result = ctx.eval('main.run.call(main)')
except execjs.RuntimeUnavailable, ex:
self.emit('error', 'JavaScript runtime is not available, try installing node.js (http:https://nodejs.org)')
return
except Exception, ex:
log.warn('Unable to run work - %s - %s', ex, traceback.format_exc())
return

log.debug('result: %s' % result)

Expand Down
18 changes: 9 additions & 9 deletions spotify/components/authentication.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
re.IGNORECASE | re.DOTALL
)

AUTH_ERRORS = {
'invalid_credentials': 'Invalid account credentials provided, check your username/password'
}

log = logging.getLogger(__name__)


Expand All @@ -24,11 +28,6 @@ def __init__(self, sp):
self.credentials = {'type': 'anonymous'}
self.landing_params = None

# Broadcast errors upstream
@self.on('error')
def on_error(*args, **kwargs):
self.sp.emit('error', *args, **kwargs)

def login(self, username=None, password=None):
if username and password:
self.credentials = {
Expand Down Expand Up @@ -119,12 +118,13 @@ def on_auth(self, future):
data = res.json()

if data['status'] == 'ERROR':
msg = data.get('error', 'unknown')
error = data.get('error', 'unknown')
message = data.get('message')

if data.get('message'):
msg += ': ' + data['message']
if not message:
message = AUTH_ERRORS.get(error, 'Unknown')

self.emit('error', msg)
self.emit('error', '%s (%s)' % (message, error))
return

self.emit('authenticated', data['config'])
Expand Down
3 changes: 2 additions & 1 deletion spotify/components/connection.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from spotify.components.base import Component
from spotify.core.helpers import repr_trim
from spotify.core.request import Request

from pyemitter import Emitter
Expand Down Expand Up @@ -141,7 +142,7 @@ def send_message(self, message):
raise Exception('Unable to send message, socket has been closed')

encoded = json.dumps(message, separators=(',', ':'))
log.debug('send encoded: %s' % repr(encoded))
log.debug('send encoded: %s' % repr_trim(encoded))

with self.send_lock:
self.client.send(encoded)
Expand Down
9 changes: 9 additions & 0 deletions spotify/core/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,12 @@ def convert(value, to_type, default=None):
return to_type(value)
except:
return default


def repr_trim(value, length=1000):
value = repr(value)

if len(value) < length:
return value

return '<%s - %s characters>' % (type(value).__name__, len(value))
32 changes: 18 additions & 14 deletions spotify/hermes/cache.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from spotify.core.helpers import convert
from spotify.core.uri import Uri

from threading import Lock
import logging
import time

Expand All @@ -21,6 +22,7 @@ class HermesCache(object):

def __init__(self):
self._store = {}
self._store_lock = Lock()

def get_schema_key(self, content_type):
key = self.schema_types.get(content_type)
Expand Down Expand Up @@ -70,12 +72,13 @@ def store(self, header, content_type, internal):
if not k_content or not k_item:
return None

if self._store.get(k_content) is None:
self._store[k_content] = {}
with self._store_lock:
if self._store.get(k_content) is None:
self._store[k_content] = {}

item = HermesCacheObject.create(header, content_type, internal)
item = HermesCacheObject.create(header, content_type, internal)

self._store[k_content][k_item] = item
self._store[k_content][k_item] = item

return item

Expand All @@ -85,20 +88,21 @@ def get(self, uri):
if not k_content or not k_item:
return None

if self._store.get(k_content) is None:
return None
with self._store_lock:
if self._store.get(k_content) is None:
return None

item = self._store[k_content].get(k_item)
item = self._store[k_content].get(k_item)

if item is None:
return None
if item is None:
return None

log.debug('retrieved "%s" from cache (timestamp: %s, valid: %s)', uri,
item.timestamp, item.is_valid())
log.debug('retrieved "%s" from cache (timestamp: %s, valid: %s)', uri,
item.timestamp, item.is_valid())

if not item.is_valid():
del self._store[k_content][k_item]
return None
if not item.is_valid():
del self._store[k_content][k_item]
return None

return item

Expand Down
2 changes: 1 addition & 1 deletion spotify/objects/playlist.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ def fetch_tracks(self, batch_size=100):
event = REvent()
self.sp.metadata(uris, callback=lambda items: event.set(items))

tracks = event.wait(5)
tracks = event.wait(10)

# Check if there was a request timeout
if tracks is None:
Expand Down

0 comments on commit 611b7b1

Please sign in to comment.