multiple fixes and re-subclass path to str

This commit is contained in:
Izalia Mae 2021-06-07 20:43:54 -04:00
parent 1ea42aeca9
commit b728df4bc0
12 changed files with 189 additions and 95 deletions

View file

@ -12,9 +12,9 @@ __version__ = '.'.join([str(v) for v in __version_tpl__])
from . import logging
izzylog = logging.get_logger('IzzyLib')
izzylog = logging.logger['IzzyLib']
from .dotdict import DotDict, LowerDotDict, DefaultDotDict, JsonEncoder
from .dotdict import DotDict, LowerDotDict, DefaultDotDict, MultiDotDict, JsonEncoder
from .misc import *
from .cache import LruCache, TtlCache
from .connection import Connection

View file

@ -107,6 +107,64 @@ class LowerDotDict(DotDict):
return super().update(data)
class MultiDotDict(DotDict):
def __getattr__(self, key):
return self.__getitem__(key)
def __setitem__(self, key, value):
try:
self.__getitem__(key.lower(), False).append(value)
except KeyError as e:
super().__setitem__(key.lower(), [value])
def __getitem__(self, key, single=True):
values = super().__getitem__(key.lower())
if single:
try:
return values[0]
except IndexError:
return None
return values
def update(self, data):
for k,v in data.items():
self[k] = v
def get(self, key, default=None):
try:
return self.__getitem__(key)
except KeyError:
return default
def getall(self, key):
try:
return super().__getitem__(key)
except KeyError as e:
if not default:
raise e from None
return default
def delone(self, key, value):
self.__getitem__(key, False).remove(value)
def delete(self, key):
self.pop(key)
class JsonEncoder(json.JSONEncoder):
def default(self, obj):
if not any(map(isinstance, [obj], [str, int, float, dict])):

View file

@ -81,12 +81,12 @@ class HttpUrllibClient:
filepath = Path(filepath)
path = filepath.parent
if not path.exists() and not create_dirs:
if not path.exists and not create_dirs:
raise FileNotFoundError(f'Path does not exist: {path}')
path.mkdir()
if filepath.exists():
if filepath.exists:
kwargs['headers']['range'] = f'bytes={filepath.size}'
resp = self.request(url, *args, stream=True, **kwargs)
@ -111,7 +111,7 @@ class HttpUrllibClient:
filepath = Path(filepath)
path = filepath.parent
if not path.exists() and not create_dirs:
if not path.exists and not create_dirs:
raise FileNotFoundError(f'Path does not exist: {path}')
path.mkdir()
@ -122,7 +122,7 @@ class HttpUrllibClient:
raise exceptions.HttpFileDownloadedError(f'Failed to download {url}: {resp.status}, body: {resp.body}')
if not filename:
filename = Path(url).stem()
filename = Path(url).stem
byte = BytesIO()
image = Image.open(BytesIO(resp.body))

View file

@ -159,7 +159,7 @@ def import_from_path(mod_path):
mod_path = Path(mod_path)
if mod_path.isdir():
if mod_path.isdir:
path = mod_path.join('__init__.py')
name = path.name
@ -167,7 +167,7 @@ def import_from_path(mod_path):
path = mod_path
name = path.name.replace('.py', '', -1)
spec = util.spec_from_file_location(name, path.str())
spec = util.spec_from_file_location(name, path)
module = util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
@ -189,16 +189,16 @@ def nfs_check(path):
return
proc = Path('/proc/mounts')
path = Path(path).resolve()
path = Path(path).resolve
if not proc.exists():
if not proc.exists:
return True
with proc.open() as fd:
for line in fd:
line = line.split()
if line[2] == 'nfs' and line[1] in path.str():
if line[2] == 'nfs' and line[1] in path:
return True
return False
@ -281,7 +281,7 @@ def prompt(prompt, default=None, valtype=str, options=[], password=False):
ret = valtype(value)
while valtype == Path and not ret.parent().exists():
while valtype == Path and not ret.parent.exists:
input_func('Parent directory doesn\'t exist')
ret = Path(input(prompt))

