mirror of
https://github.com/anxdpanic/plugin.video.youtube.git
synced 2025-12-06 02:30:50 -08:00
Python2 unicode fixes #668
This commit is contained in:
parent
516ca89696
commit
49df1d5eb3
6 changed files with 80 additions and 60 deletions
|
|
@ -15,6 +15,7 @@ __all__ = (
|
|||
'parse_qsl',
|
||||
'quote',
|
||||
'string_type',
|
||||
'to_str',
|
||||
'unescape',
|
||||
'unquote',
|
||||
'urlencode',
|
||||
|
|
@ -52,6 +53,7 @@ try:
|
|||
|
||||
string_type = str
|
||||
byte_string_type = bytes
|
||||
to_str = str
|
||||
# Compatibility shims for Kodi v18 and Python v2.7
|
||||
except ImportError:
|
||||
import BaseHTTPServer
|
||||
|
|
@ -79,23 +81,21 @@ except ImportError:
|
|||
|
||||
|
||||
def quote(data, *args, **kwargs):
|
||||
return _quote(data.encode('utf-8'), *args, **kwargs)
|
||||
return _quote(to_str(data), *args, **kwargs)
|
||||
|
||||
|
||||
def unquote(data):
|
||||
return _unquote(data.encode('utf-8'))
|
||||
return _unquote(to_str(data))
|
||||
|
||||
|
||||
def urlencode(data, *args, **kwargs):
|
||||
if isinstance(data, dict):
|
||||
data = data.items()
|
||||
return _urlencode({
|
||||
key.encode('utf-8'): (
|
||||
[part.encode('utf-8') if isinstance(part, unicode)
|
||||
else str(part)
|
||||
for part in value] if isinstance(value, (list, tuple))
|
||||
else value.encode('utf-8') if isinstance(value, unicode)
|
||||
else str(value)
|
||||
to_str(key): (
|
||||
[to_str(part) for part in value]
|
||||
if isinstance(value, (list, tuple)) else
|
||||
to_str(value)
|
||||
)
|
||||
for key, value in data
|
||||
}, *args, **kwargs)
|
||||
|
|
@ -121,6 +121,11 @@ except ImportError:
|
|||
string_type = basestring
|
||||
byte_string_type = (bytes, str)
|
||||
|
||||
def to_str(value):
|
||||
if isinstance(value, unicode):
|
||||
return value.encode('utf-8')
|
||||
return str(value)
|
||||
|
||||
# Kodi v20+
|
||||
if hasattr(xbmcgui.ListItem, 'setDateTime'):
|
||||
def datetime_infolabel(datetime_obj):
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ from __future__ import absolute_import, division, unicode_literals
|
|||
import os
|
||||
|
||||
from .. import logger
|
||||
from ..compatibility import urlencode
|
||||
from ..compatibility import to_str, urlencode
|
||||
from ..json_store import AccessManager
|
||||
from ..sql_store import (
|
||||
DataCache,
|
||||
|
|
@ -265,7 +265,7 @@ class AbstractContext(object):
|
|||
val for val in value.split(',') if val
|
||||
]
|
||||
elif param in self._STRING_PARAMS:
|
||||
parsed_value = str(value)
|
||||
parsed_value = to_str(value)
|
||||
# process and translate deprecated parameters
|
||||
if param == 'action':
|
||||
if parsed_value in ('play_all', 'play_video'):
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
from __future__ import absolute_import, division, unicode_literals
|
||||
|
||||
from .base_item import BaseItem
|
||||
from ..compatibility import unescape
|
||||
from ..compatibility import to_str, unescape
|
||||
|
||||
|
||||
class AudioItem(BaseItem):
|
||||
|
|
@ -54,7 +54,7 @@ class AudioItem(BaseItem):
|
|||
if self._artists is None:
|
||||
self._artists = []
|
||||
if artist:
|
||||
self._artists.append(str(artist))
|
||||
self._artists.append(to_str(artist))
|
||||
|
||||
def get_artists(self):
|
||||
return self._artists
|
||||
|
|
@ -72,7 +72,7 @@ class AudioItem(BaseItem):
|
|||
if self._genres is None:
|
||||
self._genres = []
|
||||
if genre:
|
||||
self._genres.append(str(genre))
|
||||
self._genres.append(to_str(genre))
|
||||
|
||||
def get_genres(self):
|
||||
return self._genres
|
||||
|
|
|
|||
|
|
@ -14,13 +14,12 @@ import json
|
|||
from datetime import date, datetime
|
||||
from hashlib import md5
|
||||
|
||||
from ..compatibility import datetime_infolabel, string_type, unescape
|
||||
from ..compatibility import datetime_infolabel, string_type, to_str, unescape
|
||||
from ..constants import MEDIA_PATH
|
||||
|
||||
|
||||
class BaseItem(object):
|
||||
VERSION = 3
|
||||
INFO_DATE = 'date' # (string) iso 8601
|
||||
|
||||
_playable = False
|
||||
|
||||
|
|
@ -48,43 +47,19 @@ class BaseItem(object):
|
|||
self._next_page = False
|
||||
|
||||
def __str__(self):
|
||||
name = self._name
|
||||
uri = self._uri
|
||||
image = self._image
|
||||
obj_str = "------------------------------\n'%s'\nURI: %s\nImage: %s\n------------------------------" % (name, uri, image)
|
||||
return obj_str
|
||||
return ('------------------------------\n'
|
||||
'Name: |{0}|\n'
|
||||
'URI: |{1}|\n'
|
||||
'Image: |{2}|\n'
|
||||
'------------------------------'.format(self._name,
|
||||
self._uri,
|
||||
self._image))
|
||||
|
||||
def to_dict(self):
|
||||
return {'type': self.__class__.__name__, 'data': self.__dict__}
|
||||
|
||||
def dumps(self):
|
||||
def _encoder(obj):
|
||||
if isinstance(obj, (date, datetime)):
|
||||
class_name = obj.__class__.__name__
|
||||
|
||||
if 'fromisoformat' in dir(obj):
|
||||
return {
|
||||
'__class__': class_name,
|
||||
'__isoformat__': obj.isoformat(),
|
||||
}
|
||||
|
||||
if class_name == 'datetime':
|
||||
if obj.tzinfo:
|
||||
format_string = '%Y-%m-%dT%H:%M:%S%z'
|
||||
else:
|
||||
format_string = '%Y-%m-%dT%H:%M:%S'
|
||||
else:
|
||||
format_string = '%Y-%m-%d'
|
||||
|
||||
return {
|
||||
'__class__': class_name,
|
||||
'__format_string__': format_string,
|
||||
'__value__': obj.strftime(format_string)
|
||||
}
|
||||
|
||||
return json.JSONEncoder().default(obj)
|
||||
|
||||
return json.dumps(self.to_dict(), ensure_ascii=False, default=_encoder)
|
||||
return json.dumps(self.to_dict(), ensure_ascii=False, cls=_Encoder)
|
||||
|
||||
def get_id(self):
|
||||
"""
|
||||
|
|
@ -230,5 +205,43 @@ class BaseItem(object):
|
|||
self._next_page = bool(value)
|
||||
|
||||
@property
|
||||
def playable(cls):
|
||||
return cls._playable
|
||||
def playable(self):
|
||||
return self._playable
|
||||
|
||||
|
||||
class _Encoder(json.JSONEncoder):
|
||||
def encode(self, obj):
|
||||
if isinstance(obj, string_type):
|
||||
return to_str(obj)
|
||||
|
||||
if isinstance(obj, dict):
|
||||
return {to_str(key): self.encode(value)
|
||||
for key, value in obj.items()}
|
||||
|
||||
if isinstance(obj, (list, tuple)):
|
||||
return [self.encode(item) for item in obj]
|
||||
|
||||
if isinstance(obj, (date, datetime)):
|
||||
class_name = obj.__class__.__name__
|
||||
|
||||
if 'fromisoformat' in dir(obj):
|
||||
return {
|
||||
'__class__': class_name,
|
||||
'__isoformat__': obj.isoformat(),
|
||||
}
|
||||
|
||||
if class_name == 'datetime':
|
||||
if obj.tzinfo:
|
||||
format_string = '%Y-%m-%dT%H:%M:%S%z'
|
||||
else:
|
||||
format_string = '%Y-%m-%dT%H:%M:%S'
|
||||
else:
|
||||
format_string = '%Y-%m-%d'
|
||||
|
||||
return {
|
||||
'__class__': class_name,
|
||||
'__format_string__': format_string,
|
||||
'__value__': obj.strftime(format_string)
|
||||
}
|
||||
|
||||
return self.iterencode(obj)
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import datetime
|
|||
import re
|
||||
|
||||
from .base_item import BaseItem
|
||||
from ..compatibility import datetime_infolabel, unescape
|
||||
from ..compatibility import datetime_infolabel, to_str, unescape
|
||||
from ..utils import duration_to_seconds, seconds_to_duration
|
||||
|
||||
|
||||
|
|
@ -71,7 +71,7 @@ class VideoItem(BaseItem):
|
|||
if self._artists is None:
|
||||
self._artists = []
|
||||
if artist:
|
||||
self._artists.append(str(artist))
|
||||
self._artists.append(to_str(artist))
|
||||
|
||||
def get_artists(self):
|
||||
return self._artists
|
||||
|
|
@ -83,7 +83,7 @@ class VideoItem(BaseItem):
|
|||
if self._studios is None:
|
||||
self._studios = []
|
||||
if studio:
|
||||
self._studios.append(str(studio))
|
||||
self._studios.append(to_str(studio))
|
||||
|
||||
def get_studios(self):
|
||||
return self._studios
|
||||
|
|
@ -156,7 +156,7 @@ class VideoItem(BaseItem):
|
|||
if self._directors is None:
|
||||
self._directors = []
|
||||
if director:
|
||||
self._directors.append(str(director))
|
||||
self._directors.append(to_str(director))
|
||||
|
||||
def get_directors(self):
|
||||
return self._directors
|
||||
|
|
@ -169,10 +169,10 @@ class VideoItem(BaseItem):
|
|||
self._cast = []
|
||||
if member:
|
||||
self._cast.append({
|
||||
'member': str(member),
|
||||
'role': str(role) if role else '',
|
||||
'member': to_str(member),
|
||||
'role': to_str(role) if role else '',
|
||||
'order': int(order) if order else len(self._cast) + 1,
|
||||
'thumbnail': str(thumbnail) if thumbnail else '',
|
||||
'thumbnail': to_str(thumbnail) if thumbnail else '',
|
||||
})
|
||||
|
||||
def get_cast(self):
|
||||
|
|
@ -262,7 +262,7 @@ class VideoItem(BaseItem):
|
|||
if self._genres is None:
|
||||
self._genres = []
|
||||
if genre:
|
||||
self._genres.append(str(genre))
|
||||
self._genres.append(to_str(genre))
|
||||
|
||||
def get_genres(self):
|
||||
return self._genres
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ from random import randint
|
|||
from .login_client import LoginClient
|
||||
from ..helper.video_info import VideoInfo
|
||||
from ..youtube_exceptions import InvalidJSON, YouTubeException
|
||||
from ...kodion.compatibility import string_type
|
||||
from ...kodion.compatibility import string_type, to_str
|
||||
from ...kodion.utils import (
|
||||
current_system_version,
|
||||
datetime_parser,
|
||||
|
|
@ -1542,13 +1542,15 @@ class YouTube(LoginClient):
|
|||
for thread in threads:
|
||||
thread.join(30)
|
||||
|
||||
do_encode = not current_system_version.compatible(19, 0)
|
||||
|
||||
for response in responses:
|
||||
if response:
|
||||
response.encoding = 'utf-8'
|
||||
xml_data = to_unicode(response.content)
|
||||
xml_data = xml_data.replace('\n', '')
|
||||
if not current_system_version.compatible(19, 0):
|
||||
xml_data = xml_data.encode('utf-8')
|
||||
if do_encode:
|
||||
xml_data = to_str(xml_data)
|
||||
|
||||
root = ET.fromstring(xml_data)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue