Browse Source

Convert between str-unicode on app bounds, fixes #57

doc-issue-template
MrS0m30n3 8 years ago
parent
commit
638d4e70ed
6 changed files with 109 additions and 41 deletions
  1. 1
      youtube_dl_gui/__init__.py
  2. 7
      youtube_dl_gui/downloadmanager.py
  3. 7
      youtube_dl_gui/logmanager.py
  4. 7
      youtube_dl_gui/optionsframe.py
  5. 6
      youtube_dl_gui/optionsmanager.py
  6. 122
      youtube_dl_gui/utils.py

1
youtube_dl_gui/__init__.py

@ -17,7 +17,6 @@ Example:
from __future__ import unicode_literals
import sys
import os.path
import gettext
try:

7
youtube_dl_gui/downloadmanager.py

@ -37,7 +37,10 @@ from .parsers import OptionsParser
from .updatemanager import UpdateThread
from .downloaders import YoutubeDLDownloader
from .utils import YOUTUBEDL_BIN
from .utils import (
YOUTUBEDL_BIN,
os_path_exists
)
MANAGER_PUB_TOPIC = 'dlmanager'
@ -201,7 +204,7 @@ class DownloadManager(Thread):
def _check_youtubedl(self):
"""Check if youtube-dl binary exists. If not try to download it. """
if not os.path.exists(self._youtubedl_path()):
if not os_path_exists(self._youtubedl_path()):
UpdateThread(self.opt_manager.options['youtubedl_path'], True).join()
def _jobs_done(self):

7
youtube_dl_gui/logmanager.py

@ -9,6 +9,7 @@ import os.path
from time import strftime
from .utils import (
os_path_exists,
get_encoding,
check_path
)
@ -35,7 +36,7 @@ class LogManager(object):
LOG_FILENAME = "log"
TIME_TEMPLATE = "[{time}] {error_msg}"
MAX_LOGSIZE = 524288
MAX_LOGSIZE = 524288 # Bytes
def __init__(self, config_path, add_time=False):
self.config_path = config_path
@ -47,7 +48,7 @@ class LogManager(object):
def log_size(self):
"""Return log file size in Bytes. """
if not os.path.exists(self.log_file):
if not os_path_exists(self.log_file):
return 0
return os.path.getsize(self.log_file)
@ -88,7 +89,7 @@ class LogManager(object):
def _init_log(self):
"""Initialize the log file if not exist. """
if not os.path.exists(self.log_file):
if not os_path_exists(self.log_file):
self._write('', 'w')
def _auto_clear_log(self):

7
youtube_dl_gui/optionsframe.py

@ -20,7 +20,10 @@ from .info import (
__author__
)
from .utils import TwoWayOrderedDict as twodict
from .utils import (
TwoWayOrderedDict as twodict,
os_path_exists
)
class OptionsFrame(wx.Frame):
@ -1493,5 +1496,5 @@ class LogGUI(wx.Frame):
def load(self, filename):
"""Load file content on the text area. """
if os.path.exists(filename):
if os_path_exists(filename):
self._text_area.LoadFile(filename)

6
youtube_dl_gui/optionsmanager.py