View file

@ -1,14 +1,18 @@
import pathlib
import os, shutil
from datetime import datetime
from functools import cached_property
from . import DotDict, JsonEncoder
class Path(pathlib.Path):
class Path(str):
def __init__(self, path, exist=True, missing=True, parents=True):
if str(path).startswith('~'):
path = pathlib.Path(path).expanduser()
str.__new__(Path, os.path.expanduser(path))
super().__init__(path)
else:
str.__new__(Path, path)
self.config = {
'missing': missing,
@ -17,18 +21,18 @@ class Path(pathlib.Path):
}
def __new__(cls, content):
return str.__new__(cls, content)
def __check_dir(self, path=None):
target = self if not path else Path(path)
if not self.parents and not target.parent().exists():
raise FileNotFoundError('Parent directories do not exist:', target.str())
if not self.parents and not target.parent.exists:
raise FileNotFoundError('Parent directories do not exist:', target)
if not self.exist and target.exists():
raise FileExistsError('File or directory already exists:', target.str())
def __parse_perm_octal(self, mode):
return mode if type(mode) == oct else eval(f'0o{mode}')
if not self.exist and target.exists:
raise FileExistsError('File or directory already exists:', target)
def append(self, text):
@ -41,8 +45,7 @@ class Path(pathlib.Path):
def chmod(self, mode=None):
octal = self.__parse_perm_octal(mode)
super().chmod(octal)
os.chmod(self, mode)
def copy(self, path, overwrite=False):
@ -51,21 +54,31 @@ class Path(pathlib.Path):
self.__check_dir(path)
if target.exists and overwrite:
target.delete
target.delete()
copyfile(self, target)
def join(self, path):
return Path(self.joinpath(path))
def delete(self):
if self.isdir:
rmtree(self)
else:
os.remove(self)
return not self.exists
def join(self, new_path):
return Path(os.path.join(self, new_path))
def json_load(self):
return DotDict(self.read())
return DotDict(read(self))
def json_save(self, data, indent=None):
with self.open('w') as fp:
with open(self, 'w') as fp:
fp.write(json.dumps(data, indent=indent, cls=JsonEncoder))
@ -74,97 +87,121 @@ class Path(pathlib.Path):
self.__check_dir(path)
if target.exists():
if target.exists:
target.delete()
self.symlink_to(path, target.isdir())
self.symlink_to(path, target.isdir)
def listdir(self, recursive=True):
if recursive:
return tuple(self.join(f) for dp, dn, fn in os.walk(self) for f in fn)
return [self.join(path) for path in os.listdir(self)]
def mkdir(self, mode=0o755):
self.__path.mkdir(mode, self.parents, self.exist)
if self.parents:
os.makedirs(self, mode, exist_ok=self.exist)
return True if self.__path.exists() else False
else:
os.makedir(self, mode, exist_ok=self.exist)
return self.exists
def move(self, path, overwrite=False):
self.copy(path, overwrite=overwrite)
self.delete()
if not overwrite and self.exists:
raise FileExistsError(f'Refusing to move file to existing destination: {path}')
shutil.move(self, path)
def touch(self, mode=0o666):
octal = __parse_perm_octal(mode)
self.__path.touch(octal, self.exist)
return self.exists()
def open(self, *args, **kwargs):
return open(self, *args, **kwargs)
@property
def delete(self):
if self.isdir():
rmtree(self)
def read(self):
fd = open(self)
data = fd.read()
fd.close()
else:
self.unlink()
return data
return not self.exists
def readlines(self):
fd = open(self)
data = fd.readlines()
fd.close()
return data
def touch(self, mode=0o644, utime=None):
timestamp = utime or datetime.now().timestamp()
with self.open('w+') as fd:
os.utime(self, (timestamp, timestamp))
self.chmod(mode)
return self.exists
@property
def exists(self):
return super().exists()
return os.path.exists(self)
@property
@cached_property
def home(self):
return Path(pathlib.Path.home())
return Path('~')
@property
@cached_property
def isdir(self):
return self.is_dir()
return os.path.isdir(self)
@property
@cached_property
def isfile(self):
return self.is_file()
return os.path.isfile(self)
@property
@cached_property
def islink(self):
return self.is_symlink()
@property
def listdir(self, recursive=True):
paths = self.iterdir() if recursive else os.listdir(self)
return [Path(path) for path in paths]
return os.path.islink(self)
@property
def mtime(self):
return os.path.getmtime(self.str())
return os.path.getmtime(self)
@property
@cached_property
def name(self):
return os.path.basename(self)
@cached_property
def parent(self):
return Path(super().parent)
return Path(os.path.dirname(self))
@property
def read(self):
return self.open().read()
@property
def readlines(self):
return self.open().readlines()
@property
@cached_property
def resolve(self):
return Path(super().resolve())
return Path(os.path.abspath(self))
@property
def size(self):
return self.stat().st_size
return os.path.getsize(self)
@cached_property
def stem(self):
return os.path.basename(self).split('.')[0]
@cached_property
def suffix(self):
return os.path.splitext(self)[1]

