From e7bd0f50e6f083f51f499d49f879110b1fc46e4f Mon Sep 17 00:00:00 2001 From: gryf Date: Mon, 15 Jun 2020 21:05:54 +0200 Subject: [PATCH] Removed lock module. --- ebook_converter/utils/config.py | 11 +- ebook_converter/utils/config_base.py | 12 +- ebook_converter/utils/lock.py | 206 --------------------------- 3 files changed, 11 insertions(+), 218 deletions(-) delete mode 100644 ebook_converter/utils/lock.py diff --git a/ebook_converter/utils/config.py b/ebook_converter/utils/config.py index 983e297..08e39ab 100644 --- a/ebook_converter/utils/config.py +++ b/ebook_converter/utils/config.py @@ -11,7 +11,6 @@ from ebook_converter.utils.config_base import ( StringConfig, json_dumps, json_loads, make_config_dir, plugin_dir, prefs, tweaks, from_json, to_json ) -from ebook_converter.utils.lock import ExclusiveFile if False: @@ -225,7 +224,7 @@ class DynamicConfig(dict): if clear_current: self.clear() if os.path.exists(self.file_path): - with ExclusiveFile(self.file_path) as f: + with open(self.file_path) as f: raw = f.read() if raw: try: @@ -241,7 +240,7 @@ class DynamicConfig(dict): migrate = bool(d) if migrate and d: raw = json_dumps(d, ignore_unserializable=True) - with ExclusiveFile(self.file_path) as f: + with open(self.file_path) as f: f.seek(0), f.truncate() f.write(raw) @@ -272,7 +271,7 @@ class DynamicConfig(dict): if not os.path.exists(self.file_path): make_config_dir() raw = json_dumps(self) - with ExclusiveFile(self.file_path) as f: + with open(self.file_path) as f: f.seek(0) f.truncate() f.write(raw) @@ -333,7 +332,7 @@ class XMLConfig(dict): def refresh(self, clear_current=True): d = {} if os.path.exists(self.file_path): - with ExclusiveFile(self.file_path) as f: + with open(self.file_path) as f: raw = f.read() try: d = self.raw_to_object(raw) if raw.strip() else {} @@ -392,7 +391,7 @@ class XMLConfig(dict): dpath = os.path.dirname(self.file_path) if not os.path.exists(dpath): os.makedirs(dpath, mode=constants_old.CONFIG_DIR_MODE) - with ExclusiveFile(self.file_path) as f: + with open(self.file_path) as f: raw = self.to_raw() f.seek(0) f.truncate() diff --git a/ebook_converter/utils/config_base.py b/ebook_converter/utils/config_base.py index f44e7e7..f1e94bd 100644 --- a/ebook_converter/utils/config_base.py +++ b/ebook_converter/utils/config_base.py @@ -16,7 +16,6 @@ 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.utils.date import isoformat from ebook_converter.utils import iso8601 @@ -374,9 +373,9 @@ class Config(ConfigInterface): migrate = False path = self.config_file_path if os.path.exists(path): - with ExclusiveFile(path) as f: + with open(path) as f: try: - src = f.read().decode('utf-8') + src = f.read() except ValueError: print("Failed to parse", path) traceback.print_exc() @@ -384,7 +383,7 @@ class Config(ConfigInterface): path = path.rpartition('.')[0] try: with open(path, 'rb') as f: - src = f.read().decode('utf-8') + src = f.read() except Exception: pass else: @@ -393,7 +392,7 @@ class Config(ConfigInterface): if migrate: new_src = self.option_set.serialize(ans, ignore_unserializable=True) - with ExclusiveFile(self.config_file_path) as f: + with open(self.config_file_path, 'w') as f: f.seek(0), f.truncate() f.write(new_src) return ans @@ -405,13 +404,14 @@ class Config(ConfigInterface): if not os.path.exists(config_dir): make_config_dir() - with ExclusiveFile(self.config_file_path) as f: + with open(self.config_file_path) as f: src = f.read() opts = self.option_set.parse_string(src) setattr(opts, name, val) src = self.option_set.serialize(opts) f.seek(0) f.truncate() + __import__('pdb').set_trace() if isinstance(src, str): src = src.encode('utf-8') f.write(src) diff --git a/ebook_converter/utils/lock.py b/ebook_converter/utils/lock.py deleted file mode 100644 index 2d8a415..0000000 --- a/ebook_converter/utils/lock.py +++ /dev/null @@ -1,206 +0,0 @@ -# License: GPLv3 Copyright: 2017, Kovid Goyal - -import atexit -import errno -import os -import stat -import tempfile -import time -from functools import partial - -from ebook_converter.constants_old import ( - __appname__, fcntl, filesystem_encoding, islinux, isosx, iswindows, plugins -) -from ebook_converter.utils.monotonic import monotonic - -# speedup = plugins['speedup'][0] -if iswindows: - import msvcrt, win32file, pywintypes, winerror, win32api, win32event - from ebook_converter.constants_old import get_windows_username - excl_file_mode = stat.S_IREAD | stat.S_IWRITE -else: - excl_file_mode = stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH - - -def unix_open(path): - flags = os.O_RDWR | os.O_CREAT - has_cloexec = False - #if hasattr(speedup, 'O_CLOEXEC'): - # try: - # fd = os.open(path, flags | speedup.O_CLOEXEC, excl_file_mode) - # has_cloexec = True - # except EnvironmentError as err: - # # Kernel may not support O_CLOEXEC - # if err.errno != errno.EINVAL: - # raise - - if not has_cloexec: - fd = os.open(path, flags, excl_file_mode) - fcntl.fcntl(fd, fcntl.F_SETFD, fcntl.FD_CLOEXEC) - return os.fdopen(fd, 'r+b') - - -def unix_retry(err): - return err.errno in (errno.EACCES, errno.EAGAIN, errno.ENOLCK, errno.EINTR) - - -def windows_open(path): - if isinstance(path, bytes): - path = path.decode('mbcs') - try: - h = win32file.CreateFileW( - path, - win32file.GENERIC_READ | - win32file.GENERIC_WRITE, # Open for reading and writing - 0, # Open exclusive - None, # No security attributes, ensures handle is not inherited by children - win32file.OPEN_ALWAYS, # If file does not exist, create it - win32file.FILE_ATTRIBUTE_NORMAL, # Normal attributes - None, # No template file - ) - except pywintypes.error as err: - raise WindowsError(err[0], err[2], path) - fd = msvcrt.open_osfhandle(h.Detach(), 0) - return os.fdopen(fd, 'r+b') - - -def windows_retry(err): - return err.winerror in ( - winerror.ERROR_SHARING_VIOLATION, winerror.ERROR_LOCK_VIOLATION - ) - - -def retry_for_a_time(timeout, sleep_time, func, error_retry, *args): - limit = monotonic() + timeout - while True: - try: - return func(*args) - except EnvironmentError as err: - if not error_retry(err) or monotonic() > limit: - raise - time.sleep(sleep_time) - - -def _lock_file(path, timeout=15, sleep_time=0.2): - if iswindows: - return retry_for_a_time( - timeout, sleep_time, windows_open, windows_retry, path - ) - f = unix_open(path) - retry_for_a_time( - timeout, sleep_time, fcntl.flock, unix_retry, - f.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB - ) - return f - - -def lock_file(path, timeout=15, sleep_time=0.2): - from filelock import FileLock - lock = FileLock(path + '.lock', timeout=timeout) - with lock: - return unix_open(path) - - -class ExclusiveFile(object): - - def __init__(self, path, timeout=15, sleep_time=0.2): - if iswindows and isinstance(path, bytes): - path = path.decode(filesystem_encoding) - self.path = path - self.timeout = timeout - self.sleep_time = sleep_time - - def __enter__(self): - self.file = lock_file(self.path, self.timeout, self.sleep_time) - return self.file - - def __exit__(self, type, value, traceback): - self.file.close() - - -def _clean_lock_file(file_obj): - try: - os.remove(file_obj.name) - except EnvironmentError: - pass - try: - file_obj.close() - except EnvironmentError: - pass - - -if iswindows: - - def create_single_instance_mutex(name, per_user=True): - mutexname = '{}-singleinstance-{}-{}'.format( - __appname__, (get_windows_username() if per_user else ''), name - ) - mutex = win32event.CreateMutex(None, False, mutexname) - if not mutex: - return - err = win32api.GetLastError() - if err == winerror.ERROR_ALREADY_EXISTS: - # Close this handle other wise this handle will prevent the mutex - # from being deleted when the process that created it exits. - win32api.CloseHandle(mutex) - return - return partial(win32api.CloseHandle, mutex) - -elif islinux: - - def create_single_instance_mutex(name, per_user=True): - import socket - from ebook_converter.utils.ipc import eintr_retry_call - name = '%s-singleinstance-%s-%s' % ( - __appname__, (os.geteuid() if per_user else ''), name - ) - name = name - address = '\0' + name.replace(' ', '_') - sock = socket.socket(family=socket.AF_UNIX) - try: - eintr_retry_call(sock.bind, address) - except socket.error as err: - if getattr(err, 'errno', None) == errno.EADDRINUSE: - return - raise - fd = sock.fileno() - old_flags = fcntl.fcntl(fd, fcntl.F_GETFD) - fcntl.fcntl(fd, fcntl.F_SETFD, old_flags | fcntl.FD_CLOEXEC) - return sock.close - -else: - - def singleinstance_path(name, per_user=True): - name = '%s-singleinstance-%s-%s.lock' % ( - __appname__, (os.geteuid() if per_user else ''), name - ) - home = os.path.expanduser('~') - locs = ['/var/lock', home, tempfile.gettempdir()] - if isosx: - locs.insert(0, '/Library/Caches') - for loc in locs: - if os.access(loc, os.W_OK | os.R_OK | os.X_OK): - return os.path.join(loc, ('.' if loc is home else '') + name) - raise EnvironmentError( - 'Failed to find a suitable filesystem location for the lock file' - ) - - def create_single_instance_mutex(name, per_user=True): - from ebook_converter.utils.ipc import eintr_retry_call - path = singleinstance_path(name, per_user) - f = open(path, 'w') - try: - eintr_retry_call(fcntl.lockf, f.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB) - return partial(_clean_lock_file, f) - except EnvironmentError as err: - if err.errno not in (errno.EAGAIN, errno.EACCES): - raise - - -def singleinstance(name): - ' Ensure that only a single process holding exists with the specified mutex key ' - release_mutex = create_single_instance_mutex(name) - if release_mutex is None: - return False - atexit.register(release_mutex) - return True