From 25541c89bffd220dfb7f093e3ba03b28ad23161b Mon Sep 17 00:00:00 2001 From: Joshua Harlow Date: Sun, 6 Dec 2015 16:47:04 -0800 Subject: [PATCH] Canonicalize paths before using them further Convert/normalize path types before further usage and attempt to translate non-string objects so that they can be used correctly in further interprocess locking code. Fixes issue #16 --- fasteners/_utils.py | 30 ++++++++++++++++++++++++++++++ fasteners/process_lock.py | 2 +- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/fasteners/_utils.py b/fasteners/_utils.py index c5418d7..00fb1f8 100644 --- a/fasteners/_utils.py +++ b/fasteners/_utils.py @@ -17,8 +17,25 @@ # under the License. import logging +import sys import time +try: + from os import fsencode as _fsencode +except (ImportError, AttributeError): + def _fsencode(path): + # Replicate similar logic to what py3.2+ fsencode does. + # See: https://bugs.python.org/issue8514 + encoding = sys.getfilesystemencoding() + if encoding == 'mbcs': + errors = 'strict' + else: + errors = 'surrogateescape' + return path.encode(encoding, errors) + + +import six + from monotonic import monotonic as now # noqa # log level for low-level debugging @@ -27,6 +44,19 @@ BLATHER = 5 LOG = logging.getLogger(__name__) +def canonicalize_path(path): + """Canonicalizes a potential path. + + Returns a binary string encoded into filesystem encoding. + """ + if isinstance(path, six.binary_type): + return path + if isinstance(path, six.text_type): + return _fsencode(path) + else: + return canonicalize_path(str(path)) + + def pick_first_not_none(*values): """Returns first of values that is *not* None (or None if all are/were).""" for val in values: diff --git a/fasteners/process_lock.py b/fasteners/process_lock.py index 74ca97d..890861f 100644 --- a/fasteners/process_lock.py +++ b/fasteners/process_lock.py @@ -84,7 +84,7 @@ class _InterProcessLock(object): def __init__(self, path, sleep_func=time.sleep, logger=None): self.lockfile = None - self.path = path + self.path = _utils.canonicalize_path(path) self.acquired = False self.sleep_func = sleep_func self.logger = _utils.pick_first_not_none(logger, LOG)