From 3db489aa7bee0361730493c81487b70414b63bf3 Mon Sep 17 00:00:00 2001 From: Carey Metcalfe Date: Thu, 17 Jan 2019 03:45:50 -0500 Subject: [PATCH] Add compatibility shims for Python 2.7 - `os.scandir` (provided by a 3rd party package in 2.7) - `os.replace` (doesn't exist in 2.7 - have to use `os.rename` instead) - `os.utime` (the times param is required in 2.7) --- setup.py | 1 + supysonic/cache.py | 8 +++++--- supysonic/py23.py | 25 +++++++++++++++++++++++++ 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/setup.py b/setup.py index 60b6584..79416a8 100755 --- a/setup.py +++ b/setup.py @@ -22,6 +22,7 @@ reqs = [ 'Pillow', 'requests>=1.0.0', 'mutagen>=1.33', + 'scandir<2.0.0', 'zipstream' ] extras = { diff --git a/supysonic/cache.py b/supysonic/cache.py index 3034c24..8553e17 100644 --- a/supysonic/cache.py +++ b/supysonic/cache.py @@ -18,6 +18,8 @@ import tempfile import threading from time import time +from .py23 import scandir, osreplace + logger = logging.getLogger(__name__) @@ -73,7 +75,7 @@ class Cache(object): self._size = 0 self._files = OrderedDict() for mtime, size, key in sorted([(f.stat().st_mtime, f.stat().st_size, f.name) - for f in os.scandir(self._cache_dir) + for f in scandir(self._cache_dir) if f.is_file()]): self._files[key] = CacheEntry(size, mtime + self.min_time) self._size += size @@ -110,7 +112,7 @@ class Cache(object): """Touch the file to change modified time and move it to the end of the cache dict""" old = self._files.pop(key) self._files[key] = CacheEntry(old.size, int(time()) + self.min_time) - os.utime(self._filepath(key)) + os.utime(self._filepath(key), None) @property def size(self): @@ -165,7 +167,7 @@ class Cache(object): with self._lock: if self._auto_prune: self._make_space(size, key=key) - os.replace(f.name, self._filename(key)) + osreplace(f.name, self._filepath(key)) self._record_file(key, size) except OSError as e: # Ignore error from trying to delete the renamed temp file diff --git a/supysonic/py23.py b/supysonic/py23.py index 319e00e..ae500cd 100644 --- a/supysonic/py23.py +++ b/supysonic/py23.py @@ -7,6 +7,31 @@ # # Distributed under terms of the GNU AGPLv3 license. +# Try built-in scandir, fall back to the package for Python 2.7 +try: + from os import scandir +except ImportError: + from scandir import scandir + +# os.replace was added in Python 3.3, provide a fallback for Python 2.7 +try: + from os import replace as osreplace +except ImportError: + # os.rename is equivalent to os.replace except on Windows + # On Windows an existing file will not be overwritten + # This fallback just attempts to delete the dst file before using rename + import sys + if sys.platform != 'win32': + from os import rename as osreplace + else: + import os + def osreplace(src, dst): + try: + os.remove(dst) + except OSError: + pass + os.rename(src, dst) + try: # Python 2 strtype = basestring