Automatically convert source code from Python 2 to 3 using futurize
This commit is contained in:
parent
e0a27bdb4e
commit
436b1fda83
85 changed files with 297 additions and 160 deletions
|
@ -1,8 +1,10 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
###############################################################################
|
###############################################################################
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
from future import standard_library
|
||||||
|
standard_library.install_aliases()
|
||||||
from sys import listitem
|
from sys import listitem
|
||||||
from urllib import urlencode
|
from urllib.parse import urlencode
|
||||||
|
|
||||||
from xbmc import getCondVisibility, sleep
|
from xbmc import getCondVisibility, sleep
|
||||||
from xbmcgui import Window
|
from xbmcgui import Window
|
||||||
|
|
|
@ -2,9 +2,12 @@
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
from future import standard_library
|
||||||
|
standard_library.install_aliases()
|
||||||
|
from builtins import object
|
||||||
import logging
|
import logging
|
||||||
from sys import argv
|
from sys import argv
|
||||||
from urlparse import parse_qsl
|
from urllib.parse import parse_qsl
|
||||||
|
|
||||||
import xbmc
|
import xbmc
|
||||||
import xbmcgui
|
import xbmcgui
|
||||||
|
@ -23,7 +26,7 @@ LOG = logging.getLogger('PLEX.default')
|
||||||
HANDLE = int(argv[1])
|
HANDLE = int(argv[1])
|
||||||
|
|
||||||
|
|
||||||
class Main():
|
class Main(object):
|
||||||
# MAIN ENTRY POINT
|
# MAIN ENTRY POINT
|
||||||
# @utils.profiling()
|
# @utils.profiling()
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -33,7 +36,7 @@ class Main():
|
||||||
arguments = unicode_paths.decode(argv[2])
|
arguments = unicode_paths.decode(argv[2])
|
||||||
path = unicode_paths.decode(argv[0])
|
path = unicode_paths.decode(argv[0])
|
||||||
# Ensure unicode
|
# Ensure unicode
|
||||||
for key, value in params.iteritems():
|
for key, value in params.items():
|
||||||
params[key.decode('utf-8')] = params.pop(key)
|
params[key.decode('utf-8')] = params.pop(key)
|
||||||
params[key] = value.decode('utf-8')
|
params[key] = value.decode('utf-8')
|
||||||
mode = params.get('mode', '')
|
mode = params.get('mode', '')
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
from builtins import object
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
|
|
||||||
from .. import utils
|
from .. import utils
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
from future import standard_library
|
||||||
|
standard_library.install_aliases()
|
||||||
|
from builtins import object
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
import Queue
|
import queue
|
||||||
from threading import Lock, RLock
|
from threading import Lock, RLock
|
||||||
|
|
||||||
import xbmc
|
import xbmc
|
||||||
|
@ -38,9 +41,9 @@ class App(object):
|
||||||
self.lock_playlists = Lock()
|
self.lock_playlists = Lock()
|
||||||
|
|
||||||
# Plex Companion Queue()
|
# Plex Companion Queue()
|
||||||
self.companion_queue = Queue.Queue(maxsize=100)
|
self.companion_queue = queue.Queue(maxsize=100)
|
||||||
# Websocket_client queue to communicate with librarysync
|
# Websocket_client queue to communicate with librarysync
|
||||||
self.websocket_queue = Queue.Queue()
|
self.websocket_queue = queue.Queue()
|
||||||
# xbmc.Monitor() instance from kodimonitor.py
|
# xbmc.Monitor() instance from kodimonitor.py
|
||||||
self.monitor = None
|
self.monitor = None
|
||||||
# xbmc.Player() instance
|
# xbmc.Player() instance
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
from builtins import object
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
|
|
||||||
from .. import utils, json_rpc as js, variables as v
|
from .. import utils, json_rpc as js, variables as v
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
|
||||||
|
from builtins import object
|
||||||
from .. import utils
|
from .. import utils
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
|
||||||
|
|
||||||
|
from builtins import object
|
||||||
class PlayState(object):
|
class PlayState(object):
|
||||||
# "empty" dict for the PLAYER_STATES above. Use copy.deepcopy to duplicate!
|
# "empty" dict for the PLAYER_STATES above. Use copy.deepcopy to duplicate!
|
||||||
template = {
|
template = {
|
||||||
|
|
|
@ -1,10 +1,15 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
from future import standard_library
|
||||||
|
standard_library.install_aliases()
|
||||||
|
from builtins import str
|
||||||
|
from builtins import range
|
||||||
|
from builtins import object
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
from time import time as _time
|
from time import time as _time
|
||||||
import threading
|
import threading
|
||||||
import Queue
|
import queue
|
||||||
import heapq
|
import heapq
|
||||||
from collections import deque
|
from collections import deque
|
||||||
|
|
||||||
|
@ -113,7 +118,7 @@ class KillableThread(threading.Thread):
|
||||||
self._suspension_reached.set()
|
self._suspension_reached.set()
|
||||||
|
|
||||||
|
|
||||||
class ProcessingQueue(Queue.Queue, object):
|
class ProcessingQueue(queue.Queue, object):
|
||||||
"""
|
"""
|
||||||
Queue of queues that processes a queue completely before moving on to the
|
Queue of queues that processes a queue completely before moving on to the
|
||||||
next queue. There's one queue per Section(). You need to initialize each
|
next queue. There's one queue per Section(). You need to initialize each
|
||||||
|
@ -148,7 +153,7 @@ class ProcessingQueue(Queue.Queue, object):
|
||||||
if self.maxsize > 0:
|
if self.maxsize > 0:
|
||||||
if not block:
|
if not block:
|
||||||
if self._total_qsize() == self.maxsize:
|
if self._total_qsize() == self.maxsize:
|
||||||
raise Queue.Full
|
raise queue.Full
|
||||||
elif timeout is None:
|
elif timeout is None:
|
||||||
while self._total_qsize() == self.maxsize:
|
while self._total_qsize() == self.maxsize:
|
||||||
self.not_full.wait()
|
self.not_full.wait()
|
||||||
|
@ -159,7 +164,7 @@ class ProcessingQueue(Queue.Queue, object):
|
||||||
while self._total_qsize() == self.maxsize:
|
while self._total_qsize() == self.maxsize:
|
||||||
remaining = endtime - _time()
|
remaining = endtime - _time()
|
||||||
if remaining <= 0.0:
|
if remaining <= 0.0:
|
||||||
raise Queue.Full
|
raise queue.Full
|
||||||
self.not_full.wait(remaining)
|
self.not_full.wait(remaining)
|
||||||
self._put(item)
|
self._put(item)
|
||||||
self.unfinished_tasks += 1
|
self.unfinished_tasks += 1
|
||||||
|
@ -212,7 +217,7 @@ class ProcessingQueue(Queue.Queue, object):
|
||||||
self._sections.append(section)
|
self._sections.append(section)
|
||||||
self._queues.append(
|
self._queues.append(
|
||||||
OrderedQueue() if section.plex_type == v.PLEX_TYPE_ALBUM
|
OrderedQueue() if section.plex_type == v.PLEX_TYPE_ALBUM
|
||||||
else Queue.Queue())
|
else queue.Queue())
|
||||||
if self._current_section is None:
|
if self._current_section is None:
|
||||||
self._activate_next_section()
|
self._activate_next_section()
|
||||||
|
|
||||||
|
@ -237,7 +242,7 @@ class ProcessingQueue(Queue.Queue, object):
|
||||||
return item[1]
|
return item[1]
|
||||||
|
|
||||||
|
|
||||||
class OrderedQueue(Queue.PriorityQueue, object):
|
class OrderedQueue(queue.PriorityQueue, object):
|
||||||
"""
|
"""
|
||||||
Queue that enforces an order on the items it returns. An item you push
|
Queue that enforces an order on the items it returns. An item you push
|
||||||
onto the queue must be a tuple
|
onto the queue must be a tuple
|
||||||
|
@ -328,7 +333,7 @@ class FunctionAsTask(Task):
|
||||||
self._callback(result)
|
self._callback(result)
|
||||||
|
|
||||||
|
|
||||||
class MutablePriorityQueue(Queue.PriorityQueue):
|
class MutablePriorityQueue(queue.PriorityQueue):
|
||||||
def _get(self, heappop=heapq.heappop):
|
def _get(self, heappop=heapq.heappop):
|
||||||
self.queue.sort()
|
self.queue.sort()
|
||||||
return heappop(self.queue)
|
return heappop(self.queue)
|
||||||
|
@ -388,7 +393,7 @@ class BackgroundWorker(object):
|
||||||
self._runTask(self._task)
|
self._runTask(self._task)
|
||||||
self._queue.task_done()
|
self._queue.task_done()
|
||||||
self._task = None
|
self._task = None
|
||||||
except Queue.Empty:
|
except queue.Empty:
|
||||||
LOG.debug('(%s): Idle', self.name)
|
LOG.debug('(%s): Idle', self.name)
|
||||||
|
|
||||||
def shutdown(self, block=True):
|
def shutdown(self, block=True):
|
||||||
|
@ -428,7 +433,7 @@ class NonstoppingBackgroundWorker(BackgroundWorker):
|
||||||
return self._working
|
return self._working
|
||||||
|
|
||||||
|
|
||||||
class BackgroundThreader:
|
class BackgroundThreader(object):
|
||||||
def __init__(self, name=None, worker=BackgroundWorker, worker_count=6):
|
def __init__(self, name=None, worker=BackgroundWorker, worker_count=6):
|
||||||
self.name = name
|
self.name = name
|
||||||
self._queue = MutablePriorityQueue()
|
self._queue = MutablePriorityQueue()
|
||||||
|
@ -508,7 +513,7 @@ class BackgroundThreader:
|
||||||
qitem.priority = lowest - 1
|
qitem.priority = lowest - 1
|
||||||
|
|
||||||
|
|
||||||
class ThreaderManager:
|
class ThreaderManager(object):
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
worker=NonstoppingBackgroundWorker,
|
worker=NonstoppingBackgroundWorker,
|
||||||
worker_count=WORKER_COUNT):
|
worker_count=WORKER_COUNT):
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
from builtins import str
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
|
|
||||||
import xbmc
|
import xbmc
|
||||||
|
|
|
@ -28,7 +28,7 @@ def skip_to(params):
|
||||||
LOG.debug('Skipping to playQueueItemID %s, plex_id %s',
|
LOG.debug('Skipping to playQueueItemID %s, plex_id %s',
|
||||||
playqueue_item_id, plex_id)
|
playqueue_item_id, plex_id)
|
||||||
found = True
|
found = True
|
||||||
for player in js.get_players().values():
|
for player in list(js.get_players().values()):
|
||||||
playqueue = PQ.PLAYQUEUES[player['playerid']]
|
playqueue = PQ.PLAYQUEUES[player['playerid']]
|
||||||
for i, item in enumerate(playqueue.items):
|
for i, item in enumerate(playqueue.items):
|
||||||
if item.id == playqueue_item_id:
|
if item.id == playqueue_item_id:
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
from builtins import object
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
import xbmc
|
import xbmc
|
||||||
import xbmcgui
|
import xbmcgui
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
from builtins import object
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
import requests
|
import requests
|
||||||
import requests.exceptions as exceptions
|
import requests.exceptions as exceptions
|
||||||
|
@ -18,7 +19,7 @@ LOG = getLogger('PLEX.download')
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
|
|
||||||
class DownloadUtils():
|
class DownloadUtils(object):
|
||||||
"""
|
"""
|
||||||
Manages any up/downloads with PKC. Careful to initiate correctly
|
Manages any up/downloads with PKC. Careful to initiate correctly
|
||||||
Use startSession() to initiate.
|
Use startSession() to initiate.
|
||||||
|
|
|
@ -5,6 +5,7 @@ Loads of different functions called in SEPARATE Python instances through
|
||||||
e.g. plugin://... calls. Hence be careful to only rely on window variables.
|
e.g. plugin://... calls. Hence be careful to only rely on window variables.
|
||||||
"""
|
"""
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
from builtins import range
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
from builtins import str
|
||||||
|
from builtins import range
|
||||||
|
from builtins import object
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
|
|
||||||
from xbmc import executebuiltin
|
from xbmc import executebuiltin
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
from builtins import object
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
from ntpath import dirname
|
from ntpath import dirname
|
||||||
|
|
||||||
|
@ -162,7 +163,7 @@ class ItemBase(object):
|
||||||
Returns a dict of the Kodi ids: {<provider>: <kodi_unique_id>}
|
Returns a dict of the Kodi ids: {<provider>: <kodi_unique_id>}
|
||||||
"""
|
"""
|
||||||
kodi_unique_ids = api.guids.copy()
|
kodi_unique_ids = api.guids.copy()
|
||||||
for provider, provider_id in api.guids.iteritems():
|
for provider, provider_id in api.guids.items():
|
||||||
kodi_unique_ids[provider] = self.kodidb.add_uniqueid(
|
kodi_unique_ids[provider] = self.kodidb.add_uniqueid(
|
||||||
kodi_id,
|
kodi_id,
|
||||||
api.kodi_type,
|
api.kodi_type,
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
from builtins import object
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
|
|
||||||
from .common import ItemBase
|
from .common import ItemBase
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
from builtins import object
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
|
|
||||||
from .common import ItemBase, process_path
|
from .common import ItemBase, process_path
|
||||||
|
|
|
@ -5,6 +5,7 @@ Collection of functions using the Kodi JSON RPC interface.
|
||||||
See http://kodi.wiki/view/JSON-RPC_API
|
See http://kodi.wiki/view/JSON-RPC_API
|
||||||
"""
|
"""
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
from builtins import object
|
||||||
from json import loads, dumps
|
from json import loads, dumps
|
||||||
from xbmc import executeJSONRPC
|
from xbmc import executeJSONRPC
|
||||||
|
|
||||||
|
@ -85,7 +86,7 @@ def get_player_ids():
|
||||||
Returns a list of all the active Kodi player ids (usually 3) as int
|
Returns a list of all the active Kodi player ids (usually 3) as int
|
||||||
"""
|
"""
|
||||||
ret = []
|
ret = []
|
||||||
for player in get_players().values():
|
for player in list(get_players().values()):
|
||||||
ret.append(player['playerid'])
|
ret.append(player['playerid'])
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
from builtins import object
|
||||||
from threading import Lock
|
from threading import Lock
|
||||||
|
|
||||||
from .. import db, path_ops
|
from .. import db, path_ops
|
||||||
|
@ -65,7 +66,7 @@ class KodiDBBase(object):
|
||||||
"""
|
"""
|
||||||
Pass in an artworks dict (see PlexAPI) to set an items artwork.
|
Pass in an artworks dict (see PlexAPI) to set an items artwork.
|
||||||
"""
|
"""
|
||||||
for kodi_art, url in artworks.iteritems():
|
for kodi_art, url in artworks.items():
|
||||||
self.add_art(url, kodi_id, kodi_type, kodi_art)
|
self.add_art(url, kodi_id, kodi_type, kodi_art)
|
||||||
|
|
||||||
@db.catch_operationalerrors
|
@db.catch_operationalerrors
|
||||||
|
@ -84,7 +85,7 @@ class KodiDBBase(object):
|
||||||
"""
|
"""
|
||||||
Pass in an artworks dict (see PlexAPI) to set an items artwork.
|
Pass in an artworks dict (see PlexAPI) to set an items artwork.
|
||||||
"""
|
"""
|
||||||
for kodi_art, url in artworks.iteritems():
|
for kodi_art, url in artworks.items():
|
||||||
self.modify_art(url, kodi_id, kodi_type, kodi_art)
|
self.modify_art(url, kodi_id, kodi_type, kodi_art)
|
||||||
|
|
||||||
@db.catch_operationalerrors
|
@db.catch_operationalerrors
|
||||||
|
|
|
@ -318,7 +318,7 @@ class KodiVideoDB(common.KodiDBBase):
|
||||||
for the elmement kodi_id, kodi_type.
|
for the elmement kodi_id, kodi_type.
|
||||||
Will also delete a freshly orphaned actor entry.
|
Will also delete a freshly orphaned actor entry.
|
||||||
"""
|
"""
|
||||||
for kind, people_list in people.iteritems():
|
for kind, people_list in people.items():
|
||||||
self._add_people_kind(kodi_id, kodi_type, kind, people_list)
|
self._add_people_kind(kodi_id, kodi_type, kind, people_list)
|
||||||
|
|
||||||
@db.catch_operationalerrors
|
@db.catch_operationalerrors
|
||||||
|
@ -363,7 +363,7 @@ class KodiVideoDB(common.KodiDBBase):
|
||||||
for kind, people_list in (people if people else
|
for kind, people_list in (people if people else
|
||||||
{'actor': [],
|
{'actor': [],
|
||||||
'director': [],
|
'director': [],
|
||||||
'writer': []}).iteritems():
|
'writer': []}).items():
|
||||||
self._modify_people_kind(kodi_id, kodi_type, kind, people_list)
|
self._modify_people_kind(kodi_id, kodi_type, kind, people_list)
|
||||||
|
|
||||||
@db.catch_operationalerrors
|
@db.catch_operationalerrors
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
from builtins import next
|
||||||
|
from builtins import object
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
import xbmc
|
import xbmc
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
from future import standard_library
|
||||||
|
standard_library.install_aliases()
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
from Queue import Full
|
from queue import Full
|
||||||
|
|
||||||
from . import common, sections
|
from . import common, sections
|
||||||
from ..plex_db import PlexDB
|
from ..plex_db import PlexDB
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
from future import standard_library
|
||||||
|
standard_library.install_aliases()
|
||||||
|
from builtins import range
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
import Queue
|
import queue
|
||||||
|
|
||||||
import xbmcgui
|
import xbmcgui
|
||||||
|
|
||||||
|
@ -80,7 +83,7 @@ class FullSync(common.LibrarySyncMixin, bg.KillableThread):
|
||||||
@utils.log_time
|
@utils.log_time
|
||||||
def process_new_and_changed_items(self, section_queue, processing_queue):
|
def process_new_and_changed_items(self, section_queue, processing_queue):
|
||||||
LOG.debug('Start working')
|
LOG.debug('Start working')
|
||||||
get_metadata_queue = Queue.Queue(maxsize=BACKLOG_QUEUE_SIZE)
|
get_metadata_queue = queue.Queue(maxsize=BACKLOG_QUEUE_SIZE)
|
||||||
scanner_thread = FillMetadataQueue(self.repair,
|
scanner_thread = FillMetadataQueue(self.repair,
|
||||||
section_queue,
|
section_queue,
|
||||||
get_metadata_queue,
|
get_metadata_queue,
|
||||||
|
@ -182,7 +185,7 @@ class FullSync(common.LibrarySyncMixin, bg.KillableThread):
|
||||||
LOG.debug('Exiting threaded_get_generators')
|
LOG.debug('Exiting threaded_get_generators')
|
||||||
|
|
||||||
def full_library_sync(self):
|
def full_library_sync(self):
|
||||||
section_queue = Queue.Queue()
|
section_queue = queue.Queue()
|
||||||
processing_queue = bg.ProcessingQueue(maxsize=XML_QUEUE_SIZE)
|
processing_queue = bg.ProcessingQueue(maxsize=XML_QUEUE_SIZE)
|
||||||
kinds = [
|
kinds = [
|
||||||
(v.PLEX_TYPE_MOVIE, v.PLEX_TYPE_MOVIE),
|
(v.PLEX_TYPE_MOVIE, v.PLEX_TYPE_MOVIE),
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
import urllib
|
from future import standard_library
|
||||||
|
standard_library.install_aliases()
|
||||||
|
from builtins import str
|
||||||
|
import urllib.request, urllib.parse, urllib.error
|
||||||
import copy
|
import copy
|
||||||
|
|
||||||
from ..utils import etree
|
from ..utils import etree
|
||||||
|
@ -56,7 +59,7 @@ NODE_TYPES = {
|
||||||
{
|
{
|
||||||
'mode': 'browseplex',
|
'mode': 'browseplex',
|
||||||
'key': ('/library/sections/{self.section_id}&%s'
|
'key': ('/library/sections/{self.section_id}&%s'
|
||||||
% urllib.urlencode({'sort': 'rating:desc'})),
|
% urllib.parse.urlencode({'sort': 'rating:desc'})),
|
||||||
'section_id': '{self.section_id}'
|
'section_id': '{self.section_id}'
|
||||||
},
|
},
|
||||||
v.CONTENT_TYPE_MOVIE,
|
v.CONTENT_TYPE_MOVIE,
|
||||||
|
@ -84,7 +87,7 @@ NODE_TYPES = {
|
||||||
{
|
{
|
||||||
'mode': 'browseplex',
|
'mode': 'browseplex',
|
||||||
'key': ('/library/sections/{self.section_id}&%s'
|
'key': ('/library/sections/{self.section_id}&%s'
|
||||||
% urllib.urlencode({'sort': 'random'})),
|
% urllib.parse.urlencode({'sort': 'random'})),
|
||||||
'section_id': '{self.section_id}'
|
'section_id': '{self.section_id}'
|
||||||
},
|
},
|
||||||
v.CONTENT_TYPE_MOVIE,
|
v.CONTENT_TYPE_MOVIE,
|
||||||
|
@ -154,7 +157,7 @@ NODE_TYPES = {
|
||||||
{
|
{
|
||||||
'mode': 'browseplex',
|
'mode': 'browseplex',
|
||||||
'key': ('/library/sections/{self.section_id}&%s'
|
'key': ('/library/sections/{self.section_id}&%s'
|
||||||
% urllib.urlencode({'sort': 'rating:desc'})),
|
% urllib.parse.urlencode({'sort': 'rating:desc'})),
|
||||||
'section_id': '{self.section_id}'
|
'section_id': '{self.section_id}'
|
||||||
},
|
},
|
||||||
v.CONTENT_TYPE_SHOW,
|
v.CONTENT_TYPE_SHOW,
|
||||||
|
@ -182,7 +185,7 @@ NODE_TYPES = {
|
||||||
{
|
{
|
||||||
'mode': 'browseplex',
|
'mode': 'browseplex',
|
||||||
'key': ('/library/sections/{self.section_id}&%s'
|
'key': ('/library/sections/{self.section_id}&%s'
|
||||||
% urllib.urlencode({'sort': 'random'})),
|
% urllib.parse.urlencode({'sort': 'random'})),
|
||||||
'section_id': '{self.section_id}'
|
'section_id': '{self.section_id}'
|
||||||
},
|
},
|
||||||
v.CONTENT_TYPE_SHOW,
|
v.CONTENT_TYPE_SHOW,
|
||||||
|
@ -192,7 +195,7 @@ NODE_TYPES = {
|
||||||
{
|
{
|
||||||
'mode': 'browseplex',
|
'mode': 'browseplex',
|
||||||
'key': ('/library/sections/{self.section_id}/recentlyViewed&%s'
|
'key': ('/library/sections/{self.section_id}/recentlyViewed&%s'
|
||||||
% urllib.urlencode({'type': v.PLEX_TYPE_NUMBER_FROM_PLEX_TYPE[v.PLEX_TYPE_EPISODE]})),
|
% urllib.parse.urlencode({'type': v.PLEX_TYPE_NUMBER_FROM_PLEX_TYPE[v.PLEX_TYPE_EPISODE]})),
|
||||||
'section_id': '{self.section_id}'
|
'section_id': '{self.section_id}'
|
||||||
},
|
},
|
||||||
v.CONTENT_TYPE_EPISODE,
|
v.CONTENT_TYPE_EPISODE,
|
||||||
|
@ -236,7 +239,7 @@ def node_pms(section, node_name, args):
|
||||||
else:
|
else:
|
||||||
folder = False
|
folder = False
|
||||||
xml = etree.Element('node',
|
xml = etree.Element('node',
|
||||||
attrib={'order': unicode(section.order),
|
attrib={'order': str(section.order),
|
||||||
'type': 'folder' if folder else 'filter'})
|
'type': 'folder' if folder else 'filter'})
|
||||||
etree.SubElement(xml, 'label').text = node_name
|
etree.SubElement(xml, 'label').text = node_name
|
||||||
etree.SubElement(xml, 'icon').text = ICON_PATH
|
etree.SubElement(xml, 'icon').text = ICON_PATH
|
||||||
|
@ -249,7 +252,7 @@ def node_ondeck(section, node_name):
|
||||||
"""
|
"""
|
||||||
For movies only - returns in-progress movies sorted by last played
|
For movies only - returns in-progress movies sorted by last played
|
||||||
"""
|
"""
|
||||||
xml = etree.Element('node', attrib={'order': unicode(section.order),
|
xml = etree.Element('node', attrib={'order': str(section.order),
|
||||||
'type': 'filter'})
|
'type': 'filter'})
|
||||||
etree.SubElement(xml, 'match').text = 'all'
|
etree.SubElement(xml, 'match').text = 'all'
|
||||||
rule = etree.SubElement(xml, 'rule', attrib={'field': 'tag',
|
rule = etree.SubElement(xml, 'rule', attrib={'field': 'tag',
|
||||||
|
@ -270,7 +273,7 @@ def node_ondeck(section, node_name):
|
||||||
|
|
||||||
def node_recent(section, node_name):
|
def node_recent(section, node_name):
|
||||||
xml = etree.Element('node',
|
xml = etree.Element('node',
|
||||||
attrib={'order': unicode(section.order),
|
attrib={'order': str(section.order),
|
||||||
'type': 'filter'})
|
'type': 'filter'})
|
||||||
etree.SubElement(xml, 'match').text = 'all'
|
etree.SubElement(xml, 'match').text = 'all'
|
||||||
rule = etree.SubElement(xml, 'rule', attrib={'field': 'tag',
|
rule = etree.SubElement(xml, 'rule', attrib={'field': 'tag',
|
||||||
|
@ -299,7 +302,7 @@ def node_recent(section, node_name):
|
||||||
|
|
||||||
|
|
||||||
def node_all(section, node_name):
|
def node_all(section, node_name):
|
||||||
xml = etree.Element('node', attrib={'order': unicode(section.order),
|
xml = etree.Element('node', attrib={'order': str(section.order),
|
||||||
'type': 'filter'})
|
'type': 'filter'})
|
||||||
etree.SubElement(xml, 'match').text = 'all'
|
etree.SubElement(xml, 'match').text = 'all'
|
||||||
rule = etree.SubElement(xml, 'rule', attrib={'field': 'tag',
|
rule = etree.SubElement(xml, 'rule', attrib={'field': 'tag',
|
||||||
|
@ -316,7 +319,7 @@ def node_all(section, node_name):
|
||||||
|
|
||||||
|
|
||||||
def node_recommended(section, node_name):
|
def node_recommended(section, node_name):
|
||||||
xml = etree.Element('node', attrib={'order': unicode(section.order),
|
xml = etree.Element('node', attrib={'order': str(section.order),
|
||||||
'type': 'filter'})
|
'type': 'filter'})
|
||||||
etree.SubElement(xml, 'match').text = 'all'
|
etree.SubElement(xml, 'match').text = 'all'
|
||||||
rule = etree.SubElement(xml, 'rule', attrib={'field': 'tag',
|
rule = etree.SubElement(xml, 'rule', attrib={'field': 'tag',
|
||||||
|
@ -337,7 +340,7 @@ def node_recommended(section, node_name):
|
||||||
|
|
||||||
|
|
||||||
def node_genres(section, node_name):
|
def node_genres(section, node_name):
|
||||||
xml = etree.Element('node', attrib={'order': unicode(section.order),
|
xml = etree.Element('node', attrib={'order': str(section.order),
|
||||||
'type': 'filter'})
|
'type': 'filter'})
|
||||||
etree.SubElement(xml, 'match').text = 'all'
|
etree.SubElement(xml, 'match').text = 'all'
|
||||||
rule = etree.SubElement(xml, 'rule', attrib={'field': 'tag',
|
rule = etree.SubElement(xml, 'rule', attrib={'field': 'tag',
|
||||||
|
@ -355,7 +358,7 @@ def node_genres(section, node_name):
|
||||||
|
|
||||||
|
|
||||||
def node_sets(section, node_name):
|
def node_sets(section, node_name):
|
||||||
xml = etree.Element('node', attrib={'order': unicode(section.order),
|
xml = etree.Element('node', attrib={'order': str(section.order),
|
||||||
'type': 'filter'})
|
'type': 'filter'})
|
||||||
etree.SubElement(xml, 'match').text = 'all'
|
etree.SubElement(xml, 'match').text = 'all'
|
||||||
rule = etree.SubElement(xml, 'rule', attrib={'field': 'tag',
|
rule = etree.SubElement(xml, 'rule', attrib={'field': 'tag',
|
||||||
|
@ -374,7 +377,7 @@ def node_sets(section, node_name):
|
||||||
|
|
||||||
|
|
||||||
def node_random(section, node_name):
|
def node_random(section, node_name):
|
||||||
xml = etree.Element('node', attrib={'order': unicode(section.order),
|
xml = etree.Element('node', attrib={'order': str(section.order),
|
||||||
'type': 'filter'})
|
'type': 'filter'})
|
||||||
etree.SubElement(xml, 'match').text = 'all'
|
etree.SubElement(xml, 'match').text = 'all'
|
||||||
rule = etree.SubElement(xml, 'rule', attrib={'field': 'tag',
|
rule = etree.SubElement(xml, 'rule', attrib={'field': 'tag',
|
||||||
|
@ -392,7 +395,7 @@ def node_random(section, node_name):
|
||||||
|
|
||||||
|
|
||||||
def node_lastplayed(section, node_name):
|
def node_lastplayed(section, node_name):
|
||||||
xml = etree.Element('node', attrib={'order': unicode(section.order),
|
xml = etree.Element('node', attrib={'order': str(section.order),
|
||||||
'type': 'filter'})
|
'type': 'filter'})
|
||||||
etree.SubElement(xml, 'match').text = 'all'
|
etree.SubElement(xml, 'match').text = 'all'
|
||||||
rule = etree.SubElement(xml, 'rule', attrib={'field': 'tag',
|
rule = etree.SubElement(xml, 'rule', attrib={'field': 'tag',
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
from builtins import str
|
||||||
|
from builtins import range
|
||||||
|
from builtins import object
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
import copy
|
import copy
|
||||||
|
|
||||||
|
@ -98,7 +101,7 @@ class Section(object):
|
||||||
"}}").format(self=self).encode('utf-8')
|
"}}").format(self=self).encode('utf-8')
|
||||||
__str__ = __repr__
|
__str__ = __repr__
|
||||||
|
|
||||||
def __nonzero__(self):
|
def __bool__(self):
|
||||||
return (self.section_id is not None and
|
return (self.section_id is not None and
|
||||||
self.name is not None and
|
self.name is not None and
|
||||||
self.section_type is not None)
|
self.section_type is not None)
|
||||||
|
@ -236,7 +239,7 @@ class Section(object):
|
||||||
{key: '{self.<Section attribute>}'}
|
{key: '{self.<Section attribute>}'}
|
||||||
"""
|
"""
|
||||||
args = copy.deepcopy(args)
|
args = copy.deepcopy(args)
|
||||||
for key, value in args.iteritems():
|
for key, value in args.items():
|
||||||
args[key] = value.format(self=self)
|
args[key] = value.format(self=self)
|
||||||
return utils.extend_url('plugin://%s' % v.ADDON_ID, args)
|
return utils.extend_url('plugin://%s' % v.ADDON_ID, args)
|
||||||
|
|
||||||
|
@ -265,7 +268,7 @@ class Section(object):
|
||||||
args = {
|
args = {
|
||||||
'mode': 'browseplex',
|
'mode': 'browseplex',
|
||||||
'key': '/library/sections/%s' % self.section_id,
|
'key': '/library/sections/%s' % self.section_id,
|
||||||
'section_id': unicode(self.section_id)
|
'section_id': str(self.section_id)
|
||||||
}
|
}
|
||||||
if not self.sync_to_kodi:
|
if not self.sync_to_kodi:
|
||||||
args['synched'] = 'false'
|
args['synched'] = 'false'
|
||||||
|
@ -276,7 +279,7 @@ class Section(object):
|
||||||
args = {
|
args = {
|
||||||
'mode': 'browseplex',
|
'mode': 'browseplex',
|
||||||
'key': '/library/sections/%s/all' % self.section_id,
|
'key': '/library/sections/%s/all' % self.section_id,
|
||||||
'section_id': unicode(self.section_id)
|
'section_id': str(self.section_id)
|
||||||
}
|
}
|
||||||
if not self.sync_to_kodi:
|
if not self.sync_to_kodi:
|
||||||
args['synched'] = 'false'
|
args['synched'] = 'false'
|
||||||
|
@ -318,7 +321,7 @@ class Section(object):
|
||||||
if not path_ops.exists(path_ops.path.join(self.path, 'index.xml')):
|
if not path_ops.exists(path_ops.path.join(self.path, 'index.xml')):
|
||||||
LOG.debug('Creating index.xml for section %s', self.name)
|
LOG.debug('Creating index.xml for section %s', self.name)
|
||||||
xml = etree.Element('node',
|
xml = etree.Element('node',
|
||||||
attrib={'order': unicode(self.order)})
|
attrib={'order': str(self.order)})
|
||||||
etree.SubElement(xml, 'label').text = self.name
|
etree.SubElement(xml, 'label').text = self.name
|
||||||
etree.SubElement(xml, 'icon').text = self.icon or nodes.ICON_PATH
|
etree.SubElement(xml, 'icon').text = self.icon or nodes.ICON_PATH
|
||||||
self._write_xml(xml, 'index.xml')
|
self._write_xml(xml, 'index.xml')
|
||||||
|
@ -708,7 +711,7 @@ def _clear_window_vars(index):
|
||||||
utils.window('%s.path' % node, clear=True)
|
utils.window('%s.path' % node, clear=True)
|
||||||
utils.window('%s.id' % node, clear=True)
|
utils.window('%s.id' % node, clear=True)
|
||||||
# Just clear everything here, ignore the plex_type
|
# Just clear everything here, ignore the plex_type
|
||||||
for typus in (x[0] for y in nodes.NODE_TYPES.values() for x in y):
|
for typus in (x[0] for y in list(nodes.NODE_TYPES.values()) for x in y):
|
||||||
for kind in WINDOW_ARGS:
|
for kind in WINDOW_ARGS:
|
||||||
node = 'Plex.nodes.%s.%s.%s' % (index, typus, kind)
|
node = 'Plex.nodes.%s.%s.%s' % (index, typus, kind)
|
||||||
utils.window(node, clear=True)
|
utils.window(node, clear=True)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
from builtins import str
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
|
|
||||||
from .common import update_kodi_library, PLAYLIST_SYNC_ENABLED
|
from .common import update_kodi_library, PLAYLIST_SYNC_ENABLED
|
||||||
|
@ -160,7 +161,7 @@ def store_timeline_message(data):
|
||||||
continue
|
continue
|
||||||
status = int(message['state'])
|
status = int(message['state'])
|
||||||
if typus == 'playlist' and PLAYLIST_SYNC_ENABLED:
|
if typus == 'playlist' and PLAYLIST_SYNC_ENABLED:
|
||||||
playlists.websocket(plex_id=unicode(message['itemID']),
|
playlists.websocket(plex_id=str(message['itemID']),
|
||||||
status=status)
|
status=status)
|
||||||
elif status == 9:
|
elif status == 9:
|
||||||
# Immediately and always process deletions (as the PMS will
|
# Immediately and always process deletions (as the PMS will
|
||||||
|
|
|
@ -41,7 +41,7 @@ class LogHandler(logging.StreamHandler):
|
||||||
self.setFormatter(logging.Formatter(fmt=b"%(name)s: %(message)s"))
|
self.setFormatter(logging.Formatter(fmt=b"%(name)s: %(message)s"))
|
||||||
|
|
||||||
def emit(self, record):
|
def emit(self, record):
|
||||||
if isinstance(record.msg, unicode):
|
if isinstance(record.msg, str):
|
||||||
record.msg = record.msg.encode('utf-8')
|
record.msg = record.msg.encode('utf-8')
|
||||||
try:
|
try:
|
||||||
xbmc.log(self.format(record), level=LEVELS[record.levelno])
|
xbmc.log(self.format(record), level=LEVELS[record.levelno])
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
from builtins import str
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
|
|
||||||
from . import variables as v
|
from . import variables as v
|
||||||
|
|
|
@ -39,6 +39,7 @@ Functions
|
||||||
.. autofunction:: parent_dir_path
|
.. autofunction:: parent_dir_path
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from builtins import next
|
||||||
import os.path
|
import os.path
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
|
||||||
|
@ -72,7 +73,7 @@ def get_dir_walker(recursive, topdown=True, followlinks=False):
|
||||||
try:
|
try:
|
||||||
yield next(os.walk(path, topdown=topdown, followlinks=followlinks))
|
yield next(os.walk(path, topdown=topdown, followlinks=followlinks))
|
||||||
except NameError:
|
except NameError:
|
||||||
yield os.walk(path, topdown=topdown, followlinks=followlinks).next() #IGNORE:E1101
|
yield next(os.walk(path, topdown=topdown, followlinks=followlinks)) #IGNORE:E1101
|
||||||
return walk
|
return walk
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@ Functions
|
||||||
.. autofunction:: filter_paths
|
.. autofunction:: filter_paths
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from builtins import map
|
||||||
from fnmatch import fnmatch, fnmatchcase
|
from fnmatch import fnmatch, fnmatchcase
|
||||||
|
|
||||||
__all__ = ['match_path',
|
__all__ = ['match_path',
|
||||||
|
|
|
@ -4,6 +4,9 @@
|
||||||
Used to kick off Kodi playback
|
Used to kick off Kodi playback
|
||||||
"""
|
"""
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
from future import standard_library
|
||||||
|
standard_library.install_aliases()
|
||||||
|
from builtins import str
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
import datetime
|
import datetime
|
||||||
|
@ -296,7 +299,7 @@ def resume_dialog(resume):
|
||||||
resume = datetime.timedelta(seconds=resume)
|
resume = datetime.timedelta(seconds=resume)
|
||||||
LOG.debug('Showing PKC resume dialog for resume: %s', resume)
|
LOG.debug('Showing PKC resume dialog for resume: %s', resume)
|
||||||
answ = utils.dialog('contextmenu',
|
answ = utils.dialog('contextmenu',
|
||||||
[utils.lang(12022).replace('{0:s}', '{0}').format(unicode(resume)),
|
[utils.lang(12022).replace('{0:s}', '{0}').format(str(resume)),
|
||||||
utils.lang(12021)])
|
utils.lang(12021)])
|
||||||
if answ == -1:
|
if answ == -1:
|
||||||
return
|
return
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
Collection of functions associated with Kodi and Plex playlists and playqueues
|
Collection of functions associated with Kodi and Plex playlists and playqueues
|
||||||
"""
|
"""
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
from builtins import object
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
|
|
||||||
from .plex_api import API
|
from .plex_api import API
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
from future import standard_library
|
||||||
|
standard_library.install_aliases()
|
||||||
|
from builtins import object
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
import Queue
|
import queue
|
||||||
import time
|
import time
|
||||||
import os
|
import os
|
||||||
import hashlib
|
import hashlib
|
||||||
|
@ -188,7 +191,7 @@ class PlaylistObserver(Observer):
|
||||||
while time.time() - start < timeout:
|
while time.time() - start < timeout:
|
||||||
try:
|
try:
|
||||||
new_event, new_watch = event_queue.get(block=False)
|
new_event, new_watch = event_queue.get(block=False)
|
||||||
except Queue.Empty:
|
except queue.Empty:
|
||||||
app.APP.monitor.waitForAbort(0.2)
|
app.APP.monitor.waitForAbort(0.2)
|
||||||
else:
|
else:
|
||||||
event_queue.task_done()
|
event_queue.task_done()
|
||||||
|
|
|
@ -5,6 +5,7 @@ Synced playlists are stored in our plex.db. Interact with it through this
|
||||||
module
|
module
|
||||||
"""
|
"""
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
from builtins import next
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
|
|
||||||
from .common import Playlist, PlaylistError
|
from .common import Playlist, PlaylistError
|
||||||
|
|
|
@ -5,6 +5,7 @@ Functions to communicate with the currently connected PMS in order to
|
||||||
manipulate playlists
|
manipulate playlists
|
||||||
"""
|
"""
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
from builtins import str
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
|
|
||||||
from .common import PlaylistError
|
from .common import PlaylistError
|
||||||
|
@ -108,7 +109,7 @@ def add_items(playlist, plex_ids):
|
||||||
'smart': 0,
|
'smart': 0,
|
||||||
'uri': ('server://%s/com.plexapp.plugins.library/library/metadata/%s'
|
'uri': ('server://%s/com.plexapp.plugins.library/library/metadata/%s'
|
||||||
% (app.CONN.machine_identifier,
|
% (app.CONN.machine_identifier,
|
||||||
','.join(unicode(x) for x in plex_ids)))
|
','.join(str(x) for x in plex_ids)))
|
||||||
}
|
}
|
||||||
xml = DU().downloadUrl(url='{server}/playlists/',
|
xml = DU().downloadUrl(url='{server}/playlists/',
|
||||||
action_type='POST',
|
action_type='POST',
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
Monitors the Kodi playqueue and adjusts the Plex playqueue accordingly
|
Monitors the Kodi playqueue and adjusts the Plex playqueue accordingly
|
||||||
"""
|
"""
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
from builtins import range
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
import copy
|
import copy
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
from builtins import object
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
|
|
||||||
from ..kodi_db import KodiVideoDB, KodiMusicDB
|
from ..kodi_db import KodiVideoDB, KodiMusicDB
|
||||||
|
@ -71,7 +72,7 @@ class Artwork(object):
|
||||||
# either the season or the show
|
# either the season or the show
|
||||||
return artworks
|
return artworks
|
||||||
for kodi_artwork, plex_artwork in \
|
for kodi_artwork, plex_artwork in \
|
||||||
v.KODI_TO_PLEX_ARTWORK_EPISODE.iteritems():
|
v.KODI_TO_PLEX_ARTWORK_EPISODE.items():
|
||||||
art = self.one_artwork(plex_artwork)
|
art = self.one_artwork(plex_artwork)
|
||||||
if art:
|
if art:
|
||||||
artworks[kodi_artwork] = art
|
artworks[kodi_artwork] = art
|
||||||
|
@ -109,7 +110,7 @@ class Artwork(object):
|
||||||
with KodiMusicDB(lock=False) as kodidb:
|
with KodiMusicDB(lock=False) as kodidb:
|
||||||
return kodidb.get_art(kodi_id, kodi_type)
|
return kodidb.get_art(kodi_id, kodi_type)
|
||||||
|
|
||||||
for kodi_artwork, plex_artwork in v.KODI_TO_PLEX_ARTWORK.iteritems():
|
for kodi_artwork, plex_artwork in v.KODI_TO_PLEX_ARTWORK.items():
|
||||||
art = self.one_artwork(plex_artwork)
|
art = self.one_artwork(plex_artwork)
|
||||||
if art:
|
if art:
|
||||||
artworks[kodi_artwork] = art
|
artworks[kodi_artwork] = art
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
from builtins import str
|
||||||
|
from builtins import object
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
from re import sub
|
from re import sub
|
||||||
|
|
||||||
|
@ -357,9 +359,9 @@ class Base(object):
|
||||||
total = int(self.xml.attrib['leafCount'])
|
total = int(self.xml.attrib['leafCount'])
|
||||||
watched = int(self.xml.attrib['viewedLeafCount'])
|
watched = int(self.xml.attrib['viewedLeafCount'])
|
||||||
return {
|
return {
|
||||||
'totalepisodes': unicode(total),
|
'totalepisodes': str(total),
|
||||||
'watchedepisodes': unicode(watched),
|
'watchedepisodes': str(watched),
|
||||||
'unwatchedepisodes': unicode(total - watched)
|
'unwatchedepisodes': str(total - watched)
|
||||||
}
|
}
|
||||||
except (KeyError, TypeError):
|
except (KeyError, TypeError):
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
from builtins import str
|
||||||
|
from builtins import range
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
from re import sub
|
from re import sub
|
||||||
from string import punctuation
|
from string import punctuation
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
|
||||||
|
from builtins import object
|
||||||
from .. import utils, variables as v, app
|
from .. import utils, variables as v, app
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
from builtins import object
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
|
|
||||||
from ..utils import cast
|
from ..utils import cast
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
|
||||||
|
from builtins import object
|
||||||
from ..utils import cast
|
from ..utils import cast
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
|
||||||
|
from builtins import object
|
||||||
from ..utils import cast
|
from ..utils import cast
|
||||||
from .. import timing, variables as v, app
|
from .. import timing, variables as v, app
|
||||||
|
|
||||||
|
|
|
@ -4,9 +4,11 @@
|
||||||
The Plex Companion master python file
|
The Plex Companion master python file
|
||||||
"""
|
"""
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
from future import standard_library
|
||||||
|
standard_library.install_aliases()
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
from Queue import Empty
|
from queue import Empty
|
||||||
from socket import SHUT_RDWR
|
from socket import SHUT_RDWR
|
||||||
from xbmc import executebuiltin
|
from xbmc import executebuiltin
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
from builtins import object
|
||||||
from threading import Lock
|
from threading import Lock
|
||||||
|
|
||||||
from .. import db, variables as v
|
from .. import db, variables as v
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
from builtins import object
|
||||||
from .. import variables as v
|
from .. import variables as v
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
from builtins import object
|
||||||
from .. import variables as v
|
from .. import variables as v
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
|
||||||
|
|
||||||
|
from builtins import object
|
||||||
class Playlists(object):
|
class Playlists(object):
|
||||||
def playlist_ids(self):
|
def playlist_ids(self):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
|
||||||
|
|
||||||
|
from builtins import object
|
||||||
class Sections(object):
|
class Sections(object):
|
||||||
def all_sections(self):
|
def all_sections(self):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
from builtins import object
|
||||||
from .. import variables as v
|
from .. import variables as v
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
from future import standard_library
|
||||||
|
standard_library.install_aliases()
|
||||||
|
from builtins import str
|
||||||
|
from builtins import range
|
||||||
|
from builtins import object
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
from ast import literal_eval
|
from ast import literal_eval
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
|
@ -333,7 +338,7 @@ def _pms_list_from_plex_tv(token):
|
||||||
LOG.error('Could not get list of PMS from plex.tv')
|
LOG.error('Could not get list of PMS from plex.tv')
|
||||||
return []
|
return []
|
||||||
|
|
||||||
from Queue import Queue
|
from queue import Queue
|
||||||
queue = Queue()
|
queue = Queue()
|
||||||
thread_queue = []
|
thread_queue = []
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
from builtins import object
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
import time
|
import time
|
||||||
import threading
|
import threading
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
from future import standard_library
|
||||||
|
standard_library.install_aliases()
|
||||||
|
from builtins import str
|
||||||
|
from builtins import object
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
import httplib
|
import http.client
|
||||||
import traceback
|
import traceback
|
||||||
import string
|
import string
|
||||||
import errno
|
import errno
|
||||||
|
@ -15,7 +19,7 @@ LOG = getLogger('PLEX.httppersist')
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
|
|
||||||
class RequestMgr:
|
class RequestMgr(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.conns = {}
|
self.conns = {}
|
||||||
|
|
||||||
|
@ -23,9 +27,9 @@ class RequestMgr:
|
||||||
conn = self.conns.get(protocol + host + str(port), False)
|
conn = self.conns.get(protocol + host + str(port), False)
|
||||||
if not conn:
|
if not conn:
|
||||||
if protocol == "https":
|
if protocol == "https":
|
||||||
conn = httplib.HTTPSConnection(host, port)
|
conn = http.client.HTTPSConnection(host, port)
|
||||||
else:
|
else:
|
||||||
conn = httplib.HTTPConnection(host, port)
|
conn = http.client.HTTPConnection(host, port)
|
||||||
self.conns[protocol + host + str(port)] = conn
|
self.conns[protocol + host + str(port)] = conn
|
||||||
return conn
|
return conn
|
||||||
|
|
||||||
|
@ -36,7 +40,7 @@ class RequestMgr:
|
||||||
self.conns.pop(protocol + host + str(port), None)
|
self.conns.pop(protocol + host + str(port), None)
|
||||||
|
|
||||||
def dumpConnections(self):
|
def dumpConnections(self):
|
||||||
for conn in self.conns.values():
|
for conn in list(self.conns.values()):
|
||||||
conn.close()
|
conn.close()
|
||||||
self.conns = {}
|
self.conns = {}
|
||||||
|
|
||||||
|
|
|
@ -4,10 +4,12 @@
|
||||||
Plex Companion listener
|
Plex Companion listener
|
||||||
"""
|
"""
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
from future import standard_library
|
||||||
|
standard_library.install_aliases()
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
from re import sub
|
from re import sub
|
||||||
from SocketServer import ThreadingMixIn
|
from socketserver import ThreadingMixIn
|
||||||
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
|
from http.server import HTTPServer, BaseHTTPRequestHandler
|
||||||
|
|
||||||
from .. import utils, companion, json_rpc as js, clientinfo, variables as v
|
from .. import utils, companion, json_rpc as js, clientinfo, variables as v
|
||||||
from .. import app
|
from .. import app
|
||||||
|
|
|
@ -24,6 +24,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
MA 02110-1301, USA.
|
MA 02110-1301, USA.
|
||||||
"""
|
"""
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
from builtins import str
|
||||||
|
from builtins import object
|
||||||
import logging
|
import logging
|
||||||
import socket
|
import socket
|
||||||
import threading
|
import threading
|
||||||
|
@ -39,7 +41,7 @@ log = logging.getLogger('PLEX.plexgdm')
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
|
|
||||||
class plexgdm:
|
class plexgdm(object):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.discover_message = 'M-SEARCH * HTTP/1.0'
|
self.discover_message = 'M-SEARCH * HTTP/1.0'
|
||||||
|
|
|
@ -5,6 +5,10 @@ Manages getting playstate from Kodi and sending it to the PMS as well as
|
||||||
subscribed Plex Companion clients.
|
subscribed Plex Companion clients.
|
||||||
"""
|
"""
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
from future import standard_library
|
||||||
|
standard_library.install_aliases()
|
||||||
|
from builtins import str
|
||||||
|
from builtins import object
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
|
|
||||||
|
@ -174,7 +178,7 @@ class SubscriptionMgr(object):
|
||||||
Returns the string 'key1="value1" key2="value2" ...' for dictionary
|
Returns the string 'key1="value1" key2="value2" ...' for dictionary
|
||||||
"""
|
"""
|
||||||
answ = ''
|
answ = ''
|
||||||
for key, value in dictionary.iteritems():
|
for key, value in dictionary.items():
|
||||||
answ += '%s="%s" ' % (key, value)
|
answ += '%s="%s" ' % (key, value)
|
||||||
return answ
|
return answ
|
||||||
|
|
||||||
|
@ -317,7 +321,7 @@ class SubscriptionMgr(object):
|
||||||
Hence we'd have a missmatch between the state.PLAYER_STATES and our
|
Hence we'd have a missmatch between the state.PLAYER_STATES and our
|
||||||
playqueues.
|
playqueues.
|
||||||
"""
|
"""
|
||||||
for player in players.values():
|
for player in list(players.values()):
|
||||||
info = app.PLAYSTATE.player_states[player['playerid']]
|
info = app.PLAYSTATE.player_states[player['playerid']]
|
||||||
playqueue = PQ.PLAYQUEUES[player['playerid']]
|
playqueue = PQ.PLAYQUEUES[player['playerid']]
|
||||||
position = self._get_correct_position(info, playqueue)
|
position = self._get_correct_position(info, playqueue)
|
||||||
|
@ -342,7 +346,7 @@ class SubscriptionMgr(object):
|
||||||
# Get all the active/playing Kodi players (video, audio, pictures)
|
# Get all the active/playing Kodi players (video, audio, pictures)
|
||||||
players = js.get_players()
|
players = js.get_players()
|
||||||
# Update the PKC info with what's playing on the Kodi side
|
# Update the PKC info with what's playing on the Kodi side
|
||||||
for player in players.values():
|
for player in list(players.values()):
|
||||||
update_player_info(player['playerid'])
|
update_player_info(player['playerid'])
|
||||||
# Check whether we can use the CURRENT info or whether PKC is still
|
# Check whether we can use the CURRENT info or whether PKC is still
|
||||||
# initializing
|
# initializing
|
||||||
|
@ -352,12 +356,12 @@ class SubscriptionMgr(object):
|
||||||
self._notify_server(players)
|
self._notify_server(players)
|
||||||
if self.subscribers:
|
if self.subscribers:
|
||||||
msg = self.msg(players)
|
msg = self.msg(players)
|
||||||
for subscriber in self.subscribers.values():
|
for subscriber in list(self.subscribers.values()):
|
||||||
subscriber.send_update(msg)
|
subscriber.send_update(msg)
|
||||||
self.lastplayers = players
|
self.lastplayers = players
|
||||||
|
|
||||||
def _notify_server(self, players):
|
def _notify_server(self, players):
|
||||||
for typus, player in players.iteritems():
|
for typus, player in players.items():
|
||||||
self._send_pms_notification(
|
self._send_pms_notification(
|
||||||
player['playerid'], self._get_pms_params(player['playerid']))
|
player['playerid'], self._get_pms_params(player['playerid']))
|
||||||
try:
|
try:
|
||||||
|
@ -365,7 +369,7 @@ class SubscriptionMgr(object):
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
# Process the players we have left (to signal a stop)
|
# Process the players we have left (to signal a stop)
|
||||||
for player in self.lastplayers.values():
|
for player in list(self.lastplayers.values()):
|
||||||
self.last_params['state'] = 'stopped'
|
self.last_params['state'] = 'stopped'
|
||||||
self._send_pms_notification(player['playerid'], self.last_params)
|
self._send_pms_notification(player['playerid'], self.last_params)
|
||||||
|
|
||||||
|
@ -442,13 +446,13 @@ class SubscriptionMgr(object):
|
||||||
(Calls the cleanup() method of the subscriber)
|
(Calls the cleanup() method of the subscriber)
|
||||||
"""
|
"""
|
||||||
with app.APP.lock_subscriber:
|
with app.APP.lock_subscriber:
|
||||||
for subscriber in self.subscribers.values():
|
for subscriber in list(self.subscribers.values()):
|
||||||
if subscriber.uuid == uuid or subscriber.host == uuid:
|
if subscriber.uuid == uuid or subscriber.host == uuid:
|
||||||
subscriber.cleanup()
|
subscriber.cleanup()
|
||||||
del self.subscribers[subscriber.uuid]
|
del self.subscribers[subscriber.uuid]
|
||||||
|
|
||||||
def _cleanup(self):
|
def _cleanup(self):
|
||||||
for subscriber in self.subscribers.values():
|
for subscriber in list(self.subscribers.values()):
|
||||||
if subscriber.age > 30:
|
if subscriber.age > 30:
|
||||||
subscriber.cleanup()
|
subscriber.cleanup()
|
||||||
del self.subscribers[subscriber.uuid]
|
del self.subscribers[subscriber.uuid]
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
from builtins import object
|
||||||
import logging
|
import logging
|
||||||
import sys
|
import sys
|
||||||
import xbmc
|
import xbmc
|
||||||
|
|
|
@ -28,7 +28,7 @@ from . import platform
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Python 2
|
# Python 2
|
||||||
str_cls = unicode
|
str_cls = str
|
||||||
bytes_cls = str
|
bytes_cls = str
|
||||||
except NameError:
|
except NameError:
|
||||||
# Python 3
|
# Python 3
|
||||||
|
|
|
@ -5,6 +5,8 @@ Used to shovel data from separate Kodi Python instances to the main thread
|
||||||
and vice versa.
|
and vice versa.
|
||||||
"""
|
"""
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
from builtins import str
|
||||||
|
from builtins import object
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
@ -33,15 +35,15 @@ def cast(func, value):
|
||||||
return value
|
return value
|
||||||
elif func == bool:
|
elif func == bool:
|
||||||
return bool(int(value))
|
return bool(int(value))
|
||||||
elif func == unicode:
|
elif func == str:
|
||||||
if isinstance(value, (int, long, float)):
|
if isinstance(value, (int, float)):
|
||||||
return unicode(value)
|
return str(value)
|
||||||
elif isinstance(value, unicode):
|
elif isinstance(value, str):
|
||||||
return value
|
return value
|
||||||
else:
|
else:
|
||||||
return value.decode('utf-8')
|
return value.decode('utf-8')
|
||||||
elif func == str:
|
elif func == str:
|
||||||
if isinstance(value, (int, long, float)):
|
if isinstance(value, (int, float)):
|
||||||
return str(value)
|
return str(value)
|
||||||
elif isinstance(value, str):
|
elif isinstance(value, str):
|
||||||
return value
|
return value
|
||||||
|
@ -163,7 +165,7 @@ def convert_pkc_to_listitem(pkc_listitem):
|
||||||
listitem.addStreamInfo(**stream)
|
listitem.addStreamInfo(**stream)
|
||||||
if data['art']:
|
if data['art']:
|
||||||
listitem.setArt(data['art'])
|
listitem.setArt(data['art'])
|
||||||
for key, value in data['property'].iteritems():
|
for key, value in data['property'].items():
|
||||||
listitem.setProperty(key, cast(str, value))
|
listitem.setProperty(key, cast(str, value))
|
||||||
if data['subtitles']:
|
if data['subtitles']:
|
||||||
listitem.setSubtitles(data['subtitles'])
|
listitem.setSubtitles(data['subtitles'])
|
||||||
|
|
|
@ -4,13 +4,17 @@
|
||||||
Various functions and decorators for PKC
|
Various functions and decorators for PKC
|
||||||
"""
|
"""
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
from future import standard_library
|
||||||
|
standard_library.install_aliases()
|
||||||
|
from builtins import str
|
||||||
|
from builtins import object
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
from sqlite3 import OperationalError
|
from sqlite3 import OperationalError
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from unicodedata import normalize
|
from unicodedata import normalize
|
||||||
from threading import Lock
|
from threading import Lock
|
||||||
import urllib
|
import urllib.request, urllib.parse, urllib.error
|
||||||
import urlparse as _urlparse
|
import urllib.parse as _urlparse
|
||||||
# Originally tried faster cElementTree, but does NOT work reliably with Kodi
|
# Originally tried faster cElementTree, but does NOT work reliably with Kodi
|
||||||
import xml.etree.ElementTree as etree
|
import xml.etree.ElementTree as etree
|
||||||
# etree parse unsafe; make sure we're always receiving unicode
|
# etree parse unsafe; make sure we're always receiving unicode
|
||||||
|
@ -191,7 +195,7 @@ def dialog(typus, *args, **kwargs):
|
||||||
'{warning}': xbmcgui.NOTIFICATION_WARNING,
|
'{warning}': xbmcgui.NOTIFICATION_WARNING,
|
||||||
'{error}': xbmcgui.NOTIFICATION_ERROR
|
'{error}': xbmcgui.NOTIFICATION_ERROR
|
||||||
}
|
}
|
||||||
for key, value in types.iteritems():
|
for key, value in types.items():
|
||||||
kwargs['icon'] = kwargs['icon'].replace(key, value)
|
kwargs['icon'] = kwargs['icon'].replace(key, value)
|
||||||
if 'type' in kwargs:
|
if 'type' in kwargs:
|
||||||
types = {
|
types = {
|
||||||
|
@ -291,15 +295,15 @@ def cast(func, value):
|
||||||
return value
|
return value
|
||||||
elif func == bool:
|
elif func == bool:
|
||||||
return bool(int(value))
|
return bool(int(value))
|
||||||
elif func == unicode:
|
elif func == str:
|
||||||
if isinstance(value, (int, long, float)):
|
if isinstance(value, (int, float)):
|
||||||
return unicode(value)
|
return str(value)
|
||||||
elif isinstance(value, unicode):
|
elif isinstance(value, str):
|
||||||
return value
|
return value
|
||||||
else:
|
else:
|
||||||
return value.decode('utf-8')
|
return value.decode('utf-8')
|
||||||
elif func == str:
|
elif func == str:
|
||||||
if isinstance(value, (int, long, float)):
|
if isinstance(value, (int, float)):
|
||||||
return str(value)
|
return str(value)
|
||||||
elif isinstance(value, str):
|
elif isinstance(value, str):
|
||||||
return value
|
return value
|
||||||
|
@ -329,7 +333,7 @@ def extend_url(url, params):
|
||||||
in unicode
|
in unicode
|
||||||
"""
|
"""
|
||||||
params = encode_dict(params) if params else {}
|
params = encode_dict(params) if params else {}
|
||||||
params = urllib.urlencode(params).decode('utf-8')
|
params = urllib.parse.urlencode(params).decode('utf-8')
|
||||||
if '?' in url:
|
if '?' in url:
|
||||||
return '%s&%s' % (url, params)
|
return '%s&%s' % (url, params)
|
||||||
else:
|
else:
|
||||||
|
@ -343,10 +347,10 @@ def encode_dict(dictionary):
|
||||||
|
|
||||||
Useful for urllib.urlencode or urllib.(un)quote
|
Useful for urllib.urlencode or urllib.(un)quote
|
||||||
"""
|
"""
|
||||||
for key, value in dictionary.iteritems():
|
for key, value in dictionary.items():
|
||||||
if isinstance(key, unicode):
|
if isinstance(key, str):
|
||||||
dictionary[key.encode('utf-8')] = dictionary.pop(key)
|
dictionary[key.encode('utf-8')] = dictionary.pop(key)
|
||||||
if isinstance(value, unicode):
|
if isinstance(value, str):
|
||||||
dictionary[key] = value.encode('utf-8')
|
dictionary[key] = value.encode('utf-8')
|
||||||
return dictionary
|
return dictionary
|
||||||
|
|
||||||
|
@ -357,11 +361,11 @@ def parse_qs(qs, keep_blank_values=0, strict_parsing=0):
|
||||||
either as str or unicode
|
either as str or unicode
|
||||||
Returns a dict with lists as values; all entires unicode
|
Returns a dict with lists as values; all entires unicode
|
||||||
"""
|
"""
|
||||||
if isinstance(qs, unicode):
|
if isinstance(qs, str):
|
||||||
qs = qs.encode('utf-8')
|
qs = qs.encode('utf-8')
|
||||||
qs = _urlparse.parse_qs(qs, keep_blank_values, strict_parsing)
|
qs = _urlparse.parse_qs(qs, keep_blank_values, strict_parsing)
|
||||||
return {k.decode('utf-8'): [e.decode('utf-8') for e in v]
|
return {k.decode('utf-8'): [e.decode('utf-8') for e in v]
|
||||||
for k, v in qs.iteritems()}
|
for k, v in qs.items()}
|
||||||
|
|
||||||
|
|
||||||
def parse_qsl(qs, keep_blank_values=0, strict_parsing=0):
|
def parse_qsl(qs, keep_blank_values=0, strict_parsing=0):
|
||||||
|
@ -369,7 +373,7 @@ def parse_qsl(qs, keep_blank_values=0, strict_parsing=0):
|
||||||
unicode-safe way to use urlparse.parse_qsl(). Pass in either str or unicode
|
unicode-safe way to use urlparse.parse_qsl(). Pass in either str or unicode
|
||||||
Returns a list of unicode tuples
|
Returns a list of unicode tuples
|
||||||
"""
|
"""
|
||||||
if isinstance(qs, unicode):
|
if isinstance(qs, str):
|
||||||
qs = qs.encode('utf-8')
|
qs = qs.encode('utf-8')
|
||||||
qs = _urlparse.parse_qsl(qs, keep_blank_values, strict_parsing)
|
qs = _urlparse.parse_qsl(qs, keep_blank_values, strict_parsing)
|
||||||
return [(x.decode('utf-8'), y.decode('utf-8')) for (x, y) in qs]
|
return [(x.decode('utf-8'), y.decode('utf-8')) for (x, y) in qs]
|
||||||
|
@ -380,7 +384,7 @@ def urlparse(url, scheme='', allow_fragments=True):
|
||||||
unicode-safe way to use urlparse.urlparse(). Pass in either str or unicode
|
unicode-safe way to use urlparse.urlparse(). Pass in either str or unicode
|
||||||
CAREFUL: returns an encoded urlparse.ParseResult()!
|
CAREFUL: returns an encoded urlparse.ParseResult()!
|
||||||
"""
|
"""
|
||||||
if isinstance(url, unicode):
|
if isinstance(url, str):
|
||||||
url = url.encode('utf-8')
|
url = url.encode('utf-8')
|
||||||
return _urlparse.urlparse(url, scheme, allow_fragments)
|
return _urlparse.urlparse(url, scheme, allow_fragments)
|
||||||
|
|
||||||
|
@ -404,13 +408,13 @@ def escape_path(path, safe_url_char=SAFE_URL_CHARACTERS):
|
||||||
user = is_http_dav_ftp.group(6)
|
user = is_http_dav_ftp.group(6)
|
||||||
psswd = is_http_dav_ftp.group(7)
|
psswd = is_http_dav_ftp.group(7)
|
||||||
if user and psswd:
|
if user and psswd:
|
||||||
user = urllib.quote(user.encode('utf-8'), safe=safe_url_char).decode('utf-8')
|
user = urllib.parse.quote(user.encode('utf-8'), safe=safe_url_char).decode('utf-8')
|
||||||
psswd = urllib.quote(psswd.encode('utf-8'), safe=safe_url_char).decode('utf-8')
|
psswd = urllib.parse.quote(psswd.encode('utf-8'), safe=safe_url_char).decode('utf-8')
|
||||||
host = is_http_dav_ftp.group(8)
|
host = is_http_dav_ftp.group(8)
|
||||||
port = is_http_dav_ftp.group(10)
|
port = is_http_dav_ftp.group(10)
|
||||||
url_path = path.replace(is_http_dav_ftp.group(), '', 1)
|
url_path = path.replace(is_http_dav_ftp.group(), '', 1)
|
||||||
if url_path:
|
if url_path:
|
||||||
url_path = urllib.quote(path.replace(is_http_dav_ftp.group(), '', 1).encode('utf-8'),
|
url_path = urllib.parse.quote(path.replace(is_http_dav_ftp.group(), '', 1).encode('utf-8'),
|
||||||
safe=safe_url_char).decode('utf-8')
|
safe=safe_url_char).decode('utf-8')
|
||||||
return protocol + \
|
return protocol + \
|
||||||
u'://' + \
|
u'://' + \
|
||||||
|
@ -422,7 +426,7 @@ def escape_path(path, safe_url_char=SAFE_URL_CHARACTERS):
|
||||||
else:
|
else:
|
||||||
# If paths does not seem to be a http(s), dav(s) or (s)ftp url (e.g. plugin://)
|
# If paths does not seem to be a http(s), dav(s) or (s)ftp url (e.g. plugin://)
|
||||||
# escape path as before
|
# escape path as before
|
||||||
return urllib.quote(path.encode('utf-8'),
|
return urllib.parse.quote(path.encode('utf-8'),
|
||||||
safe=SAFE_URL_CHARACTERS).decode('utf-8')
|
safe=SAFE_URL_CHARACTERS).decode('utf-8')
|
||||||
|
|
||||||
|
|
||||||
|
@ -431,9 +435,9 @@ def quote(s, safe='/'):
|
||||||
unicode-safe way to use urllib.quote(). Pass in either str or unicode
|
unicode-safe way to use urllib.quote(). Pass in either str or unicode
|
||||||
Returns unicode
|
Returns unicode
|
||||||
"""
|
"""
|
||||||
if isinstance(s, unicode):
|
if isinstance(s, str):
|
||||||
s = s.encode('utf-8')
|
s = s.encode('utf-8')
|
||||||
s = urllib.quote(s, safe.encode('utf-8'))
|
s = urllib.parse.quote(s, safe.encode('utf-8'))
|
||||||
return s.decode('utf-8')
|
return s.decode('utf-8')
|
||||||
|
|
||||||
|
|
||||||
|
@ -442,9 +446,9 @@ def quote_plus(s, safe=''):
|
||||||
unicode-safe way to use urllib.quote(). Pass in either str or unicode
|
unicode-safe way to use urllib.quote(). Pass in either str or unicode
|
||||||
Returns unicode
|
Returns unicode
|
||||||
"""
|
"""
|
||||||
if isinstance(s, unicode):
|
if isinstance(s, str):
|
||||||
s = s.encode('utf-8')
|
s = s.encode('utf-8')
|
||||||
s = urllib.quote_plus(s, safe.encode('utf-8'))
|
s = urllib.parse.quote_plus(s, safe.encode('utf-8'))
|
||||||
return s.decode('utf-8')
|
return s.decode('utf-8')
|
||||||
|
|
||||||
|
|
||||||
|
@ -453,9 +457,9 @@ def unquote(s):
|
||||||
unicode-safe way to use urllib.unquote(). Pass in either str or unicode
|
unicode-safe way to use urllib.unquote(). Pass in either str or unicode
|
||||||
Returns unicode
|
Returns unicode
|
||||||
"""
|
"""
|
||||||
if isinstance(s, unicode):
|
if isinstance(s, str):
|
||||||
s = s.encode('utf-8')
|
s = s.encode('utf-8')
|
||||||
s = urllib.unquote(s)
|
s = urllib.parse.unquote(s)
|
||||||
return s.decode('utf-8')
|
return s.decode('utf-8')
|
||||||
|
|
||||||
|
|
||||||
|
@ -481,7 +485,7 @@ def try_decode(string, encoding='utf-8'):
|
||||||
fails with e.g. Android TV's Python, which does not accept arguments for
|
fails with e.g. Android TV's Python, which does not accept arguments for
|
||||||
string.encode()
|
string.encode()
|
||||||
"""
|
"""
|
||||||
if isinstance(string, unicode):
|
if isinstance(string, str):
|
||||||
# already decoded
|
# already decoded
|
||||||
return string
|
return string
|
||||||
try:
|
try:
|
||||||
|
@ -496,9 +500,9 @@ def slugify(text):
|
||||||
Normalizes text (in unicode or string) to e.g. enable safe filenames.
|
Normalizes text (in unicode or string) to e.g. enable safe filenames.
|
||||||
Returns unicode
|
Returns unicode
|
||||||
"""
|
"""
|
||||||
if not isinstance(text, unicode):
|
if not isinstance(text, str):
|
||||||
text = unicode(text)
|
text = str(text)
|
||||||
return unicode(normalize('NFKD', text).encode('ascii', 'ignore'))
|
return str(normalize('NFKD', text).encode('ascii', 'ignore'))
|
||||||
|
|
||||||
|
|
||||||
def valid_filename(text):
|
def valid_filename(text):
|
||||||
|
@ -542,7 +546,7 @@ def escape_html(string):
|
||||||
'>': '>',
|
'>': '>',
|
||||||
'&': '&'
|
'&': '&'
|
||||||
}
|
}
|
||||||
for key, value in escapes.iteritems():
|
for key, value in escapes.items():
|
||||||
string = string.replace(key, value)
|
string = string.replace(key, value)
|
||||||
return string
|
return string
|
||||||
|
|
||||||
|
@ -690,7 +694,7 @@ def normalize_string(text):
|
||||||
# Remove dots from the last character as windows can not have directories
|
# Remove dots from the last character as windows can not have directories
|
||||||
# with dots at the end
|
# with dots at the end
|
||||||
text = text.rstrip('.')
|
text = text.rstrip('.')
|
||||||
text = try_encode(normalize('NFKD', unicode(text, 'utf-8')))
|
text = try_encode(normalize('NFKD', str(text, 'utf-8')))
|
||||||
|
|
||||||
return text
|
return text
|
||||||
|
|
||||||
|
@ -713,7 +717,7 @@ def normalize_nodes(text):
|
||||||
# Remove dots from the last character as windows can not have directories
|
# Remove dots from the last character as windows can not have directories
|
||||||
# with dots at the end
|
# with dots at the end
|
||||||
text = text.rstrip('.')
|
text = text.rstrip('.')
|
||||||
text = normalize('NFKD', unicode(text, 'utf-8'))
|
text = normalize('NFKD', str(text, 'utf-8'))
|
||||||
return text
|
return text
|
||||||
|
|
||||||
|
|
||||||
|
@ -936,7 +940,7 @@ class XmlKodiSetting(object):
|
||||||
# Write new values
|
# Write new values
|
||||||
element.text = value
|
element.text = value
|
||||||
if attrib:
|
if attrib:
|
||||||
for key, attribute in attrib.iteritems():
|
for key, attribute in attrib.items():
|
||||||
element.set(key, attribute)
|
element.set(key, attribute)
|
||||||
return element
|
return element
|
||||||
|
|
||||||
|
@ -958,7 +962,7 @@ def process_method_on_list(method_to_run, items):
|
||||||
pool.join()
|
pool.join()
|
||||||
else:
|
else:
|
||||||
all_items = [method_to_run(item) for item in items]
|
all_items = [method_to_run(item) for item in items]
|
||||||
all_items = filter(None, all_items)
|
all_items = [_f for _f in all_items if _f]
|
||||||
return all_items
|
return all_items
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ def try_decode(string, encoding='utf-8'):
|
||||||
fails with e.g. Android TV's Python, which does not accept arguments for
|
fails with e.g. Android TV's Python, which does not accept arguments for
|
||||||
string.encode()
|
string.encode()
|
||||||
"""
|
"""
|
||||||
if isinstance(string, unicode):
|
if isinstance(string, str):
|
||||||
# already decoded
|
# already decoded
|
||||||
return string
|
return string
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -85,6 +85,7 @@ Event Handler Classes
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from builtins import object
|
||||||
import os.path
|
import os.path
|
||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
from builtins import object
|
||||||
from __future__ import with_statement
|
from __future__ import with_statement
|
||||||
import threading
|
import threading
|
||||||
from ..utils import BaseThread
|
from ..utils import BaseThread
|
||||||
|
|
|
@ -150,7 +150,7 @@ class FSEventsObserver(BaseObserver):
|
||||||
def schedule(self, event_handler, path, recursive=False):
|
def schedule(self, event_handler, path, recursive=False):
|
||||||
# Python 2/3 compat
|
# Python 2/3 compat
|
||||||
try:
|
try:
|
||||||
str_class = unicode
|
str_class = str
|
||||||
except NameError:
|
except NameError:
|
||||||
str_class = str
|
str_class = str
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,11 @@
|
||||||
:synopsis: FSEvents based emitter implementation.
|
:synopsis: FSEvents based emitter implementation.
|
||||||
:platforms: Mac OS X
|
:platforms: Mac OS X
|
||||||
"""
|
"""
|
||||||
|
from __future__ import absolute_import
|
||||||
|
|
||||||
|
from builtins import hex
|
||||||
|
from builtins import zip
|
||||||
|
from builtins import object
|
||||||
import os
|
import os
|
||||||
import logging
|
import logging
|
||||||
import unicodedata
|
import unicodedata
|
||||||
|
@ -45,7 +49,7 @@ from ..observers.api import (
|
||||||
|
|
||||||
# pyobjc
|
# pyobjc
|
||||||
import AppKit
|
import AppKit
|
||||||
from FSEvents import (
|
from .FSEvents import (
|
||||||
FSEventStreamCreate,
|
FSEventStreamCreate,
|
||||||
CFRunLoopGetCurrent,
|
CFRunLoopGetCurrent,
|
||||||
FSEventStreamScheduleWithRunLoop,
|
FSEventStreamScheduleWithRunLoop,
|
||||||
|
@ -57,7 +61,7 @@ from FSEvents import (
|
||||||
FSEventStreamRelease,
|
FSEventStreamRelease,
|
||||||
)
|
)
|
||||||
|
|
||||||
from FSEvents import (
|
from .FSEvents import (
|
||||||
kCFAllocatorDefault,
|
kCFAllocatorDefault,
|
||||||
kCFRunLoopDefaultMode,
|
kCFRunLoopDefaultMode,
|
||||||
kFSEventStreamEventIdSinceNow,
|
kFSEventStreamEventIdSinceNow,
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
from builtins import object
|
||||||
from __future__ import with_statement
|
from __future__ import with_statement
|
||||||
import os
|
import os
|
||||||
import errno
|
import errno
|
||||||
|
|
|
@ -77,6 +77,7 @@ Collections and Utility Classes
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from builtins import object
|
||||||
from __future__ import with_statement
|
from __future__ import with_statement
|
||||||
from ..utils import platform
|
from ..utils import platform
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
# Portions of this code were taken from pyfilesystem, which uses the above
|
# Portions of this code were taken from pyfilesystem, which uses the above
|
||||||
# new BSD license.
|
# new BSD license.
|
||||||
|
|
||||||
|
from builtins import object
|
||||||
from __future__ import with_statement
|
from __future__ import with_statement
|
||||||
|
|
||||||
import ctypes.wintypes
|
import ctypes.wintypes
|
||||||
|
@ -308,7 +309,7 @@ def read_directory_changes(handle, recursive):
|
||||||
|
|
||||||
# Python 2/3 compat
|
# Python 2/3 compat
|
||||||
try:
|
try:
|
||||||
int_class = long
|
int_class = int
|
||||||
except NameError:
|
except NameError:
|
||||||
int_class = int
|
int_class = int
|
||||||
return event_buffer.raw, int_class(nbytes.value)
|
return event_buffer.raw, int_class(nbytes.value)
|
||||||
|
|
|
@ -30,6 +30,7 @@ Classes
|
||||||
:inherited-members:
|
:inherited-members:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
from __future__ import absolute_import
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import threading
|
import threading
|
||||||
|
@ -39,7 +40,7 @@ from .compat import Event
|
||||||
|
|
||||||
if sys.version_info[0] == 2 and platform.is_windows():
|
if sys.version_info[0] == 2 and platform.is_windows():
|
||||||
# st_ino is not implemented in os.stat on this platform
|
# st_ino is not implemented in os.stat on this platform
|
||||||
import win32stat
|
from . import win32stat
|
||||||
stat = win32stat.stat
|
stat = win32stat.stat
|
||||||
else:
|
else:
|
||||||
stat = os.stat
|
stat = os.stat
|
||||||
|
|
|
@ -36,6 +36,8 @@ Classes
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from builtins import next
|
||||||
|
from builtins import range
|
||||||
import sys
|
import sys
|
||||||
import collections
|
import collections
|
||||||
from .compat import queue
|
from .compat import queue
|
||||||
|
|
|
@ -13,6 +13,8 @@
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
from future import standard_library
|
||||||
|
standard_library.install_aliases()
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
__all__ = ['queue', 'Event']
|
__all__ = ['queue', 'Event']
|
||||||
|
@ -20,7 +22,7 @@ __all__ = ['queue', 'Event']
|
||||||
try:
|
try:
|
||||||
import queue
|
import queue
|
||||||
except ImportError:
|
except ImportError:
|
||||||
import Queue as queue
|
import queue as queue
|
||||||
|
|
||||||
|
|
||||||
if sys.version_info < (2, 7):
|
if sys.version_info < (2, 7):
|
||||||
|
|
|
@ -14,6 +14,7 @@ decorators:
|
||||||
- deprecated
|
- deprecated
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from builtins import zip
|
||||||
import functools
|
import functools
|
||||||
import warnings
|
import warnings
|
||||||
import threading
|
import threading
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
from builtins import object
|
||||||
import time
|
import time
|
||||||
import threading
|
import threading
|
||||||
from collections import deque
|
from collections import deque
|
||||||
|
|
|
@ -44,6 +44,8 @@ Classes
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from builtins import str
|
||||||
|
from builtins import object
|
||||||
import errno
|
import errno
|
||||||
import os
|
import os
|
||||||
from stat import S_ISDIR
|
from stat import S_ISDIR
|
||||||
|
|
|
@ -32,6 +32,8 @@ Example:
|
||||||
def my_function(args):
|
def my_function(args):
|
||||||
pass
|
pass
|
||||||
"""
|
"""
|
||||||
|
from builtins import map
|
||||||
|
from builtins import zip
|
||||||
import inspect
|
import inspect
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Backport of Event from py2.7 (method wait in py2.6 returns None)
|
# Backport of Event from py2.7 (method wait in py2.6 returns None)
|
||||||
|
|
||||||
|
from builtins import object
|
||||||
from threading import Condition, Lock
|
from threading import Condition, Lock
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ def import_module(target, relative_to=None):
|
||||||
relative_parts = relative_to.split('.')
|
relative_parts = relative_to.split('.')
|
||||||
relative_to = '.'.join(relative_parts[:-(target_depth - 1) or None])
|
relative_to = '.'.join(relative_parts[:-(target_depth - 1) or None])
|
||||||
if len(target_path) > 1:
|
if len(target_path) > 1:
|
||||||
relative_to = '.'.join(filter(None, [relative_to]) + target_path[:-1])
|
relative_to = '.'.join([_f for _f in [relative_to] if _f] + target_path[:-1])
|
||||||
fromlist = target_path[-1:]
|
fromlist = target_path[-1:]
|
||||||
target = fromlist[0]
|
target = fromlist[0]
|
||||||
elif not relative_to:
|
elif not relative_to:
|
||||||
|
|
|
@ -28,7 +28,7 @@ from . import platform
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Python 2
|
# Python 2
|
||||||
str_cls = unicode
|
str_cls = str
|
||||||
bytes_cls = str
|
bytes_cls = str
|
||||||
except NameError:
|
except NameError:
|
||||||
# Python 3
|
# Python 3
|
||||||
|
|
|
@ -24,7 +24,9 @@ Functions
|
||||||
.. autofunction:: stat
|
.. autofunction:: stat
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
from __future__ import division
|
||||||
|
|
||||||
|
from past.utils import old_div
|
||||||
import ctypes
|
import ctypes
|
||||||
import ctypes.wintypes
|
import ctypes.wintypes
|
||||||
import stat as stdstat
|
import stat as stdstat
|
||||||
|
@ -99,7 +101,7 @@ def _to_mode(attr):
|
||||||
|
|
||||||
def _to_unix_time(ft):
|
def _to_unix_time(ft):
|
||||||
t = (ft.dwHighDateTime) << 32 | ft.dwLowDateTime
|
t = (ft.dwHighDateTime) << 32 | ft.dwLowDateTime
|
||||||
return (t / 10000000) - 11644473600
|
return (old_div(t, 10000000)) - 11644473600
|
||||||
|
|
||||||
def stat(path):
|
def stat(path):
|
||||||
hfile = CreateFile(path,
|
hfile = CreateFile(path,
|
||||||
|
|
|
@ -22,6 +22,8 @@
|
||||||
:synopsis: ``watchmedo`` shell script utility.
|
:synopsis: ``watchmedo`` shell script utility.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from future import standard_library
|
||||||
|
standard_library.install_aliases()
|
||||||
import os.path
|
import os.path
|
||||||
import sys
|
import sys
|
||||||
import yaml
|
import yaml
|
||||||
|
@ -29,10 +31,10 @@ import time
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from cStringIO import StringIO
|
from io import StringIO
|
||||||
except ImportError:
|
except ImportError:
|
||||||
try:
|
try:
|
||||||
from StringIO import StringIO
|
from io import StringIO
|
||||||
except ImportError:
|
except ImportError:
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,12 @@ Copyright (C) 2010 Hiroki Ohtani(liris)
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
from future import standard_library
|
||||||
|
standard_library.install_aliases()
|
||||||
|
from builtins import str
|
||||||
|
from builtins import chr
|
||||||
|
from builtins import range
|
||||||
|
from builtins import object
|
||||||
import socket
|
import socket
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -35,7 +41,7 @@ except ImportError:
|
||||||
|
|
||||||
HAVE_SSL = False
|
HAVE_SSL = False
|
||||||
|
|
||||||
from urlparse import urlparse
|
from urllib.parse import urlparse
|
||||||
import os
|
import os
|
||||||
import array
|
import array
|
||||||
import struct
|
import struct
|
||||||
|
@ -228,7 +234,7 @@ def create_connection(url, timeout=None, **options):
|
||||||
|
|
||||||
|
|
||||||
_MAX_INTEGER = (1 << 32) - 1
|
_MAX_INTEGER = (1 << 32) - 1
|
||||||
_AVAILABLE_KEY_CHARS = range(0x21, 0x2f + 1) + range(0x3a, 0x7e + 1)
|
_AVAILABLE_KEY_CHARS = list(range(0x21, 0x2f + 1)) + list(range(0x3a, 0x7e + 1))
|
||||||
_MAX_CHAR_BYTE = (1 << 8) - 1
|
_MAX_CHAR_BYTE = (1 << 8) - 1
|
||||||
|
|
||||||
# ref. Websocket gets an update, and it breaks stuff.
|
# ref. Websocket gets an update, and it breaks stuff.
|
||||||
|
@ -308,7 +314,7 @@ class ABNF(object):
|
||||||
|
|
||||||
opcode: operation code. please see OPCODE_XXX.
|
opcode: operation code. please see OPCODE_XXX.
|
||||||
"""
|
"""
|
||||||
if opcode == ABNF.OPCODE_TEXT and isinstance(data, unicode):
|
if opcode == ABNF.OPCODE_TEXT and isinstance(data, str):
|
||||||
data = utils.try_encode(data)
|
data = utils.try_encode(data)
|
||||||
# mask must be set if send data from client
|
# mask must be set if send data from client
|
||||||
return ABNF(1, 0, 0, 0, opcode, 1, data)
|
return ABNF(1, 0, 0, 0, opcode, 1, data)
|
||||||
|
@ -358,7 +364,7 @@ class ABNF(object):
|
||||||
"""
|
"""
|
||||||
_m = array.array("B", mask_key)
|
_m = array.array("B", mask_key)
|
||||||
_d = array.array("B", data)
|
_d = array.array("B", data)
|
||||||
for i in xrange(len(_d)):
|
for i in range(len(_d)):
|
||||||
_d[i] ^= _m[i % 4]
|
_d[i] ^= _m[i % 4]
|
||||||
return _d.tostring()
|
return _d.tostring()
|
||||||
|
|
||||||
|
@ -529,7 +535,7 @@ class WebSocket(object):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _validate_header(headers, key):
|
def _validate_header(headers, key):
|
||||||
for k, v in _HEADERS_TO_CHECK.iteritems():
|
for k, v in _HEADERS_TO_CHECK.items():
|
||||||
r = headers.get(k, None)
|
r = headers.get(k, None)
|
||||||
if not r:
|
if not r:
|
||||||
return False
|
return False
|
||||||
|
@ -882,11 +888,11 @@ class WebSocketApp(object):
|
||||||
if data is None or self.keep_running is False:
|
if data is None or self.keep_running is False:
|
||||||
break
|
break
|
||||||
self._callback(self.on_message, data)
|
self._callback(self.on_message, data)
|
||||||
except Exception, e:
|
except Exception as e:
|
||||||
if "timed out" not in e.args[0]:
|
if "timed out" not in e.args[0]:
|
||||||
raise e
|
raise e
|
||||||
|
|
||||||
except Exception, e:
|
except Exception as e:
|
||||||
self._callback(self.on_error, e)
|
self._callback(self.on_error, e)
|
||||||
finally:
|
finally:
|
||||||
if thread:
|
if thread:
|
||||||
|
@ -899,7 +905,7 @@ class WebSocketApp(object):
|
||||||
if callback:
|
if callback:
|
||||||
try:
|
try:
|
||||||
callback(self, *args)
|
callback(self, *args)
|
||||||
except Exception, e:
|
except Exception as e:
|
||||||
LOG.error(e)
|
LOG.error(e)
|
||||||
_, _, tb = sys.exc_info()
|
_, _, tb = sys.exc_info()
|
||||||
traceback.print_tb(tb)
|
traceback.print_tb(tb)
|
||||||
|
|
|
@ -7,6 +7,7 @@ Loads of different functions called in SEPARATE Python instances through
|
||||||
e.g. plugin://... calls. Hence be careful to only rely on window variables.
|
e.g. plugin://... calls. Hence be careful to only rely on window variables.
|
||||||
"""
|
"""
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
from builtins import str
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
|
|
||||||
import xbmc
|
import xbmc
|
||||||
|
@ -296,7 +297,7 @@ def prepare_listitem(item):
|
||||||
if "imdbnumber" not in properties and "imdbnumber" in item:
|
if "imdbnumber" not in properties and "imdbnumber" in item:
|
||||||
properties["imdbnumber"] = item["imdbnumber"]
|
properties["imdbnumber"] = item["imdbnumber"]
|
||||||
if "imdbnumber" not in properties and "uniqueid" in item:
|
if "imdbnumber" not in properties and "uniqueid" in item:
|
||||||
for value in item["uniqueid"].values():
|
for value in list(item["uniqueid"].values()):
|
||||||
if value.startswith("tt"):
|
if value.startswith("tt"):
|
||||||
properties["imdbnumber"] = value
|
properties["imdbnumber"] = value
|
||||||
|
|
||||||
|
@ -421,8 +422,8 @@ def prepare_listitem(item):
|
||||||
item["thumbnail"] = art["thumb"]
|
item["thumbnail"] = art["thumb"]
|
||||||
|
|
||||||
# clean art
|
# clean art
|
||||||
for key, value in art.iteritems():
|
for key, value in art.items():
|
||||||
if not isinstance(value, (str, unicode)):
|
if not isinstance(value, str):
|
||||||
art[key] = ""
|
art[key] = ""
|
||||||
elif value:
|
elif value:
|
||||||
art[key] = get_clean_image(value)
|
art[key] = get_clean_image(value)
|
||||||
|
@ -473,7 +474,7 @@ def create_listitem(item, as_tuple=True, offscreen=True,
|
||||||
nodetype = "Music"
|
nodetype = "Music"
|
||||||
|
|
||||||
# extra properties
|
# extra properties
|
||||||
for key, value in item["extraproperties"].iteritems():
|
for key, value in item["extraproperties"].items():
|
||||||
liz.setProperty(key, value)
|
liz.setProperty(key, value)
|
||||||
|
|
||||||
# video infolabels
|
# video infolabels
|
||||||
|
|
|
@ -6,10 +6,12 @@
|
||||||
e.g. smb paths
|
e.g. smb paths
|
||||||
"""
|
"""
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
from future import standard_library
|
||||||
|
standard_library.install_aliases()
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
import re
|
import re
|
||||||
import socket
|
import socket
|
||||||
import urllib
|
import urllib.request, urllib.parse, urllib.error
|
||||||
|
|
||||||
import xbmc
|
import xbmc
|
||||||
|
|
||||||
|
@ -156,7 +158,7 @@ def start():
|
||||||
xml.write_xml = False
|
xml.write_xml = False
|
||||||
return
|
return
|
||||||
user = user.strip()
|
user = user.strip()
|
||||||
user = urllib.quote(user)
|
user = urllib.parse.quote(user)
|
||||||
user = user.decode('utf-8')
|
user = user.decode('utf-8')
|
||||||
# "Password"
|
# "Password"
|
||||||
# May also be blank!! (=user aborts dialog)
|
# May also be blank!! (=user aborts dialog)
|
||||||
|
@ -165,7 +167,7 @@ def start():
|
||||||
'',
|
'',
|
||||||
type='{alphanum}',
|
type='{alphanum}',
|
||||||
option='{hide}')
|
option='{hide}')
|
||||||
password = urllib.quote(password)
|
password = urllib.parse.quote(password)
|
||||||
password = password.decode('utf-8')
|
password = password.decode('utf-8')
|
||||||
utils.etree.SubElement(entry,
|
utils.etree.SubElement(entry,
|
||||||
'from',
|
'from',
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
from builtins import zip
|
||||||
|
from builtins import str
|
||||||
|
from builtins import range
|
||||||
|
from builtins import object
|
||||||
import xbmc
|
import xbmc
|
||||||
import xbmcgui
|
import xbmcgui
|
||||||
import time
|
import time
|
||||||
|
@ -12,7 +16,7 @@ from .. import app
|
||||||
MONITOR = None
|
MONITOR = None
|
||||||
|
|
||||||
|
|
||||||
class BaseFunctions:
|
class BaseFunctions(object):
|
||||||
xmlFile = ''
|
xmlFile = ''
|
||||||
path = ''
|
path = ''
|
||||||
theme = ''
|
theme = ''
|
||||||
|
@ -187,7 +191,7 @@ class BaseDialog(xbmcgui.WindowXMLDialog, BaseFunctions):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class ControlledBase:
|
class ControlledBase(object):
|
||||||
def doModal(self):
|
def doModal(self):
|
||||||
self.show()
|
self.show()
|
||||||
self.wait()
|
self.wait()
|
||||||
|
@ -242,10 +246,10 @@ class ManagedListItem(object):
|
||||||
self._manager = None
|
self._manager = None
|
||||||
self._valid = True
|
self._valid = True
|
||||||
if properties:
|
if properties:
|
||||||
for k, v in properties.items():
|
for k, v in list(properties.items()):
|
||||||
self.setProperty(k, v)
|
self.setProperty(k, v)
|
||||||
|
|
||||||
def __nonzero__(self):
|
def __bool__(self):
|
||||||
return self._valid
|
return self._valid
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -281,7 +285,7 @@ class ManagedListItem(object):
|
||||||
self.listItem.setIconImage(self.iconImage)
|
self.listItem.setIconImage(self.iconImage)
|
||||||
self.listItem.setThumbnailImage(self.thumbnailImage)
|
self.listItem.setThumbnailImage(self.thumbnailImage)
|
||||||
self.listItem.setPath(self.path)
|
self.listItem.setPath(self.path)
|
||||||
for k in self._manager._properties.keys():
|
for k in list(self._manager._properties.keys()):
|
||||||
self.listItem.setProperty(k, self.properties.get(k) or '')
|
self.listItem.setProperty(k, self.properties.get(k) or '')
|
||||||
|
|
||||||
def clear(self):
|
def clear(self):
|
||||||
|
@ -615,9 +619,9 @@ class ManagedControlList(object):
|
||||||
def getViewRange(self):
|
def getViewRange(self):
|
||||||
viewPosition = self.getViewPosition()
|
viewPosition = self.getViewPosition()
|
||||||
selected = self.getSelectedPosition()
|
selected = self.getSelectedPosition()
|
||||||
return range(max(selected - viewPosition, 0),
|
return list(range(max(selected - viewPosition, 0),
|
||||||
min(selected + (self._maxViewIndex - viewPosition) + 1,
|
min(selected + (self._maxViewIndex - viewPosition) + 1,
|
||||||
self.size() - 1))
|
self.size() - 1)))
|
||||||
|
|
||||||
def positionIsValid(self, pos):
|
def positionIsValid(self, pos):
|
||||||
return 0 <= pos < self.size()
|
return 0 <= pos < self.size()
|
||||||
|
@ -751,7 +755,7 @@ class MultiWindow(object):
|
||||||
self._current.setProperty(key, value)
|
self._current.setProperty(key, value)
|
||||||
|
|
||||||
def _onFirstInit(self):
|
def _onFirstInit(self):
|
||||||
for k, v in self._properties.items():
|
for k, v in list(self._properties.items()):
|
||||||
self._current.setProperty(k, v)
|
self._current.setProperty(k, v)
|
||||||
self.onFirstInit()
|
self.onFirstInit()
|
||||||
|
|
||||||
|
@ -897,7 +901,7 @@ class SafeControlEdit(object):
|
||||||
self._setText(self.getText()[:-1])
|
self._setText(self.getText()[:-1])
|
||||||
|
|
||||||
|
|
||||||
class PropertyTimer():
|
class PropertyTimer(object):
|
||||||
def __init__(self, window_id, timeout, property_, value='', init_value='1', addon_id=None, callback=None):
|
def __init__(self, window_id, timeout, property_, value='', init_value='1', addon_id=None, callback=None):
|
||||||
self._winID = window_id
|
self._winID = window_id
|
||||||
self._timeout = timeout
|
self._timeout = timeout
|
||||||
|
@ -976,7 +980,7 @@ class PropertyTimer():
|
||||||
self._start()
|
self._start()
|
||||||
|
|
||||||
|
|
||||||
class WindowProperty():
|
class WindowProperty(object):
|
||||||
def __init__(self, win, prop, val='1', end=None):
|
def __init__(self, win, prop, val='1', end=None):
|
||||||
self.win = win
|
self.win = win
|
||||||
self.prop = prop
|
self.prop = prop
|
||||||
|
@ -995,7 +999,7 @@ class WindowProperty():
|
||||||
self.win.setProperty(self.prop, self.end or self.old)
|
self.win.setProperty(self.prop, self.end or self.old)
|
||||||
|
|
||||||
|
|
||||||
class GlobalProperty():
|
class GlobalProperty(object):
|
||||||
def __init__(self, prop, val='1', end=None):
|
def __init__(self, prop, val='1', end=None):
|
||||||
import xbmcaddon
|
import xbmcaddon
|
||||||
self._addonID = xbmcaddon.Addon().getAddonInfo('id')
|
self._addonID = xbmcaddon.Addon().getAddonInfo('id')
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
(home) users
|
(home) users
|
||||||
"""
|
"""
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
|
from builtins import str
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
import xbmc
|
import xbmc
|
||||||
import xbmcgui
|
import xbmcgui
|
||||||
|
|
Loading…
Reference in a new issue