View file

@ -1,11 +1,11 @@
#!/usr/bin/env python3
from setuptools import setup
from setuptools import setup, find_namespace_packages
setup(
name="IzzyLib Base",
version='0.6.0',
packages=['izzylib'],
packages=find_namespace_packages(include=['izzylib']),
python_requires='>=3.7.0',
include_package_data=False,
author='Zoey Mae',

View file

@ -19,7 +19,7 @@ requires = [
setup(
name="IzzyLib HTTP Server",
version='0.6.0',
packages=['izzylib.http_server'],
packages=find_namespace_packages(include=['izzylib.http_server']),
python_requires='>=3.7.0',
install_requires=requires,
include_package_data=False,

View file

@ -12,7 +12,7 @@ requires = [
setup(
name="IzzyLib Requests Client",
version='0.6.0',
packages=['izzylib.http_requests_client'],
packages=find_namespace_packages(include=['izzylib.http_requests_client']),
python_requires='>=3.7.0',
install_requires=requires,
include_package_data=False,

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3
from setuptools import setup
from setuptools import setup, find_namespace_packages
requires = [
@ -15,7 +15,7 @@ requires = [
setup(
name="IzzyLib SQL",
version='0.6.0',
packages=['izzylib.sql'],
packages=find_namespace_packages(include=['izzylib.sql']),
python_requires='>=3.7.0',
install_requires=requires,
include_package_data=False,

View file

@ -22,7 +22,7 @@ class Template(Environment):
self.func_context = context
for path in search:
self.__add_search_path(path)
self.__add_search_path(Path(path))
super().__init__(
loader=ChoiceLoader([FileSystemLoader(path) for path in self.search]),
@ -46,13 +46,12 @@ class Template(Environment):
def __add_search_path(self, path):
tpl_path = Path(path)
if not path.exists:
raise FileNotFoundError(f'Cannot find search path: {path}')
if not tpl_path.exists():
raise FileNotFoundError('Cannot find search path:', tpl_path.str())
if path not in self.search:
self.search.append(path)
if tpl_path.str() not in self.search:
self.search.append(tpl_path.str())
def setContext(self, context):
if not hasattr(context, '__call__'):

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3
from setuptools import setup
from setuptools import setup, find_namespace_packages
requires = [
@ -13,7 +13,7 @@ requires = [
setup(
name="IzzyLib Templates",
version='0.6.0',
packages=['izzylib.template'],
packages=find_namespace_packages(include=['izzylib.template']),
python_requires='>=3.7.0',
install_requires=requires,
include_package_data=False,

View file

@ -13,7 +13,7 @@ requires = [
setup(
name="IzzyLib TinyDB",
version='0.6.0',
packages=['izzylib.tinydb'],
packages=find_namespace_packages(include=['izzylib.tinydb']),
python_requires='>=3.7.0',
install_requires=requires,
include_package_data=False,