diff --git a/ebook_converter/polyglot/builtins.py b/ebook_converter/polyglot/builtins.py index 8575ba7..b9ec1c1 100644 --- a/ebook_converter/polyglot/builtins.py +++ b/ebook_converter/polyglot/builtins.py @@ -14,6 +14,7 @@ def as_bytes(x, encoding='utf-8'): def as_unicode(x, encoding='utf-8', errors='strict'): + return str(x) if isinstance(x, bytes): return x.decode(encoding, errors) return str(x) diff --git a/ebook_converter/utils/config.py b/ebook_converter/utils/config.py index 02b1860..983e297 100644 --- a/ebook_converter/utils/config.py +++ b/ebook_converter/utils/config.py @@ -5,9 +5,7 @@ import optparse import os from copy import deepcopy -from ebook_converter.constants_old import ( - CONFIG_DIR_MODE, __appname__, __author__, config_dir, get_version, iswindows -) +from ebook_converter import constants_old from ebook_converter.utils.config_base import ( Config, ConfigInterface, ConfigProxy, Option, OptionSet, OptionValues, StringConfig, json_dumps, json_loads, make_config_dir, plugin_dir, prefs, @@ -23,7 +21,8 @@ if False: def check_config_write_access(): - return os.access(config_dir, os.W_OK) and os.access(config_dir, os.X_OK) + return (os.access(constants_old.config_dir, os.W_OK) and + os.access(constants_old.config_dir, os.X_OK)) class CustomHelpFormatter(optparse.IndentedHelpFormatter): @@ -85,14 +84,16 @@ class OptionParser(optparse.OptionParser): usage = textwrap.dedent(usage) if epilog is None: - epilog = 'Created by ' + colored(__author__, fg='cyan') + epilog = 'Created by ' + colored(constants_old.__author__, + fg='cyan') usage += ('\n\nWhenever you pass arguments to %prog that have spaces ' 'in them, enclose the arguments in quotation marks. For ' 'example: "{}"\n\n').format("C:\\some path with spaces" - if iswindows + if constants_old.iswindows else '/some path/with spaces') if version is None: - version = '%%prog (%s %s)'%(__appname__, get_version()) + version = '%%prog (%s %s)' % (constants_old.__appname__, + constants_old.get_version()) optparse.OptionParser.__init__(self, usage=usage, version=version, epilog=epilog, formatter=CustomHelpFormatter(), conflict_handler=conflict_handler, **kwds) @@ -198,18 +199,17 @@ class DynamicConfig(dict): @property def file_path(self): - return os.path.join(config_dir, self.name+'.pickle.json') + return os.path.join(constants_old.config_dir, self.name+'.pickle.json') def decouple(self, prefix): self.name = prefix + self.name self.refresh() def read_old_serialized_representation(self): - from ebook_converter.utils.shared_file import share_open from ebook_converter.utils.serialize import pickle_loads path = self.file_path.rpartition('.')[0] try: - with share_open(path, 'rb') as f: + with open(path, 'rb') as f: raw = f.read() except EnvironmentError: raw = b'' @@ -293,7 +293,8 @@ class XMLConfig(dict): EXTENSION = '.plist' - def __init__(self, rel_path_to_cf_file, base_path=config_dir): + def __init__(self, rel_path_to_cf_file, + base_path=constants_old.config_dir): dict.__init__(self) self.no_commit = False self.defaults = {} @@ -390,7 +391,7 @@ class XMLConfig(dict): if hasattr(self, 'file_path') and self.file_path: dpath = os.path.dirname(self.file_path) if not os.path.exists(dpath): - os.makedirs(dpath, mode=CONFIG_DIR_MODE) + os.makedirs(dpath, mode=constants_old.CONFIG_DIR_MODE) with ExclusiveFile(self.file_path) as f: raw = self.to_raw() f.seek(0) diff --git a/ebook_converter/utils/config_base.py b/ebook_converter/utils/config_base.py index e452974..f44e7e7 100644 --- a/ebook_converter/utils/config_base.py +++ b/ebook_converter/utils/config_base.py @@ -1,22 +1,30 @@ -__license__ = 'GPL v3' -__copyright__ = '2011, Kovid Goyal ' -__docformat__ = 'restructuredtext en' - -import os, re, traceback, numbers -from functools import partial -from collections import defaultdict -from copy import deepcopy +import json +import collections +import copy +import functools +import numbers +import os import pkg_resources +import re +import traceback +import pickle +import datetime +import base64 +from ebook_converter.constants_old import CONFIG_DIR_MODE +from ebook_converter.constants_old import config_dir +from ebook_converter.constants_old import filesystem_encoding +from ebook_converter.constants_old import iswindows +from ebook_converter.constants_old import preferred_encoding from ebook_converter.utils.lock import ExclusiveFile -from ebook_converter.constants_old import config_dir, CONFIG_DIR_MODE, preferred_encoding, filesystem_encoding, iswindows +from ebook_converter.utils.date import isoformat +from ebook_converter.utils import iso8601 plugin_dir = os.path.join(config_dir, 'plugins') def parse_old_style(src): - import pickle as cPickle - options = {'cPickle':cPickle} + options = {'cPickle': pickle} try: if not isinstance(src, str): src = src.decode('utf-8') @@ -25,20 +33,19 @@ def parse_old_style(src): exec(src, options) except Exception as err: try: - print('Failed to parse old style options string with error: {}'.format(err)) + print('Failed to parse old style options string with error: ' + '{}'.format(err)) except Exception: pass return options def to_json(obj): - import datetime if isinstance(obj, bytearray): - from base64 import standard_b64encode return {'__class__': 'bytearray', - '__value__': standard_b64encode(bytes(obj)).decode('ascii')} + '__value__': base64.standard_b64encode(bytes(obj)) + .decode('ascii')} if isinstance(obj, datetime.datetime): - from ebook_converter.utils.date import isoformat return {'__class__': 'datetime.datetime', '__value__': isoformat(obj, as_utc=True)} if isinstance(obj, (set, frozenset)): @@ -62,11 +69,10 @@ def from_json(obj): custom = obj.get('__class__') if custom is not None: if custom == 'bytearray': - from base64 import standard_b64decode - return bytearray(standard_b64decode(obj['__value__'].encode('ascii'))) + return bytearray(base64.standard_b64decode(obj['__value__'] + .encode('ascii'))) if custom == 'datetime.datetime': - from ebook_converter.utils.iso8601 import parse_iso8601 - return parse_iso8601(obj['__value__'], assume_utc=True) + return iso8601.parse_iso8601(obj['__value__'], assume_utc=True) if custom == 'set': return set(obj['__value__']) return obj @@ -88,24 +94,27 @@ def force_unicode_recursive(obj): if isinstance(obj, (list, tuple)): return type(obj)(map(force_unicode_recursive, obj)) if isinstance(obj, dict): - return {force_unicode_recursive(k): force_unicode_recursive(v) for k, v in obj.items()} + return {force_unicode_recursive(k): force_unicode_recursive(v) + for k, v in obj.items()} return obj def json_dumps(obj, ignore_unserializable=False): - import json try: - ans = json.dumps(obj, indent=2, default=safe_to_json if ignore_unserializable else to_json, sort_keys=True, ensure_ascii=False) + ans = json.dumps(obj, indent=2, default=safe_to_json + if ignore_unserializable + else to_json, sort_keys=True, ensure_ascii=False) except UnicodeDecodeError: obj = force_unicode_recursive(obj) - ans = json.dumps(obj, indent=2, default=safe_to_json if ignore_unserializable else to_json, sort_keys=True, ensure_ascii=False) + ans = json.dumps(obj, indent=2, default=safe_to_json + if ignore_unserializable + else to_json, sort_keys=True, ensure_ascii=False) if not isinstance(ans, bytes): ans = ans.encode('utf-8') return ans def json_loads(raw): - import json if isinstance(raw, bytes): raw = raw.decode('utf-8') return json.loads(raw, object_hook=from_json) @@ -119,26 +128,28 @@ def make_config_dir(): class Option(object): def __init__(self, name, switches=[], help='', type=None, choices=None, - check=None, group=None, default=None, action=None, metavar=None): + check=None, group=None, default=None, action=None, + metavar=None): if choices: type = 'choice' - self.name = name + self.name = name self.switches = switches - self.help = help.replace('%default', repr(default)) if help else None - self.type = type + self.help = help.replace('%default', repr(default)) if help else None + self.type = type if self.type is None and action is None and choices is None: if isinstance(default, float): self.type = 'float' - elif isinstance(default, numbers.Integral) and not isinstance(default, bool): + elif (isinstance(default, numbers.Integral) and + not isinstance(default, bool)): self.type = 'int' - self.choices = choices - self.check = check - self.group = group - self.default = default - self.action = action - self.metavar = metavar + self.choices = choices + self.check = check + self.group = group + self.default = default + self.action = action + self.metavar = metavar def __eq__(self, other): return self.name == getattr(other, 'name', other) @@ -153,21 +164,22 @@ class Option(object): class OptionValues(object): def copy(self): - return deepcopy(self) + return copy.deepcopy(self) class OptionSet(object): - OVERRIDE_PAT = re.compile(r'#{3,100} Override Options #{15}(.*?)#{3,100} End Override #{3,100}', - re.DOTALL|re.IGNORECASE) + OVERRIDE_PAT = re.compile(r'#{3,100} Override Options #{15}(.*?)#{3,100} ' + 'End Override #{3,100}', + re.DOTALL | re.IGNORECASE) def __init__(self, description=''): self.description = description self.defaults = {} self.preferences = [] - self.group_list = [] - self.groups = {} - self.set_buffer = {} + self.group_list = [] + self.groups = {} + self.set_buffer = {} self.loads_pat = None def has_option(self, name_or_option_object): @@ -188,10 +200,11 @@ class OptionSet(object): def add_group(self, name, description=''): if name in self.group_list: - raise ValueError('A group by the name %s already exists in this set'%name) + raise ValueError('A group by the name %s already exists in this ' + 'set' % name) self.groups[name] = description self.group_list.append(name) - return partial(self.add_opt, group=name) + return functools.partial(self.add_opt, group=name) def update(self, other): for name in other.groups.keys(): @@ -204,9 +217,10 @@ class OptionSet(object): self.preferences.append(pref) def smart_update(self, opts1, opts2): - ''' - Updates the preference values in opts1 using only the non-default preference values in opts2. - ''' + """ + Updates the preference values in opts1 using only the non-default + preference values in opts2. + """ for pref in self.preferences: new = getattr(opts2, pref.name, pref.default) if new != pref.default: @@ -217,47 +231,45 @@ class OptionSet(object): self.preferences.remove(name) def add_opt(self, name, switches=[], help=None, type=None, choices=None, - group=None, default=None, action=None, metavar=None): - ''' + group=None, default=None, action=None, metavar=None): + """ Add an option to this section. - :param name: The name of this option. Must be a valid Python identifier. - Must also be unique in this OptionSet and all its subsets. - :param switches: List of command line switches for this option - (as supplied to :module:`optparse`). If empty, this - option will not be added to the command line parser. - :param help: Help text. - :param type: Type checking of option values. Supported types are: - `None, 'choice', 'complex', 'float', 'int', 'string'`. - :param choices: List of strings or `None`. - :param group: Group this option belongs to. You must previously - have created this group with a call to :method:`add_group`. - :param default: The default value for this option. - :param action: The action to pass to optparse. Supported values are: - `None, 'count'`. For choices and boolean options, - action is automatically set correctly. - ''' - pref = Option(name, switches=switches, help=help, type=type, choices=choices, - group=group, default=default, action=action, metavar=None) + :param name: The name of this option. Must be a valid Python + identifier. Must also be unique in this OptionSet and all + its subsets. + :param switches: List of command line switches for this option (as + supplied to :module:`optparse`). If empty, this option + will not be added to the command line parser. + :param help: Help text. + :param type: Type checking of option values. Supported types are: + `None, 'choice', 'complex', 'float', 'int', 'string'`. + :param choices: List of strings or `None`. + :param group: Group this option belongs to. You must previously + have created this group with a call to + :method:`add_group`. + :param default: The default value for this option. + :param action: The action to pass to optparse. Supported values are: + `None, 'count'`. For choices and boolean options, + action is automatically set correctly. + """ + pref = Option(name, switches=switches, help=help, type=type, + choices=choices, group=group, default=default, + action=action, metavar=None) if group is not None and group not in self.groups.keys(): - raise ValueError('Group %s has not been added to this section'%group) + raise ValueError('Group %s has not been added to this section' % + group) + if pref in self.preferences: - raise ValueError('An option with the name %s already exists in this set.'%name) + raise ValueError('An option with the name %s already exists in ' + 'this set.' % name) self.preferences.append(pref) self.defaults[name] = default - def retranslate_help(self): - t = _ - for opt in self.preferences: - if opt.help: - opt.help = t(opt.help) - if opt.name == 'use_primary_find_in_search': - opt.help = opt.help.format(u'ñ') - def option_parser(self, user_defaults=None, usage='', gui_mode=False): from ebook_converter.utils.config import OptionParser parser = OptionParser(usage, gui_mode=gui_mode) - groups = defaultdict(lambda : parser) + groups = collections.defaultdict(lambda: parser) for group, desc in self.groups.items(): groups[group] = parser.add_option_group(group.upper(), desc) @@ -270,15 +282,13 @@ class OptionSet(object): action = 'store' if pref.default is True or pref.default is False: action = 'store_' + ('false' if pref.default else 'true') - args = dict( - dest=pref.name, - help=pref.help, - metavar=pref.metavar, - type=pref.type, - choices=pref.choices, - default=getattr(user_defaults, pref.name, pref.default), - action=action, - ) + args = {'dest': pref.name, + 'help': pref.help, + 'metavar': pref.metavar, + 'type': pref.type, + 'choices': pref.choices, + 'default': getattr(user_defaults, pref.name, pref.default), + 'action': action} g.add_option(*pref.switches, **args) return parser @@ -292,7 +302,9 @@ class OptionSet(object): def parse_string(self, src): options = {} if src: - is_old_style = (isinstance(src, bytes) and src.startswith(b'#')) or (isinstance(src, str) and src.startswith(u'#')) + is_old_style = (isinstance(src, bytes) and + src.startswith(b'#')) or (isinstance(src, str) and + src.startswith(u'#')) if is_old_style: options = parse_old_style(src) else: @@ -302,7 +314,8 @@ class OptionSet(object): raise Exception('options is not a dictionary') except Exception as err: try: - print('Failed to parse options string with error: {}'.format(err)) + print('Failed to parse options string with error: {}' + .format(err)) except Exception: pass opts = OptionValues() @@ -316,20 +329,21 @@ class OptionSet(object): return opts def serialize(self, opts, ignore_unserializable=False): - data = {pref.name: getattr(opts, pref.name, pref.default) for pref in self.preferences} + data = {pref.name: getattr(opts, pref.name, pref.default) + for pref in self.preferences} return json_dumps(data, ignore_unserializable=ignore_unserializable) class ConfigInterface(object): def __init__(self, description): - self.option_set = OptionSet(description=description) - self.add_opt = self.option_set.add_opt - self.add_group = self.option_set.add_group - self.remove_opt = self.remove = self.option_set.remove_opt - self.parse_string = self.option_set.parse_string - self.get_option = self.option_set.get_option - self.preferences = self.option_set.preferences + self.option_set = OptionSet(description=description) + self.add_opt = self.option_set.add_opt + self.add_group = self.option_set.add_group + self.remove_opt = self.remove = self.option_set.remove_opt + self.parse_string = self.option_set.parse_string + self.get_option = self.option_set.get_option + self.preferences = self.option_set.preferences def update(self, other): self.option_set.update(other.option_set) @@ -343,9 +357,9 @@ class ConfigInterface(object): class Config(ConfigInterface): - ''' + """ A file based configuration. - ''' + """ def __init__(self, basename, description=''): ConfigInterface.__init__(self, description) @@ -368,9 +382,8 @@ class Config(ConfigInterface): traceback.print_exc() if not src: path = path.rpartition('.')[0] - from ebook_converter.utils.shared_file import share_open try: - with share_open(path, 'rb') as f: + with open(path, 'rb') as f: src = f.read().decode('utf-8') except Exception: pass @@ -378,7 +391,8 @@ class Config(ConfigInterface): migrate = bool(src) ans = self.option_set.parse_string(src) if migrate: - new_src = self.option_set.serialize(ans, ignore_unserializable=True) + new_src = self.option_set.serialize(ans, + ignore_unserializable=True) with ExclusiveFile(self.config_file_path) as f: f.seek(0), f.truncate() f.write(new_src) @@ -386,9 +400,11 @@ class Config(ConfigInterface): def set(self, name, val): if not self.option_set.has_option(name): - raise ValueError('The option %s is not defined.'%name) + raise ValueError('The option %s is not defined.' % name) + if not os.path.exists(config_dir): make_config_dir() + with ExclusiveFile(self.config_file_path) as f: src = f.read() opts = self.option_set.parse_string(src) @@ -402,9 +418,9 @@ class Config(ConfigInterface): class StringConfig(ConfigInterface): - ''' + """ A string based configuration - ''' + """ def __init__(self, src, description=''): ConfigInterface.__init__(self, description) @@ -420,20 +436,21 @@ class StringConfig(ConfigInterface): def set(self, name, val): if not self.option_set.has_option(name): - raise ValueError('The option %s is not defined.'%name) + raise ValueError('The option %s is not defined.' % name) + opts = self.option_set.parse_string(self.src) setattr(opts, name, val) self.set_src(self.option_set.serialize(opts)) class ConfigProxy(object): - ''' + """ A Proxy to minimize file reads for widely used config settings - ''' + """ def __init__(self, config): self.__config = config - self.__opts = None + self.__opts = None @property def defaults(self): @@ -442,9 +459,6 @@ class ConfigProxy(object): def refresh(self): self.__opts = self.__config.parse() - def retranslate_help(self): - self.__config.option_set.retranslate_help() - def __getitem__(self, key): return self.get(key) @@ -470,7 +484,8 @@ class ConfigProxy(object): def create_global_prefs(conf_obj=None): - c = Config('global', 'calibre wide preferences') if conf_obj is None else conf_obj + c = Config('global', + 'calibre wide preferences') if conf_obj is None else conf_obj c.add_opt('database_path', default=os.path.expanduser('~/library1.db'), help='Path to the database in which books are stored') @@ -481,17 +496,19 @@ def create_global_prefs(conf_obj=None): c.add_opt('network_timeout', default=5, help='Default timeout for network operations (seconds)') c.add_opt('library_path', default=None, - help='Path to directory in which your library of books is stored') + help='Path to directory in which your library of books is ' + 'stored') c.add_opt('language', default=None, help='The language in which to display the user interface') - c.add_opt('output_format', default='EPUB', - help='The default output format for e-book conversions. When auto-converting' - ' to send to a device this can be overridden by individual device preferences.' - ' These can be changed by right clicking the device icon in calibre and' - ' choosing "Configure".') - c.add_opt('input_format_order', default=['EPUB', 'AZW3', 'MOBI', 'LIT', 'PRC', - 'FB2', 'HTML', 'HTM', 'XHTM', 'SHTML', 'XHTML', 'ZIP', 'DOCX', 'ODT', 'RTF', 'PDF', - 'TXT'], + c.add_opt('output_format', default='EPUB', help='The default output ' + 'format for e-book conversions. When auto-converting to send to ' + 'a device this can be overridden by individual device ' + 'preferences. These can be changed by right clicking the device ' + 'icon in calibre and choosing "Configure".') + c.add_opt('input_format_order', + default=['EPUB', 'AZW3', 'MOBI', 'LIT', 'PRC', 'FB2', 'HTML', + 'HTM', 'XHTM', 'SHTML', 'XHTML', 'ZIP', 'DOCX', 'ODT', + 'RTF', 'PDF', 'TXT'], help='Ordered list of formats to prefer for input.') c.add_opt('read_file_metadata', default=True, help='Read metadata from files') @@ -501,27 +518,32 @@ def create_global_prefs(conf_obj=None): 'Most tasks like conversion/news download/adding books/etc. ' 'are affected by this setting.') c.add_opt('swap_author_names', default=False, - help='Swap author first and last names when reading metadata') + help='Swap author first and last names when reading metadata') c.add_opt('add_formats_to_existing', default=False, - help='Add new formats to existing book records') + help='Add new formats to existing book records') c.add_opt('check_for_dupes_on_ctl', default=False, - help='Check for duplicates when copying to another library') + help='Check for duplicates when copying to another library') c.add_opt('installation_uuid', default=None, help='Installation UUID') - c.add_opt('new_book_tags', default=[], help='Tags to apply to books added to the library') - c.add_opt('mark_new_books', default=False, help='Mark newly added books. The mark is a temporary mark that is automatically removed when calibre is restarted.') + c.add_opt('new_book_tags', default=[], + help='Tags to apply to books added to the library') + c.add_opt('mark_new_books', default=False, help='Mark newly added books. ' + 'The mark is a temporary mark that is automatically removed ' + 'when calibre is restarted.') # these are here instead of the gui preferences because calibredb and # calibre server can execute searches - c.add_opt('saved_searches', default={}, help='List of named saved searches') - c.add_opt('user_categories', default={}, help='User-created Tag browser categories') + c.add_opt('saved_searches', default={}, + help='List of named saved searches') + c.add_opt('user_categories', default={}, + help='User-created Tag browser categories') c.add_opt('manage_device_metadata', default='manual', - help='How and when calibre updates metadata on the device.') + help='How and when calibre updates metadata on the device.') c.add_opt('limit_search_columns', default=False, help='When searching for text without using lookup ' 'prefixes, as for example, Red instead of title:Red, ' 'limit the columns searched to those named below.') c.add_opt('limit_search_columns_to', - default=['title', 'authors', 'tags', 'series', 'publisher'], + default=['title', 'authors', 'tags', 'series', 'publisher'], help='Choose columns to be searched when not using prefixes, ' 'as for example, when searching for Red instead of ' 'title:Red. Enter a list of search/lookup names ' @@ -536,9 +558,11 @@ def create_global_prefs(conf_obj=None): 'this is much slower than a simple search on very large ' 'libraries. Also, this option will have no effect if you turn ' 'on case-sensitive searching') - c.add_opt('case_sensitive', default=False, help='Make searches case-sensitive') + c.add_opt('case_sensitive', default=False, + help='Make searches case-sensitive') - c.add_opt('migrated', default=False, help='For Internal use. Don\'t modify.') + c.add_opt('migrated', default=False, + help='For Internal use. Don\'t modify.') return c @@ -581,7 +605,8 @@ def write_custom_tweaks(tweaks_dict): changed_tweaks = {} default_tweaks = exec_tweaks(default_tweaks_raw()) for key, cval in tweaks_dict.items(): - if key in default_tweaks and normalize_tweak(cval) == normalize_tweak(default_tweaks[key]): + if (key in default_tweaks and + normalize_tweak(cval) == normalize_tweak(default_tweaks[key])): continue changed_tweaks[key] = cval raw = json_dumps(changed_tweaks) @@ -598,10 +623,10 @@ def exec_tweaks(path): raw = f.read() fname = f.name code = compile(raw, fname, 'exec') - l = {} + x = {} g = {'__file__': fname} - exec(code, g, l) - return l + exec(code, g, x) + return x def read_custom_tweaks(): diff --git a/ebook_converter/utils/icu.py b/ebook_converter/utils/icu.py index fc2631e..bc4dc84 100644 --- a/ebook_converter/utils/icu.py +++ b/ebook_converter/utils/icu.py @@ -1,17 +1,10 @@ -import codecs import sys -import unicodedata # Setup code {{{ -from ebook_converter.constants_old import plugins from ebook_converter.polyglot.builtins import cmp -from ebook_converter.utils.config_base import tweaks +from ebook_converter.utils import config_base -__license__ = 'GPL v3' -__copyright__ = '2010, Kovid Goyal ' -__docformat__ = 'restructuredtext en' - is_narrow_build = sys.maxunicode < 0x10ffff _locale = _collator = _primary_collator = _sort_collator = _numeric_collator = _case_sensitive_collator = None cmp @@ -24,33 +17,6 @@ _icu, err = 1, None # plugins['icu'] if _icu is None: raise RuntimeError('Failed to load icu with error: %s' % err) del err -#icu_unicode_version = getattr(_icu, 'unicode_version', None) -# _nmodes = {m:getattr(_icu, m) for m in ('NFC', 'NFD', 'NFKC', 'NFKD')} - -# Ensure that the python internal filesystem and default encodings are not ASCII - - -#def is_ascii(name): -# try: -# return codecs.lookup(name).name == b'ascii' -# except (TypeError, LookupError): -# return True -# -# -#try: -# if is_ascii(sys.getdefaultencoding()): -# _icu.set_default_encoding(b'utf-8') -#except: -# import traceback -# traceback.print_exc() -# -#try: -# if is_ascii(sys.getfilesystemencoding()): -# _icu.set_filesystem_encoding(b'utf-8') -#except: -# import traceback -# traceback.print_exc() -#del is_ascii def collator(): @@ -58,8 +24,8 @@ def collator(): if _collator is None: if _locale is None: from ebook_converter.utils.localization import get_lang - if tweaks['locale_for_sorting']: - _locale = tweaks['locale_for_sorting'] + if config_base.tweaks['locale_for_sorting']: + _locale = config_base.tweaks['locale_for_sorting'] else: _locale = get_lang() try: @@ -91,7 +57,7 @@ def sort_collator(): if _sort_collator is None: _sort_collator = collator().clone() _sort_collator.strength = _icu.UCOL_SECONDARY - _sort_collator.numeric = tweaks['numeric_collation'] + _sort_collator.numeric = config_base.tweaks['numeric_collation'] return _sort_collator @@ -311,9 +277,3 @@ string_length = len #_icu.string_length if is_narrow_build else len # Return the number of UTF-16 codepoints in a string utf16_length = len # if is_narrow_build else _icu.utf16_length - -################################################################################ - -# if __name__ == '__main__': - # from ebook_converter.utils.icu_test import run - # run(verbosity=4) diff --git a/ebook_converter/utils/shared_file.py b/ebook_converter/utils/shared_file.py index 67ccf6a..80e7dfa 100644 --- a/ebook_converter/utils/shared_file.py +++ b/ebook_converter/utils/shared_file.py @@ -14,66 +14,7 @@ until all open file handles are closed. You also cannot delete the containing directory until all file handles are closed. To get around this, rename the file before deleting it. """ -import os, sys - -from ebook_converter.polyglot.builtins import reraise -from ebook_converter.constants_old import iswindows, plugins - - -__license__ = 'GPL v3' -__copyright__ = '2015, Kovid Goyal ' - -# speedup, err = plugins['speedup'] - -# if not speedup: - # raise RuntimeError('Failed to load the speedup plugin with error: %s' % err) - -valid_modes = {'a', 'a+', 'a+b', 'ab', 'r', 'rb', 'r+', 'r+b', 'w', 'wb', 'w+', 'w+b'} - - -def validate_mode(mode): - return mode in valid_modes - - -class FlagConstants(object): - - def __init__(self): - for x in 'APPEND CREAT TRUNC EXCL RDWR RDONLY WRONLY'.split(): - x = 'O_' + x - setattr(self, x, getattr(os, x)) - for x in 'RANDOM SEQUENTIAL TEXT BINARY'.split(): - x = 'O_' + x - setattr(self, x, getattr(os, x, 0)) - - -fc = FlagConstants() - - -def flags_from_mode(mode): - if not validate_mode(mode): - raise ValueError('The mode is invalid') - m = mode[0] - random = '+' in mode - binary = 'b' in mode - if m == 'a': - flags = fc.O_APPEND | fc.O_CREAT - if random: - flags |= fc.O_RDWR | fc.O_RANDOM - else: - flags |= fc.O_WRONLY | fc.O_SEQUENTIAL - elif m == 'r': - if random: - flags = fc.O_RDWR | fc.O_RANDOM - else: - flags = fc.O_RDONLY | fc.O_SEQUENTIAL - elif m == 'w': - if random: - flags = fc.O_RDWR | fc.O_RANDOM - else: - flags = fc.O_WRONLY | fc.O_SEQUENTIAL - flags |= fc.O_TRUNC | fc.O_CREAT - flags |= (fc.O_BINARY if binary else fc.O_TEXT) - return flags +import os share_open = open