diff --git a/bin/cohen b/bin/cohen index 82ca5f91..39af8f10 100755 --- a/bin/cohen +++ b/bin/cohen @@ -33,12 +33,12 @@ def daemonize(): os.setsid() if os.fork(): # launch child and... os._exit(0) # kill off parent again. - os.umask(077) + os.umask(0o77) null = os.open('/dev/null', os.O_RDWR) for i in range(3): try: os.dup2(null, i) - except OSError, e: + except OSError as e: if e.errno != errno.EBADF: raise os.close(null) @@ -78,7 +78,7 @@ if __name__ == '__main__': from coherence.base import Plugins # hack: avoid plugins are displaying there help message sys.argv = sys.argv[:1] - p = Plugins().keys() + p = list(Plugins().keys()) p.sort() self.epilog = 'Available backends are: %s' % ', '.join(p) optparse.OptionParser.print_help(self, file) @@ -108,7 +108,7 @@ if __name__ == '__main__': try: daemonize() except: - print traceback.format_exc() + print(traceback.format_exc()) config = {} @@ -116,7 +116,7 @@ if __name__ == '__main__': try: config = ConfigObj(options.configfile) except IOError: - print "Config file %r not found, ignoring" % options.configfile + print("Config file %r not found, ignoring" % options.configfile) pass if 'logging' not in config: @@ -126,7 +126,7 @@ if __name__ == '__main__': config['logging']['logfile'] = options.logfile # copy options passed by -o/--option into config - for k, v in options.options.items(): + for k, v in list(options.options.items()): if k == 'logfile': continue config[k] = v @@ -142,7 +142,7 @@ if __name__ == '__main__': from twisted.internet import glib2reactor glib2reactor.install() except AssertionError: - print "error installing glib2reactor" + print("error installing glib2reactor") if options.plugins: plugins = config.get('plugin') @@ -172,7 +172,7 @@ if __name__ == '__main__': try: plugins.append(plugin) except AttributeError: - print "mixing commandline plugins and configfile does not work with the old config file format" + print("mixing commandline plugins and configfile does not work with the old config file format") from twisted.internet import reactor diff --git a/coherence/backend.py b/coherence/backend.py index d6f9f77f..47ba7229 100644 --- a/coherence/backend.py +++ b/coherence/backend.py @@ -5,6 +5,7 @@ # Copyright 2007,, Frank Scholz from lxml import etree +from functools import cmp_to_key import time from coherence.extern.simple_plugin import Plugin @@ -211,7 +212,7 @@ def __init__(self, *args, **kwargs): self.item.res.append(res) """ log.Loggable.__init__(self) - self.name = u'my_name' # the basename of a file, the album title, + self.name = 'my_name' # the basename of a file, the album title, # the artists name,... # is expected to be unicode self.item = None @@ -350,7 +351,7 @@ def __init__(self, parent, title): self.sorted = False def childs_sort(x, y): - return cmp(x.name, y.name) + return cmp_to_key(x.name, y.name) self.sorting_method = childs_sort def register_child(self, child, external_id=None): @@ -381,7 +382,8 @@ def remove_child(self, child, external_id=None, update=True): def get_children(self, start=0, end=0): if not self.sorted: - self.children.sort(cmp=self.sorting_method) + self.children = sorted( + self.children.sort, key=cmp_to_key(self.sorting_method)) self.sorted = True if end != 0: return self.children[start:end] @@ -423,7 +425,7 @@ def __init__(self, parent, title, external_id=None, refresh=0, childrenRetriever self.children_retrieval_campaign_in_progress = False self.childrenRetriever_params = kwargs self.childrenRetriever_params['parent'] = self - self.has_pages = (self.childrenRetriever_params.has_key('per_page')) + self.has_pages = ('per_page' in self.childrenRetriever_params) self.external_id = None self.external_id = external_id @@ -453,10 +455,10 @@ def update_children(self, new_children, old_children): # let's classify the item between items to be removed, # to be updated or to be added self.debug("Refresh pass 1:%d %d", len(new_children), len(old_children)) - for id, item in old_children.items(): + for id, item in list(old_children.items()): children_to_be_removed[id] = item - for id, item in new_children.items(): - if old_children.has_key(id): + for id, item in list(new_children.items()): + if id in old_children: #print(id, "already there") children_to_be_replaced[id] = old_children[id] del children_to_be_removed[id] @@ -468,10 +470,10 @@ def update_children(self, new_children, old_children): # to the list of items self.debug("Refresh pass 2: %d %d %d", len(children_to_be_removed), len(children_to_be_replaced), len(children_to_be_added)) # Remove relevant items from Container children - for id, item in children_to_be_removed.items(): + for id, item in list(children_to_be_removed.items()): self.remove_child(item, external_id=id, update=False) # Update relevant items from Container children - for id, item in children_to_be_replaced.items(): + for id, item in list(children_to_be_replaced.items()): old_item = item new_item = new_children[id] replaced = False @@ -482,7 +484,7 @@ def update_children(self, new_children, old_children): self.remove_child(old_item, external_id=id, update=False) self.add_child(new_item, external_id=id, update=False) # Add relevant items to COntainer children - for id, item in children_to_be_added.items(): + for id, item in list(children_to_be_added.items()): self.add_child(item, external_id=id, update=False) self.update_id += 1 @@ -586,7 +588,7 @@ def remove_item(self, item): item.store = None def get_by_id(self, id): - if isinstance(id, basestring): + if isinstance(id, str): id = id.split('@', 1) id = id[0].split('.')[0] try: diff --git a/coherence/backends/ampache_storage.py b/coherence/backends/ampache_storage.py index 59ddf5b3..0205e216 100644 --- a/coherence/backends/ampache_storage.py +++ b/coherence/backends/ampache_storage.py @@ -53,7 +53,7 @@ def md5(s): VIDEO_CONTAINER_ID = 200 -from urlparse import urlsplit +from urllib.parse import urlsplit class ProxySong(utils.ReverseProxyResource): @@ -416,11 +416,8 @@ def __init__(self, store, element): self.url = element.find('url').text seconds = int(element.find('time').text) - hours = seconds / 3600 - seconds = seconds - hours * 3600 - minutes = seconds / 60 - seconds = seconds - minutes * 60 - self.duration = ("%d:%02d:%02d") % (hours, minutes, seconds) + self.duration = time.strftime( + '%H:%M:%S', time.gmtime(seconds)) self.bitrate = 0 @@ -624,10 +621,10 @@ def __repr__(self): def get_by_id(self, id): self.info("looking for id %r", id) - if isinstance(id, basestring): + if isinstance(id, str): id = id.split('@', 1) id = id[0] - if isinstance(id, basestring) and id.startswith('artist_all_tracks_'): + if isinstance(id, str) and id.startswith('artist_all_tracks_'): try: return self.containers[id] except: @@ -649,7 +646,7 @@ def got_auth_response(self, response, renegotiate=False): self.info("got_auth_response %r", response) try: response = etree.fromstring(response) - except SyntaxError, msg: + except SyntaxError as msg: self.warning('error parsing ampache answer %r', msg) raise SyntaxError('error parsing ampache answer %r' % msg) try: @@ -944,7 +941,7 @@ def build_response(tm): wmc_mapping = getattr(self, "wmc_mapping", None) if(kwargs.get('X_UPnPClient', '') == 'XBox' and wmc_mapping != None and - wmc_mapping.has_key(ObjectID)): + ObjectID in wmc_mapping): """ fake a Windows Media Connect Server """ root_id = wmc_mapping[ObjectID] @@ -1036,7 +1033,7 @@ def proceed(result): def main(): def got_result(result): - print "got_result" + print("got_result") def call_browse(ObjectID=0, StartingIndex=0, RequestedCount=0): r = f.backend.upnp_Browse(BrowseFlag='BrowseDirectChildren', diff --git a/coherence/backends/appletrailers_storage.py b/coherence/backends/appletrailers_storage.py index a733b305..342ac134 100644 --- a/coherence/backends/appletrailers_storage.py +++ b/coherence/backends/appletrailers_storage.py @@ -9,6 +9,7 @@ This is a Media Backend that allows you to access the Trailers from Apple.com """ from lxml import etree +from functools import cmp_to_key from coherence.backend import BackendItem, BackendStore from coherence.upnp.core import DIDLLite @@ -221,8 +222,14 @@ def upnp_init(self): self.server.connection_manager_server.set_variable( \ 0, 'SourceProtocolInfo', ['http-get:*:video/quicktime:*', 'http-get:*:video/mp4:*']) self.container = Container(ROOT_ID, -1, self.name) - trailers = self.trailers.values() - trailers.sort(cmp=lambda x, y: cmp(x.get_name().lower(), y.get_name().lower())) + trailers = list(self.trailers.values()) + # trailers.sort(cmp=lambda x, y: cmp( + # x.get_name().lower(), y.get_name().lower())) + trailers = sorted( + trailers, + key=lambda x, y: cmp_to_key( + x.get_name().lower(), + y.get_name().lower())) self.container.children = trailers def __repr__(self): diff --git a/coherence/backends/audiocd_storage.py b/coherence/backends/audiocd_storage.py index f4020a6e..a90cc250 100644 --- a/coherence/backends/audiocd_storage.py +++ b/coherence/backends/audiocd_storage.py @@ -134,7 +134,7 @@ def extractAudioCdInfo (self): self.disc_title = query_info['title'].encode('utf-8') tracks = {} for i in range(track_count): - tracks[i + 1] = read_info['TTITLE' + `i`].decode('ISO-8859-1').encode('utf-8') + tracks[i + 1] = read_info['TTITLE' + repr(i)].decode('ISO-8859-1').encode('utf-8') self.name = self.disc_title @@ -147,7 +147,7 @@ def childs_sort(x, y): self.set_root_item(root_item) - for number, title in tracks.items(): + for number, title in list(tracks.items()): item = TrackItem(self.device_name, number, "Unknown", title) external_id = "%s_%d" % (disc_id, number) root_item.add_child(item, external_id=external_id) diff --git a/coherence/backends/axiscam_storage.py b/coherence/backends/axiscam_storage.py index 62725a83..4a6d2345 100644 --- a/coherence/backends/axiscam_storage.py +++ b/coherence/backends/axiscam_storage.py @@ -7,7 +7,6 @@ # for the RTP payload type identifier # -from sets import Set from coherence.upnp.core.DIDLLite import classChooser, Container, Resource, DIDLElement @@ -142,7 +141,7 @@ def __repr__(self): return str(self.__class__).split('.')[-1] def append(self, obj, parent): - if isinstance(obj, basestring): + if isinstance(obj, str): mimetype = 'directory' else: protocol, network, content_type, info = obj['protocol'].split(':') @@ -175,7 +174,7 @@ def len(self): return len(self.store) def get_by_id(self, id): - if isinstance(id, basestring): + if isinstance(id, str): id = id.split('@', 1) id = id[0] id = int(id) @@ -195,9 +194,9 @@ def upnp_init(self): self.current_connection_id = None parent = self.append('AxisCam', None) - source_protocols = Set() + source_protocols = set() - for k, v in self.config.items(): + for k, v in list(self.config.items()): if isinstance(v, dict): v['name'] = k source_protocols.add(v['protocol']) @@ -214,7 +213,7 @@ def main(): f = AxisCamStore(None) def got_upnp_result(result): - print "upnp", result + print("upnp", result) #f.upnp_init() #print f.store diff --git a/coherence/backends/banshee_storage.py b/coherence/backends/banshee_storage.py index 0d3b3f98..b768e3ea 100644 --- a/coherence/backends/banshee_storage.py +++ b/coherence/backends/banshee_storage.py @@ -26,8 +26,8 @@ import re import os import time -from urlparse import urlsplit -import urllib2 +from urllib.parse import urlsplit +import urllib.request, urllib.error, urllib.parse import mimetypes mimetypes.init() @@ -102,8 +102,8 @@ def sql_execute(self, request, *params, **kw): t0 = time.time() debug_msg = request if params: - debug_msg = u"%s params=%r" % (request, params) - debug_msg = u''.join(debug_msg.splitlines()) + debug_msg = "%s params=%r" % (request, params) + debug_msg = ''.join(debug_msg.splitlines()) if debug_msg: self.debug('QUERY: %s', debug_msg) @@ -500,7 +500,7 @@ def get_resources(self): return statinfo, resources def get_path(self): - return urllib2.unquote(self.location[7:].encode('utf-8')) + return urllib.parse.unquote(self.location[7:].encode('utf-8')) def get_id(self): return "track.%d" % self.itemID @@ -850,7 +850,7 @@ def release(self): def get_by_id(self, item_id): self.info("get_by_id %s", item_id) - if isinstance(item_id, basestring) and item_id.find('.') > 0: + if isinstance(item_id, str) and item_id.find('.') > 0: item_id = item_id.split('@', 1) item_type, item_id = item_id[0].split('.')[:2] item_id = int(item_id) diff --git a/coherence/backends/bbc_storage.py b/coherence/backends/bbc_storage.py index 825a6c8a..830a71bc 100644 --- a/coherence/backends/bbc_storage.py +++ b/coherence/backends/bbc_storage.py @@ -5,6 +5,7 @@ # Copyright 2008 Frank Scholz from lxml import etree +from functools import cmp_to_key from twisted.internet import reactor @@ -64,7 +65,7 @@ def __init__(self, id, store, parent_id, title): def add_child(self, child): id = child.id - if isinstance(child.id, basestring): + if isinstance(child.id, str): _, id = child.id.split('.') self.children.append(child) self.item.childCount += 1 @@ -73,10 +74,11 @@ def add_child(self, child): def get_children(self, start=0, end=0): if self.sorted == False: def childs_sort(x, y): - r = cmp(x.name, y.name) + r = cmp_to_key(x.name, y.name) return r - self.children.sort(cmp=childs_sort) + self.children = sorted( + self.children.sort, key=childs_sort) self.sorted = True if end != 0: return self.children[start:end] @@ -122,7 +124,7 @@ def get_next_id(self): def get_by_id(self, id): #print "looking for id %r" % id - if isinstance(id, basestring): + if isinstance(id, str): id = id.split('@', 1) id = id[0] try: @@ -140,7 +142,7 @@ def upnp_init(self): def update_data(self): def fail(f): - print "fail", f + print("fail", f) return f dfr = getPage(self.rss_url) diff --git a/coherence/backends/buzztard_control.py b/coherence/backends/buzztard_control.py index ef47be6e..ea31ca09 100755 --- a/coherence/backends/buzztard_control.py +++ b/coherence/backends/buzztard_control.py @@ -3,7 +3,7 @@ # Copyright 2007, Frank Scholz -from urlparse import urlsplit +from urllib.parse import urlsplit from twisted.internet import reactor, protocol from twisted.internet import reactor @@ -540,11 +540,11 @@ def upnp_SetAVTransportURI(self, *args, **kwargs): return {} else: elt = DIDLLite.DIDLElement.fromString(CurrentURIMetaData) - print elt.numItems() + print(elt.numItems()) if elt.numItems() == 1: item = elt.getItems()[0] for res in item.res: - print res.protocolInfo, local_protocol_info + print(res.protocolInfo, local_protocol_info) if res.protocolInfo in local_protocol_info: self.load(CurrentURI, CurrentURIMetaData) return {} @@ -570,7 +570,7 @@ def upnp_SetVolume(self, *args, **kwargs): def test_init_complete(backend): - print "Houston, we have a touchdown!" + print("Houston, we have a touchdown!") backend.buzztard.sendMessage('browse') @@ -581,14 +581,14 @@ def main(): f = BuzztardStore(None) f.parent = f.append('Buzztard', 'directory', None) - print f.parent - print f.store + print(f.parent) + print(f.store) f.add_content('playlist|test label|start|stop') - print f.store + print(f.store) f.clear() - print f.store + print(f.store) f.add_content('playlist|after flush label|flush-start|flush-stop') - print f.store + print(f.store) #def got_upnp_result(result): # print "upnp", result diff --git a/coherence/backends/dvbd_storage.py b/coherence/backends/dvbd_storage.py index 15b45dea..7bb7a237 100644 --- a/coherence/backends/dvbd_storage.py +++ b/coherence/backends/dvbd_storage.py @@ -4,7 +4,7 @@ # Copyright 2008, Frank Scholz from datetime import datetime -import urllib +import urllib.request, urllib.parse, urllib.error from twisted.internet import reactor, defer from twisted.python import failure, util @@ -55,7 +55,7 @@ def __init__(self, id, parent_id, name, store=None, children_callback=None, cont def add_child(self, child): id = child.id - if isinstance(child.id, basestring): + if isinstance(child.id, str): _, id = child.id.split('.') self.children[id] = child if self.item.childCount != None: @@ -67,7 +67,7 @@ def get_children(self, start=0, end=0): if callable(self.children): return self.children(start, end - start) else: - children = self.children.values() + children = list(self.children.values()) if end == 0: return children[start:] else: @@ -111,8 +111,8 @@ def __init__(self, store, self.parent_id = parent_id self.real_id = id - self.name = unicode(name) - self.network = unicode(network) + self.name = str(name) + self.network = str(network) self.stream_url = url self.mimetype = str(mimetype) @@ -152,19 +152,19 @@ def __init__(self, store, self.parent_id = parent_id self.real_id = id - path = unicode(file) + path = str(file) # make sure path is an absolute local path (and not an URL) if path.startswith("file://"): path = path[7:] self.location = FilePath(path) - self.title = unicode(title) + self.title = str(title) self.mimetype = str(mimetype) self.date = datetime.fromtimestamp(int(date)) self.duration = int(duration) try: self.size = self.location.getsize() - except Exception, msg: + except Exception as msg: self.size = 0 self.bitrate = 0 self.url = self.store.urlbase + str(self.id) @@ -195,7 +195,7 @@ def get_item(self, parent_id=None): item.res.append(res) # add internal resource - res = DIDLLite.Resource('file://' + urllib.quote(self.get_path()), 'internal:%s:%s:*' % (self.store.server.coherence.hostname, self.mimetype)) + res = DIDLLite.Resource('file://' + urllib.parse.quote(self.get_path()), 'internal:%s:%s:*' % (self.store.server.coherence.hostname, self.mimetype)) if self.size > 0: res.size = self.size if self.duration > 0: @@ -291,7 +291,7 @@ def __repr__(self): def get_by_id(self, id): self.info("looking for id %r", id) - if isinstance(id, basestring): + if isinstance(id, str): id = id.split('@', 1) id = id[0] @@ -491,7 +491,7 @@ def process_details(results): for result, channel in results: #print channel if result == True: - name = unicode(channel['name'], errors='ignore') + name = str(channel['name'], errors='ignore') #print "add", name, channel['url'] video_item = Channel(self, channel['id'], @@ -603,7 +603,7 @@ def hidden_upnp_DestroyObject(self, *args, **kwargs): return failure.Failure(errorCode(701)) def handle_success(deleted): - print 'deleted', deleted, kwargs['ObjectID'] + print('deleted', deleted, kwargs['ObjectID']) if deleted == False: return failure.Failure(errorCode(715)) return {} diff --git a/coherence/backends/elisa_storage.py b/coherence/backends/elisa_storage.py index c4c7c57c..d9a10419 100644 --- a/coherence/backends/elisa_storage.py +++ b/coherence/backends/elisa_storage.py @@ -190,7 +190,7 @@ def main(): p = 'localhost' def got_result(result): - print result + print(result) f = MediaStore(None, 'my media', p, 'http://localhost/', ()) diff --git a/coherence/backends/feed_storage.py b/coherence/backends/feed_storage.py index 92ff1141..6576eb09 100644 --- a/coherence/backends/feed_storage.py +++ b/coherence/backends/feed_storage.py @@ -9,9 +9,9 @@ from coherence.upnp.core.utils import ReverseProxyUriResource from xml.etree.ElementTree import ElementTree -import urllib -import httplib -from urlparse import urlsplit +import urllib.request, urllib.parse, urllib.error +import http.client +from urllib.parse import urlsplit try: import feedparser except: @@ -36,7 +36,7 @@ def render(self, request): def follow_redirect(self, uri): netloc, path, query, fragment = urlsplit(uri)[1:] - conn = httplib.HTTPConnection(netloc) + conn = http.client.HTTPConnection(netloc) conn.request('HEAD', '%s?%s#%s' % (path, query, fragment)) res = conn.getresponse() if(res.status == 301 or res.status == 302): @@ -135,13 +135,13 @@ def __init__(self, server, **kwargs): try: self._update_data() - except Exception, e: + except Exception as e: self.error('error while updateing the feed contant for %s: %s', self.name, str(e)) self.init_completed() def get_by_id(self, id): """returns the item according to the DIDLite id""" - if isinstance(id, basestring): + if isinstance(id, str): id = id.split('@', 1) id = id[0] try: @@ -154,7 +154,7 @@ def _update_data(self): """get the feed xml, parse it, etc.""" feed_urls = [] if(self.opml_url): - tree = ElementTree(file=urllib.urlopen(self.opml_url)) + tree = ElementTree(file=urllib.request.urlopen(self.opml_url)) body = tree.find('body') for outline in body.findall('outline'): feed_urls.append(outline.attrib['url']) @@ -165,7 +165,7 @@ def _update_data(self): item_id = 1001 for feed_url in feed_urls: netloc, path, query, fragment = urlsplit(feed_url)[1:] - conn = httplib.HTTPConnection(netloc) + conn = http.client.HTTPConnection(netloc) conn.request('HEAD', '%s?%s#%s' % (path, query, fragment)) res = conn.getresponse() if res.status >= 400: diff --git a/coherence/backends/flickr_storage.py b/coherence/backends/flickr_storage.py index 02d2a93a..dd048cf3 100644 --- a/coherence/backends/flickr_storage.py +++ b/coherence/backends/flickr_storage.py @@ -50,7 +50,7 @@ def md5(s): from coherence import log -from urlparse import urlsplit +from urllib.parse import urlsplit ROOT_CONTAINER_ID = 0 INTERESTINGNESS_CONTAINER_ID = 100 @@ -121,7 +121,7 @@ def __init__(self, id, obj, parent, mimetype, urlbase, UPnPClass, store=None, up if isinstance(obj, str): self.name = obj - if isinstance(self.id, basestring) and self.id.startswith('upload.'): + if isinstance(self.id, str) and self.id.startswith('upload.'): self.mimetype = mimetype else: self.mimetype = 'directory' @@ -148,7 +148,7 @@ def __init__(self, id, obj, parent, mimetype, urlbase, UPnPClass, store=None, up self.mimetype = 'image/jpeg' self.parent = parent - if not (isinstance(self.id, basestring) and self.id.startswith('upload.')): + if not (isinstance(self.id, str) and self.id.startswith('upload.')): if parent: parent.add_child(self, update=update) @@ -161,7 +161,7 @@ def __init__(self, id, obj, parent, mimetype, urlbase, UPnPClass, store=None, up except: self.flickr_id = None self.url = urlbase + str(self.id) - elif isinstance(self.id, basestring) and self.id.startswith('upload.'): + elif isinstance(self.id, str) and self.id.startswith('upload.'): self.url = urlbase + str(self.id) self.location = None else: @@ -187,7 +187,7 @@ def __init__(self, id, obj, parent, mimetype, urlbase, UPnPClass, store=None, up self.url = urlbase + str(self.id) self.location = ProxyImage(self.real_url) else: - self.url = u"http://farm%s.static.flickr.com/%s/%s_%s.jpg" % ( + self.url = "http://farm%s.static.flickr.com/%s/%s_%s.jpg" % ( obj.get('farm').encode('utf-8'), obj.get('server').encode('utf-8'), obj.get('id').encode('utf-8'), @@ -260,7 +260,7 @@ def get_update_id(self): return None def get_path(self): - if isinstance(self.id, basestring) and self.id.startswith('upload.'): + if isinstance(self.id, str) and self.id.startswith('upload.'): return '/tmp/' + self.id # FIXME return self.url @@ -626,7 +626,7 @@ def len(self): return len(self.store) def get_by_id(self, id): - if isinstance(id, basestring) and id.startswith('upload.'): + if isinstance(id, str) and id.startswith('upload.'): self.info("get_by_id looking for %s", id) try: item = self.uploads[id] @@ -635,7 +635,7 @@ def get_by_id(self, id): except: return None - if isinstance(id, basestring): + if isinstance(id, str): id = id.split('@', 1) id = id[0] try: @@ -670,8 +670,8 @@ def update_flickr_result(self, result, parent, element='photo'): old_ones[child.get_flickr_id()] = child for photo in result.findall(element): new_ones[photo.get('id')] = photo - for id, child in old_ones.items(): - if new_ones.has_key(id): + for id, child in list(old_ones.items()): + if id in new_ones: self.debug("%s already there", id) del new_ones[id] elif child.id != UNSORTED_CONTAINER_ID: @@ -680,7 +680,7 @@ def update_flickr_result(self, result, parent, element='photo'): self.remove(child.get_id()) self.info("refresh pass 1: old: %i - new: %i - store: %i", len(old_ones), len(new_ones), len(self.store)) - for photo in new_ones.values(): + for photo in list(new_ones.values()): if element == 'photo': self.appendPhoto(photo, parent) elif element == 'photoset': @@ -862,13 +862,13 @@ def flickr_create_api_signature(self, **fields): def flickr_authenticate_app(self): def got_error(error): - print error + print(error) def got_auth_token(result): - print "got_auth_token", result + print("got_auth_token", result) result = result.getroot() token = result.find('token').text - print 'token', token + print('token', token) self.flickr_authtoken = token self.server.coherence.store_plugin_config(self.server.uuid, {'authtoken': token}) @@ -879,10 +879,10 @@ def get_auth_token(result, frob): return d def got_frob(result): - print "flickr", result + print("flickr", result) result = result.getroot() frob = result.text - print frob + print(frob) from twisted.internet import threads d = threads.deferToThread(FlickrAuthenticate, self.flickr_api_key, self.flickr_api_secret, frob, self.flickr_userid, self.flickr_password, self.flickr_permissions) d.addCallback(get_auth_token, frob) @@ -906,7 +906,7 @@ def soap_flickr_test_echo(self, value): api_key='837718c8a622c699edab0ea55fcec224') def got_results(result): - print result + print(result) d.addCallback(got_results) return d @@ -979,7 +979,7 @@ def upnp_init(self): d.addCallback(self.append_flickr_contact_result, self.contacts) def upnp_ImportResource(self, *args, **kwargs): - print 'upnp_ImportResource', args, kwargs + print('upnp_ImportResource', args, kwargs) SourceURI = kwargs['SourceURI'] DestinationURI = kwargs['DestinationURI'] @@ -996,11 +996,11 @@ def upnp_ImportResource(self, *args, **kwargs): def gotPage(result): try: - import cStringIO as StringIO + import io as StringIO except ImportError: - import StringIO + import io - self.backend_import(item, StringIO.StringIO(result[0])) + self.backend_import(item, io.StringIO(result[0])) def gotError(error, url): self.warning("error requesting %s", url) @@ -1015,7 +1015,7 @@ def gotError(error, url): return {'TransferID': transfer_id} def upnp_CreateObject(self, *args, **kwargs): - print "upnp_CreateObject", args, kwargs + print("upnp_CreateObject", args, kwargs) ContainerID = kwargs['ContainerID'] Elements = kwargs['Elements'] @@ -1066,7 +1066,7 @@ def upnp_CreateObject(self, *args, **kwargs): didl = DIDLElement() didl.addItem(new_item.item) r = {'ObjectID': new_id, 'Result': didl.toString()} - print r + print(r) return r return failure.Failure(errorCode(712)) @@ -1075,7 +1075,7 @@ def upnp_CreateObject(self, *args, **kwargs): def encode_multipart_form(self, fields): boundary = mimetools.choose_boundary() body = [] - for k, v in fields.items(): + for k, v in list(fields.items()): body.append("--" + boundary.encode("utf-8")) header = 'Content-Disposition: form-data; name="%s";' % k if isinstance(v, FilePath): @@ -1102,7 +1102,7 @@ def encode_multipart_form(self, fields): def flickr_upload(self, image, **kwargs): fields = {} - for k, v in kwargs.items(): + for k, v in list(kwargs.items()): if v != None: fields[k] = v @@ -1114,16 +1114,18 @@ def flickr_upload(self, image, **kwargs): fields['photo'] = image (content_type, formdata) = self.encode_multipart_form(fields) - headers = {"Content-Type": content_type, - "Content-Length": str(len(formdata))} + headers = {b"Content-Type": bytes( + content_type, encoding='utf-8'), + b"Content-Length": bytes( + str(len(formdata)), encoding='utf-8')} - d = getPage("http://api.flickr.com/services/upload/", - method="POST", - headers=headers, - postdata=formdata) + d = getPage(b"http://api.flickr.com/services/upload/", + method=b"POST", + headers=headers, + postdata=formdata) def got_something(result): - print "got_something", result + print("got_something", result) result = parse_xml(result[0], encoding='utf-8') result = result.getroot() if(result.attrib['stat'] == 'ok' and @@ -1149,7 +1151,7 @@ def got_photoid(id, item): d = self.flickr_photos_getInfo(photo_id=id) def add_it(obj, parent): - print "add_it", obj, obj.getroot(), parent + print("add_it", obj, obj.getroot(), parent) root = obj.getroot() self.appendPhoto(obj.getroot(), parent) return 200 @@ -1159,7 +1161,7 @@ def add_it(obj, parent): return d def got_fail(err): - print err + print(err) return err d.addCallback(got_photoid, item) @@ -1174,14 +1176,14 @@ def main(): authtoken='xxx-x') def got_flickr_result(result): - print "flickr", result + print("flickr", result) for photo in result.getiterator('photo'): title = photo.get('title').encode('utf-8') if len(title) == 0: - title = u'untitled' + title = 'untitled' - for k, item in photo.items(): - print k, item + for k, item in list(photo.items()): + print(k, item) url = "http://farm%s.static.flickr.com/%s/%s_%s.jpg" % ( photo.get('farm').encode('utf-8'), @@ -1193,13 +1195,13 @@ def got_flickr_result(result): # photo.get('server').encode('utf-8'), # photo.get('id').encode('utf-8'), # photo.get('originalsecret').encode('utf-8')) - print photo.get('id').encode('utf-8'), title, url + print(photo.get('id').encode('utf-8'), title, url) def got_upnp_result(result): - print "upnp", result + print("upnp", result) def got_error(error): - print error + print(error) #f.flickr_upload(FilePath('/tmp/image.jpg'),title='test') diff --git a/coherence/backends/fs_storage.py b/coherence/backends/fs_storage.py index d9c42d39..8e3cf608 100644 --- a/coherence/backends/fs_storage.py +++ b/coherence/backends/fs_storage.py @@ -4,19 +4,45 @@ # http://opensource.org/licenses/mit-license.php # Copyright 2006, Frank Scholz - +""" + FSStore - Filesystem media server + +FSStore exposes media files found in the directory trees defined by +the 'content' configuration entry. + +The first ".jpg" or ".png" file found inside a media directory is +served as a cover image. + +The plugin is configured with: + + + + FSStore + + /media/path1,/media/path2 + + my media + + 2 + + 2f7f4096-cba3-4390-be7d-d1d07106a6f4 + +""" import os import stat import glob import tempfile import shutil import time +import traceback import re from datetime import datetime -import urllib +from urllib.parse import quote from functools import partial -from sets import Set import mimetypes mimetypes.init() @@ -29,7 +55,7 @@ mimetypes.add_type('video/divx', '.avi') mimetypes.add_type('video/x-matroska', '.mkv') -from urlparse import urlsplit +from urllib.parse import urlsplit from twisted.python.filepath import FilePath from twisted.python import failure @@ -46,7 +72,7 @@ from coherence.extern.inotify import ( INotify, IN_CREATE, IN_DELETE, IN_MOVED_FROM, IN_MOVED_TO, IN_ISDIR, IN_CHANGED) -except Exception, msg: +except Exception as msg: INotify = None no_inotify_reason = msg @@ -101,11 +127,11 @@ def __init__(self, object_id, parent, path, mimetype, urlbase, UPnPClass, update if parent: parent.add_child(self, update=update) if mimetype == 'root': - self.location = unicode(path) + self.location = str(path) else: if mimetype == 'item' and path is None: - path = os.path.join(parent.get_realpath(), unicode(self.id)) - #self.location = FilePath(unicode(path)) + path = os.path.join(parent.get_realpath(), str(self.id)) + # self.location = FilePath(unicode(path)) self.location = FilePath(path) self.mimetype = mimetype if urlbase[-1] != '/': @@ -132,25 +158,27 @@ def __init__(self, object_id, parent, path, mimetype, urlbase, UPnPClass, update self.update_id = 0 self.get_url = lambda: self.url self.get_path = lambda: None - #self.item.searchable = True - #self.item.searchClass = 'object' + # self.item.searchable = True + # self.item.searchClass = 'object' if(isinstance(self.location, FilePath) and - self.location.isdir() == True): + self.location.isdir() is True): self.check_for_cover_art() if getattr(self, 'cover', None): _, ext = os.path.splitext(self.cover) - """ add the cover image extension to help clients not reacting on - the mimetype """ - self.item.albumArtURI = ''.join((urlbase, str(self.id), '?cover', ext)) + """ add the cover image extension to help clients + not reacting on the mimetype """ + self.item.albumArtURI = \ + ''.join((urlbase, str(self.id), '?cover', str(ext))) else: self.get_url = lambda: self.url if self.mimetype.startswith('audio/'): if getattr(parent, 'cover', None): _, ext = os.path.splitext(parent.cover) - """ add the cover image extension to help clients not reacting on - the mimetype """ - self.item.albumArtURI = ''.join((urlbase, str(self.id), '?cover', ext)) + """ add the cover image extension to help clients + not reacting on the mimetype """ + self.item.albumArtURI = \ + ''.join((urlbase, str(self.id), '?cover', ext)) _, host_port, _, _, _ = urlsplit(urlbase) if host_port.find(':') != -1: @@ -175,7 +203,11 @@ def __init__(self, object_id, parent, path, mimetype, urlbase, UPnPClass, update #self.item.res.append(new_res) if mimetype != 'item': - res = Resource('file://' + urllib.quote(self.get_path()), 'internal:%s:%s:*' % (host, self.mimetype)) + res = Resource( + 'file://' + quote( + self.get_path(), + encoding='utf-8'), + 'internal:%s:%s:*' % (host, self.mimetype)) res.size = size self.item.res.append(res) @@ -187,8 +219,8 @@ def __init__(self, object_id, parent, path, mimetype, urlbase, UPnPClass, update res.size = size self.item.res.append(res) - """ if this item is of type audio and we want to add a transcoding rule for it, - this is the way to do it: + """ if this item is of type audio and we want to add a transcoding + rule for it, this is the way to do it: create a new Resource object, at least a 'http-get' and maybe an 'internal' one too @@ -314,7 +346,10 @@ def rebuild(self, urlbase): else: host = host_port - res = Resource('file://' + urllib.quote(self.get_path()), 'internal:%s:%s:*' % (host, self.mimetype)) + res = Resource( + 'file://' + quote( + self.get_path()), + 'internal:%s:%s:*' % (host, self.mimetype)) try: res.size = self.location.getsize() except: @@ -402,15 +437,15 @@ def get_update_id(self): def get_path(self): if isinstance(self.location, FilePath): - return self.location.path + return str(self.location.path) else: - self.location + return str(self.location) def get_realpath(self): if isinstance(self.location, FilePath): - return self.location.path + return str(self.location.path) else: - self.location + return str(self.location) def set_path(self, path=None, extension=None): if path is None: @@ -425,9 +460,9 @@ def set_path(self, path=None, extension=None): def get_name(self): if isinstance(self.location, FilePath): - name = self.location.basename().decode("utf-8", "replace") + name = self.location.basename() else: - name = self.location.decode("utf-8", "replace") + name = self.location return name def get_cover(self): @@ -448,7 +483,8 @@ def get_xml(self): return self.item.toString() def __repr__(self): - return 'id: ' + str(self.id) + ' @ ' + self.get_name().encode('ascii', 'xmlcharrefreplace') + return 'id: ' + str(self.id) + ' @ ' + \ + str(self.get_name().encode('ascii', 'xmlcharrefreplace')) class FSStore(BackendStore): @@ -473,8 +509,8 @@ def __init__(self, server, **kwargs): self.next_id = 1000 self.name = kwargs.get('name', 'my media') self.content = kwargs.get('content', None) - if self.content != None: - if isinstance(self.content, basestring): + if self.content is not None: + if isinstance(self.content, str): self.content = [self.content] l = [] for a in self.content: @@ -483,11 +519,11 @@ def __init__(self, server, **kwargs): else: self.content = xdg_content() self.content = [x[0] for x in self.content] - if self.content == None: + if self.content is None: self.content = 'tests/content' if not isinstance(self.content, list): self.content = [self.content] - self.content = Set([os.path.abspath(x) for x in self.content]) + self.content = set([os.path.abspath(x) for x in self.content]) ignore_patterns = kwargs.get('ignore_patterns', []) self.store = {} @@ -497,7 +533,7 @@ def __init__(self, server, **kwargs): if INotify: try: self.inotify = INotify() - except Exception, msg: + except Exception as msg: self.info("%s", msg) else: self.info("%s", no_inotify_reason) @@ -522,22 +558,29 @@ def __init__(self, server, **kwargs): self.import_folder != None): UPnPClass = classChooser('root') id = str(self.getnextID()) - parent = self.store[id] = FSItem(id, parent, 'media', 'root', self.urlbase, UPnPClass, update=True, store=self) - - if self.import_folder != None: + try: + parent = self.store[id] = FSItem( + id, parent, 'media', 'root', + self.urlbase, UPnPClass, update=True, store=self) + except Exception as e: + self.error('Error on setting self.stor[id}, Error on FSItem: ' + '{}'.format(e)) + exit(1) + + if self.import_folder is not None: id = str(self.getnextID()) self.store[id] = FSItem(id, parent, self.import_folder, 'directory', self.urlbase, UPnPClass, update=True, store=self) self.import_folder_id = id - - for path in self.content: - if isinstance(path, (list, tuple)): - path = path[0] + for bytesPath in self.content: + if isinstance(bytesPath, (list, tuple)): + path = str(path[0]) + else: + path = str(bytesPath) if self.ignore_file_pattern.match(path): continue try: - path = path.encode('utf-8') # patch for #267 self.walk(path, parent, self.ignore_file_pattern) - except Exception, msg: + except Exception as msg: self.warning('on walk of %r: %r', path, msg) import traceback self.debug(traceback.format_exc()) @@ -563,7 +606,7 @@ def len(self): def get_by_id(self, id): #print "get_by_id", id, type(id) # we have referenced ids here when we are in WMC mapping mode - if isinstance(id, basestring): + if isinstance(id, str): id = id.split('@', 1) id = id[0] elif isinstance(id, int): @@ -610,13 +653,14 @@ def get_url_by_name(self, parent='0', name=''): return self.store[id].url def update_config(self, **kwargs): - print "update_config", kwargs + self.info("update_config: {}".format(kwargs)) if 'content' in kwargs: new_content = kwargs['content'] - new_content = Set([os.path.abspath(x) for x in new_content.split(',')]) + new_content = set([os.path.abspath(x) for x in new_content.split(',')]) new_folders = new_content.difference(self.content) obsolete_folders = self.content.difference(new_content) - print new_folders, obsolete_folders + self.debug('new folders: {}\nobsolete folders: {}'.format( + new_folders, obsolete_folders)) for folder in obsolete_folders: self.remove_content_folder(folder) for folder in new_folders: @@ -646,6 +690,7 @@ def walk(self, path, parent=None, ignore_file_pattern=''): container = containers.pop() try: self.debug('adding %r', container.location) + self.info('walk.adding: {}'.format(container.location)) for child in container.location.children(): if ignore_file_pattern.match(child.basename()) != None: continue @@ -686,7 +731,8 @@ def create(self, mimetype, path, parent): return id - def append(self, path, parent): + def append(self, bytes_path, parent): + path = str(bytes_path) self.debug("append %s %s %s", path, type(path), parent) if os.path.exists(path) == False: self.warning("path %r not available - ignored", path) @@ -713,14 +759,14 @@ def append(self, path, parent): path, mask=mask, autoAdd=False, callbacks=[partial(self.notify, parameter=id)]) return self.store[id] - except OSError, msg: + except OSError as msg: """ seems we have some permissions issues along the content path """ self.warning("path %r isn't accessible, error %r", path, msg) return None def remove(self, id): - print 'FSSTore remove id', id + self.debug('FSSTore remove id: {}'.format(id)) try: item = self.store[id] parent = item.get_parent() @@ -761,8 +807,10 @@ def notify(self, ignore, path, mask, parameter=None): if path.isdir(): self.walk(path.path, self.get_by_id(parameter), self.ignore_file_pattern) else: - if self.ignore_file_pattern.match(filename) == None: - self.append(path.path, self.get_by_id(parameter)) + if self.ignore_file_pattern.match(parameter) == None: + self.append( + str(path.path), + str(self.get_by_id(parameter))) def getnextID(self): ret = self.next_id @@ -780,7 +828,7 @@ def backend_import(self, item, data): return 200 except IOError: self.warning("import of file %s failed", item.get_path()) - except Exception, msg: + except Exception as msg: import traceback self.warning(traceback.format_exc()) return 500 @@ -955,11 +1003,11 @@ def hidden_upnp_DestroyObject(self, *args, **kwargs): if item == None: return failure.Failure(errorCode(701)) - print "upnp_DestroyObject", item.location + self.info("upnp_DestroyObject: {}".format(item.location)) try: item.location.remove() - except Exception, msg: - print Exception, msg + except Exception as msg: + self.error('upnp_DestroyObject [{}]: {}'.format(Exception, msg)) return failure.Failure(errorCode(715)) return {} @@ -972,14 +1020,14 @@ def hidden_upnp_DestroyObject(self, *args, **kwargs): p = 'tests/content' f = FSStore(None, name='my media', content=p, urlbase='http://localhost/xyz') - print f.len() - print f.get_by_id(1000).child_count, f.get_by_id(1000).get_xml() - print f.get_by_id(1001).child_count, f.get_by_id(1001).get_xml() - print f.get_by_id(1002).child_count, f.get_by_id(1002).get_xml() - print f.get_by_id(1003).child_count, f.get_by_id(1003).get_xml() - print f.get_by_id(1004).child_count, f.get_by_id(1004).get_xml() - print f.get_by_id(1005).child_count, f.get_by_id(1005).get_xml() - print f.store[1000].get_children(0, 0) + print(f.len()) + print(f.get_by_id(1000).child_count, f.get_by_id(1000).get_xml()) + print(f.get_by_id(1001).child_count, f.get_by_id(1001).get_xml()) + print(f.get_by_id(1002).child_count, f.get_by_id(1002).get_xml()) + print(f.get_by_id(1003).child_count, f.get_by_id(1003).get_xml()) + print(f.get_by_id(1004).child_count, f.get_by_id(1004).get_xml()) + print(f.get_by_id(1005).child_count, f.get_by_id(1005).get_xml()) + print(f.store[1000].get_children(0, 0)) #print f.upnp_Search(ContainerID ='4', # Filter ='dc:title,upnp:artist', # RequestedCount = '1000', diff --git a/coherence/backends/gallery2_storage.py b/coherence/backends/gallery2_storage.py index d53adccc..5ab08c23 100644 --- a/coherence/backends/gallery2_storage.py +++ b/coherence/backends/gallery2_storage.py @@ -14,7 +14,7 @@ from coherence.backend import BackendStore from coherence.backend import BackendItem -from urlparse import urlsplit +from urllib.parse import urlsplit from coherence.extern.galleryremote import Gallery @@ -202,7 +202,7 @@ def __repr__(self): return self.__class__.__name__ def append(self, obj, parent): - if isinstance(obj, basestring): + if isinstance(obj, str): mimetype = 'directory' else: mimetype = obj['mimetype'] @@ -235,7 +235,7 @@ def len(self): return len(self.store) def get_by_id(self, id): - if isinstance(id, basestring): + if isinstance(id, str): id = id.split('@', 1) id = id[0] try: @@ -276,7 +276,9 @@ def retrieveAlbums(self, album_gallery2_id, parent): def gotAlbums (albums): if albums: - albums = [album for album in albums.values() if album.get('parent') == album_gallery2_id] + albums = [ + album for album in list(albums.values()) if + album.get('parent') == album_gallery2_id] if album_gallery2_id == '0' and len(albums) == 1: album = albums[0] self.store[1000].gallery2_id = album.get('name') @@ -343,7 +345,7 @@ def main(): f = Gallery2Store(None) def got_upnp_result(result): - print "upnp", result + print("upnp", result) f.upnp_init() diff --git a/coherence/backends/gstreamer_renderer.py b/coherence/backends/gstreamer_renderer.py index 1f5c6195..33dc557b 100644 --- a/coherence/backends/gstreamer_renderer.py +++ b/coherence/backends/gstreamer_renderer.py @@ -3,7 +3,6 @@ # Copyright 2006,2007,2008,2009 Frank Scholz -from sets import Set from twisted.internet import reactor, defer from twisted.internet.task import LoopingCall @@ -15,7 +14,7 @@ import string import os import platform -from StringIO import StringIO +from io import StringIO import tokenize import pygst @@ -128,7 +127,7 @@ def create_pipeline(self, mimetype): self.update_LC = LoopingCall(self.update) def _set_props(self, element, props): - for option, value in props.iteritems(): + for option, value in props.items(): value = self._py_value(value) element.set_property(option, value) @@ -261,7 +260,7 @@ def on_message(self, bus, message): self.seek('-0') #self.player.set_state(gst.STATE_READY) elif t == gst.MESSAGE_TAG: - for key in message.parse_tag().keys(): + for key in list(message.parse_tag().keys()): self.tags[key] = message.structure[key] #print self.tags elif t == gst.MESSAGE_STATE_CHANGED: @@ -313,14 +312,14 @@ def query_position(self): self.duration = None self.debug("duration unknown") return r - r[u'raw'] = {u'position': unicode(str(position)), u'remaining': unicode(str(self.duration - position)), u'duration': unicode(str(self.duration))} + r['raw'] = {'position': str(str(position)), 'remaining': str(str(self.duration - position)), 'duration': str(str(self.duration))} - position_human = u'%d:%02d' % (divmod(position / 1000000000, 60)) - duration_human = u'%d:%02d' % (divmod(self.duration / 1000000000, 60)) - remaining_human = u'%d:%02d' % (divmod((self.duration - position) / 1000000000, 60)) + position_human = '%d:%02d' % (divmod(position / 1000000000, 60)) + duration_human = '%d:%02d' % (divmod(self.duration / 1000000000, 60)) + remaining_human = '%d:%02d' % (divmod((self.duration - position) / 1000000000, 60)) - r[u'human'] = {u'position': position_human, u'remaining': remaining_human, u'duration': duration_human} - r[u'percent'] = {u'position': position * 100 / self.duration, u'remaining': 100 - (position * 100 / self.duration)} + r['human'] = {'position': position_human, 'remaining': remaining_human, 'duration': duration_human} + r['percent'] = {'position': position * 100 / self.duration, 'remaining': 100 - (position * 100 / self.duration)} self.debug(r) return r @@ -387,20 +386,20 @@ def seek(self, location): _, state, _ = self.player.get_state() if state != gst.STATE_PAUSED: self.player.set_state(gst.STATE_PAUSED) - l = long(location) * 1000000000 + l = int(location) * 1000000000 p = self.query_position() #print p['raw']['position'], l if location[0] == '+': - l = long(p[u'raw'][u'position']) + (long(location[1:]) * 1000000000) - l = min(l, long(p[u'raw'][u'duration'])) + l = int(p['raw']['position']) + (int(location[1:]) * 1000000000) + l = min(l, int(p['raw']['duration'])) elif location[0] == '-': if location == '-0': - l = 0L + l = 0 else: - l = long(p[u'raw'][u'position']) - (long(location[1:]) * 1000000000) - l = max(l, 0L) + l = int(p['raw']['position']) - (int(location[1:]) * 1000000000) + l = max(l, 0) self.debug("seeking to %r", l) """ @@ -421,7 +420,7 @@ def seek(self, location): #print "setting new stream time to 0" #self.player.set_new_stream_time(0L) elif location != '-0': - print "seek to %r failed" % location + print("seek to %r failed" % location) if location == '-0': content_type, _ = self.mimetype.split("/") @@ -577,10 +576,10 @@ def _update_transport_position(self, state): for view in self.view: view.status(self.status(position)) - if position.has_key(u'raw'): + if 'raw' in position: - if self.duration == None and 'duration' in position[u'raw']: - self.duration = int(position[u'raw'][u'duration']) + if self.duration == None and 'duration' in position['raw']: + self.duration = int(position['raw']['duration']) if self.metadata != None and len(self.metadata) > 0: # FIXME: duration breaks client parsing MetaData? elt = DIDLLite.DIDLElement.fromString(self.metadata) @@ -600,21 +599,21 @@ def _update_transport_position(self, state): self.metadata) self.info("%s %d/%d/%d - %d%%/%d%% - %s/%s/%s", state, - string.atol(position[u'raw'][u'position']) / 1000000000, - string.atol(position[u'raw'][u'remaining']) / 1000000000, - string.atol(position[u'raw'][u'duration']) / 1000000000, - position[u'percent'][u'position'], - position[u'percent'][u'remaining'], - position[u'human'][u'position'], - position[u'human'][u'remaining'], - position[u'human'][u'duration']) - - duration = string.atol(position[u'raw'][u'duration']) + string.atol(position['raw']['position']) / 1000000000, + string.atol(position['raw']['remaining']) / 1000000000, + string.atol(position['raw']['duration']) / 1000000000, + position['percent']['position'], + position['percent']['remaining'], + position['human']['position'], + position['human']['remaining'], + position['human']['duration']) + + duration = string.atol(position['raw']['duration']) formatted = self._format_time(duration) av_transport.set_variable(conn_id, 'CurrentTrackDuration', formatted) av_transport.set_variable(conn_id, 'CurrentMediaDuration', formatted) - position = string.atol(position[u'raw'][u'position']) + position = string.atol(position['raw']['position']) formatted = self._format_time(position) av_transport.set_variable(conn_id, 'RelativeTimePosition', formatted) av_transport.set_variable(conn_id, 'AbsoluteTimePosition', formatted) @@ -666,9 +665,9 @@ def load(self, uri, metadata, mimetype=None): #self.server.av_transport_server.set_variable(connection_id, 'TransportState', 'TRANSITIONING') #self.server.av_transport_server.set_variable(connection_id, 'CurrentTransportActions','PLAY,STOP,PAUSE,SEEK,NEXT,PREVIOUS') if uri.startswith('http://'): - transport_actions = Set(['PLAY,STOP,PAUSE']) + transport_actions = set(['PLAY,STOP,PAUSE']) else: - transport_actions = Set(['PLAY,STOP,PAUSE,SEEK']) + transport_actions = set(['PLAY,STOP,PAUSE,SEEK']) if len(self.server.av_transport_server.get_variable('NextAVTransportURI').value) > 0: transport_actions.add('NEXT') @@ -689,30 +688,30 @@ def load(self, uri, metadata, mimetype=None): def status(self, position): uri = self.player.get_uri() if uri == None: - return {u'state': u'idle', u'uri': u''} + return {'state': 'idle', 'uri': ''} else: - r = {u'uri': unicode(uri), - u'position': position} + r = {'uri': str(uri), + 'position': position} if self.tags != {}: try: - r[u'artist'] = unicode(self.tags['artist']) + r['artist'] = str(self.tags['artist']) except: pass try: - r[u'title'] = unicode(self.tags['title']) + r['title'] = str(self.tags['title']) except: pass try: - r[u'album'] = unicode(self.tags['album']) + r['album'] = str(self.tags['album']) except: pass if self.player.get_state()[1] == gst.STATE_PLAYING: - r[u'state'] = u'playing' + r['state'] = 'playing' elif self.player.get_state()[1] == gst.STATE_PAUSED: - r[u'state'] = u'paused' + r['state'] = 'paused' else: - r[u'state'] = u'idle' + r['state'] = 'idle' return r @@ -771,7 +770,7 @@ def playcontainer_browse(self, uri): """ dlna-playcontainer://uuid%3Afe814e3e-5214-4c24-847b-383fb599ff01?sid=urn%3Aupnp-org%3AserviceId%3AContentDirectory&cid=1441&fid=1444&fii=0&sc=&md=0 """ - from urllib import unquote + from urllib.parse import unquote from cgi import parse_qs def handle_reply(r, uri, action, kw): @@ -993,7 +992,7 @@ def upnp_Previous(self, *args, **kwargs): track_nr = self.server.av_transport_server.get_variable('CurrentTrack') return self.upnp_Seek(self, InstanceID=InstanceID, Unit='TRACK_NR', Target=str(int(track_nr.value) - 1)) - def upnp_SetNextAVTransportURI(self, *args, **kwargs): + def upnp_setNextAVTransportURI(self, *args, **kwargs): InstanceID = int(kwargs['InstanceID']) NextURI = kwargs['NextURI'] current_connection_id = self.server.connection_manager_server.lookup_avt_id(self.current_connection_id) @@ -1002,7 +1001,7 @@ def upnp_SetNextAVTransportURI(self, *args, **kwargs): self.server.av_transport_server.set_variable(current_connection_id, 'NextAVTransportURIMetaData', NextMetaData) if len(NextURI) == 0 and self.playcontainer == None: transport_actions = self.server.av_transport_server.get_variable('CurrentTransportActions').value - transport_actions = Set(transport_actions.split(',')) + transport_actions = set(transport_actions.split(',')) try: transport_actions.remove('NEXT') self.server.av_transport_server.set_variable(current_connection_id, 'CurrentTransportActions', transport_actions) @@ -1010,7 +1009,7 @@ def upnp_SetNextAVTransportURI(self, *args, **kwargs): pass return {} transport_actions = self.server.av_transport_server.get_variable('CurrentTransportActions').value - transport_actions = Set(transport_actions.split(',')) + transport_actions = set(transport_actions.split(',')) transport_actions.add('NEXT') self.server.av_transport_server.set_variable(current_connection_id, 'CurrentTransportActions', transport_actions) return {} diff --git a/coherence/backends/iradio_storage.py b/coherence/backends/iradio_storage.py index 5d0f855a..60bb6037 100644 --- a/coherence/backends/iradio_storage.py +++ b/coherence/backends/iradio_storage.py @@ -23,7 +23,7 @@ from coherence import log from coherence.backend import BackendItem, BackendStore, Container, LazyContainer, AbstractBackendStore -from urlparse import urlsplit +from urllib.parse import urlsplit SHOUTCAST_WS_URL = 'http://www.shoutcast.com/sbin/newxml.phtml' @@ -130,7 +130,7 @@ def got_error(error): if request.clientproto == 'HTTP/1.1': self.connection = request.getHeader('connection') if self.connection: - tokens = map(str.lower, self.connection.split(' ')) + tokens = list(map(str.lower, self.connection.split(' '))) if 'close' in tokens: d = request.notifyFinish() d.addBoth(self.requestFinished) @@ -202,7 +202,7 @@ def __init__(self, server, **kwargs): # set root-level genre family containers # and populate the genre_parent_items dict from the family hierarchy information - for family, genres in genre_families.items(): + for family, genres in list(genre_families.items()): family_item = self.append_genre(root_item, family) if family_item is not None: self.genre_parent_items[family] = root_item @@ -218,7 +218,7 @@ def __init__(self, server, **kwargs): def append_genre(self, parent, genre): if genre in useless_genres: return None - if synonym_genres.has_key(genre): + if genre in synonym_genres: same_genres = synonym_genres[genre] else: same_genres = [genre] @@ -266,7 +266,7 @@ def retrieveItemsForGenre (self, parent, genres, per_page=1, offset=0, page=0): parent.childrenRetrievingNeeded = True url = '%s?genre=%s' % (self.shoutcast_ws_url, genre) - if genre_families.has_key(genre): + if genre in genre_families: family_genres = genre_families[genre] for family_genre in family_genres: self.append_genre(parent, family_genre) @@ -302,7 +302,7 @@ def got_page(result): 'bitrate': bitrate} stations[lower_name] = station - for station in stations.values(): + for station in list(stations.values()): station_id = station.get('station_id') name = station.get('name') url = station.get('url') @@ -337,7 +337,7 @@ def got_page(result): genres = {} main_synonym_genre = {} - for main_genre, sub_genres in synonym_genres.items(): + for main_genre, sub_genres in list(synonym_genres.items()): genres[main_genre] = sub_genres for genre in sub_genres: main_synonym_genre[genre] = main_genre @@ -348,8 +348,8 @@ def got_page(result): genres[name] = [name] main_synonym_genre[name] = name - for main_genre, sub_genres in genres.items(): - if not self.genre_parent_items.has_key(main_genre): + for main_genre, sub_genres in list(genres.items()): + if main_genre not in self.genre_parent_items: genre_families["Misc"].append(main_genre) self.init_completed() diff --git a/coherence/backends/itv_storage.py b/coherence/backends/itv_storage.py index e223aac2..12264322 100644 --- a/coherence/backends/itv_storage.py +++ b/coherence/backends/itv_storage.py @@ -6,6 +6,8 @@ # Copyright 2007, Frank Scholz # Copyright 2008,2009 Jean-Michel Sizun +from functools import cmp_to_key + from twisted.internet import defer, reactor from twisted.web import server @@ -78,7 +80,7 @@ def got_error(error): if request.clientproto == 'HTTP/1.1': self.connection = request.getHeader('connection') if self.connection: - tokens = map(str.lower, self.connection.split(' ')) + tokens = list(map(str.lower, self.connection.split(' '))) if 'close' in tokens: d = request.notifyFinish() d.addBoth(self.requestFinished) @@ -108,7 +110,7 @@ def __init__(self, id, store, parent_id, title): def add_child(self, child): id = child.id - if isinstance(child.id, basestring): + if isinstance(child.id, str): _, id = child.id.split('.') if self.children is None: self.children = [] @@ -119,10 +121,11 @@ def add_child(self, child): def get_children(self, start=0, end=0): if self.sorted == False: def childs_sort(x, y): - r = cmp(x.name, y.name) + r = cmp_to_key(x.name, y.name) return r - self.children.sort(cmp=childs_sort) + self.children = sorted( + self.children.sort, key=childs_sort) self.sorted = True if end != 0: return self.children[start:end] @@ -231,7 +234,7 @@ def len(self): return len(self.store) def get_by_id(self, id): - if isinstance(id, basestring): + if isinstance(id, str): id = id.split('@', 1) id = id[0] try: @@ -300,7 +303,7 @@ def got_page(result): genreItem = self.appendGenre(genre, parent) genreItems[genre] = genreItem - for station in stations.values(): + for station in list(stations.values()): genre = station.get('genre') parentItem = genreItems[genre] self.appendFeed({'name': station.get('name'), diff --git a/coherence/backends/lastfm_storage.py b/coherence/backends/lastfm_storage.py index 39fc7266..8cdd96da 100644 --- a/coherence/backends/lastfm_storage.py +++ b/coherence/backends/lastfm_storage.py @@ -33,7 +33,7 @@ from coherence import log from coherence.backend import BackendItem, BackendStore -from urlparse import urlsplit +from urllib.parse import urlsplit try: from hashlib import md5 @@ -110,8 +110,8 @@ def get_tracks(self): def got_page(result): result = utils.parse_xml(result, encoding='utf-8') self.getting_tracks = False - print self.getting_tracks - print "got Tracks" + print(self.getting_tracks) + print("got Tracks") for track in result.findall('trackList/track'): data = {} @@ -119,7 +119,7 @@ def get_data(name): #print track.find(name).text.encode('utf-8') return track.find(name).text.encode('utf-8') #Fixme: This section needs some work - print "adding Track" + print("adding Track") data['mimetype'] = 'audio/mpeg' data['name'] = get_data('creator') + " - " + get_data('title') data['title'] = get_data('title') @@ -324,7 +324,7 @@ def __repr__(self): return str(self.__class__).split('.')[-1] def append(self, obj, parent): - if isinstance(obj, basestring): + if isinstance(obj, str): mimetype = 'directory' else: mimetype = obj['mimetype'] @@ -372,7 +372,7 @@ def len(self): return len(self.store) def get_by_id(self, id): - if isinstance(id, basestring): + if isinstance(id, str): id = id.split('@', 1) id = id[0] id = int(id) @@ -408,7 +408,7 @@ def main(): f = LastFMStore(None) def got_upnp_result(result): - print "upnp", result + print("upnp", result) f.upnp_init() diff --git a/coherence/backends/lolcats_storage.py b/coherence/backends/lolcats_storage.py index fa82c668..f30e5f60 100644 --- a/coherence/backends/lolcats_storage.py +++ b/coherence/backends/lolcats_storage.py @@ -219,9 +219,9 @@ def __init__(self, server, *args, **kwargs): dfr.addCallback(self.queue_update) def get_by_id(self, id): - print "asked for", id, type(id) + print("asked for", id, type(id)) # what ever we are asked for, we want to return the container only - if isinstance(id, basestring): + if isinstance(id, str): id = id.split('@', 1) id = id[0] if int(id) == self.ROOT_ID: @@ -332,5 +332,5 @@ def parse_data(self, root): def queue_update(self, error_or_failure): # We use the reactor to queue another updating of our data - print error_or_failure + print(error_or_failure) reactor.callLater(self.refresh, self.update_loop) diff --git a/coherence/backends/mediadb_storage.py b/coherence/backends/mediadb_storage.py index 9d627008..b7e2b397 100644 --- a/coherence/backends/mediadb_storage.py +++ b/coherence/backends/mediadb_storage.py @@ -44,9 +44,9 @@ import os import shutil import string -import urllib +import urllib.request, urllib.parse, urllib.error -from urlparse import urlsplit +from urllib.parse import urlsplit from axiom import store, item, attributes from epsilon.extime import Time @@ -77,14 +77,14 @@ def _dict_from_tags(tag): tags['title'] = tag.title.strip() if type(tag.track) == int: tags['track'] = tag.track - elif type(tag.track) in (str, unicode): + elif type(tag.track) in (str, str): tags['track'] = int(tag.track.strip()) else: tags['track'] = tag.track[0] for key in ('artist', 'album', 'title'): - value = tags.get(key, u'') - if isinstance(value, unicode): + value = tags.get(key, '') + if isinstance(value, str): tags[key] = value.encode('utf-8') return tags @@ -136,9 +136,9 @@ def get_tags(filename): def sanitize(filename): badchars = ''.join(set(string.punctuation) - set('-_+.~')) - f = unicode(filename.lower()) - for old, new in ((u'ä', 'ae'), (u'ö', 'oe'), (u'ü', 'ue'), (u'ß', 'ss')): - f = f.replace(unicode(old), unicode(new)) + f = str(filename.lower()) + for old, new in (('ä', 'ae'), ('ö', 'oe'), ('ü', 'ue'), ('ß', 'ss')): + f = f.replace(str(old), str(new)) f = f.replace(badchars, '_') return f @@ -262,7 +262,7 @@ class Album(item.Item, BackendItem): musicbrainz_id = attributes.text() artist = attributes.reference(allowNone=False, indexed=True) cd_count = attributes.integer(default=1) - cover = attributes.text(default=u'') + cover = attributes.text(default='') get_path = None @@ -497,13 +497,13 @@ def check_for_cover_art(path): """ jpgs = [i for i in os.listdir(path) if os.path.splitext(i)[1] in ('.jpg', '.JPG')] try: - return unicode(jpgs[0]) + return str(jpgs[0]) except IndexError: pngs = [i for i in os.listdir(path) if os.path.splitext(i)[1] in ('.png', '.PNG')] try: - return unicode(pngs[0]) + return str(pngs[0]) except IndexError: - return u'' + return '' def got_tags(tags, file): #print "got_tags", tags @@ -515,34 +515,34 @@ def got_tags(tags, file): if len(artist) == 0: return - artist = u'UNKNOWN_ARTIST' + artist = 'UNKNOWN_ARTIST' if len(album) == 0: return - album = u'UNKNOWN_ALBUM' + album = 'UNKNOWN_ALBUM' if len(title) == 0: return - title = u'UNKNOWN_TITLE' + title = 'UNKNOWN_TITLE' #print "Tags:", file, album, artist, title, track - artist_ds = self.db.findOrCreate(Artist, name=unicode(artist, 'utf8')) + artist_ds = self.db.findOrCreate(Artist, name=str(artist, 'utf8')) album_ds = self.db.findOrCreate(Album, - title=unicode(album, 'utf8'), + title=str(album, 'utf8'), artist=artist_ds) if len(album_ds.cover) == 0: - dirname = unicode(os.path.dirname(file), 'utf-8') + dirname = str(os.path.dirname(file), 'utf-8') album_ds.cover = check_for_cover_art(dirname) if len(album_ds.cover) > 0: - filename = u"%s - %s" % (album_ds.artist.name, album_ds.title) + filename = "%s - %s" % (album_ds.artist.name, album_ds.title) filename = sanitize(filename + os.path.splitext(album_ds.cover)[1]) filename = os.path.join(dirname, filename) shutil.move(os.path.join(dirname, album_ds.cover), filename) album_ds.cover = filename #print album_ds.cover track_ds = self.db.findOrCreate(Track, - title=unicode(title, 'utf8'), + title=str(title, 'utf8'), track_nr=int(track), album=album_ds, - location=unicode(file, 'utf8')) + location=str(file, 'utf8')) for file in self.filelist: d = defer.maybeDeferred(get_tags, file) @@ -550,17 +550,17 @@ def got_tags(tags, file): def show_db(self): for album in list(self.db.query(Album, sort=Album.title.ascending)): - print album + print(album) for track in list(self.db.query(Track, Track.album == album, sort=Track.track_nr.ascending)): - print track + print(track) def show_albums(self): for album in list(self.db.query(Album, sort=Album.title.ascending)): - print album + print(album) def show_artists(self): for artist in list(self.db.query(Artist, sort=Artist.name.ascending)): - print artist + print(artist) def show_tracks_by_artist(self, artist_name): """ @@ -576,35 +576,35 @@ def show_tracks_by_artist(self, artist_name): Track.album == Album.storeID), sort=(Track.title.ascending) ))]: - print track + print(track) def show_tracks_by_title(self, title_or_part): - for track in list(self.db.query(Track, Track.title.like(u'%', title_or_part, u'%'), sort=Track.title.ascending)): - print track + for track in list(self.db.query(Track, Track.title.like('%', title_or_part, '%'), sort=Track.title.ascending)): + print(track) def show_tracks_to_filename(self, title_or_part): - for track in list(self.db.query(Track, Track.title.like(u'%', title_or_part, u'%'), sort=Track.title.ascending)): - print track.title, track.album.artist.name, track.track_nr + for track in list(self.db.query(Track, Track.title.like('%', title_or_part, '%'), sort=Track.title.ascending)): + print(track.title, track.album.artist.name, track.track_nr) _, ext = os.path.splitext(track.path) f = "%02d - %s - %s%s" % (track.track_nr, track.album.artist.name, track.title, ext) f = sanitize(f) - print f + print(f) def get_album_covers(self): - for album in list(self.db.query(Album, Album.cover == u'')): - print "missing cover for:", album.artist.name, album.title + for album in list(self.db.query(Album, Album.cover == '')): + print("missing cover for:", album.artist.name, album.title) filename = "%s - %s" % (album.artist.name, album.title) filename = sanitize(filename) if self.coverlocation is not None: cover_path = os.path.join(self.coverlocation, filename + '.jpg') if os.path.exists(cover_path) is True: - print "cover found:", cover_path + print("cover found:", cover_path) album.cover = cover_path else: def got_it(f, a): - print "cover saved:", f, a.title + print("cover saved:", f, a.title) a.cover = f aws_key = '1XHSE4FQJ0RK0X3S9WR2' @@ -615,10 +615,10 @@ def got_it(f, a): def get_by_id(self, id): self.info("get_by_id %s", id) - if isinstance(id, basestring): + if isinstance(id, str): id = id.split('@', 1) id = id[0].split('.')[0] - if isinstance(id, basestring) and id.startswith('artist_all_tracks_'): + if isinstance(id, str) and id.startswith('artist_all_tracks_'): try: return self.containers[id] except: diff --git a/coherence/backends/miroguide_storage.py b/coherence/backends/miroguide_storage.py index d8563843..f006f8fa 100644 --- a/coherence/backends/miroguide_storage.py +++ b/coherence/backends/miroguide_storage.py @@ -9,7 +9,7 @@ # Copyright 2009, Jean-Michel Sizun # Copyright 2009 Frank Scholz -import urllib +import urllib.request, urllib.parse, urllib.error from coherence.upnp.core import utils from coherence.upnp.core import DIDLLite @@ -113,11 +113,11 @@ def __init__(self, server, **kwargs): self.appendLanguage("Most Popular", self.language, rootItem, sort='-popular', count=15) def gotError(error): - print "ERROR: %s" % error + print("ERROR: %s" % error) def gotCategories(result): if result is None: - print "Unable to retrieve list of categories" + print("Unable to retrieve list of categories") return data, header = result categories = eval(data) # FIXME add some checks to avoid code injection @@ -132,7 +132,7 @@ def gotCategories(result): def gotLanguages(result): if result is None: - print "Unable to retrieve list of languages" + print("Unable to retrieve list of languages") return data, header = result languages = eval(data) # FIXME add some checks to avoid code injection @@ -174,7 +174,7 @@ def upnp_init(self): self.wmc_mapping = {'15': self.get_root_id()} def retrieveChannels (self, parent, filter, filter_value, per_page=100, page=0, offset=0, count=0, sort='name'): - filter_value = urllib.quote(filter_value.encode("utf-8")) + filter_value = urllib.parse.quote(filter_value.encode("utf-8")) limit = count if (count == 0): @@ -185,7 +185,7 @@ def retrieveChannels (self, parent, filter, filter_value, per_page=100, page=0, def gotChannels(result): if result is None: - print "Unable to retrieve channel for category %s" % category_id + print("Unable to retrieve channel for category %s" % category_id) return data, header = result channels = eval(data) @@ -205,7 +205,7 @@ def gotChannels(result): parent.childrenRetrievingNeeded = True def gotError(error): - print "ERROR: %s" % error + print("ERROR: %s" % error) d.addCallbacks(gotChannels, gotError) return d @@ -216,12 +216,12 @@ def retrieveChannelItems (self, parent, channel_id): def gotItems(result): if result is None: - print "Unable to retrieve items for channel %s" % channel_id + print("Unable to retrieve items for channel %s" % channel_id) return data, header = result channel = eval(data) items = [] - if (channel.has_key('item')): + if ('item' in channel): items = channel['item'] for item in items: #print "item:",item @@ -230,7 +230,7 @@ def gotItems(result): #print "description:", description name = item['name'] thumbnail_url = None - if (channel.has_key('thumbnail_url')): + if ('thumbnail_url' in channel): #print "Thumbnail:", channel['thumbnail_url'] thumbnail_url = channel['thumbnail_url'] #size = size['size'] @@ -239,7 +239,7 @@ def gotItems(result): parent.add_child(item, external_id=url) def gotError(error): - print "ERROR: %s" % error + print("ERROR: %s" % error) d.addCallbacks(gotItems, gotError) return d diff --git a/coherence/backends/picasa_storage.py b/coherence/backends/picasa_storage.py index 1d32f168..50763b44 100644 --- a/coherence/backends/picasa_storage.py +++ b/coherence/backends/picasa_storage.py @@ -19,7 +19,7 @@ AbstractBackendStore from coherence import log -from urlparse import urlsplit +from urllib.parse import urlsplit import gdata.photos.service import gdata.media @@ -32,7 +32,7 @@ def __init__(self, uri): ReverseProxyUriResource.__init__(self, uri) def render(self, request): - if request.received_headers.has_key('referer'): + if 'referer' in request.received_headers: del request.received_headers['referer'] return ReverseProxyUriResource.render(self, request) @@ -159,7 +159,7 @@ def retrieveAlbums(self, parent=None): def gotAlbums(albums): if albums is None: - print "Unable to retrieve albums" + print("Unable to retrieve albums") return for album in albums.entry: title = album.title.text @@ -168,7 +168,7 @@ def gotAlbums(albums): parent.add_child(item, external_id=album_id) def gotError(error): - print "ERROR: %s" % error + print("ERROR: %s" % error) albums.addCallbacks(gotAlbums, gotError) return albums @@ -179,7 +179,7 @@ def retrieveFeedPhotos (self, parent=None, feed_uri=''): def gotPhotos(photos): if photos is None: - print "Unable to retrieve photos for feed %s" % feed_uri + print("Unable to retrieve photos for feed %s" % feed_uri) return for photo in photos.entry: photo_id = photo.gphoto_id.text @@ -188,7 +188,7 @@ def gotPhotos(photos): parent.add_child(item, external_id=photo_id) def gotError(error): - print "ERROR: %s" % error + print("ERROR: %s" % error) photos.addCallbacks(gotPhotos, gotError) return photos diff --git a/coherence/backends/playlist_storage.py b/coherence/backends/playlist_storage.py index 10f06ebc..3a5c3670 100644 --- a/coherence/backends/playlist_storage.py +++ b/coherence/backends/playlist_storage.py @@ -19,7 +19,7 @@ from coherence import log -from urlparse import urlsplit +from urllib.parse import urlsplit import re from coherence.upnp.core.utils import getPage @@ -97,7 +97,7 @@ def __repr__(self): return self.__class__.__name__ def append(self, obj, parent): - if isinstance(obj, basestring): + if isinstance(obj, str): mimetype = 'directory' else: mimetype = obj['mimetype'] @@ -149,29 +149,29 @@ def gotPlaylist(playlist): if playlist: content, header = playlist lines = content.splitlines().__iter__() - line = lines.next() + line = next(lines) while line is not None: if re.search('#EXTINF', line): channel = re.match('#EXTINF:.*,(.*)', line).group(1) mimetype = 'video/mpeg' - line = lines.next() + line = next(lines) while re.search('#EXTVLCOPT', line): option = re.match('#EXTVLCOPT:(.*)', line).group(1) if option == 'no-video': mimetype = 'audio/mpeg' - line = lines.next() + line = next(lines) url = line item = PlaylistItem(channel, url, mimetype) parent_item.add_child(item) try: - line = lines.next() + line = next(lines) except StopIteration: line = None return items def gotError(error): self.warning("Unable to retrieve playlist: %s", url) - print "Error: %s" % error + print("Error: %s" % error) return None d = getPage(url) diff --git a/coherence/backends/radiotime_storage.py b/coherence/backends/radiotime_storage.py index 1220f90c..65ae4021 100644 --- a/coherence/backends/radiotime_storage.py +++ b/coherence/backends/radiotime_storage.py @@ -165,7 +165,7 @@ def got_error(error): def got_xml_error(error): self.warning("Data received from Radiotime service is invalid: %s", url) #self.debug("%r", error.getTraceback()) - print error.getTraceback() + print(error.getTraceback()) parent.childrenRetrievingNeeded = True # we retry return Failure("Unable to retrieve items for url %s" % url) diff --git a/coherence/backends/swr3_storage.py b/coherence/backends/swr3_storage.py index 0f73cafb..c5957834 100644 --- a/coherence/backends/swr3_storage.py +++ b/coherence/backends/swr3_storage.py @@ -66,7 +66,7 @@ def __init__(self, id, store, parent_id, title): def add_child(self, child): id = child.id - if isinstance(child.id, basestring): + if isinstance(child.id, str): _, id = child.id.split('.') self.children.append(child) self.item.childCount += 1 @@ -74,11 +74,10 @@ def add_child(self, child): def get_children(self, start=0, end=0): if not self.sorted: - def childs_sort(x, y): - r = cmp(x.name, y.name) - return r + def childs_key_sort(x): + return x.name - self.children.sort(cmp=childs_sort) + sorted(self.children, key=childs_key_sort) self.sorted = True if end != 0: return self.children[start:end] @@ -144,7 +143,7 @@ def get_next_id(self): return self.next_id def get_by_id(self, id): - if isinstance(id, basestring): + if isinstance(id, str): id = id.split('@', 1) id = id[0] try: diff --git a/coherence/backends/test_storage.py b/coherence/backends/test_storage.py index c09861e6..bfd40fae 100644 --- a/coherence/backends/test_storage.py +++ b/coherence/backends/test_storage.py @@ -96,15 +96,15 @@ def __init__(self, caller): self.caller = caller def connectionMade(self): - print "pp connection made" + print("pp connection made") def outReceived(self, data): - print "outReceived with %d bytes!" % len(data) + print("outReceived with %d bytes!" % len(data)) self.caller.write_data(data) def errReceived(self, data): #print "errReceived! with %d bytes!" % len(data) - print "pp (err):", data.strip() + print("pp (err):", data.strip()) def inConnectionLost(self): #print "inConnectionLost! stdin is closed! (we probably did it)" @@ -119,8 +119,8 @@ def errConnectionLost(self): pass def processEnded(self, status_object): - print "processEnded, status %d" % status_object.value.exitCode - print "processEnded quitting" + print("processEnded, status %d" % status_object.value.exitCode) + print("processEnded quitting") self.caller.ended = True self.caller.write_data('') @@ -136,7 +136,7 @@ def __init__(self, pipeline, mimetype): self.mimetype = mimetype def render(self, request): - print "ExternalProcessPipeline render" + print("ExternalProcessPipeline render") if self.mimetype: request.setHeader('content-type', self.mimetype) @@ -160,19 +160,19 @@ def __init__(self, pipeline, request): def write_data(self, data): if data: - print "write %d bytes of data" % len(data) + print("write %d bytes of data" % len(data)) self.written += len(data) # this .write will spin the reactor, calling .doWrite and then # .resumeProducing again, so be prepared for a re-entrant call self.request.write(data) if self.request and self.ended == True: - print "closing" + print("closing") self.request.unregisterProducer() self.request.finish() self.request = None def resumeProducing(self): - print "resumeProducing", self.request + print("resumeProducing", self.request) if not self.request: return if self.process == None: @@ -185,7 +185,7 @@ def pauseProducing(self): pass def stopProducing(self): - print "stopProducing", self.request + print("stopProducing", self.request) self.request.unregisterProducer() self.process.loseConnection() self.request.finish() @@ -213,7 +213,7 @@ def __init__(self, parent, id, title, location, url): self.item = None def get_item(self): - print "get_item %r" % self.item + print("get_item %r" % self.item) if self.item == None: self.item = self.upnp_class(self.id, self.parent.id, self.get_name()) self.item.description = self.description @@ -281,7 +281,7 @@ def __init__(self, id, store, parent_id, title): self.sorted = False def add_child(self, child): - print "ADD CHILD %r" % child + print("ADD CHILD %r" % child) #id = child.id #if isinstance(child.id, basestring): # _,id = child.id.split('.') @@ -290,13 +290,12 @@ def add_child(self, child): self.sorted = False def get_children(self, start=0, end=0): - print "GET CHILDREN" + print("GET CHILDREN") if self.sorted == False: - def childs_sort(x, y): - r = cmp(x.name, y.name) - return r + def childs_key_sort(x): + return x.name - self.children.sort(cmp=childs_sort) + sorted(self.children, key=childs_key_sort) self.sorted = True if end != 0: return self.children[start:end] @@ -323,7 +322,7 @@ class TestStore(BackendStore): implements = ['MediaServer'] def __init__(self, server, *args, **kwargs): - print "TestStore kwargs", kwargs + print("TestStore kwargs", kwargs) BackendStore.__init__(self, server, **kwargs) self.name = kwargs.get('name', 'TestServer') self.next_id = 1000 @@ -338,7 +337,7 @@ def __init__(self, server, *args, **kwargs): items = [items] for item in items: - if isinstance(item, basestring): + if isinstance(item, str): xml = etree.fromstring(item) item = {} for child in xml: @@ -420,7 +419,7 @@ def get_next_id(self): return self.next_id def get_by_id(self, id): - print "GET_BY_ID %r" % id + print("GET_BY_ID %r" % id) item = self.store.get(id, None) if item == None: if int(id) == 0: diff --git a/coherence/backends/tracker_storage.py b/coherence/backends/tracker_storage.py index d131d472..434487cd 100644 --- a/coherence/backends/tracker_storage.py +++ b/coherence/backends/tracker_storage.py @@ -89,7 +89,7 @@ def __init__(self, id, parent_id, name, store=None, children_callback=None, cont def add_child(self, child): id = child.id - if isinstance(child.id, basestring): + if isinstance(child.id, str): _, id = child.id.split('.') self.children[id] = child if self.item.childCount != None: @@ -101,7 +101,7 @@ def get_children(self, start=0, end=0): if callable(self.children): return self.children(start, end - start) else: - children = self.children.values() + children = list(self.children.values()) if end == 0: return children[start:] else: @@ -144,12 +144,12 @@ def add_child(self, child): def sort_children(self): if self.sorted_children == None: - def childs_sort(x, y): - r = cmp(self.children[x].name, self.children[y].name) - return r + def childs_key_sort(x): + return self.children[x].name - self.sorted_children = self.children.keys() - self.sorted_children.sort(cmp=childs_sort) + self.sorted_children = list(self.children.keys()) + self.sorted_children = sorted(self.sorted_children, + key=childs_key_sort) return self.sorted_children def get_artist_all_tracks(self, start=0, request_count=0): @@ -193,8 +193,8 @@ def __init__(self, store, id, title, artist): BackendItem.__init__(self) self.store = store self.id = 'album.%d' % int(id) - self.name = unicode(title) - self.artist = unicode(artist) + self.name = str(title) + self.artist = str(artist) self.cover = None self.children = {} self.sorted_children = None @@ -209,12 +209,12 @@ def get_children(self, start=0, end=0): for key in self.sorted_children: children.append(self.children[key]) else: - def childs_sort(x, y): - r = cmp(self.children[x].track_nr, self.children[y].track_nr) - return r + def childs_key_sort(x): + return self.children[x].track_nr - self.sorted_children = self.children.keys() - self.sorted_children.sort(cmp=childs_sort) + self.sorted_children = list(self.children.keys()) + self.sorted_children = \ + sorted(self.sorted_children, key=childs_key_sort) for key in self.sorted_children: children.append(self.children[key]) @@ -259,7 +259,7 @@ def __init__(self, store, self.id = 'song.%d' % int(id) self.parent_id = parent_id - self.path = unicode(file) + self.path = str(file) duration = str(duration).strip() duration = duration.split('.')[0] @@ -274,10 +274,10 @@ def __init__(self, store, self.bitrate = 0 - self.title = unicode(title) - self.artist = unicode(artist) - self.album = unicode(album) - self.genre = unicode(genre) + self.title = str(title) + self.artist = str(artist) + self.album = str(album) + self.genre = str(genre) track_number = str(track_number).strip() if len(track_number) == 0: track_number = 1 @@ -373,7 +373,7 @@ def __init__(self, store, self.id = 'video.%d' % int(id) self.parent_id = parent_id - self.path = unicode(file) + self.path = str(file) duration = str(duration).strip() duration = duration.split('.')[0] @@ -386,7 +386,7 @@ def __init__(self, store, seconds = seconds - minutes * 60 self.duration = ("%d:%02d:%02d") % (hours, minutes, seconds) - self.title = unicode(title) + self.title = str(title) self.cover = None self.mimetype = str(mimetype) @@ -448,11 +448,11 @@ def __init__(self, store, self.id = 'image.%d' % int(id) self.parent_id = parent_id - self.path = unicode(file) + self.path = str(file) - self.title = unicode(title) + self.title = str(title) - self.album = unicode(album.strip()) + self.album = str(album.strip()) self.mimetype = str(mimetype) self.size = int(size) @@ -547,7 +547,7 @@ def queries_failed(r): louie.send('Coherence.UPnP.Backend.init_failed', None, backend=self, msg=error) services = kwargs.get('service', 'Music,Videos,Images') - services = map(lambda x: x.strip().lower(), services.split(',')) + services = [x.strip().lower() for x in services.split(',')] l = [] mapping = {'music': self.get_tracks, @@ -570,10 +570,10 @@ def __repr__(self): def get_by_id(self, id): self.info("looking for id %r", id) - if isinstance(id, basestring): + if isinstance(id, str): id = id.split('@', 1) id = id[0] - if isinstance(id, basestring) and id.startswith('artist_all_tracks_'): + if isinstance(id, str) and id.startswith('artist_all_tracks_'): try: return self.containers[id] except: @@ -602,7 +602,7 @@ def get_by_id(self, id): def get_videos(self): def handle_error(error): - print error + print(error) return error def parse_videos_query_result(resultlist): @@ -615,7 +615,7 @@ def parse_videos_query_result(resultlist): if len(title) == 0: title = os.path.basename(file) if mimetype == 'video/x-theora+ogg': - mimetype = u'video/ogg' + mimetype = 'video/ogg' video_item = Video(self, self.videos, VIDEO_ALL_CONTAINER_ID, file, title, \ @@ -624,7 +624,9 @@ def parse_videos_query_result(resultlist): self.videos += 1 videos.append(video_item) - videos.sort(cmp=lambda x, y: cmp(x.get_name().lower(), y.get_name().lower())) + videos = sorted(videos, + key=lambda x, y: (x.get_name().lower() > y.get_name().lower()) - + (x.get_name().lower() < y.get_name().lower())) for video_item in videos: self.containers[VIDEO_ALL_CONTAINER_ID].add_child(video_item) @@ -638,8 +640,8 @@ def parse_videos_query_result(resultlist): children_callback=None) self.containers[VIDEO_CONTAINER_ID].add_child(self.containers[VIDEO_ALL_CONTAINER_ID]) - fields = [u'Video:Title', u'Video:Duration', - u'File:Size', u'File:Mime'] + fields = ['Video:Title', 'Video:Duration', + 'File:Size', 'File:Mime'] d = defer.Deferred() d.addCallback(parse_videos_query_result) @@ -654,7 +656,7 @@ def handle_error(error): return error def parse_images_query_result(resultlist): - print "images", resultlist + print("images", resultlist) images = [] for image in resultlist: file, _, title, album, \ @@ -671,7 +673,9 @@ def parse_images_query_result(resultlist): self.images += 1 images.append(image_item) - images.sort(cmp=lambda x, y: cmp(x.get_name().lower(), y.get_name().lower())) + images = sorted( + images, key=lambda x, y: (x.get_name().lower() > y.get_name().lower()) - + (x.get_name().lower() < y.get_name().lower())) for image_item in images: self.containers[IMAGE_ALL_CONTAINER_ID].add_child(image_item) @@ -685,9 +689,9 @@ def parse_images_query_result(resultlist): children_callback=None) self.containers[IMAGE_CONTAINER_ID].add_child(self.containers[IMAGE_ALL_CONTAINER_ID]) - fields = [u'Image:Title', u'Image:Album', - u'Image:Date', u'Image:Width', u'Image:Height', - u'File:Size', u'File:Mime'] + fields = ['Image:Title', 'Image:Album', + 'Image:Date', 'Image:Width', 'Image:Height', + 'File:Size', 'File:Mime'] d = defer.Deferred() d.addCallback(parse_images_query_result) @@ -721,7 +725,9 @@ def parse_tracks_query_result(resultlist): self.songs += 1 tracks.append(track_item) - tracks.sort(cmp=lambda x, y: cmp(x.get_name(), y.get_name())) + tracks = sorted( + tracks, key=lambda x, y: (x.get_name() > y.get_name()) - + (x.get_name() < y.get_name())) for track_item in tracks: self.containers[AUDIO_ALL_CONTAINER_ID].add_child(track_item) @@ -730,7 +736,7 @@ def parse_tracks_query_result(resultlist): album_item.add_child(track_item) except: album_item = Album(self, self.albums, track_item.album, track_item.artist) - albums[unicode(track_item.album)] = album_item + albums[str(track_item.album)] = album_item self.albums += 1 album_item.add_child(track_item) @@ -739,15 +745,15 @@ def parse_tracks_query_result(resultlist): artist_item.add_child(album_item) except: artist_item = Artist(self, self.artists, track_item.artist) - artists[unicode(track_item.artist)] = artist_item + artists[str(track_item.artist)] = artist_item self.artists += 1 artist_item.add_child(album_item) - sorted_keys = albums.keys() + sorted_keys = list(albums.keys()) sorted_keys.sort() for key in sorted_keys: self.containers[AUDIO_ALBUM_CONTAINER_ID].add_child(albums[key]) - sorted_keys = artists.keys() + sorted_keys = list(artists.keys()) sorted_keys.sort() for key in sorted_keys: self.containers[AUDIO_ARTIST_CONTAINER_ID].add_child(artists[key]) @@ -794,11 +800,11 @@ def parse_tracks_query_result(resultlist): '13': lambda: self.get_by_id(AUDIO_PLAYLIST_CONTAINER_ID), # all playlists }) - fields = [u'Audio:Title', u'Audio:Artist', - u'Audio:Album', u'Audio:Genre', - u'Audio:Duration', u'Audio:AlbumTrackCount', - u'Audio:TrackNo', u'Audio:Codec', - u'File:Size', u'File:Mime'] + fields = ['Audio:Title', 'Audio:Artist', + 'Audio:Album', 'Audio:Genre', + 'Audio:Duration', 'Audio:AlbumTrackCount', + 'Audio:TrackNo', 'Audio:Codec', + 'File:Size', 'File:Mime'] d = defer.Deferred() d.addCallback(parse_tracks_query_result) diff --git a/coherence/backends/twitch_storage.py b/coherence/backends/twitch_storage.py index 6f5e2a4d..6097ecad 100644 --- a/coherence/backends/twitch_storage.py +++ b/coherence/backends/twitch_storage.py @@ -19,7 +19,8 @@ """ import json -import urllib +from functools import cmp_to_key +import urllib.request, urllib.parse, urllib.error from coherence.log import Loggable from dateutil import parser as dateutil_parser @@ -97,9 +98,9 @@ def _retrieve_children(self, parent=None, **kwargs): return kwargs.update({'limit': self.limit}) - kwargs = {k: v for k, v in kwargs.items() if v is not None} + kwargs = {k: v for k, v in list(kwargs.items()) if v is not None} - url = "%s?%s" % (self.children_url, urllib.urlencode(kwargs)) if kwargs else self.children_url + url = "%s?%s" % (self.children_url, urllib.parse.urlencode(kwargs)) if kwargs else self.children_url d = utils.getPage(url) d.addCallbacks(self._got_page, self._got_error) @@ -296,10 +297,10 @@ def upnp_init(self): def sort_by_viewers(x, y): - return cmp(y.viewers, x.viewers) + return cmp_to_key(y.viewers, x.viewers) def json_loads(data): if isinstance(data, (list, tuple)): data = data[0] - return json.loads(data) \ No newline at end of file + return json.loads(data) diff --git a/coherence/backends/yamj_storage.py b/coherence/backends/yamj_storage.py index 76af39dd..44ae3561 100644 --- a/coherence/backends/yamj_storage.py +++ b/coherence/backends/yamj_storage.py @@ -9,7 +9,7 @@ # from lxml import etree -import urllib +import urllib.request, urllib.parse, urllib.error import mimetypes from coherence.upnp.core import DIDLLite @@ -209,7 +209,7 @@ def retrieveIndexMovies (self, parent, name, root_name, per_page=10, page=0, off counter = 1 else: counter = abs(offset / self.nbMoviesPerFile) + 1 - fileUrl = "%s/%s_%d.xml" % (self.jukebox_url, urllib.quote(root_name), counter) + fileUrl = "%s/%s_%d.xml" % (self.jukebox_url, urllib.parse.quote(root_name), counter) def fail_readPage(f): self.warning("failure reading yamj index (%s): %r", fileUrl, f.getErrorMessage()) diff --git a/coherence/backends/youtube_storage.py b/coherence/backends/youtube_storage.py index 496ed57a..dde260ec 100644 --- a/coherence/backends/youtube_storage.py +++ b/coherence/backends/youtube_storage.py @@ -238,7 +238,7 @@ def renderBufferFile (self, request, filepath, buffer_size): bufferFile.encoding = None try: return bufferFile.render(request) - except Exception, error: + except Exception as error: self.info(error) if request.method != 'HEAD': @@ -325,7 +325,7 @@ def extractDataURL(url, quality): 'forcetitle': False, 'simulate': True, 'format': format, - 'outtmpl': u'%(id)s.%(ext)s', + 'outtmpl': '%(id)s.%(ext)s', 'ignoreerrors': True, 'ratelimit': None, } diff --git a/coherence/base.py b/coherence/base.py index a5dfaa41..28664e33 100644 --- a/coherence/base.py +++ b/coherence/base.py @@ -48,8 +48,12 @@ def getChild(self, name, request): """ we have an out-of-band request """ return static.File(self.coherence.dbus.pinboard[request.args['key'][0]]) - if name == '': + if name in ['', None, '\'']: return self + if name.endswith('\''): + self.warning('\t modified wrong name from {} to {}'.format( + name, name[:-1])) + name = name[:-1] # at this stage, name should be a device UUID try: @@ -145,7 +149,7 @@ def __getitem__(self, key): if pkg_resources and isinstance(plugin, pkg_resources.EntryPoint): try: plugin = plugin.load(require=False) - except (ImportError, AttributeError, pkg_resources.ResolutionError), msg: + except (ImportError, AttributeError, pkg_resources.ResolutionError) as msg: self.warning("Can't load plugin %s (%s), maybe missing dependencies...", plugin.name, msg) self.info(traceback.format_exc()) del self._plugins[key] @@ -167,7 +171,7 @@ def set(self, key, value): return self.__setitem__(key, value) def keys(self): - return self._plugins.keys() + return list(self._plugins.keys()) def _collect_from_module(self): from coherence.extern.simple_plugin import Reception @@ -243,12 +247,12 @@ def __init__(self, config=None): logging.getLogger(subsystem['name'].lower()).setLevel(subsystem['level'].upper()) except (KeyError, TypeError): subsystem_log = config.get('subsystem_log', {}) - for subsystem, level in subsystem_log.items(): + for subsystem, level in list(subsystem_log.items()): logging.getLogger(subsystem.lower()).setLevel(level.upper()) try: logfile = config.get('logging').get('logfile', None) if logfile is not None: - logfile = unicode(logfile) + logfile = str(logfile) except (KeyError, AttributeError, TypeError): logfile = config.get('logfile', None) log.init(logfile, logmode.upper()) @@ -294,7 +298,7 @@ def setup_part2(self): try: # TODO: add ip/interface bind self.ssdp_server = SSDPServer(test=unittest) - except CannotListenError, err: + except CannotListenError as err: self.error("Error starting the SSDP-server: %s", err) self.debug("Error starting the SSDP-server", exc_info=True) reactor.stop() @@ -340,12 +344,12 @@ def setup_part2(self): self.info("No plugin defined!") else: if isinstance(plugins, dict): - for plugin, arguments in plugins.items(): + for plugin, arguments in list(plugins.items()): try: if not isinstance(arguments, dict): arguments = {} self.add_plugin(plugin, **arguments) - except Exception, msg: + except Exception as msg: self.warning("Can't enable plugin, %s: %s!", plugin, msg) self.info(traceback.format_exc()) else: @@ -364,7 +368,7 @@ def setup_part2(self): if 'uuid' not in plugin: plugin['uuid'] = str(backend.uuid)[5:] self.config.save() - except Exception, msg: + except Exception as msg: self.warning("Can't enable plugin, %s: %s!", plugin, msg) self.info(traceback.format_exc()) @@ -396,7 +400,7 @@ def setup_part2(self): self.ctrl = ControlPoint(self) self.ctrl.auto_client_append('InternetGatewayDevice') self.dbus = dbus_service.DBusPontoon(self.ctrl) - except Exception, msg: + except Exception as msg: self.warning("Unable to activate dbus sub-system: %r", msg) self.debug(traceback.format_exc()) @@ -426,7 +430,7 @@ def add_plugin(self, plugin, **kwargs): self.debug(traceback.format_exc()) except KeyError: self.warning("Can't enable %s plugin, not found!", plugin) - except Exception, msg: + except Exception as msg: self.warning("Can't enable %s plugin, %s!", plugin, msg) self.debug(traceback.format_exc()) @@ -436,7 +440,7 @@ def remove_plugin(self, plugin): @:param plugin: is the object return by add_plugin or an UUID string """ - if isinstance(plugin, basestring): + if isinstance(plugin, str): try: plugin = self.active_backends[plugin] except KeyError: @@ -474,7 +478,7 @@ def store_plugin_config(self, uuid, items): for plugin in plugins: try: if plugin['uuid'] == uuid: - for k, v in items.items(): + for k, v in list(items.items()): plugin[k] = v self.config.save() except: @@ -494,7 +498,7 @@ def shutdown(self, force=False): self.dbus.shutdown() self.dbus = None - for backend in self.active_backends.itervalues(): + for backend in self.active_backends.values(): backend.unregister() self.active_backends = {} @@ -576,6 +580,7 @@ def get_device_with_usn(self, usn): return found def get_device_with_id(self, device_id): + # print('get_device_with_id [{}]: {}'.format(type(device_id), device_id)) found = None for device in self.devices: id = device.get_id() @@ -587,32 +592,36 @@ def get_device_with_id(self, device_id): return found def get_devices(self): + # print('get_devices: {}'.format(self.devices)) return self.devices def get_local_devices(self): + # print('get_local_devices: {}'.format([d for d in self.devices if d.manifestation == 'local'])) return [d for d in self.devices if d.manifestation == 'local'] def get_nonlocal_devices(self): + # print('get_nonlocal_devices: {}'.format([d for d in self.devices if d.manifestation == 'remote'])) return [d for d in self.devices if d.manifestation == 'remote'] def create_device(self, device_type, infos): self.info("creating %s %s", infos['ST'], infos['USN']) if infos['ST'] == 'upnp:rootdevice': - self.info("creating upnp:rootdevice %s", infos['USN']) + self.info('creating upnp:rootdevice {}'.format(infos['USN'])) root = RootDevice(infos) else: - self.info("creating device/service %s", infos['USN']) + self.info('creating device/service {}'.format(infos['USN'])) root_id = infos['USN'][:-len(infos['ST']) - 2] root = self.get_device_with_id(root_id) # FIXME doesn't look like doing right thing device = Device(infos, root) def add_device(self, device): - self.info("adding device %s %s %s", device.get_id(), device.get_usn(), device.friendly_device_type) + self.info('adding device {} {} {}'.format( + device.get_id(), device.get_usn(), device.friendly_device_type)) self.devices.append(device) def remove_device(self, device_type, infos): - self.info("removed device %s %s", infos['ST'], infos['USN']) + self.info('removed device {} %s{}'.format(infos['ST'], infos['USN'])) device = self.get_device_with_usn(infos['USN']) if device: louie.send('Coherence.UPnP.Device.removed', None, usn=infos['USN']) diff --git a/coherence/dbus_service.py b/coherence/dbus_service.py index a8f57a9a..8cc9ef0c 100644 --- a/coherence/dbus_service.py +++ b/coherence/dbus_service.py @@ -9,8 +9,8 @@ from lxml import etree import time -import urllib -import urlparse +import urllib.request, urllib.parse, urllib.error +import urllib.parse import dbus @@ -37,7 +37,7 @@ def un_namespace(text): - for k, v in namespaces.items(): + for k, v in list(namespaces.items()): if text.startswith(k): return text.replace(k, v) return text @@ -97,7 +97,7 @@ def StateVariableChanged(self, udn, service, variable, value): def getAvailableActions(self): actions = self.service.get_actions() r = [] - for name in actions.keys(): + for name in list(actions.keys()): r.append(name) return r @@ -105,16 +105,16 @@ def getAvailableActions(self): def subscribeStateVariables(self): if not self.service: return - notify = [v for v in self.service._variables[0].values() if v.send_events == True] + notify = [v for v in list(self.service._variables[0].values()) if v.send_events == True] if len(notify) == 0: return data = {} for n in notify: if n.name == 'LastChange': lc = {} - for instance, vdict in self.service._variables.items(): + for instance, vdict in list(self.service._variables.items()): v = {} - for variable in vdict.values(): + for variable in list(vdict.values()): if(variable.name != 'LastChange' and variable.name[0:11] != 'A_ARG_TYPE_' and variable.never_evented == False): @@ -123,9 +123,9 @@ def subscribeStateVariables(self): if len(v) > 0: lc[str(instance)] = v if len(lc) > 0: - data[unicode(n.name)] = lc + data[str(n.name)] = lc else: - data[unicode(n.name)] = unicode(n.value) + data[str(n.name)] = str(n.value) return self.dbus_device.device.get_id(), self.type, dbus.Dictionary(data, signature='sv', variant_level=3) @dbus.service.method(CDS_SERVICE, in_signature='', out_signature='s', @@ -137,7 +137,7 @@ def GetSearchCapabilites(self, dbus_async_cb, dbus_async_err_cb): return r def convert_reply(data): - dbus_async_cb(unicode(data['SearchCaps'])) + dbus_async_cb(str(data['SearchCaps'])) r.addCallback(convert_reply) r.addErrback(dbus_async_err_cb) @@ -150,7 +150,7 @@ def GetSortCapabilities(self, dbus_async_cb, dbus_async_err_cb): return r def convert_reply(data): - dbus_async_cb(unicode(data['SortCaps'])) + dbus_async_cb(str(data['SortCaps'])) r.addCallback(convert_reply) r.addErrback(dbus_async_err_cb) @@ -163,7 +163,7 @@ def GetSortExtensionCapabilities(self, dbus_async_cb, dbus_async_err_cb): return r def convert_reply(data): - dbus_async_cb(unicode(data['SortExtensionCaps'])) + dbus_async_cb(str(data['SortExtensionCaps'])) r.addCallback(convert_reply) r.addErrback(dbus_async_err_cb) @@ -176,7 +176,7 @@ def GetFeatureList(self, dbus_async_cb, dbus_async_err_cb): return r def convert_reply(data): - dbus_async_cb(unicode(data['FeatureList'])) + dbus_async_cb(str(data['FeatureList'])) r.addCallback(convert_reply) r.addErrback(dbus_async_err_cb) @@ -198,12 +198,12 @@ def convert_reply(data): def Browse(self, ObjectID, BrowseFlag, Filter, StartingIndex, RequestedCount, SortCriteria, dbus_async_cb, dbus_async_err_cb): - arguments = {'ObjectID': unicode(ObjectID), - 'BrowseFlag': unicode(BrowseFlag), - 'Filter': unicode(Filter), + arguments = {'ObjectID': str(ObjectID), + 'BrowseFlag': str(BrowseFlag), + 'Filter': str(Filter), 'StartingIndex': int(StartingIndex), 'RequestedCount': int(RequestedCount), - 'SortCriteria': unicode(SortCriteria)} + 'SortCriteria': str(SortCriteria)} r = self.callAction('Browse', arguments) if r == '': return r @@ -214,14 +214,14 @@ def convert_reply(data): def append(item): i = dbus.Dictionary({}, signature='sv') - for k, v in item.attrib.items(): + for k, v in list(item.attrib.items()): i[un_namespace(k)] = v res = dbus.Array([], signature='v') for child in item: if un_namespace(child.tag) == 'DIDL-Lite:res': res_dict = dbus.Dictionary({}, signature='sv') - res_dict['url'] = unicode(child.text) - for k, v in child.attrib.items(): + res_dict['url'] = str(child.text) + for k, v in list(child.attrib.items()): res_dict[un_namespace(k)] = v res.append(res_dict) else: @@ -242,12 +242,12 @@ def append(item): def Search(self, ContainerID, SearchCriteria, Filter, StartingIndex, RequestedCount, SortCriteria, dbus_async_cb, dbus_async_err_cb): - arguments = {'ContainerID': unicode(ContainerID), - 'SearchCriteria': unicode(SearchCriteria), - 'Filter': unicode(Filter), + arguments = {'ContainerID': str(ContainerID), + 'SearchCriteria': str(SearchCriteria), + 'Filter': str(Filter), 'StartingIndex': int(StartingIndex), 'RequestedCount': int(RequestedCount), - 'SortCriteria': unicode(SortCriteria)} + 'SortCriteria': str(SortCriteria)} r = self.callAction('Search', arguments) if r == '': return r @@ -258,14 +258,14 @@ def convert_reply(data): def append(item): i = dbus.Dictionary({}, signature='sv') - for k, v in item.attrib.items(): + for k, v in list(item.attrib.items()): i[un_namespace(k)] = v res = dbus.Array([], signature='v') for child in item: if un_namespace(child.tag) == 'DIDL-Lite:res': res_dict = dbus.Dictionary({}, signature='sv') - res_dict['url'] = unicode(child.text) - for k, v in child.attrib.items(): + res_dict['url'] = str(child.text) + for k, v in list(child.attrib.items()): res_dict[un_namespace(k)] = v res.append(res_dict) else: @@ -287,14 +287,14 @@ def append(item): def CreateObject(self, ContainerID, Elements, dbus_async_cb, dbus_async_err_cb): - arguments = {'ContainerID': unicode(ContainerID), - 'Elements': unicode(Elements)} + arguments = {'ContainerID': str(ContainerID), + 'Elements': str(Elements)} r = self.callAction('CreateObject', arguments) if r == '': return r def convert_reply(data): - dbus_async_cb(unicode(data['ObjectID']), unicode(data['Result'])) + dbus_async_cb(str(data['ObjectID']), str(data['Result'])) r.addCallback(convert_reply) r.addErrback(dbus_async_err_cb) @@ -303,7 +303,7 @@ def convert_reply(data): def DestroyObject(self, ObjectID, dbus_async_cb, dbus_async_err_cb): - arguments = {'ObjectID': unicode(ObjectID)} + arguments = {'ObjectID': str(ObjectID)} r = self.callAction('DestroyObject', arguments) if r == '': return r @@ -318,8 +318,8 @@ def convert_reply(data): def UpdateObject(self, ObjectID, CurrentTagValue, NewTagValue, dbus_async_cb, dbus_async_err_cb): - arguments = {'ObjectID': unicode(ObjectID), - 'CurrentTagValue': unicode(CurrentTagValue), + arguments = {'ObjectID': str(ObjectID), + 'CurrentTagValue': str(CurrentTagValue), 'NewTagValue': NewTagValue} r = self.callAction('UpdateObject', arguments) if r == '': @@ -335,14 +335,14 @@ def convert_reply(data): def MoveObject(self, ObjectID, NewParentID, dbus_async_cb, dbus_async_err_cb): - arguments = {'ObjectID': unicode(ObjectID), - 'NewParentID': unicode(NewParentID)} + arguments = {'ObjectID': str(ObjectID), + 'NewParentID': str(NewParentID)} r = self.callAction('MoveObject', arguments) if r == '': return r def convert_reply(data): - dbus_async_cb(unicode(data['NewObjectID'])) + dbus_async_cb(str(data['NewObjectID'])) r.addCallback(convert_reply) r.addErrback(dbus_async_err_cb) @@ -351,14 +351,14 @@ def convert_reply(data): def ImportResource(self, SourceURI, DestinationURI, dbus_async_cb, dbus_async_err_cb): - arguments = {'SourceURI': unicode(SourceURI), - 'DestinationURI': unicode(DestinationURI)} + arguments = {'SourceURI': str(SourceURI), + 'DestinationURI': str(DestinationURI)} r = self.callAction('ImportResource', arguments) if r == '': return r def convert_reply(data): - dbus_async_cb(unicode(data['TransferID'])) + dbus_async_cb(str(data['TransferID'])) r.addCallback(convert_reply) r.addErrback(dbus_async_err_cb) @@ -367,14 +367,14 @@ def convert_reply(data): def ExportResource(self, SourceURI, DestinationURI, dbus_async_cb, dbus_async_err_cb): - arguments = {'SourceURI': unicode(SourceURI), - 'DestinationURI': unicode(DestinationURI)} + arguments = {'SourceURI': str(SourceURI), + 'DestinationURI': str(DestinationURI)} r = self.callAction('ExportResource', arguments) if r == '': return r def convert_reply(data): - dbus_async_cb(unicode(data['TransferID'])) + dbus_async_cb(str(data['TransferID'])) r.addCallback(convert_reply) r.addErrback(dbus_async_err_cb) @@ -383,7 +383,7 @@ def convert_reply(data): def DeleteResource(self, ResourceURI, dbus_async_cb, dbus_async_err_cb): - arguments = {'ResourceURI': unicode(ResourceURI)} + arguments = {'ResourceURI': str(ResourceURI)} r = self.callAction('DeleteResource', arguments) if r == '': return r @@ -398,7 +398,7 @@ def convert_reply(data): def StopTransferResource(self, TransferID, dbus_async_cb, dbus_async_err_cb): - arguments = {'TransferID': unicode(TransferID)} + arguments = {'TransferID': str(TransferID)} r = self.callAction('StopTransferResource', arguments) if r == '': return r @@ -413,13 +413,13 @@ def convert_reply(data): def GetTransferProgress(self, TransferID, dbus_async_cb, dbus_async_err_cb): - arguments = {'TransferID': unicode(TransferID)} + arguments = {'TransferID': str(TransferID)} r = self.callAction('GetTransferProgress', arguments) if r == '': return r def convert_reply(data): - dbus_async_cb(unicode(data['TransferStatus']), unicode(data['TransferLength']), unicode(data['TransferTotal'])) + dbus_async_cb(str(data['TransferStatus']), str(data['TransferLength']), str(data['TransferTotal'])) r.addCallback(convert_reply) r.addErrback(dbus_async_err_cb) @@ -428,14 +428,14 @@ def convert_reply(data): def CreateReference(self, ContainerID, ObjectID, dbus_async_cb, dbus_async_err_cb): - arguments = {'ContainerID': unicode(ContainerID), - 'ObjectID': unicode(ObjectID)} + arguments = {'ContainerID': str(ContainerID), + 'ObjectID': str(ObjectID)} r = self.callAction('CreateReference', arguments) if r == '': return r def convert_reply(data): - dbus_async_cb(unicode(data['NewID'])) + dbus_async_cb(str(data['NewID'])) r.addCallback(convert_reply) r.addErrback(dbus_async_err_cb) @@ -515,9 +515,9 @@ def _get_service_methods(self): for func in dir(self): func = getattr(self, func) if callable(func) and hasattr(func, '_dbus_is_method'): - print func, func._dbus_interface, func._dbus_is_method + print(func, func._dbus_interface, func._dbus_is_method) if hasattr(func, 'im_func'): - print func.im_func + print(func.__func__) def variable_changed(self, variable): #print self.service, "got signal for change of", variable @@ -539,7 +539,7 @@ def get_scpd_xml(self): def get_available_actions(self): actions = self.service.get_actions() r = [] - for name in actions.keys(): + for name in list(actions.keys()): r.append(name) return r @@ -562,8 +562,8 @@ def reply(data): if callable(func): kwargs = {} try: - for k, v in arguments.items(): - kwargs[str(k)] = unicode(v) + for k, v in list(arguments.items()): + kwargs[str(k)] = str(v) except: pass d = func(**kwargs) @@ -576,7 +576,7 @@ def reply(data): sender_keyword='sender', connection_keyword='connection') def call_action(self, name, arguments, dbus_async_cb, dbus_async_err_cb, sender=None, connection=None): - print "call_action called by ", sender, connection, self.type, self.tube + print("call_action called by ", sender, connection, self.type, self.tube) def reply(data, name, connection): if hasattr(connection, '_tube') == True: @@ -588,12 +588,12 @@ def reply(data, name, connection): for res in item.res: remote_protocol, remote_network, remote_content_format, _ = res.protocolInfo.split(':') if remote_protocol == 'http-get' and remote_network == '*': - quoted_url = 'mirabeau' + '/' + urllib.quote_plus(res.data) - print "modifying", res.data + quoted_url = 'mirabeau' + '/' + urllib.parse.quote_plus(res.data) + print("modifying", res.data) host_port = ':'.join((self.service.device.client.coherence.mirabeau._external_address, str(self.service.device.client.coherence.mirabeau._external_port))) - res.data = urlparse.urlunsplit(('http', host_port, quoted_url, "", "")) - print "--->", res.data + res.data = urllib.parse.urlunsplit(('http', host_port, quoted_url, "", "")) + print("--->", res.data) new_res.append(res) changed = True item.res = new_res @@ -608,8 +608,8 @@ def reply(data, name, connection): if action: kwargs = {} try: - for k, v in arguments.items(): - kwargs[str(k)] = unicode(v) + for k, v in list(arguments.items()): + kwargs[str(k)] = str(v) except: pass d = action.call(**kwargs) @@ -626,7 +626,7 @@ def reply(data): if self.service.client is not None: kwargs = {} - for k, v in arguments.items(): + for k, v in list(arguments.items()): kwargs[str(k)] = str(v) d = self.service.client.destroy_object(**kwargs) d.addCallback(reply) @@ -637,16 +637,16 @@ def reply(data): def subscribe(self): notify = [] if self.service: - notify = [v for v in self.service._variables[0].values() if v.send_events == True] + notify = [v for v in list(self.service._variables[0].values()) if v.send_events == True] if len(notify) == 0: return data = {} for n in notify: if n.name == 'LastChange': lc = {} - for instance, vdict in self.service._variables.items(): + for instance, vdict in list(self.service._variables.items()): v = {} - for variable in vdict.values(): + for variable in list(vdict.values()): if(variable.name != 'LastChange' and variable.name[0:11] != 'A_ARG_TYPE_' and variable.never_evented == False): @@ -659,9 +659,9 @@ def subscribe(self): if len(v) > 0: lc[str(instance)] = v if len(lc) > 0: - data[unicode(n.name)] = lc + data[str(n.name)] = lc else: - data[unicode(n.name)] = unicode(n.value) + data[str(n.name)] = str(n.value) return self.dbus_device.device.get_id(), self.type, dbus.Dictionary(data, signature='sv', variant_level=3) @@ -727,7 +727,7 @@ def get_info(self): 'device_type': self.device.get_device_type(), 'friendly_name': self.device.get_friendly_name(), 'udn': self.device.get_id(), - 'uri': list(urlparse.urlsplit(self.device.get_location())), + 'uri': list(urllib.parse.urlsplit(self.device.get_location())), 'presentation_url': self.device.get_presentation_url(), 'parent_udn': self.device.get_parent_id(), 'services': services} @@ -811,7 +811,7 @@ def __init__(self, controlpoint, bus=None): def shutdown(self): louie.disconnect(self._device_detected, 'Coherence.UPnP.Device.detection_completed', louie.Any) louie.disconnect(self._device_removed, 'Coherence.UPnP.Device.removed', louie.Any) - for device_id, device in self.devices.iteritems(): + for device_id, device in self.devices.items(): device.shutdown() self.devices = {} self.remove_from_connection() @@ -820,7 +820,7 @@ def shutdown(self): @dbus.service.method(BUS_NAME, in_signature='sv', out_signature='') def pin(self, key, value): self.pinboard[key] = value - print self.pinboard + print(self.pinboard) @dbus.service.method(BUS_NAME, in_signature='s', out_signature='v') def get_pin(self, key): @@ -832,10 +832,10 @@ def unpin(self, key): @dbus.service.method(BUS_NAME, in_signature='s', out_signature='s') def create_oob(self, file): - print 'create_oob' + print('create_oob') key = str(time.time()) self.pinboard[key] = file - print self.pinboard + print(self.pinboard) return self.controlpoint.coherence.urlbase + 'oob?key=' + key def remove_client(self, usn, client): @@ -864,7 +864,7 @@ def hostname(self): @dbus.service.method(BUS_NAME, in_signature='', out_signature='av') def get_devices(self): r = [] - for device in self.devices.values(): + for device in list(self.devices.values()): #r.append(device.path()) r.append(device.get_info()) return dbus.Array(r, signature='v', variant_level=2) @@ -886,20 +886,20 @@ def iterate_devices(devices): def done(generator): dbus_async_cb(dbus.Array(infos, signature='v', variant_level=2)) - devices = self.devices.copy().values() + devices = list(self.devices.copy().values()) dfr = task.coiterate(iterate_devices(devices)) dfr.addCallbacks(done, lambda failure: dbus_async_err_cb(failure.value)) @dbus.service.method(BUS_NAME, in_signature='s', out_signature='v') def get_device_with_id(self, id): - for device in self.devices.values(): + for device in list(self.devices.values()): if id == device.device.get_id(): return device.get_info() @dbus.service.method(BUS_NAME, in_signature='sa{ss}', out_signature='s') def add_plugin(self, backend, arguments): kwargs = {} - for k, v in arguments.iteritems(): + for k, v in arguments.items(): kwargs[str(k)] = str(v) p = self.controlpoint.coherence.add_plugin(backend, **kwargs) return str(p.uuid) @@ -919,8 +919,8 @@ def call_plugin(self, uuid, method, arguments): if function == None: return "" kwargs = {} - for k, v in arguments.iteritems(): - kwargs[str(k)] = unicode(v) + for k, v in arguments.items(): + kwargs[str(k)] = str(v) function(**kwargs) return uuid @@ -931,8 +931,8 @@ def create_object(self, device_id, container_id, arguments, dbus_async_cb, dbus_ if device != None: client = device.get_client() new_arguments = {} - for k, v in arguments.items(): - new_arguments[str(k)] = unicode(v) + for k, v in list(arguments.items()): + new_arguments[str(k)] = str(v) def reply(data): dbus_async_cb(dbus.Dictionary(data, signature='sv', variant_level=4)) @@ -961,13 +961,13 @@ def put_resource(self, destination_uri, filepath, dbus_async_cb, dbus_async_err_ def reply(data): dbus_async_cb(200) - d = self.controlpoint.put_resource(str(destination_uri), unicode(filepath)) + d = self.controlpoint.put_resource(str(destination_uri), str(filepath)) d.addCallback(reply) d.addErrback(dbus_async_err_cb) def _device_detected(self, device): id = device.get_id() - #print "new_device_detected",device.get_usn(),device.friendly_device_type,id + print("new_device_detected", device.get_usn(), device.friendly_device_type, id) if id not in self.devices: new_device = DBusDevice(device, self.bus) self.devices[id] = new_device @@ -980,7 +980,7 @@ def _device_detected(self, device): self.UPnP_ControlPoint_MediaRenderer_detected(info, id) def _device_removed(self, usn=''): - #print "_device_removed", usn + print("_device_removed", usn) id = usn.split('::')[0] device = self.devices[id] self.device_removed(id) @@ -992,7 +992,7 @@ def _device_removed(self, usn=''): reactor.callLater(1, self.remove, id) def cp_ms_detected(self, client, udn=''): - #print "cp_ms_detected", udn + print("cp_ms_detected", udn) if client.device.get_id() not in self.devices: new_device = DBusDevice(client.device, self.bus) self.devices[client.device.get_id()] = new_device @@ -1005,7 +1005,7 @@ def cp_mr_detected(self, client, udn=''): self.UPnP_ControlPoint_MediaRenderer_detected(new_device.get_info(), udn) def cp_ms_removed(self, udn): - #print "cp_ms_removed", udn + print("cp_ms_removed", udn) self.UPnP_ControlPoint_MediaServer_removed(udn) # schedule removal of device from our cache after signal has # been called. Let's assume one second is long enough... @@ -1057,7 +1057,7 @@ def getDMSList(self): signature='v', variant_level=2) def _get_devices_of_type(self, typ): - return [device.get_info() for device in self.devices.itervalues() + return [device.get_info() for device in self.devices.values() if device.get_friendly_device_type() == typ] @dbus.service.method(DLNA_BUS_NAME + '.DMC', in_signature='', diff --git a/coherence/dispatcher.py b/coherence/dispatcher.py index df23e62b..60df3e68 100644 --- a/coherence/dispatcher.py +++ b/coherence/dispatcher.py @@ -25,7 +25,7 @@ def __repr__(self): ['%r' % x for x in self.arguments] ), ', '.join( - ['%s=%s' % (x, y) for x, y in self.keywords.iteritems()] + ['%s=%s' % (x, y) for x, y in self.keywords.items()] ) ) @@ -39,7 +39,7 @@ class Dispatcher(object): def __init__(self): self.receivers = {} - for signal in self.__signals__.iterkeys(): + for signal in self.__signals__.keys(): self.receivers[signal] = [] def connect(self, signal, callback, *args, **kw): @@ -70,7 +70,7 @@ def emit(self, signal, *args, **kwargs): for receiver in self._get_receivers(signal): try: results.append((receiver, receiver(*args, **kwargs))) - except Exception, e: + except Exception as e: errors.append((receiver, e)) return results, errors diff --git a/coherence/extern/covers_by_amazon.py b/coherence/extern/covers_by_amazon.py index 6f10222d..92130b4b 100644 --- a/coherence/extern/covers_by_amazon.py +++ b/coherence/extern/covers_by_amazon.py @@ -42,8 +42,8 @@ from lxml import etree import os -import urllib -import StringIO +import urllib.request, urllib.parse, urllib.error +import io from twisted.internet import reactor from twisted.internet import defer @@ -160,27 +160,27 @@ def __init__(self, filename, aws_key, callback=None, not_found_callback=None, def sanitize(s): if s is not None: - s = unicode(s.lower()) - s = s.replace(unicode(u'ä'), unicode('ae')) - s = s.replace(unicode(u'ö'), unicode('oe')) - s = s.replace(unicode(u'ü'), unicode('ue')) - s = s.replace(unicode(u'ß'), unicode('ss')) - if isinstance(s, unicode): + s = str(s.lower()) + s = s.replace(str('ä'), str('ae')) + s = s.replace(str('ö'), str('oe')) + s = s.replace(str('ü'), str('ue')) + s = s.replace(str('ß'), str('ss')) + if isinstance(s, str): s = s.encode('ascii', 'ignore') else: s = s.decode('utf-8').encode('ascii', 'ignore') return s if asin != None: - query = aws_asin_query + '&ItemId=%s' % urllib.quote(asin) + query = aws_asin_query + '&ItemId=%s' % urllib.parse.quote(asin) elif (artist is not None or title is not None): query = aws_artist_query if artist is not None: artist = sanitize(artist) - query = '&'.join((query, 'Artist=%s' % urllib.quote(artist))) + query = '&'.join((query, 'Artist=%s' % urllib.parse.quote(artist))) if title is not None: title = sanitize(title) - query = '&'.join((query, 'Title=%s' % urllib.quote(title))) + query = '&'.join((query, 'Title=%s' % urllib.parse.quote(title))) else: raise KeyError("Please supply either asin, title or artist and title arguments") url = self.server + self.aws_base_query + aws_response_group + query @@ -200,13 +200,13 @@ def got_image(self, result, convert_from='', convert_to=''): try: import Image - im = Image.open(StringIO.StringIO(result)) + im = Image.open(io.StringIO(result)) name, file_ext = os.path.splitext(self.filename) self.filename = name + convert_to im.save(self.filename) except ImportError: - print "we need the Python Imaging Library to do image conversion" + print("we need the Python Imaging Library to do image conversion") if self.filename == None: data = result @@ -286,7 +286,8 @@ def got_response(self, result): self._errcall() def got_error(self, failure, url): - print "got_error", failure, url + print("got_error", failure, url) + if __name__ == '__main__': @@ -302,17 +303,17 @@ class Options(usage.Options): options = Options() try: options.parseOptions() - except usage.UsageError, errortext: + except usage.UsageError as errortext: import sys - print '%s: %s' % (sys.argv[0], errortext) - print '%s: Try --help for usage details.' % (sys.argv[0]) + print('%s: %s' % (sys.argv[0], errortext)) + print('%s: Try --help for usage details.' % (sys.argv[0])) sys.exit(1) def got_it(filename, *args, **kwargs): - print "Mylady, it is an image and its name is", filename, args, kwargs + print("Mylady, it is an image and its name is", filename, args, kwargs) aws_key = '1XHSE4FQJ0RK0X3S9WR2' - print options['asin'], options['artist'], options['title'] + print(options['asin'], options['artist'], options['title']) if len(options['asin']): reactor.callWhenRunning(CoverGetter, options['filename'], aws_key, callback=got_it, asin=options['asin']) elif len(options['artist']) and len(options['title']): diff --git a/coherence/extern/db_row.py b/coherence/extern/db_row.py index 02920964..d0348197 100644 --- a/coherence/extern/db_row.py +++ b/coherence/extern/db_row.py @@ -108,7 +108,7 @@ def __setslice__(self, i, j, list): def keys(self): """Return the field names""" - return self.fields.keys() + return list(self.fields.keys()) def keymappings(self): """Return a dictionary of the keys and their indices in the row""" @@ -116,13 +116,13 @@ def keymappings(self): def has_key(self, key): """Return whether the given key is valid""" - return self.fields.has_key(key) + return key in self.fields def as_dict(self): d = {} - for field_name, pos in self.fields.iteritems(): + for field_name, pos in self.fields.items(): d[field_name] = self.row[pos] - for field_name, field in self._extra_fields.iteritems(): + for field_name, field in self._extra_fields.items(): d[field_name] = field return d @@ -130,7 +130,7 @@ def __len__(self): """Return how many columns are in this row""" return len(self.row) - def __nonzero__(self): + def __bool__(self): return len(self.row) != 0 def __eq__(self, other): diff --git a/coherence/extern/simple_plugin.py b/coherence/extern/simple_plugin.py index 55288aef..8b968a23 100644 --- a/coherence/extern/simple_plugin.py +++ b/coherence/extern/simple_plugin.py @@ -60,9 +60,9 @@ def checkin(self, plugin_path): if plugin != '__init__.py' and os.path.isfile(p) and os.path.splitext(p)[1] == '.py': try: __import__(os.path.splitext(plugin)[0], None, None, ['']) - except Exception, msg: + except Exception as msg: if self.log is None: - print "can't import %r - %s" % (os.path.splitext(plugin)[0], msg) + print("can't import %r - %s" % (os.path.splitext(plugin)[0], msg)) else: self.log("can't import %r - %r" % (os.path.splitext(plugin)[0], msg)) diff --git a/coherence/extern/xdg.py b/coherence/extern/xdg.py index 7db030c2..3f3bd197 100644 --- a/coherence/extern/xdg.py +++ b/coherence/extern/xdg.py @@ -36,4 +36,4 @@ def xdg_content(): if __name__ == '__main__': - print xdg_content() + print(xdg_content()) diff --git a/coherence/extern/youtubedl/__init__.py b/coherence/extern/youtubedl/__init__.py index 676df99c..351420dc 100644 --- a/coherence/extern/youtubedl/__init__.py +++ b/coherence/extern/youtubedl/__init__.py @@ -1,4 +1,4 @@ -from youtubedl import FileDownloader -from youtubedl import YoutubeIE -from youtubedl import MetacafeIE -from youtubedl import YoutubePlaylistIE +from .youtubedl import FileDownloader +from .youtubedl import YoutubeIE +from .youtubedl import MetacafeIE +from .youtubedl import YoutubePlaylistIE diff --git a/coherence/extern/youtubedl/youtubedl.py b/coherence/extern/youtubedl/youtubedl.py index 1d458145..7e205465 100644 --- a/coherence/extern/youtubedl/youtubedl.py +++ b/coherence/extern/youtubedl/youtubedl.py @@ -4,8 +4,8 @@ # Author: Danny Colligan # Author: Jean-Michel Sizun (integration within coherence framework) # License: Public domain code -import htmlentitydefs -import httplib +import html.entities +import http.client import locale import math import netrc @@ -16,7 +16,7 @@ import string import sys import time -from urllib import urlencode, unquote, unquote_plus +import urllib from coherence.upnp.core.utils import getPage std_headers = { @@ -157,7 +157,7 @@ def __init__(self, params): def pmkdir(filename): """Create directory components in filename. Similar to Unix "mkdir -p".""" components = filename.split(os.sep) - aggregate = [os.sep.join(components[0:x]) for x in xrange(1, len(components))] + aggregate = [os.sep.join(components[0:x]) for x in range(1, len(components))] aggregate = ['%s%s' % (x, os.sep) for x in aggregate] # Finish names with separator for dir in aggregate: if not os.path.exists(dir): @@ -172,7 +172,7 @@ def format_bytes(bytes): if bytes == 0.0: exponent = 0 else: - exponent = long(math.log(bytes, 1024.0)) + exponent = int(math.log(bytes, 1024.0)) suffix = 'bkMGTPEZY'[exponent] converted = float(bytes) / float(1024 ** exponent) return '%.2f%s' % (converted, suffix) @@ -191,7 +191,7 @@ def calc_eta(start, now, total, current): if current == 0 or dif < 0.001: # One millisecond return '--:--' rate = float(current) / dif - eta = long((float(total) - float(current)) / rate) + eta = int((float(total) - float(current)) / rate) (eta_mins, eta_secs) = divmod(eta, 60) if eta_mins > 99: return '--:--' @@ -209,13 +209,13 @@ def best_block_size(elapsed_time, bytes): new_min = max(bytes / 2.0, 1.0) new_max = min(max(bytes * 2.0, 1.0), 4194304) # Do not surpass 4 MB if elapsed_time < 0.001: - return long(new_max) + return int(new_max) rate = bytes / elapsed_time if rate > new_max: - return long(new_max) + return int(new_max) if rate < new_min: - return long(new_min) - return long(rate) + return int(new_min) + return int(rate) @staticmethod def parse_bytes(bytestr): @@ -225,13 +225,13 @@ def parse_bytes(bytestr): return None number = float(matchobj.group(1)) multiplier = 1024.0 ** 'bkmgtpezy'.index(matchobj.group(2).lower()) - return long(round(number * multiplier)) + return int(round(number * multiplier)) @staticmethod def verify_url(url): """Verify a URL is valid and data could be downloaded. Return real data URL.""" - request = urllib2.Request(url, None, std_headers) - data = urllib2.urlopen(request) + request = urllib.request.Request(url, None, std_headers) + data = urllib.request.urlopen(request) data.read(1) url = data.geturl() data.close() @@ -250,16 +250,16 @@ def add_post_processor(self, pp): def to_stdout(self, message, skip_eol=False): """Print message to stdout if not in quiet mode.""" if not self.params.get('quiet', False): - print (u'%s%s' % (message, [u'\n', u''][skip_eol])).encode(preferredencoding()), + print(('%s%s' % (message, ['\n', ''][skip_eol])).encode(preferredencoding()), end=' ') sys.stdout.flush() def to_stderr(self, message): """Print message to stderr.""" - print >> sys.stderr, message.encode(preferredencoding()) + print(message.encode(preferredencoding()), file=sys.stderr) def fixed_template(self): """Checks if the output template is fixed.""" - return (re.search(ur'(?u)%\(.+?\)s', self.params['outtmpl']) is None) + return (re.search(r'(?u)%\(.+?\)s', self.params['outtmpl']) is None) def trouble(self, message=None): """Determine action to take when a download problem appears. @@ -289,28 +289,28 @@ def slow_down(self, start_time, byte_counter): def report_destination(self, filename): """Report destination filename.""" - self.to_stdout(u'[download] Destination: %s' % filename) + self.to_stdout('[download] Destination: %s' % filename) def report_progress(self, percent_str, data_len_str, speed_str, eta_str): """Report download progress.""" - self.to_stdout(u'\r[download] %s of %s at %s ETA %s' % + self.to_stdout('\r[download] %s of %s at %s ETA %s' % (percent_str, data_len_str, speed_str, eta_str), skip_eol=True) def report_resuming_byte(self, resume_len): """Report attemtp to resume at given byte.""" - self.to_stdout(u'[download] Resuming download at byte %s' % resume_len) + self.to_stdout('[download] Resuming download at byte %s' % resume_len) def report_file_already_downloaded(self, file_name): """Report file has already been fully downloaded.""" - self.to_stdout(u'[download] %s has already been downloaded' % file_name) + self.to_stdout('[download] %s has already been downloaded' % file_name) def report_unable_to_resume(self): """Report it was impossible to resume download.""" - self.to_stdout(u'[download] Unable to resume') + self.to_stdout('[download] Unable to resume') def report_finish(self): """Report download finished.""" - self.to_stdout(u'') + self.to_stdout('') def process_info(self, info_dict): """Process a single dictionary returned by an InfoExtractor.""" @@ -318,48 +318,48 @@ def process_info(self, info_dict): if self.params.get('simulate', False): try: info_dict['url'] = self.verify_url(info_dict['url']) - except (OSError, IOError, urllib2.URLError, httplib.HTTPException, socket.error), err: + except (OSError, IOError, urllib.error.URLError, http.client.HTTPException, socket.error) as err: raise UnavailableFormatError # Forced printings if self.params.get('forcetitle', False): - print info_dict['title'].encode(preferredencoding()) + print(info_dict['title'].encode(preferredencoding())) if self.params.get('forceurl', False): - print info_dict['url'].encode(preferredencoding()) + print(info_dict['url'].encode(preferredencoding())) return try: template_dict = dict(info_dict) - template_dict['epoch'] = unicode(long(time.time())) + template_dict['epoch'] = str(int(time.time())) filename = self.params['outtmpl'] % template_dict - except (ValueError, KeyError), err: + except (ValueError, KeyError) as err: self.trouble('ERROR: invalid output template or system charset: %s' % str(err)) if self.params['nooverwrites'] and os.path.exists(filename): - self.to_stderr(u'WARNING: file exists: %s; skipping' % filename) + self.to_stderr('WARNING: file exists: %s; skipping' % filename) return try: self.pmkdir(filename) - except (OSError, IOError), err: + except (OSError, IOError) as err: self.trouble('ERROR: unable to create directories: %s' % str(err)) return try: success = self._do_download(filename, info_dict['url']) - except (OSError, IOError), err: + except (OSError, IOError) as err: raise UnavailableFormatError - except (urllib2.URLError, httplib.HTTPException, socket.error), err: + except (urllib.error.URLError, http.client.HTTPException, socket.error) as err: self.trouble('ERROR: unable to download video data: %s' % str(err)) return - except (ContentTooShortError, ), err: + except (ContentTooShortError, ) as err: self.trouble('ERROR: content too short (expected %s bytes and served %s)' % (err.expected, err.downloaded)) return if success: try: self.post_process(filename, info_dict) - except (PostProcessingError), err: + except (PostProcessingError) as err: self.trouble('ERROR: postprocessing: %s' % str(err)) return @@ -486,11 +486,11 @@ def set_downloader(self, downloader): def to_stdout(self, message): """Print message to stdout if downloader is not in quiet mode.""" if self._downloader is None or not self._downloader.get_params().get('quiet', False): - print message + print(message) def to_stderr(self, message): """Print message to stderr.""" - print >> sys.stderr, message + print(message, file=sys.stderr) def _real_initialize(self): """Real initialization process. Redefine in subclasses.""" @@ -504,10 +504,10 @@ def _real_extract(self, url): class YoutubeIE(InfoExtractor): """Information extractor for youtube.com.""" - _VALID_URL = r'^((?:http://)?(?:\w+\.)?youtube\.com/(?:(?:v/)|(?:(?:watch(?:\.php)?)?\?(?:.+&)?v=)))?([0-9A-Za-z_-]+)(?(1).+)?$' - _LANG_URL = r'http://uk.youtube.com/?hl=en&persist_hl=1&gl=US&persist_gl=1&opt_out_ackd=1' - _LOGIN_URL = 'http://www.youtube.com/signup?next=/&gl=US&hl=en' - _AGE_URL = 'http://www.youtube.com/verify_age?next_url=/&gl=US&hl=en' + _VALID_URL = r'^((?:https://)?(?:\w+\.)?youtube\.com/(?:(?:v/)|(?:(?:watch(?:\.php)?)?\?(?:.+&)?v=)))?([0-9A-Za-z_-]+)(?(1).+)?$' + _LANG_URL = r'https://uk.youtube.com/?hl=en&persist_hl=1&gl=US&persist_gl=1&opt_out_ackd=1' + _LOGIN_URL = 'https://www.youtube.com/signup?next=/&gl=US&hl=en' + _AGE_URL = 'https://www.youtube.com/verify_age?next_url=/&gl=US&hl=en' _NETRC_MACHINE = 'youtube' _available_formats = ['22', '35', '18', '5', '17', '13', None] # listed in order of priority for -b flag _video_extensions = { @@ -527,50 +527,50 @@ def htmlentity_transform(matchobj): entity = matchobj.group(1) # Known non-numeric HTML entity - if entity in htmlentitydefs.name2codepoint: - return unichr(htmlentitydefs.name2codepoint[entity]) + if entity in html.entities.name2codepoint: + return chr(html.entities.name2codepoint[entity]) # Unicode character - mobj = re.match(ur'(?u)#(x?\d+)', entity) + mobj = re.match(r'(?u)#(x?\d+)', entity) if mobj is not None: numstr = mobj.group(1) - if numstr.startswith(u'x'): + if numstr.startswith('x'): base = 16 - numstr = u'0%s' % numstr + numstr = '0%s' % numstr else: base = 10 - return unichr(long(numstr, base)) + return chr(int(numstr, base)) # Unknown entity in name, return its literal representation - return (u'&%s;' % entity) + return ('&%s;' % entity) def report_lang(self): """Report attempt to set language.""" - self._downloader.to_stdout(u'[youtube] Setting language') + self._downloader.to_stdout('[youtube] Setting language') def report_login(self): """Report attempt to log in.""" - self._downloader.to_stdout(u'[youtube] Logging in') + self._downloader.to_stdout('[youtube] Logging in') def report_age_confirmation(self): """Report attempt to confirm age.""" - self._downloader.to_stdout(u'[youtube] Confirming age') + self._downloader.to_stdout('[youtube] Confirming age') def report_video_info_webpage_download(self, video_id): """Report attempt to download video info webpage.""" - self._downloader.to_stdout(u'[youtube] %s: Downloading video info webpage' % video_id) + self._downloader.to_stdout('[youtube] %s: Downloading video info webpage' % video_id) def report_information_extraction(self, video_id): """Report attempt to extract video information.""" - self._downloader.to_stdout(u'[youtube] %s: Extracting video information' % video_id) + self._downloader.to_stdout('[youtube] %s: Extracting video information' % video_id) def report_unavailable_format(self, video_id, format): """Report extracted video URL.""" - self._downloader.to_stdout(u'[youtube] %s: Format %s not available' % (video_id, format)) + self._downloader.to_stdout('[youtube] %s: Format %s not available' % (video_id, format)) def report_video_url(self, video_id, video_real_url): """Report extracted video URL.""" - self._downloader.to_stdout(u'[youtube] %s: URL: %s' % (video_id, video_real_url)) + self._downloader.to_stdout('[youtube] %s: URL: %s' % (video_id, video_real_url)) def _real_initialize(self): @@ -593,32 +593,32 @@ def _real_initialize(self): password = info[2] else: raise netrc.NetrcParseError('No authenticators for %s' % self._NETRC_MACHINE) - except (IOError, netrc.NetrcParseError), err: - self._downloader.to_stderr(u'WARNING: parsing .netrc: %s' % str(err)) + except (IOError, netrc.NetrcParseError) as err: + self._downloader.to_stderr('WARNING: parsing .netrc: %s' % str(err)) return def gotAgeConfirmedPage(result): - print "Age confirmed in Youtube" + print("Age confirmed in Youtube") def gotLoggedInPage(result): data, headers = result if re.search(r'(?i)]* name="loginForm"', data) is not None: - print 'WARNING: unable to log in: bad username or password' + print('WARNING: unable to log in: bad username or password') return - print "logged in in Youtube" + print("logged in in Youtube") # Confirm age age_form = { 'next_url': '/', 'action_confirm': 'Confirm', } - postdata = urlencode(age_form) + postdata = urllib.parse.urlencode(age_form) d = getPage(self._AGE_URL, postdata=postdata, headers=std_headers) d.addCallback(gotAgeConfirmedPage) def gotLoginError(error): - print "Unable to login to Youtube : %s:%s @ %s" % (username, password, self._LOGIN_URL) - print "Error: %s" % error + print("Unable to login to Youtube : %s:%s @ %s" % (username, password, self._LOGIN_URL)) + print("Error: %s" % error) return def gotLanguageSet(result): @@ -634,13 +634,13 @@ def gotLanguageSet(result): 'username': username, 'password': password, } - postdata = urlencode(login_form) + postdata = urllib.parse.urlencode(login_form) d = getPage(self._LOGIN_URL, method='POST', postdata=postdata, headers=std_headers) d.addCallbacks(gotLoggedInPage, gotLoginError) def gotLanguageSetError(error): - print "Unable to process Youtube request: %s" % self._LANG_URL - print "Error: %s" % error + print("Unable to process Youtube request: %s" % self._LANG_URL) + print("Error: %s" % error) return # Set language (will lead to log in, and then age confirmation) @@ -651,7 +651,7 @@ def _real_extract(self, url): # Extract video id from URL mobj = re.match(self._VALID_URL, url) if mobj is None: - self._downloader.trouble(u'ERROR: invalid URL: %s' % url) + self._downloader.trouble('ERROR: invalid URL: %s' % url) return video_id = mobj.group(2) @@ -670,7 +670,7 @@ def _real_extract(self, url): video_extension = self._video_extensions.get(format_param, 'flv') # video info - video_info_url = 'http://www.youtube.com/get_video_info?&video_id=%s&el=detailpage&ps=default&eurl=&gl=US&hl=en' % video_id + video_info_url = 'https://www.youtube.com/get_video_info?&video_id=%s&el=detailpage&ps=default&eurl=&gl=US&hl=en' % video_id if format_param is not None: video_info_url = '%s&fmt=%s' % (video_info_url, format_param) @@ -679,13 +679,13 @@ def gotPage(result, format_param, video_extension): # check format if (format_param == '22'): - print "Check if HD video exists..." + print("Check if HD video exists...") mobj = re.search(r'var isHDAvailable = true;', video_info_webpage) if mobj is None: - print "No HD video -> switch back to SD" + print("No HD video -> switch back to SD") format_param = '18' else: - print "...HD video OK!" + print("...HD video OK!") # "t" param mobj = re.search(r'(?m)&token=([^&]+)(?:&|$)', video_info_webpage) @@ -693,38 +693,38 @@ def gotPage(result, format_param, video_extension): # Attempt to see if YouTube has issued an error message mobj = re.search(r'(?m)&reason=([^&]+)(?:&|$)', video_info_webpage) if mobj is None: - self.to_stderr(u'ERROR: unable to extract "t" parameter') - print video_info_webpage + self.to_stderr('ERROR: unable to extract "t" parameter') + print(video_info_webpage) return [None] else: - reason = unquote_plus(mobj.group(1)) - self.to_stderr(u'ERROR: YouTube said: %s' % reason.decode('utf-8')) + reason = urllib.parse.unquote_plus(mobj.group(1)) + self.to_stderr('ERROR: YouTube said: %s' % reason.decode('utf-8')) - token = unquote(mobj.group(1)) - video_real_url = 'http://www.youtube.com/get_video?video_id=%s&t=%s&eurl=&el=detailpage&ps=default&gl=US&hl=en' % (video_id, token) + token = urllib.parse.unquote(mobj.group(1)) + video_real_url = 'https://www.youtube.com/get_video?video_id=%s&t=%s&eurl=&el=detailpage&ps=default&gl=US&hl=en' % (video_id, token) if format_param is not None: video_real_url = '%s&fmt=%s' % (video_real_url, format_param) # uploader mobj = re.search(r'(?m)&author=([^&]+)(?:&|$)', video_info_webpage) if mobj is None: - self._downloader.trouble(u'ERROR: unable to extract uploader nickname') + self._downloader.trouble('ERROR: unable to extract uploader nickname') return - video_uploader = unquote(mobj.group(1)) + video_uploader = urllib.parse.unquote(mobj.group(1)) # title mobj = re.search(r'(?m)&title=([^&]+)(?:&|$)', video_info_webpage) if mobj is None: - self._downloader.trouble(u'ERROR: unable to extract video title') + self._downloader.trouble('ERROR: unable to extract video title') return - video_title = unquote(mobj.group(1)) + video_title = urllib.parse.unquote(mobj.group(1)) video_title = video_title.decode('utf-8') - video_title = re.sub(ur'(?u)&(.+?);', self.htmlentity_transform, video_title) - video_title = video_title.replace(os.sep, u'%') + video_title = re.sub(r'(?u)&(.+?);', self.htmlentity_transform, video_title) + video_title = video_title.replace(os.sep, '%') # simplified title - simple_title = re.sub(ur'(?u)([^%s]+)' % simple_title_chars, ur'_', video_title) - simple_title = simple_title.strip(ur'_') + simple_title = re.sub(r'(?u)([^%s]+)' % simple_title_chars, r'_', video_title) + simple_title = simple_title.strip(r'_') # Return information return [{ @@ -737,8 +737,8 @@ def gotPage(result, format_param, video_extension): }] def gotError(error): - print "Unable to process Youtube request: %s" % url - print "Error: %s" % error + print("Unable to process Youtube request: %s" % url) + print("Error: %s" % error) return [None] d = getPage(video_info_url, headers=std_headers) @@ -750,9 +750,9 @@ def gotError(error): class MetacafeIE(InfoExtractor): """Information Extractor for metacafe.com.""" - _VALID_URL = r'(?:http://)?(?:www\.)?metacafe\.com/watch/([^/]+)/([^/]+)/.*' - _DISCLAIMER = 'http://www.metacafe.com/family_filter/' - _FILTER_POST = 'http://www.metacafe.com/f/index.php?inputType=filter&controllerGroup=user' + _VALID_URL = r'(?:https://)?(?:www\.)?metacafe\.com/watch/([^/]+)/([^/]+)/.*' + _DISCLAIMER = 'https://www.metacafe.com/family_filter/' + _FILTER_POST = 'https://www.metacafe.com/f/index.php?inputType=filter&controllerGroup=user' _youtube_ie = None def __init__(self, youtube_ie, downloader=None): @@ -765,28 +765,28 @@ def suitable(url): def report_disclaimer(self): """Report disclaimer retrieval.""" - self._downloader.to_stdout(u'[metacafe] Retrieving disclaimer') + self._downloader.to_stdout('[metacafe] Retrieving disclaimer') def report_age_confirmation(self): """Report attempt to confirm age.""" - self._downloader.to_stdout(u'[metacafe] Confirming age') + self._downloader.to_stdout('[metacafe] Confirming age') def report_download_webpage(self, video_id): """Report webpage download.""" - self._downloader.to_stdout(u'[metacafe] %s: Downloading webpage' % video_id) + self._downloader.to_stdout('[metacafe] %s: Downloading webpage' % video_id) def report_extraction(self, video_id): """Report information extraction.""" - self._downloader.to_stdout(u'[metacafe] %s: Extracting information' % video_id) + self._downloader.to_stdout('[metacafe] %s: Extracting information' % video_id) def _real_initialize(self): # Retrieve disclaimer - request = urllib2.Request(self._DISCLAIMER, None, std_headers) + request = urllib.request.Request(self._DISCLAIMER, None, std_headers) try: self.report_disclaimer() - disclaimer = urllib2.urlopen(request).read() - except (urllib2.URLError, httplib.HTTPException, socket.error), err: - self._downloader.trouble(u'ERROR: unable to retrieve disclaimer: %s' % str(err)) + disclaimer = urllib.request.urlopen(request).read() + except (urllib.error.URLError, http.client.HTTPException, socket.error) as err: + self._downloader.trouble('ERROR: unable to retrieve disclaimer: %s' % str(err)) return # Confirm age @@ -794,19 +794,19 @@ def _real_initialize(self): 'filters': '0', 'submit': "Continue - I'm over 18", } - request = urllib2.Request(self._FILTER_POST, urllib.urlencode(disclaimer_form), std_headers) + request = urllib.request.Request(self._FILTER_POST, urllib.parse.urlencode(disclaimer_form), std_headers) try: self.report_age_confirmation() - disclaimer = urllib2.urlopen(request).read() - except (urllib2.URLError, httplib.HTTPException, socket.error), err: - self._downloader.trouble(u'ERROR: unable to confirm age: %s' % str(err)) + disclaimer = urllib.request.urlopen(request).read() + except (urllib.error.URLError, http.client.HTTPException, socket.error) as err: + self._downloader.trouble('ERROR: unable to confirm age: %s' % str(err)) return def _real_extract(self, url): # Extract id and simplified title from URL mobj = re.match(self._VALID_URL, url) if mobj is None: - self._downloader.trouble(u'ERROR: invalid URL: %s' % url) + self._downloader.trouble('ERROR: invalid URL: %s' % url) return video_id = mobj.group(1) @@ -814,28 +814,28 @@ def _real_extract(self, url): # Check if video comes from YouTube mobj2 = re.match(r'^yt-(.*)$', video_id) if mobj2 is not None: - self._youtube_ie.extract('http://www.youtube.com/watch?v=%s' % mobj2.group(1)) + self._youtube_ie.extract('https://www.youtube.com/watch?v=%s' % mobj2.group(1)) return simple_title = mobj.group(2).decode('utf-8') video_extension = 'flv' # Retrieve video webpage to extract further information - request = urllib2.Request('http://www.metacafe.com/watch/%s/' % video_id) + request = urllib.request.Request('https://www.metacafe.com/watch/%s/' % video_id) try: self.report_download_webpage(video_id) - webpage = urllib2.urlopen(request).read() - except (urllib2.URLError, httplib.HTTPException, socket.error), err: - self._downloader.trouble(u'ERROR: unable retrieve video webpage: %s' % str(err)) + webpage = urllib.request.urlopen(request).read() + except (urllib.error.URLError, http.client.HTTPException, socket.error) as err: + self._downloader.trouble('ERROR: unable retrieve video webpage: %s' % str(err)) return # Extract URL, uploader and title from webpage self.report_extraction(video_id) mobj = re.search(r'(?m)&mediaURL=([^&]+)', webpage) if mobj is None: - self._downloader.trouble(u'ERROR: unable to extract media URL') + self._downloader.trouble('ERROR: unable to extract media URL') return - mediaURL = urllib.unquote(mobj.group(1)) + mediaURL = urllib.parse.unquote(mobj.group(1)) #mobj = re.search(r'(?m)&gdaKey=(.*?)&', webpage) #if mobj is None: # self._downloader.trouble(u'ERROR: unable to extract gdaKey') @@ -848,13 +848,13 @@ def _real_extract(self, url): mobj = re.search(r'(?im)(.*) - Video', webpage) if mobj is None: - self._downloader.trouble(u'ERROR: unable to extract title') + self._downloader.trouble('ERROR: unable to extract title') return video_title = mobj.group(1).decode('utf-8') mobj = re.search(r'(?ms)
  • .*?Submitter:.*?(.*?)<', webpage) if mobj is None: - self._downloader.trouble(u'ERROR: unable to extract uploader nickname') + self._downloader.trouble('ERROR: unable to extract uploader nickname') return video_uploader = mobj.group(1) @@ -869,13 +869,13 @@ def _real_extract(self, url): 'ext': video_extension.decode('utf-8'), }) except UnavailableFormatError: - self._downloader.trouble(u'ERROR: format not available for video') + self._downloader.trouble('ERROR: format not available for video') class YoutubeSearchIE(InfoExtractor): """Information Extractor for YouTube search queries.""" _VALID_QUERY = r'ytsearch(\d+|all)?:[\s\S]+' - _TEMPLATE_URL = 'http://www.youtube.com/results?search_query=%s&page=%s&gl=US&hl=en' + _TEMPLATE_URL = 'https://www.youtube.com/results?search_query=%s&page=%s&gl=US&hl=en' _VIDEO_INDICATOR = r'href="/watch\?v=.+?"' _MORE_PAGES_INDICATOR = r'(?m)>\s*Next\s*' _youtube_ie = None @@ -891,7 +891,7 @@ def suitable(url): def report_download_page(self, query, pagenum): """Report attempt to download playlist page with given number.""" - self._downloader.to_stdout(u'[youtube] query "%s": Downloading page %s' % (query, pagenum)) + self._downloader.to_stdout('[youtube] query "%s": Downloading page %s' % (query, pagenum)) def _real_initialize(self): self._youtube_ie.initialize() @@ -899,7 +899,7 @@ def _real_initialize(self): def _real_extract(self, query): mobj = re.match(self._VALID_QUERY, query) if mobj is None: - self._downloader.trouble(u'ERROR: invalid search query "%s"' % query) + self._downloader.trouble('ERROR: invalid search query "%s"' % query) return prefix, query = query.split(':') @@ -912,12 +912,12 @@ def _real_extract(self, query): return else: try: - n = long(prefix) + n = int(prefix) if n <= 0: - self._downloader.trouble(u'ERROR: invalid download number %s for query "%s"' % (n, query)) + self._downloader.trouble('ERROR: invalid download number %s for query "%s"' % (n, query)) return elif n > self._max_youtube_results: - self._downloader.to_stderr(u'WARNING: ytsearch returns max %i results (you requested %i)' % (self._max_youtube_results, n)) + self._downloader.to_stderr('WARNING: ytsearch returns max %i results (you requested %i)' % (self._max_youtube_results, n)) n = self._max_youtube_results self._download_n_results(query, n) return @@ -934,12 +934,12 @@ def _download_n_results(self, query, n): while True: self.report_download_page(query, pagenum) - result_url = self._TEMPLATE_URL % (urllib.quote_plus(query), pagenum) - request = urllib2.Request(result_url, None, std_headers) + result_url = self._TEMPLATE_URL % (urllib.parse.quote_plus(query), pagenum) + request = urllib.request.Request(result_url, None, std_headers) try: - page = urllib2.urlopen(request).read() - except (urllib2.URLError, httplib.HTTPException, socket.error), err: - self._downloader.trouble(u'ERROR: unable to download webpage: %s' % str(err)) + page = urllib.request.urlopen(request).read() + except (urllib.error.URLError, http.client.HTTPException, socket.error) as err: + self._downloader.trouble('ERROR: unable to download webpage: %s' % str(err)) return # Extract video identifiers @@ -951,12 +951,12 @@ def _download_n_results(self, query, n): if len(video_ids) == n: # Specified n videos reached for id in video_ids: - self._youtube_ie.extract('http://www.youtube.com/watch?v=%s' % id) + self._youtube_ie.extract('https://www.youtube.com/watch?v=%s' % id) return if re.search(self._MORE_PAGES_INDICATOR, page) is None: for id in video_ids: - self._youtube_ie.extract('http://www.youtube.com/watch?v=%s' % id) + self._youtube_ie.extract('https://www.youtube.com/watch?v=%s' % id) return pagenum = pagenum + 1 @@ -965,8 +965,8 @@ def _download_n_results(self, query, n): class YoutubePlaylistIE(InfoExtractor): """Information Extractor for YouTube playlists.""" - _VALID_URL = r'(?:http://)?(?:\w+\.)?youtube.com/(?:view_play_list|my_playlists)\?.*?p=([^&]+).*' - _TEMPLATE_URL = 'http://www.youtube.com/view_play_list?p=%s&page=%s&gl=US&hl=en' + _VALID_URL = r'(?:https://)?(?:\w+\.)?youtube.com/(?:view_play_list|my_playlists)\?.*?p=([^&]+).*' + _TEMPLATE_URL = 'https://www.youtube.com/view_play_list?p=%s&page=%s&gl=US&hl=en' _VIDEO_INDICATOR = r'/watch\?v=(.+?)&' _MORE_PAGES_INDICATOR = r'/view_play_list?p=%s&page=%s' _youtube_ie = None @@ -981,7 +981,7 @@ def suitable(url): def report_download_page(self, playlist_id, pagenum): """Report attempt to download playlist page with given number.""" - self.to_stdout(u'[youtube] PL %s: Downloading page #%s' % (playlist_id, pagenum)) + self.to_stdout('[youtube] PL %s: Downloading page #%s' % (playlist_id, pagenum)) def _real_initialize(self): self._youtube_ie.initialize() @@ -990,7 +990,7 @@ def _real_extract(self, url): # Extract playlist id mobj = re.match(self._VALID_URL, url) if mobj is None: - self._downloader.trouble(u'ERROR: invalid url: %s' % url) + self._downloader.trouble('ERROR: invalid url: %s' % url) return # Download playlist pages @@ -1000,11 +1000,11 @@ def _real_extract(self, url): while True: self.report_download_page(playlist_id, pagenum) - request = urllib2.Request(self._TEMPLATE_URL % (playlist_id, pagenum), None, std_headers) + request = urllib.request.Request(self._TEMPLATE_URL % (playlist_id, pagenum), None, std_headers) try: - page = urllib2.urlopen(request).read() - except (urllib2.URLError, httplib.HTTPException, socket.error), err: - self._downloader.trouble(u'ERROR: unable to download webpage: %s' % str(err)) + page = urllib.request.urlopen(request).read() + except (urllib.error.URLError, http.client.HTTPException, socket.error) as err: + self._downloader.trouble('ERROR: unable to download webpage: %s' % str(err)) return # Extract video identifiers @@ -1019,7 +1019,7 @@ def _real_extract(self, url): pagenum = pagenum + 1 for id in video_ids: - self._youtube_ie.extract('http://www.youtube.com/watch?v=%s' % id) + self._youtube_ie.extract('https://www.youtube.com/watch?v=%s' % id) return @@ -1048,11 +1048,11 @@ def __init__(self, downloader=None): def to_stdout(self, message): """Print message to stdout if downloader is not in quiet mode.""" if self._downloader is None or not self._downloader.get_params().get('quiet', False): - print message + print(message) def to_stderr(self, message): """Print message to stderr.""" - print >> sys.stderr, message + print(message, file=sys.stderr) def set_downloader(self, downloader): """Sets the downloader for this PP.""" @@ -1086,8 +1086,8 @@ def run(self, information): import optparse # General configuration - urllib2.install_opener(urllib2.build_opener(urllib2.ProxyHandler())) - urllib2.install_opener(urllib2.build_opener(urllib2.HTTPCookieProcessor())) + urllib.request.install_opener(urllib.request.build_opener(urllib.request.ProxyHandler())) + urllib.request.install_opener(urllib.request.build_opener(urllib.request.HTTPCookieProcessor())) socket.setdefaulttimeout(300) # 5 minutes should be enough (famous last words) # Parse command line @@ -1161,26 +1161,26 @@ def run(self, information): batchurls = [x.strip() for x in batchurls] batchurls = [x for x in batchurls if len(x) > 0] except IOError: - sys.exit(u'ERROR: batch file could not be read') + sys.exit('ERROR: batch file could not be read') all_urls = batchurls + args # Conflicting, missing and erroneous options if len(all_urls) < 1: - parser.error(u'you must provide at least one URL') + parser.error('you must provide at least one URL') if opts.usenetrc and (opts.username is not None or opts.password is not None): - parser.error(u'using .netrc conflicts with giving username/password') + parser.error('using .netrc conflicts with giving username/password') if opts.password is not None and opts.username is None: - parser.error(u'account username missing') + parser.error('account username missing') if opts.outtmpl is not None and (opts.useliteral or opts.usetitle): - parser.error(u'using output template conflicts with using title or literal title') + parser.error('using output template conflicts with using title or literal title') if opts.usetitle and opts.useliteral: - parser.error(u'using title conflicts with using literal title') + parser.error('using title conflicts with using literal title') if opts.username is not None and opts.password is None: - opts.password = getpass.getpass(u'Type account password and press return:') + opts.password = getpass.getpass('Type account password and press return:') if opts.ratelimit is not None: numeric_limit = FileDownloader.parse_bytes(opts.ratelimit) if numeric_limit is None: - parser.error(u'invalid rate limit specified') + parser.error('invalid rate limit specified') opts.ratelimit = numeric_limit # Information extractors @@ -1200,9 +1200,9 @@ def run(self, information): 'simulate': (opts.simulate or opts.geturl or opts.gettitle), 'format': opts.format, 'outtmpl': ((opts.outtmpl is not None and opts.outtmpl.decode(preferredencoding())) - or (opts.usetitle and u'%(stitle)s-%(id)s.%(ext)s') - or (opts.useliteral and u'%(title)s-%(id)s.%(ext)s') - or u'%(id)s.%(ext)s'), + or (opts.usetitle and '%(stitle)s-%(id)s.%(ext)s') + or (opts.useliteral and '%(title)s-%(id)s.%(ext)s') + or '%(id)s.%(ext)s'), 'ignoreerrors': opts.ignoreerrors, 'ratelimit': opts.ratelimit, 'nooverwrites': opts.nooverwrites, @@ -1218,6 +1218,6 @@ def run(self, information): except DownloadError: sys.exit(1) except SameFileError: - sys.exit(u'ERROR: fixed output name but more than one file to download') + sys.exit('ERROR: fixed output name but more than one file to download') except KeyboardInterrupt: - sys.exit(u'\nERROR: Interrupted by user') + sys.exit('\nERROR: Interrupted by user') diff --git a/coherence/json_service.py b/coherence/json_service.py index aba34aaa..cd2c0b90 100644 --- a/coherence/json_service.py +++ b/coherence/json_service.py @@ -72,8 +72,8 @@ def list_devices(self, request): def call_action(self, action, request): kwargs = {} - for entry, value_list in request.args.items(): - kwargs[entry] = unicode(value_list[0]) + for entry, value_list in list(request.args.items()): + kwargs[entry] = str(value_list[0]) def to_json(result): self.warning("to_json") diff --git a/coherence/log.py b/coherence/log.py index 5d3a8c5d..a5708b01 100644 --- a/coherence/log.py +++ b/coherence/log.py @@ -3,15 +3,63 @@ # Copyright 2013, Hartmut Goebel -import sys +import io import logging - import os +import sys +import traceback + +loggers = {} +BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(8) + +# The background is set with 40 plus the number of the color, +# and the foreground with 30 + +# These are the sequences need to get colored output +RESET_SEQ = "\033[0m" +COLOR_SEQ = "\033[1;%dm" +BOLD_SEQ = "\033[1m" + + +def formatter_message(message, use_color=True): + if use_color: + message = message.replace( + "$RESET", RESET_SEQ).replace( + "$BOLD", BOLD_SEQ) + else: + message = message.replace( + "$RESET", "").replace( + "$BOLD", "") + return message + + +COLORS = { + 'WARNING': YELLOW, + 'INFO': WHITE, + 'DEBUG': BLUE, + 'CRITICAL': YELLOW, + 'ERROR': RED +} + + +class ColoredFormatter(logging.Formatter): + def __init__(self, msg, use_color = True): + logging.Formatter.__init__(self, msg) + self.use_color = use_color + def format(self, record): + levelname = record.levelname + if self.use_color and levelname in COLORS: + levelname_color = \ + COLOR_SEQ % (30 + COLORS[levelname]) + levelname + RESET_SEQ + record.levelname = levelname_color + return logging.Formatter.format(self, record) -LOG_FORMAT = ('%(asctime)s %(levelname)s ' - '%(name)s: %(message)s ' - '(%(filename)s:%(lineno)s)') + +# LOG_FORMAT = '%(asctime)s %(levelname)s %(name)s: %(message)s (%(filename)s:%(lineno)s)' +# LOG_FORMAT = ('[%(levelname)-10s] [ %(name)-14s %(lineno)-5d] %(message)s') +LOG_FORMAT = ("[%(levelname)-18s][$BOLD%(name)-15s$RESET] " + "%(message)s ($BOLD%(filename)s$RESET:%(lineno)d)") ENV_VAR_NAME = 'COHEN_DEBUG' @@ -20,95 +68,143 @@ # caller stack frame. # if hasattr(sys, 'frozen'): # support for py2exe - _srcfile = "coherence%slog%s" % (os.sep, __file__[-4:]) + _srcfile = "coherence%slog%s" % (os.sep, __file__[-4:]) elif __file__[-4:].lower() in ['.pyc', '.pyo']: - _srcfile = __file__[:-4] + '.py' + _srcfile = __file__[:-4] + '.py' else: - _srcfile = __file__ + _srcfile = __file__ _srcfile = os.path.normcase(_srcfile) _srcfiles = (_srcfile, logging._srcfile) -class Logger(logging.Logger): - def findCaller(self): - # This is nearly a plain copy of logging.Logger.findCaller - # Since findCaller tests for _srcfile to find the caller, we - # need to test for this file and the loggin module. - # - # :fixme: If each subclass of Loggable calls __init__ properly - # (see Loggable.__getLogger below), we can build a different - # delegation and remove this hak/work-around. - f = logging.currentframe() - # On some versions of IronPython, currentframe() returns None if IronPython isn't run with -X:Frames. - if f is not None: - f = f.f_back - rv = "(unknown file)", 0, "(unknown function)" - while hasattr(f, "f_code"): - co = f.f_code - filename = os.path.normcase(co.co_filename) - if filename in _srcfiles: # # chaanged line - f = f.f_back - continue - rv = (co.co_filename, f.f_lineno, co.co_name) - break - return rv - - -logging.setLoggerClass(Logger) +class ColoredLogger(logging.Logger): + + FORMAT = LOG_FORMAT + COLOR_FORMAT = formatter_message(FORMAT, True) + + def __init__(self, name): + logging.Logger.__init__(self, name, logging.DEBUG) + + color_formatter = ColoredFormatter(self.COLOR_FORMAT) + + console = logging.StreamHandler() + console.setFormatter(color_formatter) + + # print(self.handlers) + if console not in self.handlers: + self.addHandler(console) + # print(self.handlers) + return + + +# class Logger(ColoredLogger): +# + def findCaller(self, stack_info=False, use_color=True): + """ + Find the stack frame of the caller so that we can note the source + file name, line number and function name. + """ + f = logging.currentframe() + # On some versions of IronPython, currentframe() returns None if + # IronPython isn't run with -X:Frames. + if f is not None: + f = f.f_back + rv = "(unknown file)", 0, "(unknown function)", None + while hasattr(f, "f_code"): + co = f.f_code + filename = os.path.normcase(co.co_filename) + if filename in _srcfiles: + f = f.f_back + continue + sinfo = None + if stack_info: + sio = io.StringIO() + sio.write('Stack (most recent call last):\n') + traceback.print_stack(f, file=sio) + sinfo = sio.getvalue() + if sinfo[-1] == '\n': + sinfo = sinfo[:-1] + sio.close() + rv = (co.co_filename, f.f_lineno, co.co_name, sinfo) + break + return rv + + +logging.setLoggerClass(ColoredLogger) class Loggable(object): - """ - Base class for objects that want to be able to log messages with - different level of severity. The levels are, in order from least - to most: log, debug, info, warning, error. + """ + Base class for objects that want to be able to log messages with + different level of severity. The levels are, in order from least + to most: log, debug, info, warning, error. - @cvar logCategory: Implementors can provide a category to log their - messages under. - """ + @cvar logCategory: Implementors can provide a category to log their + messages under. + """ - logCategory = 'default' - _Loggable__logger = None + logCategory = 'default' + _Loggable__logger = None - def __init__(self): - self.__logger = logging.getLogger(self.logCategory) + FORMAT = LOG_FORMAT + COLOR_FORMAT = formatter_message(FORMAT, True) - def log(self, message, *args, **kwargs): - self.__logger.log(message, *args, **kwargs) + def __init__(self): + global loggers + if loggers.get(self.logCategory): + self._logger = loggers.get(self.logCategory) + else: + self._logger = logging.getLogger(self.logCategory) + loggers[self.logCategory] = self._logger + self.debug('Added logger with logCategory: {}'.format( + self.logCategory)) + return - def warning(self, message, *args, **kwargs): - self.__logger.warning(message, *args, **kwargs) + def log(self, message, *args, **kwargs): + self._logger.log(message, *args, **kwargs) - def info(self, message, *args, **kwargs): - self.__logger.info(message, *args, **kwargs) + def warning(self, message, *args, **kwargs): + self._logger.warning(message, *args, **kwargs) - def critical(self, message, *args, **kwargs): - self.__logger.critical(message, *args, **kwargs) + def info(self, message, *args, **kwargs): + self._logger.info(message, *args, **kwargs) - def debug(self, message, *args, **kwargs): - self.__logger.debug(message, *args, **kwargs) + def critical(self, message, *args, **kwargs): + self._logger.critical(message, *args, **kwargs) - def error(self, message, *args, **kwargs): - self.__logger.error(message, *args, **kwargs) + def debug(self, message, *args, **kwargs): + self._logger.debug(message, *args, **kwargs) - def exception(self, message, *args, **kwargs): - self.__logger.exception(message, *args, **kwargs) + def error(self, message, *args, **kwargs): + self._logger.error(message, *args, **kwargs) - fatal = critical - warn = warning - msg = info + def exception(self, message, *args, **kwargs): + self._logger.exception(message, *args, **kwargs) + + fatal = critical + warn = warning + msg = info getLogger = logging.getLogger def init(logfilename=None, loglevel=logging.WARN): - logger = logging.getLogger() - logging.addLevelName(100, 'NONE') - - logging.basicConfig(filename=logfilename, level=loglevel, format=LOG_FORMAT) - - if ENV_VAR_NAME in os.environ: - logger.setLevel(os.environ[ENV_VAR_NAME]) - else: - logger.setLevel(loglevel) + global loggers + if loggers.get('coherence'): + return loggers.get('coherence') + else: + logger = logging.getLogger() + logging.addLevelName(100, 'NONE') + + logging.basicConfig( + filename=logfilename, + level=loglevel, + format=LOG_FORMAT) + + if ENV_VAR_NAME in os.environ: + logger.setLevel(os.environ[ENV_VAR_NAME]) + else: + logger.setLevel(loglevel) + loggers['coherence'] = logger + logger.debug('Added logger with logCategory: {}'.format('coherence')) diff --git a/coherence/transcoder.py b/coherence/transcoder.py index 355dca4c..e42aa991 100644 --- a/coherence/transcoder.py +++ b/coherence/transcoder.py @@ -19,7 +19,7 @@ gobject.threads_init() import os.path -import urllib +import urllib.request, urllib.parse, urllib.error from twisted.web import resource, server from twisted.internet import protocol @@ -204,7 +204,7 @@ def new_preroll(self, appsink): # check caps for streamheader buffer caps = buffer.get_caps() s = caps[0] - if s.has_key("streamheader"): + if "streamheader" in s: self.streamheader = s["streamheader"] self.debug("setting streamheader") for r in self.requests: @@ -221,7 +221,7 @@ def new_buffer(self, appsink): # check caps for streamheader buffers caps = buffer.get_caps() s = caps[0] - if s.has_key("streamheader"): + if "streamheader" in s: self.streamheader = s["streamheader"] self.debug("setting streamheader") for r in self.requests: @@ -281,7 +281,7 @@ def requestFinished(self, result, request): def on_message(self, bus, message): t = message.type - print "on_message", t + print("on_message", t) if t == gst.MESSAGE_ERROR: #err, debug = message.parse_error() #print "Error: %s" % err, debug @@ -303,7 +303,7 @@ class BaseTranscoder(resource.Resource, log.Loggable): def __init__(self, uri, destination=None): self.info('uri %s %r', uri, type(uri)) if uri[:7] not in ['file://', 'http://']: - uri = 'file://' + urllib.quote(uri) # FIXME + uri = 'file://' + urllib.parse.quote(uri) # FIXME self.uri = uri self.destination = destination resource.Resource.__init__(self) @@ -344,7 +344,7 @@ def requestFinished(self, result): def on_message(self, bus, message): t = message.type - print "on_message", t + print("on_message", t) if t == gst.MESSAGE_ERROR: #err, debug = message.parse_error() #print "Error: %s" % err, debug @@ -538,7 +538,7 @@ def __init__(self, caller): self.caller = caller def connectionMade(self): - print "pp connection made" + print("pp connection made") def outReceived(self, data): #print "outReceived with %d bytes!" % len(data) @@ -546,7 +546,7 @@ def outReceived(self, data): def errReceived(self, data): #print "errReceived! with %d bytes!" % len(data) - print "pp (err):", data.strip() + print("pp (err):", data.strip()) def inConnectionLost(self): #print "inConnectionLost! stdin is closed! (we probably did it)" @@ -561,8 +561,8 @@ def errConnectionLost(self): pass def processEnded(self, status_object): - print "processEnded, status %d" % status_object.value.exitCode - print "processEnded quitting" + print("processEnded, status %d" % status_object.value.exitCode) + print("processEnded quitting") self.caller.ended = True self.caller.write_data('') @@ -587,7 +587,7 @@ def write_data(self, data): # .resumeProducing again, so be prepared for a re-entrant call self.request.write(data) if self.request and self.ended: - print "closing" + print("closing") self.request.unregisterProducer() self.request.finish() self.request = None @@ -608,7 +608,7 @@ def pauseProducing(self): pass def stopProducing(self): - print "stopProducing", self.request + print("stopProducing", self.request) self.request.unregisterProducer() self.process.loseConnection() self.request.finish() @@ -628,7 +628,7 @@ def getChildWithDefault(self, path, request): return self def render(self, request): - print "ExternalProcessPipeline render" + print("ExternalProcessPipeline render") try: if self.contentType: request.setHeader('Content-Type', self.contentType) diff --git a/coherence/tube_service.py b/coherence/tube_service.py index 59065a12..80f5f670 100644 --- a/coherence/tube_service.py +++ b/coherence/tube_service.py @@ -8,9 +8,9 @@ """ from lxml import etree -import urllib -import urlparse -from upnp.core import xml_constants +import urllib.request, urllib.parse, urllib.error +import urllib.parse +from .upnp.core import xml_constants import dbus @@ -41,7 +41,7 @@ def __init__(self): def getChildWithDefault(self, path, request): self.info('MiraBeau getChildWithDefault %s, %s, %s %s', request.method, path, request.uri, request.client) - uri = urllib.unquote_plus(path) + uri = urllib.parse.unquote_plus(path) self.info('MiraBeau uri %r', uri) return ReverseProxyUriResource(uri) @@ -90,10 +90,10 @@ def get_action_results(self, result, action, instance): for res in item.res: remote_protocol, remote_network, remote_content_format, _ = res.protocolInfo.split(':') if remote_protocol == 'http-get' and remote_network == '*': - quoted_url = urllib.quote_plus(res.data) - print "modifying", res.data - res.data = urlparse.urlunsplit(('http', self.service.device.external_address, 'mirabeau', quoted_url, "")) - print "--->", res.data + quoted_url = urllib.parse.quote_plus(res.data) + print("modifying", res.data) + res.data = urllib.parse.urlunsplit(('http', self.service.device.external_address, 'mirabeau', quoted_url, "")) + print("--->", res.data) new_res.append(res) changed = True item.res = new_res @@ -126,7 +126,7 @@ def soap__generic(self, *args, **kwargs): del kwargs['soap_methodName'] in_arguments = action.get_in_arguments() - for arg_name, arg in kwargs.iteritems(): + for arg_name, arg in kwargs.items(): if arg_name.find('X_') == 0: continue l = [a for a in in_arguments if arg_name == a.get_name()] diff --git a/coherence/upnp/core/DIDLLite.py b/coherence/upnp/core/DIDLLite.py index 655e705e..feb38fe3 100644 --- a/coherence/upnp/core/DIDLLite.py +++ b/coherence/upnp/core/DIDLLite.py @@ -11,13 +11,14 @@ """ import string -import urllib +import urllib.request, urllib.parse, urllib.error from datetime import datetime from lxml import etree +from functools import cmp_to_key from coherence.upnp.core import utils from coherence import log -import xml_constants +from . import xml_constants def qname(tag, ns=None): @@ -60,11 +61,11 @@ class Resources(list): def __init__(self): super(Resources, self).__init__() - self.sort(cmp=self.p_sort) + self.sort(key=cmp_to_key(self.p_sort)) def append(self, value): list.append(self, value) - self.sort(cmp=self.p_sort) + self.sort(key=cmp_to_key(self.p_sort)) def p_sort(self, x, y): """ we want the following order @@ -132,13 +133,13 @@ def classChooser(mimetype, sub=None): return MusicAlbum return Container else: - if string.find(mimetype, 'image/') == 0: + if mimetype.find('image/') == 0: return Photo - if string.find(mimetype, 'audio/') == 0: + if mimetype.find('audio/') == 0: if sub == 'music': # FIXME: this is stupid return MusicTrack return AudioItem - if string.find(mimetype, 'video/') == 0: + if mimetype.find('video/') == 0: return VideoItem if mimetype == 'application/ogg': if sub == 'music': # FIXME: this is stupid @@ -202,6 +203,8 @@ class Resource(object): """An object representing a resource.""" def __init__(self, data=None, protocol_info=None): + if isinstance(data, bytes): + data = str(data) self.data = data self.protocolInfo = protocol_info self.bitrate = None @@ -348,15 +351,16 @@ def __init__(self, udn, raise AttributeError('missing first Child Id') self.protocolInfo = protocol_info - args = ['sid=' + urllib.quote(sid), - 'cid=' + urllib.quote(str(cid)), - 'fid=' + urllib.quote(str(fid)), - 'fii=' + urllib.quote(str(fii)), - 'sc=' + urllib.quote(''), - 'md=' + urllib.quote(str(0))] + args = ['sid=' + urllib.parse.quote(sid), + 'cid=' + urllib.parse.quote(str(cid)), + 'fid=' + urllib.parse.quote(str(fid)), + 'fii=' + urllib.parse.quote(str(fii)), + 'sc=' + urllib.parse.quote(''), + 'md=' + urllib.parse.quote(str(0))] - self.data = 'dlna-playcontainer://' + urllib.quote(str(udn)) \ - + '?' + '&'.join(args) + self.data = 'dlna-playcontainer://' + \ + urllib.parse.quote(str(udn)) \ + + '?' + '&'.join(args) if self.protocolInfo is None: self.protocolInfo = 'http-get:*:*:*' @@ -758,7 +762,7 @@ class VideoItem(Item): def toElement(self, **kwargs): root = Item.toElement(self, **kwargs) - for attr_name, ns in self.valid_attrs.iteritems(): + for attr_name, ns in self.valid_attrs.items(): value = getattr(self, attr_name, None) if value: self.debug("Setting value {%s}%s=%s", ns, attr_name, value) @@ -771,7 +775,7 @@ def fromElement(self, elt): for child in elt.getchildren(): tag = child.tag val = child.text - if tag in self.valid_attrs.keys(): + if tag in list(self.valid_attrs.keys()): setattr(self, tag, val) @@ -1029,4 +1033,4 @@ def fromString(cls, data): res.append(Resource('7', 'http-get:*:*:*')) for r in res: - print r.data, r.protocolInfo + print(r.data, r.protocolInfo) diff --git a/coherence/upnp/core/action.py b/coherence/upnp/core/action.py index 8c6d5faa..5af41021 100644 --- a/coherence/upnp/core/action.py +++ b/coherence/upnp/core/action.py @@ -87,7 +87,7 @@ def call(self, *args, **kwargs): in_arguments = self.get_in_arguments() self.info("in arguments %s", [a.get_name() for a in in_arguments]) instance_id = 0 - for arg_name, arg in kwargs.iteritems(): + for arg_name, arg in kwargs.items(): l = [a for a in in_arguments if arg_name == a.get_name()] if len(l) > 0: in_arguments.remove(l[0]) @@ -103,7 +103,7 @@ def call(self, *args, **kwargs): action_name = self.name if(hasattr(self.service.device.client, 'overlay_actions') and - self.service.device.client.overlay_actions.has_key(self.name)): + self.name in self.service.device.client.overlay_actions): self.info("we have an overlay method %r for action %r", self.service.device.client.overlay_actions[self.name], self.name) action_name, kwargs = self.service.device.client.overlay_actions[self.name](**kwargs) self.info("changing action to %r %r", action_name, kwargs) @@ -116,8 +116,8 @@ def got_error(failure): return failure if hasattr(self.service.device.client, 'overlay_headers'): - self.info("action call has headers %r", kwargs.has_key('headers')) - if kwargs.has_key('headers'): + self.info("action call has headers %r", 'headers' in kwargs) + if 'headers' in kwargs: kwargs['headers'].update(self.service.device.client.overlay_headers) else: kwargs['headers'] = self.service.device.client.overlay_headers @@ -128,7 +128,7 @@ def got_error(failure): ordered_arguments = OrderedDict() for argument in self.get_in_arguments(): ordered_arguments[argument.name] = kwargs[argument.name] - if kwargs.has_key('headers'): + if 'headers' in kwargs: ordered_arguments['headers'] = kwargs['headers'] d = client.callRemote(action_name, ordered_arguments) @@ -150,15 +150,19 @@ def got_results(self, results, instance_id, name): #elif len(out_arguments) > 1: if len(out_arguments) > 0: - for arg_name, value in results.items(): - state_variable_name = [a.get_state_variable() for a in out_arguments if a.get_name() == arg_name] - self.service.get_state_variable(state_variable_name[0], instance_id).update(value) + for arg_name, value in list(results.items()): + state_variable_name = \ + [a.get_state_variable() for a in out_arguments if + a.get_name() == arg_name] + self.service.get_state_variable( + state_variable_name[0], instance_id).update(value) return results def __repr__(self): - return "Action: %s [%s], (%s args)" % (self.get_name(), self.get_implementation(), - len(self.get_arguments_list())) + return "Action: %s [%s], (%s args)" % \ + (self.get_name(), self.get_implementation(), + len(self.get_arguments_list())) def as_tuples(self): r = [] diff --git a/coherence/upnp/core/device.py b/coherence/upnp/core/device.py index b71cceb1..93eac9cc 100644 --- a/coherence/upnp/core/device.py +++ b/coherence/upnp/core/device.py @@ -7,7 +7,7 @@ import time from lxml import etree -import xml_constants +from . import xml_constants from twisted.internet import defer from coherence.upnp.core.service import Service from coherence.upnp.core import utils @@ -56,17 +56,20 @@ def as_dict(self): return d def remove(self, *args): - self.info("removal of %s %s", self.friendly_name, self.udn) + self.info('removal of {} {}'.format( + self.friendly_name, self.udn)) while len(self.devices) > 0: device = self.devices.pop() - self.debug("try to remove %r", device) + self.debug('try to remove {}'.format(device)) device.remove() while len(self.services) > 0: service = self.services.pop() self.debug("try to remove %r", service) service.remove() if self.client is not None: - louie.send('Coherence.UPnP.Device.remove_client', None, self.udn, self.client) + louie.send( + 'Coherence.UPnP.Device.remove_client', + None, self.udn, self.client) self.client = None #del self @@ -80,12 +83,20 @@ def receiver(self, *args, **kwargs): return self.detection_completed = True if self.parent is not None: - self.info("embedded device %r %r initialized, parent %r", self.friendly_name, self.device_type, self.parent) - louie.send('Coherence.UPnP.Device.detection_completed', None, device=self) + self.info( + 'embedded device {} {} initialized, parent {}'.format( + self.friendly_name, self.device_type, self.parent)) + louie.send( + 'Coherence.UPnP.Device.detection_completed', + None, device=self) if self.parent is not None: - louie.send('Coherence.UPnP.Device.detection_completed', self.parent, device=self) + louie.send( + 'Coherence.UPnP.Device.detection_completed', + self.parent, device=self) else: - louie.send('Coherence.UPnP.Device.detection_completed', self, device=self) + louie.send( + 'Coherence.UPnP.Device.detection_completed', + self, device=self) def service_detection_failed(self, device): self.remove() @@ -118,7 +129,7 @@ def get_service_by_type(self, type): return service def add_service(self, service): - self.debug("add_service %r", service) + self.debug('add_service {}'.format(service)) self.services.append(service) # :fixme: This fails as Service.get_usn() is not implemented. @@ -146,8 +157,10 @@ def get_markup_name(self): try: return self._markup_name except AttributeError: - self._markup_name = u"%s:%s %s" % (self.friendly_device_type, - self.device_type_version, self.friendly_name) + self._markup_name = "%s:%s %s" % \ + (self.friendly_device_type, + self.device_type_version, + self.friendly_name) return self._markup_name def get_device_type_version(self): @@ -161,17 +174,17 @@ def get_client(self): def renew_service_subscriptions(self): """ iterate over device's services and renew subscriptions """ - self.info("renew service subscriptions for %s", self.friendly_name) + self.info('renew service subscriptions for {}'.format(self.friendly_name)) now = time.time() for service in self.services: - self.info("check service %r %r %s %s", service.id, service.get_sid(), - service.get_timeout(), now) + self.info('check service {} {} {} {}'.format(service.id, service.get_sid(), + service.get_timeout(), now)) if service.get_sid() is not None: if service.get_timeout() < now: - self.debug("wow, we lost an event subscription for %s %s, " - "maybe we need to rethink the loop time and " - "timeout calculation?", - self.friendly_name, service.get_id()) + self.debug('wow, we lost an event subscription for {} {}, ' + 'maybe we need to rethink the loop time and ' + 'timeout calculation?'.format( + self.friendly_name, service.get_id())) if service.get_timeout() < now + 30: service.renew_subscription() @@ -188,11 +201,11 @@ def unsubscribe_service_subscriptions(self): return dl def parse_device(self, d): - self.info("parse_device %r", d) - self.device_type = unicode(d.findtext('./{%s}deviceType' % ns)) + self.info('parse_device {}'.format(d)) + self.device_type = d.findtext('./{%s}deviceType' % ns) self.friendly_device_type, self.device_type_version = \ self.device_type.split(':')[-2:] - self.friendly_name = unicode(d.findtext('./{%s}friendlyName' % ns)) + self.friendly_name = d.findtext('./{%s}friendlyName' % ns) self.udn = d.findtext('./{%s}UDN' % ns) self.info("found udn %r %r", self.udn, self.friendly_name) @@ -256,8 +269,8 @@ def parse_device(self, d): icon_list = d.find('./{%s}iconList' % ns) if icon_list is not None: - import urllib2 - url_base = "%s://%s" % urllib2.urlparse.urlparse(self.get_location())[:2] + from urllib.parse import urlparse + url_base = "%s://%s" % urlparse(self.get_location())[:2] for icon in icon_list.findall('./{%s}icon' % ns): try: i = {} @@ -268,11 +281,14 @@ def parse_device(self, d): i['realurl'] = icon.find('./{%s}url' % ns).text i['url'] = self.make_fullyqualified(i['realurl']) self.icons.append(i) - self.debug("adding icon %r for %r", i, self.friendly_name) + self.debug('adding icon {} for {}'.format( + i, self.friendly_name)) except: import traceback self.debug(traceback.format_exc()) - self.warning("device %r seems to have an invalid icon description, ignoring that icon", self.friendly_name) + self.warning( + 'device {} seems to have an invalid icon description, ' + 'ignoring that icon'.format(self.friendly_name)) serviceList = d.find('./{%s}serviceList' % ns) if serviceList is not None: @@ -286,17 +302,22 @@ def parse_device(self, d): """ check if values are somehow reasonable """ if len(scpdUrl) == 0: - self.warning("service has no uri for its description") + self.warning('service has no uri for its description') continue if len(eventSubUrl) == 0: - self.warning("service has no uri for eventing") + self.warning('service has no uri for eventing') continue if len(controlUrl) == 0: - self.warning("service has no uri for controling") + self.warning('service has no uri for controling') continue - self.add_service(Service(serviceType, serviceId, self.get_location(), + try: + self.add_service(Service(serviceType, serviceId, self.get_location(), controlUrl, eventSubUrl, presentationUrl, scpdUrl, self)) + except Exception as e: + self.error( + 'Error on adding service: {} [ERROR: {}]'.format( + service, e)) # now look for all sub devices embedded_devices = d.find('./{%s}deviceList' % ns) @@ -366,7 +387,8 @@ def append(name, attribute): self.debug(traceback.format_exc()) try: - r.append(('Location', (self.get_location(), self.get_location()))) + r.append(('Location', (str(self.get_location()), + str(self.get_location())))) except: pass try: @@ -456,13 +478,19 @@ def __init__(self, infos): self.host = infos['HOST'] self.root_detection_completed = False Device.__init__(self, None) - louie.connect(self.device_detect, 'Coherence.UPnP.Device.detection_completed', self) + louie.connect( + self.device_detect, + 'Coherence.UPnP.Device.detection_completed', + self) # we need to handle root device completion # these events could be ourself or our children. self.parse_description() + self.debug('RootDevice initialized'.format(self.location)) def __repr__(self): - return "rootdevice %r %r %r %r, manifestation %r" % (self.friendly_name, self.udn, self.st, self.host, self.manifestation) + return "rootdevice %r %r %r %r, manifestation %r" % \ + (self.friendly_name, self.udn, self.st, + self.host, self.manifestation) def remove(self, *args): result = Device.remove(self, *args) @@ -557,22 +585,27 @@ def gotPage(x): d = tree.find('./{%s}device' % ns) if d is not None: self.parse_device(d) # root device + self.debug("device parsed succesfully %r", self.location) def gotError(failure, url): self.warning("error getting device description from %r", url) self.info(failure) - - utils.getPage(self.location).addCallbacks(gotPage, gotError, None, None, [self.location], None) + try: + utils.getPage( + self.location).addCallbacks( + gotPage, gotError, None, None, [self.location], None) + except Exception as e: + self.error('Error on parsing device description: {}'.format(e)) def make_fullyqualified(self, url): if url.startswith('http://'): return url - import urlparse + from urllib.parse import urljoin base = self.get_urlbase() if base != None: if base[-1] != '/': base += '/' - r = urlparse.urljoin(base, url) + r = urljoin(base, url) else: - r = urlparse.urljoin(self.get_location(), url) + r = urljoin(self.get_location(), url) return r diff --git a/coherence/upnp/core/event.py b/coherence/upnp/core/event.py index 08820f05..058606ac 100644 --- a/coherence/upnp/core/event.py +++ b/coherence/upnp/core/event.py @@ -6,7 +6,7 @@ from lxml import etree import time -from urlparse import urlsplit +from urllib.parse import urlsplit from twisted.internet import reactor, defer from twisted.web import resource @@ -123,7 +123,7 @@ def render_SUBSCRIBE(self, request): s = self.subscribers[headers['sid']] s['timeout'] = headers['timeout'] s['created'] = time.time() - elif not headers.has_key('callback'): + elif 'callback' not in headers: request.setResponseCode(404) request.setHeader('SERVER', SERVER_ID) request.setHeader('CONTENT-LENGTH', 0) @@ -132,8 +132,8 @@ def render_SUBSCRIBE(self, request): from .uuid import UUID sid = UUID() s = {'sid': str(sid), - 'callback': headers['callback'][1:len(headers['callback']) - 1], - 'seq': 0} + 'callback': headers['callback'][1:len(headers['callback']) - 1], + 'seq': 0} s['timeout'] = headers['timeout'] s['created'] = time.time() self.service.new_subscriber(s) @@ -223,8 +223,12 @@ def dataReceived(self, data): except: pass self.info("response received from the Service Events HTTP server ") + if isinstance(data, bytes): + d = str(data) + else: + d = data #self.debug(data) - cmd, headers = utils.parse_http_response(data) + cmd, headers = utils.parse_http_response(d) self.debug("%r %r", cmd, headers) if int(cmd[1]) != 200: self.warning("response with error code %r received upon our %r request", cmd[1], self.action) @@ -307,7 +311,7 @@ def send_request(p, action): request.append("Content-Length: 0") request.append("") request.append("") - request = '\r\n'.join(request) + request = bytes('\r\n'.join(request), encoding='utf-8') logger.debug("event.subscribe.send_request %r %r", request, p) try: p.transport.writeSomeData(request) @@ -365,7 +369,11 @@ def dataReceived(self, data): self.timeout_checker.cancel() except: pass - cmd, headers = utils.parse_http_response(data) + if isinstance(data, bytes): + d = str(data) + else: + d = data + cmd, headers = utils.parse_http_response(d) self.debug("notification response received %r %r", cmd, headers) try: if int(cmd[1]) != 200: @@ -400,18 +408,18 @@ def send_notification(s, xml): port = 80 def send_request(p, port_item): - request = ['NOTIFY %s HTTP/1.1' % path, - 'HOST: %s:%d' % (host, port), - 'SEQ: %d' % s['seq'], - 'CONTENT-TYPE: text/xml;charset="utf-8"', - 'SID: %s' % s['sid'], - 'NTS: upnp:propchange', - 'NT: upnp:event', - 'Content-Length: %d' % len(xml), - '', + request = [b'NOTIFY %s HTTP/1.1' % path, + b'HOST: %s:%d' % (host, port), + b'SEQ: %d' % s['seq'], + b'CONTENT-TYPE: text/xml;charset="utf-8"', + b'SID: %s' % s['sid'], + b'NTS: upnp:propchange', + b'NT: upnp:event', + b'Content-Length: %d' % len(xml), + b'', xml] - request = '\r\n'.join(request) + request = b'\r\n'.join(request) logger.info("send_notification.send_request to %r %r", s['sid'], s['callback']) logger.debug("request: %r", request) s['seq'] += 1 diff --git a/coherence/upnp/core/msearch.py b/coherence/upnp/core/msearch.py index f7676e84..50db9878 100644 --- a/coherence/upnp/core/msearch.py +++ b/coherence/upnp/core/msearch.py @@ -33,7 +33,11 @@ def __init__(self, ssdp_server, test=False): self.double_discover_loop = task.LoopingCall(self.double_discover) self.double_discover_loop.start(120.0) - def datagramReceived(self, data, (host, port)): + def datagramReceived(self, data, xxx_todo_changeme): + (host, port) = xxx_todo_changeme + if isinstance(data, bytes): + data = data.decode('utf-8') + cmd, headers = utils.parse_http_response(data) self.info('datagramReceived from %s:%d, protocol %s code %s', host, port, cmd[0], cmd[1]) if cmd[0].startswith('HTTP/1.') and cmd[1] == '200': @@ -62,14 +66,14 @@ def double_discover(self): def discover(self): req = ['M-SEARCH * HTTP/1.1', - 'HOST: %s:%d' % (SSDP_ADDR, SSDP_PORT), - 'MAN: "ssdp:discover"', - 'MX: 5', - 'ST: ssdp:all', - '', ''] - req = '\r\n'.join(req) + 'HOST: %s:%d' % (SSDP_ADDR, SSDP_PORT), + 'MAN: "ssdp:discover"', + 'MX: 5', + 'ST: ssdp:all', + '', ''] + req = bytes('\r\n'.join(req), encoding='utf-8') try: self.transport.write(req, (SSDP_ADDR, SSDP_PORT)) - except socket.error, msg: + except socket.error as msg: self.info("failure sending out the discovery message: %r", msg) diff --git a/coherence/upnp/core/service.py b/coherence/upnp/core/service.py index 121f9f4a..38f0aad2 100644 --- a/coherence/upnp/core/service.py +++ b/coherence/upnp/core/service.py @@ -8,7 +8,7 @@ import os import time -import urllib2 +from urllib.parse import urlparse from coherence.upnp.core import action from coherence.upnp.core import event from coherence.upnp.core import variable @@ -69,11 +69,12 @@ def __init__(self, service_type, service_id, location, control_url, self.client = None - parsed = urllib2.urlparse.urlparse(location) + parsed = urlparse(location) self.url_base = "%s://%s" % (parsed[0], parsed[1]) self.parse_actions() - self.info("%s %s %s initialized", self.device.friendly_name, self.service_type, self.id) + self.info('{} {} {} initialized'.format( + self.device.friendly_name, self.service_type, self.id)) def as_tuples(self): r = [] @@ -127,7 +128,7 @@ def append(name, attribute): def as_dict(self): d = {'type': self.service_type} - d['actions'] = [a.as_dict() for a in self._actions.values()] + d['actions'] = [a.as_dict() for a in list(self._actions.values())] return d def __repr__(self): @@ -153,15 +154,15 @@ def remove(self): self.event_connection.teardown() if self.subscription_id != None: self.unsubscribe() - for name, action in self._actions.items(): + for name, action in list(self._actions.items()): self.debug("remove %s %s", name, action) del self._actions[name] del action - for instance, variables in self._variables.items(): - for name, variable in variables.items(): + for instance, variables in list(self._variables.items()): + for name, variable in list(variables.items()): del variables[name] del variable - if variables.has_key(instance): + if instance in variables: del variables[instance] del variables del self @@ -268,7 +269,7 @@ def renew_subscription(self): def process_event(self, event): self.info("process event %r %r", self, event) - for var_name, var_value in event.items(): + for var_name, var_value in list(event.items()): if var_name == 'LastChange': self.info("we have a LastChange event") self.get_state_variable(var_name, 0).update(var_value) @@ -285,7 +286,7 @@ def process_event(self, event): self.info("updated var %r", var) if len(var.attrib) > 1: self.info("Extended StateVariable %s - %r", var.tag, var.attrib) - if var.attrib.has_key('channel') and var.attrib['channel'] != 'Master': + if 'channel' in var.attrib and var.attrib['channel'] != 'Master': # TODO handle attributes that them selves have multiple instances self.info("Skipping update to %s its not for master channel %s", var.tag, var.attrib) pass @@ -293,27 +294,33 @@ def process_event(self, event): if not self.get_state_variables(instance_id): # TODO Create instance ? self.error("%r update failed (not self.get_state_variables(instance_id)) %r", self, instance_id) - elif not self.get_state_variables(instance_id).has_key(tag): + elif tag not in self.get_state_variables(instance_id): # TODO Create instance StateVariable? # SONOS stuff self.error("%r update failed (not self.get_state_variables(instance_id).has_key(tag)) %r", self, tag) else: val = None - if var.attrib.has_key('val'): + if 'val' in var.attrib: val = var.attrib['val'] #self.debug("%r update %r %r %r", self,namespace_uri, tag, var.attrib['val']) self.get_state_variable(tag, instance_id).update(var.attrib['val']) self.debug("updated 'attributed' var %r", var) - louie.send('Coherence.UPnP.DeviceClient.Service.Event.processed', None, self, (var_name, var_value, event.raw)) + louie.send('Coherence.UPnP.DeviceClient.Service.Event.processed', + None, self, (var_name, var_value, event.raw)) else: self.get_state_variable(var_name, 0).update(var_value) - louie.send('Coherence.UPnP.DeviceClient.Service.Event.processed', None, self, (var_name, var_value, event.raw)) + louie.send('Coherence.UPnP.DeviceClient.Service.Event.processed', + None, self, (var_name, var_value, event.raw)) if self.last_time_updated is None: - # The clients (e.g. media_server_client) check for last time to detect whether service detection is complete - # so we need to set it here and now to avoid a potential race condition + # The clients (e.g. media_server_client) check for last time + # to detect whether service detection is complete so we need to + # set it here and now to avoid a potential race condition self.last_time_updated = time.time() - louie.send('Coherence.UPnP.DeviceClient.Service.notified', sender=self.device, service=self) - self.info("send signal Coherence.UPnP.DeviceClient.Service.notified for %r", self) + louie.send('Coherence.UPnP.DeviceClient.Service.notified', + sender=self.device, service=self) + self.info('send signal ' + 'Coherence.UPnP.DeviceClient.Service.notified for ' + '{}'.format(self)) self.last_time_updated = time.time() def parse_actions(self): @@ -323,7 +330,9 @@ def gotPage(x): try: tree = etree.fromstring(self.scpdXML) except Exception as e: - self.warning("Invalid service description received from %r: %r", self.get_scpd_url(), e) + self.warning( + 'Invalid service description received from {}: {}'.format( + self.get_scpd_url(), e)) return ns = UPNP_SERVICE_NS @@ -362,8 +371,11 @@ def gotPage(x): #print 'service parse:', self, self.device self.detection_completed = True - louie.send('Coherence.UPnP.Service.detection_completed', sender=self.device, device=self.device) - self.info("send signal Coherence.UPnP.Service.detection_completed for %r", self) + louie.send('Coherence.UPnP.Service.detection_completed', + sender=self.device, device=self.device) + self.info('send signal ' + 'Coherence.UPnP.Service.detection_completed for' + ' {}'.format(self)) """ if (self.last_time_updated == None): if( self.id.endswith('AVTransport') or @@ -373,8 +385,8 @@ def gotPage(x): """ def gotError(failure, url): - self.warning('error requesting %s', url) - self.info('failure %s', failure) + self.warning('error requesting {}'.format(url)) + self.info('failure {}'.format(failure)) louie.send('Coherence.UPnP.Service.detection_failed', self.device, device=self.device) utils.getPage(self.get_scpd_url()).addCallbacks(gotPage, gotError, None, None, [self.get_scpd_url()], None) @@ -444,12 +456,12 @@ def __init__(self, id, version, backend): self.check_subscribers_loop.start(120.0, now=False) self.check_moderated_loop = None - if moderated_variables.has_key(self.service_type): + if self.service_type in moderated_variables: self.check_moderated_loop = task.LoopingCall(self.check_moderated_variables) self.check_moderated_loop.start(0.5, now=False) def _release(self): - for p in self._pending_notifications.values(): + for p in list(self._pending_notifications.values()): p.disconnect() self._pending_notifications = {} @@ -473,8 +485,8 @@ def rm_notification(self, result, d): def new_subscriber(self, subscriber): notify = [] - for vdict in self._variables.values(): - notify += [v for v in vdict.values() if v.send_events == True] + for vdict in list(self._variables.values()): + notify += [v for v in list(vdict.values()) if v.send_events == True] self.info("new_subscriber %s %s", subscriber, notify) if len(notify) <= 0: @@ -511,7 +523,7 @@ def get_type(self): def create_new_instance(self, instance): self._variables[instance] = {} - for v in self._variables[0].values(): + for v in list(self._variables[0].values()): self._variables[instance][v.name] = variable.StateVariable(v.service, v.name, v.implementation, @@ -539,7 +551,7 @@ def process_value(result): variable.default_value = variable.value if variable.send_events and not variable.moderated and len(self._subscribers) > 0: xml = self.build_single_notification(instance, variable_name, variable.value) - for s in self._subscribers.values(): + for s in list(self._subscribers.values()): d, p = event.send_notification(s, xml) self._pending_notifications[d] = p d.addBoth(self.rm_notification, d) @@ -567,10 +579,10 @@ def build_single_notification(self, instance, variable_name, value): def build_last_change_event(self, instance=0, force=False): got_one = False root = etree.Element('Event', nsmap={None: self.event_metadata}) - for instance, vdict in self._variables.items(): + for instance, vdict in list(self._variables.items()): e = etree.SubElement(root, 'InstanceID') e.attrib['val'] = str(instance) - for variable in vdict.values(): + for variable in list(vdict.values()): if variable.name != 'LastChange' and variable.name[0:11] != 'A_ARG_TYPE_' and not variable.never_evented: if variable.updated or force: s = etree.SubElement(e, variable.name) @@ -617,13 +629,13 @@ def propagate_notification(self, notify): return xml = etree.tostring(root, encoding='utf-8', pretty_print=True) - for s in self._subscribers.values(): + for s in list(self._subscribers.values()): d, p = event.send_notification(s, xml) self._pending_notifications[d] = p d.addBoth(self.rm_notification, d) def check_subscribers(self): - for s in self._subscribers.values(): + for s in list(self._subscribers.values()): timeout = 86400 if s['timeout'].startswith('Second-'): timeout = int(s['timeout'][len('Second-'):]) @@ -639,7 +651,7 @@ def check_moderated_variables(self): notify = [] for v in variables: #print self._variables[0][v].name, self._variables[0][v].updated - for vdict in self._variables.values(): + for vdict in list(self._variables.values()): if vdict[v].updated == True: vdict[v].updated = False notify.append(vdict[v]) @@ -655,7 +667,7 @@ def is_variable_moderated(self, name): return False def simulate_notification(self): - print "simulate_notification for", self.id + self.info("simulate_notification for {}".format(self.id)) self.set_variable(0, 'CurrentConnectionIDs', '0') def get_scpdXML(self): @@ -798,7 +810,7 @@ def init_var_and_actions(self): else: if (hasattr(self, 'implementation') and self.implementation == 'required') or not hasattr(self, 'implementation'): self.warning('%s has a missing callback for %s action %s, service disabled', self.id, implementation, name) - raise LookupError, "missing callback" + raise LookupError("missing callback") new_action = action.Action(self, name, implementation, arguments) self._actions[name] = new_action @@ -885,7 +897,7 @@ def init_var_and_actions(self): self._variables.get(instance)[name].set_allowed_value_range(**variable_range_defaults) self._variables.get(instance)[name].has_vendor_values = True - for v in self._variables.get(0).values(): + for v in list(self._variables.get(0).values()): if isinstance(v.dependant_variable, str): v.dependant_variable = self._variables.get(instance).get(v.dependant_variable) @@ -909,7 +921,7 @@ def build_xml(self): etree.SubElement(e, 'minor').text = '0' e = etree.SubElement(root, 'actionList') - for action in self.service_server._actions.values(): + for action in list(self.service_server._actions.values()): s = etree.SubElement(e, 'action') etree.SubElement(s, 'name').text = action.get_name() al = etree.SubElement(s, 'argumentList') @@ -920,7 +932,7 @@ def build_xml(self): etree.SubElement(a, 'relatedStateVariable').text = argument.get_state_variable() e = etree.SubElement(root, 'serviceStateTable') - for var in self.service_server._variables[0].values(): + for var in list(self.service_server._variables[0].values()): s = etree.SubElement(e, 'stateVariable') if var.send_events: s.attrib['sendEvents'] = 'yes' @@ -935,12 +947,12 @@ def build_xml(self): if var.allowed_value_range is not None and len(var.allowed_value_range) > 0: complete = True - for name, value in var.allowed_value_range.items(): + for name, value in list(var.allowed_value_range.items()): if value is None: complete = False if complete: avl = etree.SubElement(s, 'allowedValueRange') - for name, value in var.allowed_value_range.items(): + for name, value in list(var.allowed_value_range.items()): if value is not None: etree.SubElement(avl, name).text = str(value) @@ -1004,16 +1016,16 @@ def soap__generic(self, *args, **kwargs): self.info("soap__generic %s %s %s", action, __name__, kwargs) del kwargs['soap_methodName'] - if(kwargs.has_key('X_UPnPClient') and + if('X_UPnPClient' in kwargs and kwargs['X_UPnPClient'] == 'XBox'): if(action.name == 'Browse' and - kwargs.has_key('ContainerID')): + 'ContainerID' in kwargs): """ XXX: THIS IS SICK """ kwargs['ObjectID'] = kwargs['ContainerID'] del kwargs['ContainerID'] in_arguments = action.get_in_arguments() - for arg_name, arg in kwargs.iteritems(): + for arg_name, arg in kwargs.items(): if arg_name.find('X_') == 0: continue l = [a for a in in_arguments if arg_name == a.get_name()] diff --git a/coherence/upnp/core/soap_lite.py b/coherence/upnp/core/soap_lite.py index 9d62e0c6..c617237a 100644 --- a/coherence/upnp/core/soap_lite.py +++ b/coherence/upnp/core/soap_lite.py @@ -22,7 +22,7 @@ NS_UPNP_ORG_CONTROL_1_0 = 'urn:schemas-upnp-org:control-1-0' TYPE_MAP = {str: 'string', - unicode: 'string', + bytes: 'bytes', int: 'int', float: 'float', bool: 'boolean'} @@ -93,11 +93,13 @@ def build_soap_call(method, arguments, ns=None, # append the arguments if isinstance(arguments, (dict, OrderedDict)): - for arg_name, arg_val in arguments.iteritems(): + for arg_name, arg_val in arguments.items(): if type(arg_val) in TYPE_MAP: arg_type = TYPE_MAP[type(arg_val)] if arg_type == 'int' or arg_type == 'float': arg_val = str(arg_val) + if arg_type == 'bytes': + arg_val = str(arg_val) if arg_type == 'boolean': arg_val = '1' if arg_val else '0' e = etree.SubElement(re, arg_name) diff --git a/coherence/upnp/core/soap_proxy.py b/coherence/upnp/core/soap_proxy.py index 47493e27..c0353067 100644 --- a/coherence/upnp/core/soap_proxy.py +++ b/coherence/upnp/core/soap_proxy.py @@ -37,14 +37,15 @@ def __init__(self, url, namespace=None, envelope_attrib=None, header=None, soapa def callRemote(self, soapmethod, arguments): soapaction = soapmethod or self.soapaction + url_bytes = bytes(self.url, encoding='utf-8') if '#' not in soapaction: soapaction = '#'.join((self.namespace[1], soapaction)) self.action = soapaction.split('#')[1] self.info("callRemote %r %r %r %r", self.soapaction, soapmethod, self.namespace, self.action) - headers = {'content-type': 'text/xml ;charset="utf-8"', - 'SOAPACTION': '"%s"' % soapaction, } + headers = {b'content-type': b'text/xml ;charset="utf-8"', + b'SOAPACTION': bytes('"%s"' % soapaction, encoding='utf-8'), } if 'headers' in arguments: headers.update(arguments['headers']) del arguments['headers'] @@ -58,7 +59,12 @@ def gotError(error, url): self.warning("error requesting url %r", url) self.debug(error) try: - tree = etree.fromstring(error.value.response) + # TODO: Must deal with error handling + self.error('\t-> callRemote [type: {}]: {} => {}'.format( + type(error.value.__traceback__), + 'error.value.__traceback__', + error.value.__traceback__)) + tree = etree.fromstring(error.value.__traceback__) body = tree.find('{http://schemas.xmlsoap.org/soap/envelope/}Body') return failure.Failure(Exception("%s - %s" % ( body.find('.//{urn:schemas-upnp-org:control-1-0}errorCode').text, @@ -68,16 +74,19 @@ def gotError(error, url): self.debug(traceback.format_exc()) return error - return getPage(self.url, postdata=payload, method="POST", headers=headers).addCallbacks(self._cbGotResult, - gotError, None, None, - [self.url], None) + return getPage( + url_bytes, + postdata=payload, + method=b"POST", + headers=headers).addCallbacks( + self._cbGotResult, gotError, None, None, [url_bytes], None) def _cbGotResult(self, result): page, headers = result def print_c(e): for c in e.getchildren(): - print c, c.tag + print(c, c.tag) print_c(c) self.debug("result: %r", page) diff --git a/coherence/upnp/core/soap_service.py b/coherence/upnp/core/soap_service.py index 5e338fce..5dde941b 100644 --- a/coherence/upnp/core/soap_service.py +++ b/coherence/upnp/core/soap_service.py @@ -95,7 +95,7 @@ def render(self, request): def print_c(e): for c in e.getchildren(): - print c, c.tag + print(c, c.tag) print_c(c) tree = etree.fromstring(data) @@ -133,19 +133,19 @@ def print_c(e): return server.NOT_DONE_YET else: keywords = {'soap_methodName': methodName} - if(headers.has_key('user-agent') and + if('user-agent' in headers and headers['user-agent'].find('Xbox/') == 0): keywords['X_UPnPClient'] = 'XBox' #if(headers.has_key('user-agent') and # headers['user-agent'].startswith("""Mozilla/4.0 (compatible; UPnP/1.0; Windows""")): # keywords['X_UPnPClient'] = 'XBox' - if(headers.has_key('x-av-client-info') and + if('x-av-client-info' in headers and headers['x-av-client-info'].find('"PLAYSTATION3') > 0): keywords['X_UPnPClient'] = 'PLAYSTATION3' - if(headers.has_key('user-agent') and + if('user-agent' in headers and headers['user-agent'].find('Philips-Software-WebClient/4.32') == 0): keywords['X_UPnPClient'] = 'Philips-TV' - for k, v in kwargs.items(): + for k, v in list(kwargs.items()): keywords[str(k)] = v self.info('call %s %s', methodName, keywords) if hasattr(function, "useKeywords"): diff --git a/coherence/upnp/core/ssdp.py b/coherence/upnp/core/ssdp.py index 3968b8f8..70f86079 100644 --- a/coherence/upnp/core/ssdp.py +++ b/coherence/upnp/core/ssdp.py @@ -65,26 +65,30 @@ def shutdown(self): if self.known[st]['MANIFESTATION'] == 'local': self.doByebye(st) - def datagramReceived(self, data, (host, port)): + def datagramReceived(self, data, xxx_todo_changeme): """Handle a received multicast datagram.""" - + (host, port) = xxx_todo_changeme + if isinstance(data, bytes): + data = data.decode('utf-8') try: header, payload = data.split('\r\n\r\n')[:2] - except ValueError, err: - print err - print 'Arggg,', data - import pdb; pdb.set_trace() + except ValueError as err: + print(err) + print('Arggg,', data) + import pdb + pdb.set_trace() lines = header.split('\r\n') - cmd = string.split(lines[0], ' ') - lines = map(lambda x: x.replace(': ', ':', 1), lines[1:]) - lines = filter(lambda x: len(x) > 0, lines) + cmd = lines[0].split(' ') + lines = [x.replace(': ', ':', 1) for x in lines[1:]] + lines = [x for x in lines if len(x) > 0] - headers = [string.split(x, ':', 1) for x in lines] - headers = dict(map(lambda x: (x[0].lower(), x[1]), headers)) + headers = [x.split(':', 1) for x in lines] + headers = dict([(x[0].lower(), x[1]) for x in headers]) - self.msg('SSDP command %s %s - from %s:%d', cmd[0], cmd[1], host, port) - self.debug('with headers: %s', headers) + self.msg('SSDP command {} {} - from {}:{}'.format( + cmd[0], cmd[1], host, port)) + self.debug('with headers: {}'.format(headers)) if cmd[0] == 'M-SEARCH' and cmd[1] == '*': # SSDP discovery self.discoveryRequest(headers, (host, port)) @@ -92,7 +96,7 @@ def datagramReceived(self, data, (host, port)): # SSDP presence self.notifyReceived(headers, (host, port)) else: - self.warning('Unknown SSDP command %s %s', cmd[0], cmd[1]) + self.warning('Unknown SSDP command {} {}'.format(cmd[0], cmd[1])) # make raw data available # send out the signal after we had a chance to register the device @@ -106,53 +110,62 @@ def register(self, manifestation, usn, st, location, """Register a service or device that this SSDP server will respond to.""" - self.info('Registering %s (%s)', st, location) - - self.known[usn] = {} - self.known[usn]['USN'] = usn - self.known[usn]['LOCATION'] = location - self.known[usn]['ST'] = st - self.known[usn]['EXT'] = '' - self.known[usn]['SERVER'] = server - self.known[usn]['CACHE-CONTROL'] = cache_control - - self.known[usn]['MANIFESTATION'] = manifestation - self.known[usn]['SILENT'] = silent - self.known[usn]['HOST'] = host - self.known[usn]['last-seen'] = time.time() + self.info('Registering {} ({})'.format(st, location)) - self.msg(self.known[usn]) - - if manifestation == 'local': - self.doNotify(usn) + try: + self.known[usn] = {} + self.known[usn]['USN'] = usn + self.known[usn]['LOCATION'] = location + self.known[usn]['ST'] = st + self.known[usn]['EXT'] = '' + self.known[usn]['SERVER'] = server + self.known[usn]['CACHE-CONTROL'] = cache_control + + self.known[usn]['MANIFESTATION'] = manifestation + self.known[usn]['SILENT'] = silent + self.known[usn]['HOST'] = host + self.known[usn]['last-seen'] = time.time() + + self.msg(self.known[usn]) + + if manifestation == 'local': + self.doNotify(usn) - if st == 'upnp:rootdevice': - louie.send('Coherence.UPnP.SSDP.new_device', None, device_type=st, infos=self.known[usn]) - #self.callback("new_device", st, self.known[usn]) + if st == 'upnp:rootdevice': + louie.send( + 'Coherence.UPnP.SSDP.new_device', + None, device_type=st, infos=self.known[usn]) + #self.callback("new_device", st, self.known[usn]) + print('\t - ok all') + except Exception as e: + print(('\t -> Error on registering service: {}'.format(manifestation, e))) def unRegister(self, usn): - self.msg("Un-registering %s", usn) + self.msg("Un-registering {}".format(usn)) st = self.known[usn]['ST'] if st == 'upnp:rootdevice': - louie.send('Coherence.UPnP.SSDP.removed_device', None, device_type=st, infos=self.known[usn]) + louie.send( + 'Coherence.UPnP.SSDP.removed_device', + None, device_type=st, infos=self.known[usn]) #self.callback("removed_device", st, self.known[usn]) del self.known[usn] def isKnown(self, usn): - return self.known.has_key(usn) + return usn in self.known - def notifyReceived(self, headers, (host, port)): + def notifyReceived(self, headers, xxx_todo_changeme1): """Process a presence announcement. We just remember the details of the SSDP service announced.""" - - self.info('Notification from (%s,%d) for %s', host, port, headers['nt']) - self.debug('Notification headers: %s', headers) + (host, port) = xxx_todo_changeme1 + self.info('Notification from ({},{}) for {}'.format( + host, port, headers['nt'])) + self.debug('Notification headers: {}'.format(headers)) if headers['nts'] == 'ssdp:alive': try: self.known[headers['usn']]['last-seen'] = time.time() - self.debug('updating last-seen for %r', headers['usn']) + self.debug('updating last-seen for {}'.format(headers['usn'])) except KeyError: self.register('remote', headers['usn'], headers['nt'], headers['location'], headers['server'], headers['cache-control'], host=host) @@ -160,39 +173,45 @@ def notifyReceived(self, headers, (host, port)): if self.isKnown(headers['usn']): self.unRegister(headers['usn']) else: - self.warning('Unknown subtype %s for notification type %s', - headers['nts'], headers['nt']) + self.warning('Unknown subtype {} for notification type {}'.format( + headers['nts'], headers['nt'])) louie.send('Coherence.UPnP.Log', None, 'SSDP', host, 'Notify %s for %s' % (headers['nts'], headers['usn'])) def send_it(self, response, destination, delay, usn): - self.info('send discovery response delayed by %ds for %s to %r', delay, usn, destination) + self.info('send discovery response delayed by ' + '{} for {} to {}'.format(delay, usn, destination)) try: - self.transport.write(response, destination) - except (AttributeError, socket.error), msg: - self.info("failure sending out byebye notification: %r", msg) + self.transport.write( + bytes(str(response), encoding='utf-8'), + bytes(str(destination), encoding='utf-8')) + except (AttributeError, socket.error) as msg: + self.info('failure sending out byebye notification: {}'.format(msg)) - def discoveryRequest(self, headers, (host, port)): + def discoveryRequest(self, headers, xxx_todo_changeme2): """Process a discovery request. The response must be sent to the address specified by (host, port).""" + (host, port) = xxx_todo_changeme2 + self.info('Discovery request from ({},{}) for {}'.format( + host, port, headers['st'])) + self.info('Discovery request for {}'.format(headers['st'])) - self.info('Discovery request from (%s,%d) for %s', host, port, headers['st']) - self.info('Discovery request for %s', headers['st']) - - louie.send('Coherence.UPnP.Log', None, 'SSDP', host, 'M-Search for %s' % headers['st']) + louie.send( + 'Coherence.UPnP.Log', + None, 'SSDP', host, 'M-Search for %s' % headers['st']) # Do we know about this service? - for i in self.known.values(): + for i in list(self.known.values()): if i['MANIFESTATION'] == 'remote': continue if(headers['st'] == 'ssdp:all' and - i['SILENT'] == True): + i['SILENT'] is True): continue if(i['ST'] == headers['st'] or headers['st'] == 'ssdp:all'): response = [] response.append('HTTP/1.1 200 OK') - for k, v in i.items(): + for k, v in list(i.items()): if k == 'USN': usn = v if k not in ('MANIFESTATION', 'SILENT', 'HOST'): @@ -202,21 +221,22 @@ def discoveryRequest(self, headers, (host, port)): response.extend(('', '')) delay = random.randint(0, int(headers['mx'])) - reactor.callLater(delay, self.send_it, - '\r\n'.join(response), (host, port), delay, usn) + reactor.callLater( + delay, self.send_it, b'\r\n'.join(response), + (host, port), delay, usn) def doNotify(self, usn): """Do notification""" - if self.known[usn]['SILENT'] == True: + if self.known[usn]['SILENT'] is True: return - self.info('Sending alive notification for %s', usn) + self.info('Sending alive notification for {}'.format(usn)) - resp = ['NOTIFY * HTTP/1.1', - 'HOST: %s:%d' % (SSDP_ADDR, SSDP_PORT), - 'NTS: ssdp:alive', + resp = [b'NOTIFY * HTTP/1.1', + b'HOST: %s:%s' % (SSDP_ADDR, SSDP_PORT), + b'NTS: ssdp:alive', ] - stcpy = dict(self.known[usn].iteritems()) + stcpy = dict(iter(self.known[usn].items())) stcpy['NT'] = stcpy['ST'] del stcpy['ST'] del stcpy['MANIFESTATION'] @@ -224,41 +244,45 @@ def doNotify(self, usn): del stcpy['HOST'] del stcpy['last-seen'] - resp.extend(map(lambda x: ': '.join(x), stcpy.iteritems())) - resp.extend(('', '')) - self.debug('doNotify content %s', resp) + resp.extend([bytes( + ': '.join(x), encoding='utf-8') for x in iter(stcpy.items())]) + resp.extend((b'', b'')) + self.debug('doNotify content {}'.format(resp)) try: - self.transport.write('\r\n'.join(resp), (SSDP_ADDR, SSDP_PORT)) - self.transport.write('\r\n'.join(resp), (SSDP_ADDR, SSDP_PORT)) - except (AttributeError, socket.error), msg: - self.info("failure sending out alive notification: %r", msg) + self.transport.write(b'\r\n'.join(resp), (SSDP_ADDR, SSDP_PORT)) + self.transport.write(b'\r\n'.join(resp), (SSDP_ADDR, SSDP_PORT)) + except (AttributeError, socket.error) as msg: + self.info('failure sending out alive notification: {}'.format(msg)) def doByebye(self, usn): """Do byebye""" self.info('Sending byebye notification for %s', usn) - resp = ['NOTIFY * HTTP/1.1', - 'HOST: %s:%d' % (SSDP_ADDR, SSDP_PORT), - 'NTS: ssdp:byebye', + resp = [b'NOTIFY * HTTP/1.1', + b'HOST: %s:%s' % (SSDP_ADDR, SSDP_PORT), + b'NTS: ssdp:byebye', ] try: - stcpy = dict(self.known[usn].iteritems()) + stcpy = dict(iter(self.known[usn].items())) stcpy['NT'] = stcpy['ST'] del stcpy['ST'] del stcpy['MANIFESTATION'] del stcpy['SILENT'] del stcpy['HOST'] del stcpy['last-seen'] - resp.extend(map(lambda x: ': '.join(x), stcpy.iteritems())) - resp.extend(('', '')) + resp.extend([bytes( + ': '.join(x), encoding='utf-8') for x in iter(stcpy.items())]) + resp.extend((b'', b'')) self.debug('doByebye content %s', resp) if self.transport: try: - self.transport.write('\r\n'.join(resp), (SSDP_ADDR, SSDP_PORT)) - except (AttributeError, socket.error), msg: - self.info("failure sending out byebye notification: %r", msg) - except KeyError, msg: + self.transport.write( + b'\r\n'.join(resp), (SSDP_ADDR, SSDP_PORT)) + except (AttributeError, socket.error) as msg: + self.info( + "failure sending out byebye notification: %r", msg) + except KeyError as msg: self.debug("error building byebye notification: %r", msg) def resendNotify(self): @@ -278,11 +302,16 @@ def check_valid(self): expiry = int(expiry) now = time.time() last_seen = self.known[usn]['last-seen'] - self.debug("Checking if %r is still valid - last seen %d (+%d), now %d", self.known[usn]['USN'], last_seen, expiry, now) + self.debug('Checking if {} is still valid - last seen ' + '{} (+{}), now {}'.format( + self.known[usn]['USN'], last_seen, expiry, now)) if last_seen + expiry + 30 < now: - self.debug("Expiring: %r", self.known[usn]) + self.debug('Expiring: {}'.format(self.known[usn])) if self.known[usn]['ST'] == 'upnp:rootdevice': - louie.send('Coherence.UPnP.SSDP.removed_device', None, device_type=self.known[usn]['ST'], infos=self.known[usn]) + louie.send( + 'Coherence.UPnP.SSDP.removed_device', + None, device_type=self.known[usn]['ST'], + infos=self.known[usn]) removable.append(usn) while len(removable) > 0: usn = removable.pop(0) diff --git a/coherence/upnp/core/utils.py b/coherence/upnp/core/utils.py index b87e887e..3ab89226 100644 --- a/coherence/upnp/core/utils.py +++ b/coherence/upnp/core/utils.py @@ -3,9 +3,8 @@ # Copyright (C) 2006 Fluendo, S.A. (www.fluendo.com). # Copyright 2006, Frank Scholz -import urlparse -from io import StringIO -from urlparse import urlsplit +from urllib.parse import urlsplit, urlparse +import xml.etree.ElementTree as ET from lxml import etree from coherence import SERVER_ID @@ -15,11 +14,14 @@ from twisted.internet import reactor, defer, abstract from twisted.python import failure +from coherence import log +logger = log.getLogger('utils') + try: from twisted.protocols._c_urlarg import unquote except ImportError: - from urllib import unquote + from urllib.parse import unquote try: import netifaces @@ -29,7 +31,7 @@ def means_true(value): - if isinstance(value, basestring): + if isinstance(value, str): value = value.lower() return value in [True, 1, '1', 'true', 'yes', 'ok'] @@ -47,18 +49,48 @@ def generalise_boolean(value): generalize_boolean = generalise_boolean +def parse_xml(data, encoding="utf-8", dump_invalid_data=False): + + parser = ET.XMLParser() + + # my version of twisted.web returns page_infos as a dictionary in + # the second item of the data list + # :fixme: This must be handled where twisted.web is fetching the data + if isinstance(data, (list, tuple)): + data = data[0] + + try: + data = data.encode(encoding) + except UnicodeDecodeError: + pass + + # Guess from who we're getting this? + data = data.replace(b'\x00', b'') + try: + parser.feed(data) + except Exception as error: + if dump_invalid_data: + print(error, repr(data)) + parser.close() + raise + else: + return ET.ElementTree(parser.close()) + + def parse_http_response(data): """ don't try to get the body, there are reponses without """ + if isinstance(data, bytes): + data = data.decode('utf-8') header = data.split('\r\n\r\n')[0] lines = header.split('\r\n') cmd = lines[0].split(' ') - lines = map(lambda x: x.replace(': ', ':', 1), lines[1:]) - lines = filter(lambda x: len(x) > 0, lines) + lines = [x.replace(': ', ':', 1) for x in lines[1:]] + lines = [x for x in lines if len(x) > 0] headers = [x.split(':', 1) for x in lines] - headers = dict(map(lambda x: (x[0].lower(), x[1]), headers)) + headers = dict([(x[0].lower(), x[1]) for x in headers]) return cmd, headers @@ -141,7 +173,7 @@ def get_host_address(): if l[1] == '00000000': # default route... route.close() return get_ip_address(l[0]) - except IOError, msg: + except IOError as msg: """ fallback to parsing the output of netstat """ from twisted.internet import utils @@ -167,7 +199,7 @@ def fail(f): d.addCallback(result) d.addErrback(fail) return d - except Exception, msg: + except Exception as msg: import traceback traceback.print_exc() @@ -177,15 +209,12 @@ def fail(f): def de_chunk_payload(response): - try: - import cStringIO as StringIO - except ImportError: - import StringIO + import io """ This method takes a chunked HTTP data object and unchunks it.""" - newresponse = StringIO.StringIO() + newresponse = io.StringIO() # chunked encoding consists of a bunch of lines with # a length in hex followed by a data chunk and a CRLF pair. - response = StringIO.StringIO(response) + response = io.StringIO(response) def read_chunk_length(): line = response.readline() @@ -218,7 +247,7 @@ def process(self): self.setHeader('content-type', "text/html") # Resource Identification - url = self.path + url = str(self.path) #remove trailing "/", if ever url = url.rstrip('/') @@ -228,7 +257,7 @@ def process(self): if path == "": self.postpath = [] else: - self.postpath = map(unquote, path[1:].split('/')) + self.postpath = list(map(unquote, path[1:].split('/'))) try: def deferred_rendering(r): @@ -258,13 +287,13 @@ def startFactory(self): #http._logDateTimeStart() -class ProxyClient(proxy.ProxyClient): +class ProxyClient(proxy.ProxyClient, log.Loggable): def __init__(self, command, rest, version, headers, data, father): log.Loggable.__init__(self) #headers["connection"] = "close" self.send_data = 0 - web.ProxyClient.__init__(self, command, rest, version, + proxy.ProxyClient.__init__(self, command, rest, version, headers, data, father) def handleStatus(self, version, code, message): @@ -274,15 +303,15 @@ def handleStatus(self, version, code, message): message = " %s" % (message, ) if version == 'ICY': version = 'HTTP/1.1' - web.ProxyClient.handleStatus(self, version, code, message) + proxy.ProxyClient.handleStatus(self, version, code, message) def handleHeader(self, key, value): if not key.startswith('icy-'): - web.ProxyClient.handleHeader(self, key, value) + proxy.ProxyClient.handleHeader(self, key, value) def handleResponsePart(self, buffer): self.send_data += len(buffer) - web.ProxyClient.handleResponsePart(self, buffer) + proxy.ProxyClient.handleResponsePart(self, buffer) class ProxyClientFactory(proxy.ProxyClientFactory): @@ -345,7 +374,7 @@ def render(self, request): else: request.received_headers['host'] = "%s:%d" % (self.host, self.port) request.content.seek(0, 0) - qs = urlparse.urlparse(request.uri)[4] + qs = urlparse(request.uri)[4] if qs == '': qs = self.qs if qs: @@ -437,12 +466,24 @@ def getPage(url, contextFactory=None, *args, **kwargs): # This function is like twisted.web.client.getPage, except it uses # our HeaderAwareHTTPClientFactory instead of HTTPClientFactory # and sets the user agent. + + url_bytes = url + if not isinstance(url, bytes): + url_bytes = bytes(url, encoding='utf-8') + if args is None: + args = [] + if kwargs is None: + kwargs = {} + if 'headers' in kwargs and 'user-agent' in kwargs['headers']: kwargs['agent'] = kwargs['headers']['user-agent'] elif not 'agent' in kwargs: kwargs['agent'] = "Coherence PageGetter" + logger.info('getPage [url]: {} [type: {}]'.format(url, type(url))) + logger.debug('\t->[args]: {} [type: {}]'.format(args, type(args))) + logger.debug('\t->[kwargs]: {} [type: {}]'.format(kwargs, type(kwargs))) return client._makeGetterFactory( - url, + url_bytes, HeaderAwareHTTPClientFactory, contextFactory=contextFactory, *args, **kwargs).deferred @@ -487,7 +528,7 @@ def render(self, request): # FIXME detect when request is REALLY finished if request is None or request.finished: - print "No request to render!" + logger.info("No request to render!") return '' """You know what you doing.""" @@ -523,7 +564,7 @@ def render(self, request): try: f = self.openForReading() - except IOError, e: + except IOError as e: import errno if e[0] == errno.EACCES: return error.ForbiddenResource().render(request) @@ -548,14 +589,17 @@ def render(self, request): # Are we requesting something beyond the current size of the file? if (start >= self.getFileSize()): # Retry later! - print bytesrange - print "Requesting data beyond current scope -> postpone rendering!" - self.upnp_retry = reactor.callLater(1.0, self.render, request) + logger.info(bytesrange) + logger.info( + "Requesting data beyond current scope -> " + "postpone rendering!") + self.upnp_retry = reactor.callLater( + 1.0, self.render, request) return server.NOT_DONE_YET f.seek(start) if end: - #print ":%s" % end + #print(":%s" % end) end = int(end) else: end = size - 1 diff --git a/coherence/upnp/core/uuid.py b/coherence/upnp/core/uuid.py index de89c661..12ba9b24 100644 --- a/coherence/upnp/core/uuid.py +++ b/coherence/upnp/core/uuid.py @@ -6,15 +6,13 @@ # Copyright 2013, Hartmut Goebel # -from __future__ import absolute_import - -from uuid import uuid4 +import uuid class UUID: def __init__(self): - self.uuid = 'uuid:' + str(uuid4()) + self.uuid = 'uuid:' + str(uuid.uuid4()) def __repr__(self): return self.uuid diff --git a/coherence/upnp/core/variable.py b/coherence/upnp/core/variable.py index 00dbb2a9..3233a0a1 100644 --- a/coherence/upnp/core/variable.py +++ b/coherence/upnp/core/variable.py @@ -5,7 +5,6 @@ # Copyright 2006, Frank Scholz import time -from sets import Set from coherence.upnp.core import utils try: @@ -15,7 +14,7 @@ # from coherence.upnp.core import service except ImportError: - import service + from . import service from coherence import log @@ -62,7 +61,7 @@ def as_tuples(self): r.append(('Evented', 'no')) r.append(('Data Type', self.data_type)) r.append(('Default Value', self.default_value)) - r.append(('Current Value', unicode(self.value))) + r.append(('Current Value', str(self.value))) if(self.allowed_values != None and len(self.allowed_values) > 0): r.append(('Allowed Values', ','.join(self.allowed_values))) return r @@ -116,17 +115,17 @@ def update(self, value): new_value = value else: if self.data_type == 'string': - if isinstance(value, basestring): + if isinstance(value, str): value = value.split(',') if(isinstance(value, tuple) or - isinstance(value, Set)): + isinstance(value, set)): value = list(value) if not isinstance(value, list): value = [value] new_value = [] for v in value: - if type(v) == unicode: - v = v.encode('utf-8') + if type(v) == str: + v = v # .encode('utf-8') else: v = str(v) if len(self.allowed_values): @@ -148,9 +147,7 @@ def update(self, value): new_value = int(value) else: if self.data_type == 'string': - if type(value) == unicode: - value = value.encode('utf-8') - else: + if type(value) != str: value = str(value) if len(self.allowed_values): if self.has_vendor_values == True: diff --git a/coherence/upnp/core/xml_constants.py b/coherence/upnp/core/xml_constants.py index c3aee280..d9f08c7a 100644 --- a/coherence/upnp/core/xml_constants.py +++ b/coherence/upnp/core/xml_constants.py @@ -26,7 +26,5 @@ UPNP_EVENT_NS: 'e', } -for k, v in namespaces.iteritems(): +for k, v in namespaces.items(): etree.register_namespace(v, k) - - diff --git a/coherence/upnp/devices/basics.py b/coherence/upnp/devices/basics.py index 9ab304d0..d52226fb 100644 --- a/coherence/upnp/devices/basics.py +++ b/coherence/upnp/devices/basics.py @@ -28,7 +28,7 @@ def getChildWithDefault(self, path, request): self.info('DeviceHttpRoot %s getChildWithDefault %s %s %s', self.server.device_type, path, request.uri, request.client) self.info(request.getAllHeaders()) - if self.children.has_key(path): + if path in self.children: return self.children[path] if request.uri == '/': return self @@ -187,7 +187,7 @@ def __init__(self, coherence, backend, **kwargs): self.version = int(kwargs.get('version', self.coherence.config.get('version', 2))) try: - self.uuid = kwargs['uuid'] + self.uuid = str(kwargs['uuid']) if not self.uuid.startswith('uuid:'): self.uuid = 'uuid:' + self.uuid except KeyError: @@ -195,7 +195,7 @@ def __init__(self, coherence, backend, **kwargs): self.uuid = UUID() self.backend = None - urlbase = self.coherence.urlbase + urlbase = str(self.coherence.urlbase) if urlbase[-1] != '/': urlbase += '/' self.urlbase = urlbase + str(self.uuid)[5:] @@ -203,7 +203,7 @@ def __init__(self, coherence, backend, **kwargs): kwargs['urlbase'] = self.urlbase self.icons = kwargs.get('iconlist', kwargs.get('icons', [])) if len(self.icons) == 0: - if kwargs.has_key('icon'): + if 'icon' in kwargs: if isinstance(kwargs['icon'], dict): self.icons.append(kwargs['icon']) else: diff --git a/coherence/upnp/devices/control_point.py b/coherence/upnp/devices/control_point.py index 734312b3..9598bb3c 100644 --- a/coherence/upnp/devices/control_point.py +++ b/coherence/upnp/devices/control_point.py @@ -33,7 +33,7 @@ def __init__(self, type, pattern, callback, timeout=0, oneshot=True): def fire(self, device): if callable(self.callback): self.callback(device) - elif isinstance(self.callback, basestring): + elif isinstance(self.callback, str): louie.send(self.callback, None, device=device) self.fired = True @@ -68,6 +68,7 @@ def __init__(self, coherence, auto_client=None): self.coherence.add_web_resource('RPC2', XMLRPC(self)) for device in self.get_devices(): + self.info('ControlPoint [check device]: {}'.format(device)) self.check_device(device) louie.connect(self.check_device, 'Coherence.UPnP.Device.detection_completed', louie.Any) @@ -87,6 +88,7 @@ def auto_client_append(self, device_type): self.check_device(device) def browse(self, device): + self.info('ControlPoint.browse: {}'.format(device)) device = self.coherence.get_device_with_usn(infos['USN']) if not device: return @@ -158,28 +160,29 @@ def propagate(self, event): if event.get_sid() in service.subscribers: try: service.subscribers[event.get_sid()].process_event(event) - except Exception, msg: + except Exception as msg: self.debug(msg) self.debug(traceback.format_exc()) pass def put_resource(self, url, path): def got_result(result): - print result + print(result) def got_error(result): - print "error", result + print("error", result) try: f = open(path) data = f.read() f.close() headers = { - "Content-Type": "application/octet-stream", - "Content-Length": str(len(data)) + b"Content-Type": b"application/octet-stream", + b"Content-Length": bytes(str(len(data)), encoding='utf-8') } - df = client.getPage(url, method="POST", - headers=headers, postdata=data) + df = client.getPage( + url, method=b"POST", + headers=headers, postdata=data) df.addCallback(got_result) df.addErrback(got_error) return df @@ -195,20 +198,20 @@ def __init__(self, control_point): self.allowNone = True def xmlrpc_list_devices(self): - print "list_devices" + print("list_devices") r = [] for device in self.control_point.get_devices(): #print device.get_friendly_name(), device.get_service_type(), device.get_location(), device.get_id() d = {} - d[u'friendly_name'] = device.get_friendly_name() - d[u'device_type'] = device.get_device_type() - d[u'location'] = unicode(device.get_location()) - d[u'id'] = unicode(device.get_id()) + d['friendly_name'] = device.get_friendly_name() + d['device_type'] = device.get_device_type() + d['location'] = str(device.get_location()) + d['id'] = str(device.get_id()) r.append(d) return r def xmlrpc_mute_device(self, device_id): - print "mute" + print("mute") device = self.control_point.get_device_with_id(device_id) if device != None: client = device.get_client() @@ -217,7 +220,7 @@ def xmlrpc_mute_device(self, device_id): return "Error" def xmlrpc_unmute_device(self, device_id): - print "unmute", device_id + print("unmute", device_id) device = self.control_point.get_device_with_id(device_id) if device != None: client = device.get_client() @@ -226,7 +229,7 @@ def xmlrpc_unmute_device(self, device_id): return "Error" def xmlrpc_set_volume(self, device_id, volume): - print "set volume" + print("set volume") device = self.control_point.get_device_with_id(device_id) if device != None: client = device.get_client() @@ -235,7 +238,7 @@ def xmlrpc_set_volume(self, device_id, volume): return "Error" def xmlrpc_play(self, device_id): - print "play" + print("play") device = self.control_point.get_device_with_id(device_id) if device != None: client = device.get_client() @@ -244,7 +247,7 @@ def xmlrpc_play(self, device_id): return "Error" def xmlrpc_pause(self, device_id): - print "pause" + print("pause") device = self.control_point.get_device_with_id(device_id) if device != None: client = device.get_client() @@ -253,7 +256,7 @@ def xmlrpc_pause(self, device_id): return "Error" def xmlrpc_stop(self, device_id): - print "stop" + print("stop") device = self.control_point.get_device_with_id(device_id) if device != None: client = device.get_client() @@ -262,16 +265,16 @@ def xmlrpc_stop(self, device_id): return "Error" def xmlrpc_next(self, device_id): - print "next" + print("next") device = self.control_point.get_device_with_id(device_id) if device != None: client = device.get_client() - client.av_transport.next() + next(client.av_transport) return "Ok" return "Error" def xmlrpc_previous(self, device_id): - print "previous" + print("previous") device = self.control_point.get_device_with_id(device_id) if device != None: client = device.get_client() @@ -280,7 +283,7 @@ def xmlrpc_previous(self, device_id): return "Error" def xmlrpc_set_av_transport_uri(self, device_id, uri): - print "set_av_transport_uri" + print("set_av_transport_uri") device = self.control_point.get_device_with_id(device_id) if device != None: client = device.get_client() @@ -289,7 +292,7 @@ def xmlrpc_set_av_transport_uri(self, device_id, uri): return "Error" def xmlrpc_create_object(self, device_id, container_id, arguments): - print "create_object", arguments + print("create_object", arguments) device = self.control_point.get_device_with_id(device_id) if device != None: client = device.get_client() @@ -298,7 +301,7 @@ def xmlrpc_create_object(self, device_id, container_id, arguments): return "Error" def xmlrpc_import_resource(self, device_id, source_uri, destination_uri): - print "import_resource", source_uri, destination_uri + print("import_resource", source_uri, destination_uri) device = self.control_point.get_device_with_id(device_id) if device != None: client = device.get_client() @@ -307,19 +310,19 @@ def xmlrpc_import_resource(self, device_id, source_uri, destination_uri): return "Error" def xmlrpc_put_resource(self, url, path): - print "put_resource", url, path + print("put_resource", url, path) self.control_point.put_resource(url, path) return "Ok" def xmlrpc_ping(self): - print "ping" + print("ping") return "Ok" def startXMLRPC(control_point, port): from twisted.web import server r = XMLRPC(control_point) - print "XMLRPC-API on port %d ready" % port + print("XMLRPC-API on port %d ready" % port) reactor.listenTCP(port, server.Site(r)) @@ -329,30 +332,30 @@ def startXMLRPC(control_point, port): config['logmode'] = 'warning' config['serverport'] = 30020 - #ctrl = ControlPoint(Coherence(config),auto_client=[]) - #ctrl = ControlPoint(Coherence(config)) + # ctrl = ControlPoint(Coherence(config),auto_client=[]) + # ctrl = ControlPoint(Coherence(config)) def show_devices(): - print "show_devices" + print("show_devices") for d in ctrl.get_devices(): - print d, d.get_id() + print(d, d.get_id()) def the_result(r): - print "result", r, r.get_id() + print("result", r, r.get_id()) def query_devices(): - print "query_devices" + print("query_devices") ctrl.add_query(DeviceQuery('host', '192.168.1.163', the_result)) def query_devices2(): - print "query_devices with timeout" + print("query_devices with timeout") ctrl.add_query(DeviceQuery('host', '192.168.1.163', the_result, timeout=10, oneshot=False)) - #reactor.callLater(2, show_devices) - #reactor.callLater(3, query_devices) - #reactor.callLater(4, query_devices2) - #reactor.callLater(5, ctrl.add_query, DeviceQuery('friendly_name', 'Coherence Test Content', the_result, timeout=10, oneshot=False)) + # reactor.callLater(2, show_devices) + # reactor.callLater(3, query_devices) + # reactor.callLater(4, query_devices2) + # reactor.callLater(5, ctrl.add_query, DeviceQuery('friendly_name', 'Coherence Test Content', the_result, timeout=10, oneshot=False)) reactor.run() diff --git a/coherence/upnp/devices/media_renderer.py b/coherence/upnp/devices/media_renderer.py index 8d9fa991..dd1fe93e 100644 --- a/coherence/upnp/devices/media_renderer.py +++ b/coherence/upnp/devices/media_renderer.py @@ -63,21 +63,21 @@ def init_complete(self, backend): try: self.connection_manager_server = ConnectionManagerServer(self) self._services.append(self.connection_manager_server) - except LookupError, msg: + except LookupError as msg: self.warning('ConnectionManagerServer %s', msg) raise LookupError(msg) try: self.rendering_control_server = RenderingControlServer(self) self._services.append(self.rendering_control_server) - except LookupError, msg: + except LookupError as msg: self.warning('RenderingControlServer %s', msg) raise LookupError(msg) try: self.av_transport_server = AVTransportServer(self) self._services.append(self.av_transport_server) - except LookupError, msg: + except LookupError as msg: self.warning('AVTransportServer %s', msg) raise LookupError(msg) @@ -116,7 +116,7 @@ def init_complete(self, backend): self.web_resource.putChild('AVTransport', self.av_transport_server) for icon in self.icons: - if icon.has_key('url'): + if 'url' in icon: if icon['url'].startswith('file://'): if os.path.exists(icon['url'][7:]): self.web_resource.putChild(os.path.basename(icon['url']), diff --git a/coherence/upnp/devices/media_server.py b/coherence/upnp/devices/media_server.py index 82853b11..e5474681 100644 --- a/coherence/upnp/devices/media_server.py +++ b/coherence/upnp/devices/media_server.py @@ -5,8 +5,8 @@ # Copyright 2006,2007 Frank Scholz import traceback -from StringIO import StringIO -import urllib +from io import StringIO +import urllib.request, urllib.parse, urllib.error import os import re @@ -68,7 +68,7 @@ def getChildWithDefault(self, path, request): request.setHeader('CaptionInfo.sec', caption) return static.Data('', 'text/html') except: - print traceback.format_exc() + print(traceback.format_exc()) request.setResponseCode(404) return static.Data('

    the requested srt file was not found

    ', 'text/html') @@ -158,12 +158,12 @@ def got_stuff_to_transcode(ch): return d return self.import_response(None, path) - if(headers.has_key('user-agent') and + if('user-agent' in headers and (headers['user-agent'].find('Xbox/') == 0 or # XBox headers['user-agent'].startswith("""Mozilla/4.0 (compatible; UPnP/1.0; Windows""")) and # wmp11 path in ['description-1.xml', 'description-2.xml']): self.info('XBox/WMP alert, we need to simulate a Windows Media Connect server') - if self.children.has_key('xbox-description-1.xml'): + if 'xbox-description-1.xml' in self.children: self.msg('returning xbox-description-1.xml') return self.children['xbox-description-1.xml'] @@ -179,7 +179,7 @@ def got_stuff_to_transcode(ch): def constructConfigData(backend): msg = "" msg += "" + backend_type + "" - for key, value in backend.config.items(): + for key, value in list(backend.config.items()): msg += "<" + key + ">" + value + "" msg += "" return msg @@ -195,7 +195,7 @@ def constructConfigData(backend): def convert_elementtree_to_dict (root): active = False - for name, value in root.items(): + for name, value in list(root.items()): if name == 'active': if value in ('yes'): active = True @@ -227,7 +227,7 @@ def convert_elementtree_to_dict (root): msg = "

    Device restarted. Config file not modified

    " # constructConfigData(new_backend) request.setResponseCode(202) return static.Data(msg, 'text/html') # 'text/xml') - except SyntaxError, e: + except SyntaxError as e: request.setResponseCode(400) return static.Data("

    Invalid data posted:
    %s

    " % e, 'text/html') else: @@ -235,7 +235,7 @@ def convert_elementtree_to_dict (root): request.setResponseCode(405) return static.Data("

    This resource does not allow the requested HTTP method

    ", 'text/html') - if self.children.has_key(path): + if path in self.children: return self.children[path] if request.uri == '/': return self @@ -249,10 +249,10 @@ def requestFinished(self, result, id, request): def import_file(self, name, request): self.info("import file, id %s", name) - print "import file, id %s" % name + print("import file, id %s" % name) def got_file(ch): - print "ch", ch + print("ch", ch) if ch is not None: if hasattr(self.store, 'backend_import'): response_code = self.store.backend_import(ch, request.content) @@ -288,7 +288,7 @@ def process_child(self, ch, name, request): if(request.method == 'GET' or request.method == 'HEAD'): headers = request.getAllHeaders() - if headers.has_key('content-length'): + if 'content-length' in headers: self.warning('%s request with content-length %s header - sanitizing', request.method, headers['content-length']) @@ -315,7 +315,7 @@ def process_child(self, ch, name, request): p = ch.get_path() except TypeError: return self.list_content(name, ch, request) - except Exception, msg: + except Exception as msg: self.debug("error accessing items path %r", msg) self.debug(traceback.format_exc()) return self.list_content(name, ch, request) @@ -366,7 +366,7 @@ def build_page(r, page): elif hasattr(c, 'get_path') and c.get_path != None: #path = c.get_path().encode('utf-8').encode('string_escape') path = c.get_path() - if isinstance(path, unicode): + if isinstance(path, str): path = path.encode('ascii', 'xmlcharrefreplace') else: path = path.decode('utf-8').encode('ascii', 'xmlcharrefreplace') @@ -379,7 +379,7 @@ def build_page(r, page): title = c.get_name() self.debug('title is: %s', type(title)) try: - if isinstance(title, unicode): + if isinstance(title, str): title = title.encode('ascii', 'xmlcharrefreplace') else: title = title.decode('utf-8').encode('ascii', 'xmlcharrefreplace') @@ -393,16 +393,16 @@ def build_page(r, page): children = item.get_children() if isinstance(children, defer.Deferred): - print "list_content, we have a Deferred", children + print("list_content, we have a Deferred", children) children.addCallback(build_page, page) - #children.addErrback(....) #FIXME + # children.addErrback(....) #FIXME return children return build_page(children, page) elif hasattr(item, 'mimetype') and item.mimetype.find('image/') == 0: #path = item.get_path().encode('utf-8').encode('string_escape') - path = urllib.quote(item.get_path().encode('utf-8')) + path = urllib.parse.quote(item.get_path().encode('utf-8')) title = item.get_name().decode('utf-8').encode('ascii', 'xmlcharrefreplace') page += """

    %s

    """ % \ (path, title) @@ -484,7 +484,7 @@ def __init__(self, hostname, uuid, urlbase, if os.path.exists(icon_path): i = etree.SubElement(e, 'icon') - for k, v in icon.items(): + for k, v in list(icon.items()): if k == 'url': if v.startswith('file://'): etree.SubElement(i, k).text = '/' + uuid[5:] + '/' + os.path.basename(v) @@ -589,7 +589,7 @@ def init_complete(self, backend): try: self.connection_manager_server = ConnectionManagerServer(self) self._services.append(self.connection_manager_server) - except LookupError, msg: + except LookupError as msg: self.warning('ConnectionManagerServer %s', msg) raise LookupError(msg) @@ -599,7 +599,7 @@ def init_complete(self, backend): transcoding = True self.content_directory_server = ContentDirectoryServer(self, transcoding=transcoding) self._services.append(self.content_directory_server) - except LookupError, msg: + except LookupError as msg: self.warning('ContentDirectoryServer %s', msg) raise LookupError(msg) @@ -607,13 +607,13 @@ def init_complete(self, backend): self.media_receiver_registrar_server = MediaReceiverRegistrarServer(self, backend=FakeMediaReceiverRegistrarBackend()) self._services.append(self.media_receiver_registrar_server) - except LookupError, msg: + except LookupError as msg: self.warning('MediaReceiverRegistrarServer (optional) %s', msg) try: self.scheduled_recording_server = ScheduledRecordingServer(self) self._services.append(self.scheduled_recording_server) - except LookupError, msg: + except LookupError as msg: self.info('ScheduledRecordingServer %s', msg) upnp_init = getattr(self.backend, "upnp_init", None) @@ -656,7 +656,7 @@ def init_complete(self, backend): self.web_resource.putChild('X_MS_MediaReceiverRegistrar', self.media_receiver_registrar_server) for icon in self.icons: - if icon.has_key('url'): + if 'url' in icon: if icon['url'].startswith('file://'): if os.path.exists(icon['url'][7:]): self.web_resource.putChild(os.path.basename(icon['url']), diff --git a/coherence/upnp/devices/media_server_client.py b/coherence/upnp/devices/media_server_client.py index afa6d754..eae0c515 100644 --- a/coherence/upnp/devices/media_server_client.py +++ b/coherence/upnp/devices/media_server_client.py @@ -103,6 +103,6 @@ def print_results(self, results): self.info("results= %s", results) def process_meta(self, results): - for k, v in results.iteritems(): + for k, v in results.items(): dfr = self.content_directory.browse(k, "BrowseMetadata") dfr.addCallback(self.print_results) diff --git a/coherence/upnp/services/clients/content_directory_client.py b/coherence/upnp/services/clients/content_directory_client.py index 81a22541..abb981f0 100644 --- a/coherence/upnp/services/clients/content_directory_client.py +++ b/coherence/upnp/services/clients/content_directory_client.py @@ -155,7 +155,7 @@ def dict2item(self, elements): parentID=elements.get('parentID', None), title=elements.get('title', None), restricted=elements.get('restricted', None)) - for k, v in elements.items(): + for k, v in list(elements.items()): attribute = getattr(item, k, None) if attribute is None: continue diff --git a/coherence/upnp/services/clients/wan_ip_connection_client.py b/coherence/upnp/services/clients/wan_ip_connection_client.py index af674d3b..8815086d 100644 --- a/coherence/upnp/services/clients/wan_ip_connection_client.py +++ b/coherence/upnp/services/clients/wan_ip_connection_client.py @@ -4,6 +4,7 @@ # Copyright 2010, Frank Scholz from twisted.internet import defer +from functools import cmp_to_key class WANIPConnectionClient: @@ -51,8 +52,9 @@ def add_index(r, index): def request_cb(r, last_updated_timestamp, v): if last_updated_timestamp == v.last_time_touched: - mappings = [m[1] for m in r if m[0] == True] - mappings.sort(cmp=lambda x, y: cmp(x['NewPortMappingIndex'], y['NewPortMappingIndex'])) + mappings = [m[1] for m in r if m[0] is True] + mappings.sort(key=lambda x, y: cmp_to_key( + x['NewPortMappingIndex'], y['NewPortMappingIndex'])) return mappings else: #FIXME - we should raise something here, as the mappings have changed during our query diff --git a/coherence/upnp/services/clients/wan_ppp_connection_client.py b/coherence/upnp/services/clients/wan_ppp_connection_client.py index 96f1e86e..716f3759 100644 --- a/coherence/upnp/services/clients/wan_ppp_connection_client.py +++ b/coherence/upnp/services/clients/wan_ppp_connection_client.py @@ -4,6 +4,7 @@ # Copyright 2010, Frank Scholz from twisted.internet import defer +from functools import cmp_to_key class WANPPPConnectionClient: @@ -51,8 +52,9 @@ def add_index(r, index): def request_cb(r, last_updated_timestamp, v): if last_updated_timestamp == v.last_time_touched: - mappings = [m[1] for m in r if m[0] == True] - mappings.sort(cmp=lambda x, y: cmp(x['NewPortMappingIndex'], y['NewPortMappingIndex'])) + mappings = [m[1] for m in r if m[0] is True] + mappings.sort(key=lambda x, y: cmp_to_key( + x['NewPortMappingIndex'], y['NewPortMappingIndex'])) return mappings else: #FIXME - we should raise something here, as the mappings have changed during our query diff --git a/coherence/upnp/services/servers/connection_manager_server.py b/coherence/upnp/services/servers/connection_manager_server.py index 3aa0cc26..200921c6 100644 --- a/coherence/upnp/services/servers/connection_manager_server.py +++ b/coherence/upnp/services/servers/connection_manager_server.py @@ -134,7 +134,7 @@ def remove_lingering_connections(self): now = time.time() - for id, connection in self.connections.items(): + for id, connection in list(self.connections.items()): avt_id = connection['AVTransportID'] rcs_id = connection['RcsID'] avt_active = True @@ -145,7 +145,7 @@ def remove_lingering_connections(self): avt_variables = self.device.av_transport_server.get_variables().get(avt_id) if avt_variables: avt_active = False - for variable in avt_variables.values(): + for variable in list(avt_variables.values()): if variable.last_time_touched + 300 >= now: avt_active = True break @@ -153,7 +153,7 @@ def remove_lingering_connections(self): rcs_variables = self.device.rendering_control_server.get_variables().get(rcs_id) if rcs_variables: rcs_active = False - for variable in rcs_variables.values(): + for variable in list(rcs_variables.values()): if variable.last_time_touched + 300 >= now: rcs_active = True break @@ -187,7 +187,7 @@ def render(self, request): def set_variable(self, instance, variable_name, value, default=False): if(variable_name == 'SourceProtocolInfo' or variable_name == 'SinkProtocolInfo'): - if isinstance(value, basestring) and len(value) > 0: + if isinstance(value, str) and len(value) > 0: value = [v.strip() for v in value.split(',')] without_dlna_tags = [] for v in value: diff --git a/coherence/upnp/services/servers/content_directory_server.py b/coherence/upnp/services/servers/content_directory_server.py index a05934c8..f8ee727c 100644 --- a/coherence/upnp/services/servers/content_directory_server.py +++ b/coherence/upnp/services/servers/content_directory_server.py @@ -144,7 +144,7 @@ def proceed(result): wmc_mapping = getattr(self.backend, "wmc_mapping", None) if kwargs.get('X_UPnPClient', '') == 'XBox': if(wmc_mapping is not None and - wmc_mapping.has_key(ContainerID)): + ContainerID in wmc_mapping): """ fake a Windows Media Connect Server """ root_id = wmc_mapping[ContainerID] @@ -291,7 +291,7 @@ def proceed(result): wmc_mapping = getattr(self.backend, "wmc_mapping", None) if kwargs.get('X_UPnPClient', '') == 'XBox' and \ - wmc_mapping is not None and wmc_mapping.has_key(ObjectID): + wmc_mapping is not None and ObjectID in wmc_mapping: """ fake a Windows Media Connect Server """ root_id = wmc_mapping[ObjectID] diff --git a/coherence/web/ui.py b/coherence/web/ui.py index 34107ca8..d0597e6c 100644 --- a/coherence/web/ui.py +++ b/coherence/web/ui.py @@ -32,7 +32,7 @@ def __init__(self, coherence): class MenuFragment(athena.LiveElement, log.Loggable): logCategory = 'webui_menu_fragment' - jsClass = u'Coherence.Base' + jsClass = 'Coherence.Base' fragmentName = 'coherence-menu' docFactory = loaders.stan( @@ -61,11 +61,11 @@ def going_live(self): def add_tab(self, title, active, id): self.info("add tab %s to the MenuFragment", title) - new_tab = {u'title': unicode(title), - u'active': unicode(active), - u'athenaid': u'athenaid:%d' % id} + new_tab = {'title': str(title), + 'active': str(active), + 'athenaid': 'athenaid:%d' % id} for t in self.tabs: - if t[u'title'] == new_tab[u'title']: + if t['title'] == new_tab['title']: return self.tabs.append(new_tab) self.callRemote('addTab', new_tab) @@ -76,7 +76,7 @@ def remove_me(self, result): class DevicesFragment(athena.LiveElement, log.Loggable): logCategory = 'webui_device_fragment' - jsClass = u'Coherence.Devices' + jsClass = 'Coherence.Devices' fragmentName = 'coherence-devices' docFactory = loaders.stan( @@ -101,8 +101,8 @@ def going_live(self): devices = [] for device in self.coherence.get_devices(): if device is not None: - devices.append({u'name': device.get_markup_name(), - u'usn': unicode(device.get_usn())}) + devices.append({'name': device.get_markup_name(), + 'usn': str(device.get_usn())}) louie.connect(self.add_device, 'Coherence.UPnP.Device.detection_completed', louie.Any) @@ -122,12 +122,12 @@ def add_device(self, device): device.get_friendly_name(), device.get_device_type()) self.callRemote('addDevice', - {u'name': device.get_markup_name(), - u'usn': unicode(device.get_usn())}) + {'name': device.get_markup_name(), + 'usn': str(device.get_usn())}) def remove_device(self, usn): self.info("DevicesFragment remove device %s", usn) - self.callRemote('removeDevice', unicode(usn)) + self.callRemote('removeDevice', str(usn)) def render_devices(self, ctx, data): cl = [] @@ -146,7 +146,7 @@ def render_devices(self, ctx, data): class LoggingFragment(athena.LiveElement, log.Loggable): logCategory = 'webui_logging_fragment' - jsClass = u'Coherence.Logging' + jsClass = 'Coherence.Logging' fragmentName = 'coherence-logging' docFactory = loaders.stan( @@ -179,7 +179,7 @@ class WebUI(athena.LivePage, log.Loggable): """ """ logCategory = 'webui' - jsClass = u'Coherence' + jsClass = 'Coherence' addSlash = True docFactory = loaders.xmlstr("""\ diff --git a/misc/media_server_observer.py b/misc/media_server_observer.py index e8363955..8be3e155 100644 --- a/misc/media_server_observer.py +++ b/misc/media_server_observer.py @@ -16,24 +16,24 @@ # browse callback def process_media_server_browse(result, client): - print "browsing root of", client.device.get_friendly_name() - print "result contains", result['NumberReturned'], - print "out of", result['TotalMatches'], "total matches." + print("browsing root of: {}".format(client.device.get_friendly_name())) + print("result contains: {}".format(result['NumberReturned']), end=' ') + print("out of: {} {}".format(result['TotalMatches'], "total matches.")) elt = DIDLLite.DIDLElement.fromString(result['Result']) for item in elt.getItems(): if item.upnp_class.startswith("object.container"): - print " container", item.title, "(%s)" % item.id, - print "with", item.childCount, "items." + print(" container", item.title, "(%s)" % item.id, end=' ') + print("with", item.childCount, "items.") if item.upnp_class.startswith("object.item"): - print " item", item.title, "(%s)." % item.id + print(" item", item.title, "(%s)." % item.id) # called for each media server found def media_server_found(client, udn): - print "Media Server found:", client.device.get_friendly_name() + print("Media Server found: {}".format(client.device.get_friendly_name())) d = client.content_directory.browse(0, browse_flag='BrowseDirectChildren', @@ -44,7 +44,7 @@ def media_server_found(client, udn): # sadly they sometimes get removed as well :( def media_server_removed(udn): - print "Media Server gone:", udn + print("Media Server gone:", udn) def start(): @@ -55,7 +55,7 @@ def start(): # now we should also try to discover the ones that are already there: for device in control_point.coherence.devices: - print device + print(device) if __name__ == "__main__": reactor.callWhenRunning(start) diff --git a/misc/upnp-tester.py b/misc/upnp-tester.py index 12049de1..b3353b1f 100644 --- a/misc/upnp-tester.py +++ b/misc/upnp-tester.py @@ -20,7 +20,7 @@ # import os -from sets import Set +from functools import cmp_to_key from twisted.internet import stdio from twisted.protocols import basic @@ -32,7 +32,7 @@ from twisted.names import client as namesclient from twisted.names import dns - import StringIO + import io class SMTPClient(smtp.ESMTPClient): @@ -69,10 +69,10 @@ def getMailData(self): fp.close() tar.add_header('Content-Disposition', 'attachment', filename=os.path.basename(self.mail_file)) msg.attach(tar) - return StringIO.StringIO(msg.as_string()) + return io.StringIO(msg.as_string()) def sentMail(self, code, resp, numOk, addresses, log): - print 'Sent', numOk, 'messages' + print('Sent', numOk, 'messages') class SMTPClientFactory(protocol.ClientFactory): @@ -118,7 +118,7 @@ def lineReceived(self, line): def cmd_help(self, args): "help -- show help" - methods = Set([getattr(self, x) for x in dir(self) if x[:4] == "cmd_"]) + methods = set([getattr(self, x) for x in dir(self) if x[:4] == "cmd_"]) self.transport.write("Commands:\n") for method in methods: if hasattr(method, '__doc__'): @@ -162,7 +162,7 @@ def finished(result): dl = defer.DeferredList(l) dl.addCallback(finished) - except Exception, msg: + except Exception as msg: self.transport.write(str("problem creating download directory %s\n" % msg)) def cmd_send(self, args): @@ -179,7 +179,13 @@ def cmd_send(self, args): def got_mx(result): mx_list = result[0] - mx_list.sort(lambda x, y: cmp(x.payload.preference, y.payload.preference)) + # mx_list.sort( + # lambda x, y: cmp( + # x.payload.preference, y.payload.preference)) + mx_list = sorted( + mx_list, + key=lambda x, y: cmp_to_key( + x.payload.preference, y.payload.preference)) if len(mx_list) > 0: import posix import pwd @@ -197,8 +203,7 @@ def cmd_quit(self, args): cmd_exit = cmd_quit def print_prompt(self): - self.transport.write('>>> ') - + self.transport.write(b'>>> ') if __name__ == '__main__': diff --git a/tests/backends/test_ampache_storage.py b/tests/backends/test_ampache_storage.py index a839e44e..89314bcf 100644 --- a/tests/backends/test_ampache_storage.py +++ b/tests/backends/test_ampache_storage.py @@ -86,7 +86,7 @@ def test_song(self): track = ampache_storage.Track(store, song) self.assertEqual(track.get_id(), 'song.3180') self.assertEqual(track.parent_id, 'album.2910') - self.assertEqual(track.duration, '0:03:54') + self.assertEqual(track.duration, '00:03:54') self.assertEqual(track.get_url(), 'http://localhost/play/index.php?oid=123908...') self.assertEqual(track.get_name(), 'Hells Bells') @@ -110,7 +110,7 @@ def test_song_370(self): track = ampache_storage.Track(store, song) self.assertEqual(track.get_id(), 'song.3440') self.assertEqual(track.parent_id, 'album.359') - self.assertEqual(track.duration, '0:10:25') + self.assertEqual(track.duration, '00:10:25') self.assertEqual(track.get_url(), 'http://songserver/ampache/play/index.php?ssid=1e11a4&type=song&oid=3440&uid=4&name=Led%20Zeppelin%20-%20Achilles%20Last%20Stand.mp3') self.assertEqual(track.get_name(), 'Achilles Last Stand') self.assertEqual(track.title, 'Achilles Last Stand') diff --git a/tests/backends/test_fs_storage.py b/tests/backends/test_fs_storage.py index a6cfb0d8..720c10bd 100644 --- a/tests/backends/test_fs_storage.py +++ b/tests/backends/test_fs_storage.py @@ -17,6 +17,7 @@ import coherence.log coherence.log.init() + class TestFSStorageAssumptions(unittest.TestCase): def setUp(self): @@ -80,6 +81,7 @@ def test_Root(self): mediaobject.container2003-07-23T01:18:00+02:00 ''' + class TestFSStorage(unittest.TestCase): def setUp(self): @@ -117,6 +119,6 @@ def test_Content(self): self.assertEqual(content.get_name(), 'my content') self.assertIs(root.get_children(0, 0)[0], content) self.assertEqual(self.storage.get_by_id('1002').get_name(), - 'audio') + 'images') self.assertEqual(self.storage.get_by_id('1005').get_name(), - 'album-1') + 'album-2') diff --git a/tests/rpc_client.py b/tests/rpc_client.py index 4757c839..59db6035 100755 --- a/tests/rpc_client.py +++ b/tests/rpc_client.py @@ -8,7 +8,7 @@ import getopt import sys import string -import xmlrpclib +import xmlrpc.client command = "status" device = '' @@ -21,7 +21,7 @@ try: optlist, args = getopt.getopt(sys.argv[1:], "c:d:i:v:u:", ['command=', 'device=', 'id=', 'volume=', 'uri=']) except getopt.GetoptError: - print "falsche parameter" + print("falsche parameter") sys.exit(1) for option, param in optlist: @@ -46,9 +46,9 @@ continue k, v = p.split('=') arguments[k] = v -#print 'Arguments', arguments +# print('Arguments', arguments) -s = xmlrpclib.Server('http://127.0.0.1:30020/RPC2') +s = xmlrpc.client.Server('http://127.0.0.1:30020/RPC2') if command == "ping": r = s.ping() @@ -95,4 +95,4 @@ if command == "put_resource": r = s.put_resource(arguments['url'], arguments['path']) -print r +print(r) diff --git a/tests/test_dispatching.py b/tests/test_dispatching.py index 3e5dbe33..44b9f0b4 100644 --- a/tests/test_dispatching.py +++ b/tests/test_dispatching.py @@ -44,27 +44,27 @@ def test_simple_emit(self): receiver = self.dispatcher.connect('test', self.target.callback) self.dispatcher.emit('test') - self.assertEquals(self.target.called, 1) + self.assertEqual(self.target.called, 1) self.dispatcher.emit('test') - self.assertEquals(self.target.called, 2) + self.assertEqual(self.target.called, 2) self.dispatcher.disconnect(receiver) self.dispatcher.emit('test') - self.assertEquals(self.target.called, 2) + self.assertEqual(self.target.called, 2) def test_simple_deferred_emit(self): receiver = self.dispatcher.connect('test', self.target.callback) self.dispatcher.deferred_emit('test') - self.assertEquals(self.target.called, 1) + self.assertEqual(self.target.called, 1) self.dispatcher.deferred_emit('test') - self.assertEquals(self.target.called, 2) + self.assertEqual(self.target.called, 2) self.dispatcher.disconnect(receiver) self.dispatcher.deferred_emit('test') - self.assertEquals(self.target.called, 2) + self.assertEqual(self.target.called, 2) def test_simple_save_emit(self): @@ -72,7 +72,7 @@ def call(res): return self.dispatcher.save_emit('test') def test(res, val): - self.assertEquals(self.target.called, val) + self.assertEqual(self.target.called, val) receiver = self.dispatcher.connect('test', self.target.callback) @@ -115,7 +115,7 @@ def test_emit_false_signal(self): def test_emit_without_receivers(self): self.dispatcher.emit('test') - self.assertEquals(self.target.called, 0) + self.assertEqual(self.target.called, 0) def test_emit_with_multiple_receiver(self): rc1 = self.dispatcher.connect('test', self.target.updater, @@ -127,14 +127,14 @@ def test_emit_with_multiple_receiver(self): self.dispatcher.emit('test', self, 'other', key_a='q') # check rc1 - self.assertEquals(self.target.va1, 1) - self.assertEquals(self.target.va1_other, 'q') + self.assertEqual(self.target.va1, 1) + self.assertEqual(self.target.va1_other, 'q') #check rc2 - self.assertEquals(self.target.variable, 'value') - self.assertEquals(self.target.variable_other, 'q') + self.assertEqual(self.target.variable, 'value') + self.assertEqual(self.target.variable_other, 'q') # check rc3 - self.assertEquals(self.target.one, 'other') - self.assertEquals(self.target.one_other, 'q') + self.assertEqual(self.target.one, 'other') + self.assertEqual(self.target.one_other, 'q') # now removing the one in the middel self.dispatcher.disconnect(rc2) @@ -142,20 +142,20 @@ def test_emit_with_multiple_receiver(self): # and try again with other data self.dispatcher.emit('test', self, 'other', key_a='thistime') # check rc1 - self.assertEquals(self.target.va1, 1) - self.assertEquals(self.target.va1_other, 'thistime') + self.assertEqual(self.target.va1, 1) + self.assertEqual(self.target.va1_other, 'thistime') #check rc2 - self.assertEquals(self.target.variable, 'value') - self.assertEquals(self.target.variable_other, 'q') + self.assertEqual(self.target.variable, 'value') + self.assertEqual(self.target.variable_other, 'q') # check rc3 - self.assertEquals(self.target.one, 'other') - self.assertEquals(self.target.one_other, 'thistime') + self.assertEqual(self.target.one, 'other') + self.assertEqual(self.target.one_other, 'thistime') # no keyword self.dispatcher.emit('test', self, 'a') # worked for rc1 and rc3 with the default value - self.assertEquals(self.target.va1_a, 'p') - self.assertEquals(self.target.one_a, 'p') + self.assertEqual(self.target.va1_a, 'p') + self.assertEqual(self.target.one_a, 'p') # but not on rc2 self.assertFalse(hasattr(self.target, 'variable_a')) @@ -174,16 +174,16 @@ def test_emit_multiple_with_failing_in_between(self): 4, variable='called_d') self.dispatcher.emit('test') - self.assertEquals(self.target.called_a, 1) - self.assertEquals(self.target.called_b, 2) - self.assertEquals(self.target.called_c, 0) - self.assertEquals(self.target.called_d, 4) + self.assertEqual(self.target.called_a, 1) + self.assertEqual(self.target.called_b, 2) + self.assertEqual(self.target.called_c, 0) + self.assertEqual(self.target.called_d, 4) self.dispatcher.emit('test') - self.assertEquals(self.target.called_a, 2) - self.assertEquals(self.target.called_b, 4) - self.assertEquals(self.target.called_c, 0) - self.assertEquals(self.target.called_d, 8) + self.assertEqual(self.target.called_a, 2) + self.assertEqual(self.target.called_b, 4) + self.assertEqual(self.target.called_c, 0) + self.assertEqual(self.target.called_d, 8) self.dispatcher.disconnect(rc1) self.dispatcher.disconnect(rc2) @@ -204,84 +204,84 @@ def _callback(self, *args, **kw): def test_simple_calling(self): rec = Receiver('test', self._callback, (), {}) - self.assertEquals(rec.signal, 'test') + self.assertEqual(rec.signal, 'test') rec() - self.assertEquals(self.called, 1) - self.assertEquals(self.args, ()) - self.assertEquals(self.kw, {}) + self.assertEqual(self.called, 1) + self.assertEqual(self.args, ()) + self.assertEqual(self.kw, {}) rec() - self.assertEquals(self.called, 2) - self.assertEquals(self.args, ()) - self.assertEquals(self.kw, {}) + self.assertEqual(self.called, 2) + self.assertEqual(self.args, ()) + self.assertEqual(self.kw, {}) rec() - self.assertEquals(self.called, 3) - self.assertEquals(self.args, ()) - self.assertEquals(self.kw, {}) + self.assertEqual(self.called, 3) + self.assertEqual(self.args, ()) + self.assertEqual(self.kw, {}) def test_calling_with_args(self): rec = Receiver('test', self._callback, (1, 2, 3), {'test': 'a'}) - self.assertEquals(rec.signal, 'test') + self.assertEqual(rec.signal, 'test') rec(0) - self.assertEquals(self.called, 1) - self.assertEquals(self.args, (0, 1, 2, 3)) - self.assertEquals(self.kw, {'test': 'a'}) + self.assertEqual(self.called, 1) + self.assertEqual(self.args, (0, 1, 2, 3)) + self.assertEqual(self.kw, {'test': 'a'}) rec(-1) - self.assertEquals(self.called, 2) - self.assertEquals(self.args, (-1, 1, 2, 3)) - self.assertEquals(self.kw, {'test': 'a'}) + self.assertEqual(self.called, 2) + self.assertEqual(self.args, (-1, 1, 2, 3)) + self.assertEqual(self.kw, {'test': 'a'}) rec(-2) - self.assertEquals(self.called, 3) - self.assertEquals(self.args, (-2, 1, 2, 3)) - self.assertEquals(self.kw, {'test': 'a'}) + self.assertEqual(self.called, 3) + self.assertEqual(self.args, (-2, 1, 2, 3)) + self.assertEqual(self.kw, {'test': 'a'}) def test_calling_with_kw(self): rec = Receiver('test', self._callback, (1, 2, 3), {'test': 'a'}) - self.assertEquals(rec.signal, 'test') + self.assertEqual(rec.signal, 'test') rec(p='q') - self.assertEquals(self.called, 1) - self.assertEquals(self.args, (1, 2, 3)) - self.assertEquals(self.kw, {'test': 'a', 'p': 'q'}) + self.assertEqual(self.called, 1) + self.assertEqual(self.args, (1, 2, 3)) + self.assertEqual(self.kw, {'test': 'a', 'p': 'q'}) rec(other='wise') - self.assertEquals(self.called, 2) - self.assertEquals(self.args, (1, 2, 3)) - self.assertEquals(self.kw, {'test': 'a', 'other': 'wise'}) + self.assertEqual(self.called, 2) + self.assertEqual(self.args, (1, 2, 3)) + self.assertEqual(self.kw, {'test': 'a', 'other': 'wise'}) rec(and_one='more') - self.assertEquals(self.called, 3) - self.assertEquals(self.args, (1, 2, 3)) - self.assertEquals(self.kw, {'test': 'a', 'and_one': 'more'}) + self.assertEqual(self.called, 3) + self.assertEqual(self.args, (1, 2, 3)) + self.assertEqual(self.kw, {'test': 'a', 'and_one': 'more'}) def test_calling_with_clashing_kw(self): rec = Receiver('test', self._callback, (1, 2, 3), {'test': 'a', 'p': 'a'}) - self.assertEquals(rec.signal, 'test') + self.assertEqual(rec.signal, 'test') rec(p='q') - self.assertEquals(self.called, 1) - self.assertEquals(self.args, (1, 2, 3)) - self.assertEquals(self.kw, {'test': 'a', 'p': 'q'}) + self.assertEqual(self.called, 1) + self.assertEqual(self.args, (1, 2, 3)) + self.assertEqual(self.kw, {'test': 'a', 'p': 'q'}) rec(other='wise') - self.assertEquals(self.called, 2) - self.assertEquals(self.args, (1, 2, 3)) - self.assertEquals(self.kw, {'test': 'a', 'other': 'wise', 'p': 'a'}) + self.assertEqual(self.called, 2) + self.assertEqual(self.args, (1, 2, 3)) + self.assertEqual(self.kw, {'test': 'a', 'other': 'wise', 'p': 'a'}) def test_calling_with_clashing_kw_and_args(self): rec = Receiver('test', self._callback, (1, 2, 3), {'test': 'a', 'p': 'a'}) - self.assertEquals(rec.signal, 'test') + self.assertEqual(rec.signal, 'test') # without rec() - self.assertEquals(self.called, 1) - self.assertEquals(self.args, (1, 2, 3)) - self.assertEquals(self.kw, {'test': 'a', 'p': 'a'}) + self.assertEqual(self.called, 1) + self.assertEqual(self.args, (1, 2, 3)) + self.assertEqual(self.kw, {'test': 'a', 'p': 'a'}) rec(1, 2, 7, test='True', o='p') - self.assertEquals(self.called, 2) - self.assertEquals(self.args, (1, 2, 7, 1, 2, 3)) - self.assertEquals(self.kw, {'test': 'True', 'o': 'p', 'p': 'a'}) + self.assertEqual(self.called, 2) + self.assertEqual(self.args, (1, 2, 7, 1, 2, 3)) + self.assertEqual(self.kw, {'test': 'True', 'o': 'p', 'p': 'a'}) def test_repr(self): rec = Receiver('test', 'callback', (0, 1, 2), {}) @@ -425,7 +425,7 @@ def test_custom(self): self.signaler.x = 'Pocahontas' self._check(values=[('x-changed', ('Pocahontas', ), {})], x='Pocahontas', x_get=2, x_set=1) - self.assertEquals(self.signaler.x, 'Pocahontas') + self.assertEqual(self.signaler.x, 'Pocahontas') # settings again to the same value is boring me self.signaler.emitted = [] @@ -433,27 +433,27 @@ def test_custom(self): self.signaler.x_set = 0 self.signaler.x = 'Pocahontas' - self.assertEquals(self.signaler.emitted, []) - self.assertEquals(self.signaler.x, 'Pocahontas') + self.assertEqual(self.signaler.emitted, []) + self.assertEqual(self.signaler.x, 'Pocahontas') def test_custom_square(self): self.signaler.x_square = 10 self._check(values=[('x-square', (100, ), {})], x=100, x_get=2, x_set=1) - self.assertEquals(self.signaler.x, 100) + self.assertEqual(self.signaler.x, 100) def test_custom_square_nearly_the_same(self): self.signaler._x = 10 self.signaler.x_square = 10 self._check(values=[('x-square', (100, ), {})], x=100, x_get=2, x_set=1) - self.assertEquals(self.signaler.x, 100) + self.assertEqual(self.signaler.x, 100) def _check(self, values=[], x=0, x_set=0, x_get=0): - self.assertEquals(self.signaler._x, x) - self.assertEquals(self.signaler.x_set, x_set) - self.assertEquals(self.signaler.x_get, x_get) - self.assertEquals(self.signaler.emitted, values) + self.assertEqual(self.signaler._x, x) + self.assertEqual(self.signaler.x_set, x_set) + self.assertEqual(self.signaler.x_get, x_get) + self.assertEqual(self.signaler.emitted, values) class TestStayInObjectSignaling(unittest.TestCase): @@ -465,10 +465,10 @@ def setUp(self): def test_double_different_values(self): self.foo.simple = 'A' self.bar.simple = 'B' - self.assertEquals(self.foo.simple, 'A') - self.assertEquals(self.bar.simple, 'B') - self.assertEquals(len(self.foo.emitted), 1) - self.assertEquals(len(self.bar.emitted), 1) + self.assertEqual(self.foo.simple, 'A') + self.assertEqual(self.bar.simple, 'B') + self.assertEqual(len(self.foo.emitted), 1) + self.assertEqual(len(self.bar.emitted), 1) - self.assertEquals(self.foo.emitted[0][1][0], 'A') - self.assertEquals(self.bar.emitted[0][1][0], 'B') + self.assertEqual(self.foo.emitted[0][1][0], 'A') + self.assertEqual(self.bar.emitted[0][1][0], 'B') diff --git a/tests/test_transcoder.py b/tests/test_transcoder.py index 0e17b78d..95e8aee7 100644 --- a/tests/test_transcoder.py +++ b/tests/test_transcoder.py @@ -30,7 +30,7 @@ def test_is_really_singleton(self): # FIXME: singleton tests should be outsourced some when old_id = id(self.manager) new_manager = tc.TranscoderManager() - self.assertEquals(old_id, id(new_manager)) + self.assertEqual(old_id, id(new_manager)) class TestTranscoderAutoloading(TranscoderTestMixin, TestCase): @@ -47,7 +47,7 @@ def __init__(self, **kwargs): process_config = {'name': 'megaprocess', 'pipeline': 'uiui%suiui', 'type': 'process', 'target': 'yay'} - bad_name_config = {'name': u'so bäd', 'pipeline': 'fake %s', + bad_name_config = {'name': 'so bäd', 'pipeline': 'fake %s', 'type': 'process', 'target': 'norway'} def setUp(self): @@ -60,7 +60,7 @@ def test_is_loading_all_known_transcoders(self): def _check_for_transcoders(self, transcoders): for klass in transcoders: loaded_transcoder = self.manager.transcoders[tc.get_transcoder_name(klass)] - self.assertEquals(loaded_transcoder, klass) + self.assertEqual(loaded_transcoder, klass) def test_is_loading_no_config(self): coherence = self.CoherenceStump() @@ -78,8 +78,8 @@ def test_is_loading_one_gst_from_config(self): def _check_transcoder_attrs(self, transcoder, pipeline=None, uri=None): # bahh... relying on implementation details of the basetranscoder here - self.assertEquals(transcoder.pipeline_description, pipeline) - self.assertEquals(transcoder.uri, uri) + self.assertEqual(transcoder.pipeline_description, pipeline) + self.assertEqual(transcoder.uri, uri) def test_is_loading_one_process_from_config(self): coherence = self.CoherenceStump(transcoder=self.process_config) @@ -108,7 +108,7 @@ def test_badname_in_config(self): coherence = self.CoherenceStump(transcoder=self.bad_name_config) self.manager = tc.TranscoderManager(coherence) self._check_for_transcoders(known_transcoders) - self.assertRaises(KeyError, self.manager.select, u'so bäd', + self.assertRaises(KeyError, self.manager.select, 'so bäd', 'http://another/uri') def test_is_loading_multiple_from_config(self): @@ -141,5 +141,5 @@ def test_loaded_gst_always_new_instance(self): self.assertTrue(isinstance(transcoder_b, tc.GStreamerTranscoder)) self._check_transcoder_attrs(transcoder_b, pipeline='pp%spppl', uri="http://another/uri") - self.assertNotEquals(transcoder_a, transcoder_b) - self.assertNotEquals(id(transcoder_a), id(transcoder_b)) + self.assertNotEqual(transcoder_a, transcoder_b) + self.assertNotEqual(id(transcoder_a), id(transcoder_b)) diff --git a/tests/upnp/core/test_ServiceServer.py b/tests/upnp/core/test_ServiceServer.py index 3266f89c..43e9170f 100644 --- a/tests/upnp/core/test_ServiceServer.py +++ b/tests/upnp/core/test_ServiceServer.py @@ -147,9 +147,9 @@ def test_build_single_notification(self): self.assertSequenceEqual( srv.build_single_notification(0, 'DummyVariable', 987), # :todo: this tested result heavily depends on how ElementTree handles the namespace. - ('' - '987' - '')) + (b'' + b'987' + b'')) self.assertRaises(TypeError, srv.build_single_notification, 0, 321, 987) def test_build_last_change_event(self): diff --git a/tests/upnp/core/test_action.py b/tests/upnp/core/test_action.py index 8d55b7e2..d9f62f55 100644 --- a/tests/upnp/core/test_action.py +++ b/tests/upnp/core/test_action.py @@ -190,7 +190,7 @@ class TestAction2(unittest.TestCase): def setUp(self): self.arguments = _build_action_arguments() self.service = DummyServiceWithStateVariables('Brightness') - self.action= action.Action(self.service, 'SomeTestAction', + self.action= action.Action(self.service, b'SomeTestAction', NoImplementation, self.arguments) def test_setup(self): @@ -207,7 +207,7 @@ def check_result(*args, **kw): self.assertEqual( self.service.get_state_variable('Brightness').value, 12) - self.assertEqual(client._called_action_name, 'SomeTestAction') + self.assertEqual(client._called_action_name, b'SomeTestAction') self.assertEqual(client._passed_arguments, {'InstanceID': 23, 'Color': 'red'}) diff --git a/tests/upnp/core/test_device.py b/tests/upnp/core/test_device.py index 498a023a..d7226289 100644 --- a/tests/upnp/core/test_device.py +++ b/tests/upnp/core/test_device.py @@ -14,7 +14,7 @@ # :todo: test-cases with embedded devices import os -import urlparse +import urllib.parse import posixpath try: import unittest.mock as mock @@ -73,10 +73,10 @@ def fakeGetPageURL(url): Example: http://1.2.3.4/a/b/c/some.xml -> /some.xml """ - path = urlparse.urlparse(url).path + path = urllib.parse.urlparse(url).path path = posixpath.normpath(path) words = path.split('/') - words = filter(None, words)[-1:] + words = [_f for _f in words if _f][-1:] file = FilePath(os.path.join(FILE_BASE, *words)) d = Deferred() d.callback((file.open().read(), {})) diff --git a/tests/upnp/core/test_msearch.py b/tests/upnp/core/test_msearch.py index cbbe1a45..0b316320 100644 --- a/tests/upnp/core/test_msearch.py +++ b/tests/upnp/core/test_msearch.py @@ -95,4 +95,6 @@ def test_discover(self): data, (host, port) = self.tr.written[0] self.assertEqual((host, port), (SSDP_ADDR, SSDP_PORT)) recieved = data.splitlines(True) - self.assertEqual(sorted(recieved), sorted(expected)) + self.assertEqual( + sorted(recieved), + sorted([bytes(str(i), encoding='utf-8') for i in expected])) diff --git a/tests/upnp/core/test_service.py b/tests/upnp/core/test_service.py index 45c57e73..b095c363 100644 --- a/tests/upnp/core/test_service.py +++ b/tests/upnp/core/test_service.py @@ -365,7 +365,7 @@ def compare_variables(variables_to_test): svc = self.service # there is one instance self.assertEqual(len(svc._variables), 1) - self.assertEqual(svc._variables.keys(), [0]) + self.assertEqual(list(svc._variables.keys()), [0]) compare_variables(svc._variables[0]) #self.assertEqual(svc._var_subscribers, {}) #compare_variables(svc.get_state_variables(0)) diff --git a/tests/upnp/core/test_soap_lite.py b/tests/upnp/core/test_soap_lite.py index 4957bc08..484d3d2a 100644 --- a/tests/upnp/core/test_soap_lite.py +++ b/tests/upnp/core/test_soap_lite.py @@ -5,7 +5,7 @@ import unittest SOAP_CALL_WITH_ARGS = ( - '\n' + '' '' '' diff --git a/tests/upnp/core/test_ssdp.py b/tests/upnp/core/test_ssdp.py index b7747c88..4525bb8e 100644 --- a/tests/upnp/core/test_ssdp.py +++ b/tests/upnp/core/test_ssdp.py @@ -80,7 +80,7 @@ def test_doNotify(self): data = '\r\n'.join(SSDP_NOTIFY_1) + '\r\n\r\n' self.proto.datagramReceived(data, ('10.20.30.40', 1234)) self.assertEqual(self.tr.written, []) - self.proto.doNotify('uuid:e711a4bf::upnp:rootdevice') + self.proto.doNotify(b'uuid:e711a4bf::upnp:rootdevice') expected = [(l + '\r\n') for l in [ 'NOTIFY * HTTP/1.1', 'HOST: 239.255.255.250:1900', @@ -97,15 +97,19 @@ def test_doNotify(self): self.assertEqual(len(self.tr.written), 2) self.assertEqual(self.tr.written[0], self.tr.written[1]) data, (host, port) = self.tr.written[0] - self.assertEqual((host, port), (SSDP_ADDR, SSDP_PORT)) + self.assertEqual( + (host, port), + (bytes(SSDP_ADDR, encoding='utf-8'), bytes(str(SSDP_PORT), encoding='utf-8'))) recieved = data.splitlines(True) - self.assertEqual(sorted(recieved), sorted(expected)) + self.assertEqual( + sorted(recieved), + sorted([bytes(str(i), encoding='utf-8') for i in expected])) def test_doByebye(self): data = '\r\n'.join(SSDP_NOTIFY_1) + '\r\n\r\n' self.proto.datagramReceived(data, ('10.20.30.40', 1234)) self.assertEqual(self.tr.written, []) - self.proto.doByebye('uuid:e711a4bf::upnp:rootdevice') + self.proto.doByebye(b'uuid:e711a4bf::upnp:rootdevice') expected = [(l + '\r\n') for l in [ 'NOTIFY * HTTP/1.1', 'HOST: 239.255.255.250:1900', @@ -120,6 +124,10 @@ def test_doByebye(self): ]] self.assertEqual(len(self.tr.written), 1) data, (host, port) = self.tr.written[0] - self.assertEqual((host, port), (SSDP_ADDR, SSDP_PORT)) + self.assertEqual( + (host, port), + (bytes(SSDP_ADDR, encoding='utf-8'), bytes(str(SSDP_PORT), encoding='utf-8'))) recieved = data.splitlines(True) - self.assertEqual(sorted(recieved), sorted(expected)) + self.assertEqual( + sorted(recieved), + sorted([bytes(str(i), encoding='utf-8') for i in expected])) diff --git a/tests/upnp/core/test_utils.py b/tests/upnp/core/test_utils.py index 8e9684a9..348c6f52 100644 --- a/tests/upnp/core/test_utils.py +++ b/tests/upnp/core/test_utils.py @@ -140,7 +140,7 @@ def _listen(self, site): def setUp(self): name = self.mktemp() os.mkdir(name) - FilePath(name).child("file").setContent("0123456789") + FilePath(name).child("file").setContent(b"0123456789") r = static.File(name) self.site = server.Site(r, timeout=None) self.wrapper = policies.WrappingFactory(self.site) @@ -162,10 +162,10 @@ def assertResponse(self, original, content, headers): self.assertEqual(originalHeaders[header], headers[header]) def test_getPage(self): - content = '0123456789' - headers = {'accept-ranges': ['bytes'], - 'content-length': ['10'], - 'content-type': ['text/html']} + content = b'0123456789' + headers = {b'accept-ranges': [b'bytes'], + b'content-length': [b'10'], + b'content-type': [b'text/html']} d = utils.getPage(self.getURL("file")) d.addCallback(self.assertResponse, content, headers) return d