diff --git a/izzylib/cache.py b/izzylib/cache.py index 01fb92c..42bd459 100644 --- a/izzylib/cache.py +++ b/izzylib/cache.py @@ -1,6 +1,6 @@ import json, re -from datetime import datetime +from datetime import datetime, timedelta from collections import OrderedDict from functools import update_wrapper from hashlib import sha1 @@ -13,7 +13,10 @@ def parse_ttl(ttl): return 0 if type(ttl) == int: - return ttl * 60 + return ttl + + if type(ttl) == timedelta: + return timedelta.seconds m = re.match(r'^(\d+)([smhdw]?)$', ttl) @@ -49,45 +52,25 @@ class DefaultValue(object): class BaseCache(OrderedDict): _get = OrderedDict.get _items = OrderedDict.items + + def __init__(self, maxsize=1024, ttl=None): self.ttl = parse_ttl(ttl) self.maxsize = maxsize + self.get = self.fetch self.set = self.store self.deco = lambda *args: CacheDecorator(self, *args) def __str__(self): - data = ', '.join([f'{k}="{v}"' for k,v in self.items()]) - return f'BaseCache({data})' + return f'BaseCache(maxsize={self.maxsize}, ttl={self.ttl})' def items(self): return [[k, v.data] for k,v in self._items()] - def get(self, key): - while len(self) >= self.maxsize and self.maxsize > 0: - self.popitem(last=False) - - item = self._get(key) - - if not item: - return - - if self.ttl > 0: - timestamp = int(datetime.timestamp(datetime.now())) - - if timestamp >= self[key].timestamp: - del self[key] - return - - self[key].timestamp = timestamp + self.ttl - - self.move_to_end(key) - return item['data'] - - def remove(self, key): if self.get(key): del self[key] @@ -107,13 +90,14 @@ class BaseCache(OrderedDict): def fetch(self, key): - item = self.get(key) - timestamp = int(datetime.timestamp(datetime.now())) + item = self._get(key) if not item: return if self.ttl: + timestamp = int(datetime.timestamp(datetime.now())) + if timestamp >= self[key].timestamp: del self[key] return @@ -121,21 +105,7 @@ class BaseCache(OrderedDict): self[key]['timestamp'] = timestamp + self.ttl self.move_to_end(key) - return item - - - def pop(self, key, default=DefaultValue): - try: - item = self.get(key) - del self[key] - - return item - - except Exception as e: - if default == DefaultValue: - raise e from None - - return default + return item.data ## This doesn't work for some reason diff --git a/izzylib/path.py b/izzylib/path.py index eecea36..27e66b3 100644 --- a/izzylib/path.py +++ b/izzylib/path.py @@ -24,6 +24,7 @@ class Path(str, metaclass=PathMeta): #else: #str.__new__(Path, path) + ## todo: move these to direct properties of Path self.config = { 'missing': missing, 'parents': parents, @@ -112,9 +113,10 @@ class Path(str, metaclass=PathMeta): def backup(self, ext='backup', overwrite=False): target = f'{self.parent}.{ext}' self.copy(target, overwrite) + return Path(target) - def chmod(self, mode=None): + def chmod(self, mode): os.chmod(self, mode) @@ -127,17 +129,25 @@ class Path(str, metaclass=PathMeta): self.__check_dir(path) - if overwrite: - try: - target.delete() + if target.exists(): + if overwrite: + try: + target.delete() - except FileNotFoundError: - pass + except FileNotFoundError: + pass + + elif not self.config.exist: + raise FileExistsError(target) shutil.copy2(self, target) + return target def delete(self): + if not self.exists() and not self.config.exist: + raise FileNotFoundError(self) + if self.isdir: shutil.rmtree(self, ignore_errors=True) @@ -155,12 +165,13 @@ class Path(str, metaclass=PathMeta): return Path(os.path.expanduser(self)) - def glob(self, pattern='*'): - return tuple(sorted(self.join(path) for path in PyPath(self).rglob(pattern))) + def glob(self, pattern='*', recursive=True): + paths = PyPath(self).rglob(pattern) if recursive else PyPath(self).glob(pattern) + return tuple(sorted(self.join(path) for path in paths)) - def join(self, new_path): - return Path(os.path.join(self, new_path)) + def join(self, path): + return Path(os.path.join(self, path)) def json_load(self): @@ -178,10 +189,14 @@ class Path(str, metaclass=PathMeta): self.__check_dir(path) - if target.exists: + if target.exists(): + if not self.config.exist: + raise FileExistsError(target) + target.delete() self.symlink_to(path, target.isdir) + return target def listdir(self, recursive=True): @@ -192,11 +207,11 @@ class Path(str, metaclass=PathMeta): def mkdir(self, mode=0o755): - if self.config['parents']: - os.makedirs(self, mode, exist_ok=self.config['exist']) + if self.config.parents: + os.makedirs(self, mode, exist_ok=self.config.exist) else: - os.makedir(self, mode, exist_ok=self.config['exist']) + os.makedir(self, mode, exist_ok=self.config.exist) return self.exists @@ -228,8 +243,8 @@ class Path(str, metaclass=PathMeta): return Path(os.path.abspath(self)) - def touch(self, mode=0o644, utime=None): - timestamp = utime or datetime.now().timestamp() + def touch(self, mode=0o644, mtime=None): + timestamp = mtime or datetime.now().timestamp() with self.open('w+') as fd: os.utime(self, (timestamp, timestamp))