@ -9,6 +9,8 @@ import json
import os.path
from .utils import (
os_path_expanduser,
os_path_exists,
encode_tuple,
decode_tuple,
check_path
@ -198,7 +200,7 @@ class OptionsManager(object):
"""
self.options = {
'save_path': os.path.expanduser('~'),
'save_path': os_path_expanduser('~'),
'video_format': '0',
'second_video_format': '0',
'to_audio': False,
@ -246,7 +248,7 @@ class OptionsManager(object):
def load_from_file(self):
"""Load options from settings file. """
if not os.path.exists(self.settings_file):
if not os_path_exists(self.settings_file):
return
with open(self.settings_file, 'rb') as settings_file:

122
youtube_dl_gui/utils.py

@ -29,21 +29,91 @@ if os.name == 'nt':
YOUTUBEDL_BIN += '.exe'
def get_encoding():
"""Return system encoding. """
try:
encoding = locale.getpreferredencoding()
'TEST'.encode(encoding)
except:
encoding = 'UTF-8'
return encoding
def convert_on_bounds(func):
"""Decorator to convert string inputs & outputs.
Covert string inputs & outputs between 'str' and 'unicode' at the
application bounds using the preferred system encoding. It will convert
all the string params (args, kwargs) to 'str' type and all the
returned strings values back to 'unicode'.
"""
def convert_item(item, to_unicode=False):
"""The actual function which handles the conversion.
Args:
item (-): Can be any python item.
to_unicode (boolean): When True it will convert all the 'str' types
to 'unicode'. When False it will convert all the 'unicode'
types back to 'str'.
"""
if to_unicode and isinstance(item, str):
# Convert str to unicode
return item.decode(get_encoding(), 'ignore')
if not to_unicode and isinstance(item, unicode):
# Convert unicode to str
return item.encode(get_encoding(), 'ignore')
if hasattr(item, '__iter__'):
# Handle iterables
temp_list = []
for sub_item in item:
if isinstance(item, dict):
temp_list.append((sub_item, covert_item(item[sub_item])))
else:
temp_list.append(convert_item(sub_item))
return type(item)(temp_list)
return item
def wrapper(*args, **kwargs):
returned_value = func(*convert_item(args), **convert_item(kwargs))
return convert_item(returned_value, True)
return wrapper
# See: https://github.com/MrS0m30n3/youtube-dl-gui/issues/57
# Patch os functions to convert between 'str' and 'unicode' on app bounds
os_getenv = convert_on_bounds(os.getenv)
os_makedirs = convert_on_bounds(os.makedirs)
os_path_isdir = convert_on_bounds(os.path.isdir)
os_path_exists = convert_on_bounds(os.path.exists)
os_path_dirname = convert_on_bounds(os.path.dirname)
os_path_abspath = convert_on_bounds(os.path.abspath)
os_path_realpath = convert_on_bounds(os.path.realpath)
os_path_expanduser = convert_on_bounds(os.path.expanduser)
# Patch Windows specific functions
if os.name == 'nt':
os_startfile = convert_on_bounds(os.startfile)
def remove_shortcuts(path):
"""Return given path after removing the shortcuts. """
path = path.replace('~', os.path.expanduser('~'))
return path
return path.replace('~', os_path_expanduser('~'))
def absolute_path(filename):
"""Return absolute path to the given file. """
path = os.path.realpath(os.path.abspath(filename))
return os.path.dirname(path).decode(get_encoding(), 'ignore')
def get_lib_path():
"""Return path to the current file. """
return os.path.dirname(__file__).decode(get_encoding(), 'ignore')
return os_path_dirname(os_path_realpath(os_path_abspath(filename)))
def open_dir(path):
@ -51,11 +121,11 @@ def open_dir(path):
Return True if path exists else False. """
path = remove_shortcuts(path)
if not os.path.exists(path):
if not os_path_exists(path):
return False
if os.name == 'nt':
os.startfile(path)
os_startfile(path)
else:
subprocess.call(('xdg-open', path))
@ -66,6 +136,7 @@ def encode_tuple(tuple_to_encode):
"""Turn size tuple into string. """
return '%s/%s' % (tuple_to_encode[0], tuple_to_encode[1])
def decode_tuple(encoded_tuple):
"""Turn tuple string back to tuple. """
s = encoded_tuple.split('/')
@ -74,8 +145,8 @@ def decode_tuple(encoded_tuple):
def check_path(path):
"""Create path if not exist. """
if not os.path.exists(path):
os.makedirs(path)
if not os_path_exists(path):
os_makedirs(path)
def get_config_path():
@ -87,9 +158,9 @@ def get_config_path():
"""
if os.name == 'nt':
path = os.getenv('APPDATA')
path = os_getenv('APPDATA')
else:
path = os.path.join(os.path.expanduser('~'), '.config')
path = os.path.join(os_path_expanduser('~'), '.config')
return os.path.join(path, __appname__.lower())
@ -164,17 +235,6 @@ def get_time(seconds):
return dtime
def get_encoding():
"""Return system encoding. """
try:
encoding = locale.getpreferredencoding()
'TEST'.encode(encoding)
except:
encoding = 'UTF-8'
return encoding
def get_locale_file():
"""Search for youtube-dlg locale file.
@ -191,7 +251,7 @@ def get_locale_file():
SEARCH_DIRS = [
os.path.join(absolute_path(sys.argv[0]), DIR_NAME),
os.path.join(get_lib_path(), DIR_NAME),
os.path.join(os_path_dirname(__file__), DIR_NAME),
os.path.join('/usr', 'share', __appname__.lower(), DIR_NAME)
]
@ -199,7 +259,7 @@ def get_locale_file():
SEARCH_DIRS.append('/usr/local/Cellar/youtube-dl-gui/{version}/share/locale'.format(version=__version__))
for directory in SEARCH_DIRS:
if os.path.isdir(directory):
if os_path_isdir(directory):
return directory
return None
@ -224,11 +284,11 @@ def get_icon_file():
search_dirs = [
os.path.join(absolute_path(sys.argv[0]), 'icons'),
os.path.join(get_lib_path(), 'icons'),
os.path.join(os_path_dirname(__file__), 'icons'),
]
# Append $XDG_DATA_DIRS on search_dirs
path = os.getenv('XDG_DATA_DIRS')
path = os_getenv('XDG_DATA_DIRS')
if path is not None:
for xdg_path in path.split(':'):
@ -244,7 +304,7 @@ def get_icon_file():
for icon in ICONS_LIST:
icon_file = os.path.join(directory, icon)
if os.path.exists(icon_file):
if os_path_exists(icon_file):
return icon_file
return None

Loading…
Cancel
Save