From c7606472683bcdca4fc739a0932836d42f0ba372 Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Wed, 24 Mar 2021 20:52:17 -0400 Subject: [PATCH 01/74] misc.Path:fix user dir expanding --- IzzyLib/misc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/IzzyLib/misc.py b/IzzyLib/misc.py index 7045e62..4542bae 100644 --- a/IzzyLib/misc.py +++ b/IzzyLib/misc.py @@ -323,7 +323,7 @@ class Path(object): self.__path = Pathlib(str(path)) if str(path).startswith('~'): - self.__path == self.__path.expanduser() + self.__path = self.__path.expanduser() self.json = DotDict({}) self.exist = exist From 1dc8d9162f40618e33c96bdb4f3225c919c25d56 Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Thu, 25 Mar 2021 21:55:59 -0400 Subject: [PATCH 02/74] http: Add client based on requests module --- IzzyLib/http.py | 216 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 215 insertions(+), 1 deletion(-) diff --git a/IzzyLib/http.py b/IzzyLib/http.py index 4f915d9..d320573 100644 --- a/IzzyLib/http.py +++ b/IzzyLib/http.py @@ -12,6 +12,13 @@ from urllib.request import Request, urlopen from . import error, __version__ + +try: + import requests +except ImportError: + logging.verbose('Requests module not found. RequestsClient disabled') + requests = False + try: from Crypto.Hash import SHA256 from Crypto.PublicKey import RSA @@ -35,6 +42,7 @@ except ImportError: Client = None +methods = ['connect', 'delete', 'get', 'head', 'options', 'patch', 'post', 'put', 'trace'] class HttpClient(object): @@ -107,7 +115,7 @@ class HttpClient(object): request = Request(url, data=data, headers=parsed_headers, method=method) if self.proxy.enabled: - request.set_proxy(f'{self.proxy.host}:{self.proxy.host}', self.proxy.ptype) + request.set_proxy(f'{self.proxy.host}:{self.proxy.port}', self.proxy.ptype) return request @@ -223,6 +231,212 @@ class HttpResponse(object): return json.dumps(self.json().asDict(), indent=indent) +class RequestsClient(object): + def __init__(self, headers={}, useragent=f'IzzyLib/{__version__}', appagent=None, proxy_type='https', proxy_host=None, proxy_port=None): + proxy_ports = { + 'http': 80, + 'https': 443 + } + + if proxy_type not in ['http', 'https']: + raise ValueError(f'Not a valid proxy type: {proxy_type}') + + self.headers=headers + self.agent = f'{useragent} ({appagent})' if appagent else useragent + self.proxy = DotDict({ + 'enabled': True if proxy_host else False, + 'ptype': proxy_type, + 'host': proxy_host, + 'port': proxy_ports[proxy_type] if not proxy_port else proxy_port + }) + + self.SetGlobal = SetClient + + + def __sign_request(self, request, privkey, keyid): + if not crypto_enabled: + logging.error('Crypto functions disabled') + return + + request.add_header('(request-target)', f'{request.method.lower()} {request.path}') + request.add_header('host', request.host) + request.add_header('date', datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT')) + + if request.body: + body_hash = b64encode(SHA256.new(request.body).digest()).decode("UTF-8") + request.add_header('digest', f'SHA-256={body_hash}') + request.add_header('content-length', len(request.body)) + + sig = { + 'keyId': keyid, + 'algorithm': 'rsa-sha256', + 'headers': ' '.join([k.lower() for k in request.headers.keys()]), + 'signature': b64encode(PkcsHeaders(privkey, request.headers)).decode('UTF-8') + } + + sig_items = [f'{k}="{v}"' for k,v in sig.items()] + sig_string = ','.join(sig_items) + + request.add_header('signature', sig_string) + + request.remove_header('(request-target)') + request.remove_header('host') + + + def request(self, *args, method='get', **kwargs): + if method.lower() not in methods: + raise ValueError(f'Invalid method: {method}') + + request = RequestsRequest(self, *args, method=method.lower(), **kwargs) + return RequestsResponse(request.send()) + + + def file(self, url, filepath, *args, filename=None, **kwargs): + resp = self.request(url, *args, **kwargs) + + if resp.status != 200: + logging.error(f'Failed to download {url}:', resp.status, resp.body) + return False + + return resp.save(filepath) + + + def image(self, url, filepath, *args, filename=None, ext='png', dimensions=(50, 50), **kwargs): + if not Image: + logging.error('Pillow module is not installed') + return + + resp = self.request(url, *args, **kwargs) + + if resp.status != 200: + logging.error(f'Failed to download {url}:', resp.status, resp.body) + return False + + if not filename: + filename = Path(url).stem() + + path = Path(filepath) + + if not path.exists(): + logging.error('Path does not exist:', path) + return False + + byte = BytesIO() + image = Image.open(BytesIO(resp.body)) + image.thumbnail(dimensions) + image.save(byte, format=ext.upper()) + + with path.join(filename).open('wb') as fd: + fd.write(byte.getvalue()) + + + def json(self, *args, **kwargs): + return self.dict(*args, **kwargs) + + + def dict(self, *args, headers={}, activity=True, **kwargs): + json_type = 'activity+json' if activity else 'json' + headers.update({ + 'accept': f'application/{json_type}' + }) + return self.request(*args, headers=headers, **kwargs).dict + + + def signed_request(self, privkey, keyid, *args, **kwargs): + request = RequestsRequest(self, *args, **kwargs) + self.__sign_request(request, privkey, keyid) + return RequestsResponse(request.send()) + + +class RequestsRequest(object): + def __init__(self, client, url, data=None, headers={}, query={}, method='get'): + self.args = [url] + self.kwargs = {'params': query} + self.method = method.lower() + self.client = client + + new_headers = client.headers.copy() + new_headers.update(headers) + + parsed_headers = {k.lower(): v for k,v in new_headers.items()} + + if not parsed_headers.get('user-agent'): + parsed_headers['user-agent'] = client.agent + + self.kwargs['headers'] = new_headers + self.kwargs['data'] = data + + if client.proxy.enabled: + self.kwargs['proxies'] = {self.proxy.ptype: f'{self.proxy.ptype}://{self.proxy.host}:{self.proxy.port}'} + + + def send(self): + func = getattr(requests, self.method) + return func(*self.args, **self.kwargs) + + +class RequestsResponse(object): + def __init__(self, response): + self.response = response + self.data = b'' + self.headers = DefaultDict({k.lower(): v.lower() for k,v in response.headers.items()}) + self.status = response.status_code + self.url = response.url + + + def chunks(self, size=256): + return self.response.iter_content(chunk_size=256) + + + @property + def body(self): + for chunk in self.chunks(): + self.data += chunk + + return self.data + + + @property + def text(self): + if not self.data: + return self.body.decode(self.response.encoding) + + return self.data.decode(self.response.encoding) + + + @property + def dict(self): + try: + return DotDict(self.text) + except Exception as e: + return DotDict() + + + @property + def json(self): + return json.dumps(self.dict) + + + @property + def json_pretty(self, indent=4): + return json.dumps(self.dict, indent=indent) + + + def save(self, path, overwrite=True): + path = Path(path) + parent = path.parent() + + if not parent.exists(): + raise ValueError(f'Path does not exist: {parent}') + + if overwrite and path.exists(): + path.delete() + + with path.open('wb') as fd: + for chunk in self.chunks(): + fd.write(chunk) + + def VerifyRequest(request: SanicRequest, actor: dict): '''Verify a header signature from a sanic request From 3887a68db948e06f63052b7c4d399eb66dc9f439 Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Tue, 6 Apr 2021 21:31:07 -0400 Subject: [PATCH 03/74] database: add session tracking --- IzzyLib/database.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/IzzyLib/database.py b/IzzyLib/database.py index a71f00f..0624b69 100644 --- a/IzzyLib/database.py +++ b/IzzyLib/database.py @@ -6,7 +6,7 @@ from sqlalchemy import create_engine, ForeignKey, MetaData, Table from sqlalchemy import Column as SqlColumn, types as Types #from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.exc import OperationalError, ProgrammingError -from sqlalchemy.orm import sessionmaker +from sqlalchemy.orm import scoped_session, sessionmaker from . import logging from .cache import LRUCache @@ -27,6 +27,7 @@ class DataBase(): session_class = kwargs.get('session_class', Session) self.session = lambda trans=True: session_class(self, trans) + self.sessions = {} self.SetupCache() @@ -109,7 +110,7 @@ class Session(object): def __init__(self, db, trans=True): self.db = db self.classes = self.db.classes - self.session = sessionmaker(bind=db.db)() + self.session = scoped_session(sessionmaker(bind=db.db))() self.table = self.db.table self.cache = self.db.cache self.trans = trans @@ -121,6 +122,7 @@ class Session(object): self.rollback = self.s.rollback self.query = self.s.query self.execute = self.s.execute + self.close = self.s.close self._setup() @@ -130,6 +132,7 @@ class Session(object): def __enter__(self): self.sessionid = RandomGen(10) + self.db.sessions[self.sessionid] = self return self @@ -137,8 +140,9 @@ class Session(object): if tb: self.rollback() - else: - self.commit() + self.commit() + self.close() + del self.db.sessions[self.sessionid] def _setup(self): From 0d18205d1792ea1ea2037a1be25af113b5a949ae Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Wed, 14 Apr 2021 08:12:34 -0400 Subject: [PATCH 04/74] database: track sessions and allow threads with sql, misc: new functions --- IzzyLib/database.py | 43 ++++++++++++++++++------------ IzzyLib/misc.py | 65 +++++++++++++++++++++++++++++++++++++-------- 2 files changed, 80 insertions(+), 28 deletions(-) diff --git a/IzzyLib/database.py b/IzzyLib/database.py index 0624b69..79372c0 100644 --- a/IzzyLib/database.py +++ b/IzzyLib/database.py @@ -1,25 +1,22 @@ -import sys +import json, sys, threading, time from contextlib import contextmanager from datetime import datetime from sqlalchemy import create_engine, ForeignKey, MetaData, Table from sqlalchemy import Column as SqlColumn, types as Types -#from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.exc import OperationalError, ProgrammingError from sqlalchemy.orm import scoped_session, sessionmaker from . import logging from .cache import LRUCache -from .misc import DotDict, RandomGen, NfsCheck, PrintMethods - +from .misc import DotDict, RandomGen, NfsCheck, PrintMethods, Path SqlTypes = DotDict({t.lower(): getattr(Types, t) for t in dir(Types) if not t.startswith('_')}) class DataBase(): - def __init__(self, dbtype='postgresql+psycopg2', tables={}, **kwargs): - self.engine_string = self.__engine_string(dbtype, kwargs) - self.db = create_engine(self.engine_string) + def __init__(self, dbtype='postgresql+pg8000', tables={}, **kwargs): + self.db = self.__create_engine(dbtype, kwargs) self.table = Tables(self, tables) self.table_names = tables.keys() self.classes = kwargs.get('row_classes', CustomRows()) @@ -32,7 +29,10 @@ class DataBase(): self.SetupCache() - def __engine_string(self, dbtype, kwargs): + def __create_engine(self, dbtype, kwargs): + engine_args = [] + engine_kwargs = {} + if not kwargs.get('database'): raise MissingDatabaseError('Database not set') @@ -43,6 +43,7 @@ class DataBase(): logging.error('Database file is on an NFS share which does not support locking. Any writes to the database will fail') engine_string += '/' + kwargs.get('database') + engine_kwargs['connect_args'] = {'check_same_thread': False} else: user = kwargs.get('user') @@ -64,7 +65,7 @@ class DataBase(): else: engine_string += f'{host}:{port}/{name}' - return engine_string + return create_engine(engine_string, *engine_args, **engine_kwargs) def close(self): @@ -110,7 +111,7 @@ class Session(object): def __init__(self, db, trans=True): self.db = db self.classes = self.db.classes - self.session = scoped_session(sessionmaker(bind=db.db))() + self.session = sessionmaker(bind=db.db)() self.table = self.db.table self.cache = self.db.cache self.trans = trans @@ -126,9 +127,6 @@ class Session(object): self._setup() - if not self.trans: - self.commit() - def __enter__(self): self.sessionid = RandomGen(10) @@ -149,6 +147,11 @@ class Session(object): pass + @property + def dirty(self): + return any([self.s.new, self.s.dirty, self.s.deleted]) + + def count(self, table_name, **kwargs): return self.query(self.table[table_name]).filter_by(**kwargs).count() @@ -178,6 +181,11 @@ class Session(object): return [RowClass(table_name, row, self) for row in rows] + def search(self, *args, **kwargs): + kwargs.pop('single', None) + return self.fetch(*args, single=False, **kwargs) + + def insert(self, table_name, **kwargs): row = self.fetch(table_name, **kwargs) @@ -203,10 +211,8 @@ class Session(object): raise ValueError('Missing row ID or table') tclass = self.table[table] - self.execute(tclass.update().where(tclass.c.id == rowid).values(**data)) - def remove(self, table=None, rowid=None, row=None): if row: rowid = row.id @@ -348,7 +354,10 @@ class CustomRows(object): def update_session(self, s, dict_data={}, **data): - return s.update(row=self, **dict_data, **data) + dict_data.update(data) + self._update(dict_data) + print(dict_data) + return s.update(row=self, **dict_data) class Tables(DotDict): @@ -387,4 +396,4 @@ def Column(name, stype=None, fkey=None, **kwargs): class MissingDatabaseError(Exception): - '''raise when the "database" kwargs is not set''' + '''raise when the "database" kwarg is not set''' diff --git a/IzzyLib/misc.py b/IzzyLib/misc.py index 4542bae..b1ddb8b 100644 --- a/IzzyLib/misc.py +++ b/IzzyLib/misc.py @@ -153,6 +153,16 @@ def NfsCheck(path): return False +def PortCheck(port, address='127.0.0.1', tcp=True): + with socket.socket(socket.AF_INET, socket.SOCK_STREAM if tcp else socket.SOCK_DGRAM) as s: + try: + return not s.connect_ex((address, port)) == 0 + + except socket.error as e: + print(e) + return False + + def PrintMethods(object, include_underscore=False): for line in dir(object): if line.startswith('_'): @@ -162,6 +172,31 @@ def PrintMethods(object, include_underscore=False): else: print(line) + +class Connection(socket.socket): + def __init__(self, address='127.0.0.1', port=8080, tcp=True): + super().__init__(socket.AF_INET, socket.SOCK_STREAM if tcp else socket.SOCK_DGRAM) + self.address = address + self.port = port + + + def __enter__(self): + self.connect((self.address, self.port)) + return self + + + def __exit__(self, exctype, value, tb): + self.close() + + + def send(self, msg): + self.sendall(msg) + + + def recieve(self, size=8192): + return self.recv(size) + + class DotDict(dict): def __init__(self, value=None, **kwargs): '''Python dictionary, but variables can be set/get via attributes @@ -171,7 +206,6 @@ class DotDict(dict): kwargs: key/value pairs to set on init. Overrides identical keys set by 'value' ''' super().__init__() - data = {} if isinstance(value, (str, bytes)): self.fromJson(value) @@ -265,7 +299,7 @@ class DotDict(dict): def toJson(self, indent=None, **kwargs): if 'cls' not in kwargs: - kwargs['cls'] = DotDictEncoder + kwargs['cls'] = JsonEncoder return json.dumps(dict(self), indent=indent, **kwargs) @@ -275,6 +309,15 @@ class DotDict(dict): self.update(data) + def load_json(self, path: str=None): + self.update(Path(path).load_json()) + + + def save_json(self, path: str, **kwargs): + with Path(path).open(w) as fd: + write(self.toJson(*kwargs)) + + class DefaultDict(DotDict): def __getattr__(self, key): try: @@ -325,7 +368,7 @@ class Path(object): if str(path).startswith('~'): self.__path = self.__path.expanduser() - self.json = DotDict({}) + self.json = DotDict() self.exist = exist self.missing = missing self.parents = parents @@ -475,24 +518,24 @@ class Path(object): return True if self.__path.exists() else False - def loadJson(self): + def load_json(self): self.json = DotDict(self.read()) return self.json - def updateJson(self, data={}): + def save_json(self, indent=None): + with self.__path.open('w') as fp: + fp.write(json.dumps(self.json.asDict(), indent=indent, cls=JsonEncoder)) + + + def update_json(self, data={}): if type(data) == str: data = json.loads(data) self.json.update(data) - def storeJson(self, indent=None): - with self.__path.open('w') as fp: - fp.write(json.dumps(self.json.asDict(), indent=indent)) - - # This needs to be extended to handle dirs with files/sub-dirs def delete(self): if self.isdir(): @@ -516,7 +559,7 @@ class Path(object): return self.open().readlines() -class DotDictEncoder(json.JSONEncoder): +class JsonEncoder(json.JSONEncoder): def default(self, obj): if type(obj) not in [str, int, float, dict]: return str(obj) From 7f23bd9ece53c51301af1e95187612eeee654284 Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Thu, 15 Apr 2021 17:01:22 -0400 Subject: [PATCH 05/74] minor changes --- IzzyLib/database.py | 1 - IzzyLib/logging.py | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/IzzyLib/database.py b/IzzyLib/database.py index 79372c0..9715724 100644 --- a/IzzyLib/database.py +++ b/IzzyLib/database.py @@ -356,7 +356,6 @@ class CustomRows(object): def update_session(self, s, dict_data={}, **data): dict_data.update(data) self._update(dict_data) - print(dict_data) return s.update(row=self, **dict_data) diff --git a/IzzyLib/logging.py b/IzzyLib/logging.py index 78dee25..cec3fca 100644 --- a/IzzyLib/logging.py +++ b/IzzyLib/logging.py @@ -194,6 +194,7 @@ DefaultLog = logger['default'] '''aliases for default logger's log output functions''' +log = DefaultLog.log critical = DefaultLog.critical error = DefaultLog.error warning = DefaultLog.warning From 48f0178405f0a04d498287eb4e828cfa1218fb84 Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Sun, 18 Apr 2021 01:49:58 -0400 Subject: [PATCH 06/74] database: add optional session arg to delete and update --- IzzyLib/database.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/IzzyLib/database.py b/IzzyLib/database.py index 9715724..4d13891 100644 --- a/IzzyLib/database.py +++ b/IzzyLib/database.py @@ -336,7 +336,10 @@ class CustomRows(object): self[k] = v - def delete(self): + def delete(self, s=None): + if s: + return self.delete_session(s) + with self._db.session() as s: return self.delete_session(s) @@ -345,10 +348,13 @@ class CustomRows(object): return s.remove(row=self) - def update(self, dict_data={}, **data): + def update(self, dict_data={}, s=None, **data): dict_data.update(data) self._update(dict_data) + if s: + return self.update_session(s, **self._filter_data()) + with self._db.session() as s: s.update(row=self, **self._filter_data()) From 096dfd159b87c1b42a2b0656138c8d586becbb8b Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Mon, 19 Apr 2021 10:47:26 -0400 Subject: [PATCH 07/74] http: make RequetsClient.file use streaming --- IzzyLib/http.py | 26 ++++++++++++++++++-------- IzzyLib/misc.py | 4 ++++ 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/IzzyLib/http.py b/IzzyLib/http.py index d320573..cded316 100644 --- a/IzzyLib/http.py +++ b/IzzyLib/http.py @@ -97,7 +97,7 @@ class HttpClient(object): request.remove_header('host') - def __build_request(self, url, data=None, headers={}, method='GET'): + def __build_request(self, url, data=None, headers={}, method='GET', stream=False): new_headers = self.headers.copy() new_headers.update(headers) @@ -112,7 +112,7 @@ class HttpClient(object): if isinstance(data, str): data = data.encode('UTF-8') - request = Request(url, data=data, headers=parsed_headers, method=method) + request = Request(url, data=data, headers=parsed_headers, method=method, stream=stream) if self.proxy.enabled: request.set_proxy(f'{self.proxy.host}:{self.proxy.port}', self.proxy.ptype) @@ -136,21 +136,31 @@ class HttpClient(object): return HttpResponse(response) - def file(self, url, filepath, *args, filename=None, **kwargs): - resp = self.request(url, *args, **kwargs) + def file(self, url, filepath, *args, filename=None, size=2048, **kwargs): + path = Path(filepath) + filepath = path.join(filename if filename else Path(url).name) + + if filepath.exists(): + kwargs['headers']['range'] = f'bytes={filepath.size}' + + resp = self.request(url, *args, stream=True, **kwargs) + + if not resp.headers.get('content-length'): + logging.verbose('File already downloaded fully') + return True if resp.status != 200: logging.error(f'Failed to download {url}:', resp.status, resp.body) return False - path = Path(filepath) - if not path.exists(): logging.error('Path does not exist:', path) return False - with path.join(filename).open('wb') as fd: - fd.write(resp.body) + with filepath.open('ab') as fd: + for chunk in resp.chunks(size): + fd.write(chunk) + return True diff --git a/IzzyLib/misc.py b/IzzyLib/misc.py index b1ddb8b..657e558 100644 --- a/IzzyLib/misc.py +++ b/IzzyLib/misc.py @@ -491,6 +491,10 @@ class Path(object): return os.path.getmtime(self.str()) + def size(self): + return self.__path.stat().st_size + + def link(self, path): target = Path(path) From d0bf77cade06415688e8b0f4799e8e92dd8aad8c Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Thu, 29 Apr 2021 13:12:21 -0400 Subject: [PATCH 08/74] database: fix CreateDatabase function --- IzzyLib/database.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/IzzyLib/database.py b/IzzyLib/database.py index 4d13891..f2c7039 100644 --- a/IzzyLib/database.py +++ b/IzzyLib/database.py @@ -82,7 +82,7 @@ class DataBase(): def CreateDatabase(self): - if self.engine_string.startswith('postgresql'): + if self.db.url.get_backend_name() == 'postgresql': predb = create_engine(db.engine_string.replace(config.db.name, 'postgres', -1)) conn = predb.connect() conn.execute('commit') From 820a5b4772fab8696cde35990eb7e251ab7aadf1 Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Sun, 2 May 2021 14:15:11 -0400 Subject: [PATCH 09/74] add incomplete json-based database classes --- IzzyLib/database_pysondb.py | 353 ++++++++++++++++++++++++++++++++++++ IzzyLib/database_tiny.py | 249 +++++++++++++++++++++++++ 2 files changed, 602 insertions(+) create mode 100644 IzzyLib/database_pysondb.py create mode 100644 IzzyLib/database_tiny.py diff --git a/IzzyLib/database_pysondb.py b/IzzyLib/database_pysondb.py new file mode 100644 index 0000000..c601edb --- /dev/null +++ b/IzzyLib/database_pysondb.py @@ -0,0 +1,353 @@ +import asyncio +import base64 +import datetime +import filelock +import json +import multiprocessing +import operator +import pysondb +import queue +import random + +from pysondb.db import JsonDatabase, IdNotFoundError + +from . import misc + + +class Database(multiprocessing.Process): + def __init__(self, dbpath: misc.Path, tables: dict=None): + multiprocessing.Process.__init__(self, daemon=True) + + self.dbpath = dbpath + self.tables = tables + self.shutdown = False + self.port = self._setup_port() + self.token = misc.RandomGen() + print(self.port) + + self.fetch = lambda *args, **kwargs: self.send_message('fetch', *args, **kwargs) + self.search = lambda *args, **kwargs: self.send_message('search', *args, **kwargs) + self.insert = lambda *args, **kwargs: self.send_message('insert', *args, **kwargs) + self.remove = lambda *args, **kwargs: self.send_message('remove', *args, **kwargs) + + self.start() + + + def run(self): + self.db = DatabaseProcess(self.dbpath, self.tables) + print(self.port) + server = asyncio.create_server(process_queue, '127.0.0.1', self.port) + + loop = asyncio.new_event_loop() + loop.run_until_complete(server) + loop.run_forever() + + + def close(self): + self.terminate() + self.join(timeout=5) + + + def _setup_port(self): + port = None + + while True: + port = random.randint(8096, 16394) + + if misc.PortCheck(port) == True: + return port + + + def get_action(self, action): + return getattr(self.db, action) + + + def send_message(self, action, table, *args, **kwargs): + data = { + 'token': self.token, + 'action': action, + 'table': table, + 'args': args, + 'kwargs': kwargs + } + + with self.socket as s: + s.send(json.dumps(data)) + return s.recieve(16 * 1024 * 1024) + + + @property + def socket(self): + return misc.Connection(port=self.port) + + + async def process_queue(self, reader, writer): + data = misc.DotDict(await reader.read(16 * 1024 * 1024)) + + if data.token != self.token: + return + + if data.action == 'close': + self._shutdown = True + + new_data = self.get_action(data.action)(data.table, *args, **kwargs) + + if isinstance(new_data, dict): + writer.write(json.dumps(new_data)) + await writer.drain() + + writer.close() + + async def pipe_listener(self): + pass + + +class DatabaseProcess(misc.DotDict): + def __init__(self, dbpath: misc.Path, tables: dict=None): + dbpath = misc.Path(dbpath) + super().__init__() + + self.path = misc.Path(dbpath).resolve() + self.metadata = misc.DotDict(**{ + 'path': self.path.join('metadata.json'), + 'lock': self.path.join('metadata.json.lock'), + 'version': 0 + }) + + self._closed = False + self.__setup_database(tables) + + + def __setup_database(self, tables): + self.path.mkdir() + self.load_meta() + + for name, columns in tables.items(): + self[name] = columns if type(columns) == Table else Table(name, columns) + + if not self[name].db: + self[name].setup(self) + + + def load_meta(self): + if self.metadata.path.exists(): + with filelock.FileLock(self.metadata.lock.str()): + data = self.metadata.path.load_json() + self.metadata.update(data) + + + def save_meta(self): + with filelock.FileLock(self.metadata.lock.str()): + data = self.metadata.copy() + data.pop('path') + data.pop('lock') + + self.metadata.path.update_json(data) + self.metadata.path.save_json() + + + def close(self): + self.save_meta() + self._closed = True + + + def fetch(self, table, *args, **kwargs): + return self[table].fetch(*args, **kwargs) + + + def search(self, table, *args, **kwargs): + return self[table].search(*args, **kwargs) + + + def insert(self, table, *args, **kwargs): + return self[table].insert(*args, **kwargs) + + + def remove(self, table, *args, **kwargs): + return self[table].remove(*args, **kwargs) + + + def migrate(self, table=None): + tables = [self[table]] if table else self.table + + for name, table in tables: + for row in table.search(): + table.update(row.id, ) + + +class Table(JsonDatabase): + def __init__(self, name: str, columns: dict={}): + self.db = None + self.name = name + self.columns = {} + self.add_column('id') + + for name, col in columns.items(): + if name != 'id': + self.add_column(name, *col) + + + def setup(self, db): + self.db = db + tablefile = db.path.join(f'table_{self.name}.json') + + if not tablefile.exists(): + tablefile.touch(mode=0o644) + with tablefile.open('w') as fd: + fd.write('{"data": []}') + + super().__init__(tablefile.str()) + + + def add_column(self, name: str, type: str='str', default: bool=None, nullable: bool=True, primary_key: bool=False): + if name == 'id': + type = 'int' + nullable = False + primary_key = True + + self.columns[name] = misc.DotDict({ + 'default': default, + 'type': type, + 'primary_key': primary_key, + 'nullable': nullable + }) + + + def fetch(self, single=True, orderby=None, reverse=False, **kwargs): + if self.db._closed: + return logging.error('Database closed') + + if not kwargs: + rows = DBRows(self, self.getAll()) + single = False + + else: + rows = DBRows(self, self.getBy(kwargs)) + + if single: + return rows[0] if rows else None + + return rows if not orderby else sorted(rows, key=operator.itemgetter(orderby), reverse=reverse) + + + def search(self, orderby=None, reverse=None, **kwargs): + self.fetch(single=False, orderby=orderby, reverse=reverse, **kwargs) + + + def insert(self, row=None, rowid=None, **kwargs): + if self.db._closed: + return logging.error('Database closed') + + new_data = {} + + for name, col in self.columns.items(): + raw_value = kwargs.get(name, col.default) + value = serialize(raw_value, col.type) + + if not value and not col.nullable: + raise ValueError(f'Column "{name}" cannot be empty') + + new_data[name] = value + + if row: + rowid = row.id + + if rowid: + return self.update({'id': rowid}, new_data) + + return self.add(new_data) + + + def delete(self, rowid): + with self.lock: + with open(self.filename, "r+") as db_file: + db_data = self._get_load_function()(db_file) + result = [] + found = False + + for d in db_data["data"]: + print(d) + if rowid in d: + found = True + + else: + result.append(d) + + if not found: + raise IdNotFoundError(kwargs) + + db_data["data"] = result + db_file.seek(0) + db_file.truncate() + self._get_dump_function()(db_data, db_file) + + return True + + + def remove(self, row=None, rowid=None, **kwargs): + if self.db._closed: + return logging.error('Database closed') + + if row or rowid: + return self.remove({'id': rowid or row.id}) + + return self.delete(kwargs) + + + def _get_dump_function(self): + return lambda *args, **kwargs: json.dump(*args, indent=2, **kwargs) + + +def serialize(data, dtype): + types = { + 'datetime': lambda arg: arg.timestamp(), + 'dotdict': lambda arg: arg.toDict(), + 'bytes': lambda arg: base64.b64encode(arg).decode('ascii'), + 'bool': misc.Boolean, + 'int': int, + 'path': lambda arg: arg.str() + } + + if data != None: + serial_type = types.get(dtype) + return serial_type(data) if serial_type else data + + return data + + +def deserialize(data, dtype): + types = { + 'datetime': datetime.datetime.fromtimestamp, + 'dotdict': misc.DotDict, + 'dict': misc.DotDict, + 'bytes': lambda: base64.b64decode, + 'path': misc.Path + } + + return types.get(dtype)(data) if data else None + + + + +def DBRows(table, rows): + return [DBRow(table, row) for row in rows] + + +class DBRow(misc.DotDict): + def __init__(self, table, row): + super().__init(**{k: deserialize(row[v], v.type) for k,v in table.items()}) + self.table = table + + + def __str__(self): + data = ', '.join(f'{k}={v}' for k,v in self.items()) + return + + + def update(self, data={}): + super().update(data) + self.table.update(rowid=self.id, **self) + + + def remove(self): + self.table.remove(rowid=self.id) diff --git a/IzzyLib/database_tiny.py b/IzzyLib/database_tiny.py new file mode 100644 index 0000000..258b465 --- /dev/null +++ b/IzzyLib/database_tiny.py @@ -0,0 +1,249 @@ +import base64 +import json +import operator +import queue +import threading +import time + +import tinydb +import tinydb_serialization + +from . import misc + + +class AwaitingResult(object): + pass + + +class DataBase(tinydb.TinyDB): + def __init__(self, dbfile: misc.Path, queue_limit: int=64, serializers: list=[]): + options = { + 'indent': 2, + 'separators': (',', ': '), + } + + serialization = tinydb_serialization.SerializationMiddleware(ThreadSupport) + serialization.register_serializer(tinydb_serialization.serializers.DateTimeSerializer(), 'TinyDate') + serialization.register_serializer(ByteSerializer(), 'TinyBytes') + serialization.register_serializer(PathSerialize(), 'IzzyLibPath') + serialization.register_serializer(DotDictSerialize(), 'IzzyLibDotDict') + + for serializer in serializers: + serialization.register_serializer(serializer(), serializer.__class__.__name__) + + options['storage'] = serialization + + super().__init__(dbfile, **options) + + self.dbfile = dbfile + self.queue = queue.Queue(maxsize=queue_limit) + self.sessions = {} + + + @property + def session(self): + return TinySession(self) + + + def fetch(self, table, single=True, orderby=None, reverse=False, **kwargs): + query = tinydb.Query() + + if not kwargs: + rows = TinyRows(self, self.table(table).all()) + single = False + + else: + rows = TinyRows(self, self.table(table).search(query.fragment(kwargs))) + + if single: + return rows[0] if rows else None + + return rows if not orderby else sorted(rows, key=operator.itemgetter(orderby), reverse=reverse) + + + def insert(self, table, row=None, rowid=None, **kwargs): + if row: + rowid = row.doc_id + + elif not rowid: + row = self.fetch(table, **kwargs) + rowid = row.doc_id if row else None + + if rowid: + return self.table(table).update(kwargs, doc_ids=[rowid]) + + return self.table(table).insert(kwargs) + + + def remove(self, table, row=None, rowid=None, **kwargs): + query = tinydb.Query() + + if row or rowid: + rowid = rowid or row.doc_id + return self.table(table).remove(doc_ids=[row.doc_id]) + + return self.table(table).remove(query.fragment(kwargs)) + + +def TinyRows(db, rows): + return [TinyRow(db, row) for row in rows] + + +class TinyRow(misc.DotDict): + def __init__(self, db, row): + super().__init({'id': row.doc_id}) + super().update({k: v for k,v in row.items()}) + + + def update(self, data={}): + db.update(rowid=self.id, **data) + super().update(data) + + + def remove(self): + db.remove(rowid=self.id) + + +class ThreadSupport(tinydb.storages.JSONStorage): + def __init__(self, filename, *args, **kwargs): + super().__init__(filename, *args, **kwargs) + + self._thread_event = threading.Event() + self._shutdown = False + self._results = {} + self._queue = queue.Queue() + + self._lock = threading.Lock() + self._thread = threading.Thread(target=self.process_queue) + self._thread.daemon = True + self._thread.start() + + ## send all storage commands to the queue + def read(self): + data = self.queue_put('read') + return data + + + def write(self, data): + self.queue_put('write', data) + + + def close(self): + self.queue_put('close') + + + def get_action(self, action): + return getattr(super(), action) + + + def get_result(self, qid): + with self._lock: + return self._results[qid] + + + def set_result(self, qid, data=AwaitingResult): + with self._lock: + self._results[qid] = data + + + def pop_result(self, qid): + with self._lock: + return self._result.pop(qid) + + + ## queue + def process_queue(self): + while not self._thread_event.is_set(): + if not self._queue.empty(): + qid, action, args, kwargs = self._queue.get(block=False) + + if qid not in self._results: + self.set_result(qid) + if action == 'close': + self._shutdown = True + + func = self.get_action(action) + + if action == 'read': + self.set_result(qid, func(*args, **kwargs)) + + else: + time.sleep(0.1) + + if self._shutdown: + self.get_action('close')() + return + + + def queue_put(self, func, *args, **kwargs): + if self._shutdown: + logging.error('Storage has been closed. Refusing to send more commands') + return + + qid = misc.RandomGen() + + self._queue.put((qid, func, args, kwargs)) + + if func != 'read': + return + + sleep_time = 0.0 + + while self.get_result(qid) == AwaitingResult: + time.sleep(0.1) + sleep_time += 0.1 + + if sleep_time >= 5.0: + raise TimeoutError(f'Timeout on "{func}" with args: {args}, {kwargs}') + + result = self.pop_result(qid) + print(result) + return result + + +class ByteSerializer(tinydb_serialization.Serializer): + OBJ_CLASS = bytes + + def encode(self, obj): + #print('encode', self.__class__.__name__, obj) + return base64.b64encode(obj).decode('ascii') + + def decode(self, obj): + #print('decode', self.__class__.__name__, obj) + return base64.b64decode(obj) + + +class DictSerializer(tinydb_serialization.Serializer): + OBJ_CLASS = dict + + def encode(self, obj): + #print('encode', self.__class__.__name__, obj) + return json.dumps(obj) + + def decode(self, obj): + #print('decode', self.__class__.__name__, obj) + return json.loads(obj) + + +class DotDictSerialize(tinydb_serialization.Serializer): + OBJ_CLASS = misc.DotDict + + def encode(self, obj): + #print('encode', self.__class__.__name__, obj) + return obj.toJson() + + def decode(self, obj): + #print('decode', self.__class__.__name__, obj) + return misc.DotDict(obj) + + +class PathSerialize(tinydb_serialization.Serializer): + OBJ_CLASS = misc.Path + + def encode(self, obj): + #print('encode', self.__class__.__name__, obj) + return obj.str() + + def decode(self, obj): + #print('decode', self.__class__.__name__, obj) + return misc.Path(obj) From 649507fdaacef1393b5be1fa4eddddd85e9dcf66 Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Mon, 17 May 2021 17:38:18 -0400 Subject: [PATCH 10/74] Move database classes to subdir and create half-implemented sqlite server --- IzzyLib/database/__init__.py | 17 + .../pysondb.py} | 4 +- IzzyLib/{database.py => database/sql.py} | 69 ++-- IzzyLib/database/sqlite_server.py | 374 ++++++++++++++++++ .../{database_tiny.py => database/tiny.py} | 4 +- IzzyLib/misc.py | 9 +- 6 files changed, 447 insertions(+), 30 deletions(-) create mode 100644 IzzyLib/database/__init__.py rename IzzyLib/{database_pysondb.py => database/pysondb.py} (99%) rename IzzyLib/{database.py => database/sql.py} (89%) create mode 100644 IzzyLib/database/sqlite_server.py rename IzzyLib/{database_tiny.py => database/tiny.py} (99%) diff --git a/IzzyLib/database/__init__.py b/IzzyLib/database/__init__.py new file mode 100644 index 0000000..9765c09 --- /dev/null +++ b/IzzyLib/database/__init__.py @@ -0,0 +1,17 @@ +from .. import logging + +try: + from .sql import SqlDatabase + from .sqlite_server import SqliteClient, SqliteServer +except ImportError as e: + logging.verbose('Failed to load SqlDatabase, SqliteClient, and SqliteServer. Is sqlalchemy installed?') + +try: + from .tiny import TinyDatabase +except ImportError as e: + logging.verbose('Failed to import TinyDatabase. Is tinydb and tinydb-serialization installed?') + +try: + from .pysondb import PysonDatabase +except ImportError as e: + logging.verbose('Failed to import PysonDatabase. Is pysondb installed?') diff --git a/IzzyLib/database_pysondb.py b/IzzyLib/database/pysondb.py similarity index 99% rename from IzzyLib/database_pysondb.py rename to IzzyLib/database/pysondb.py index c601edb..4887895 100644 --- a/IzzyLib/database_pysondb.py +++ b/IzzyLib/database/pysondb.py @@ -11,10 +11,10 @@ import random from pysondb.db import JsonDatabase, IdNotFoundError -from . import misc +from .. import misc -class Database(multiprocessing.Process): +class PysonDatabase(multiprocessing.Process): def __init__(self, dbpath: misc.Path, tables: dict=None): multiprocessing.Process.__init__(self, daemon=True) diff --git a/IzzyLib/database.py b/IzzyLib/database/sql.py similarity index 89% rename from IzzyLib/database.py rename to IzzyLib/database/sql.py index f2c7039..614fe0c 100644 --- a/IzzyLib/database.py +++ b/IzzyLib/database/sql.py @@ -7,25 +7,25 @@ from sqlalchemy import Column as SqlColumn, types as Types from sqlalchemy.exc import OperationalError, ProgrammingError from sqlalchemy.orm import scoped_session, sessionmaker -from . import logging -from .cache import LRUCache -from .misc import DotDict, RandomGen, NfsCheck, PrintMethods, Path +from .. import logging +from ..cache import LRUCache +from ..misc import DotDict, RandomGen, NfsCheck, PrintMethods, Path SqlTypes = DotDict({t.lower(): getattr(Types, t) for t in dir(Types) if not t.startswith('_')}) -class DataBase(): - def __init__(self, dbtype='postgresql+pg8000', tables={}, **kwargs): +class SqlDatabase: + def __init__(self, dbtype='sqlite', tables={}, **kwargs): self.db = self.__create_engine(dbtype, kwargs) - self.table = Tables(self, tables) - self.table_names = tables.keys() + self.table = None + self.table_names = None self.classes = kwargs.get('row_classes', CustomRows()) self.cache = None - session_class = kwargs.get('session_class', Session) - self.session = lambda trans=True: session_class(self, trans) + self.session_class = kwargs.get('session_class', Session) self.sessions = {} + self.SetupTables(tables) self.SetupCache() @@ -42,7 +42,7 @@ class DataBase(): if NfsCheck(kwargs.get('database')): logging.error('Database file is on an NFS share which does not support locking. Any writes to the database will fail') - engine_string += '/' + kwargs.get('database') + engine_string += '/' + str(kwargs.get('database')) engine_kwargs['connect_args'] = {'check_same_thread': False} else: @@ -68,6 +68,11 @@ class DataBase(): return create_engine(engine_string, *engine_args, **engine_kwargs) + @property + def session(self): + return self.session_class(self) + + def close(self): self.SetupCache() @@ -102,19 +107,25 @@ class DataBase(): self.table.meta.create_all(self.db) + def SetupTables(self, tables): + self.table = Tables(self, tables) + self.table_names = tables.keys() + + def execute(self, *args, **kwargs): with self.session() as s: return s.execute(*args, **kwargs) class Session(object): - def __init__(self, db, trans=True): + def __init__(self, db): + self.closed = False + self.db = db self.classes = self.db.classes self.session = sessionmaker(bind=db.db)() self.table = self.db.table self.cache = self.db.cache - self.trans = trans # session aliases self.s = self.session @@ -123,14 +134,12 @@ class Session(object): self.rollback = self.s.rollback self.query = self.s.query self.execute = self.s.execute - self.close = self.s.close self._setup() def __enter__(self): - self.sessionid = RandomGen(10) - self.db.sessions[self.sessionid] = self + self.open() return self @@ -138,10 +147,23 @@ class Session(object): if tb: self.rollback() - self.commit() self.close() + + + def open(self): + self.sessionid = RandomGen(10) + self.db.sessions[self.sessionid] = self + + + def close(self): + self.commit() + self.s.close() + self.closed = True + del self.db.sessions[self.sessionid] + self.sessionid = None + def _setup(self): pass @@ -216,7 +238,6 @@ class Session(object): def remove(self, table=None, rowid=None, row=None): if row: rowid = row.id - table = row._table_name if not rowid or not table: raise ValueError('Missing row ID or table') @@ -297,12 +318,15 @@ class CustomRows(object): return super().__init__() - self._update(row._asdict()) + + try: + self._update(row._asdict()) + except: + self._update(row) self._db = session.db self._table_name = table self._columns = self.keys() - #self._columns = self._filter_columns(row) self.__run__(session) @@ -345,7 +369,7 @@ class CustomRows(object): def delete_session(self, s): - return s.remove(row=self) + return s.remove(table=self._table_name, row=self) def update(self, dict_data={}, s=None, **data): @@ -362,7 +386,7 @@ class CustomRows(object): def update_session(self, s, dict_data={}, **data): dict_data.update(data) self._update(dict_data) - return s.update(row=self, **dict_data) + return s.update(table=self._table_name, row=self, **dict_data) class Tables(DotDict): @@ -378,7 +402,8 @@ class Tables(DotDict): def __setup_table(self, name, table): - self[name] = Table(name, self.meta, *table) + columns = [col if type(col) == SqlColumn else Column(*col.get('args'), **col.get('kwargs')) for col in table] + self[name] = Table(name, self.meta, *columns) def Column(name, stype=None, fkey=None, **kwargs): diff --git a/IzzyLib/database/sqlite_server.py b/IzzyLib/database/sqlite_server.py new file mode 100644 index 0000000..8dddb0b --- /dev/null +++ b/IzzyLib/database/sqlite_server.py @@ -0,0 +1,374 @@ +import asyncio, json, socket, sqlite3, ssl, time, traceback + +from . import SqlDatabase +from .sql import CustomRows +from .. import logging, misc + + +commands = [ + 'insert', 'update', 'remove', 'query', 'execute', 'dirty', 'count', + 'DropTables', 'GetTables', 'AppendColumn', 'RemoveColumn' +] + + +class SqliteClient(object): + def __init__(self, database: str='metadata', host: str='localhost', port: int=3926, password: str=None, session_class=None): + self.ssl = None + self.data = misc.DotDict({ + 'host': host, + 'port': int(port), + 'password': password, + 'database': database + }) + + self.session_class = session_class or SqliteSession + self.classes = CustomRows() + + self._setup() + + + @property + def session(self): + return self.session_class(self) + + + def setup_ssl(self, certfile, keyfile, password=None): + self.ssl = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2) + self.ssl.load_cert_chain(certfile, keyfile, password) + + + def switch_database(self, database): + self.data.database = database + + + def _setup(self): + pass + + +class SqliteSession(socket.socket): + def __init__(self, client): + super().__init__(socket.AF_INET, socket.SOCK_STREAM) + self.connected = False + + self.client = client + self.classes = client.classes + self.data = client.data + self.begin = lambda: self.send('begin') + self.commit = lambda: self.send('commit') + self.rollback = lambda: self.send('rollback') + + for cmd in commands: + self.setup_command(cmd) + + + def __enter__(self): + self.open() + return self + + + def __exit__(self, exctype, value, tb): + if tb: + self.rollback() + + self.commit() + self.close() + + + def fetch(self, table, *args, **kwargs): + RowClass = self.classes.get(table.capitalize()) + data = self.send('fetch', table, *args, **kwargs) + + if isinstance(data, dict): + return RowClass(table, data, self) + + elif isinstance(data, list): + return [RowClass(table, row, self) for row in data] + + + def search(self, *args, **kwargs): + return self.fetch(*args, **kwargs, single=False) + + + def setup_command(self, name): + setattr(self, name, lambda *args, **kwargs: self.send(name, *args, **kwargs)) + + + def send(self, command, *args, **kwargs): + self.sendall(json.dumps({'database': self.data.database, 'command': command, 'args': list(args), 'kwargs': dict(kwargs)}).encode('utf8')) + data = self.recv(8*1024*1024).decode() + + try: + data = misc.DotDict(data) + except ValueError: + data = json.loads(data) + + if isinstance(data, dict) and data.get('error'): + raise ServerError(data.get('error')) + + return data + + + def open(self): + try: + self.connect((self.data.host, self.data.port)) + except ConnectionRefusedError: + time.sleep(2) + self.connect((self.data.host, self.data.port)) + + if self.data.password: + login = self.send('login', self.data.password) + + if not login.get('message') == 'OK': + logging.error('Server error:', login.error) + return + + self.connected = True + + + def close(self): + self.send('close') + super().close() + self.connected = False + + + def is_transaction(self): + self.send('trans_state') + + + def is_connected(self): + return self.connected + + + def _setup(self): + pass + + +def Column(*args, **kwargs): + return {'args': list(args), 'kwargs': dict(kwargs)} + + +class SqliteServer(misc.DotDict): + def __init__(self, path, host='localhost', port=3926, password=None): + self.server = None + self.database = misc.DotDict() + + self.path = misc.Path(path).resolve() + self.ssl = None + self.password = password + self.host = host + self.port = int(port) + + self.metadata_layout = { + 'databases': [ + Column('id'), + Column('name', 'text', nullable=False), + Column('layout', 'text', nullable=False) + ] + } + + if not self.path.exists(): + raise FileNotFoundError('Database directory not found') + + if not self.path.isdir(): + raise NotADirectoryError('Database directory is a file') + + try: + self.open('metadata') + except: + self.setup_metadata() + + for path in self.path.listdir(False): + if path.str().endswith('.sqlite3') and path.stem != 'metadata': + self.open(path.stem) + + + def open(self, database, new=False): + db = SqlDatabase(dbtype='sqlite', database=self.path.join(database + '.sqlite3')) + + if database != 'metadata' and not new: + with self.get_database('metadata').session() as s: + row = s.fetch('databases', name=database) + + if not row: + logging.error('Database not found:', database) + return + + db.SetupTables(row.layout) + + else: + db.SetupTables(self.metadata_layout) + + setattr(db, 'name', database) + self[database] = db + return db + + + def close(self, database): + del self[database] + + + def delete(self, database): + self.close(database) + path.join(database + '.sqlite3').unlink() + + + def get_database(self, database): + return self[database] + + + def asyncio_run(self): + self.server = asyncio.start_server(self.handle_connection, self.host, self.port, ssl=self.ssl) + return self.server + + + def run(self): + loop = asyncio.get_event_loop() + loop.run_until_complete(self.asyncio_run()) + + try: + logging.info('Starting Sqlite Server') + loop.run_forever() + except KeyboardInterrupt: + print() + logging.info('Closing...') + return + + + def setup_metadata(self): + meta = self.open('metadata') + tables = { + 'databases': [ + Column('id'), + Column('name', 'text', nullable=False), + Column('layout', 'text', nullable=False) + ] + } + + db = self.open('metadata') + db.SetupTables(tables) + db.CreateDatabase() + + + def setup_ssl(self, certfile, keyfile, password=None): + self.ssl = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2) + self.ssl.load_cert_chain(certfile, keyfile, password) + + + async def handle_connection(self, reader, writer): + session = None + database = None + valid = None + close = False + + try: + while not close: + raw_data = await asyncio.wait_for(reader.read(8*1024*1024), timeout=60) + + if not raw_data: + break + + try: + data = misc.DotDict(raw_data) + + if self.password: + if valid == None and data.command == 'login': + valid = self.login(*data.get('args')) + + if not valid: + response = {'error': 'Missing or invalid password'} + + elif data.command in ['session']: + response = {'error': 'Invalid command'} + + else: + if not database: + database = data.database + + if data.command == 'close' and session: + session.commit() + + else: + if not session: + session = self[database].session() + session.open() + + response = self.run_command(session, database, data.command, *data.get('args'), **data.get('kwargs')) + + except Exception as e: + traceback.print_exc() + response = {'error': f'{e.__class__.__name__}: {str(e)}'} + + writer.write(json.dumps(response or {'message': 'OK'}, cls=misc.JsonEncoder).encode('utf8')) + await writer.drain() + logging.info(f'{writer.get_extra_info("peername")[0]}: [{database}] {data.command} {data.args} {data.kwargs}') + + if data.command == 'delete': + writer.close() + break + + except ConnectionResetError: + pass + + if session: + session.close() + + writer.close() + + + def login(self, password): + return self.password == password + + + def run_command(self, session, database, command, *args, **kwargs): + if command == 'update': + return self.cmd_update(*args, **kwargs) + + if command == 'dropdb': + return self.cmd_delete(session, database) + + elif command == 'createdb': + return self.cmd_createdb(session, database, *args) + + elif command == 'test': + return + + elif command == 'trans_state': + return {'trans_state': session.dirty} + + cmd = getattr(session, command, None) + + if not cmd: + return {'error': f'Command not found: {command}'} + + return cmd(*args, **kwargs) + + + def cmd_delete(self, session, database): + session.rollback() + session.close() + + self.delete(database) + + + def cmd_createdb(self, session, database, name, tables): + if session.fetch('databases', name=name): + raise ValueError('Database already exists:', database) + + session.insert('databases', name=name, layout=json.dumps(tables)) + + db = self.open(name, new=True) + db.SetupTables(tables) + db.CreateDatabase() + + self[name] = db + + + def cmd_update(self, table=None, rowid=None, row=None, **data): + if row: + row = misc.DotDict(row) + + return self.update(table, rowid, row, **data) + + +class ServerError(Exception): + pass diff --git a/IzzyLib/database_tiny.py b/IzzyLib/database/tiny.py similarity index 99% rename from IzzyLib/database_tiny.py rename to IzzyLib/database/tiny.py index 258b465..a9cafe4 100644 --- a/IzzyLib/database_tiny.py +++ b/IzzyLib/database/tiny.py @@ -8,14 +8,14 @@ import time import tinydb import tinydb_serialization -from . import misc +from .. import misc class AwaitingResult(object): pass -class DataBase(tinydb.TinyDB): +class TinyDatabase(tinydb.TinyDB): def __init__(self, dbfile: misc.Path, queue_limit: int=64, serializers: list=[]): options = { 'indent': 2, diff --git a/IzzyLib/misc.py b/IzzyLib/misc.py index 657e558..268c474 100644 --- a/IzzyLib/misc.py +++ b/IzzyLib/misc.py @@ -210,11 +210,11 @@ class DotDict(dict): if isinstance(value, (str, bytes)): self.fromJson(value) - elif isinstance(value, dict): + elif isinstance(value, dict) or isinstance(value, list): self.update(value) elif value: - raise TypeError('The value must be a JSON string, dict, or another DotDict object, not', value.__class__) + raise TypeError('The value must be a JSON string, list, dict, or another DotDict object, not', value.__class__) if kwargs: self.update(kwargs) @@ -479,8 +479,9 @@ class Path(object): return self.__path.is_symlink() - def listdir(self): - return [Path(path) for path in self.__path.iterdir()] + def listdir(self, recursive=True): + paths = self.__path.iterdir() if recursive else os.listdir(self.__path) + return [Path(path) for path in paths] def exists(self): From 944b2be072feb652b8ce78cfa9340ce7669cdcea Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Tue, 18 May 2021 00:04:47 -0400 Subject: [PATCH 11/74] misc.path: add chmod, mkdir, and backup --- IzzyLib/database/sql.py | 2 ++ IzzyLib/misc.py | 27 ++++++++++++++++++++++++--- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/IzzyLib/database/sql.py b/IzzyLib/database/sql.py index 614fe0c..d422e8c 100644 --- a/IzzyLib/database/sql.py +++ b/IzzyLib/database/sql.py @@ -29,6 +29,8 @@ class SqlDatabase: self.SetupCache() + ## Leaving link to example code for read-only sqlite for later use + ## https://github.com/pudo/dataset/issues/136#issuecomment-128693122 def __create_engine(self, dbtype, kwargs): engine_args = [] engine_kwargs = {} diff --git a/IzzyLib/misc.py b/IzzyLib/misc.py index 268c474..4d52071 100644 --- a/IzzyLib/misc.py +++ b/IzzyLib/misc.py @@ -398,6 +398,10 @@ class Path(object): 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}') + + def size(self): return self.__path.stat().st_size @@ -438,6 +442,11 @@ class Path(object): copyfile(self.str(), target.str()) + def backup(self, ext='backup', overwrite=False): + target = f'{self.__path.parent}.{ext}' + self.copy(target, overwrite) + + def move(self, path, overwrite=False): self.copy(path, overwrite=overwrite) self.delete() @@ -517,10 +526,22 @@ class Path(object): return self - def touch(self, mode=0o666): - self.__path.touch(mode, self.exist) + def chmod(self, mode=None): + octal = self.__parse_perm_octal(mode) + self.__path.chmod(octal) - return True if self.__path.exists() else False + + def touch(self, mode=0o666): + octal = __parse_perm_octal(mode) + self.__path.touch(octal, self.exist) + + return self.exists() + + + def mkdir(self): + self.__path.mkdir(parents=self.parents, exist_ok=self.exist) + + return self.exists() def load_json(self): From 02e7e3072840ffb3af761157ef32cddb2d2e5c02 Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Tue, 18 May 2021 03:36:11 -0400 Subject: [PATCH 12/74] update gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index e61bca2..a893c51 100644 --- a/.gitignore +++ b/.gitignore @@ -114,3 +114,5 @@ dmypy.json # Pyre type checker .pyre/ +test*.py +reload.cfg From 6372edad04e66b47613579786442dc8cd48b6ace Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Tue, 18 May 2021 08:33:48 -0400 Subject: [PATCH 13/74] fix session.remove --- IzzyLib/database/sql.py | 1 + 1 file changed, 1 insertion(+) diff --git a/IzzyLib/database/sql.py b/IzzyLib/database/sql.py index d422e8c..5c29299 100644 --- a/IzzyLib/database/sql.py +++ b/IzzyLib/database/sql.py @@ -240,6 +240,7 @@ class Session(object): def remove(self, table=None, rowid=None, row=None): if row: rowid = row.id + table = row._table_name if not rowid or not table: raise ValueError('Missing row ID or table') From 713dffa1af4e7090c6b85af906de08686f33d006 Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Tue, 18 May 2021 08:40:22 -0400 Subject: [PATCH 14/74] fix a silly goofup --- IzzyLib/database/sql.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/IzzyLib/database/sql.py b/IzzyLib/database/sql.py index 5c29299..33aa382 100644 --- a/IzzyLib/database/sql.py +++ b/IzzyLib/database/sql.py @@ -194,7 +194,7 @@ class Session(object): rows = query.order_by(getattr(table.c, orderby).asc()).all() elif orderdir == 'desc': - rows = query.order_by(getattr(table.c, orderby).asc()).all() + rows = query.order_by(getattr(table.c, orderby).desc()).all() else: raise ValueError(f'Unsupported order direction: {orderdir}') From 9d6a043bb22cd1e74963f6d45a8c983c4cf046d5 Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Tue, 18 May 2021 08:47:48 -0400 Subject: [PATCH 15/74] spacing fix --- IzzyLib/database/sql.py | 1 + 1 file changed, 1 insertion(+) diff --git a/IzzyLib/database/sql.py b/IzzyLib/database/sql.py index 33aa382..348ae7b 100644 --- a/IzzyLib/database/sql.py +++ b/IzzyLib/database/sql.py @@ -237,6 +237,7 @@ class Session(object): tclass = self.table[table] self.execute(tclass.update().where(tclass.c.id == rowid).values(**data)) + def remove(self, table=None, rowid=None, row=None): if row: rowid = row.id From 5cd4eff2b05ba59042e94b782b2b39fead5987aa Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Thu, 20 May 2021 06:09:33 -0400 Subject: [PATCH 16/74] database.sql: fix new session for some functions --- IzzyLib/database/sql.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/IzzyLib/database/sql.py b/IzzyLib/database/sql.py index 348ae7b..0957a2c 100644 --- a/IzzyLib/database/sql.py +++ b/IzzyLib/database/sql.py @@ -115,7 +115,7 @@ class SqlDatabase: def execute(self, *args, **kwargs): - with self.session() as s: + with self.session as s: return s.execute(*args, **kwargs) @@ -368,7 +368,7 @@ class CustomRows(object): if s: return self.delete_session(s) - with self._db.session() as s: + with self._db.session as s: return self.delete_session(s) @@ -383,7 +383,7 @@ class CustomRows(object): if s: return self.update_session(s, **self._filter_data()) - with self._db.session() as s: + with self._db.session as s: s.update(row=self, **self._filter_data()) From c8d927abb33e78f46bb8bf52fd93aab5823535a1 Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Sat, 22 May 2021 08:28:53 -0400 Subject: [PATCH 17/74] logging: add setLogger, fix getLogger, and add logger name if not default --- IzzyLib/logging.py | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/IzzyLib/logging.py b/IzzyLib/logging.py index cec3fca..53febd5 100644 --- a/IzzyLib/logging.py +++ b/IzzyLib/logging.py @@ -10,7 +10,7 @@ stdout = sys.stdout class Log(): - def __init__(self, config=dict()): + def __init__(self, name=None, config=dict()): '''setup the logger''' if not isinstance(config, dict): raise TypeError(f'config is not a dict') @@ -35,6 +35,7 @@ class Log(): 'MERP': 'MERP' } + self.name = name self.config = {'windows': sys.executable.endswith('pythonw.exe')} self.setConfig(self._parseConfig(config)) @@ -123,13 +124,20 @@ class Log(): levelNum = self._lvlCheck(level) if type(level) == int: - level = _getLevelName(level) + level = self._getLevelName(level) if levelNum < self.config['levelnum']: return message = ' '.join([str(message) for message in msg]) - output = f'{level}: {message}\n' + + if self.name: + output = f'[{self.name}] ' + + else: + output = '' + + output += f'{level}: {message}\n' if self.config['systemnotif']: self.config['systemnotif'].New(level, message) @@ -165,18 +173,21 @@ class Log(): self.log('MERP', *msg) -def getLogger(loginst, config=None): +def getLogger(name): '''get a logging instance and create one if it doesn't exist''' - Logger = logger.get(loginst) + log = logger.get(name) - if not Logger: - if config: - logger[loginst] = Log(config) + if not log: + raise InvalidLogger(f'logger "{name}" doesn\'t exist') - else: - raise InvalidLogger(f'logger "{loginst}" doesn\'t exist') + return log + + +def setLogger(name, config={}): + log = Log(name, config) + logger[name.lower()] = log + return log - return logger[loginst] class InvalidLevel(Exception): '''Raise when an invalid logging level was specified''' From a1f7b8942cffe61ba749d6f53b605e222fa8307a Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Wed, 26 May 2021 00:35:23 -0400 Subject: [PATCH 18/74] misc: add ImportFromPath, Path: add dir handling in remove --- IzzyLib/misc.py | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/IzzyLib/misc.py b/IzzyLib/misc.py index 4d52071..c966e99 100644 --- a/IzzyLib/misc.py +++ b/IzzyLib/misc.py @@ -4,8 +4,9 @@ import hashlib, random, string, sys, os, json, socket, time from os import environ as env from datetime import datetime from getpass import getpass +from importlib import util from pathlib import Path as Pathlib -from shutil import copyfile +from shutil import copyfile, rmtree from . import logging @@ -105,6 +106,17 @@ def GetIp(): return ip +def ImportFromPath(mod_path): + mod_path = Path(mod_path) + path = mod_path.join('__init__.py') if mod_path.isdir() else mod_path + name = path.name.replace('.py', '', -1) + + spec = util.spec_from_file_location(name, path.str()) + module = util.module_from_spec(spec) + spec.loader.exec_module(module) + return module + + def Input(prompt, default=None, valtype=str, options=[], password=False): input_func = getpass if password else input @@ -264,10 +276,6 @@ class DotDict(dict): return (k, v) - def update(self, data): - super().update(data) - - def get(self, key, default=None): value = dict.get(self, key, default) return DotDict(value) if type(value) == dict else value @@ -562,10 +570,9 @@ class Path(object): self.json.update(data) - # This needs to be extended to handle dirs with files/sub-dirs def delete(self): if self.isdir(): - self.__path.rmdir() + rmtree(self.__path) else: self.__path.unlink() @@ -587,7 +594,7 @@ class Path(object): class JsonEncoder(json.JSONEncoder): def default(self, obj): - if type(obj) not in [str, int, float, dict]: + if not any(map(isinstance, [obj], [str, int, float, dict])): return str(obj) return json.JSONEncoder.default(self, obj) From e7fd9aa78a8c8495c4398fbf5de78794360038f4 Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Mon, 31 May 2021 03:42:43 -0400 Subject: [PATCH 19/74] add options for misc.RandomGen and create dbus classes --- IzzyLib/misc.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/IzzyLib/misc.py b/IzzyLib/misc.py index c966e99..28dbcf3 100644 --- a/IzzyLib/misc.py +++ b/IzzyLib/misc.py @@ -38,14 +38,20 @@ def Boolean(v, return_value=False): return True -def RandomGen(length=20, chars=None): +def RandomGen(length=20, letters=True, digits=True, extra=None): if not isinstance(length, int): raise TypeError(f'Character length must be an integer, not {type(length)}') - characters = string.ascii_letters + string.digits + characters = '' - if chars: - characters += chars + if letters: + characters += string.ascii_letters + + if digits: + characters += string.digits + + if extra: + characters += extra return ''.join(random.choices(characters, k=length)) From 47ba46b53d4b6a01c8da7ee295e4cec8164ab821 Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Tue, 1 Jun 2021 13:39:22 -0400 Subject: [PATCH 20/74] database.sql: replace 'db' variable in Session with 'database' --- IzzyLib/database/sql.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/IzzyLib/database/sql.py b/IzzyLib/database/sql.py index 0957a2c..4184c1a 100644 --- a/IzzyLib/database/sql.py +++ b/IzzyLib/database/sql.py @@ -123,11 +123,11 @@ class Session(object): def __init__(self, db): self.closed = False - self.db = db - self.classes = self.db.classes + self.database = db + self.classes = db.classes self.session = sessionmaker(bind=db.db)() - self.table = self.db.table - self.cache = self.db.cache + self.table = db.table + self.cache = db.cache # session aliases self.s = self.session @@ -137,6 +137,9 @@ class Session(object): self.query = self.s.query self.execute = self.s.execute + # remove in the future + self.db = db + self._setup() From 08895f778eb229d763fab51a089278d9cded4b9d Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Tue, 1 Jun 2021 16:55:01 -0400 Subject: [PATCH 21/74] misc: Rework DotDict --- IzzyLib/misc.py | 115 ++++++++++++------------------------------------ 1 file changed, 29 insertions(+), 86 deletions(-) diff --git a/IzzyLib/misc.py b/IzzyLib/misc.py index 28dbcf3..33200fc 100644 --- a/IzzyLib/misc.py +++ b/IzzyLib/misc.py @@ -220,105 +220,64 @@ class DotDict(dict): '''Python dictionary, but variables can be set/get via attributes value [str, bytes, dict]: JSON or dict of values to init with - case_insensitive [bool]: Wether keys should be case sensitive or not kwargs: key/value pairs to set on init. Overrides identical keys set by 'value' ''' + super().__init__() + self.__setattr__ = self.__setitem__ + + ## compatibility + self.toJson = self.to_json + self.fromJson = self.from_json if isinstance(value, (str, bytes)): - self.fromJson(value) + self.from_json(value) elif isinstance(value, dict) or isinstance(value, list): self.update(value) elif value: - raise TypeError('The value must be a JSON string, list, dict, or another DotDict object, not', value.__class__) + raise TypeError(f'The value must be a JSON string, list, dict, or another DotDict object, not {value.__class__}') if kwargs: self.update(kwargs) - def __getattr__(self, key): + def __getattr__(self, k): try: - val = super().__getattribute__(key) + return super().__getitem__(k) - except AttributeError: - val = self.get(key, KeyError) - - try: - if val == KeyError: - raise KeyError(f'Invalid key: {key}') - - except AttributeError: - 'PyCryptodome.PublicKey.RSA.RsaKey.__eq__ does not seem to play nicely' - - return DotDict(val) if type(val) == dict else val + except KeyError: + raise AttributeError(f'{self.__class__.__name__} object has no attribute {k}') from None - def __delattr__(self, key): - if self.get(key): - del self[key] - - super().__delattr__(key) - - - def __setattr__(self, key, value): - if key.startswith('_'): - super().__setattr__(key, value) - - else: - super().__setitem__(key, value) - - - def __str__(self): - return self.toJson() - - - def __parse_item__(self, k, v): - if type(v) == dict: + def __setitem__(self, k, v): + if isinstance(v, dict): v = DotDict(v) - if not k.startswith('_'): - return (k, v) + super().__setitem__(k, v) - def get(self, key, default=None): - value = dict.get(self, key, default) - return DotDict(value) if type(value) == dict else value + def __delattr__(self, k): + try: + dict.__delitem__(self, k) + except KeyError: + raise AttributeError(f'{self.__class__.__name__} object has no attribute {k}') from None - def items(self): - data = [] - - for k, v in super().items(): - new = self.__parse_item__(k, v) - - if new: - data.append(new) - - return data + def update(self, data): + for k,v in data.items(): + self.__setitem__(k, v) - def values(self): - return list(super().values()) - - - def keys(self): - return list(super().keys()) - - - def asDict(self): - return dict(self) - - - def toJson(self, indent=None, **kwargs): + def to_json(self, indent=None, **kwargs): if 'cls' not in kwargs: kwargs['cls'] = JsonEncoder return json.dumps(dict(self), indent=indent, **kwargs) - def fromJson(self, string): + def from_json(self, string): data = json.loads(string) self.update(data) @@ -332,6 +291,7 @@ class DotDict(dict): write(self.toJson(*kwargs)) +## This has to be reworked tbh class DefaultDict(DotDict): def __getattr__(self, key): try: @@ -345,34 +305,17 @@ class DefaultDict(DotDict): class LowerDotDict(DotDict): def __getattr__(self, key): - key = key.lower() - - try: - val = super().__getattribute__(key) - - except AttributeError: - val = self.get(key, KeyError) - - if val == KeyError: - raise KeyError(f'Invalid key: {key}') - - return DotDict(val) if type(val) == dict else val + return super().__getattr__(self, key.lower()) def __setattr__(self, key, value): - key = key.lower() - - if key.startswith('_'): - super().__setattr__(key, value) - - else: - super().__setitem__(key, value) + return super().__setattr(self, key.lower(), value) def update(self, data): data = {k.lower(): v for k,v in self.items()} - super().update(data) + return super().update(data) class Path(object): From 63a6819e41182792db8e7dfb0468ba4362123cfd Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Thu, 3 Jun 2021 15:40:30 -0400 Subject: [PATCH 22/74] expand PasswordHasher and minor DotDict fixes --- IzzyLib/http_server.py | 13 +++- IzzyLib/misc.py | 165 ++++++++++++++++++++++++++++++----------- 2 files changed, 133 insertions(+), 45 deletions(-) diff --git a/IzzyLib/http_server.py b/IzzyLib/http_server.py index 5a467c4..51baeb9 100644 --- a/IzzyLib/http_server.py +++ b/IzzyLib/http_server.py @@ -4,6 +4,7 @@ import logging as pylog from jinja2.exceptions import TemplateNotFound from multidict import CIMultiDict from multiprocessing import cpu_count, current_process +from sanic.views import HTTPMethodView from urllib.parse import parse_qsl, urlparse from . import http, logging @@ -30,12 +31,11 @@ class HttpServer(sanic.Sanic): self.port = int(port) self.workers = int(kwargs.get('workers', cpu_count())) self.sig_handler = kwargs.get('sig_handler') - self.ctx = DotDict() super().__init__(name, request_class=kwargs.get('request_class', HttpRequest)) - #for log in ['sanic.root', 'sanic.access']: - #pylog.getLogger(log).setLevel(pylog.CRITICAL) + for log in ['sanic.root', 'sanic.access']: + pylog.getLogger(log).setLevel(pylog.ERROR) self.template = Template( kwargs.get('tpl_search', []), @@ -56,6 +56,11 @@ class HttpServer(sanic.Sanic): signal.signal(signal.SIGTERM, self.finish) + ## Sanic spits out a warning, so this is the workaround to stop it + def __setattr__(self, key, value): + object.__setattr__(self, key, value) + + def add_method_route(self, method, *routes): for route in routes: self.add_route(method.as_view(), route) @@ -88,8 +93,10 @@ class HttpServer(sanic.Sanic): if self.sig_handler: self.sig_handler() + print('stopping.....') self.stop() logging.info('Bye! :3') + sys.exit() class HttpRequest(sanic.request.Request): diff --git a/IzzyLib/misc.py b/IzzyLib/misc.py index 33200fc..1abcdb9 100644 --- a/IzzyLib/misc.py +++ b/IzzyLib/misc.py @@ -1,5 +1,5 @@ '''Miscellaneous functions''' -import hashlib, random, string, sys, os, json, socket, time +import hashlib, random, string, sys, os, json, statistics, socket, time, timeit from os import environ as env from datetime import datetime @@ -11,8 +11,9 @@ from shutil import copyfile, rmtree from . import logging try: - from passlib.hash import argon2 + import argon2 except ImportError: + logging.verbose('argon2-cffi not installed. PasswordHasher class disabled') argon2 = None @@ -191,6 +192,47 @@ def PrintMethods(object, include_underscore=False): print(line) +def TimeFunction(func, *args, passes=1, use_gc=True, **kwargs): + options = [ + lambda: func(*args, **kwargs) + ] + + if use_gc: + options.append('gc.enable()') + + timer = timeit.Timer(*options) + + if passes > 1: + return timer.repeat(passes, 1) + + return timer.timeit(1) + + +def TimeFunctionPPrint(func, *args, passes=5, use_gc=True, floatlen=3, **kwargs): + parse_time = lambda num: f'{round(num, floatlen)}s' + times = [] + + for idx in range(0, passes): + passtime = TimeFunction(func, *args, **kwargs, passes=1, use_gc=use_gc) + times.append(passtime) + print(f'Pass {idx+1}: {parse_time(passtime)}') + + average = statistics.fmean(times) + + print('-----------------') + print(f'Average: {parse_time(average)}') + print(f'Total: {parse_time(sum(times))}') + + + +def TimePassHasher(string='hecking heck', passes=3, iterations=[2,4,8,16,32,64,96]): + for iteration in iterations: + print('\nTesting hash iterations:', iteration) + hasher = PasswordHasher(iterations=iteration) + strhash = hasher.hash(string) + TimeFunctionPPrint(hasher.verify, strhash, string, passes=passes) + + class Connection(socket.socket): def __init__(self, address='127.0.0.1', port=8080, tcp=True): super().__init__(socket.AF_INET, socket.SOCK_STREAM if tcp else socket.SOCK_DGRAM) @@ -216,6 +258,9 @@ class Connection(socket.socket): class DotDict(dict): + dict_ignore_types = ['basecache', 'lrucache', 'ttlcache'] + + def __init__(self, value=None, **kwargs): '''Python dictionary, but variables can be set/get via attributes @@ -233,7 +278,7 @@ class DotDict(dict): if isinstance(value, (str, bytes)): self.from_json(value) - elif isinstance(value, dict) or isinstance(value, list): + elif value.__class__.__name__.lower() not in self.dict_ignore_types and isinstance(value, dict): self.update(value) elif value: @@ -252,7 +297,7 @@ class DotDict(dict): def __setitem__(self, k, v): - if isinstance(v, dict): + if v.__class__.__name__.lower() not in self.dict_ignore_types and isinstance(v, dict): v = DotDict(v) super().__setitem__(k, v) @@ -309,7 +354,7 @@ class LowerDotDict(DotDict): def __setattr__(self, key, value): - return super().__setattr(self, key.lower(), value) + return super().__setattr__(key.lower(), value) def update(self, data): @@ -359,6 +404,17 @@ class Path(object): return mode if type(mode) == oct else eval(f'0o{mode}') + def append(self, text, new=True): + path = str(self.__path) + text + + if new: + return Path(path) + + self.__path = Pathlib(path) + + return self + + def size(self): return self.__path.stat().st_size @@ -549,45 +605,70 @@ class JsonEncoder(json.JSONEncoder): return json.JSONEncoder.default(self, obj) -class PasswordHash(object): - def __init__(self, salt=None, rounds=8, bsize=50, threads=os.cpu_count(), length=64): - if type(salt) == Path: - if salt.exists(): - with salt.open() as fd: - self.salt = fd.read() +class PasswordHasher(DotDict): + ## The defaults can usually be used, except for `iterations`. That should be tweaked on each machine + ## You can use the TimeFunctionPPrint command above to test this - else: - newsalt = RandomGen(40) - - with salt.open('w') as fd: - fd.write(newsalt) - - self.salt = newsalt - - else: - self.salt = salt or RandomGen(40) - - self.rounds = rounds - self.bsize = bsize * 1024 - self.threads = threads - self.length = length + aliases = { + 'iterations': 'time_cost', + 'memory': 'memory_cost', + 'threads': 'parallelism' + } - def hash(self, password): - return argon2.using( - salt = self.salt.encode('UTF-8'), - rounds = self.rounds, - memory_cost = self.bsize, - max_threads = self.threads, - digest_size = self.length - ).hash(password) + def __init__(self, **kwargs): + if not argon2: + raise ValueError('password hashing disabled') + + super().__init__({ + 'time_cost': 16, + 'memory_cost': 100 * 1024, + 'parallelism': os.cpu_count(), + 'encoding': 'utf-8', + 'type': argon2.Type.ID, + }) + + self.hasher = None + self.update(kwargs) + self.setup() - def verify(self, password, passhash): - return argon2.using( - salt = self.salt.encode('UTF-8'), - rounds = self.rounds, - memory_cost = self.bsize, - max_threads = self.threads, - digest_size = self.length - ).verify(password, passhash) + def get_config(self, key): + key = self.aliases.get(key, key) + + self[key] + return self.get(key) / 1024 if key == 'memory_cost' else self.get(key) + + + def set_config(self, key, value): + key = self.aliases.get(key, key) + self[key] = value * 1024 if key == 'memory_cost' else value + self.setup() + + + def setup(self): + self.hasher = argon2.PasswordHasher(**self) + + + def hash(self, password: str): + return self.hasher.hash(password) + + + def verify(self, passhash: str, password: str): + try: + return self.hasher.verify(passhash, password) + + except argon2.exceptions.VerifyMismatchError: + return False + + + def iteration_test(self, string='hecking heck', passes=3, iterations=[8,16,24,32,40,48,56,64]): + original_iter = self.get_config('iterations') + + for iteration in iterations: + self.set_config('iterations', iteration) + print('\nTesting hash iterations:', iteration) + + TimeFunctionPPrint(self.verify, self.hash(string), string, passes=passes) + + self.set_config('iterations', original_iter) From 27ec8c96a8d84d8214711e2da68b90473d2f2815 Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Mon, 7 Jun 2021 16:45:29 -0400 Subject: [PATCH 23/74] first draft of rework --- IzzyLib/__init__.py | 12 - IzzyLib/color.py | 56 -- IzzyLib/database/__init__.py | 17 - IzzyLib/database/pysondb.py | 353 --------- IzzyLib/error.py | 23 - IzzyLib/http.py | 657 ----------------- IzzyLib/logging.py | 221 ------ IzzyLib/misc.py | 674 ------------------ LICENSE | 52 +- README.md | 31 +- base/izzylib/__init__.py | 56 ++ {IzzyLib => base/izzylib}/cache.py | 6 +- base/izzylib/connection.py | 25 + base/izzylib/dotdict.py | 115 +++ base/izzylib/exceptions.py | 2 + base/izzylib/http_urllib_client.py | 163 +++++ base/izzylib/logging.py | 129 ++++ base/izzylib/misc.py | 411 +++++++++++ base/izzylib/path.py | 170 +++++ base/setup.py | 36 + http_server/izzylib/http_server/__init__.py | 2 + http_server/izzylib/http_server/hasher.py | 78 ++ .../izzylib/http_server/server.py | 92 ++- http_server/setup.py | 53 ++ .../izzylib/http_requests_client/__init__.py | 393 ++++++++++ requests_client/setup.py | 44 ++ requirements.txt | 10 - setup.py | 124 +++- sql/izzylib/sql/__init__.py | 2 + .../sql.py => sql/izzylib/sql/generic.py | 31 +- .../izzylib/sql}/sqlite_server.py | 28 +- sql/setup.py | 47 ++ .../izzylib/template/__init__.py | 66 +- template/setup.py | 46 ++ tinydb/izzylib/tinydb/__init__.py | 1 + .../izzylib/tinydb}/tiny.py | 103 +-- tinydb/setup.py | 45 ++ 37 files changed, 2112 insertions(+), 2262 deletions(-) delete mode 100644 IzzyLib/__init__.py delete mode 100644 IzzyLib/color.py delete mode 100644 IzzyLib/database/__init__.py delete mode 100644 IzzyLib/database/pysondb.py delete mode 100644 IzzyLib/error.py delete mode 100644 IzzyLib/http.py delete mode 100644 IzzyLib/logging.py delete mode 100644 IzzyLib/misc.py create mode 100644 base/izzylib/__init__.py rename {IzzyLib => base/izzylib}/cache.py (96%) create mode 100644 base/izzylib/connection.py create mode 100644 base/izzylib/dotdict.py create mode 100644 base/izzylib/exceptions.py create mode 100644 base/izzylib/http_urllib_client.py create mode 100644 base/izzylib/logging.py create mode 100644 base/izzylib/misc.py create mode 100644 base/izzylib/path.py create mode 100755 base/setup.py create mode 100644 http_server/izzylib/http_server/__init__.py create mode 100644 http_server/izzylib/http_server/hasher.py rename IzzyLib/http_server.py => http_server/izzylib/http_server/server.py (89%) create mode 100644 http_server/setup.py create mode 100644 requests_client/izzylib/http_requests_client/__init__.py create mode 100644 requests_client/setup.py delete mode 100644 requirements.txt mode change 100755 => 100644 setup.py create mode 100644 sql/izzylib/sql/__init__.py rename IzzyLib/database/sql.py => sql/izzylib/sql/generic.py (93%) rename {IzzyLib/database => sql/izzylib/sql}/sqlite_server.py (92%) create mode 100644 sql/setup.py rename IzzyLib/template.py => template/izzylib/template/__init__.py (69%) create mode 100644 template/setup.py create mode 100644 tinydb/izzylib/tinydb/__init__.py rename {IzzyLib/database => tinydb/izzylib/tinydb}/tiny.py (64%) create mode 100644 tinydb/setup.py diff --git a/IzzyLib/__init__.py b/IzzyLib/__init__.py deleted file mode 100644 index 511e2e9..0000000 --- a/IzzyLib/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -''' -IzzyLib by Zoey Mae -Licensed under the CNPL: https://git.pixie.town/thufie/CNPL -https://git.barkshark.xyz/izaliamae/izzylib -''' - -import sys -assert sys.version_info >= (3, 6) - - -__version_tpl__ = (0, 5, 0) -__version__ = '.'.join([str(v) for v in __version_tpl__]) diff --git a/IzzyLib/color.py b/IzzyLib/color.py deleted file mode 100644 index 9e1a019..0000000 --- a/IzzyLib/color.py +++ /dev/null @@ -1,56 +0,0 @@ -'''functions to alter colors in hex format''' -import re - -from colour import Color - - -check = lambda color: Color(f'#{str(color)}' if re.search(r'^(?:[0-9a-fA-F]{3}){1,2}$', color) else color) - -def _multi(multiplier): - if multiplier >= 1: - return 1 - - elif multiplier <= 0: - return 0 - - return multiplier - -def lighten(color, multiplier): - col = check(color) - col.luminance += ((1 - col.luminance) * _multi(multiplier)) - - return col.hex_l - -def darken(color, multiplier): - col = check(color) - col.luminance -= (col.luminance * _multi(multiplier)) - - return col.hex_l - - -def saturate(color, multiplier): - col = check(color) - col.saturation += ((1 - col.saturation) * _multi(multiplier)) - - return col.hex_l - - -def desaturate(color, multiplier): - col = check(color) - col.saturation -= (col.saturation * _multi(multiplier)) - - return col.hex_l - - -def rgba(color, transparency): - col = check(color) - - red = col.red*255 - green = col.green*255 - blue = col.blue*255 - trans = _multi(transparency) - - return f'rgba({red:0.2f}, {green:0.2f}, {blue:0.2f}, {trans:0.2f})' - - -__all__ = ['lighten', 'darken', 'saturate', 'desaturate', 'rgba'] diff --git a/IzzyLib/database/__init__.py b/IzzyLib/database/__init__.py deleted file mode 100644 index 9765c09..0000000 --- a/IzzyLib/database/__init__.py +++ /dev/null @@ -1,17 +0,0 @@ -from .. import logging - -try: - from .sql import SqlDatabase - from .sqlite_server import SqliteClient, SqliteServer -except ImportError as e: - logging.verbose('Failed to load SqlDatabase, SqliteClient, and SqliteServer. Is sqlalchemy installed?') - -try: - from .tiny import TinyDatabase -except ImportError as e: - logging.verbose('Failed to import TinyDatabase. Is tinydb and tinydb-serialization installed?') - -try: - from .pysondb import PysonDatabase -except ImportError as e: - logging.verbose('Failed to import PysonDatabase. Is pysondb installed?') diff --git a/IzzyLib/database/pysondb.py b/IzzyLib/database/pysondb.py deleted file mode 100644 index 4887895..0000000 --- a/IzzyLib/database/pysondb.py +++ /dev/null @@ -1,353 +0,0 @@ -import asyncio -import base64 -import datetime -import filelock -import json -import multiprocessing -import operator -import pysondb -import queue -import random - -from pysondb.db import JsonDatabase, IdNotFoundError - -from .. import misc - - -class PysonDatabase(multiprocessing.Process): - def __init__(self, dbpath: misc.Path, tables: dict=None): - multiprocessing.Process.__init__(self, daemon=True) - - self.dbpath = dbpath - self.tables = tables - self.shutdown = False - self.port = self._setup_port() - self.token = misc.RandomGen() - print(self.port) - - self.fetch = lambda *args, **kwargs: self.send_message('fetch', *args, **kwargs) - self.search = lambda *args, **kwargs: self.send_message('search', *args, **kwargs) - self.insert = lambda *args, **kwargs: self.send_message('insert', *args, **kwargs) - self.remove = lambda *args, **kwargs: self.send_message('remove', *args, **kwargs) - - self.start() - - - def run(self): - self.db = DatabaseProcess(self.dbpath, self.tables) - print(self.port) - server = asyncio.create_server(process_queue, '127.0.0.1', self.port) - - loop = asyncio.new_event_loop() - loop.run_until_complete(server) - loop.run_forever() - - - def close(self): - self.terminate() - self.join(timeout=5) - - - def _setup_port(self): - port = None - - while True: - port = random.randint(8096, 16394) - - if misc.PortCheck(port) == True: - return port - - - def get_action(self, action): - return getattr(self.db, action) - - - def send_message(self, action, table, *args, **kwargs): - data = { - 'token': self.token, - 'action': action, - 'table': table, - 'args': args, - 'kwargs': kwargs - } - - with self.socket as s: - s.send(json.dumps(data)) - return s.recieve(16 * 1024 * 1024) - - - @property - def socket(self): - return misc.Connection(port=self.port) - - - async def process_queue(self, reader, writer): - data = misc.DotDict(await reader.read(16 * 1024 * 1024)) - - if data.token != self.token: - return - - if data.action == 'close': - self._shutdown = True - - new_data = self.get_action(data.action)(data.table, *args, **kwargs) - - if isinstance(new_data, dict): - writer.write(json.dumps(new_data)) - await writer.drain() - - writer.close() - - async def pipe_listener(self): - pass - - -class DatabaseProcess(misc.DotDict): - def __init__(self, dbpath: misc.Path, tables: dict=None): - dbpath = misc.Path(dbpath) - super().__init__() - - self.path = misc.Path(dbpath).resolve() - self.metadata = misc.DotDict(**{ - 'path': self.path.join('metadata.json'), - 'lock': self.path.join('metadata.json.lock'), - 'version': 0 - }) - - self._closed = False - self.__setup_database(tables) - - - def __setup_database(self, tables): - self.path.mkdir() - self.load_meta() - - for name, columns in tables.items(): - self[name] = columns if type(columns) == Table else Table(name, columns) - - if not self[name].db: - self[name].setup(self) - - - def load_meta(self): - if self.metadata.path.exists(): - with filelock.FileLock(self.metadata.lock.str()): - data = self.metadata.path.load_json() - self.metadata.update(data) - - - def save_meta(self): - with filelock.FileLock(self.metadata.lock.str()): - data = self.metadata.copy() - data.pop('path') - data.pop('lock') - - self.metadata.path.update_json(data) - self.metadata.path.save_json() - - - def close(self): - self.save_meta() - self._closed = True - - - def fetch(self, table, *args, **kwargs): - return self[table].fetch(*args, **kwargs) - - - def search(self, table, *args, **kwargs): - return self[table].search(*args, **kwargs) - - - def insert(self, table, *args, **kwargs): - return self[table].insert(*args, **kwargs) - - - def remove(self, table, *args, **kwargs): - return self[table].remove(*args, **kwargs) - - - def migrate(self, table=None): - tables = [self[table]] if table else self.table - - for name, table in tables: - for row in table.search(): - table.update(row.id, ) - - -class Table(JsonDatabase): - def __init__(self, name: str, columns: dict={}): - self.db = None - self.name = name - self.columns = {} - self.add_column('id') - - for name, col in columns.items(): - if name != 'id': - self.add_column(name, *col) - - - def setup(self, db): - self.db = db - tablefile = db.path.join(f'table_{self.name}.json') - - if not tablefile.exists(): - tablefile.touch(mode=0o644) - with tablefile.open('w') as fd: - fd.write('{"data": []}') - - super().__init__(tablefile.str()) - - - def add_column(self, name: str, type: str='str', default: bool=None, nullable: bool=True, primary_key: bool=False): - if name == 'id': - type = 'int' - nullable = False - primary_key = True - - self.columns[name] = misc.DotDict({ - 'default': default, - 'type': type, - 'primary_key': primary_key, - 'nullable': nullable - }) - - - def fetch(self, single=True, orderby=None, reverse=False, **kwargs): - if self.db._closed: - return logging.error('Database closed') - - if not kwargs: - rows = DBRows(self, self.getAll()) - single = False - - else: - rows = DBRows(self, self.getBy(kwargs)) - - if single: - return rows[0] if rows else None - - return rows if not orderby else sorted(rows, key=operator.itemgetter(orderby), reverse=reverse) - - - def search(self, orderby=None, reverse=None, **kwargs): - self.fetch(single=False, orderby=orderby, reverse=reverse, **kwargs) - - - def insert(self, row=None, rowid=None, **kwargs): - if self.db._closed: - return logging.error('Database closed') - - new_data = {} - - for name, col in self.columns.items(): - raw_value = kwargs.get(name, col.default) - value = serialize(raw_value, col.type) - - if not value and not col.nullable: - raise ValueError(f'Column "{name}" cannot be empty') - - new_data[name] = value - - if row: - rowid = row.id - - if rowid: - return self.update({'id': rowid}, new_data) - - return self.add(new_data) - - - def delete(self, rowid): - with self.lock: - with open(self.filename, "r+") as db_file: - db_data = self._get_load_function()(db_file) - result = [] - found = False - - for d in db_data["data"]: - print(d) - if rowid in d: - found = True - - else: - result.append(d) - - if not found: - raise IdNotFoundError(kwargs) - - db_data["data"] = result - db_file.seek(0) - db_file.truncate() - self._get_dump_function()(db_data, db_file) - - return True - - - def remove(self, row=None, rowid=None, **kwargs): - if self.db._closed: - return logging.error('Database closed') - - if row or rowid: - return self.remove({'id': rowid or row.id}) - - return self.delete(kwargs) - - - def _get_dump_function(self): - return lambda *args, **kwargs: json.dump(*args, indent=2, **kwargs) - - -def serialize(data, dtype): - types = { - 'datetime': lambda arg: arg.timestamp(), - 'dotdict': lambda arg: arg.toDict(), - 'bytes': lambda arg: base64.b64encode(arg).decode('ascii'), - 'bool': misc.Boolean, - 'int': int, - 'path': lambda arg: arg.str() - } - - if data != None: - serial_type = types.get(dtype) - return serial_type(data) if serial_type else data - - return data - - -def deserialize(data, dtype): - types = { - 'datetime': datetime.datetime.fromtimestamp, - 'dotdict': misc.DotDict, - 'dict': misc.DotDict, - 'bytes': lambda: base64.b64decode, - 'path': misc.Path - } - - return types.get(dtype)(data) if data else None - - - - -def DBRows(table, rows): - return [DBRow(table, row) for row in rows] - - -class DBRow(misc.DotDict): - def __init__(self, table, row): - super().__init(**{k: deserialize(row[v], v.type) for k,v in table.items()}) - self.table = table - - - def __str__(self): - data = ', '.join(f'{k}={v}' for k,v in self.items()) - return - - - def update(self, data={}): - super().update(data) - self.table.update(rowid=self.id, **self) - - - def remove(self): - self.table.remove(rowid=self.id) diff --git a/IzzyLib/error.py b/IzzyLib/error.py deleted file mode 100644 index 5565727..0000000 --- a/IzzyLib/error.py +++ /dev/null @@ -1,23 +0,0 @@ -class MissingHeadersError(Exception): - def __init__(self, headers: list): - self.headers = ', '.join(headers) - self.message = f'Missing required headers for verificaton: {self.headers}' - super().init(self.message) - - - def __str__(self): - return self.message - - -class VerificationError(Exception): - def __init__(self, string=None): - self.message = f'Failed to verify hash' - - if string: - self.message += ' for ' + string - - super().__init__(self.message) - - - def __str__(self): - return self.message diff --git a/IzzyLib/http.py b/IzzyLib/http.py deleted file mode 100644 index cded316..0000000 --- a/IzzyLib/http.py +++ /dev/null @@ -1,657 +0,0 @@ -import functools, json, sys - -from IzzyLib import logging -from IzzyLib.misc import DefaultDict, DotDict, Path -from base64 import b64decode, b64encode -from datetime import datetime -from io import BytesIO -from ssl import SSLCertVerificationError -from urllib.error import HTTPError -from urllib.parse import urlparse -from urllib.request import Request, urlopen - -from . import error, __version__ - - -try: - import requests -except ImportError: - logging.verbose('Requests module not found. RequestsClient disabled') - requests = False - -try: - from Crypto.Hash import SHA256 - from Crypto.PublicKey import RSA - from Crypto.Signature import PKCS1_v1_5 - crypto_enabled = True -except ImportError: - logging.verbose('Pycryptodome module not found. HTTP header signing and verifying is disabled') - crypto_enabled = False - -try: - from sanic.request import Request as SanicRequest -except ImportError: - logging.verbose('Sanic module not found. Request verification is disabled') - SanicRequest = False - -try: - from PIL import Image -except ImportError: - logging.verbose('Pillow module not found. Image downloading is disabled') - Image = False - - -Client = None -methods = ['connect', 'delete', 'get', 'head', 'options', 'patch', 'post', 'put', 'trace'] - - -class HttpClient(object): - def __init__(self, headers={}, useragent=f'IzzyLib/{__version__}', appagent=None, proxy_type='https', proxy_host=None, proxy_port=None): - proxy_ports = { - 'http': 80, - 'https': 443 - } - - if proxy_type not in ['http', 'https']: - raise ValueError(f'Not a valid proxy type: {proxy_type}') - - self.headers=headers - self.agent = f'{useragent} ({appagent})' if appagent else useragent - self.proxy = DotDict({ - 'enabled': True if proxy_host else False, - 'ptype': proxy_type, - 'host': proxy_host, - 'port': proxy_ports[proxy_type] if not proxy_port else proxy_port - }) - - self.SetGlobal = SetClient - - - def __sign_request(self, request, privkey, keyid): - if not crypto_enabled: - logging.error('Crypto functions disabled') - return - - request.add_header('(request-target)', f'{request.method.lower()} {request.path}') - request.add_header('host', request.host) - request.add_header('date', datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT')) - - if request.body: - body_hash = b64encode(SHA256.new(request.body).digest()).decode("UTF-8") - request.add_header('digest', f'SHA-256={body_hash}') - request.add_header('content-length', len(request.body)) - - sig = { - 'keyId': keyid, - 'algorithm': 'rsa-sha256', - 'headers': ' '.join([k.lower() for k in request.headers.keys()]), - 'signature': b64encode(PkcsHeaders(privkey, request.headers)).decode('UTF-8') - } - - sig_items = [f'{k}="{v}"' for k,v in sig.items()] - sig_string = ','.join(sig_items) - - request.add_header('signature', sig_string) - - request.remove_header('(request-target)') - request.remove_header('host') - - - def __build_request(self, url, data=None, headers={}, method='GET', stream=False): - new_headers = self.headers.copy() - new_headers.update(headers) - - parsed_headers = {k.lower(): v for k,v in new_headers.items()} - - if not parsed_headers.get('user-agent'): - parsed_headers['user-agent'] = self.agent - - if isinstance(data, dict): - data = json.dumps(data) - - if isinstance(data, str): - data = data.encode('UTF-8') - - request = Request(url, data=data, headers=parsed_headers, method=method, stream=stream) - - if self.proxy.enabled: - request.set_proxy(f'{self.proxy.host}:{self.proxy.port}', self.proxy.ptype) - - return request - - - def request(self, *args, **kwargs): - request = self.__build_request(*args, **kwargs) - - try: - response = urlopen(request) - - except HTTPError as e: - response = e.fp - - except SSLCertVerificationError as e: - logging.error('HttpClient.request: Certificate error:', e) - return - - return HttpResponse(response) - - - def file(self, url, filepath, *args, filename=None, size=2048, **kwargs): - path = Path(filepath) - filepath = path.join(filename if filename else Path(url).name) - - if filepath.exists(): - kwargs['headers']['range'] = f'bytes={filepath.size}' - - resp = self.request(url, *args, stream=True, **kwargs) - - if not resp.headers.get('content-length'): - logging.verbose('File already downloaded fully') - return True - - if resp.status != 200: - logging.error(f'Failed to download {url}:', resp.status, resp.body) - return False - - if not path.exists(): - logging.error('Path does not exist:', path) - return False - - with filepath.open('ab') as fd: - for chunk in resp.chunks(size): - fd.write(chunk) - - return True - - - def image(self, url, filepath, *args, filename=None, ext='png', dimensions=(50, 50), **kwargs): - if not Image: - logging.error('Pillow module is not installed') - return - - resp = self.request(url, *args, **kwargs) - - if resp.status != 200: - logging.error(f'Failed to download {url}:', resp.status, resp.body) - return False - - if not filename: - filename = Path(url).stem() - - path = Path(filepath) - - if not path.exists(): - logging.error('Path does not exist:', path) - return False - - byte = BytesIO() - image = Image.open(BytesIO(resp.body)) - image.thumbnail(dimensions) - image.save(byte, format=ext.upper()) - - with path.join(filename).open('wb') as fd: - fd.write(byte.getvalue()) - - - def json(self, *args, headers={}, activity=True, **kwargs): - json_type = 'activity+json' if activity else 'json' - headers.update({ - 'accept': f'application/{json_type}' - }) - return self.request(*args, headers=headers, **kwargs) - - - def signed_request(self, privkey, keyid, *args, **kwargs): - request = self.__build_request(*args, **kwargs) - - self.__sign_request(request, privkey, keyid) - - try: - response = urlopen(request) - except HTTPError as e: - response = e - - return HttpResponse(response) - - -class HttpResponse(object): - def __init__(self, response): - self.body = response.read() - self.headers = DefaultDict({k.lower(): v.lower() for k,v in response.headers.items()}) - self.status = response.status - self.url = response.url - - - def text(self): - return self.body.decode('UTF-8') - - - def json(self, fail=False): - try: - return DotDict(self.text()) - except Exception as e: - if fail: - raise e from None - - else: - return DotDict() - - - def json_pretty(self, indent=4): - return json.dumps(self.json().asDict(), indent=indent) - - -class RequestsClient(object): - def __init__(self, headers={}, useragent=f'IzzyLib/{__version__}', appagent=None, proxy_type='https', proxy_host=None, proxy_port=None): - proxy_ports = { - 'http': 80, - 'https': 443 - } - - if proxy_type not in ['http', 'https']: - raise ValueError(f'Not a valid proxy type: {proxy_type}') - - self.headers=headers - self.agent = f'{useragent} ({appagent})' if appagent else useragent - self.proxy = DotDict({ - 'enabled': True if proxy_host else False, - 'ptype': proxy_type, - 'host': proxy_host, - 'port': proxy_ports[proxy_type] if not proxy_port else proxy_port - }) - - self.SetGlobal = SetClient - - - def __sign_request(self, request, privkey, keyid): - if not crypto_enabled: - logging.error('Crypto functions disabled') - return - - request.add_header('(request-target)', f'{request.method.lower()} {request.path}') - request.add_header('host', request.host) - request.add_header('date', datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT')) - - if request.body: - body_hash = b64encode(SHA256.new(request.body).digest()).decode("UTF-8") - request.add_header('digest', f'SHA-256={body_hash}') - request.add_header('content-length', len(request.body)) - - sig = { - 'keyId': keyid, - 'algorithm': 'rsa-sha256', - 'headers': ' '.join([k.lower() for k in request.headers.keys()]), - 'signature': b64encode(PkcsHeaders(privkey, request.headers)).decode('UTF-8') - } - - sig_items = [f'{k}="{v}"' for k,v in sig.items()] - sig_string = ','.join(sig_items) - - request.add_header('signature', sig_string) - - request.remove_header('(request-target)') - request.remove_header('host') - - - def request(self, *args, method='get', **kwargs): - if method.lower() not in methods: - raise ValueError(f'Invalid method: {method}') - - request = RequestsRequest(self, *args, method=method.lower(), **kwargs) - return RequestsResponse(request.send()) - - - def file(self, url, filepath, *args, filename=None, **kwargs): - resp = self.request(url, *args, **kwargs) - - if resp.status != 200: - logging.error(f'Failed to download {url}:', resp.status, resp.body) - return False - - return resp.save(filepath) - - - def image(self, url, filepath, *args, filename=None, ext='png', dimensions=(50, 50), **kwargs): - if not Image: - logging.error('Pillow module is not installed') - return - - resp = self.request(url, *args, **kwargs) - - if resp.status != 200: - logging.error(f'Failed to download {url}:', resp.status, resp.body) - return False - - if not filename: - filename = Path(url).stem() - - path = Path(filepath) - - if not path.exists(): - logging.error('Path does not exist:', path) - return False - - byte = BytesIO() - image = Image.open(BytesIO(resp.body)) - image.thumbnail(dimensions) - image.save(byte, format=ext.upper()) - - with path.join(filename).open('wb') as fd: - fd.write(byte.getvalue()) - - - def json(self, *args, **kwargs): - return self.dict(*args, **kwargs) - - - def dict(self, *args, headers={}, activity=True, **kwargs): - json_type = 'activity+json' if activity else 'json' - headers.update({ - 'accept': f'application/{json_type}' - }) - return self.request(*args, headers=headers, **kwargs).dict - - - def signed_request(self, privkey, keyid, *args, **kwargs): - request = RequestsRequest(self, *args, **kwargs) - self.__sign_request(request, privkey, keyid) - return RequestsResponse(request.send()) - - -class RequestsRequest(object): - def __init__(self, client, url, data=None, headers={}, query={}, method='get'): - self.args = [url] - self.kwargs = {'params': query} - self.method = method.lower() - self.client = client - - new_headers = client.headers.copy() - new_headers.update(headers) - - parsed_headers = {k.lower(): v for k,v in new_headers.items()} - - if not parsed_headers.get('user-agent'): - parsed_headers['user-agent'] = client.agent - - self.kwargs['headers'] = new_headers - self.kwargs['data'] = data - - if client.proxy.enabled: - self.kwargs['proxies'] = {self.proxy.ptype: f'{self.proxy.ptype}://{self.proxy.host}:{self.proxy.port}'} - - - def send(self): - func = getattr(requests, self.method) - return func(*self.args, **self.kwargs) - - -class RequestsResponse(object): - def __init__(self, response): - self.response = response - self.data = b'' - self.headers = DefaultDict({k.lower(): v.lower() for k,v in response.headers.items()}) - self.status = response.status_code - self.url = response.url - - - def chunks(self, size=256): - return self.response.iter_content(chunk_size=256) - - - @property - def body(self): - for chunk in self.chunks(): - self.data += chunk - - return self.data - - - @property - def text(self): - if not self.data: - return self.body.decode(self.response.encoding) - - return self.data.decode(self.response.encoding) - - - @property - def dict(self): - try: - return DotDict(self.text) - except Exception as e: - return DotDict() - - - @property - def json(self): - return json.dumps(self.dict) - - - @property - def json_pretty(self, indent=4): - return json.dumps(self.dict, indent=indent) - - - def save(self, path, overwrite=True): - path = Path(path) - parent = path.parent() - - if not parent.exists(): - raise ValueError(f'Path does not exist: {parent}') - - if overwrite and path.exists(): - path.delete() - - with path.open('wb') as fd: - for chunk in self.chunks(): - fd.write(chunk) - - -def VerifyRequest(request: SanicRequest, actor: dict): - '''Verify a header signature from a sanic request - - request: The request with the headers to verify - actor: A dictionary containing the activitypub actor and the link to the pubkey used for verification - ''' - if not SanicRequest: - logging.error('Sanic request verification disabled') - return - - body = request.body if request.body else None - return VerifyHeaders(request.headers, request.method, request.path, body, actor) - - -def VerifyHeaders(headers: dict, method: str, path: str, actor: dict=None, body=None): - '''Verify a header signature - - headers: A dictionary containing all the headers from a request - method: The HTTP method of the request - path: The path of the HTTP request - actor (optional): A dictionary containing the activitypub actor and the link to the pubkey used for verification - body (optional): The body of the request. Only needed if the signature includes the digest header - fail (optional): If set to True, raise an error instead of returning False if any step of the process fails - ''' - if not crypto_enabled: - logging.error('Crypto functions disabled') - return - - headers = {k.lower(): v for k,v in headers.items()} - headers['(request-target)'] = f'{method.lower()} {path}' - signature = ParseSig(headers.get('signature')) - digest = ParseBodyDigest(headers.get('digest')) - missing_headers = [k for k in headers if k in ['date', 'host'] if headers.get(k) == None] - - if not signature: - logging.verbose('Missing signature') - return False - - if not actor: - actor = FetchActor(signature.keyid) - - ## Add digest header to missing headers list if it doesn't exist - if method.lower() == 'post' and not digest: - missing_headers.append('digest') - - ## Fail if missing date, host or digest (if POST) headers - if missing_headers: - logging.verbose('Missing headers:', missing_headers) - return False - - ## Fail if body verification fails - if digest and not VerifyString(body, digest.sig, digest.alg): - logging.verbose('Failed body digest verification') - return False - - pubkey = actor.publicKey['publicKeyPem'] - - if PkcsHeaders(pubkey, {k:v for k,v in headers.items() if k in signature.headers}, sig=signature): - return True - - logging.verbose('Failed header verification') - return False - - -def ParseBodyDigest(digest): - if not digest: - return - - parsed = DotDict() - parts = digest.split('=', 1) - - if len(parts) != 2: - return - - parsed.sig = parts[1] - parsed.alg = parts[0].replace('-', '') - - return parsed - - -def VerifyString(string, enc_string, alg='SHA256', fail=False): - if not crypto_enabled: - logging.error('Crypto functions disabled') - return - - if type(string) != bytes: - string = string.encode('UTF-8') - - body_hash = b64encode(SHA256.new(string).digest()).decode('UTF-8') - - if body_hash == enc_string: - return True - - if fail: - raise error.VerificationError() - - else: - return False - - -def PkcsHeaders(key: str, headers: dict, sig=None): - if not crypto_enabled: - logging.error('Crypto functions disabled') - return - - if sig: - head_items = [f'{item}: {headers[item]}' for item in sig.headers] - - else: - head_items = [f'{k.lower()}: {v}' for k,v in headers.items()] - - head_string = '\n'.join(head_items) - head_bytes = head_string.encode('UTF-8') - - KEY = RSA.importKey(key) - pkcs = PKCS1_v1_5.new(KEY) - h = SHA256.new(head_bytes) - - if sig: - return pkcs.verify(h, b64decode(sig.signature)) - - else: - return pkcs.sign(h) - - -def ParseSig(signature: str): - if not signature: - logging.verbose('Missing signature header') - return - - split_sig = signature.split(',') - sig = DefaultDict({}) - - for part in split_sig: - key, value = part.split('=', 1) - sig[key.lower()] = value.replace('"', '') - - if not sig.headers: - logging.verbose('Missing headers section in signature') - return - - sig.headers = sig.headers.split() - - return sig - - -def FetchActor(url): - if not Client: - logging.error('IzzyLib.http: Please set global client with "SetClient(client)"') - return {} - - url = url.split('#')[0] - headers = {'Accept': 'application/activity+json'} - resp = Client.request(url, headers=headers) - - if not resp.json(): - logging.verbose('functions.FetchActor: Failed to fetch actor:', url) - logging.debug(f'Error {resp.status}: {resp.body}') - return {} - - actor = resp.json() - actor.web_domain = urlparse(url).netloc - actor.shared_inbox = actor.inbox - actor.pubkey = None - actor.handle = actor.preferredUsername - - if actor.get('endpoints'): - actor.shared_inbox = actor.endpoints.get('sharedInbox', actor.inbox) - - if actor.get('publicKey'): - actor.pubkey = actor.publicKey.get('publicKeyPem') - - return actor - - -@functools.lru_cache(maxsize=512) -def FetchWebfingerAcct(handle, domain): - if not Client: - logging.error('IzzyLib.http: Please set global client with "SetClient(client)"') - return {} - - data = DefaultDict() - webfinger = Client.request(f'https://{domain}/.well-known/webfinger?resource=acct:{handle}@{domain}') - - if not webfinger.body: - return - - data.handle, data.domain = webfinger.json().subject.replace('acct:', '').split('@') - - for link in webfinger.json().links: - if link['rel'] == 'self' and link['type'] == 'application/activity+json': - data.actor = link['href'] - - return data - - -def SetClient(client=None): - global Client - Client = client or HttpClient() - - -def GenRsaKey(): - privkey = RSA.generate(2048) - - key = DotDict({'PRIVKEY': privkey, 'PUBKEY': privkey.publickey()}) - key.update({'privkey': key.PRIVKEY.export_key().decode(), 'pubkey': key.PUBKEY.export_key().decode()}) - - return key diff --git a/IzzyLib/logging.py b/IzzyLib/logging.py deleted file mode 100644 index 53febd5..0000000 --- a/IzzyLib/logging.py +++ /dev/null @@ -1,221 +0,0 @@ -'''Simple logging module''' - -import sys - -from os import environ as env -from datetime import datetime - - -stdout = sys.stdout - - -class Log(): - def __init__(self, name=None, config=dict()): - '''setup the logger''' - if not isinstance(config, dict): - raise TypeError(f'config is not a dict') - - self.levels = { - 'CRIT': 60, - 'ERROR': 50, - 'WARN': 40, - 'INFO': 30, - 'VERB': 20, - 'DEBUG': 10, - 'MERP': 0 - } - - self.long_levels = { - 'CRITICAL': 'CRIT', - 'ERROR': 'ERROR', - 'WARNING': 'WARN', - 'INFO': 'INFO', - 'VERBOSE': 'VERB', - 'DEBUG': 'DEBUG', - 'MERP': 'MERP' - } - - self.name = name - self.config = {'windows': sys.executable.endswith('pythonw.exe')} - self.setConfig(self._parseConfig(config)) - - - def _lvlCheck(self, level): - '''make sure the minimum logging level is an int''' - try: - value = int(level) - - except ValueError: - level = self.long_levels.get(level.upper(), level) - value = self.levels.get(level) - - if value not in self.levels.values(): - raise InvalidLevel(f'Invalid logging level: {level}') - - return value - - - def _getLevelName(self, level): - for name, num in self.levels.items(): - if level == num: - return name - - raise InvalidLevel(f'Invalid logging level: {level}') - - - def _parseConfig(self, config): - '''parse the new config and update the old values''' - date = config.get('date', self.config.get('date',True)) - systemd = config.get('systemd', self.config.get('systemd,', True)) - windows = config.get('windows', self.config.get('windows', False)) - - if not isinstance(date, bool): - raise TypeError(f'value for "date" is not a boolean: {date}') - - if not isinstance(systemd, bool): - raise TypeError(f'value for "systemd" is not a boolean: {date}') - - level_num = self._lvlCheck(config.get('level', self.config.get('level', 'INFO'))) - - newconfig = { - 'level': self._getLevelName(level_num), - 'levelnum': level_num, - 'datefmt': config.get('datefmt', self.config.get('datefmt', '%Y-%m-%d %H:%M:%S')), - 'date': date, - 'systemd': systemd, - 'windows': windows, - 'systemnotif': config.get('systemnotif', None) - } - - return newconfig - - - def setConfig(self, config): - '''set the config''' - self.config = self._parseConfig(config) - - - def getConfig(self, key=None): - '''return the current config''' - if key: - if self.config.get(key): - return self.config.get(key) - else: - raise ValueError(f'Invalid config option: {key}') - return self.config - - - def printConfig(self): - for k,v in self.config.items(): - stdout.write(f'{k}: {v}\n') - - stdout.flush() - - - def setLevel(self, level): - self.minimum = self._lvlCheck(level) - - - def log(self, level, *msg): - if self.config['windows']: - return - - '''log to the console''' - levelNum = self._lvlCheck(level) - - if type(level) == int: - level = self._getLevelName(level) - - if levelNum < self.config['levelnum']: - return - - message = ' '.join([str(message) for message in msg]) - - if self.name: - output = f'[{self.name}] ' - - else: - output = '' - - output += f'{level}: {message}\n' - - if self.config['systemnotif']: - self.config['systemnotif'].New(level, message) - - if self.config['date'] and (self.config['systemd'] and not env.get('INVOCATION_ID')): - '''only show date when not running in systemd and date var is True''' - date = datetime.now().strftime(self.config['datefmt']) - output = f'{date} {output}' - - stdout.write(output) - stdout.flush() - - - def critical(self, *msg): - self.log('CRIT', *msg) - - def error(self, *msg): - self.log('ERROR', *msg) - - def warning(self, *msg): - self.log('WARN', *msg) - - def info(self, *msg): - self.log('INFO', *msg) - - def verbose(self, *msg): - self.log('VERB', *msg) - - def debug(self, *msg): - self.log('DEBUG', *msg) - - def merp(self, *msg): - self.log('MERP', *msg) - - -def getLogger(name): - '''get a logging instance and create one if it doesn't exist''' - log = logger.get(name) - - if not log: - raise InvalidLogger(f'logger "{name}" doesn\'t exist') - - return log - - -def setLogger(name, config={}): - log = Log(name, config) - logger[name.lower()] = log - return log - - -class InvalidLevel(Exception): - '''Raise when an invalid logging level was specified''' - -class InvalidLogger(Exception): - '''Raise when the specified logger doesn't exist''' - - -'''create a default logger''' -logger = { - 'default': Log() -} - -DefaultLog = logger['default'] - - -'''aliases for default logger's log output functions''' -log = DefaultLog.log -critical = DefaultLog.critical -error = DefaultLog.error -warning = DefaultLog.warning -info = DefaultLog.info -verbose = DefaultLog.verbose -debug = DefaultLog.debug -merp = DefaultLog.merp - -'''aliases for the default logger's config functions''' -setConfig = DefaultLog.setConfig -getConfig = DefaultLog.getConfig -setLevel = DefaultLog.setLevel -printConfig = DefaultLog.printConfig diff --git a/IzzyLib/misc.py b/IzzyLib/misc.py deleted file mode 100644 index 1abcdb9..0000000 --- a/IzzyLib/misc.py +++ /dev/null @@ -1,674 +0,0 @@ -'''Miscellaneous functions''' -import hashlib, random, string, sys, os, json, statistics, socket, time, timeit - -from os import environ as env -from datetime import datetime -from getpass import getpass -from importlib import util -from pathlib import Path as Pathlib -from shutil import copyfile, rmtree - -from . import logging - -try: - import argon2 -except ImportError: - logging.verbose('argon2-cffi not installed. PasswordHasher class disabled') - argon2 = None - - -def Boolean(v, return_value=False): - if type(v) not in [str, bool, int, type(None)]: - raise ValueError(f'Value is not a string, boolean, int, or nonetype: {value}') - - '''make the value lowercase if it's a string''' - value = v.lower() if isinstance(v, str) else v - - if value in [1, True, 'on', 'y', 'yes', 'true', 'enable']: - '''convert string to True''' - return True - - if value in [0, False, None, 'off', 'n', 'no', 'false', 'disable', '']: - '''convert string to False''' - return False - - if return_value: - '''just return the value''' - return v - - return True - - -def RandomGen(length=20, letters=True, digits=True, extra=None): - if not isinstance(length, int): - raise TypeError(f'Character length must be an integer, not {type(length)}') - - characters = '' - - if letters: - characters += string.ascii_letters - - if digits: - characters += string.digits - - if extra: - characters += extra - - return ''.join(random.choices(characters, k=length)) - - -def HashString(string, alg='blake2s'): - if alg not in hashlib.__always_supported: - logging.error('Unsupported hash algorithm:', alg) - logging.error('Supported algs:', ', '.join(hashlib.__always_supported)) - return - - string = string.encode('UTF-8') if type(string) != bytes else string - salt = salt.encode('UTF-8') if type(salt) != bytes else salt - - newhash = hashlib.new(alg) - newhash.update(string) - return newhash.hexdigest() - - -def Timestamp(dtobj=None, utc=False): - dtime = dtobj if dtobj else datetime - date = dtime.utcnow() if utc else dtime.now() - - return date.timestamp() - - -def GetVarName(*kwargs, single=True): - keys = list(kwargs.keys()) - return key[0] if single else keys - - -def ApDate(date=None, alt=False): - if not date: - date = datetime.utcnow() - - elif type(date) == int: - date = datetime.fromtimestamp(date) - - elif type(date) != datetime: - raise TypeError(f'Unsupported object type for ApDate: {type(date)}') - - return date.strftime('%a, %d %b %Y %H:%M:%S GMT' if alt else '%Y-%m-%dT%H:%M:%SZ') - - -def GetIp(): - s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - - try: - s.connect(('10.255.255.255', 1)) - data = s.getsockname() - ip = data[0] - - except Exception: - ip = '127.0.0.1' - - finally: - s.close() - - return ip - - -def ImportFromPath(mod_path): - mod_path = Path(mod_path) - path = mod_path.join('__init__.py') if mod_path.isdir() else mod_path - name = path.name.replace('.py', '', -1) - - spec = util.spec_from_file_location(name, path.str()) - module = util.module_from_spec(spec) - spec.loader.exec_module(module) - return module - - -def Input(prompt, default=None, valtype=str, options=[], password=False): - input_func = getpass if password else input - - if default != None: - prompt += ' [-redacted-]' if password else f' [{default}]' - - prompt += '\n' - - if options: - opt = '/'.join(options) - prompt += f'[{opt}]' - - prompt += ': ' - value = input_func(prompt) - - while value and len(options) > 0 and value not in options: - input_func('Invalid value:', value) - value = input(prompt) - - if not value or value == '': - return default - - ret = valtype(value) - - while valtype == Path and not ret.parent().exists(): - input_func('Parent directory doesn\'t exist') - ret = Path(input(prompt)) - - return ret - - -def NfsCheck(path): - proc = Path('/proc/mounts') - path = Path(path).resolve() - - 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(): - return True - - return False - - -def PortCheck(port, address='127.0.0.1', tcp=True): - with socket.socket(socket.AF_INET, socket.SOCK_STREAM if tcp else socket.SOCK_DGRAM) as s: - try: - return not s.connect_ex((address, port)) == 0 - - except socket.error as e: - print(e) - return False - - -def PrintMethods(object, include_underscore=False): - for line in dir(object): - if line.startswith('_'): - if include_underscore: - print(line) - - else: - print(line) - - -def TimeFunction(func, *args, passes=1, use_gc=True, **kwargs): - options = [ - lambda: func(*args, **kwargs) - ] - - if use_gc: - options.append('gc.enable()') - - timer = timeit.Timer(*options) - - if passes > 1: - return timer.repeat(passes, 1) - - return timer.timeit(1) - - -def TimeFunctionPPrint(func, *args, passes=5, use_gc=True, floatlen=3, **kwargs): - parse_time = lambda num: f'{round(num, floatlen)}s' - times = [] - - for idx in range(0, passes): - passtime = TimeFunction(func, *args, **kwargs, passes=1, use_gc=use_gc) - times.append(passtime) - print(f'Pass {idx+1}: {parse_time(passtime)}') - - average = statistics.fmean(times) - - print('-----------------') - print(f'Average: {parse_time(average)}') - print(f'Total: {parse_time(sum(times))}') - - - -def TimePassHasher(string='hecking heck', passes=3, iterations=[2,4,8,16,32,64,96]): - for iteration in iterations: - print('\nTesting hash iterations:', iteration) - hasher = PasswordHasher(iterations=iteration) - strhash = hasher.hash(string) - TimeFunctionPPrint(hasher.verify, strhash, string, passes=passes) - - -class Connection(socket.socket): - def __init__(self, address='127.0.0.1', port=8080, tcp=True): - super().__init__(socket.AF_INET, socket.SOCK_STREAM if tcp else socket.SOCK_DGRAM) - self.address = address - self.port = port - - - def __enter__(self): - self.connect((self.address, self.port)) - return self - - - def __exit__(self, exctype, value, tb): - self.close() - - - def send(self, msg): - self.sendall(msg) - - - def recieve(self, size=8192): - return self.recv(size) - - -class DotDict(dict): - dict_ignore_types = ['basecache', 'lrucache', 'ttlcache'] - - - def __init__(self, value=None, **kwargs): - '''Python dictionary, but variables can be set/get via attributes - - value [str, bytes, dict]: JSON or dict of values to init with - kwargs: key/value pairs to set on init. Overrides identical keys set by 'value' - ''' - - super().__init__() - self.__setattr__ = self.__setitem__ - - ## compatibility - self.toJson = self.to_json - self.fromJson = self.from_json - - if isinstance(value, (str, bytes)): - self.from_json(value) - - elif value.__class__.__name__.lower() not in self.dict_ignore_types and isinstance(value, dict): - self.update(value) - - elif value: - raise TypeError(f'The value must be a JSON string, list, dict, or another DotDict object, not {value.__class__}') - - if kwargs: - self.update(kwargs) - - - def __getattr__(self, k): - try: - return super().__getitem__(k) - - except KeyError: - raise AttributeError(f'{self.__class__.__name__} object has no attribute {k}') from None - - - def __setitem__(self, k, v): - if v.__class__.__name__.lower() not in self.dict_ignore_types and isinstance(v, dict): - v = DotDict(v) - - super().__setitem__(k, v) - - - def __delattr__(self, k): - try: - dict.__delitem__(self, k) - except KeyError: - raise AttributeError(f'{self.__class__.__name__} object has no attribute {k}') from None - - - def update(self, data): - for k,v in data.items(): - self.__setitem__(k, v) - - - def to_json(self, indent=None, **kwargs): - if 'cls' not in kwargs: - kwargs['cls'] = JsonEncoder - - return json.dumps(dict(self), indent=indent, **kwargs) - - - def from_json(self, string): - data = json.loads(string) - self.update(data) - - - def load_json(self, path: str=None): - self.update(Path(path).load_json()) - - - def save_json(self, path: str, **kwargs): - with Path(path).open(w) as fd: - write(self.toJson(*kwargs)) - - -## This has to be reworked tbh -class DefaultDict(DotDict): - def __getattr__(self, key): - try: - val = super().__getattribute__(key) - - except AttributeError: - val = self.get(key, DefaultDict()) - - return DotDict(val) if type(val) == dict else val - - -class LowerDotDict(DotDict): - def __getattr__(self, key): - return super().__getattr__(self, key.lower()) - - - def __setattr__(self, key, value): - return super().__setattr__(key.lower(), value) - - - def update(self, data): - data = {k.lower(): v for k,v in self.items()} - - return super().update(data) - - -class Path(object): - def __init__(self, path, exist=True, missing=True, parents=True): - self.__path = Pathlib(str(path)) - - if str(path).startswith('~'): - self.__path = self.__path.expanduser() - - self.json = DotDict() - self.exist = exist - self.missing = missing - self.parents = parents - self.name = self.__path.name - self.stem = self.__path.stem - - - def __str__(self): - return str(self.__path) - - - def __repr__(self): - return f'Path({str(self.__path)})' - - - def str(self): - return self.__str__() - - - 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.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}') - - - def append(self, text, new=True): - path = str(self.__path) + text - - if new: - return Path(path) - - self.__path = Pathlib(path) - - return self - - - def size(self): - return self.__path.stat().st_size - - - def mtime(self): - return self.__path.stat().st_mtime - - - def mkdir(self, mode=0o755): - self.__path.mkdir(mode, self.parents, self.exist) - - return True if self.__path.exists() else False - - - def new(self): - return Path(self.__path) - - - def parent(self, new=True): - path = Pathlib(self.__path).parent - - if new: - return Path(path) - - self.__path = path - - return self - - - def copy(self, path, overwrite=False): - target = Path(path) - - self.__check_dir(path) - - if target.exists() and overwrite: - target.delete() - - copyfile(self.str(), target.str()) - - - def backup(self, ext='backup', overwrite=False): - target = f'{self.__path.parent}.{ext}' - self.copy(target, overwrite) - - - def move(self, path, overwrite=False): - self.copy(path, overwrite=overwrite) - self.delete() - - - def join(self, path, new=True): - new_path = self.__path.joinpath(path) - - if new: - return Path(new_path) - - self.__path = new_path - - return self - - - def home(self, path=None, new=True): - new_path = Pathlib.home() - - if path: - new_path = new_path.joinpath(path) - - if new: - return Path(new_path) - - self.__path = new_path - return self - - - def isdir(self): - return self.__path.is_dir() - - - def isfile(self): - return self.__path.is_file() - - - def islink(self): - return self.__path.is_symlink() - - - def listdir(self, recursive=True): - paths = self.__path.iterdir() if recursive else os.listdir(self.__path) - return [Path(path) for path in paths] - - - def exists(self): - return self.__path.exists() - - - def mtime(self): - return os.path.getmtime(self.str()) - - - def size(self): - return self.__path.stat().st_size - - - def link(self, path): - target = Path(path) - - self.__check_dir(path) - - if target.exists(): - target.delete() - - self.__path.symlink_to(path, target.isdir()) - - - def resolve(self, new=True): - path = self.__path.resolve() - - if new: - return Path(path) - - self.__path = path - return self - - - def chmod(self, mode=None): - octal = self.__parse_perm_octal(mode) - self.__path.chmod(octal) - - - def touch(self, mode=0o666): - octal = __parse_perm_octal(mode) - self.__path.touch(octal, self.exist) - - return self.exists() - - - def mkdir(self): - self.__path.mkdir(parents=self.parents, exist_ok=self.exist) - - return self.exists() - - - def load_json(self): - self.json = DotDict(self.read()) - - return self.json - - - def save_json(self, indent=None): - with self.__path.open('w') as fp: - fp.write(json.dumps(self.json.asDict(), indent=indent, cls=JsonEncoder)) - - - def update_json(self, data={}): - if type(data) == str: - data = json.loads(data) - - self.json.update(data) - - - def delete(self): - if self.isdir(): - rmtree(self.__path) - - else: - self.__path.unlink() - - return not self.exists() - - - def open(self, *args): - return self.__path.open(*args) - - - def read(self, *args): - return self.open().read(*args) - - - def readlines(self): - return self.open().readlines() - - -class JsonEncoder(json.JSONEncoder): - def default(self, obj): - if not any(map(isinstance, [obj], [str, int, float, dict])): - return str(obj) - - return json.JSONEncoder.default(self, obj) - - -class PasswordHasher(DotDict): - ## The defaults can usually be used, except for `iterations`. That should be tweaked on each machine - ## You can use the TimeFunctionPPrint command above to test this - - aliases = { - 'iterations': 'time_cost', - 'memory': 'memory_cost', - 'threads': 'parallelism' - } - - - def __init__(self, **kwargs): - if not argon2: - raise ValueError('password hashing disabled') - - super().__init__({ - 'time_cost': 16, - 'memory_cost': 100 * 1024, - 'parallelism': os.cpu_count(), - 'encoding': 'utf-8', - 'type': argon2.Type.ID, - }) - - self.hasher = None - self.update(kwargs) - self.setup() - - - def get_config(self, key): - key = self.aliases.get(key, key) - - self[key] - return self.get(key) / 1024 if key == 'memory_cost' else self.get(key) - - - def set_config(self, key, value): - key = self.aliases.get(key, key) - self[key] = value * 1024 if key == 'memory_cost' else value - self.setup() - - - def setup(self): - self.hasher = argon2.PasswordHasher(**self) - - - def hash(self, password: str): - return self.hasher.hash(password) - - - def verify(self, passhash: str, password: str): - try: - return self.hasher.verify(passhash, password) - - except argon2.exceptions.VerifyMismatchError: - return False - - - def iteration_test(self, string='hecking heck', passes=3, iterations=[8,16,24,32,40,48,56,64]): - original_iter = self.get_config('iterations') - - for iteration in iterations: - self.set_config('iterations', iteration) - print('\nTesting hash iterations:', iteration) - - TimeFunctionPPrint(self.verify, self.hash(string), string, passes=passes) - - self.set_config('iterations', original_iter) diff --git a/LICENSE b/LICENSE index 474951a..e6dfff4 100644 --- a/LICENSE +++ b/LICENSE @@ -1,7 +1,7 @@ IzzyLib -Copyright Zoey Mae 2020 +Copyright Zoey Mae 2021 -COOPERATIVE NON-VIOLENT PUBLIC LICENSE v4 +COOPERATIVE NON-VIOLENT PUBLIC LICENSE v6 Preamble @@ -19,7 +19,7 @@ Official Webpage: https://thufie.lain.haus/NPL.html Terms and Conditions THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS -COOPERATIVE NON-VIOLENT PUBLIC LICENSE v4 ("LICENSE"). THE WORK IS +COOPERATIVE NON-VIOLENT PUBLIC LICENSE v5 ("LICENSE"). THE WORK IS PROTECTED BY COPYRIGHT AND ALL OTHER APPLICABLE LAWS. ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED. BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED IN THIS @@ -51,11 +51,14 @@ TO BE BOUND BY THE TERMS AND CONDITIONS OF THIS LICENSE. For the avoidance of doubt, where the Work is a musical work, performance or phonogram, the synchronization of the Work in timed-relation with a moving image ("synching") will be - considered an Adaptation for the purpose of this License. + considered an Adaptation for the purpose of this License. In + addition, where the Work is designed to output a neural network + the output of the neural network will be considered an + Adaptation for the purpose of this license. c. "Bodily Harm" means any physical hurt or injury to a person that interferes with the health or comfort of the person and that is more - more than merely transient or trifling in nature. + than merely transient or trifling in nature. d. "Collection" means a collection of literary or artistic works, such as encyclopedias and anthologies, or performances, @@ -75,9 +78,13 @@ TO BE BOUND BY THE TERMS AND CONDITIONS OF THIS LICENSE. through sale, gift or any other transfer of possession or ownership. - f. "Incarceration" means confinement in a jail, prison, or any - other place where individuals of any kind are held against - either their will or the will of their legal guardians. + f. "Incarceration" means confinement in a jail, prison, or + any other place where individuals of any kind are held against + either their will or (if their will cannot be determined) the + will of their legal guardian or guardians. In the case of a + conflict between the will of the individual and the will of + their legal guardian or guardians, the will of the + individual will take precedence. g. "Licensor" means the individual, individuals, entity or entities that offer(s) the Work under the terms of this License. @@ -153,7 +160,7 @@ TO BE BOUND BY THE TERMS AND CONDITIONS OF THIS LICENSE. overtly or covertly observe and record persons and or their activities. - p. "Web Service" means the use of a piece of Software to + p. "Network Service" means the use of a piece of Software to interpret or modify information that is subsequently and directly served to users over the Internet. @@ -166,6 +173,11 @@ TO BE BOUND BY THE TERMS AND CONDITIONS OF THIS LICENSE. for some group or advocating a form of Discrimination (to Discriminate per definition in (q)) between humans. + s. "Coercion" means leveraging of the threat of force or use of force + to intimidate a person in order to gain compliance, or to offer + large incentives which aim to entice a person to act against their + will. + 2. FAIR DEALING RIGHTS Nothing in this License is intended to reduce, limit, or restrict any @@ -251,7 +263,7 @@ TO BE BOUND BY THE TERMS AND CONDITIONS OF THIS LICENSE. form, or You provide a URI for the corresponding Source Code of the Work, to any recipients upon request. - d. If the Work is used as or for a Web Service, You may exercise + d. If the Work is used as or for a Network Service, You may exercise the rights granted in Section 3 only if You provide a copy of the corresponding Source Code from which the Work was derived in digital form, or You provide a URI for the corresponding Source Code to the @@ -259,11 +271,11 @@ TO BE BOUND BY THE TERMS AND CONDITIONS OF THIS LICENSE. Service. e. You may exercise the rights granted in Section 3 for - commercial purposes only if you satisfy any of the following: + commercial purposes only if: i. You are a worker-owned business or worker-owned collective; and - ii. after tax, all financial gain, surplus, profits and + ii. after tax, all financial gain, surplus, profits and benefits produced by the business or collective are distributed among the worker-owners unless a set amount is to be allocated towards community projects as decided @@ -285,15 +297,19 @@ TO BE BOUND BY THE TERMS AND CONDITIONS OF THIS LICENSE. i. You do not use the Work for the purpose of inflicting Bodily Harm on human beings (subject to criminal - prosecution or otherwise) outside of providing medical aid. + prosecution or otherwise) outside of providing medical aid + or undergoing a voluntary procedure under no form of + Coercion. ii.You do not use the Work for the purpose of Surveilling or tracking individuals for financial gain. iii. You do not use the Work in an Act of War. iv. You do not use the Work for the purpose of supporting or profiting from an Act of War. v. You do not use the Work for the purpose of Incarceration. - vi. You do not use the Work for the purpose of extracting - oil, gas, or coal. + vi. You do not use the Work for the purpose of extracting, + processing, or refining, oil, gas, or coal. Or to in any other + way to deliberately pollute the environment as a byproduct + of manufacturing or irresponsible disposal of hazardous materials. vii. You do not use the Work for the purpose of expediting, coordinating, or facilitating paid work undertaken by individuals under the age of 12 years. @@ -310,11 +326,11 @@ TO BE BOUND BY THE TERMS AND CONDITIONS OF THIS LICENSE. pseudonym, if applicable) if supplied, and/or if the Original Author and/or Licensor designate another party or parties (e.g., a sponsor institute, publishing entity, journal) for attribution - ("Attribution Parties") in Licensor!s copyright notice, terms of + ("Attribution Parties") in Licensor's copyright notice, terms of service or by other reasonable means, the name of such party or parties; (ii) the title of the Work if supplied; (iii) to the extent reasonably practicable, the URI, if any, that Licensor - specifies to be associated with the Work, unless such URI does + to be associated with the Work, unless such URI does not refer to the copyright notice or licensing information for the Work; and, (iv) consistent with Section 3(b), in the case of an Adaptation, a credit identifying the use of the Work in the @@ -464,7 +480,7 @@ TO BE BOUND BY THE TERMS AND CONDITIONS OF THIS LICENSE. a copy and/or URI of the corresponding Source Code on the same terms and conditions as the license granted to You under this License. - d. If the Work is used as a Web Service, each time You Distribute + d. If the Work is used as a Network Service, each time You Distribute or Publicly Perform an Adaptation, or serve data derived from the Software, the Licensor offers to any recipients of the data a copy and/or URI of the corresponding Source Code on the same terms and diff --git a/README.md b/README.md index 722c610..22a77fd 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,32 @@ # IzzyLib -These are just a number of functions I keep reusing over and over again in most of my projects +These are just a number of functions I keep reusing over and over again in most of my projects. It's okay to use them if you also find them useful -Note: not in a stable state yet. Expect major changes +## Installation + +You only need to install the base and whatever sub-modules you want to use + +### From Git +$(venv)/bin/python -m pip install -e git+https://git.barkshark.xyz/izaliamae/izzylib.git#egg=izzylib-base&subdirectory=base +$(venv)/bin/python -m pip install -e git+https://git.barkshark.xyz/izaliamae/izzylib.git#egg=izzylib-http-server&subdirectory=http_server +$(venv)/bin/python -m pip install -e git+https://git.barkshark.xyz/izaliamae/izzylib.git#egg=izzylib-http-requests-client&subdirectory=requests_client +$(venv)/bin/python -m pip install -e git+https://git.barkshark.xyz/izaliamae/izzylib.git#egg=izzylib-sql&subdirectory=sql +$(venv)/bin/python -m pip install -e git+https://git.barkshark.xyz/izaliamae/izzylib.git#egg=izzylib-templates&subdirectory=template +$(venv)/bin/python -m pip install -e git+https://git.barkshark.xyz/izaliamae/izzylib.git#egg=izzylib-tinydb&subdirectory=tinydb + +### From Source + +$(venv)/bin/python -m pip install ./base ./http_server ./requests_client ./sql ./template ./tinydb + +## Documentation + +### Importing + +Most useful classes and functions are imported in the module root, so you don't need to do any multi-level imports. For example, just do `from izzylib import SqlDatabase` instead of `from izzylib.sql.generic import SqlDatabase`. Or even simply do `import izzylib` and use `izzylib.SqlDatabase()`. + +### Usage + +All classes and functions will have docstrings. Either look through the code or run `help()` on an object + +# NOTE! +not in a stable state yet. Expect major changes diff --git a/base/izzylib/__init__.py b/base/izzylib/__init__.py new file mode 100644 index 0000000..6772c29 --- /dev/null +++ b/base/izzylib/__init__.py @@ -0,0 +1,56 @@ +''' +IzzyLib by Zoey Mae +Licensed under the CNPL: https://git.pixie.town/thufie/CNPL +https://git.barkshark.xyz/izaliamae/izzylib +''' + +import sys, traceback +assert sys.version_info >= (3, 7) + +__version_tpl__ = (0, 6, 0) +__version__ = '.'.join([str(v) for v in __version_tpl__]) + +from . import logging + +izzylog = logging.get_logger('IzzyLib') + +from .dotdict import DotDict, LowerDotDict, DefaultDotDict, JsonEncoder +from .misc import * +from .cache import LruCache, TtlCache +from .connection import Connection +from .path import Path + +from .http_urllib_client import HttpUrllibClient, HttpUrllibResponse + + +def log_import_error(*message): + izzylog.verbose(*message) + + if izzylog.get_config('level') == logging.Levels.DEBUG: + traceback.print_exc() + + +try: + from izzylib.sql import Column, CustomRows, Session, SqlDatabase, Tables, SqliteClient, SqliteColumn, SqliteServer, SqliteSession +except ImportError: + log_import_error('Failed to import SQL classes. Connecting to SQL databases is disabled') + +try: + from izzylib.tinydb import TinyDatabase, TinyRow, TinyRows +except ImportError: + log_import_error('Failed to import TinyDB classes. TinyDB database is disabled') + +try: + from izzylib.template import Template, Color +except ImportError: + log_import_error('Failed to import http template classes. Jinja and HAML templates disabled') + +try: + from izzylib.http_requests_client import HttpRequestsClient, HttpRequestsRequest, HttpRequestsResponse +except ImportError: + log_import_error('Failed to import Requests http client classes. Requests http client is disabled.') + +try: + from izzylib.http_server import PasswordHasher, HttpServer, HttpServerRequest, HttpServerResponse +except ImportError: + log_import_error('Failed to import HTTP server classes. The HTTP server will be disabled') diff --git a/IzzyLib/cache.py b/base/izzylib/cache.py similarity index 96% rename from IzzyLib/cache.py rename to base/izzylib/cache.py index 3e063a5..646434a 100644 --- a/IzzyLib/cache.py +++ b/base/izzylib/cache.py @@ -5,7 +5,7 @@ import re from datetime import datetime from collections import OrderedDict -from .misc import DotDict +from . import DotDict def parse_ttl(ttl): @@ -113,11 +113,11 @@ class BaseCache(OrderedDict): return self[key].data -class TTLCache(BaseCache): +class TtlCache(BaseCache): def __init__(self, maxsize=1024, ttl='1h'): super().__init__(maxsize, ttl) -class LRUCache(BaseCache): +class LruCache(BaseCache): def __init__(self, maxsize=1024): super().__init__(maxsize) diff --git a/base/izzylib/connection.py b/base/izzylib/connection.py new file mode 100644 index 0000000..85fd0c4 --- /dev/null +++ b/base/izzylib/connection.py @@ -0,0 +1,25 @@ +import socket + + +class Connection(socket.socket): + def __init__(self, address='127.0.0.1', port=8080, tcp=True): + super().__init__(socket.AF_INET, socket.SOCK_STREAM if tcp else socket.SOCK_DGRAM) + self.address = address + self.port = port + + + def __enter__(self): + self.connect((self.address, self.port)) + return self + + + def __exit__(self, exctype, value, tb): + self.close() + + + def send(self, msg): + self.sendall(msg) + + + def recieve(self, size=8192): + return self.recv(size) diff --git a/base/izzylib/dotdict.py b/base/izzylib/dotdict.py new file mode 100644 index 0000000..455f3a7 --- /dev/null +++ b/base/izzylib/dotdict.py @@ -0,0 +1,115 @@ +import json + + +class DotDict(dict): + dict_ignore_types = ['basecache', 'lrucache', 'ttlcache'] + + + def __init__(self, value=None, **kwargs): + '''Python dictionary, but variables can be set/get via attributes + + value [str, bytes, dict]: JSON or dict of values to init with + kwargs: key/value pairs to set on init. Overrides identical keys set by 'value' + ''' + + super().__init__() + self.__setattr__ = self.__setitem__ + + ## compatibility + self.toJson = self.to_json + self.fromJson = self.from_json + + if isinstance(value, (str, bytes)): + self.from_json(value) + + elif value.__class__.__name__.lower() not in self.dict_ignore_types and isinstance(value, dict): + self.update(value) + + elif value: + raise TypeError(f'The value must be a JSON string, list, dict, or another DotDict object, not {value.__class__}') + + if kwargs: + self.update(kwargs) + + + def __getattr__(self, k): + try: + return super().__getitem__(k) + + except KeyError: + raise AttributeError(f'{self.__class__.__name__} object has no attribute {k}') from None + + + def __setitem__(self, k, v): + if v.__class__.__name__.lower() not in self.dict_ignore_types and isinstance(v, dict): + v = DotDict(v) + + super().__setitem__(k, v) + + + def __delattr__(self, k): + try: + dict.__delitem__(self, k) + except KeyError: + raise AttributeError(f'{self.__class__.__name__} object has no attribute {k}') from None + + + def update(self, data): + for k,v in data.items(): + self.__setitem__(k, v) + + + def to_json(self, indent=None, **kwargs): + if 'cls' not in kwargs: + kwargs['cls'] = JsonEncoder + + return json.dumps(dict(self), indent=indent, **kwargs) + + + def from_json(self, string): + data = json.loads(string) + self.update(data) + + + def load_json(self, path: str=None): + self.update(Path(path).load_json()) + + + def save_json(self, path: str, **kwargs): + with Path(path).open(w) as fd: + write(self.toJson(*kwargs)) + + +## This has to be reworked tbh +class DefaultDotDict(DotDict): + def __getattr__(self, key): + try: + val = super().__getattribute__(key) + + except AttributeError: + val = self.get(key, DefaultDict()) + + return DotDict(val) if type(val) == dict else val + + +class LowerDotDict(DotDict): + def __getattr__(self, key): + return super().__getattr__(self, key.lower()) + + + def __setattr__(self, key, value): + return super().__setattr__(key.lower(), value) + + + def update(self, data): + data = {k.lower(): v for k,v in self.items()} + + return super().update(data) + + +class JsonEncoder(json.JSONEncoder): + def default(self, obj): + if not any(map(isinstance, [obj], [str, int, float, dict])): + return str(obj) + + return json.JSONEncoder.default(self, obj) diff --git a/base/izzylib/exceptions.py b/base/izzylib/exceptions.py new file mode 100644 index 0000000..b097f1d --- /dev/null +++ b/base/izzylib/exceptions.py @@ -0,0 +1,2 @@ +class HttpFileDownloadedError(Exception): + 'raise when a download failed for any reason' diff --git a/base/izzylib/http_urllib_client.py b/base/izzylib/http_urllib_client.py new file mode 100644 index 0000000..fc71193 --- /dev/null +++ b/base/izzylib/http_urllib_client.py @@ -0,0 +1,163 @@ +import functools, json, sys + + +from base64 import b64decode, b64encode +from datetime import datetime +from functools import cached_property +from io import BytesIO +from ssl import SSLCertVerificationError +from urllib.error import HTTPError +from urllib.parse import urlparse +from urllib.request import Request, urlopen + +from . import DefaultDotDict, DotDict, Path, exceptions, izzylog, __version__ + +try: + from PIL import Image +except ImportError: + izzylog.verbose('Pillow module not found. Image downloading is disabled') + Image = False + + +methods = ['connect', 'delete', 'get', 'head', 'options', 'patch', 'post', 'put', 'trace'] + + +class HttpUrllibClient: + def __init__(self, headers={}, useragent=f'IzzyLib/{__version__}', appagent=None, proxy_type='https', proxy_host=None, proxy_port=None): + proxy_ports = { + 'http': 80, + 'https': 443 + } + + if proxy_type not in ['http', 'https']: + raise ValueError(f'Not a valid proxy type: {proxy_type}') + + self.headers=headers + self.agent = f'{useragent} ({appagent})' if appagent else useragent + self.proxy = DotDict({ + 'enabled': True if proxy_host else False, + 'ptype': proxy_type, + 'host': proxy_host, + 'port': proxy_ports[proxy_type] if not proxy_port else proxy_port + }) + + + def __build_request(self, url, data=None, headers={}, method='GET'): + new_headers = self.headers.copy() + new_headers.update(headers) + + parsed_headers = {k.lower(): v for k,v in new_headers.items()} + + if not parsed_headers.get('user-agent'): + parsed_headers['user-agent'] = self.agent + + if isinstance(data, dict): + data = json.dumps(data) + + if isinstance(data, str): + data = data.encode('UTF-8') + + request = Request(url, data=data, headers=parsed_headers, method=method) + + if self.proxy.enabled: + request.set_proxy(f'{self.proxy.host}:{self.proxy.port}', self.proxy.ptype) + + return request + + + def request(self, *args, **kwargs): + request = self.__build_request(*args, **kwargs) + + try: + response = urlopen(request) + + except HTTPError as e: + response = e.fp + + return HttpUrllibResponse(response) + + + def file(self, url, filepath, *args, filename=None, size=2048, create_dirs=True, **kwargs): + filepath = Path(filepath) + path = filepath.parent + + if not path.exists() and not create_dirs: + raise FileNotFoundError(f'Path does not exist: {path}') + + path.mkdir() + + if filepath.exists(): + kwargs['headers']['range'] = f'bytes={filepath.size}' + + resp = self.request(url, *args, stream=True, **kwargs) + + if not resp.headers.get('content-length'): + raise exceptions.HttpFileDownloadedError('File already downloaded fully') + + if resp.status != 200: + raise exceptions.HttpFileDownloadedError(f'Failed to download {url}: {resp.status}, body: {resp.body}') + + with filepath.open('ab') as fd: + for chunk in resp.chunks(size): + fd.write(chunk) + + return True + + + def image(self, url, filepath, *args, filename=None, ext='png', dimensions=(50, 50), create_dirs=True, **kwargs): + if not Image: + raise ValueError('Pillow module is not installed') + + filepath = Path(filepath) + path = filepath.parent + + if not path.exists() and not create_dirs: + raise FileNotFoundError(f'Path does not exist: {path}') + + path.mkdir() + + resp = self.request(url, *args, **kwargs) + + if resp.status != 200: + raise exceptions.HttpFileDownloadedError(f'Failed to download {url}: {resp.status}, body: {resp.body}') + + if not filename: + filename = Path(url).stem() + + byte = BytesIO() + image = Image.open(BytesIO(resp.body)) + image.thumbnail(dimensions) + image.save(byte, format=ext.upper()) + + with path.join(filename).open('wb') as fd: + fd.write(byte.getvalue()) + + + def json(self, *args, headers={}, activity=True, **kwargs): + json_type = 'activity+json' if activity else 'json' + headers.update({ + 'accept': f'application/{json_type}' + }) + return self.request(*args, headers=headers, **kwargs) + + +class HttpUrllibResponse(object): + def __init__(self, response): + self.body = response.read() + self.headers = DefaultDotDict({k.lower(): v.lower() for k,v in response.headers.items()}) + self.status = response.status + self.url = response.url + + + @cached_property + def text(self): + return self.body.decode('UTF-8') + + + @cached_property + def json(self): + return DotDict(self.text) + + + def json_pretty(self, indent=4): + return json.dumps(self.json, indent=indent) diff --git a/base/izzylib/logging.py b/base/izzylib/logging.py new file mode 100644 index 0000000..4dba74e --- /dev/null +++ b/base/izzylib/logging.py @@ -0,0 +1,129 @@ +import sys + +from os import getppid, environ as env +from datetime import datetime +from enum import Enum + + +class Levels(Enum): + CRITICAL = 60, + ERROR = 50 + WARNING = 40 + INFO = 30 + VERBOSE = 20 + DEBUG = 10 + MERP = 0 + + +class Log: + __slots__ = [ + 'name', 'level', 'date', 'format', + 'critical', 'error', 'warning', + 'info', 'verbose', 'debug', 'merp' + ] + + def __init__(self, name, **config): + self.name = name + self.level = Levels.INFO + self.date = True + self.format = '%Y-%m-%d %H:%M:%S' + self.update_config(**config) + + for level in Levels: + self._set_log_function(level) + + + def _set_log_function(self, level): + setattr(self, level.name.lower(), lambda *args: self.log(level, *args)) + + + def print(self, *args): + sys.stdout.write(' '.join([str(arg) for arg in args])) + sys.stdout.flush() + + + def parse_level(self, level): + try: + return Levels(int(level)) + except ValueError: + return getattr(Levels, level.upper()) + + + def update_config(self, **data): + for key, value in data.items(): + self.set_config(key, value) + + + def set_config(self, key, value): + if key == 'level' and type(value) == str: + value = self.parse_level(value) + + setattr(self, key, value) + + + def get_config(self, key): + return getattr(self, key) + + + def print_config(self): + self.print(*(f'{k}: {v}\n' for k,v in self.items())) + + + def log(self, level, *msg): + if level.value < self.level.value: + return + + default = self.name == 'Default' + options = [ + level.name + ':', + ' '.join([str(message) for message in msg]), + '\n' + ] + + if self.date and not getppid() == 1: + options.insert(0, datetime.now().strftime(self.format)) + + if not default: + options.insert(0 if not self.date else 1, f'[{self.name}]') + + self.print(*options) + + +def get_logger(name, **config): + try: + return logger[name.lower()] + + except KeyError: + log = Log(name, **config) + logger[name.lower()] = log + return log + + +'''create a default logger''' +logger = { + 'default': Log('Default') + 'IzzyLib': Log('IzzyLib') +} + +DefaultLog = logger['default'] + +'''aliases for default logger's log output functions''' +critical = DefaultLog.critical +error = DefaultLog.error +warning = DefaultLog.warning +info = DefaultLog.info +verbose = DefaultLog.verbose +debug = DefaultLog.debug +merp = DefaultLog.merp + +'''aliases for the default logger's config functions''' +update_config = DefaultLog.update_config +set_config = DefaultLog.set_config +get_config = DefaultLog.get_config +print_config = DefaultLog.print_config + + +try: + logger['IzzyLib'].set_config('level', env['LOG_LEVEL']) +except KeyError: + 'heck' diff --git a/base/izzylib/misc.py b/base/izzylib/misc.py new file mode 100644 index 0000000..a567dd1 --- /dev/null +++ b/base/izzylib/misc.py @@ -0,0 +1,411 @@ +'''Miscellaneous functions''' +import hashlib, random, string, statistics, socket, time, timeit + +from datetime import datetime +from getpass import getpass +from importlib import util +from pathlib import Path + +from . import izzylog + + +__all__ = [ + 'ap_date', + 'boolean', + 'get_ip', + 'hasher', + 'import_from_path', + 'nfs_check', + 'port_check', + 'print_methods', + 'prompt', + 'random_gen', + 'time_function', + 'time_function_pprint', + 'timestamp', + 'var_name' +] + + +def ap_date(date=None, alt=False): + ''' + Takes a datetime object and returns it as an ActivityPub-friendly string + + Arguments: + date (datetime): The datetime object to be converted. It not set, will create a new datetime object with the current date and time + alt (bool): If True, the returned string will be in the Mastodon API format + + Return: + str: The date in an ActivityPub-friendly format + ''' + + if not date: + date = datetime.utcnow() + + elif type(date) == int: + date = datetime.fromtimestamp(date) + + elif type(date) != datetime: + raise TypeError(f'Unsupported object type for ApDate: {type(date)}') + + return date.strftime('%a, %d %b %Y %H:%M:%S GMT' if alt else '%Y-%m-%dT%H:%M:%SZ') + + +def boolean(v, return_value=False): + ''' + Convert a str, bool, int or None object into a boolean. + + Arguments: + v (str, bool, int, None): The value to be checked + return_value (bool): If True, return v instead of True if it can't be converted + + Return: + various: A boolean or the value itself + + ''' + + if type(v) not in [str, bool, int, type(None)]: + raise ValueError(f'Value is not a string, boolean, int, or nonetype: {value}') + + value = v.lower() if isinstance(v, str) else v + + if value in [1, True, 'on', 'y', 'yes', 'true', 'enable']: + return True + + if value in [0, False, None, 'off', 'n', 'no', 'false', 'disable', '']: + return False + + if return_value: + return v + + return True + + +def catch_kb_interrupt(function, *args, **kwargs): + ''' + Run a function and catch the KeyboardInterrupt exception + + Parameters: + function (function): The function to be ran + *args, **kwargs: The arguments and keyword arguments to pass to the function + + Return: + None + ''' + + try: + function(*args, **kwargs) + + except KeyboardInterrupt: + izzylog.verbose('Bye! UvU') + + +def get_ip(): + ''' + Get the IP address of the machine + + Return: + str: An IP address + ''' + + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + + try: + s.connect(('10.255.255.255', 1)) + data = s.getsockname() + ip = data[0] + + except Exception: + ip = '127.0.0.1' + + finally: + s.close() + + return ip + + +def hasher(string, alg='blake2s'): + ''' + Hash a string and return the digest in hex format as a string + + Arguments: + string (str, bytes): A string or bytes object to be hashed + alg (str): The name of algorithm to use for hashing. Check hashlib.__always_supported for valid hash algs + + Return: + str: The hashed string in hex format as a string + ''' + + if alg not in hashlib.__always_supported: + raise TypeError('Unsupported hash algorithm. Supported algs:', ', '.join(hashlib.__always_supported)) + + string = string.encode('UTF-8') if type(string) != bytes else string + + newhash = hashlib.new(alg) + newhash.update(string) + return newhash.hexdigest() + + +def import_from_path(mod_path): + ''' + Import a module from a directory + + Arguments: + mod_path (str, Path): Py file or directory to import + + Return: + module: A module object + ''' + + mod_path = Path(mod_path) + + if mod_path.isdir(): + path = mod_path.join('__init__.py') + name = path.name + + else: + path = mod_path + name = path.name.replace('.py', '', -1) + + spec = util.spec_from_file_location(name, path.str()) + module = util.module_from_spec(spec) + spec.loader.exec_module(module) + return module + + +def nfs_check(path): + ''' + Check if a file or directory is on an NFS share. Only tested on Linux + + Arguments: + path (str, Path): Path to a file or directory + + Return: + bool: True if the path is on an nfs share. False if not + ''' + + if platform.system() == 'Windows': + izzylog.verbose('Refusing to check unix mounts on a non-unix system') + return + + proc = Path('/proc/mounts') + path = Path(path).resolve() + + 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(): + return True + + return False + + +def port_check(port, address='127.0.0.1', tcp=True): + ''' + Checks if a TCP or UDP port is open or not + + Arguments: + port (int): The port number to check + address (str): The address to connect to to check + tcp (bool): Use TCP if True, else use UDP + + Return: + bool: True if the port is in use. False if it is not + ''' + + with socket.socket(socket.AF_INET, socket.SOCK_STREAM if tcp else socket.SOCK_DGRAM) as s: + try: + return not s.connect_ex((address, port)) == 0 + + except socket.error as e: + return False + + +def print_methods(object, include_underscore=False): + ''' + Prints each method of an object on a new line + + Arguments: + object (object): The object to work with + include_underscore (bool): If True, also include methods that start with '_' + + Return: + None (The methods are printed to stdout) + ''' + + for line in dir(object): + if line.startswith('_') and include_underscore: + print(line) + + print(line) + + +def prompt(prompt, default=None, valtype=str, options=[], password=False): + '''An upgraded `input` + + Arguments: + prompt (str): The string to display to the user + default (various): The value that should be returned if there is no user input + valtype (str): The type the value should be returned as + options (list(str)): If set, these are the only values the user can select + password (bool): If set to True, the input will be treated like a password and not show the user's input on screen + + Return: + various: The value typed by the user (and converted if necessary) + ''' + + input_func = getpass if password else input + + if default != None: + prompt += ' [-redacted-]' if password else f' [{default}]' + + prompt += '\n' + + if options: + opt = '/'.join(options) + prompt += f'[{opt}]' + + prompt += ': ' + value = input_func(prompt) + + while value and len(options) > 0 and value not in options: + input_func('Invalid value:', value) + value = input(prompt) + + if not value or value == '': + return default + + ret = valtype(value) + + while valtype == Path and not ret.parent().exists(): + input_func('Parent directory doesn\'t exist') + ret = Path(input(prompt)) + + return ret + + +def random_gen(length=20, letters=True, numbers=True, extra=None): + '''Return a randomly generated string + + Arguments: + length (int): The length of the returned string + letters (bool): If True, include all upper and lowercase letters + numbers (bool): if True, include all numbers + extra (str): A string of any extra characters to include + + Return: + str: A random string of characters + ''' + + if not isinstance(length, int): + raise TypeError(f'Character length must be an integer, not {type(length)}') + + characters = '' + + if letters: + characters += string.ascii_letters + + if digits: + characters += string.digits + + if extra: + characters += extra + + return ''.join(random.choices(characters, k=length)) + + +def time_function(func, *args, passes=1, use_gc=True, **kwargs): + '''Run a function and return the time it took + + Arguments: + func (function): The command to be timed + args (list(various)): The arguments to be passed to the timed function + kwargs (dict(str:various)): The keyword arguments to be passed to the timed function + passes (int): How many times the timed function should be run + use_gc (bool): If True, keep garbage collection enabled + + Return: + int: The time it took to run the function in miliseconds + ''' + + options = [ + lambda: func(*args, **kwargs) + ] + + if use_gc: + options.append('gc.enable()') + + timer = timeit.Timer(*options) + + if passes > 1: + return timer.repeat(passes, 1) + + return timer.timeit(1) + + +def time_function_pprint(func, *args, passes=5, use_gc=True, floatlen=3, **kwargs): + '''Run a function and print out the time it took for each pass, the average and total + + Arguments: + func (function): The command to be timed + args (list(various)): The arguments to be passed to the timed function + kwargs (dict(str:various)): The keyword arguments to be passed to the timed function + passes (int): How many times the timed function should be run + use_gc (bool): If True, keep garbage collection enabled + floatlen (int): The amount of decimal places each result should have + + Return: + None: The data gets printed to stdout + ''' + + parse_time = lambda num: f'{round(num, floatlen)}s' + times = [] + + for idx in range(0, passes): + passtime = time_function(func, *args, **kwargs, passes=1, use_gc=use_gc) + times.append(passtime) + print(f'Pass {idx+1}: {parse_time(passtime)}') + + average = statistics.fmean(times) + + print('-----------------') + print(f'Average: {parse_time(average)}') + print(f'Total: {parse_time(sum(times))}') + + +def timestamp(dtobj=None, utc=False): + ''' + Turn a datetime object into a unix timestamp + + Arguments: + dtobj (datetime): The datetime object to be converted + utc (bool): If True, use UTC instead of local time for new objects + + Return: + int: The timestamp version of a datetime object + ''' + + dtime = dtobj if dtobj else datetime + date = dtime.utcnow() if utc else dtime.now() + + return date.timestamp() + + +def var_name(single=True, **kwargs): + ''' + Return a variable name as a string + + Agruments: + kwargs (dict(str:variable)): Variables and their values + single (bool): If True, only return the first variable name + + Return: + str or list(str): The variable name as a str (or names in a list if not Single) + ''' + + keys = list(kwargs.keys()) + return key[0] if single else keys diff --git a/base/izzylib/path.py b/base/izzylib/path.py new file mode 100644 index 0000000..1e53ce0 --- /dev/null +++ b/base/izzylib/path.py @@ -0,0 +1,170 @@ +import pathlib + +from . import DotDict, JsonEncoder + + +class Path(pathlib.Path): + def __init__(self, path, exist=True, missing=True, parents=True): + if str(path).startswith('~'): + path = pathlib.Path(path).expanduser() + + super().__init__(path) + + self.config = { + 'missing': missing, + 'parents': parents, + 'exist': exist + } + + + 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.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}') + + + def append(self, text): + return Path(str(self.__path) + text) + + + def backup(self, ext='backup', overwrite=False): + target = f'{self.parent}.{ext}' + self.copy(target, overwrite) + + + def chmod(self, mode=None): + octal = self.__parse_perm_octal(mode) + super().chmod(octal) + + + def copy(self, path, overwrite=False): + target = Path(path) + + self.__check_dir(path) + + if target.exists and overwrite: + target.delete + + copyfile(self, target) + + + def join(self, path): + return Path(self.joinpath(path)) + + + def json_load(self): + return DotDict(self.read()) + + + def json_save(self, data, indent=None): + with self.open('w') as fp: + fp.write(json.dumps(data, indent=indent, cls=JsonEncoder)) + + + def link(self, path): + target = Path(path) + + self.__check_dir(path) + + if target.exists(): + target.delete() + + self.symlink_to(path, target.isdir()) + + + def mkdir(self, mode=0o755): + self.__path.mkdir(mode, self.parents, self.exist) + + return True if self.__path.exists() else False + + + def move(self, path, overwrite=False): + self.copy(path, overwrite=overwrite) + self.delete() + + + def touch(self, mode=0o666): + octal = __parse_perm_octal(mode) + self.__path.touch(octal, self.exist) + + return self.exists() + + + @property + def delete(self): + if self.isdir(): + rmtree(self) + + else: + self.unlink() + + return not self.exists + + + @property + def exists(self): + return super().exists() + + + @property + def home(self): + return Path(pathlib.Path.home()) + + + @property + def isdir(self): + return self.is_dir() + + + @property + def isfile(self): + return self.is_file() + + + @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] + + + @property + def mtime(self): + return os.path.getmtime(self.str()) + + + @property + def parent(self): + return Path(super().parent) + + + @property + def read(self): + return self.open().read() + + + @property + def readlines(self): + return self.open().readlines() + + + @property + def resolve(self): + return Path(super().resolve()) + + + @property + def size(self): + return self.stat().st_size diff --git a/base/setup.py b/base/setup.py new file mode 100755 index 0000000..221dda8 --- /dev/null +++ b/base/setup.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 +from setuptools import setup + + +setup( + name="IzzyLib Base", + version='0.6.0', + packages=['izzylib'], + python_requires='>=3.7.0', + include_package_data=False, + author='Zoey Mae', + author_email='admin@barkshark.xyz', + description='a collection of often-used functions and classes', + keywords='web http client', + url='https://git.barkshark.xyz/izaliamae/izzylib', + project_urls={ + 'Bug Tracker': 'https://git.barkshark.xyz/izaliamae/izzylib/issues', + 'Documentation': 'https://git.barkshark.xyz/izaliamae/izzylib/wiki', + 'Source Code': 'https://git.barkshark.xyz/izaliamae/izzylib' + }, + + classifiers=[ + 'License :: Co-operative Non-violent Public License (CNPL 6+)', + 'Development Status :: 3 - Alpha', + 'Intended Audience :: Information Technology', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', + 'Operating System :: POSIX', + 'Operating System :: MacOS :: MacOS X', + 'Operating System :: Microsoft :: Windows', + 'Topic :: Internet :: WWW/HTTP', + 'Topic :: Software Development :: Libraries', + 'Topic :: Software Development :: Libraries :: Python Modules' + ] +) diff --git a/http_server/izzylib/http_server/__init__.py b/http_server/izzylib/http_server/__init__.py new file mode 100644 index 0000000..a501f67 --- /dev/null +++ b/http_server/izzylib/http_server/__init__.py @@ -0,0 +1,2 @@ +from .hasher import PasswordHasher +from .server import HttpServer, HttpServerRequest, HttpServerResponse diff --git a/http_server/izzylib/http_server/hasher.py b/http_server/izzylib/http_server/hasher.py new file mode 100644 index 0000000..921af17 --- /dev/null +++ b/http_server/izzylib/http_server/hasher.py @@ -0,0 +1,78 @@ +import argon2, os + +from izzylib import time_function_pprint + + +class PasswordHasher: + ''' + Argon2 password hasher and validator + + Attributes: + config (dict): The settings used for the hasher + + Methods: + get_config(key): Get the value of a config options + set_config(key, value): Set a config option + hash(password): hash a password and return the digest as a hex string + verify(hash, password): verify a password and the password hash match + iteration_test(string, passes, iterations): Time the hashing functionality + ''' + + aliases = { + 'iterations': 'time_cost', + 'memory': 'memory_cost', + 'threads': 'parallelism' + } + + + def __init__(self, iterations=16, memory=100, threads=os.cpu_count(), type=argon2.Type.ID): + if not argon2: + raise ValueError('password hashing disabled') + + self.config = { + 'time_cost': iterations, + 'memory_cost': memory * 1024, + 'parallelism': threads, + 'encoding': 'utf-8', + 'type': algtype, + } + + self.hasher = argon2.PasswordHasher(**self.config) + + + def get_config(self, key): + key = self.aliases.get(key, key) + + self[key] + return self.get(key) / 1024 if key == 'memory_cost' else self.get(key) + + + def set_config(self, key, value): + key = self.aliases.get(key, key) + self.config[key] = value * 1024 if key == 'memory_cost' else value + self.hasher = argon2.PasswordHasher(**self.config) + + + def hash(self, password: str): + return super().hash(password) + + + def verify(self, passhash: str, password: str): + try: + return self.hasher.verify(passhash, password) + + except argon2.exceptions.VerifyMismatchError: + return False + + + def iteration_test(self, string='hecking heck', passes=3, iterations=[8,16,24,32,40,48,56,64]): + original_iter = self.get_config('iterations') + + for iteration in iterations: + self.set_config('iterations', iteration) + print('\nTesting hash iterations:', iteration) + + time_function_pprint(self.verify, self.hash(string), string, passes=passes) + + self.set_config('iterations', original_iter) + diff --git a/IzzyLib/http_server.py b/http_server/izzylib/http_server/server.py similarity index 89% rename from IzzyLib/http_server.py rename to http_server/izzylib/http_server/server.py index 51baeb9..5e4ca53 100644 --- a/IzzyLib/http_server.py +++ b/http_server/izzylib/http_server/server.py @@ -1,3 +1,4 @@ +# probably gonna remove this since I'll be using my asgi framework import multiprocessing, sanic, signal, traceback import logging as pylog @@ -7,7 +8,7 @@ from multiprocessing import cpu_count, current_process from sanic.views import HTTPMethodView from urllib.parse import parse_qsl, urlparse -from . import http, logging +from . import http, izzylog from .misc import DotDict, DefaultDict, LowerDotDict from .template import Template @@ -32,7 +33,7 @@ class HttpServer(sanic.Sanic): self.workers = int(kwargs.get('workers', cpu_count())) self.sig_handler = kwargs.get('sig_handler') - super().__init__(name, request_class=kwargs.get('request_class', HttpRequest)) + super().__init__(name, request_class=kwargs.get('request_class', HttpServerRequest)) for log in ['sanic.root', 'sanic.access']: pylog.getLogger(log).setLevel(pylog.ERROR) @@ -85,7 +86,7 @@ class HttpServer(sanic.Sanic): if self.workers > 1: msg += f' with {self.workers} workers' - logging.info(msg) + izzylog.info(msg) self.run(**options) @@ -95,16 +96,16 @@ class HttpServer(sanic.Sanic): print('stopping.....') self.stop() - logging.info('Bye! :3') + izzylog.info('Bye! :3') sys.exit() -class HttpRequest(sanic.request.Request): +class HttpServerRequest(sanic.request.Request): def __init__(self, url_bytes, headers, version, method, transport, app): super().__init__(url_bytes, headers, version, method, transport, app) - self.Headers = Headers(headers) - self.Data = Data(self) + self.Headers = HttpHeaders(headers) + self.Data = HttpData(self) self.template = self.app.template self.__setup_defaults() self.__parse_path() @@ -178,7 +179,34 @@ class HttpRequest(sanic.request.Request): return False -class Headers(LowerDotDict): +class HttpServerResponse: + Text = sanic.response.text + Html = sanic.response.html + Json = sanic.response.json + Redir = sanic.response.redirect + + + def Css(*args, headers={}, **kwargs): + ReplaceHeader(headers, 'content-type', 'text/css') + return sanic.response.text(*args, headers=headers, **kwargs) + + + def Js(*args, headers={}, **kwargs): + ReplaceHeader(headers, 'content-type', 'application/javascript') + return sanic.response.text(*args, headers=headers, **kwargs) + + + def Ap(*args, headers={}, **kwargs): + ReplaceHeader(headers, 'content-type', 'application/activity+json') + return sanic.response.json(*args, headers=headers, **kwargs) + + + def Jrd(*args, headers={}, **kwargs): + ReplaceHeader(headers, 'content-type', 'application/jrd+json') + return sanic.response.json(*args, headers=headers, **kwargs) + + +class HttpHeaders(LowerDotDict): def __init__(self, headers): super().__init__() @@ -202,7 +230,7 @@ class Headers(LowerDotDict): return self.get(key.lower(), default) -class Data(object): +class HttpData(object): def __init__(self, request): self.request = request @@ -235,8 +263,8 @@ class Data(object): try: return self.request.body except Exception as e: - logging.verbose('IzzyLib.http_server.Data.raw: failed to get body') - logging.debug(f'{e.__class__.__name__}: {e}') + izzylog.verbose('IzzyLib.http_server.Data.raw: failed to get body') + izzylog.debug(f'{e.__class__.__name__}: {e}') return b'' @@ -245,8 +273,8 @@ class Data(object): try: return self.raw.decode() except Exception as e: - logging.verbose('IzzyLib.http_server.Data.text: failed to get body') - logging.debug(f'{e.__class__.__name__}: {e}') + izzylog.verbose('IzzyLib.http_server.Data.text: failed to get body') + izzylog.debug(f'{e.__class__.__name__}: {e}') return '' @@ -255,8 +283,8 @@ class Data(object): try: return DotDict(self.text) except Exception as e: - logging.verbose('IzzyLib.http_server.Data.json: failed to get body') - logging.debug(f'{e.__class__.__name__}: {e}') + izzylog.verbose('IzzyLib.http_server.Data.json: failed to get body') + izzylog.debug(f'{e.__class__.__name__}: {e}') data = '{}' return {} @@ -268,7 +296,7 @@ async def MiddlewareAccessLog(request, response): uagent = request.headers.get('user-agent') address = request.headers.get('x-real-ip', request.forwarded.get('for', request.remote_addr)) - logging.info(f'({multiprocessing.current_process().name}) {address} {request.method} {request.path} {response.status} "{uagent}"') + izzylog.info(f'({multiprocessing.current_process().name}) {address} {request.method} {request.path} {response.status} "{uagent}"') def GenericError(request, exception): @@ -293,7 +321,7 @@ def GenericError(request, exception): def NoTemplateError(request, exception): - logging.error('TEMPLATE_ERROR:', f'{exception.__class__.__name__}: {str(exception)}') + izzylog.error('TEMPLATE_ERROR:', f'{exception.__class__.__name__}: {str(exception)}') return sanic.response.html('I\'m a dumbass and forgot to create a template for this page', 500) @@ -301,33 +329,3 @@ def ReplaceHeader(headers, key, value): for k,v in headers.items(): if k.lower() == header.lower(): del headers[k] - - -class Response: - Text = sanic.response.text - Html = sanic.response.html - Json = sanic.response.json - Redir = sanic.response.redirect - - - def Css(*args, headers={}, **kwargs): - ReplaceHeader(headers, 'content-type', 'text/css') - return sanic.response.text(*args, headers=headers, **kwargs) - - - def Js(*args, headers={}, **kwargs): - ReplaceHeader(headers, 'content-type', 'application/javascript') - return sanic.response.text(*args, headers=headers, **kwargs) - - - def Ap(*args, headers={}, **kwargs): - ReplaceHeader(headers, 'content-type', 'application/activity+json') - return sanic.response.json(*args, headers=headers, **kwargs) - - - def Jrd(*args, headers={}, **kwargs): - ReplaceHeader(headers, 'content-type', 'application/jrd+json') - return sanic.response.json(*args, headers=headers, **kwargs) - - -Resp = Response diff --git a/http_server/setup.py b/http_server/setup.py new file mode 100644 index 0000000..5b5ea40 --- /dev/null +++ b/http_server/setup.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python3 +from setuptools import setup, find_namespace_packages + + +requires = [ + 'argon2-cffi==20.1.0', + 'colour==0.1.5', + 'Hamlish-Jinja==0.3.3', + 'Jinja2==2.11.2', + 'Markdown==3.3.3', + 'pillow==8.2.0', + 'pycryptodome==3.9.9', + 'requests==2.25.1', + 'sanic==20.12.1', + 'Sanic-Cors==0.10.0.post3' +] + + +setup( + name="IzzyLib HTTP Server", + version='0.6.0', + packages=['izzylib.http_server'], + python_requires='>=3.7.0', + install_requires=requires, + include_package_data=False, + author='Zoey Mae', + author_email='admin@barkshark.xyz', + description='a collection of often-used functions and classes', + keywords='web http server templates argon2 jinja haml', + url='https://git.barkshark.xyz/izaliamae/izzylib', + project_urls={ + 'Bug Tracker': 'https://git.barkshark.xyz/izaliamae/izzylib/issues', + 'Documentation': 'https://git.barkshark.xyz/izaliamae/izzylib/wiki', + 'Source Code': 'https://git.barkshark.xyz/izaliamae/izzylib' + }, + + classifiers=[ + 'Development Status :: 3 - Alpha', + 'Intended Audience :: Information Technology', + 'License :: Co-operative Non-violent Public License (CNPL 6+)', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', + 'Operating System :: POSIX', + 'Operating System :: MacOS :: MacOS X', + 'Operating System :: Microsoft :: Windows', + 'Topic :: Internet :: WWW/HTTP', + 'Topic :: Internet :: WWW/HTTP :: Dynamic Content', + 'Topic :: Internet :: WWW/HTTP :: HTTP Servers', + 'Topic :: Software Development :: Libraries', + 'Topic :: Software Development :: Libraries :: Python Modules' + ] +) diff --git a/requests_client/izzylib/http_requests_client/__init__.py b/requests_client/izzylib/http_requests_client/__init__.py new file mode 100644 index 0000000..4ce85d2 --- /dev/null +++ b/requests_client/izzylib/http_requests_client/__init__.py @@ -0,0 +1,393 @@ +import json, requests, sys + +from Crypto.Hash import SHA256 +from Crypto.PublicKey import RSA +from Crypto.Signature import PKCS1_v1_5 +from PIL import Image + +from base64 import b64decode, b64encode +from datetime import datetime +from functools import cached_property, lru_cache +from io import BytesIO +from izzylib import DefaultDotDict, DotDict, Path, izzylog, __version__ +from ssl import SSLCertVerificationError +from urllib.error import HTTPError +from urllib.parse import urlparse +from urllib.request import Request, urlopen + + +methods = ['connect', 'delete', 'get', 'head', 'options', 'patch', 'post', 'put', 'trace'] + + +class RequestsClient(object): + def __init__(self, headers={}, useragent=f'IzzyLib/{__version__}', appagent=None, proxy_type='https', proxy_host=None, proxy_port=None): + proxy_ports = { + 'http': 80, + 'https': 443 + } + + if proxy_type not in ['http', 'https']: + raise ValueError(f'Not a valid proxy type: {proxy_type}') + + self.headers=headers + self.agent = f'{useragent} ({appagent})' if appagent else useragent + self.proxy = DotDict({ + 'enabled': True if proxy_host else False, + 'ptype': proxy_type, + 'host': proxy_host, + 'port': proxy_ports[proxy_type] if not proxy_port else proxy_port + }) + + self.SetGlobal = SetClient + + + def __sign_request(self, request, privkey, keyid): + if not crypto_enabled: + izzylog.error('Crypto functions disabled') + return + + request.add_header('(request-target)', f'{request.method.lower()} {request.path}') + request.add_header('host', request.host) + request.add_header('date', datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT')) + + if request.body: + body_hash = b64encode(SHA256.new(request.body).digest()).decode("UTF-8") + request.add_header('digest', f'SHA-256={body_hash}') + request.add_header('content-length', len(request.body)) + + sig = { + 'keyId': keyid, + 'algorithm': 'rsa-sha256', + 'headers': ' '.join([k.lower() for k in request.headers.keys()]), + 'signature': b64encode(PkcsHeaders(privkey, request.headers)).decode('UTF-8') + } + + sig_items = [f'{k}="{v}"' for k,v in sig.items()] + sig_string = ','.join(sig_items) + + request.add_header('signature', sig_string) + + request.remove_header('(request-target)') + request.remove_header('host') + + + def request(self, *args, method='get', **kwargs): + if method.lower() not in methods: + raise ValueError(f'Invalid method: {method}') + + request = RequestsRequest(self, *args, method=method.lower(), **kwargs) + return RequestsResponse(request.send()) + + + def file(self, url, filepath, *args, filename=None, **kwargs): + resp = self.request(url, *args, **kwargs) + + if resp.status != 200: + izzylog.error(f'Failed to download {url}:', resp.status, resp.body) + return False + + return resp.save(filepath) + + + def image(self, url, filepath, *args, filename=None, ext='png', dimensions=(50, 50), **kwargs): + if not Image: + izzylog.error('Pillow module is not installed') + return + + resp = self.request(url, *args, **kwargs) + + if resp.status != 200: + izzylog.error(f'Failed to download {url}:', resp.status, resp.body) + return False + + if not filename: + filename = Path(url).stem() + + path = Path(filepath) + + if not path.exists(): + izzylog.error('Path does not exist:', path) + return False + + byte = BytesIO() + image = Image.open(BytesIO(resp.body)) + image.thumbnail(dimensions) + image.save(byte, format=ext.upper()) + + with path.join(filename).open('wb') as fd: + fd.write(byte.getvalue()) + + + def json(self, *args, headers={}, activity=True, **kwargs): + json_type = 'activity+json' if activity else 'json' + headers.update({ + 'accept': f'application/{json_type}' + }) + + return self.request(*args, headers=headers, **kwargs) + + + def signed_request(self, privkey, keyid, *args, **kwargs): + request = RequestsRequest(self, *args, **kwargs) + self.__sign_request(request, privkey, keyid) + return RequestsResponse(request.send()) + + +class RequestsRequest(object): + def __init__(self, client, url, data=None, headers={}, query={}, method='get'): + self.args = [url] + self.kwargs = {'params': query} + self.method = method.lower() + self.client = client + + new_headers = client.headers.copy() + new_headers.update(headers) + + parsed_headers = {k.lower(): v for k,v in new_headers.items()} + + if not parsed_headers.get('user-agent'): + parsed_headers['user-agent'] = client.agent + + self.kwargs['headers'] = new_headers + self.kwargs['data'] = data + + if client.proxy.enabled: + self.kwargs['proxies'] = {self.proxy.ptype: f'{self.proxy.ptype}://{self.proxy.host}:{self.proxy.port}'} + + + def send(self): + func = getattr(requests, self.method) + return func(*self.args, **self.kwargs) + + +class RequestsResponse(object): + def __init__(self, response): + self.response = response + self.data = b'' + self.headers = DefaultDict({k.lower(): v.lower() for k,v in response.headers.items()}) + self.status = response.status_code + self.url = response.url + + + def chunks(self, size=256): + return self.response.iter_content(chunk_size=256) + + + @property + def body(self): + for chunk in self.chunks(): + self.data += chunk + + return self.data + + + @cached_property + def text(self): + return self.data.decode(self.response.encoding) + + + @cached_property + def json(self): + return DotDict(self.text) + + + @cached_property + def json_pretty(self, indent=4): + return json.dumps(self.json, indent=indent) + + + def save(self, path, overwrite=True): + path = Path(path) + parent = path.parent() + + if not parent.exists(): + raise ValueError(f'Path does not exist: {parent}') + + if overwrite and path.exists(): + path.delete() + + with path.open('wb') as fd: + for chunk in self.chunks(): + fd.write(chunk) + + +def verify_request(request: SanicRequest, actor: dict): + '''Verify a header signature from a SimpleASGI request + + request: The request with the headers to verify + actor: A dictionary containing the activitypub actor and the link to the pubkey used for verification + ''' + + body = request.body if request.body else None + return verify_headers(request.headers, request.method, request.path, body, actor) + + +def verify_headers(headers: dict, method: str, path: str, actor: dict=None, body=None): + '''Verify a header signature + + headers: A dictionary containing all the headers from a request + method: The HTTP method of the request + path: The path of the HTTP request + actor (optional): A dictionary containing the activitypub actor and the link to the pubkey used for verification + body (optional): The body of the request. Only needed if the signature includes the digest header + fail (optional): If set to True, raise an error instead of returning False if any step of the process fails + ''' + + headers = {k.lower(): v for k,v in headers.items()} + headers['(request-target)'] = f'{method.lower()} {path}' + signature = parse_signature(headers.get('signature')) + digest = parse_body_digest(headers.get('digest')) + missing_headers = [k for k in headers if k in ['date', 'host'] if headers.get(k) == None] + + if not signature: + raise ValueError('Missing signature') + + if not actor: + actor = fetch_actor(signature.keyid) + + ## Add digest header to missing headers list if it doesn't exist + if method.lower() == 'post' and not digest: + missing_headers.append('digest') + + ## Fail if missing date, host or digest (if POST) headers + if missing_headers: + raise KeyError(f'Missing headers: {missing_headers}') + + ## Fail if body verification fails + if digest and not VerifyString(body, digest.sig, digest.alg): + raise ValueError('Failed body digest verification') + + pubkey = actor.publicKey['publicKeyPem'] + + return PkcsHeaders(pubkey, {k:v for k,v in headers.items() if k in signature.headers}, sig=signature) + + +def parse_body_digest(digest): + if not digest: + raise ValueError('Empty digest') + + parsed = DotDict() + alg, sig = digest.split('=', 1) + + parsed.sig = sig + parsed.alg = alg.replace('-', '') + + return parsed + + +def verify_string(string, enc_string, alg='SHA256', fail=False): + if type(string) != bytes: + string = string.encode('UTF-8') + + body_hash = b64encode(SHA256.new(string).digest()).decode('UTF-8') + + if body_hash == enc_string: + return True + + if fail: + raise ValueError('String failed validation') + + else: + return False + + +def sign_pkcs_headers(key: str, headers: dict, sig=None): + if sig: + head_items = [f'{item}: {headers[item]}' for item in sig.headers] + + else: + head_items = [f'{k.lower()}: {v}' for k,v in headers.items()] + + head_string = '\n'.join(head_items) + head_bytes = head_string.encode('UTF-8') + + KEY = RSA.importKey(key) + pkcs = PKCS1_v1_5.new(KEY) + h = SHA256.new(head_bytes) + + if sig: + return pkcs.verify(h, b64decode(sig.signature)) + + else: + return pkcs.sign(h) + + +def parse_signature(signature: str): + if not signature: + raise ValueError('Missing signature header') + + split_sig = signature.split(',') + sig = DefaultDict({}) + + for part in split_sig: + key, value = part.split('=', 1) + sig[key.lower()] = value.replace('"', '') + + sig.headers = sig.headers.split() + + return sig + + +@lru_cache(maxsize=512) +def fetch_actor(url): + if not Client: + raise ValueError('Please set global client with "SetRequestsClient(client)"') + + url = url.split('#')[0] + headers = {'Accept': 'application/activity+json'} + resp = Client.request(url, headers=headers) + + try: + actor = resp.json() + + except Exception as e: + izzylog.debug(f'HTTP {resp.status}: {resp.body}') + raise e from None + + actor.web_domain = urlparse(url).netloc + actor.shared_inbox = actor.inbox + actor.pubkey = None + actor.handle = actor.preferredUsername + + if actor.get('endpoints'): + actor.shared_inbox = actor.endpoints.get('sharedInbox', actor.inbox) + + if actor.get('publicKey'): + actor.pubkey = actor.publicKey.get('publicKeyPem') + + return actor + + +@lru_cache(maxsize=512) +def fetch_webfinger_account(handle, domain): + if not Client: + izzylog.error('IzzyLib.http: Please set global client with "SetClient(client)"') + return {} + + data = DefaultDict() + webfinger = Client.request(f'https://{domain}/.well-known/webfinger?resource=acct:{handle}@{domain}') + + if not webfinger.body: + raise ValueError('Webfinger body empty') + + data.handle, data.domain = webfinger.json().subject.replace('acct:', '').split('@') + + for link in webfinger.json().links: + if link['rel'] == 'self' and link['type'] == 'application/activity+json': + data.actor = link['href'] + + return data + + +def set_requests_client(client=None): + global Client + Client = client or RequestsClient() + + +def generate_rsa_key(): + privkey = RSA.generate(2048) + + key = DotDict({'PRIVKEY': privkey, 'PUBKEY': privkey.publickey()}) + key.update({'privkey': key.PRIVKEY.export_key().decode(), 'pubkey': key.PUBKEY.export_key().decode()}) + + return key diff --git a/requests_client/setup.py b/requests_client/setup.py new file mode 100644 index 0000000..ddb7ad7 --- /dev/null +++ b/requests_client/setup.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python3 +from setuptools import setup, find_namespace_packages + + +requires = [ + 'pillow==8.2.0', + 'pycryptodome==3.9.9', + 'requests==2.25.1', +] + + +setup( + name="IzzyLib Requests Client", + version='0.6.0', + packages=['izzylib.http_requests_client'], + python_requires='>=3.7.0', + install_requires=requires, + include_package_data=False, + author='Zoey Mae', + author_email='admin@barkshark.xyz', + description='A Requests client with support for http header signing and verifying', + keywords='web http client', + url='https://git.barkshark.xyz/izaliamae/izzylib', + project_urls={ + 'Bug Tracker': 'https://git.barkshark.xyz/izaliamae/izzylib/issues', + 'Documentation': 'https://git.barkshark.xyz/izaliamae/izzylib/wiki', + 'Source Code': 'https://git.barkshark.xyz/izaliamae/izzylib' + }, + + classifiers=[ + 'Development Status :: 3 - Alpha', + 'Intended Audience :: Information Technology', + 'License :: Co-operative Non-violent Public License (CNPL 6+)', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', + 'Operating System :: POSIX', + 'Operating System :: MacOS :: MacOS X', + 'Operating System :: Microsoft :: Windows', + 'Topic :: Internet :: WWW/HTTP', + 'Topic :: Software Development :: Libraries', + 'Topic :: Software Development :: Libraries :: Python Modules' + ] +) diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index b486ed0..0000000 --- a/requirements.txt +++ /dev/null @@ -1,10 +0,0 @@ -colour>=0.1.5 -envbash>=1.2.0 -Hamlish-Jinja==0.3.3 -Jinja2>=2.10.1 -jinja2-markdown>=0.0.3 -Mastodon.py>=1.5.0 -pycryptodome>=3.9.1 -python-magic>=0.4.18 -sanic>=19.12.2 -watchdog>=0.8.3 diff --git a/setup.py b/setup.py old mode 100755 new mode 100644 index 24183ba..209d21f --- a/setup.py +++ b/setup.py @@ -1,40 +1,94 @@ -#!/usr/bin/env python3 -from setuptools import setup -import sys - -from IzzyLib import __version__ as v +import subprocess, sys -version = '.'.join([str(i) for i in v]) +submodules = [ + 'http_server', + 'requests_client', + 'sql', + 'template', + 'tinydb' +] + +submodule_names = [ + 'IzzyLib-Base', + 'IzzyLib-Database', + 'IzzyLib-HTTP-Server', + 'IzzyLib-Requests-Client', + 'IzzyLib-SQL', + 'IzzyLib-Templates', + 'IzzyLib-TinyDB', +] -setup( - name="IzzyLib", - version=version, - packages=['IzzyLib'], - python_requires='>=3.6.0', - install_requires=[req.replace('\n', '') for req in open('requirements.txt').readlines()], - include_package_data=False, - author='Zoey Mae', - author_email='admin@barkshark.xyz', - description='a collection of often-used functions and classes', - keywords='web http server database postgresql', - url='https://git.barkshark.xyz/izaliamae/izzylib', - project_urls={ - 'Bug Tracker': 'https://git.barkshark.xyz/izaliamae/izzylib/issues', - 'Documentation': 'https://git.barkshark.xyz/izaliamae/izzylib/wiki', - 'Source Code': 'https://git.barkshark.xyz/izaliamae/izzylib' - }, +def main(*args): + if not len(args): + print('Missing command') + return cmd_help() - classifiers=[ - 'Development Status :: 5 - Production/Stable', - 'Intended Audience :: Information Technology', - 'Programming Language :: Python :: 3.6', - 'Programming Language :: Python :: 3.7', - 'Programming Language :: Python :: 3.8', - 'Operating System :: POSIX', - 'Operating System :: MacOS :: MacOS X', - 'Operating System :: Microsoft :: Windows', - 'Topic :: Internet :: WWW/HTTP' - ] -) + command = args[0] + + if command not in ['install', 'uninstall', 'dev']: + print('Invalid command:', command) + return cmd_help() + + if command == 'uninstall': + subprocess.run([sys.executable, '-m', 'pip', 'uninstall', '-y', *submodule_names]) + return + + submodule_args = [] + + if len(args) > 1: + if args[1] == 'all': + submodule_args = [f'./{module}' for module in modinstall] + + else: + submodule_args = [f'./{module}' for module in args[1:]] + + for mod in submodules: + if mod not in submodules: + print('Invalid submodule:', mod) + return cmd_help() + + options = ['-m', 'pip', 'install', './base', *submodule_args] + + if command == 'dev': + options.insert(3, '--use-feature=in-tree-build') + + print(options) + + subprocess.run([sys.executable, *options]) + + +def cmd_help(*args): + text = f'''IzzyLib manager + +Commands: + install [submodules: space-separated list]: + Install IzzyLib as well as any sub-modules if any are required + + uninstall [submodules] + Uninstall IzzyLib and any installed submodules + +Valid Submodules: + {', '.join(submodules)} +''' + + print(text) + + +if __name__ == '__main__': + try: + args = sys.argv[1:] + + except IndexError: + args = [] + + try: + if not args: + cmd_help() + + else: + main(*args) + + except KeyboardInterrupt: + print('Bye! UvU') diff --git a/sql/izzylib/sql/__init__.py b/sql/izzylib/sql/__init__.py new file mode 100644 index 0000000..77d7732 --- /dev/null +++ b/sql/izzylib/sql/__init__.py @@ -0,0 +1,2 @@ +from .generic import Column, CustomRows, Session, SqlDatabase, Tables +from .sqlite_server import SqliteClient, SqliteColumn, SqliteServer, SqliteSession diff --git a/IzzyLib/database/sql.py b/sql/izzylib/sql/generic.py similarity index 93% rename from IzzyLib/database/sql.py rename to sql/izzylib/sql/generic.py index 4184c1a..c8dac85 100644 --- a/IzzyLib/database/sql.py +++ b/sql/izzylib/sql/generic.py @@ -7,9 +7,14 @@ from sqlalchemy import Column as SqlColumn, types as Types from sqlalchemy.exc import OperationalError, ProgrammingError from sqlalchemy.orm import scoped_session, sessionmaker -from .. import logging -from ..cache import LRUCache -from ..misc import DotDict, RandomGen, NfsCheck, PrintMethods, Path +from izzylib import ( + LruCache, + DotDict, + Path, + random_gen, + nfs_check, + izzylog +) SqlTypes = DotDict({t.lower(): getattr(Types, t) for t in dir(Types) if not t.startswith('_')}) @@ -36,13 +41,13 @@ class SqlDatabase: engine_kwargs = {} if not kwargs.get('database'): - raise MissingDatabaseError('Database not set') + raise KeyError('Database argument is not set') engine_string = dbtype + '://' if dbtype == 'sqlite': - if NfsCheck(kwargs.get('database')): - logging.error('Database file is on an NFS share which does not support locking. Any writes to the database will fail') + if nfs_check(kwargs.get('database')): + izzylog.error('Database file is on an NFS share which does not support locking. Any writes to the database will fail') engine_string += '/' + str(kwargs.get('database')) engine_kwargs['connect_args'] = {'check_same_thread': False} @@ -80,7 +85,7 @@ class SqlDatabase: def SetupCache(self): - self.cache = DotDict({table: LRUCache() for table in self.table_names}) + self.cache = DotDict({table: LruCache() for table in self.table_names}) def CreateTables(self, *tables): @@ -156,7 +161,7 @@ class Session(object): def open(self): - self.sessionid = RandomGen(10) + self.sessionid = random_gen(10) self.db.sessions[self.sessionid] = self @@ -271,13 +276,13 @@ class Session(object): column = getattr(table.c, col) except AttributeError: - logging.error(f'Table "{tbl}" does not have column "{col}"') + izzylog.error(f'Table "{tbl}" does not have column "{col}"') return columns = [row[1] for row in self.execute(f'PRAGMA table_info({tbl})')] if col in columns: - logging.info(f'Column "{col}" already exists') + izzylog.info(f'Column "{col}" already exists') return sql = f'ALTER TABLE {tbl} ADD COLUMN {col} {column.type}' @@ -300,7 +305,7 @@ class Session(object): columns = [row[1] for row in self.execute(f'PRAGMA table_info({tbl})')] if col not in columns: - logging.info(f'Column "{col}" already exists') + izzylog.info(f'Column "{col}" already exists') return columns.remove(col) @@ -430,7 +435,3 @@ def Column(name, stype=None, fkey=None, **kwargs): options.append(ForeignKey(fkey)) return SqlColumn(*options, **kwargs) - - -class MissingDatabaseError(Exception): - '''raise when the "database" kwarg is not set''' diff --git a/IzzyLib/database/sqlite_server.py b/sql/izzylib/sql/sqlite_server.py similarity index 92% rename from IzzyLib/database/sqlite_server.py rename to sql/izzylib/sql/sqlite_server.py index 8dddb0b..5088aec 100644 --- a/IzzyLib/database/sqlite_server.py +++ b/sql/izzylib/sql/sqlite_server.py @@ -1,8 +1,6 @@ import asyncio, json, socket, sqlite3, ssl, time, traceback -from . import SqlDatabase -from .sql import CustomRows -from .. import logging, misc +from izzylib import CustomRows, DotDict, Path, JsonEncoder, SqlDatabase, izzylog commands = [ @@ -119,7 +117,7 @@ class SqliteSession(socket.socket): login = self.send('login', self.data.password) if not login.get('message') == 'OK': - logging.error('Server error:', login.error) + izzylog.error('Server error:', login.error) return self.connected = True @@ -143,7 +141,7 @@ class SqliteSession(socket.socket): pass -def Column(*args, **kwargs): +def SqliteColumn(*args, **kwargs): return {'args': list(args), 'kwargs': dict(kwargs)} @@ -160,9 +158,9 @@ class SqliteServer(misc.DotDict): self.metadata_layout = { 'databases': [ - Column('id'), - Column('name', 'text', nullable=False), - Column('layout', 'text', nullable=False) + SqliteColumn('id'), + SqliteColumn('name', 'text', nullable=False), + SqliteColumn('layout', 'text', nullable=False) ] } @@ -190,7 +188,7 @@ class SqliteServer(misc.DotDict): row = s.fetch('databases', name=database) if not row: - logging.error('Database not found:', database) + izzylog.error('Database not found:', database) return db.SetupTables(row.layout) @@ -226,11 +224,11 @@ class SqliteServer(misc.DotDict): loop.run_until_complete(self.asyncio_run()) try: - logging.info('Starting Sqlite Server') + izzylog.info('Starting Sqlite Server') loop.run_forever() except KeyboardInterrupt: print() - logging.info('Closing...') + izzylog.info('Closing...') return @@ -238,9 +236,9 @@ class SqliteServer(misc.DotDict): meta = self.open('metadata') tables = { 'databases': [ - Column('id'), - Column('name', 'text', nullable=False), - Column('layout', 'text', nullable=False) + SqliteColumn('id'), + SqliteColumn('name', 'text', nullable=False), + SqliteColumn('layout', 'text', nullable=False) ] } @@ -300,7 +298,7 @@ class SqliteServer(misc.DotDict): writer.write(json.dumps(response or {'message': 'OK'}, cls=misc.JsonEncoder).encode('utf8')) await writer.drain() - logging.info(f'{writer.get_extra_info("peername")[0]}: [{database}] {data.command} {data.args} {data.kwargs}') + izzylog.info(f'{writer.get_extra_info("peername")[0]}: [{database}] {data.command} {data.args} {data.kwargs}') if data.command == 'delete': writer.close() diff --git a/sql/setup.py b/sql/setup.py new file mode 100644 index 0000000..46a7aa6 --- /dev/null +++ b/sql/setup.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python3 +from setuptools import setup + + +requires = [ + 'SQLAlchemy==1.3.22', + 'SQLAlchemy-Paginator==0.2', + 'tinydb==4.4.0', + 'tinydb-serialization==2.1.0', + 'tinydb-smartcache==2.0.0', + 'tinyrecord==0.2.0' +] + + +setup( + name="IzzyLib SQL", + version='0.6.0', + packages=['izzylib.sql'], + python_requires='>=3.7.0', + install_requires=requires, + include_package_data=False, + author='Zoey Mae', + author_email='admin@barkshark.xyz', + description='a collection of often-used functions and classes', + keywords='database postgresql sqlite tinydb', + url='https://git.barkshark.xyz/izaliamae/izzylib', + project_urls={ + 'Bug Tracker': 'https://git.barkshark.xyz/izaliamae/izzylib/issues', + 'Documentation': 'https://git.barkshark.xyz/izaliamae/izzylib/wiki', + 'Source Code': 'https://git.barkshark.xyz/izaliamae/izzylib' + }, + + classifiers=[ + 'Development Status :: 3 - Alpha', + 'Intended Audience :: Information Technology', + 'License :: Co-operative Non-violent Public License (CNPL 6+)', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', + 'Operating System :: POSIX', + 'Operating System :: MacOS :: MacOS X', + 'Operating System :: Microsoft :: Windows', + 'Topic :: Database', + 'Topic :: Software Development :: Libraries', + 'Topic :: Software Development :: Libraries :: Python Modules' + ] +) diff --git a/IzzyLib/template.py b/template/izzylib/template/__init__.py similarity index 69% rename from IzzyLib/template.py rename to template/izzylib/template/__init__.py index c49f683..0855bec 100644 --- a/IzzyLib/template.py +++ b/template/izzylib/template/__init__.py @@ -1,11 +1,11 @@ -'''functions for web template management and rendering''' import codecs, traceback, os, json, xml +from colour import Color as Colour +from hamlish_jinja import HamlishExtension +from izzylib import izzylog, DotDict, Path +from jinja2 import Environment, FileSystemLoader, ChoiceLoader, select_autoescape, Markup from os import listdir, makedirs from os.path import isfile, isdir, getmtime, abspath - -from jinja2 import Environment, FileSystemLoader, ChoiceLoader, select_autoescape, Markup -from hamlish_jinja import HamlishExtension from xml.dom import minidom try: @@ -14,10 +14,6 @@ try: except ModuleNotFoundError: Response = None -from . import logging -from .color import * -from .misc import Path, DotDict - class Template(Environment): def __init__(self, search=[], global_vars={}, context=None, autoescape=True): @@ -43,11 +39,7 @@ class Template(Environment): self.globals.update({ 'markup': Markup, 'cleanhtml': lambda text: ''.join(xml.etree.ElementTree.fromstring(text).itertext()), - 'lighten': lighten, - 'darken': darken, - 'saturate': saturate, - 'desaturate': desaturate, - 'rgba': rgba + 'color': Color }) self.globals.update(global_vars) @@ -64,11 +56,11 @@ class Template(Environment): def setContext(self, context): if not hasattr(context, '__call__'): - logging.error('Context is not callable') + izzylog.error('Context is not callable') return if not isinstance(context({}, {}), dict): - logging.error('Context does not return a dict or dict-like object') + izzylog.error('Context does not return a dict or dict-like object') return self.func_context = context @@ -135,3 +127,47 @@ class Template(Environment): html = self.render(tpl, request=request, **kwargs) return Response.HTTPResponse(body=html, status=status, content_type=ctype, headers=kwargs.get('headers', {})) + + +class Color(Colour): + def __init__(self, color): + super.__init__(f'#{str(raw_color)}' if raw_color.startswith('#') else raw_color) + + self.lighten = lambda color, multi: self.alter('lighten', multi) + self.darken = lambda color, multi: self.alter('darken', multi) + self.saturate = lambda color, multi: self.alter('saturate', multi) + self.desaturate = lambda color, multi: self.alter('desaturate', multi) + self.rgba = lambda color, multi: self.alter('rgba', multi) + + + def multi(multiplier): + if multiplier >= 1: + return 1 + + elif multiplier <= 0: + return 0 + + return multiplier + + + def alter(action, multiplier): + if action == 'lighten': + self.luminance += ((1 - color.luminance) * self.multi(multiplier)) + + elif action == 'darken': + self.luminance -= (color.luminance * self.multi(multiplier)) + + elif action == 'saturate': + self.saturation += ((1 - color.saturation) * self.multi(multiplier)) + + elif action == 'desaturate': + self.saturation -= (color.saturation * self.multi(multiplier)) + + elif action == 'rgba': + red = self.red*255 + green = self.green*255 + blue = self.blue*255 + trans = self.multi(multiplier) + return f'rgba({red:0.2f}, {green:0.2f}, {blue:0.2f}, {trans:0.2f})' + + return self.hex_l diff --git a/template/setup.py b/template/setup.py new file mode 100644 index 0000000..3d22a23 --- /dev/null +++ b/template/setup.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python3 +from setuptools import setup + + +requires = [ + 'colour==0.1.5', + 'Hamlish-Jinja==0.3.3', + 'Jinja2==2.11.2', + 'Markdown==3.3.3', +] + + +setup( + name="IzzyLib Templates", + version='0.6.0', + packages=['izzylib.template'], + python_requires='>=3.7.0', + install_requires=requires, + include_package_data=False, + author='Zoey Mae', + author_email='admin@barkshark.xyz', + description='A template engine based on Jinja2 and HAMLish-Jinja', + keywords='web http templates jinja haml', + url='https://git.barkshark.xyz/izaliamae/izzylib', + project_urls={ + 'Bug Tracker': 'https://git.barkshark.xyz/izaliamae/izzylib/issues', + 'Documentation': 'https://git.barkshark.xyz/izaliamae/izzylib/wiki', + 'Source Code': 'https://git.barkshark.xyz/izaliamae/izzylib' + }, + + classifiers=[ + 'Development Status :: 3 - Alpha', + 'Intended Audience :: Information Technology', + 'License :: Co-operative Non-violent Public License (CNPL 6+)', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', + 'Operating System :: POSIX', + 'Operating System :: MacOS :: MacOS X', + 'Operating System :: Microsoft :: Windows', + 'Topic :: Internet :: WWW/HTTP', + 'Topic :: Internet :: WWW/HTTP :: Dynamic Content', + 'Topic :: Software Development :: Libraries', + 'Topic :: Software Development :: Libraries :: Python Modules' + ] +) diff --git a/tinydb/izzylib/tinydb/__init__.py b/tinydb/izzylib/tinydb/__init__.py new file mode 100644 index 0000000..d7a8b4e --- /dev/null +++ b/tinydb/izzylib/tinydb/__init__.py @@ -0,0 +1 @@ +from .tiny import TinyDatabase, TinyRow, TinyRows diff --git a/IzzyLib/database/tiny.py b/tinydb/izzylib/tinydb/tiny.py similarity index 64% rename from IzzyLib/database/tiny.py rename to tinydb/izzylib/tinydb/tiny.py index a9cafe4..ae10a5f 100644 --- a/IzzyLib/database/tiny.py +++ b/tinydb/izzylib/tinydb/tiny.py @@ -1,3 +1,4 @@ +# incomplete import base64 import json import operator @@ -8,7 +9,8 @@ import time import tinydb import tinydb_serialization -from .. import misc +from concurrent.futures import ThreadPoolExecutor, as_completed +from izzylib import Path, random_gen class AwaitingResult(object): @@ -16,10 +18,9 @@ class AwaitingResult(object): class TinyDatabase(tinydb.TinyDB): - def __init__(self, dbfile: misc.Path, queue_limit: int=64, serializers: list=[]): + def __init__(self, dbfile: Path, queue_limit: int=64, serializers: list=[]): options = { - 'indent': 2, - 'separators': (',', ': '), + 'indent': 2 } serialization = tinydb_serialization.SerializationMiddleware(ThreadSupport) @@ -89,7 +90,7 @@ def TinyRows(db, rows): return [TinyRow(db, row) for row in rows] -class TinyRow(misc.DotDict): +class TinyRow(DotDict): def __init__(self, db, row): super().__init({'id': row.doc_id}) super().update({k: v for k,v in row.items()}) @@ -108,15 +109,7 @@ class ThreadSupport(tinydb.storages.JSONStorage): def __init__(self, filename, *args, **kwargs): super().__init__(filename, *args, **kwargs) - self._thread_event = threading.Event() - self._shutdown = False - self._results = {} - self._queue = queue.Queue() - - self._lock = threading.Lock() - self._thread = threading.Thread(target=self.process_queue) - self._thread.daemon = True - self._thread.start() + self.pool = ThreadPoolExecutor(max_workers=8) ## send all storage commands to the queue def read(self): @@ -125,80 +118,12 @@ class ThreadSupport(tinydb.storages.JSONStorage): def write(self, data): - self.queue_put('write', data) + for future in as_completed(self.pool.submit(super().write, data)): + self.queue_put('write', data) def close(self): - self.queue_put('close') - - - def get_action(self, action): - return getattr(super(), action) - - - def get_result(self, qid): - with self._lock: - return self._results[qid] - - - def set_result(self, qid, data=AwaitingResult): - with self._lock: - self._results[qid] = data - - - def pop_result(self, qid): - with self._lock: - return self._result.pop(qid) - - - ## queue - def process_queue(self): - while not self._thread_event.is_set(): - if not self._queue.empty(): - qid, action, args, kwargs = self._queue.get(block=False) - - if qid not in self._results: - self.set_result(qid) - if action == 'close': - self._shutdown = True - - func = self.get_action(action) - - if action == 'read': - self.set_result(qid, func(*args, **kwargs)) - - else: - time.sleep(0.1) - - if self._shutdown: - self.get_action('close')() - return - - - def queue_put(self, func, *args, **kwargs): - if self._shutdown: - logging.error('Storage has been closed. Refusing to send more commands') - return - - qid = misc.RandomGen() - - self._queue.put((qid, func, args, kwargs)) - - if func != 'read': - return - - sleep_time = 0.0 - - while self.get_result(qid) == AwaitingResult: - time.sleep(0.1) - sleep_time += 0.1 - - if sleep_time >= 5.0: - raise TimeoutError(f'Timeout on "{func}" with args: {args}, {kwargs}') - - result = self.pop_result(qid) - print(result) - return result + self.pool.shutdown(wait=False) class ByteSerializer(tinydb_serialization.Serializer): @@ -226,7 +151,7 @@ class DictSerializer(tinydb_serialization.Serializer): class DotDictSerialize(tinydb_serialization.Serializer): - OBJ_CLASS = misc.DotDict + OBJ_CLASS = DotDict def encode(self, obj): #print('encode', self.__class__.__name__, obj) @@ -234,11 +159,11 @@ class DotDictSerialize(tinydb_serialization.Serializer): def decode(self, obj): #print('decode', self.__class__.__name__, obj) - return misc.DotDict(obj) + return DotDict(obj) class PathSerialize(tinydb_serialization.Serializer): - OBJ_CLASS = misc.Path + OBJ_CLASS = Path def encode(self, obj): #print('encode', self.__class__.__name__, obj) @@ -246,4 +171,4 @@ class PathSerialize(tinydb_serialization.Serializer): def decode(self, obj): #print('decode', self.__class__.__name__, obj) - return misc.Path(obj) + return Path(obj) diff --git a/tinydb/setup.py b/tinydb/setup.py new file mode 100644 index 0000000..6368abc --- /dev/null +++ b/tinydb/setup.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +from setuptools import setup, find_namespace_packages + + +requires = [ + 'tinydb==4.4.0', + 'tinydb-serialization==2.1.0', + 'tinydb-smartcache==2.0.0', + 'tinyrecord==0.2.0' +] + + +setup( + name="IzzyLib TinyDB", + version='0.6.0', + packages=['izzylib.tinydb'], + python_requires='>=3.7.0', + install_requires=requires, + include_package_data=False, + author='Zoey Mae', + author_email='admin@barkshark.xyz', + description='a collection of often-used functions and classes', + keywords='database postgresql sqlite tinydb', + url='https://git.barkshark.xyz/izaliamae/izzylib', + project_urls={ + 'Bug Tracker': 'https://git.barkshark.xyz/izaliamae/izzylib/issues', + 'Documentation': 'https://git.barkshark.xyz/izaliamae/izzylib/wiki', + 'Source Code': 'https://git.barkshark.xyz/izaliamae/izzylib' + }, + + classifiers=[ + 'Development Status :: 3 - Alpha', + 'Intended Audience :: Information Technology', + 'License :: Co-operative Non-violent Public License (CNPL 6+)', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', + 'Operating System :: POSIX', + 'Operating System :: MacOS :: MacOS X', + 'Operating System :: Microsoft :: Windows', + 'Topic :: Database', + 'Topic :: Software Development :: Libraries', + 'Topic :: Software Development :: Libraries :: Python Modules' + ] +) From a65a1e8733150f3102f1c07b57f5e7d794a68cab Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Mon, 7 Jun 2021 16:57:38 -0400 Subject: [PATCH 24/74] Update 'README.md' --- README.md | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 22a77fd..794de42 100644 --- a/README.md +++ b/README.md @@ -7,26 +7,43 @@ These are just a number of functions I keep reusing over and over again in most You only need to install the base and whatever sub-modules you want to use ### From Git -$(venv)/bin/python -m pip install -e git+https://git.barkshark.xyz/izaliamae/izzylib.git#egg=izzylib-base&subdirectory=base -$(venv)/bin/python -m pip install -e git+https://git.barkshark.xyz/izaliamae/izzylib.git#egg=izzylib-http-server&subdirectory=http_server -$(venv)/bin/python -m pip install -e git+https://git.barkshark.xyz/izaliamae/izzylib.git#egg=izzylib-http-requests-client&subdirectory=requests_client -$(venv)/bin/python -m pip install -e git+https://git.barkshark.xyz/izaliamae/izzylib.git#egg=izzylib-sql&subdirectory=sql -$(venv)/bin/python -m pip install -e git+https://git.barkshark.xyz/izaliamae/izzylib.git#egg=izzylib-templates&subdirectory=template -$(venv)/bin/python -m pip install -e git+https://git.barkshark.xyz/izaliamae/izzylib.git#egg=izzylib-tinydb&subdirectory=tinydb + + `$(venv)/bin/python -m pip install -e "git+https://git.barkshark.xyz/izaliamae/izzylib.git@rework#egg=izzylib-base&subdirectory=base"` + + `$(venv)/bin/python -m pip install -e "git+https://git.barkshark.xyz/izaliamae/izzylib.git@rework#egg=izzylib-http-server&subdirectory=http_server"` + + `$(venv)/bin/python -m pip install -e "git+https://git.barkshark.xyz/izaliamae/izzylib.git@rework#egg=izzylib-http-requests-client&subdirectory=requests_client"` + + `$(venv)/bin/python -m pip install -e "git+https://git.barkshark.xyz/izaliamae/izzylib.git@rework#egg=izzylib-sql&subdirectory=sql"` + + `$(venv)/bin/python -m pip install -e "git+https://git.barkshark.xyz/izaliamae/izzylib.git@rework#egg=izzylib-templates&subdirectory=template"` + + `$(venv)/bin/python -m pip install -e "git+https://git.barkshark.xyz/izaliamae/izzylib.git@rework#egg=izzylib-tinydb&subdirectory=tinydb"` ### From Source -$(venv)/bin/python -m pip install ./base ./http_server ./requests_client ./sql ./template ./tinydb + `$(venv)/bin/python setup.py install ['all' or a combination of these: http_server requests_client sql template tinydb]` ## Documentation ### Importing -Most useful classes and functions are imported in the module root, so you don't need to do any multi-level imports. For example, just do `from izzylib import SqlDatabase` instead of `from izzylib.sql.generic import SqlDatabase`. Or even simply do `import izzylib` and use `izzylib.SqlDatabase()`. +Most useful classes and functions are imported in the module root, so you don't need to do any multi-level imports. Example + +This is fine: + + `from izzylib import SqlDatabase` + +and points to: + + `from izzylib.sql.generic import SqlDatabase` + +Or even simply do `import izzylib` and use `izzylib.SqlDatabase()`. ### Usage All classes and functions will have docstrings. Either look through the code or run `help()` on an object # NOTE! -not in a stable state yet. Expect major changes + +Not in a stable state yet. Expect major changes From 5dde150146854df969a8d462bc89b34d756e6d42 Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Mon, 7 Jun 2021 16:59:47 -0400 Subject: [PATCH 25/74] Update 'README.md' minor readme fixes --- README.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 794de42..26a4023 100644 --- a/README.md +++ b/README.md @@ -8,21 +8,21 @@ You only need to install the base and whatever sub-modules you want to use ### From Git - `$(venv)/bin/python -m pip install -e "git+https://git.barkshark.xyz/izaliamae/izzylib.git@rework#egg=izzylib-base&subdirectory=base"` + $(venv)/bin/python -m pip install -e "git+https://git.barkshark.xyz/izaliamae/izzylib.git@rework#egg=izzylib-base&subdirectory=base" - `$(venv)/bin/python -m pip install -e "git+https://git.barkshark.xyz/izaliamae/izzylib.git@rework#egg=izzylib-http-server&subdirectory=http_server"` + $(venv)/bin/python -m pip install -e "git+https://git.barkshark.xyz/izaliamae/izzylib.git@rework#egg=izzylib-http-server&subdirectory=http_server" - `$(venv)/bin/python -m pip install -e "git+https://git.barkshark.xyz/izaliamae/izzylib.git@rework#egg=izzylib-http-requests-client&subdirectory=requests_client"` + $(venv)/bin/python -m pip install -e "git+https://git.barkshark.xyz/izaliamae/izzylib.git@rework#egg=izzylib-http-requests-client&subdirectory=requests_client" - `$(venv)/bin/python -m pip install -e "git+https://git.barkshark.xyz/izaliamae/izzylib.git@rework#egg=izzylib-sql&subdirectory=sql"` + $(venv)/bin/python -m pip install -e "git+https://git.barkshark.xyz/izaliamae/izzylib.git@rework#egg=izzylib-sql&subdirectory=sql" - `$(venv)/bin/python -m pip install -e "git+https://git.barkshark.xyz/izaliamae/izzylib.git@rework#egg=izzylib-templates&subdirectory=template"` + $(venv)/bin/python -m pip install -e "git+https://git.barkshark.xyz/izaliamae/izzylib.git@rework#egg=izzylib-templates&subdirectory=template" - `$(venv)/bin/python -m pip install -e "git+https://git.barkshark.xyz/izaliamae/izzylib.git@rework#egg=izzylib-tinydb&subdirectory=tinydb"` + $(venv)/bin/python -m pip install -e "git+https://git.barkshark.xyz/izaliamae/izzylib.git@rework#egg=izzylib-tinydb&subdirectory=tinydb" ### From Source - `$(venv)/bin/python setup.py install ['all' or a combination of these: http_server requests_client sql template tinydb]` + $(venv)/bin/python setup.py install ['all' or a combination of these: http_server requests_client sql template tinydb] ## Documentation @@ -32,11 +32,11 @@ Most useful classes and functions are imported in the module root, so you don't This is fine: - `from izzylib import SqlDatabase` + from izzylib import SqlDatabase and points to: - `from izzylib.sql.generic import SqlDatabase` + from izzylib.sql.generic import SqlDatabase Or even simply do `import izzylib` and use `izzylib.SqlDatabase()`. From 1ea42aeca9890e673b3714e74d7a38f72463bf91 Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Mon, 7 Jun 2021 17:08:41 -0400 Subject: [PATCH 26/74] fix logging --- base/izzylib/logging.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/izzylib/logging.py b/base/izzylib/logging.py index 4dba74e..637773e 100644 --- a/base/izzylib/logging.py +++ b/base/izzylib/logging.py @@ -101,7 +101,7 @@ def get_logger(name, **config): '''create a default logger''' logger = { - 'default': Log('Default') + 'default': Log('Default'), 'IzzyLib': Log('IzzyLib') } From b728df4bc043259660fb5c27321fd0e0af088d68 Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Mon, 7 Jun 2021 20:43:54 -0400 Subject: [PATCH 27/74] multiple fixes and re-subclass path to str --- base/izzylib/__init__.py | 4 +- base/izzylib/dotdict.py | 58 +++++++++ base/izzylib/http_urllib_client.py | 8 +- base/izzylib/misc.py | 12 +- base/izzylib/path.py | 173 ++++++++++++++++---------- base/setup.py | 4 +- http_server/setup.py | 2 +- requests_client/setup.py | 2 +- sql/setup.py | 4 +- template/izzylib/template/__init__.py | 11 +- template/setup.py | 4 +- tinydb/setup.py | 2 +- 12 files changed, 189 insertions(+), 95 deletions(-) diff --git a/base/izzylib/__init__.py b/base/izzylib/__init__.py index 6772c29..ddbee12 100644 --- a/base/izzylib/__init__.py +++ b/base/izzylib/__init__.py @@ -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 diff --git a/base/izzylib/dotdict.py b/base/izzylib/dotdict.py index 455f3a7..ec101ca 100644 --- a/base/izzylib/dotdict.py +++ b/base/izzylib/dotdict.py @@ -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])): diff --git a/base/izzylib/http_urllib_client.py b/base/izzylib/http_urllib_client.py index fc71193..ece6a5d 100644 --- a/base/izzylib/http_urllib_client.py +++ b/base/izzylib/http_urllib_client.py @@ -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)) diff --git a/base/izzylib/misc.py b/base/izzylib/misc.py index a567dd1..41d07d8 100644 --- a/base/izzylib/misc.py +++ b/base/izzylib/misc.py @@ -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)) diff --git a/base/izzylib/path.py b/base/izzylib/path.py index 1e53ce0..2df16db 100644 --- a/base/izzylib/path.py +++ b/base/izzylib/path.py @@ -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] diff --git a/base/setup.py b/base/setup.py index 221dda8..6b78e70 100755 --- a/base/setup.py +++ b/base/setup.py @@ -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', diff --git a/http_server/setup.py b/http_server/setup.py index 5b5ea40..87ed6e1 100644 --- a/http_server/setup.py +++ b/http_server/setup.py @@ -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, diff --git a/requests_client/setup.py b/requests_client/setup.py index ddb7ad7..2db89d2 100644 --- a/requests_client/setup.py +++ b/requests_client/setup.py @@ -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, diff --git a/sql/setup.py b/sql/setup.py index 46a7aa6..4d39128 100644 --- a/sql/setup.py +++ b/sql/setup.py @@ -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, diff --git a/template/izzylib/template/__init__.py b/template/izzylib/template/__init__.py index 0855bec..14ab6c3 100644 --- a/template/izzylib/template/__init__.py +++ b/template/izzylib/template/__init__.py @@ -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__'): diff --git a/template/setup.py b/template/setup.py index 3d22a23..9c37147 100644 --- a/template/setup.py +++ b/template/setup.py @@ -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, diff --git a/tinydb/setup.py b/tinydb/setup.py index 6368abc..c02d993 100644 --- a/tinydb/setup.py +++ b/tinydb/setup.py @@ -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, From 95cc5c71033baaeb85dd47edc3181c7f0f809fad Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Mon, 7 Jun 2021 20:51:00 -0400 Subject: [PATCH 28/74] remove Path.str() calls --- base/izzylib/path.py | 2 +- sql/izzylib/sql/generic.py | 6 ++++-- sql/izzylib/sql/sqlite_server.py | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/base/izzylib/path.py b/base/izzylib/path.py index 2df16db..09b3364 100644 --- a/base/izzylib/path.py +++ b/base/izzylib/path.py @@ -36,7 +36,7 @@ class Path(str): def append(self, text): - return Path(str(self.__path) + text) + return Path(self + text) def backup(self, ext='backup', overwrite=False): diff --git a/sql/izzylib/sql/generic.py b/sql/izzylib/sql/generic.py index c8dac85..dd31153 100644 --- a/sql/izzylib/sql/generic.py +++ b/sql/izzylib/sql/generic.py @@ -46,10 +46,12 @@ class SqlDatabase: engine_string = dbtype + '://' if dbtype == 'sqlite': - if nfs_check(kwargs.get('database')): + database = kwargs.get('database') + + if nfs_check(database): izzylog.error('Database file is on an NFS share which does not support locking. Any writes to the database will fail') - engine_string += '/' + str(kwargs.get('database')) + engine_string += f'/{database}' engine_kwargs['connect_args'] = {'check_same_thread': False} else: diff --git a/sql/izzylib/sql/sqlite_server.py b/sql/izzylib/sql/sqlite_server.py index 5088aec..9cd5b6d 100644 --- a/sql/izzylib/sql/sqlite_server.py +++ b/sql/izzylib/sql/sqlite_server.py @@ -176,7 +176,7 @@ class SqliteServer(misc.DotDict): self.setup_metadata() for path in self.path.listdir(False): - if path.str().endswith('.sqlite3') and path.stem != 'metadata': + if path.endswith('.sqlite3') and path.stem != 'metadata': self.open(path.stem) From 4564fced5be12051eaff687f55ba71ce27112d55 Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Mon, 7 Jun 2021 21:05:30 -0400 Subject: [PATCH 29/74] update reequirements --- http_server/setup.py | 11 +++-------- requests_client/setup.py | 2 +- sql/setup.py | 8 ++------ template/setup.py | 2 +- 4 files changed, 7 insertions(+), 16 deletions(-) diff --git a/http_server/setup.py b/http_server/setup.py index 87ed6e1..02fdcb4 100644 --- a/http_server/setup.py +++ b/http_server/setup.py @@ -4,15 +4,10 @@ from setuptools import setup, find_namespace_packages requires = [ 'argon2-cffi==20.1.0', - 'colour==0.1.5', - 'Hamlish-Jinja==0.3.3', - 'Jinja2==2.11.2', - 'Markdown==3.3.3', 'pillow==8.2.0', - 'pycryptodome==3.9.9', - 'requests==2.25.1', - 'sanic==20.12.1', - 'Sanic-Cors==0.10.0.post3' + 'pycryptodome==3.10.1', + 'sanic==21.2.4', + 'Sanic-Cors==1.0.0' ] diff --git a/requests_client/setup.py b/requests_client/setup.py index 2db89d2..d7edd78 100644 --- a/requests_client/setup.py +++ b/requests_client/setup.py @@ -4,7 +4,7 @@ from setuptools import setup, find_namespace_packages requires = [ 'pillow==8.2.0', - 'pycryptodome==3.9.9', + 'pycryptodome==3.10.1', 'requests==2.25.1', ] diff --git a/sql/setup.py b/sql/setup.py index 4d39128..e118755 100644 --- a/sql/setup.py +++ b/sql/setup.py @@ -3,12 +3,8 @@ from setuptools import setup, find_namespace_packages requires = [ - 'SQLAlchemy==1.3.22', - 'SQLAlchemy-Paginator==0.2', - 'tinydb==4.4.0', - 'tinydb-serialization==2.1.0', - 'tinydb-smartcache==2.0.0', - 'tinyrecord==0.2.0' + 'SQLAlchemy==1.4.7', + 'SQLAlchemy-Paginator==0.2' ] diff --git a/template/setup.py b/template/setup.py index 9c37147..36c6a77 100644 --- a/template/setup.py +++ b/template/setup.py @@ -5,7 +5,7 @@ from setuptools import setup, find_namespace_packages requires = [ 'colour==0.1.5', 'Hamlish-Jinja==0.3.3', - 'Jinja2==2.11.2', + 'Jinja2==3.0.1', 'Markdown==3.3.3', ] From bdbd1f4621af22233cb1d9df891eee60432caad3 Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Mon, 7 Jun 2021 21:21:20 -0400 Subject: [PATCH 30/74] change env var for izzylib's log level --- base/izzylib/logging.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/izzylib/logging.py b/base/izzylib/logging.py index 637773e..b9d336d 100644 --- a/base/izzylib/logging.py +++ b/base/izzylib/logging.py @@ -124,6 +124,6 @@ print_config = DefaultLog.print_config try: - logger['IzzyLib'].set_config('level', env['LOG_LEVEL']) + logger['IzzyLib'].set_config('level', env['IZZYLIB_LOG_LEVEL']) except KeyError: 'heck' From 2dafcbcc051198c11e0c002ac4739dcbe49b6cf5 Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Tue, 8 Jun 2021 01:12:30 -0400 Subject: [PATCH 31/74] move json loading and saving to DotDict --- base/izzylib/__init__.py | 2 +- base/izzylib/dotdict.py | 13 ++++++++----- base/izzylib/path.py | 13 +------------ 3 files changed, 10 insertions(+), 18 deletions(-) diff --git a/base/izzylib/__init__.py b/base/izzylib/__init__.py index ddbee12..1b689e9 100644 --- a/base/izzylib/__init__.py +++ b/base/izzylib/__init__.py @@ -14,11 +14,11 @@ from . import logging izzylog = logging.logger['IzzyLib'] +from .path import Path from .dotdict import DotDict, LowerDotDict, DefaultDotDict, MultiDotDict, JsonEncoder from .misc import * from .cache import LruCache, TtlCache from .connection import Connection -from .path import Path from .http_urllib_client import HttpUrllibClient, HttpUrllibResponse diff --git a/base/izzylib/dotdict.py b/base/izzylib/dotdict.py index ec101ca..71d7d75 100644 --- a/base/izzylib/dotdict.py +++ b/base/izzylib/dotdict.py @@ -1,5 +1,7 @@ import json +from . import Path + class DotDict(dict): dict_ignore_types = ['basecache', 'lrucache', 'ttlcache'] @@ -71,13 +73,14 @@ class DotDict(dict): self.update(data) - def load_json(self, path: str=None): - self.update(Path(path).load_json()) + def load_json(self, path): + with open(path) as fd: + self.update(json.load(fd)) - def save_json(self, path: str, **kwargs): - with Path(path).open(w) as fd: - write(self.toJson(*kwargs)) + def save_json(self, path, indent=None): + with open(path, 'w') as fp: + fp.write(self.to_json(indent=indent)) ## This has to be reworked tbh diff --git a/base/izzylib/path.py b/base/izzylib/path.py index 09b3364..afbfdd1 100644 --- a/base/izzylib/path.py +++ b/base/izzylib/path.py @@ -3,11 +3,9 @@ import os, shutil from datetime import datetime from functools import cached_property -from . import DotDict, JsonEncoder - class Path(str): - def __init__(self, path, exist=True, missing=True, parents=True): + def __init__(self, path=os.getcwd(), exist=True, missing=True, parents=True): if str(path).startswith('~'): str.__new__(Path, os.path.expanduser(path)) @@ -73,15 +71,6 @@ class Path(str): return Path(os.path.join(self, new_path)) - def json_load(self): - return DotDict(read(self)) - - - def json_save(self, data, indent=None): - with open(self, 'w') as fp: - fp.write(json.dumps(data, indent=indent, cls=JsonEncoder)) - - def link(self, path): target = Path(path) From 9f6b70987de1e9c7fe62a53b82c4664de8cd7874 Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Tue, 8 Jun 2021 12:07:48 -0400 Subject: [PATCH 32/74] include catch_kb_interrupt in __all__ --- base/izzylib/misc.py | 1 + 1 file changed, 1 insertion(+) diff --git a/base/izzylib/misc.py b/base/izzylib/misc.py index 41d07d8..ebbb0c1 100644 --- a/base/izzylib/misc.py +++ b/base/izzylib/misc.py @@ -12,6 +12,7 @@ from . import izzylog __all__ = [ 'ap_date', 'boolean', + 'catch_kb_interrupt', 'get_ip', 'hasher', 'import_from_path', From 00a5b039950a0f8190c88b295edb48273d2dc143 Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Mon, 14 Jun 2021 03:44:12 -0400 Subject: [PATCH 33/74] a lot --- base/izzylib/__init__.py | 22 +- base/izzylib/cache.py | 20 +- base/izzylib/dotdict.py | 13 +- base/izzylib/misc.py | 13 +- base/izzylib/path.py | 10 +- http_server/izzylib/http_server/hasher.py | 2 +- .../izzylib/http_requests_client/__init__.py | 429 ++---------------- .../izzylib/http_requests_client/client.py | 426 +++++++++++++++++ .../izzylib/http_requests_client/error.py | 0 requests_client/setup.py | 1 + sql/izzylib/sql/__init__.py | 2 +- sql/izzylib/sql/generic.py | 49 +- sql/izzylib/sql/sqlite_server.py | 18 +- template/izzylib/template/__init__.py | 102 +++-- 14 files changed, 630 insertions(+), 477 deletions(-) create mode 100644 requests_client/izzylib/http_requests_client/client.py create mode 100644 requests_client/izzylib/http_requests_client/error.py diff --git a/base/izzylib/__init__.py b/base/izzylib/__init__.py index 1b689e9..ae08e51 100644 --- a/base/izzylib/__init__.py +++ b/base/izzylib/__init__.py @@ -23,34 +23,36 @@ from .connection import Connection from .http_urllib_client import HttpUrllibClient, HttpUrllibResponse -def log_import_error(*message): - izzylog.verbose(*message) +def log_import_error(package, *message): + izzylog.debug(*message) + path = Path(__file__).resolve.parent.join(package) - if izzylog.get_config('level') == logging.Levels.DEBUG: + if path.exists: traceback.print_exc() try: - from izzylib.sql import Column, CustomRows, Session, SqlDatabase, Tables, SqliteClient, SqliteColumn, SqliteServer, SqliteSession + from izzylib.sql import SqlColumn, CustomRows, SqlSession, SqlDatabase, Tables, SqliteClient, SqliteColumn, SqliteServer, SqliteSession except ImportError: - log_import_error('Failed to import SQL classes. Connecting to SQL databases is disabled') + log_import_error('sql', 'Failed to import SQL classes. Connecting to SQL databases is disabled') try: from izzylib.tinydb import TinyDatabase, TinyRow, TinyRows except ImportError: - log_import_error('Failed to import TinyDB classes. TinyDB database is disabled') + log_import_error('tinydb', 'Failed to import TinyDB classes. TinyDB database is disabled') try: from izzylib.template import Template, Color except ImportError: - log_import_error('Failed to import http template classes. Jinja and HAML templates disabled') + log_import_error('template', 'Failed to import http template classes. Jinja and HAML templates disabled') try: - from izzylib.http_requests_client import HttpRequestsClient, HttpRequestsRequest, HttpRequestsResponse + from izzylib.http_requests_client import * + except ImportError: - log_import_error('Failed to import Requests http client classes. Requests http client is disabled.') + log_import_error('requests_client', 'Failed to import Requests http client classes. Requests http client is disabled') try: from izzylib.http_server import PasswordHasher, HttpServer, HttpServerRequest, HttpServerResponse except ImportError: - log_import_error('Failed to import HTTP server classes. The HTTP server will be disabled') + log_import_error('http_server', 'Failed to import HTTP server classes. The HTTP server will be disabled') diff --git a/base/izzylib/cache.py b/base/izzylib/cache.py index 646434a..905711c 100644 --- a/base/izzylib/cache.py +++ b/base/izzylib/cache.py @@ -1,9 +1,8 @@ -'''Simple caches that uses ordered dicts''' - import re from datetime import datetime from collections import OrderedDict +from functools import wraps from . import DotDict @@ -113,6 +112,23 @@ class BaseCache(OrderedDict): return self[key].data + ## Was gonna use this for db stuff, but I need to plan it out better + def decorator(function, key, arg=0): + @wraps(function) + def wrapper(*args, **kwargs): + cached = self.fetch(key) + + if cached: + return cached + + result = function(*args, **kwargs) + + self.store(key, args[arg] if type(arg) == int else kwargs[arg]) + + return result + return wrapper + + class TtlCache(BaseCache): def __init__(self, maxsize=1024, ttl='1h'): super().__init__(maxsize, ttl) diff --git a/base/izzylib/dotdict.py b/base/izzylib/dotdict.py index 71d7d75..4168de3 100644 --- a/base/izzylib/dotdict.py +++ b/base/izzylib/dotdict.py @@ -56,6 +56,10 @@ class DotDict(dict): raise AttributeError(f'{self.__class__.__name__} object has no attribute {k}') from None + def copy(self): + return DotDict(self) + + def update(self, data): for k,v in data.items(): self.__setitem__(k, v) @@ -90,7 +94,7 @@ class DefaultDotDict(DotDict): val = super().__getattribute__(key) except AttributeError: - val = self.get(key, DefaultDict()) + val = self.get(key, DefaultDotDict()) return DotDict(val) if type(val) == dict else val @@ -160,6 +164,13 @@ class MultiDotDict(DotDict): return default + def set(self, key, value): + if self.get(key): + del self[key] + + self[key] = value + + def delone(self, key, value): self.__getitem__(key, False).remove(value) diff --git a/base/izzylib/misc.py b/base/izzylib/misc.py index ebbb0c1..c75dbb1 100644 --- a/base/izzylib/misc.py +++ b/base/izzylib/misc.py @@ -1,5 +1,5 @@ '''Miscellaneous functions''' -import hashlib, random, string, statistics, socket, time, timeit +import hashlib, platform, random, string, statistics, socket, time, timeit from datetime import datetime from getpass import getpass @@ -137,8 +137,11 @@ def hasher(string, alg='blake2s'): str: The hashed string in hex format as a string ''' - if alg not in hashlib.__always_supported: - raise TypeError('Unsupported hash algorithm. Supported algs:', ', '.join(hashlib.__always_supported)) + if alg not in hashlib.algorithms_available: + raise TypeError('Unsupported hash algorithm. Supported algs:', ', '.join(hashlib.algorithms_available)) + + if alg in ['sha1', 'md4', 'md5', 'md5-sha1']: + logging.verbose('Warning: Using an insecure hashing algorithm. sha256 or sha512 is recommended') string = string.encode('UTF-8') if type(string) != bytes else string @@ -220,7 +223,7 @@ def port_check(port, address='127.0.0.1', tcp=True): with socket.socket(socket.AF_INET, socket.SOCK_STREAM if tcp else socket.SOCK_DGRAM) as s: try: - return not s.connect_ex((address, port)) == 0 + return s.connect_ex((address, port)) == 0 except socket.error as e: return False @@ -310,7 +313,7 @@ def random_gen(length=20, letters=True, numbers=True, extra=None): if letters: characters += string.ascii_letters - if digits: + if numbers: characters += string.digits if extra: diff --git a/base/izzylib/path.py b/base/izzylib/path.py index afbfdd1..3897348 100644 --- a/base/izzylib/path.py +++ b/base/izzylib/path.py @@ -26,10 +26,10 @@ class Path(str): def __check_dir(self, path=None): target = self if not path else Path(path) - if not self.parents and not target.parent.exists: + if not self.config['parents'] and not target.parent.exists: raise FileNotFoundError('Parent directories do not exist:', target) - if not self.exist and target.exists: + if not self.config['exist'] and target.exists: raise FileExistsError('File or directory already exists:', target) @@ -90,11 +90,11 @@ class Path(str): def mkdir(self, mode=0o755): - if self.parents: - os.makedirs(self, mode, exist_ok=self.exist) + if self.config['parents']: + os.makedirs(self, mode, exist_ok=self.config['exist']) else: - os.makedir(self, mode, exist_ok=self.exist) + os.makedir(self, mode, exist_ok=self.config['exist']) return self.exists diff --git a/http_server/izzylib/http_server/hasher.py b/http_server/izzylib/http_server/hasher.py index 921af17..a708dae 100644 --- a/http_server/izzylib/http_server/hasher.py +++ b/http_server/izzylib/http_server/hasher.py @@ -34,7 +34,7 @@ class PasswordHasher: 'memory_cost': memory * 1024, 'parallelism': threads, 'encoding': 'utf-8', - 'type': algtype, + 'type': type, } self.hasher = argon2.PasswordHasher(**self.config) diff --git a/requests_client/izzylib/http_requests_client/__init__.py b/requests_client/izzylib/http_requests_client/__init__.py index 4ce85d2..902e7b5 100644 --- a/requests_client/izzylib/http_requests_client/__init__.py +++ b/requests_client/izzylib/http_requests_client/__init__.py @@ -1,393 +1,36 @@ -import json, requests, sys - -from Crypto.Hash import SHA256 -from Crypto.PublicKey import RSA -from Crypto.Signature import PKCS1_v1_5 -from PIL import Image - -from base64 import b64decode, b64encode -from datetime import datetime -from functools import cached_property, lru_cache -from io import BytesIO -from izzylib import DefaultDotDict, DotDict, Path, izzylog, __version__ -from ssl import SSLCertVerificationError -from urllib.error import HTTPError -from urllib.parse import urlparse -from urllib.request import Request, urlopen - - -methods = ['connect', 'delete', 'get', 'head', 'options', 'patch', 'post', 'put', 'trace'] - - -class RequestsClient(object): - def __init__(self, headers={}, useragent=f'IzzyLib/{__version__}', appagent=None, proxy_type='https', proxy_host=None, proxy_port=None): - proxy_ports = { - 'http': 80, - 'https': 443 - } - - if proxy_type not in ['http', 'https']: - raise ValueError(f'Not a valid proxy type: {proxy_type}') - - self.headers=headers - self.agent = f'{useragent} ({appagent})' if appagent else useragent - self.proxy = DotDict({ - 'enabled': True if proxy_host else False, - 'ptype': proxy_type, - 'host': proxy_host, - 'port': proxy_ports[proxy_type] if not proxy_port else proxy_port - }) - - self.SetGlobal = SetClient - - - def __sign_request(self, request, privkey, keyid): - if not crypto_enabled: - izzylog.error('Crypto functions disabled') - return - - request.add_header('(request-target)', f'{request.method.lower()} {request.path}') - request.add_header('host', request.host) - request.add_header('date', datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT')) - - if request.body: - body_hash = b64encode(SHA256.new(request.body).digest()).decode("UTF-8") - request.add_header('digest', f'SHA-256={body_hash}') - request.add_header('content-length', len(request.body)) - - sig = { - 'keyId': keyid, - 'algorithm': 'rsa-sha256', - 'headers': ' '.join([k.lower() for k in request.headers.keys()]), - 'signature': b64encode(PkcsHeaders(privkey, request.headers)).decode('UTF-8') - } - - sig_items = [f'{k}="{v}"' for k,v in sig.items()] - sig_string = ','.join(sig_items) - - request.add_header('signature', sig_string) - - request.remove_header('(request-target)') - request.remove_header('host') - - - def request(self, *args, method='get', **kwargs): - if method.lower() not in methods: - raise ValueError(f'Invalid method: {method}') - - request = RequestsRequest(self, *args, method=method.lower(), **kwargs) - return RequestsResponse(request.send()) - - - def file(self, url, filepath, *args, filename=None, **kwargs): - resp = self.request(url, *args, **kwargs) - - if resp.status != 200: - izzylog.error(f'Failed to download {url}:', resp.status, resp.body) - return False - - return resp.save(filepath) - - - def image(self, url, filepath, *args, filename=None, ext='png', dimensions=(50, 50), **kwargs): - if not Image: - izzylog.error('Pillow module is not installed') - return - - resp = self.request(url, *args, **kwargs) - - if resp.status != 200: - izzylog.error(f'Failed to download {url}:', resp.status, resp.body) - return False - - if not filename: - filename = Path(url).stem() - - path = Path(filepath) - - if not path.exists(): - izzylog.error('Path does not exist:', path) - return False - - byte = BytesIO() - image = Image.open(BytesIO(resp.body)) - image.thumbnail(dimensions) - image.save(byte, format=ext.upper()) - - with path.join(filename).open('wb') as fd: - fd.write(byte.getvalue()) - - - def json(self, *args, headers={}, activity=True, **kwargs): - json_type = 'activity+json' if activity else 'json' - headers.update({ - 'accept': f'application/{json_type}' - }) - - return self.request(*args, headers=headers, **kwargs) - - - def signed_request(self, privkey, keyid, *args, **kwargs): - request = RequestsRequest(self, *args, **kwargs) - self.__sign_request(request, privkey, keyid) - return RequestsResponse(request.send()) - - -class RequestsRequest(object): - def __init__(self, client, url, data=None, headers={}, query={}, method='get'): - self.args = [url] - self.kwargs = {'params': query} - self.method = method.lower() - self.client = client - - new_headers = client.headers.copy() - new_headers.update(headers) - - parsed_headers = {k.lower(): v for k,v in new_headers.items()} - - if not parsed_headers.get('user-agent'): - parsed_headers['user-agent'] = client.agent - - self.kwargs['headers'] = new_headers - self.kwargs['data'] = data - - if client.proxy.enabled: - self.kwargs['proxies'] = {self.proxy.ptype: f'{self.proxy.ptype}://{self.proxy.host}:{self.proxy.port}'} - - - def send(self): - func = getattr(requests, self.method) - return func(*self.args, **self.kwargs) - - -class RequestsResponse(object): - def __init__(self, response): - self.response = response - self.data = b'' - self.headers = DefaultDict({k.lower(): v.lower() for k,v in response.headers.items()}) - self.status = response.status_code - self.url = response.url - - - def chunks(self, size=256): - return self.response.iter_content(chunk_size=256) - - - @property - def body(self): - for chunk in self.chunks(): - self.data += chunk - - return self.data - - - @cached_property - def text(self): - return self.data.decode(self.response.encoding) - - - @cached_property - def json(self): - return DotDict(self.text) - - - @cached_property - def json_pretty(self, indent=4): - return json.dumps(self.json, indent=indent) - - - def save(self, path, overwrite=True): - path = Path(path) - parent = path.parent() - - if not parent.exists(): - raise ValueError(f'Path does not exist: {parent}') - - if overwrite and path.exists(): - path.delete() - - with path.open('wb') as fd: - for chunk in self.chunks(): - fd.write(chunk) - - -def verify_request(request: SanicRequest, actor: dict): - '''Verify a header signature from a SimpleASGI request - - request: The request with the headers to verify - actor: A dictionary containing the activitypub actor and the link to the pubkey used for verification - ''' - - body = request.body if request.body else None - return verify_headers(request.headers, request.method, request.path, body, actor) - - -def verify_headers(headers: dict, method: str, path: str, actor: dict=None, body=None): - '''Verify a header signature - - headers: A dictionary containing all the headers from a request - method: The HTTP method of the request - path: The path of the HTTP request - actor (optional): A dictionary containing the activitypub actor and the link to the pubkey used for verification - body (optional): The body of the request. Only needed if the signature includes the digest header - fail (optional): If set to True, raise an error instead of returning False if any step of the process fails - ''' - - headers = {k.lower(): v for k,v in headers.items()} - headers['(request-target)'] = f'{method.lower()} {path}' - signature = parse_signature(headers.get('signature')) - digest = parse_body_digest(headers.get('digest')) - missing_headers = [k for k in headers if k in ['date', 'host'] if headers.get(k) == None] - - if not signature: - raise ValueError('Missing signature') - - if not actor: - actor = fetch_actor(signature.keyid) - - ## Add digest header to missing headers list if it doesn't exist - if method.lower() == 'post' and not digest: - missing_headers.append('digest') - - ## Fail if missing date, host or digest (if POST) headers - if missing_headers: - raise KeyError(f'Missing headers: {missing_headers}') - - ## Fail if body verification fails - if digest and not VerifyString(body, digest.sig, digest.alg): - raise ValueError('Failed body digest verification') - - pubkey = actor.publicKey['publicKeyPem'] - - return PkcsHeaders(pubkey, {k:v for k,v in headers.items() if k in signature.headers}, sig=signature) - - -def parse_body_digest(digest): - if not digest: - raise ValueError('Empty digest') - - parsed = DotDict() - alg, sig = digest.split('=', 1) - - parsed.sig = sig - parsed.alg = alg.replace('-', '') - - return parsed - - -def verify_string(string, enc_string, alg='SHA256', fail=False): - if type(string) != bytes: - string = string.encode('UTF-8') - - body_hash = b64encode(SHA256.new(string).digest()).decode('UTF-8') - - if body_hash == enc_string: - return True - - if fail: - raise ValueError('String failed validation') - - else: - return False - - -def sign_pkcs_headers(key: str, headers: dict, sig=None): - if sig: - head_items = [f'{item}: {headers[item]}' for item in sig.headers] - - else: - head_items = [f'{k.lower()}: {v}' for k,v in headers.items()] - - head_string = '\n'.join(head_items) - head_bytes = head_string.encode('UTF-8') - - KEY = RSA.importKey(key) - pkcs = PKCS1_v1_5.new(KEY) - h = SHA256.new(head_bytes) - - if sig: - return pkcs.verify(h, b64decode(sig.signature)) - - else: - return pkcs.sign(h) - - -def parse_signature(signature: str): - if not signature: - raise ValueError('Missing signature header') - - split_sig = signature.split(',') - sig = DefaultDict({}) - - for part in split_sig: - key, value = part.split('=', 1) - sig[key.lower()] = value.replace('"', '') - - sig.headers = sig.headers.split() - - return sig - - -@lru_cache(maxsize=512) -def fetch_actor(url): - if not Client: - raise ValueError('Please set global client with "SetRequestsClient(client)"') - - url = url.split('#')[0] - headers = {'Accept': 'application/activity+json'} - resp = Client.request(url, headers=headers) - - try: - actor = resp.json() - - except Exception as e: - izzylog.debug(f'HTTP {resp.status}: {resp.body}') - raise e from None - - actor.web_domain = urlparse(url).netloc - actor.shared_inbox = actor.inbox - actor.pubkey = None - actor.handle = actor.preferredUsername - - if actor.get('endpoints'): - actor.shared_inbox = actor.endpoints.get('sharedInbox', actor.inbox) - - if actor.get('publicKey'): - actor.pubkey = actor.publicKey.get('publicKeyPem') - - return actor - - -@lru_cache(maxsize=512) -def fetch_webfinger_account(handle, domain): - if not Client: - izzylog.error('IzzyLib.http: Please set global client with "SetClient(client)"') - return {} - - data = DefaultDict() - webfinger = Client.request(f'https://{domain}/.well-known/webfinger?resource=acct:{handle}@{domain}') - - if not webfinger.body: - raise ValueError('Webfinger body empty') - - data.handle, data.domain = webfinger.json().subject.replace('acct:', '').split('@') - - for link in webfinger.json().links: - if link['rel'] == 'self' and link['type'] == 'application/activity+json': - data.actor = link['href'] - - return data - - -def set_requests_client(client=None): - global Client - Client = client or RequestsClient() - - -def generate_rsa_key(): - privkey = RSA.generate(2048) - - key = DotDict({'PRIVKEY': privkey, 'PUBKEY': privkey.publickey()}) - key.update({'privkey': key.PRIVKEY.export_key().decode(), 'pubkey': key.PUBKEY.export_key().decode()}) - - return key +from .client import ( + HttpRequestsClient, + HttpRequestsRequest, + HttpRequestsResponse, + SigningError, + verify_request, + verify_headers, + parse_signature, + fetch_actor, + fetch_webfinger_account, + fetch_nodeinfo, + set_requests_client, + generate_rsa_key +) + + ## These usually only get called by the above functions, but importing anyway +from .client import ( + parse_body_digest, + verify_string, + sign_pkcs_headers +) + +__all__ = [ + 'HttpRequestsClient', + 'HttpRequestsRequest', + 'HttpRequestsResponse', + 'SigningError', + 'fetch_actor', + 'fetch_webfinger_account', + 'fetch_nodeinfo', + 'generate_rsa_key', + 'parse_signature', + 'set_requests_client', + 'verify_headers', + 'verify_request', +] diff --git a/requests_client/izzylib/http_requests_client/client.py b/requests_client/izzylib/http_requests_client/client.py new file mode 100644 index 0000000..68ee52a --- /dev/null +++ b/requests_client/izzylib/http_requests_client/client.py @@ -0,0 +1,426 @@ +import json, requests, sys + +from Crypto.Hash import SHA256 +from Crypto.PublicKey import RSA +from Crypto.Signature import PKCS1_v1_5 +from PIL import Image + +from base64 import b64decode, b64encode +from datetime import datetime +from functools import cached_property, lru_cache +from io import BytesIO +from izzylib import DefaultDotDict, DotDict, Path, izzylog as logging, __version__ +from izzylib.exceptions import HttpFileDownloadedError +from ssl import SSLCertVerificationError +from tldextract import extract +from urllib.parse import urlparse + + +Client = None +methods = ['connect', 'delete', 'get', 'head', 'options', 'patch', 'post', 'put', 'trace'] + + +class HttpRequestsClient(object): + def __init__(self, headers={}, useragent=f'IzzyLib/{__version__}', appagent=None, proxy_type='https', proxy_host=None, proxy_port=None): + proxy_ports = { + 'http': 80, + 'https': 443 + } + + if proxy_type not in ['http', 'https']: + raise ValueError(f'Not a valid proxy type: {proxy_type}') + + self.headers=headers + self.agent = f'{useragent} ({appagent})' if appagent else useragent + self.proxy = DotDict({ + 'enabled': True if proxy_host else False, + 'ptype': proxy_type, + 'host': proxy_host, + 'port': proxy_ports[proxy_type] if not proxy_port else proxy_port + }) + + + def set_global(self): + global Client + Client = self + + + def __sign_request(self, request, privkey, keyid): + if not crypto_enabled: + izzylog.error('Crypto functions disabled') + return + + request.add_header('(request-target)', f'{request.method.lower()} {request.path}') + request.add_header('host', request.host) + request.add_header('date', datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT')) + + if request.body: + body_hash = b64encode(SHA256.new(request.body).digest()).decode("UTF-8") + request.add_header('digest', f'SHA-256={body_hash}') + request.add_header('content-length', len(request.body)) + + sig = { + 'keyId': keyid, + 'algorithm': 'rsa-sha256', + 'headers': ' '.join([k.lower() for k in request.headers.keys()]), + 'signature': b64encode(PkcsHeaders(privkey, request.headers)).decode('UTF-8') + } + + sig_items = [f'{k}="{v}"' for k,v in sig.items()] + sig_string = ','.join(sig_items) + + request.add_header('signature', sig_string) + + request.remove_header('(request-target)') + request.remove_header('host') + + + def request(self, *args, method='get', **kwargs): + if method.lower() not in methods: + raise ValueError(f'Invalid method: {method}') + + request = HttpRequestsRequest(self, *args, method=method.lower(), **kwargs) + return HttpRequestsResponse(request.send()) + + + def download(self, url, filepath, *args, filename=None, **kwargs): + resp = self.request(url, *args, **kwargs) + + if resp.status != 200: + raise HttpFileDownloadedError(f'Failed to download {url}: Status: {resp.status}, Body: {resp.body}') + + return resp.save(filepath) + + + def image(self, url, filepath, *args, filename=None, ext='png', dimensions=(50, 50), **kwargs): + if not Image: + izzylog.error('Pillow module is not installed') + return + + resp = self.request(url, *args, **kwargs) + + if resp.status != 200: + izzylog.error(f'Failed to download {url}:', resp.status, resp.body) + return False + + if not filename: + filename = Path(url).stem() + + path = Path(filepath) + + if not path.exists: + izzylog.error('Path does not exist:', path) + return False + + byte = BytesIO() + image = Image.open(BytesIO(resp.body)) + image.thumbnail(dimensions) + image.save(byte, format=ext.upper()) + + with path.join(filename).open('wb') as fd: + fd.write(byte.getvalue()) + + + def json(self, *args, headers={}, activity=True, **kwargs): + json_type = 'activity+json' if activity else 'json' + headers.update({ + 'accept': f'application/{json_type}' + }) + + return self.request(*args, headers=headers, **kwargs) + + + def signed_request(self, privkey, keyid, *args, **kwargs): + request = HttpRequestsRequest(self, *args, **kwargs) + self.__sign_request(request, privkey, keyid) + return HttpRequestsResponse(request.send()) + + +class HttpRequestsRequest(object): + def __init__(self, client, url, data=None, headers={}, query={}, method='get'): + self.args = [url] + self.kwargs = {'params': query} + self.method = method.lower() + self.client = client + + new_headers = client.headers.copy() + new_headers.update(headers) + + parsed_headers = {k.lower(): v for k,v in new_headers.items()} + + if not parsed_headers.get('user-agent'): + parsed_headers['user-agent'] = client.agent + + self.kwargs['headers'] = new_headers + self.kwargs['data'] = data + + if client.proxy.enabled: + self.kwargs['proxies'] = {self.proxy.ptype: f'{self.proxy.ptype}://{self.proxy.host}:{self.proxy.port}'} + + + def send(self): + func = getattr(requests, self.method) + return func(*self.args, **self.kwargs) + + +class HttpRequestsResponse(object): + def __init__(self, response): + self.response = response + self.data = b'' + self.headers = DefaultDotDict({k.lower(): v.lower() for k,v in response.headers.items()}) + self.status = response.status_code + self.url = response.url + + + def chunks(self, size=256): + return self.response.iter_content(chunk_size=256) + + + @property + def body(self): + for chunk in self.chunks(): + self.data += chunk + + return self.data + + + @cached_property + def text(self): + return self.data.decode(self.response.encoding) + + + @cached_property + def json(self): + return DotDict(self.body) + + + @cached_property + def json_pretty(self, indent=4): + return json.dumps(self.json, indent=indent) + + + def save(self, path, overwrite=True): + path = Path(path) + + if not path.parent.exists: + raise ValueError(f'Path does not exist: {path.parent}') + + if overwrite and path.exists: + path.delete() + + with path.open('wb') as fd: + for chunk in self.chunks(): + fd.write(chunk) + + +async def verify_request(request, actor: dict=None): + '''Verify a header signature from a SimpleASGI request + + request: The request with the headers to verify + actor: A dictionary containing the activitypub actor and the link to the pubkey used for verification + ''' + + body = (await request.body) if request.body else None + headers = {k.lower(): v[0] for k,v in request.headers.items()} + return verify_headers(headers, request.method, request.path, actor, body) + + +def verify_headers(headers: dict, method: str, path: str, actor: dict=None, body=None): + '''Verify a header signature + + headers: A dictionary containing all the headers from a request + method: The HTTP method of the request + path: The path of the HTTP request + actor (optional): A dictionary containing the activitypub actor and the link to the pubkey used for verification + body (optional): The body of the request. Only needed if the signature includes the digest header + fail (optional): If set to True, raise an error instead of returning False if any step of the process fails + ''' + + headers = {k.lower(): v for k,v in headers.items()} + headers['(request-target)'] = f'{method.lower()} {path}' + signature = parse_signature(headers.get('signature')) + digest = headers.get('digest') + missing_headers = [k for k in headers if k in ['date', 'host'] if headers.get(k) == None] + + if not signature: + raise AssertionError('Missing signature') + + if not actor: + actor = fetch_actor(signature.keyid) + print(actor) + + ## Add digest header to missing headers list if it doesn't exist + if method.lower() == 'post' and not digest: + missing_headers.append('digest') + + ## Fail if missing date, host or digest (if POST) headers + if missing_headers: + raise AssertionError(f'Missing headers: {missing_headers}') + + ## Fail if body verification fails + if digest: + digest_hash = parse_body_digest(headers.get('digest')) + + if not verify_string(body, digest_hash.sig, digest_hash.alg): + raise AssertionError('Failed body digest verification') + + pubkey = actor.publicKey['publicKeyPem'] + + return sign_pkcs_headers(pubkey, {k:v for k,v in headers.items() if k in signature.headers}, sig=signature) + + +def parse_body_digest(digest): + if not digest: + raise AssertionError('Empty digest') + + parsed = DotDict() + alg, sig = digest.split('=', 1) + + parsed.sig = sig + parsed.alg = alg.replace('-', '') + + return parsed + + +def verify_string(string, enc_string, alg='SHA256', fail=False): + if type(string) != bytes: + string = string.encode('UTF-8') + + body_hash = b64encode(SHA256.new(string).digest()).decode('UTF-8') + + if body_hash == enc_string: + return True + + if fail: + raise AssertionError('String failed validation') + + else: + return False + + +def sign_pkcs_headers(key: str, headers: dict, sig=None): + if sig: + head_items = [f'{item}: {headers[item]}' for item in sig.headers] + + else: + head_items = [f'{k.lower()}: {v}' for k,v in headers.items()] + + head_string = '\n'.join(head_items) + head_bytes = head_string.encode('UTF-8') + + KEY = RSA.importKey(key) + pkcs = PKCS1_v1_5.new(KEY) + h = SHA256.new(head_bytes) + + if sig: + return pkcs.verify(h, b64decode(sig.signature)) + + else: + return pkcs.sign(h) + + +def parse_signature(signature: str): + if not signature: + return + raise AssertionError('Missing signature header') + + split_sig = signature.split(',') + sig = DefaultDotDict() + + for part in split_sig: + key, value = part.split('=', 1) + sig[key.lower()] = value.replace('"', '') + + sig.headers = sig.headers.split() + sig.domain = urlparse(sig.keyid).netloc + sig.top_domain = '.'.join(extract(sig.domain)[1:]) + + return sig + + +@lru_cache(maxsize=512) +def fetch_actor(url): + if not Client: + raise ValueError('Please set global client with "SetRequestsClient(client)"') + + url = url.split('#')[0] + headers = {'Accept': 'application/activity+json'} + resp = Client.request(url, headers=headers) + + try: + actor = resp.json + + except json.decoder.JSONDecodeError: + return + + except Exception as e: + izzylog.debug(f'HTTP {resp.status}: {resp.body}') + raise e from None + + actor.web_domain = urlparse(url).netloc + actor.shared_inbox = actor.inbox + actor.pubkey = None + actor.handle = actor.preferredUsername + + if actor.get('endpoints'): + actor.shared_inbox = actor.endpoints.get('sharedInbox', actor.inbox) + + if actor.get('publicKey'): + actor.pubkey = actor.publicKey.get('publicKeyPem') + + return actor + + +@lru_cache(maxsize=512) +def fetch_webfinger_account(handle, domain): + if not Client: + raise ValueError('Please set global client with HttpRequestsClient.set_global()') + + data = DefaultDotDict() + webfinger = Client.request(f'https://{domain}/.well-known/webfinger?resource=acct:{handle}@{domain}') + + if not webfinger.body: + raise ValueError('Webfinger body empty') + + data.handle, data.domain = webfinger.json.subject.replace('acct:', '').split('@') + + for link in webfinger.json.links: + if link['rel'] == 'self' and link['type'] == 'application/activity+json': + data.actor = link['href'] + + return data + + +@lru_cache(maxsize=512) +def fetch_nodeinfo(domain): + if not Client: + raise ValueError('Please set global client with HttpRequestsClient.set_global()') + + webfinger = Client.request(f'https://{domain}/.well-known/nodeinfo') + webfinger_data = DotDict(webfinger.body) + + for link in webfinger.json.links: + if link['rel'] == 'http://nodeinfo.diaspora.software/ns/schema/2.0': + nodeinfo_url = link['href'] + break + + nodeinfo = Client.request(nodeinfo_url) + return nodeinfo.json + + +def set_requests_client(client=None): + global Client + Client = client or RequestsClient() + + +def generate_rsa_key(): + privkey = RSA.generate(2048) + + key = DotDict({'PRIVKEY': privkey, 'PUBKEY': privkey.publickey()}) + key.update({'privkey': key.PRIVKEY.export_key().decode(), 'pubkey': key.PUBKEY.export_key().decode()}) + + return key + + +class SigningError(Exception): + pass diff --git a/requests_client/izzylib/http_requests_client/error.py b/requests_client/izzylib/http_requests_client/error.py new file mode 100644 index 0000000..e69de29 diff --git a/requests_client/setup.py b/requests_client/setup.py index d7edd78..187d62b 100644 --- a/requests_client/setup.py +++ b/requests_client/setup.py @@ -6,6 +6,7 @@ requires = [ 'pillow==8.2.0', 'pycryptodome==3.10.1', 'requests==2.25.1', + 'tldextract==3.1.0' ] diff --git a/sql/izzylib/sql/__init__.py b/sql/izzylib/sql/__init__.py index 77d7732..5228cfa 100644 --- a/sql/izzylib/sql/__init__.py +++ b/sql/izzylib/sql/__init__.py @@ -1,2 +1,2 @@ -from .generic import Column, CustomRows, Session, SqlDatabase, Tables +from .generic import SqlColumn, CustomRows, SqlSession, SqlDatabase, Tables from .sqlite_server import SqliteClient, SqliteColumn, SqliteServer, SqliteSession diff --git a/sql/izzylib/sql/generic.py b/sql/izzylib/sql/generic.py index dd31153..7255a50 100644 --- a/sql/izzylib/sql/generic.py +++ b/sql/izzylib/sql/generic.py @@ -3,7 +3,7 @@ import json, sys, threading, time from contextlib import contextmanager from datetime import datetime from sqlalchemy import create_engine, ForeignKey, MetaData, Table -from sqlalchemy import Column as SqlColumn, types as Types +from sqlalchemy import Column, types as Types from sqlalchemy.exc import OperationalError, ProgrammingError from sqlalchemy.orm import scoped_session, sessionmaker @@ -27,11 +27,11 @@ class SqlDatabase: self.classes = kwargs.get('row_classes', CustomRows()) self.cache = None - self.session_class = kwargs.get('session_class', Session) + self.session_class = kwargs.get('session_class', SqlSession) self.sessions = {} - self.SetupTables(tables) - self.SetupCache() + self.setup_tables(tables) + self.setup_cache() ## Leaving link to example code for read-only sqlite for later use @@ -69,7 +69,7 @@ class SqlDatabase: engine_string += user + '@' if host == '/var/run/postgresql': - engine_string += '/' + name + engine_string += f'/{name}:{port}/{name}' else: engine_string += f'{host}:{port}/{name}' @@ -83,19 +83,19 @@ class SqlDatabase: def close(self): - self.SetupCache() + self.setup_cache() - def SetupCache(self): + def setup_cache(self): self.cache = DotDict({table: LruCache() for table in self.table_names}) - def CreateTables(self, *tables): + def create_tables(self, *tables): new_tables = [self.table[table] for table in tables] self.table.meta.create_all(bind=self.db, tables=new_tables) - def CreateDatabase(self): + def create_database(self): if self.db.url.get_backend_name() == 'postgresql': predb = create_engine(db.engine_string.replace(config.db.name, 'postgres', -1)) conn = predb.connect() @@ -116,7 +116,7 @@ class SqlDatabase: self.table.meta.create_all(self.db) - def SetupTables(self, tables): + def setup_tables(self, tables): self.table = Tables(self, tables) self.table_names = tables.keys() @@ -126,7 +126,7 @@ class SqlDatabase: return s.execute(*args, **kwargs) -class Session(object): +class SqlSession(object): def __init__(self, db): self.closed = False @@ -259,19 +259,19 @@ class Session(object): row = self.execute(f'DELETE FROM {table} WHERE id={rowid}') - def DropTables(self): - tables = self.GetTables() + def drop_tables(self): + tables = self.get_tables() for table in tables: self.execute(f'DROP TABLE {table}') - def GetTables(self): + def get_tables(self): rows = self.execute("SELECT name FROM sqlite_master WHERE type IN ('table','view') and name NOT LIKE 'sqlite_%'") return [row[0] for row in rows] - def AppendColumn(self, tbl, col): + def append_column(self, tbl, col): table = self.table[tbl] try: @@ -301,7 +301,7 @@ class Session(object): self.execute(sql) - def RemoveColumn(self, tbl, col): + def remove_column(self, tbl, col): table = self.table[tbl] column = getattr(table, col, None) columns = [row[1] for row in self.execute(f'PRAGMA table_info({tbl})')] @@ -416,24 +416,29 @@ class Tables(DotDict): def __setup_table(self, name, table): - columns = [col if type(col) == SqlColumn else Column(*col.get('args'), **col.get('kwargs')) for col in table] + columns = [col if type(col) == Column else Column(*col.get('args'), **col.get('kwargs')) for col in table] self[name] = Table(name, self.meta, *columns) -def Column(name, stype=None, fkey=None, **kwargs): +def SqlColumn(name, stype=None, fkey=None, **kwargs): if not stype and not kwargs: if name == 'id': - return Column('id', 'integer', primary_key=True, autoincrement=True) + return Column('id', SqlTypes['integer'], primary_key=True, autoincrement=True) elif name == 'timestamp': - return Column('timestamp', 'datetime') + return Column('timestamp', SqlTypes['datetime']) raise ValueError('Missing column type and options') else: - options = [name, SqlTypes.get(stype.lower(), SqlTypes['string'])] + try: + stype = stype or 'string' + options = [name, SqlTypes[stype.lower()]] + + except KeyError: + raise KeyError(f'Invalid SQL data type: {stype}') if fkey: options.append(ForeignKey(fkey)) - return SqlColumn(*options, **kwargs) + return Column(*options, **kwargs) diff --git a/sql/izzylib/sql/sqlite_server.py b/sql/izzylib/sql/sqlite_server.py index 9cd5b6d..a4aeb8a 100644 --- a/sql/izzylib/sql/sqlite_server.py +++ b/sql/izzylib/sql/sqlite_server.py @@ -1,6 +1,8 @@ import asyncio, json, socket, sqlite3, ssl, time, traceback -from izzylib import CustomRows, DotDict, Path, JsonEncoder, SqlDatabase, izzylog +from izzylib import DotDict, JsonEncoder, Path, izzylog + +from . import CustomRows, SqlDatabase commands = [ @@ -12,7 +14,7 @@ commands = [ class SqliteClient(object): def __init__(self, database: str='metadata', host: str='localhost', port: int=3926, password: str=None, session_class=None): self.ssl = None - self.data = misc.DotDict({ + self.data = DotDict({ 'host': host, 'port': int(port), 'password': password, @@ -96,7 +98,7 @@ class SqliteSession(socket.socket): data = self.recv(8*1024*1024).decode() try: - data = misc.DotDict(data) + data = DotDict(data) except ValueError: data = json.loads(data) @@ -145,12 +147,12 @@ def SqliteColumn(*args, **kwargs): return {'args': list(args), 'kwargs': dict(kwargs)} -class SqliteServer(misc.DotDict): +class SqliteServer(DotDict): def __init__(self, path, host='localhost', port=3926, password=None): self.server = None - self.database = misc.DotDict() + self.database = DotDict() - self.path = misc.Path(path).resolve() + self.path = Path(path).resolve() self.ssl = None self.password = password self.host = host @@ -266,7 +268,7 @@ class SqliteServer(misc.DotDict): break try: - data = misc.DotDict(raw_data) + data = DotDict(raw_data) if self.password: if valid == None and data.command == 'login': @@ -363,7 +365,7 @@ class SqliteServer(misc.DotDict): def cmd_update(self, table=None, rowid=None, row=None, **data): if row: - row = misc.DotDict(row) + row = DotDict(row) return self.update(table, rowid, row, **data) diff --git a/template/izzylib/template/__init__.py b/template/izzylib/template/__init__.py index 14ab6c3..1f61b77 100644 --- a/template/izzylib/template/__init__.py +++ b/template/izzylib/template/__init__.py @@ -1,6 +1,7 @@ import codecs, traceback, os, json, xml from colour import Color as Colour +from functools import partial from hamlish_jinja import HamlishExtension from izzylib import izzylog, DotDict, Path from jinja2 import Environment, FileSystemLoader, ChoiceLoader, select_autoescape, Markup @@ -18,14 +19,14 @@ except ModuleNotFoundError: class Template(Environment): def __init__(self, search=[], global_vars={}, context=None, autoescape=True): self.autoescape = autoescape - self.search = [] self.func_context = context + self.search = FileSystemLoader([]) for path in search: - self.__add_search_path(Path(path)) + self.add_search_path(Path(path)) super().__init__( - loader=ChoiceLoader([FileSystemLoader(path) for path in self.search]), + loader=self.search, extensions=[HamlishExtension], autoescape=self.autoescape, lstrip_blocks=True, @@ -39,21 +40,31 @@ class Template(Environment): self.globals.update({ 'markup': Markup, 'cleanhtml': lambda text: ''.join(xml.etree.ElementTree.fromstring(text).itertext()), - 'color': Color + 'color': Color, + 'lighten': partial(color_func, 'lighten'), + 'darken': partial(color_func, 'darken'), + 'saturate': partial(color_func, 'saturate'), + 'desaturate': partial(color_func, 'desaturate'), + 'rgba': partial(color_func, 'rgba') }) self.globals.update(global_vars) - def __add_search_path(self, path): + def add_search_path(self, path, index=None): if not path.exists: raise FileNotFoundError(f'Cannot find search path: {path}') - if path not in self.search: - self.search.append(path) + if path not in self.search.searchpath: + loader = os.fspath(path) + + if index != None: + self.search.searchpath.insert(index, loader) + else: + self.search.searchpath.append(loader) - def setContext(self, context): + def set_context(self, context): if not hasattr(context, '__call__'): izzylog.error('Context is not callable') return @@ -65,37 +76,37 @@ class Template(Environment): self.func_context = context - def addEnv(self, k, v): + def add_env(self, k, v): self.globals[k] = v - def delEnv(self, var): + def del_env(self, var): if not self.globals.get(var): raise ValueError(f'"{var}" not in global variables') del self.var[var] - def updateEnv(self, data): + def update_env(self, data): if not isinstance(data, dict): raise ValueError(f'Environment data not a dict') self.globals.update(data) - def addFilter(self, funct, name=None): + def add_filter(self, funct, name=None): name = funct.__name__ if not name else name self.filters[name] = funct - def delFilter(self, name): + def del_filter(self, name): if not self.filters.get(name): raise valueError(f'"{name}" not in global filters') del self.filters[name] - def updateFilter(self, data): + def update_filter(self, data): if not isinstance(context, dict): raise ValueError(f'Filter data not a dict') @@ -130,37 +141,66 @@ class Template(Environment): class Color(Colour): def __init__(self, color): - super.__init__(f'#{str(raw_color)}' if raw_color.startswith('#') else raw_color) + if isinstance(color, str): + super().__init__(f'#{str(color)}' if not color.startswith('#') else color) - self.lighten = lambda color, multi: self.alter('lighten', multi) - self.darken = lambda color, multi: self.alter('darken', multi) - self.saturate = lambda color, multi: self.alter('saturate', multi) - self.desaturate = lambda color, multi: self.alter('desaturate', multi) - self.rgba = lambda color, multi: self.alter('rgba', multi) + elif isinstance(color, Colour): + super().__init__(str(color)) + + else: + raise TypeError(f'Color has to be a string or Color class, not {type(color)}') - def multi(multiplier): - if multiplier >= 1: + def __repr__(self): + return self.__str__() + + + def __str__(self): + return self.hex_l + + + def lighten(self, multiplier): + return self.alter('lighten', multiplier) + + + def darken(self, multiplier): + return self.alter('darken', multiplier) + + + def saturate(self, multiplier): + return self.alter('saturate', multiplier) + + + def desaturate(self, multiplier): + return self.alter('desaturate', multiplier) + + + def rgba(self, multiplier): + return self.alter('rgba', multiplier) + + + def multi(self, multiplier): + if multiplier >= 100: return 1 elif multiplier <= 0: return 0 - return multiplier + return multiplier / 100 - def alter(action, multiplier): + def alter(self, action, multiplier): if action == 'lighten': - self.luminance += ((1 - color.luminance) * self.multi(multiplier)) + self.luminance += ((1 - self.luminance) * self.multi(multiplier)) elif action == 'darken': - self.luminance -= (color.luminance * self.multi(multiplier)) + self.luminance -= (self.luminance * self.multi(multiplier)) elif action == 'saturate': - self.saturation += ((1 - color.saturation) * self.multi(multiplier)) + self.saturation += ((1 - self.saturation) * self.multi(multiplier)) elif action == 'desaturate': - self.saturation -= (color.saturation * self.multi(multiplier)) + self.saturation -= (self.saturation * self.multi(multiplier)) elif action == 'rgba': red = self.red*255 @@ -169,4 +209,8 @@ class Color(Colour): trans = self.multi(multiplier) return f'rgba({red:0.2f}, {green:0.2f}, {blue:0.2f}, {trans:0.2f})' - return self.hex_l + return self + + +def color_func(action, color, multi): + return Color(color).alter(action, multi) From b4615af1393e2410e40f29fe1993e5153e38a71c Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Thu, 17 Jun 2021 23:05:55 -0400 Subject: [PATCH 34/74] a bunch --- base/izzylib/__init__.py | 2 +- base/izzylib/cache.py | 37 +- base/izzylib/misc.py | 2 +- hasher/izzylib/hasher/__init__.py | 1 + .../izzylib/hasher}/hasher.py | 2 +- {http_server => hasher}/setup.py | 10 +- http_server/izzylib/http_server/__init__.py | 2 - http_server/izzylib/http_server/server.py | 331 ------------------ .../izzylib/http_requests_client/__init__.py | 6 +- .../izzylib/http_requests_client/client.py | 75 +++- sql/izzylib/sql/generic.py | 13 +- 11 files changed, 105 insertions(+), 376 deletions(-) create mode 100644 hasher/izzylib/hasher/__init__.py rename {http_server/izzylib/http_server => hasher/izzylib/hasher}/hasher.py (98%) rename {http_server => hasher}/setup.py (86%) delete mode 100644 http_server/izzylib/http_server/__init__.py delete mode 100644 http_server/izzylib/http_server/server.py diff --git a/base/izzylib/__init__.py b/base/izzylib/__init__.py index ae08e51..e440d40 100644 --- a/base/izzylib/__init__.py +++ b/base/izzylib/__init__.py @@ -17,7 +17,7 @@ izzylog = logging.logger['IzzyLib'] from .path import Path from .dotdict import DotDict, LowerDotDict, DefaultDotDict, MultiDotDict, JsonEncoder from .misc import * -from .cache import LruCache, TtlCache +from .cache import CacheDecorator, LruCache, TtlCache from .connection import Connection from .http_urllib_client import HttpUrllibClient, HttpUrllibResponse diff --git a/base/izzylib/cache.py b/base/izzylib/cache.py index 905711c..aec9ffe 100644 --- a/base/izzylib/cache.py +++ b/base/izzylib/cache.py @@ -1,8 +1,9 @@ -import re +import json, re from datetime import datetime from collections import OrderedDict -from functools import wraps +from functools import update_wrapper +from hashlib import sha1 from . import DotDict @@ -43,17 +44,24 @@ def parse_ttl(ttl): 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.set = self.store + self.deco = lambda *args: CacheDecorator(self, *args) + def __str__(self): - data = ', '.join([f'{k}="{v["data"]}"' for k,v in self.items()]) + data = ', '.join([f'{k}="{v}"' for k,v in self.items()]) return f'BaseCache({data})' + 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) @@ -109,24 +117,29 @@ class BaseCache(OrderedDict): self[key]['timestamp'] = timestamp + self.ttl self.move_to_end(key) - return self[key].data + return item.data - ## Was gonna use this for db stuff, but I need to plan it out better - def decorator(function, key, arg=0): - @wraps(function) - def wrapper(*args, **kwargs): - cached = self.fetch(key) +## This doesn't work for some reason +def CacheDecorator(cache): + def decorator(func): + def wrapper(cls, *args, **kwargs): + key = sha1(json.dumps(args).encode() + json.dumps(kwargs).encode()).hexdigest() + cached = cache.fetch(key) + print(cached) - if cached: + if cached != None: + print('Returning cached value:', cache) return cached - result = function(*args, **kwargs) + result = func(cls, *args, **kwargs) - self.store(key, args[arg] if type(arg) == int else kwargs[arg]) + cache.store(key, result) return result + return wrapper + return decorator class TtlCache(BaseCache): diff --git a/base/izzylib/misc.py b/base/izzylib/misc.py index c75dbb1..b4de428 100644 --- a/base/izzylib/misc.py +++ b/base/izzylib/misc.py @@ -95,7 +95,7 @@ def catch_kb_interrupt(function, *args, **kwargs): ''' try: - function(*args, **kwargs) + return function(*args, **kwargs) except KeyboardInterrupt: izzylog.verbose('Bye! UvU') diff --git a/hasher/izzylib/hasher/__init__.py b/hasher/izzylib/hasher/__init__.py new file mode 100644 index 0000000..114a4b9 --- /dev/null +++ b/hasher/izzylib/hasher/__init__.py @@ -0,0 +1 @@ +from .hasher import PasswordHasher diff --git a/http_server/izzylib/http_server/hasher.py b/hasher/izzylib/hasher/hasher.py similarity index 98% rename from http_server/izzylib/http_server/hasher.py rename to hasher/izzylib/hasher/hasher.py index a708dae..92ff922 100644 --- a/http_server/izzylib/http_server/hasher.py +++ b/hasher/izzylib/hasher/hasher.py @@ -54,7 +54,7 @@ class PasswordHasher: def hash(self, password: str): - return super().hash(password) + return self.hasher.hash(password) def verify(self, passhash: str, password: str): diff --git a/http_server/setup.py b/hasher/setup.py similarity index 86% rename from http_server/setup.py rename to hasher/setup.py index 02fdcb4..35ac1d7 100644 --- a/http_server/setup.py +++ b/hasher/setup.py @@ -3,18 +3,14 @@ from setuptools import setup, find_namespace_packages requires = [ - 'argon2-cffi==20.1.0', - 'pillow==8.2.0', - 'pycryptodome==3.10.1', - 'sanic==21.2.4', - 'Sanic-Cors==1.0.0' + 'argon2-cffi==20.1.0' ] setup( - name="IzzyLib HTTP Server", + name="IzzyLib Password Hasher", version='0.6.0', - packages=find_namespace_packages(include=['izzylib.http_server']), + packages=find_namespace_packages(include=['izzylib.hasher']), python_requires='>=3.7.0', install_requires=requires, include_package_data=False, diff --git a/http_server/izzylib/http_server/__init__.py b/http_server/izzylib/http_server/__init__.py deleted file mode 100644 index a501f67..0000000 --- a/http_server/izzylib/http_server/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from .hasher import PasswordHasher -from .server import HttpServer, HttpServerRequest, HttpServerResponse diff --git a/http_server/izzylib/http_server/server.py b/http_server/izzylib/http_server/server.py deleted file mode 100644 index 5e4ca53..0000000 --- a/http_server/izzylib/http_server/server.py +++ /dev/null @@ -1,331 +0,0 @@ -# probably gonna remove this since I'll be using my asgi framework -import multiprocessing, sanic, signal, traceback -import logging as pylog - -from jinja2.exceptions import TemplateNotFound -from multidict import CIMultiDict -from multiprocessing import cpu_count, current_process -from sanic.views import HTTPMethodView -from urllib.parse import parse_qsl, urlparse - -from . import http, izzylog -from .misc import DotDict, DefaultDict, LowerDotDict -from .template import Template - - -log_path_ignore = [ - '/media', - '/static' -] - -log_ext_ignore = [ - 'js', 'ttf', 'woff2', - 'ac3', 'aiff', 'flac', 'm4a', 'mp3', 'ogg', 'wav', 'wma', - 'apng', 'ico', 'jpeg', 'jpg', 'png', 'svg', - 'divx', 'mov', 'mp4', 'webm', 'wmv' -] - - -class HttpServer(sanic.Sanic): - def __init__(self, name='sanic', host='0.0.0.0', port='4080', **kwargs): - self.host = host - self.port = int(port) - self.workers = int(kwargs.get('workers', cpu_count())) - self.sig_handler = kwargs.get('sig_handler') - - super().__init__(name, request_class=kwargs.get('request_class', HttpServerRequest)) - - for log in ['sanic.root', 'sanic.access']: - pylog.getLogger(log).setLevel(pylog.ERROR) - - self.template = Template( - kwargs.get('tpl_search', []), - kwargs.get('tpl_globals', {}), - kwargs.get('tpl_context'), - kwargs.get('tpl_autoescape', True) - ) - - self.template.addEnv('app', self) - - self.error_handler.add(TemplateNotFound, NoTemplateError) - self.error_handler.add(Exception, kwargs.get('error_handler', GenericError)) - self.register_middleware(MiddlewareAccessLog, attach_to='response') - - signal.signal(signal.SIGHUP, self.finish) - signal.signal(signal.SIGINT, self.finish) - signal.signal(signal.SIGQUIT, self.finish) - signal.signal(signal.SIGTERM, self.finish) - - - ## Sanic spits out a warning, so this is the workaround to stop it - def __setattr__(self, key, value): - object.__setattr__(self, key, value) - - - def add_method_route(self, method, *routes): - for route in routes: - self.add_route(method.as_view(), route) - - - def add_method_routes(self, routes: list): - for route in routes: - self.add_method_route(*route) - - - def start(self): - options = { - 'host': self.host, - 'port': self.port, - 'workers': self.workers, - 'access_log': False, - 'debug': False - } - - msg = f'Starting {self.name} at {self.host}:{self.port}' - - if self.workers > 1: - msg += f' with {self.workers} workers' - - izzylog.info(msg) - self.run(**options) - - - def finish(self): - if self.sig_handler: - self.sig_handler() - - print('stopping.....') - self.stop() - izzylog.info('Bye! :3') - sys.exit() - - -class HttpServerRequest(sanic.request.Request): - def __init__(self, url_bytes, headers, version, method, transport, app): - super().__init__(url_bytes, headers, version, method, transport, app) - - self.Headers = HttpHeaders(headers) - self.Data = HttpData(self) - self.template = self.app.template - self.__setup_defaults() - self.__parse_path() - - #if self.paths.media: - #return - - self.__parse_signature() - self.Run() - - - def Run(self): - pass - - - def response(self, tpl, *args, **kwargs): - return self.template.response(self, tpl, *args, **kwargs) - - - def alldata(self): - return self.__combine_dicts(self.content.json, self.data.query, self.data.form) - - - def verify(self, actor=None): - self.ap.valid = http.VerifyHeaders(self.headers, self.method, self.path, actor, self.body) - return self.ap.valid - - - def __combine_dicts(self, *dicts): - data = DotDict() - - for item in dicts: - data.update(item) - - return data - - - def __setup_defaults(self): - self.paths = DotDict({'media': False, 'json': False, 'ap': False, 'cookie': False}) - self.ap = DotDict({'valid': False, 'signature': {}, 'actor': None, 'inbox': None, 'domain': None}) - - - def __parse_path(self): - self.paths.media = any(map(self.path.startswith, log_path_ignore)) or any(map(self.path.startswith, log_ext_ignore)) - self.paths.json = self.__json_check() - - - def __parse_signature(self): - sig = self.headers.getone('signature', None) - - if sig: - self.ap.signature = http.ParseSig(sig) - - if self.ap.signature: - self.ap.actor = self.ap.signature.get('keyid', '').split('#', 1)[0] - self.ap.domain = urlparse(self.ap.actor).netloc - - - def __json_check(self): - if self.path.endswith('.json'): - return True - - accept = self.headers.getone('Accept', None) - - if accept: - mimes = [v.strip() for v in accept.split(',')] - - if any(mime in ['application/json', 'application/activity+json'] for mime in mimes): - return True - - return False - - -class HttpServerResponse: - Text = sanic.response.text - Html = sanic.response.html - Json = sanic.response.json - Redir = sanic.response.redirect - - - def Css(*args, headers={}, **kwargs): - ReplaceHeader(headers, 'content-type', 'text/css') - return sanic.response.text(*args, headers=headers, **kwargs) - - - def Js(*args, headers={}, **kwargs): - ReplaceHeader(headers, 'content-type', 'application/javascript') - return sanic.response.text(*args, headers=headers, **kwargs) - - - def Ap(*args, headers={}, **kwargs): - ReplaceHeader(headers, 'content-type', 'application/activity+json') - return sanic.response.json(*args, headers=headers, **kwargs) - - - def Jrd(*args, headers={}, **kwargs): - ReplaceHeader(headers, 'content-type', 'application/jrd+json') - return sanic.response.json(*args, headers=headers, **kwargs) - - -class HttpHeaders(LowerDotDict): - def __init__(self, headers): - super().__init__() - - for k,v in headers.items(): - if not self.get(k): - self[k] = [] - - self[k].append(v) - - - def getone(self, key, default=None): - value = self.get(key) - - if not value: - return default - - return value[0] - - - def getall(self, key, default=[]): - return self.get(key.lower(), default) - - -class HttpData(object): - def __init__(self, request): - self.request = request - - - @property - def combined(self): - return DotDict(**self.form.asDict(), **self.query.asDict(), **self.json.asDict()) - - - @property - def query(self): - data = {k: v for k,v in parse_qsl(self.request.query_string)} - return DotDict(data) - - - @property - def form(self): - data = {k: v[0] for k,v in self.request.form.items()} - return DotDict(data) - - - @property - def files(self): - return DotDict({k:v[0] for k,v in self.request.files.items()}) - - - ### body functions - @property - def raw(self): - try: - return self.request.body - except Exception as e: - izzylog.verbose('IzzyLib.http_server.Data.raw: failed to get body') - izzylog.debug(f'{e.__class__.__name__}: {e}') - return b'' - - - @property - def text(self): - try: - return self.raw.decode() - except Exception as e: - izzylog.verbose('IzzyLib.http_server.Data.text: failed to get body') - izzylog.debug(f'{e.__class__.__name__}: {e}') - return '' - - - @property - def json(self): - try: - return DotDict(self.text) - except Exception as e: - izzylog.verbose('IzzyLib.http_server.Data.json: failed to get body') - izzylog.debug(f'{e.__class__.__name__}: {e}') - data = '{}' - return {} - - -async def MiddlewareAccessLog(request, response): - if request.paths.media: - return - - uagent = request.headers.get('user-agent') - address = request.headers.get('x-real-ip', request.forwarded.get('for', request.remote_addr)) - - izzylog.info(f'({multiprocessing.current_process().name}) {address} {request.method} {request.path} {response.status} "{uagent}"') - - -def GenericError(request, exception): - try: - status = exception.status_code - except: - status = 500 - - if status not in range(200, 499): - traceback.print_exc() - - msg = f'{exception.__class__.__name__}: {str(exception)}' - - if request.paths.json: - return sanic.response.json({'error': {'status': status, 'message': msg}}) - - try: - return request.response('server_error.haml', status=status, context={'status': str(status), 'error': msg}) - - except TemplateNotFound: - return sanic.response.text(f'Error {status}: {msg}') - - -def NoTemplateError(request, exception): - izzylog.error('TEMPLATE_ERROR:', f'{exception.__class__.__name__}: {str(exception)}') - return sanic.response.html('I\'m a dumbass and forgot to create a template for this page', 500) - - -def ReplaceHeader(headers, key, value): - for k,v in headers.items(): - if k.lower() == header.lower(): - del headers[k] diff --git a/requests_client/izzylib/http_requests_client/__init__.py b/requests_client/izzylib/http_requests_client/__init__.py index 902e7b5..e9bd444 100644 --- a/requests_client/izzylib/http_requests_client/__init__.py +++ b/requests_client/izzylib/http_requests_client/__init__.py @@ -7,8 +7,9 @@ from .client import ( verify_headers, parse_signature, fetch_actor, - fetch_webfinger_account, + fetch_instance, fetch_nodeinfo, + fetch_webfinger_account, set_requests_client, generate_rsa_key ) @@ -26,8 +27,9 @@ __all__ = [ 'HttpRequestsResponse', 'SigningError', 'fetch_actor', - 'fetch_webfinger_account', + 'fetch_instance', 'fetch_nodeinfo', + 'fetch_webfinger_account', 'generate_rsa_key', 'parse_signature', 'set_requests_client', diff --git a/requests_client/izzylib/http_requests_client/client.py b/requests_client/izzylib/http_requests_client/client.py index 68ee52a..6316648 100644 --- a/requests_client/izzylib/http_requests_client/client.py +++ b/requests_client/izzylib/http_requests_client/client.py @@ -46,10 +46,6 @@ class HttpRequestsClient(object): def __sign_request(self, request, privkey, keyid): - if not crypto_enabled: - izzylog.error('Crypto functions disabled') - return - request.add_header('(request-target)', f'{request.method.lower()} {request.path}') request.add_header('host', request.host) request.add_header('date', datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT')) @@ -63,7 +59,7 @@ class HttpRequestsClient(object): 'keyId': keyid, 'algorithm': 'rsa-sha256', 'headers': ' '.join([k.lower() for k in request.headers.keys()]), - 'signature': b64encode(PkcsHeaders(privkey, request.headers)).decode('UTF-8') + 'signature': b64encode(sign_pkcs_headers(privkey, request.headers)).decode('UTF-8') } sig_items = [f'{k}="{v}"' for k,v in sig.items()] @@ -83,6 +79,12 @@ class HttpRequestsClient(object): return HttpRequestsResponse(request.send()) + def signed_request(self, privkey, keyid, *args, **kwargs): + request = HttpRequestsRequest(self, *args, **kwargs) + self.__sign_request(request, privkey, keyid) + return HttpRequestsResponse(request.send()) + + def download(self, url, filepath, *args, filename=None, **kwargs): resp = self.request(url, *args, **kwargs) @@ -130,18 +132,15 @@ class HttpRequestsClient(object): return self.request(*args, headers=headers, **kwargs) - def signed_request(self, privkey, keyid, *args, **kwargs): - request = HttpRequestsRequest(self, *args, **kwargs) - self.__sign_request(request, privkey, keyid) - return HttpRequestsResponse(request.send()) - - class HttpRequestsRequest(object): def __init__(self, client, url, data=None, headers={}, query={}, method='get'): + parsed = urlparse(url) self.args = [url] - self.kwargs = {'params': query} + self.kwargs = DotDict({'params': query}) self.method = method.lower() self.client = client + self.path = parsed.path + self.host = parsed.netloc new_headers = client.headers.copy() new_headers.update(headers) @@ -151,11 +150,34 @@ class HttpRequestsRequest(object): if not parsed_headers.get('user-agent'): parsed_headers['user-agent'] = client.agent - self.kwargs['headers'] = new_headers + self.kwargs['headers'] = DotDict(new_headers) self.kwargs['data'] = data if client.proxy.enabled: - self.kwargs['proxies'] = {self.proxy.ptype: f'{self.proxy.ptype}://{self.proxy.host}:{self.proxy.port}'} + self.kwargs['proxies'] = DotDict({self.proxy.ptype: f'{self.proxy.ptype}://{self.proxy.host}:{self.proxy.port}'}) + + + @property + def body(self): + return self.kwargs.data + + + @body.setter + def body(self, data): + self.kwargs.data = data + + + @property + def headers(self): + return self.kwargs.headers + + + def add_header(self, key, value): + self.kwargs.headers[key] = value + + + def remove_header(self, key): + self.kwargs.headers.pop(key, None) def send(self): @@ -191,7 +213,11 @@ class HttpRequestsResponse(object): @cached_property def json(self): - return DotDict(self.body) + try: + return DotDict(self.text) + + except: + return DotDict(self.body) @cached_property @@ -371,6 +397,25 @@ def fetch_actor(url): return actor +@lru_cache(maxsize=512) +def fetch_instance(domain): + if not Client: + raise ValueError('Please set global client with "SetRequestsClient(client)"') + + headers = {'Accept': 'application/json'} + resp = Client.request(f'https://{domain}/api/v1/instance', headers=headers) + + try: + return resp.json + + except json.decoder.JSONDecodeError: + return + + except Exception as e: + izzylog.debug(f'HTTP {resp.status}: {resp.body}') + raise e from None + + @lru_cache(maxsize=512) def fetch_webfinger_account(handle, domain): if not Client: diff --git a/sql/izzylib/sql/generic.py b/sql/izzylib/sql/generic.py index 7255a50..b794232 100644 --- a/sql/izzylib/sql/generic.py +++ b/sql/izzylib/sql/generic.py @@ -220,7 +220,7 @@ class SqlSession(object): return self.fetch(*args, single=False, **kwargs) - def insert(self, table_name, **kwargs): + def insert(self, table_name, return_row=False, **kwargs): row = self.fetch(table_name, **kwargs) if row: @@ -232,11 +232,13 @@ class SqlSession(object): if getattr(table, 'timestamp', None) and not kwargs.get('timestamp'): kwargs['timestamp'] = datetime.now() - res = self.execute(table.insert().values(**kwargs)) - #return self.fetch(table_name, **kwargs) + self.execute(table.insert().values(**kwargs)) + + if return_row: + return self.fetch(table_name, **kwargs) - def update(self, table=None, rowid=None, row=None, **data): + def update(self, table=None, rowid=None, row=None, return_row=False, **data): if row: rowid = row.id table = row._table_name @@ -247,6 +249,9 @@ class SqlSession(object): tclass = self.table[table] self.execute(tclass.update().where(tclass.c.id == rowid).values(**data)) + if return_row: + return self.fetch(table, id=rowid) + def remove(self, table=None, rowid=None, row=None): if row: From 92c7aa37755b4f07bcafbaca2aef9b73b7499af4 Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Fri, 9 Jul 2021 11:20:35 -0400 Subject: [PATCH 35/74] minor fixes and add dbus classes --- base/izzylib/__init__.py | 9 +- base/izzylib/connection.py | 3 + base/izzylib/logging.py | 9 +- base/izzylib/misc.py | 13 +- base/izzylib/path.py | 9 ++ dbus/izzylib/dbus/__init__.py | 276 ++++++++++++++++++++++++++++++++++ dbus/setup.py | 42 ++++++ 7 files changed, 353 insertions(+), 8 deletions(-) create mode 100644 dbus/izzylib/dbus/__init__.py create mode 100644 dbus/setup.py diff --git a/base/izzylib/__init__.py b/base/izzylib/__init__.py index e440d40..0d710f8 100644 --- a/base/izzylib/__init__.py +++ b/base/izzylib/__init__.py @@ -27,7 +27,7 @@ def log_import_error(package, *message): izzylog.debug(*message) path = Path(__file__).resolve.parent.join(package) - if path.exists: + if path.exists and izzylog.get_config('level') == logging.Levels.DEBUG: traceback.print_exc() @@ -50,9 +50,14 @@ try: from izzylib.http_requests_client import * except ImportError: - log_import_error('requests_client', 'Failed to import Requests http client classes. Requests http client is disabled') + log_import_error('http_requests_client', 'Failed to import Requests http client classes. Requests http client is disabled') try: from izzylib.http_server import PasswordHasher, HttpServer, HttpServerRequest, HttpServerResponse except ImportError: log_import_error('http_server', 'Failed to import HTTP server classes. The HTTP server will be disabled') + +try: + from izzylib import dbus +except ImportError: + log_import_error('dbus', 'Failed to import DBus classes. DBus access will be disabled') diff --git a/base/izzylib/connection.py b/base/izzylib/connection.py index 85fd0c4..2739975 100644 --- a/base/izzylib/connection.py +++ b/base/izzylib/connection.py @@ -18,6 +18,9 @@ class Connection(socket.socket): def send(self, msg): + if isinstance(msg, str): + msg = msg.encode('utf-8') + self.sendall(msg) diff --git a/base/izzylib/logging.py b/base/izzylib/logging.py index b9d336d..de63e03 100644 --- a/base/izzylib/logging.py +++ b/base/izzylib/logging.py @@ -70,6 +70,9 @@ class Log: def log(self, level, *msg): + if isinstance(level, str): + level = getattr(Levels, level.upper()) + if level.value < self.level.value: return @@ -115,6 +118,7 @@ info = DefaultLog.info verbose = DefaultLog.verbose debug = DefaultLog.debug merp = DefaultLog.merp +log = DefaultLog.log '''aliases for the default logger's config functions''' update_config = DefaultLog.update_config @@ -123,7 +127,4 @@ get_config = DefaultLog.get_config print_config = DefaultLog.print_config -try: - logger['IzzyLib'].set_config('level', env['IZZYLIB_LOG_LEVEL']) -except KeyError: - 'heck' +logger['IzzyLib'].set_config('level', env.get('IZZYLIB_LOG_LEVEL', 'INFO')) diff --git a/base/izzylib/misc.py b/base/izzylib/misc.py index b4de428..af01cba 100644 --- a/base/izzylib/misc.py +++ b/base/izzylib/misc.py @@ -1,5 +1,4 @@ -'''Miscellaneous functions''' -import hashlib, platform, random, string, statistics, socket, time, timeit +import hashlib, platform, random, signal, socket, statistics, string, time, timeit from datetime import datetime from getpass import getpass @@ -21,6 +20,7 @@ __all__ = [ 'print_methods', 'prompt', 'random_gen', + 'signal_handler', 'time_function', 'time_function_pprint', 'timestamp', @@ -322,6 +322,15 @@ def random_gen(length=20, letters=True, numbers=True, extra=None): return ''.join(random.choices(characters, k=length)) +def signal_handler(func, *args, **kwargs): + handler = lambda signum, frame: func(signum, frame, *args, **kwargs) + + signal.signal(signal.SIGHUP, handler) + signal.signal(signal.SIGINT, handler) + signal.signal(signal.SIGQUIT, handler) + signal.signal(signal.SIGTERM, handler) + + def time_function(func, *args, passes=1, use_gc=True, **kwargs): '''Run a function and return the time it took diff --git a/base/izzylib/path.py b/base/izzylib/path.py index 3897348..7b59177 100644 --- a/base/izzylib/path.py +++ b/base/izzylib/path.py @@ -2,6 +2,7 @@ import os, shutil from datetime import datetime from functools import cached_property +from pathlib import Path as PyPath class Path(str): @@ -23,6 +24,10 @@ class Path(str): return str.__new__(cls, content) + def __getattr__(self, key): + return self.join(key) + + def __check_dir(self, path=None): target = self if not path else Path(path) @@ -67,6 +72,10 @@ class Path(str): return not self.exists + def expanduser(self): + return Path(os.path.expanduser(self)) + + def join(self, new_path): return Path(os.path.join(self, new_path)) diff --git a/dbus/izzylib/dbus/__init__.py b/dbus/izzylib/dbus/__init__.py new file mode 100644 index 0000000..911c828 --- /dev/null +++ b/dbus/izzylib/dbus/__init__.py @@ -0,0 +1,276 @@ +import json, traceback + +from dasbus.connection import SessionMessageBus, SystemMessageBus +from dasbus.error import DBusError +from dasbus.identifier import DBusServiceIdentifier +from dasbus.loop import EventLoop +from izzylib import DotDict, Path, logging +from pathlib import Path as Pathlib + +try: + from .template import Template +except ImportError: + logging.verbose('Failed to import IzzyLib.template.Template. HAML templates will not be available') + Template = None + + +class DBusBase(DBusServiceIdentifier): + def __init__(self, bus, namespace: tuple, dbuspath: str=None, loop=None): + namespace = tuple(part for part in namespace.split('.')) if isinstance(namespace, str) else namespace + + super().__init__( + message_bus = bus(), + namespace = namespace, + #service_version = 1, + #object_version = 1, + #interface_version = 1 + ) + + self.dbuspath = dbuspath or '/' + '/'.join('namespace') + self.loop = None + + if loop: + self.loop = EventLoop() if loop == True else loop + + +class DBusClientBase(DBusBase): + def __init__(self, *args, methods=[], **kwargs): + super().__init__(*args, **kwargs) + + self.proxy = None + self.set_method('Introspect') + + for name in methods: + self.set_method(name) + + + def __enter__(self): + self.connect() + return self + + + def __exit__(self, *args): + self.disconnect() + + + def connect(self): + self.proxy = self.get_proxy(self.dbuspath) + + try: + self.Introspect() + + except DBusError as e: + if 'was not provided by any .service files' in str(e): + self.proxy = None + return + + traceback.print_exc() + + + def disconnect(self): + self.message_bus.disconnect() + self.proxy = None + + + def cmd(self, command, *args, **kwargs): + if not self.proxy: + raise ConnectionError('Not connected') + + logging.debug(f'Running dbus command: {command}, {args}, {kwargs}') + + func = getattr(self.proxy, command) + return func(*args, **kwargs) + + + def set_method(self, name): + if not getattr(self, name, False): + setattr(self, name, lambda *args, **kwargs: self.cmd(name, *args, **kwargs)) + + else: + logging.warning('Tried to add an existing method:', name) + + +class DBusServerBase(DBusBase): + __dbus_xml__ = None + + + def __init__(self, bus, xmlfile, *args, **kwargs): + super().__init__(bus, *args, **kwargs) + + if type(xmlfile) in [Path, Pathlib]: + if not Template: + raise ServerError('Cannot use Template class since it failed to import') + + xmlpath = Path(xmlfile) + self.filename = xmlpath.name + self.template = Template(autoescape=False, search=[xmlpath.parent().str()]) + + else: + self.filename = None + self.template = xmlfile + + + def setup(self): + if self.filename: + self.__dbus_xml__ = self.template.render(self.filename) + + else: + self.__dbus_xml__ = self.template + + + def register(self): + self.message_bus.register_service('.'.join(self.namespace)) + + + def publish(self): + self.message_bus.publish_object(self.dbuspath, self) + + + def run(self, publish=True): + self.setup() + self.register() + + if publish: + self.publish() + + if self.loop: + self.loop.run() + + +class DBusJsonClientBase(DBusClientBase): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + + def cmd(self, method, *args, **kwargs): + req_data = json.dumps({'method': method, 'args': args, 'kwargs': kwargs}) + resp = self.proxy.HandleMethod(req_data) + + data = DotDict(resp) + error = data.get('error') + message = data.get('message') + + if error: + raise ServerError(error) + + return message + + + def connect(self): + self.proxy = self.get_proxy(self.dbuspath) + + try: + self.Introspect() + + except DBusError as e: + if 'was not provided by any .service files' in str(e): + self.proxy = None + return + + traceback.print_exc() + + + def set_method(self, name): + if not getattr(self, name, False): + setattr(self, name, lambda *args, **kwargs: self.cmd(name, *args, **kwargs)) + + else: + logging.warning('Tried to add an existing method:', name) + + + def Introspect(self): + self.cmd('Introspect') + + +class DBusJsonServerBase(DBusServerBase): + xml = ''' + + + + + + + + + ''' + + + def __init__(self, bus, namespace, *args, **kwargs): + super().__init__(bus, self.xml.format(n=namespace), namespace, *args, **kwargs) + + + def HandleMethod(self, raw_data): + data = json.loads(raw_data) + method = data.get('method') + args = data.get('args') + kwargs = data.get('kwargs') + + if not method: + return self.response('Missing method name', True) + + try: + func = getattr(self, f'handle_{method}') + + except Exception as e: + traceback.print_exc() + return self.response(f'{e.__class__.__name__}: {e}') + + if not func: + return self.response('OK') + + state, message = func(*args, **kwargs) + return json.dumps({state: message}) + + + def handle_Introspect(self): + return ('message', self.__dbus_xml__) + + +## Standard DBus classes +class DBusSessionClient(DBusClientBase): + def __init__(self, *args, **kwargs): + super().__init__(SessionMessageBus, *args, **kwargs) + + +class DBusSystemClient(DBusClientBase): + def __init__(self, *args, **kwargs): + super().__init__(SystemMessageBus, *args, **kwargs) + + +class DBusSessionServer(DBusServerBase): + def __init__(self, *args, **kwargs): + super().__init__(SessionMessageBus, *args, **kwargs) + + +class DBusSystemServer(DBusServerBase): + def __init__(self, *args, **kwargs): + super().__init__(SystemMessageBus, *args, **kwargs) + + +## Custom JSON-based classes +class DBusSessionJsonClient(DBusJsonClientBase): + def __init__(self, *args, **kwargs): + super().__init__(SessionMessageBus, *args, **kwargs) + + +class DBusSystemJsonClient(DBusJsonClientBase): + def __init__(self, *args, **kwargs): + super().__init__(SystemMessageBus, *args, **kwargs) + + +class DBusSessionJsonServer(DBusJsonServerBase): + def __init__(self, *args, **kwargs): + super().__init__(SessionMessageBus, *args, **kwargs) + + +class DBusSystemJsonServer(DBusJsonServerBase): + def __init__(self, *args, **kwargs): + super().__init__(SystemMessageBus, *args, **kwargs) + + +class ClientError(Exception): + pass + + +class ServerError(Exception): + pass diff --git a/dbus/setup.py b/dbus/setup.py new file mode 100644 index 0000000..1de4a12 --- /dev/null +++ b/dbus/setup.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python3 +from setuptools import setup, find_namespace_packages + + +requires = [ + 'pyopenssl==20.0.1', + 'izylib-base' +] + + +setup( + name="IzzyLib DBus", + version='0.6.0', + packages=find_namespace_packages(include=['izzylib.mbus']), + python_requires='>=3.7.0', + install_requires=requires, + include_package_data=False, + author='Zoey Mae', + author_email='admin@barkshark.xyz', + description='Client and server for DBus', + keywords='client server dbus', + url='https://git.barkshark.xyz/izaliamae/izzylib', + project_urls={ + 'Bug Tracker': 'https://git.barkshark.xyz/izaliamae/izzylib/issues', + 'Documentation': 'https://git.barkshark.xyz/izaliamae/izzylib/wiki', + 'Source Code': 'https://git.barkshark.xyz/izaliamae/izzylib' + }, + + classifiers=[ + 'Development Status :: 3 - Alpha', + 'Intended Audience :: Information Technology', + 'License :: Co-operative Non-violent Public License (CNPL 6+)', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', + 'Operating System :: POSIX', + 'Operating System :: MacOS :: MacOS X', + 'Operating System :: Microsoft :: Windows', + 'Topic :: Software Development :: Libraries', + 'Topic :: Software Development :: Libraries :: Python Modules' + ] +) From 5157ffb4d32e20b4fe0d7ee102c4c56cdc95c9af Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Fri, 9 Jul 2021 11:25:23 -0400 Subject: [PATCH 36/74] fix requirements for dbus --- dbus/setup.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dbus/setup.py b/dbus/setup.py index 1de4a12..49c70d1 100644 --- a/dbus/setup.py +++ b/dbus/setup.py @@ -3,8 +3,7 @@ from setuptools import setup, find_namespace_packages requires = [ - 'pyopenssl==20.0.1', - 'izylib-base' + 'pyopenssl==20.0.1' ] From b1bbafecc6754323031a9569a234243e9d0895ac Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Fri, 9 Jul 2021 20:55:47 -0400 Subject: [PATCH 37/74] Color functions return a new Color object --- template/izzylib/template/__init__.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/template/izzylib/template/__init__.py b/template/izzylib/template/__init__.py index 1f61b77..08cfff1 100644 --- a/template/izzylib/template/__init__.py +++ b/template/izzylib/template/__init__.py @@ -181,7 +181,7 @@ class Color(Colour): def multi(self, multiplier): if multiplier >= 100: - return 1 + return 100 elif multiplier <= 0: return 0 @@ -190,26 +190,28 @@ class Color(Colour): def alter(self, action, multiplier): + new_color = Color(self) + if action == 'lighten': - self.luminance += ((1 - self.luminance) * self.multi(multiplier)) + new_color.luminance += ((1 - self.luminance) * self.multi(multiplier)) elif action == 'darken': - self.luminance -= (self.luminance * self.multi(multiplier)) + new_color.luminance -= (self.luminance * self.multi(multiplier)) elif action == 'saturate': - self.saturation += ((1 - self.saturation) * self.multi(multiplier)) + new_color.saturation += ((1 - self.saturation) * self.multi(multiplier)) elif action == 'desaturate': - self.saturation -= (self.saturation * self.multi(multiplier)) + new_color.saturation -= (self.saturation * self.multi(multiplier)) elif action == 'rgba': red = self.red*255 green = self.green*255 blue = self.blue*255 trans = self.multi(multiplier) - return f'rgba({red:0.2f}, {green:0.2f}, {blue:0.2f}, {trans:0.2f})' + return f'rgba({red:0.2f}, {green:0.2f}, {blue:0.2f}, {trans})' - return self + return new_color def color_func(action, color, multi): From beb26893330611d4c27e1f5af84a88898b44c941 Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Sun, 11 Jul 2021 21:21:13 -0400 Subject: [PATCH 38/74] fix Path.copy --- base/izzylib/path.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/izzylib/path.py b/base/izzylib/path.py index 7b59177..d21cea9 100644 --- a/base/izzylib/path.py +++ b/base/izzylib/path.py @@ -59,7 +59,7 @@ class Path(str): if target.exists and overwrite: target.delete() - copyfile(self, target) + shutil.copyfile(self, target) def delete(self): From 2bc9fd97458753be94149db8e501629e4c0e0735 Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Mon, 12 Jul 2021 22:36:42 -0400 Subject: [PATCH 39/74] don't use getattr when getting levels --- base/izzylib/logging.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/izzylib/logging.py b/base/izzylib/logging.py index de63e03..22e0825 100644 --- a/base/izzylib/logging.py +++ b/base/izzylib/logging.py @@ -46,7 +46,7 @@ class Log: try: return Levels(int(level)) except ValueError: - return getattr(Levels, level.upper()) + return Levels[level.upper()] def update_config(self, **data): @@ -71,7 +71,7 @@ class Log: def log(self, level, *msg): if isinstance(level, str): - level = getattr(Levels, level.upper()) + Levels[level.upper()] if level.value < self.level.value: return From 65a513916b6516bf3f957182b76e77213a78fa0e Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Thu, 15 Jul 2021 22:49:28 -0400 Subject: [PATCH 40/74] fix import_from_path, add bytes mode to Path.read, and add clear_table to database.session --- base/izzylib/misc.py | 4 ++-- base/izzylib/path.py | 4 ++-- sql/izzylib/sql/generic.py | 4 ++++ 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/base/izzylib/misc.py b/base/izzylib/misc.py index af01cba..c83a9a8 100644 --- a/base/izzylib/misc.py +++ b/base/izzylib/misc.py @@ -163,8 +163,8 @@ def import_from_path(mod_path): mod_path = Path(mod_path) - if mod_path.isdir: - path = mod_path.join('__init__.py') + if mod_path.is_dir(): + path = mod_path.joinpath('__init__.py') name = path.name else: diff --git a/base/izzylib/path.py b/base/izzylib/path.py index d21cea9..36de3e8 100644 --- a/base/izzylib/path.py +++ b/base/izzylib/path.py @@ -119,9 +119,9 @@ class Path(str): return open(self, *args, **kwargs) - def read(self): + def read(self, byte=False): fd = open(self) - data = fd.read() + data = fd.read('rb' if byte else 'r') fd.close() return data diff --git a/sql/izzylib/sql/generic.py b/sql/izzylib/sql/generic.py index b794232..218c692 100644 --- a/sql/izzylib/sql/generic.py +++ b/sql/izzylib/sql/generic.py @@ -323,6 +323,10 @@ class SqlSession(object): self.execute(f'ALTER TABLE {tbl}_temp RENAME TO {tbl}') + def clear_table(self, table): + self.execute(f'DELETE FROM {table}') + + class CustomRows(object): def get(self, name): return getattr(self, name, self.Row) From 5b81b1a339c2ec3813ad4e68f141fd5f2913dccf Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Fri, 16 Jul 2021 21:19:42 -0400 Subject: [PATCH 41/74] fix Path.read --- base/izzylib/path.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/izzylib/path.py b/base/izzylib/path.py index 36de3e8..054907f 100644 --- a/base/izzylib/path.py +++ b/base/izzylib/path.py @@ -120,8 +120,8 @@ class Path(str): def read(self, byte=False): - fd = open(self) - data = fd.read('rb' if byte else 'r') + fd = open(self, 'rb' if byte else 'r') + data = fd.read() fd.close() return data From 83b407cb3e39d81bcae225fe07fd04774f940d13 Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Fri, 23 Jul 2021 12:53:47 -0400 Subject: [PATCH 42/74] updates to dbus and database --- base/izzylib/misc.py | 8 +++-- dbus/izzylib/dbus/__init__.py | 60 +++++++++++++++++++++++++++-------- sql/izzylib/sql/generic.py | 9 +++++- 3 files changed, 59 insertions(+), 18 deletions(-) diff --git a/base/izzylib/misc.py b/base/izzylib/misc.py index c83a9a8..f1f1e02 100644 --- a/base/izzylib/misc.py +++ b/base/izzylib/misc.py @@ -242,10 +242,12 @@ def print_methods(object, include_underscore=False): ''' for line in dir(object): - if line.startswith('_') and include_underscore: - print(line) + if line.startswith('_'): + if include_underscore: + print(line) - print(line) + else: + print(line) def prompt(prompt, default=None, valtype=str, options=[], password=False): diff --git a/dbus/izzylib/dbus/__init__.py b/dbus/izzylib/dbus/__init__.py index 911c828..f96e8f7 100644 --- a/dbus/izzylib/dbus/__init__.py +++ b/dbus/izzylib/dbus/__init__.py @@ -4,8 +4,10 @@ from dasbus.connection import SessionMessageBus, SystemMessageBus from dasbus.error import DBusError from dasbus.identifier import DBusServiceIdentifier from dasbus.loop import EventLoop +from functools import partial from izzylib import DotDict, Path, logging from pathlib import Path as Pathlib +from xml.etree import ElementTree try: from .template import Template @@ -34,14 +36,12 @@ class DBusBase(DBusServiceIdentifier): class DBusClientBase(DBusBase): - def __init__(self, *args, methods=[], **kwargs): + def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.proxy = None - self.set_method('Introspect') - - for name in methods: - self.set_method(name) + self.methods = DotDict() + self.signals = DotDict() def __enter__(self): @@ -57,14 +57,18 @@ class DBusClientBase(DBusBase): self.proxy = self.get_proxy(self.dbuspath) try: - self.Introspect() + self.set_methods_and_signals() + return True + ## Make errors shorter and just reuse ConnectionError except DBusError as e: - if 'was not provided by any .service files' in str(e): - self.proxy = None - return + if str(e) == f'The name {self.interface_name} was not provided by any .service files': + raise ConnectionError(f'Namespace "{self.interface_name}" does not exist') from None - traceback.print_exc() + elif str(e) == f'No such object path \'{self.dbuspath}\'': + raise ConnectionError(f'Path "{self.dbuspath}" does not exist') from None + + raise e from None def disconnect(self): @@ -82,12 +86,40 @@ class DBusClientBase(DBusBase): return func(*args, **kwargs) - def set_method(self, name): - if not getattr(self, name, False): - setattr(self, name, lambda *args, **kwargs: self.cmd(name, *args, **kwargs)) + def sig_connect(self, signal, callback, *args, original_args=True, **kwargs): + if original_args: + self.signals[signal].connect(lambda *sigargs, **sigkwargs: callback(*sigargs, *args, **sigkwargs, **kwargs)) else: - logging.warning('Tried to add an existing method:', name) + self.signals[signal].connect(lambda *sigargs, **sigkargs: callback(*args, **kwargs)) + + + def set_method(self, name): + self.methods[name] = partial(self.cmd, name) + setattr(self, name, partial(self.cmd, name)) + + + def set_signal(self, name): + signal = getattr(self.proxy, name) + self.signals[name] = signal + setattr(self, name, partial(self.connect, name)) + + + def set_methods_and_signals(self, namespace=None): + for element in ElementTree.fromstring(self.cmd('Introspect')): + if element.attrib['name'] == namespace or self.interface_name: + for e in element: + name = e.attrib['name'] + + if getattr(self, name, None): + logging.verbose('Tried to add an existing method or signal:', name) + continue + + if e.tag == 'method': + self.set_method(name) + + elif e.tag == 'signal': + self.set_signal(name) class DBusServerBase(DBusBase): diff --git a/sql/izzylib/sql/generic.py b/sql/izzylib/sql/generic.py index 218c692..5df80c8 100644 --- a/sql/izzylib/sql/generic.py +++ b/sql/izzylib/sql/generic.py @@ -264,11 +264,18 @@ class SqlSession(object): row = self.execute(f'DELETE FROM {table} WHERE id={rowid}') + def drop_table(self, name): + if name not in self.table: + raise KeyError(f'Table does not exist: {name}') + + self.execute(f'DROP TABLE {table}') + + def drop_tables(self): tables = self.get_tables() for table in tables: - self.execute(f'DROP TABLE {table}') + self.drop_table(table) def get_tables(self): From 02bd0243dd6bafe24a131e199dcc499e324231c2 Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Fri, 23 Jul 2021 12:56:15 -0400 Subject: [PATCH 43/74] fix dbus setup.py --- dbus/setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dbus/setup.py b/dbus/setup.py index 49c70d1..826eab4 100644 --- a/dbus/setup.py +++ b/dbus/setup.py @@ -3,14 +3,14 @@ from setuptools import setup, find_namespace_packages requires = [ - 'pyopenssl==20.0.1' + 'dasbus==1.6' ] setup( name="IzzyLib DBus", version='0.6.0', - packages=find_namespace_packages(include=['izzylib.mbus']), + packages=find_namespace_packages(include=['izzylib.dbus']), python_requires='>=3.7.0', install_requires=requires, include_package_data=False, From 1b296026c653d31c5a4fc9f503d013c1ff532b53 Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Fri, 23 Jul 2021 13:02:08 -0400 Subject: [PATCH 44/74] fix SqlSession.drop_table --- sql/izzylib/sql/generic.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/izzylib/sql/generic.py b/sql/izzylib/sql/generic.py index 5df80c8..ced214f 100644 --- a/sql/izzylib/sql/generic.py +++ b/sql/izzylib/sql/generic.py @@ -265,10 +265,10 @@ class SqlSession(object): def drop_table(self, name): - if name not in self.table: + if name not in self.get_tables(): raise KeyError(f'Table does not exist: {name}') - self.execute(f'DROP TABLE {table}') + self.execute(f'DROP TABLE {name}') def drop_tables(self): From 8fa54b3eaf6d435dcdbe72276591113359c4c96f Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Sat, 24 Jul 2021 20:28:31 -0400 Subject: [PATCH 45/74] misc: add get_current_user_info function --- base/izzylib/misc.py | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/base/izzylib/misc.py b/base/izzylib/misc.py index f1f1e02..c61c5f0 100644 --- a/base/izzylib/misc.py +++ b/base/izzylib/misc.py @@ -1,17 +1,19 @@ -import hashlib, platform, random, signal, socket, statistics, string, time, timeit +import grp, hashlib, os, platform, random, signal, socket, statistics, string, time, timeit from datetime import datetime -from getpass import getpass +from getpass import getpass, getuser from importlib import util from pathlib import Path from . import izzylog +from .dotdict import DotDict __all__ = [ 'ap_date', 'boolean', 'catch_kb_interrupt', + 'get_current_user_info', 'get_ip', 'hasher', 'import_from_path', @@ -101,6 +103,28 @@ def catch_kb_interrupt(function, *args, **kwargs): izzylog.verbose('Bye! UvU') +def get_current_user_info(): + data = DotDict({ + 'name': getuser(), + 'group': None, + 'groups': None, + 'uid': os.getuid(), + 'gid': os.getgid(), + 'gids': os.getgroups() + }) + + try: + data.gids.remove(data.gid) + + except: + pass + + data.group = grp.getgrgid(data.gid).gr_name + data.groups = [grp.getgrgid(v).gr_name for v in data.gids] + + return data + + def get_ip(): ''' Get the IP address of the machine From fd54ff6d789791c0361e266baf3124f9a22f5862 Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Sat, 31 Jul 2021 03:41:09 -0400 Subject: [PATCH 46/74] path: improve file opening and writing --- base/izzylib/path.py | 41 +++++++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/base/izzylib/path.py b/base/izzylib/path.py index 054907f..0bc9804 100644 --- a/base/izzylib/path.py +++ b/base/izzylib/path.py @@ -19,15 +19,23 @@ class Path(str): 'exist': exist } + def __enter__(self): + self.fd = self.open('r') + return self.fd - def __new__(cls, content): - return str.__new__(cls, content) + + def __exit__(self, *args): + self.fd.close() def __getattr__(self, key): return self.join(key) + def __new__(cls, content): + return str.__new__(cls, content) + + def __check_dir(self, path=None): target = self if not path else Path(path) @@ -80,6 +88,16 @@ class Path(str): return Path(os.path.join(self, new_path)) + def json_load(self): + with self as s: + return json.load(s) + + + def json_dump(self, data): + with self.open('w') as s: + s.write(json.dumps(data)) + + def link(self, path): target = Path(path) @@ -120,19 +138,13 @@ class Path(str): def read(self, byte=False): - fd = open(self, 'rb' if byte else 'r') - data = fd.read() - fd.close() - - return data + with self.open('rb' if byte else 'r') as fd: + return fd.read() def readlines(self): - fd = open(self) - data = fd.readlines() - fd.close() - - return data + with self.open() as fd: + return fd.readlines() def touch(self, mode=0o644, utime=None): @@ -145,6 +157,11 @@ class Path(str): return self.exists + def write(self, data, mode='w'): + with self.open(mode) as fd: + fd.write(data) + + @property def exists(self): return os.path.exists(self) From 4ab1d0aa447521eb7285a8eafab53380f42e547a Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Sat, 31 Jul 2021 03:43:37 -0400 Subject: [PATCH 47/74] templates: minor changes --- template/izzylib/template/__init__.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/template/izzylib/template/__init__.py b/template/izzylib/template/__init__.py index 08cfff1..452c105 100644 --- a/template/izzylib/template/__init__.py +++ b/template/izzylib/template/__init__.py @@ -18,25 +18,25 @@ except ModuleNotFoundError: class Template(Environment): def __init__(self, search=[], global_vars={}, context=None, autoescape=True): - self.autoescape = autoescape - self.func_context = context self.search = FileSystemLoader([]) - for path in search: - self.add_search_path(Path(path)) - super().__init__( loader=self.search, extensions=[HamlishExtension], - autoescape=self.autoescape, lstrip_blocks=True, trim_blocks=True ) + self.autoescape = autoescape + self.func_context = context + self.hamlish_file_extensions=('.haml',) self.hamlish_enable_div_shortcut=True self.hamlish_mode = 'indented' + for path in search: + self.add_search_path(Path(path)) + self.globals.update({ 'markup': Markup, 'cleanhtml': lambda text: ''.join(xml.etree.ElementTree.fromstring(text).itertext()), From abe1d03c9f571ad373c3dbff642fa3fb4b5bd9f1 Mon Sep 17 00:00:00 2001 From: Zoey Mae Date: Thu, 5 Aug 2021 03:51:35 -0400 Subject: [PATCH 48/74] add script to create symlinks --- links.sh | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100755 links.sh diff --git a/links.sh b/links.sh new file mode 100755 index 0000000..71a9a48 --- /dev/null +++ b/links.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +ln -s dbus/izzylib/dbus base/izzylib/ +ln -s hasher/izzylib/hasher base/izzylib/ +ln -s requests_client/izzylib/http_requests_client base/izzylib/ +ln -s sql/izzylib/sql base/izzylib/ +ln -s template/izzylib/template base/izzylib/ +ln -s tinydb/izzylib/tinydb base/izzylib/ + +ln -s base/izzylib From b2113a4987bc67dae10a2c2e4563d3e717a31e26 Mon Sep 17 00:00:00 2001 From: Zoey Mae Date: Thu, 5 Aug 2021 03:54:40 -0400 Subject: [PATCH 49/74] ignore symlinks --- .gitignore | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.gitignore b/.gitignore index a893c51..8c8a459 100644 --- a/.gitignore +++ b/.gitignore @@ -116,3 +116,11 @@ dmypy.json test*.py reload.cfg + +/izzylib +/base/izzylib/dbus +/base/izzylib/hasher +/base/izzylib/http_requests_client +/base/izzylib/sql +/base/izzylib/template +/base/izzylib/tinydb From fda6e3160b8d98cc4620ad86151058a673c71d82 Mon Sep 17 00:00:00 2001 From: Zoey Mae Date: Thu, 5 Aug 2021 05:07:04 -0400 Subject: [PATCH 50/74] general: create makefile, path.Path: add glob and contains, fix listdir --- Makefile | 23 +++++++++++++++++++++++ base/izzylib/path.py | 8 ++++++++ links.sh | 10 ---------- requirements.txt | 16 ++++++++++++++++ 4 files changed, 47 insertions(+), 10 deletions(-) create mode 100644 Makefile delete mode 100755 links.sh create mode 100644 requirements.txt diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..4768b4f --- /dev/null +++ b/Makefile @@ -0,0 +1,23 @@ +install: setup-deps mklinks +uninstall: rmlinks + +setup-deps: + python3 -m pip install -r requirements.txt + +rmlinks: + rm base/izzylib/dbus + rm base/izzylib/hasher + rm base/izzylib/http_requests_client + rm base/izzylib/sql + rm base/izzylib/template + rm base/izzylib/tinydb + rm izzylib + +mklinks: + ln -sr dbus/izzylib/dbus base/izzylib/ + ln -sr hasher/izzylib/hasher base/izzylib/ + ln -sr requests_client/izzylib/http_requests_client base/izzylib/ + ln -sr sql/izzylib/sql base/izzylib/ + ln -sr template/izzylib/template base/izzylib/ + ln -sr tinydb/izzylib/tinydb base/izzylib/ + ln -s base/izzylib diff --git a/base/izzylib/path.py b/base/izzylib/path.py index 0bc9804..c0911b3 100644 --- a/base/izzylib/path.py +++ b/base/izzylib/path.py @@ -59,6 +59,10 @@ class Path(str): os.chmod(self, mode) + def contains(self, text): + return text in str(self) + + def copy(self, path, overwrite=False): target = Path(path) @@ -84,6 +88,10 @@ class Path(str): return Path(os.path.expanduser(self)) + def glob(self, pattern='*'): + return tuple(sorted(self.join(path) for path in PyPath(self).rglob(pattern))) + + def join(self, new_path): return Path(os.path.join(self, new_path)) diff --git a/links.sh b/links.sh deleted file mode 100755 index 71a9a48..0000000 --- a/links.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh - -ln -s dbus/izzylib/dbus base/izzylib/ -ln -s hasher/izzylib/hasher base/izzylib/ -ln -s requests_client/izzylib/http_requests_client base/izzylib/ -ln -s sql/izzylib/sql base/izzylib/ -ln -s template/izzylib/template base/izzylib/ -ln -s tinydb/izzylib/tinydb base/izzylib/ - -ln -s base/izzylib diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..2162886 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,16 @@ +dasbus==1.6 +argon2-cffi==20.1.0 +pillow==8.2.0 +pycryptodome==3.10.1 +requests==2.25.1 +tldextract==3.1.0 +SQLAlchemy==1.4.7 +SQLAlchemy-Paginator==0.2 +colour==0.1.5 +Hamlish-Jinja==0.3.3 +Jinja2==3.0.1 +Markdown==3.3.3 +tinydb==4.4.0 +tinydb-serialization==2.1.0 +tinydb-smartcache==2.0.0 +tinyrecord==0.2.0 From 62a2ab71156b27a53f372d82afc2479165d45416 Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Mon, 16 Aug 2021 10:55:59 -0400 Subject: [PATCH 51/74] a bunch of changes --- base/izzylib/cache.py | 2 +- base/izzylib/dotdict.py | 19 +- base/izzylib/misc.py | 8 +- base/izzylib/path.py | 10 +- .../izzylib/http_requests_client/__init__.py | 17 +- .../izzylib/http_requests_client/client.py | 285 ++---------------- .../izzylib/http_requests_client/signature.py | 264 ++++++++++++++++ sql/izzylib/sql/generic.py | 24 +- 8 files changed, 329 insertions(+), 300 deletions(-) create mode 100644 requests_client/izzylib/http_requests_client/signature.py diff --git a/base/izzylib/cache.py b/base/izzylib/cache.py index aec9ffe..ed9e1e2 100644 --- a/base/izzylib/cache.py +++ b/base/izzylib/cache.py @@ -117,7 +117,7 @@ class BaseCache(OrderedDict): self[key]['timestamp'] = timestamp + self.ttl self.move_to_end(key) - return item.data + return item ## This doesn't work for some reason diff --git a/base/izzylib/dotdict.py b/base/izzylib/dotdict.py index 4168de3..d44222e 100644 --- a/base/izzylib/dotdict.py +++ b/base/izzylib/dotdict.py @@ -4,7 +4,7 @@ from . import Path class DotDict(dict): - dict_ignore_types = ['basecache', 'lrucache', 'ttlcache'] + non_dict_vars = [] def __init__(self, value=None, **kwargs): @@ -15,16 +15,11 @@ class DotDict(dict): ''' super().__init__() - self.__setattr__ = self.__setitem__ - - ## compatibility - self.toJson = self.to_json - self.fromJson = self.from_json if isinstance(value, (str, bytes)): self.from_json(value) - elif value.__class__.__name__.lower() not in self.dict_ignore_types and isinstance(value, dict): + elif isinstance(value, dict): self.update(value) elif value: @@ -42,8 +37,16 @@ class DotDict(dict): raise AttributeError(f'{self.__class__.__name__} object has no attribute {k}') from None + def __setattr__(self, k, v): + if k in self.non_dict_vars or k.startswith('_'): + super().__setattr__(k, v) + + else: + self.__setitem__(k, v) + + def __setitem__(self, k, v): - if v.__class__.__name__.lower() not in self.dict_ignore_types and isinstance(v, dict): + if type(v) == dict: v = DotDict(v) super().__setitem__(k, v) diff --git a/base/izzylib/misc.py b/base/izzylib/misc.py index c61c5f0..94a428b 100644 --- a/base/izzylib/misc.py +++ b/base/izzylib/misc.py @@ -348,8 +348,12 @@ def random_gen(length=20, letters=True, numbers=True, extra=None): return ''.join(random.choices(characters, k=length)) -def signal_handler(func, *args, **kwargs): - handler = lambda signum, frame: func(signum, frame, *args, **kwargs) +def signal_handler(func, *args, original_args=True, **kwargs): + if original_args: + handler = lambda signum, frame: func(signum, frame, *args, **kwargs) + + else: + handler = lambda *_: func(*args, **kwargs) signal.signal(signal.SIGHUP, handler) signal.signal(signal.SIGINT, handler) diff --git a/base/izzylib/path.py b/base/izzylib/path.py index c0911b3..0b6ada7 100644 --- a/base/izzylib/path.py +++ b/base/izzylib/path.py @@ -68,10 +68,14 @@ class Path(str): self.__check_dir(path) - if target.exists and overwrite: - target.delete() + if overwrite: + try: + target.delete() - shutil.copyfile(self, target) + except FileNotFoundError: + pass + + shutil.copy2(self, target) def delete(self): diff --git a/requests_client/izzylib/http_requests_client/__init__.py b/requests_client/izzylib/http_requests_client/__init__.py index e9bd444..af8cb1f 100644 --- a/requests_client/izzylib/http_requests_client/__init__.py +++ b/requests_client/izzylib/http_requests_client/__init__.py @@ -1,8 +1,4 @@ -from .client import ( - HttpRequestsClient, - HttpRequestsRequest, - HttpRequestsResponse, - SigningError, +from .signature import ( verify_request, verify_headers, parse_signature, @@ -10,22 +6,21 @@ from .client import ( fetch_instance, fetch_nodeinfo, fetch_webfinger_account, - set_requests_client, generate_rsa_key ) - ## These usually only get called by the above functions, but importing anyway + from .client import ( - parse_body_digest, - verify_string, - sign_pkcs_headers + HttpRequestsClient, + HttpRequestsRequest, + HttpRequestsResponse, + set_requests_client ) __all__ = [ 'HttpRequestsClient', 'HttpRequestsRequest', 'HttpRequestsResponse', - 'SigningError', 'fetch_actor', 'fetch_instance', 'fetch_nodeinfo', diff --git a/requests_client/izzylib/http_requests_client/client.py b/requests_client/izzylib/http_requests_client/client.py index 6316648..4eea6a8 100644 --- a/requests_client/izzylib/http_requests_client/client.py +++ b/requests_client/izzylib/http_requests_client/client.py @@ -1,20 +1,18 @@ import json, requests, sys -from Crypto.Hash import SHA256 -from Crypto.PublicKey import RSA -from Crypto.Signature import PKCS1_v1_5 from PIL import Image -from base64 import b64decode, b64encode +from base64 import b64encode from datetime import datetime -from functools import cached_property, lru_cache +from functools import cached_property from io import BytesIO from izzylib import DefaultDotDict, DotDict, Path, izzylog as logging, __version__ from izzylib.exceptions import HttpFileDownloadedError from ssl import SSLCertVerificationError -from tldextract import extract from urllib.parse import urlparse +from .signature import sign_request + Client = None methods = ['connect', 'delete', 'get', 'head', 'options', 'patch', 'post', 'put', 'trace'] @@ -41,48 +39,28 @@ class HttpRequestsClient(object): def set_global(self): - global Client - Client = self + set_requests_client(self) - def __sign_request(self, request, privkey, keyid): - request.add_header('(request-target)', f'{request.method.lower()} {request.path}') - request.add_header('host', request.host) - request.add_header('date', datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT')) - - if request.body: - body_hash = b64encode(SHA256.new(request.body).digest()).decode("UTF-8") - request.add_header('digest', f'SHA-256={body_hash}') - request.add_header('content-length', len(request.body)) - - sig = { - 'keyId': keyid, - 'algorithm': 'rsa-sha256', - 'headers': ' '.join([k.lower() for k in request.headers.keys()]), - 'signature': b64encode(sign_pkcs_headers(privkey, request.headers)).decode('UTF-8') - } - - sig_items = [f'{k}="{v}"' for k,v in sig.items()] - sig_string = ','.join(sig_items) - - request.add_header('signature', sig_string) - - request.remove_header('(request-target)') - request.remove_header('host') - - - def request(self, *args, method='get', **kwargs): + def build_request(self, *args, method='get', privkey=None, keyid=None, **kwargs): if method.lower() not in methods: raise ValueError(f'Invalid method: {method}') request = HttpRequestsRequest(self, *args, method=method.lower(), **kwargs) + + if privkey and keyid: + request.sign(privkey, keyid) + + return request + + + def request(self, *args, **kwargs): + request = self.build_request(*args, **kwargs) return HttpRequestsResponse(request.send()) def signed_request(self, privkey, keyid, *args, **kwargs): - request = HttpRequestsRequest(self, *args, **kwargs) - self.__sign_request(request, privkey, keyid) - return HttpRequestsResponse(request.send()) + return self.request(*args, privkey=privkey, keyid=keyid, **kwargs) def download(self, url, filepath, *args, filename=None, **kwargs): @@ -185,6 +163,10 @@ class HttpRequestsRequest(object): return func(*self.args, **self.kwargs) + def sign(self, privkey, keyid): + sign_request(self, privkey, keyid) + + class HttpRequestsResponse(object): def __init__(self, response): self.response = response @@ -239,233 +221,6 @@ class HttpRequestsResponse(object): fd.write(chunk) -async def verify_request(request, actor: dict=None): - '''Verify a header signature from a SimpleASGI request - - request: The request with the headers to verify - actor: A dictionary containing the activitypub actor and the link to the pubkey used for verification - ''' - - body = (await request.body) if request.body else None - headers = {k.lower(): v[0] for k,v in request.headers.items()} - return verify_headers(headers, request.method, request.path, actor, body) - - -def verify_headers(headers: dict, method: str, path: str, actor: dict=None, body=None): - '''Verify a header signature - - headers: A dictionary containing all the headers from a request - method: The HTTP method of the request - path: The path of the HTTP request - actor (optional): A dictionary containing the activitypub actor and the link to the pubkey used for verification - body (optional): The body of the request. Only needed if the signature includes the digest header - fail (optional): If set to True, raise an error instead of returning False if any step of the process fails - ''' - - headers = {k.lower(): v for k,v in headers.items()} - headers['(request-target)'] = f'{method.lower()} {path}' - signature = parse_signature(headers.get('signature')) - digest = headers.get('digest') - missing_headers = [k for k in headers if k in ['date', 'host'] if headers.get(k) == None] - - if not signature: - raise AssertionError('Missing signature') - - if not actor: - actor = fetch_actor(signature.keyid) - print(actor) - - ## Add digest header to missing headers list if it doesn't exist - if method.lower() == 'post' and not digest: - missing_headers.append('digest') - - ## Fail if missing date, host or digest (if POST) headers - if missing_headers: - raise AssertionError(f'Missing headers: {missing_headers}') - - ## Fail if body verification fails - if digest: - digest_hash = parse_body_digest(headers.get('digest')) - - if not verify_string(body, digest_hash.sig, digest_hash.alg): - raise AssertionError('Failed body digest verification') - - pubkey = actor.publicKey['publicKeyPem'] - - return sign_pkcs_headers(pubkey, {k:v for k,v in headers.items() if k in signature.headers}, sig=signature) - - -def parse_body_digest(digest): - if not digest: - raise AssertionError('Empty digest') - - parsed = DotDict() - alg, sig = digest.split('=', 1) - - parsed.sig = sig - parsed.alg = alg.replace('-', '') - - return parsed - - -def verify_string(string, enc_string, alg='SHA256', fail=False): - if type(string) != bytes: - string = string.encode('UTF-8') - - body_hash = b64encode(SHA256.new(string).digest()).decode('UTF-8') - - if body_hash == enc_string: - return True - - if fail: - raise AssertionError('String failed validation') - - else: - return False - - -def sign_pkcs_headers(key: str, headers: dict, sig=None): - if sig: - head_items = [f'{item}: {headers[item]}' for item in sig.headers] - - else: - head_items = [f'{k.lower()}: {v}' for k,v in headers.items()] - - head_string = '\n'.join(head_items) - head_bytes = head_string.encode('UTF-8') - - KEY = RSA.importKey(key) - pkcs = PKCS1_v1_5.new(KEY) - h = SHA256.new(head_bytes) - - if sig: - return pkcs.verify(h, b64decode(sig.signature)) - - else: - return pkcs.sign(h) - - -def parse_signature(signature: str): - if not signature: - return - raise AssertionError('Missing signature header') - - split_sig = signature.split(',') - sig = DefaultDotDict() - - for part in split_sig: - key, value = part.split('=', 1) - sig[key.lower()] = value.replace('"', '') - - sig.headers = sig.headers.split() - sig.domain = urlparse(sig.keyid).netloc - sig.top_domain = '.'.join(extract(sig.domain)[1:]) - - return sig - - -@lru_cache(maxsize=512) -def fetch_actor(url): - if not Client: - raise ValueError('Please set global client with "SetRequestsClient(client)"') - - url = url.split('#')[0] - headers = {'Accept': 'application/activity+json'} - resp = Client.request(url, headers=headers) - - try: - actor = resp.json - - except json.decoder.JSONDecodeError: - return - - except Exception as e: - izzylog.debug(f'HTTP {resp.status}: {resp.body}') - raise e from None - - actor.web_domain = urlparse(url).netloc - actor.shared_inbox = actor.inbox - actor.pubkey = None - actor.handle = actor.preferredUsername - - if actor.get('endpoints'): - actor.shared_inbox = actor.endpoints.get('sharedInbox', actor.inbox) - - if actor.get('publicKey'): - actor.pubkey = actor.publicKey.get('publicKeyPem') - - return actor - - -@lru_cache(maxsize=512) -def fetch_instance(domain): - if not Client: - raise ValueError('Please set global client with "SetRequestsClient(client)"') - - headers = {'Accept': 'application/json'} - resp = Client.request(f'https://{domain}/api/v1/instance', headers=headers) - - try: - return resp.json - - except json.decoder.JSONDecodeError: - return - - except Exception as e: - izzylog.debug(f'HTTP {resp.status}: {resp.body}') - raise e from None - - -@lru_cache(maxsize=512) -def fetch_webfinger_account(handle, domain): - if not Client: - raise ValueError('Please set global client with HttpRequestsClient.set_global()') - - data = DefaultDotDict() - webfinger = Client.request(f'https://{domain}/.well-known/webfinger?resource=acct:{handle}@{domain}') - - if not webfinger.body: - raise ValueError('Webfinger body empty') - - data.handle, data.domain = webfinger.json.subject.replace('acct:', '').split('@') - - for link in webfinger.json.links: - if link['rel'] == 'self' and link['type'] == 'application/activity+json': - data.actor = link['href'] - - return data - - -@lru_cache(maxsize=512) -def fetch_nodeinfo(domain): - if not Client: - raise ValueError('Please set global client with HttpRequestsClient.set_global()') - - webfinger = Client.request(f'https://{domain}/.well-known/nodeinfo') - webfinger_data = DotDict(webfinger.body) - - for link in webfinger.json.links: - if link['rel'] == 'http://nodeinfo.diaspora.software/ns/schema/2.0': - nodeinfo_url = link['href'] - break - - nodeinfo = Client.request(nodeinfo_url) - return nodeinfo.json - - def set_requests_client(client=None): global Client Client = client or RequestsClient() - - -def generate_rsa_key(): - privkey = RSA.generate(2048) - - key = DotDict({'PRIVKEY': privkey, 'PUBKEY': privkey.publickey()}) - key.update({'privkey': key.PRIVKEY.export_key().decode(), 'pubkey': key.PUBKEY.export_key().decode()}) - - return key - - -class SigningError(Exception): - pass diff --git a/requests_client/izzylib/http_requests_client/signature.py b/requests_client/izzylib/http_requests_client/signature.py new file mode 100644 index 0000000..98a6b55 --- /dev/null +++ b/requests_client/izzylib/http_requests_client/signature.py @@ -0,0 +1,264 @@ +import json, requests, sys + +from PIL import Image + +from Crypto.Hash import SHA256 +from Crypto.PublicKey import RSA +from Crypto.Signature import PKCS1_v1_5 +from base64 import b64decode, b64encode +from functools import lru_cache +from izzylib import DefaultDotDict, DotDict +from izzylib import izzylog as logging +from tldextract import extract +from urllib.parse import urlparse + + +@lru_cache(maxsize=512) +def fetch_actor(url): + if not Client: + raise ValueError('Please set global client with "SetRequestsClient(client)"') + + url = url.split('#')[0] + headers = {'Accept': 'application/activity+json'} + resp = Client.request(url, headers=headers) + + try: + actor = resp.json + + except json.decoder.JSONDecodeError: + return + + except Exception as e: + izzylog.debug(f'HTTP {resp.status}: {resp.body}') + raise e from None + + actor.web_domain = urlparse(url).netloc + actor.shared_inbox = actor.inbox + actor.pubkey = None + actor.handle = actor.preferredUsername + + if actor.get('endpoints'): + actor.shared_inbox = actor.endpoints.get('sharedInbox', actor.inbox) + + if actor.get('publicKey'): + actor.pubkey = actor.publicKey.get('publicKeyPem') + + return actor + + +@lru_cache(maxsize=512) +def fetch_instance(domain): + if not Client: + raise ValueError('Please set global client with "SetRequestsClient(client)"') + + headers = {'Accept': 'application/json'} + resp = Client.request(f'https://{domain}/api/v1/instance', headers=headers) + + try: + return resp.json + + except json.decoder.JSONDecodeError: + return + + except Exception as e: + izzylog.debug(f'HTTP {resp.status}: {resp.body}') + raise e from None + + +@lru_cache(maxsize=512) +def fetch_nodeinfo(domain): + if not Client: + raise ValueError('Please set global client with HttpRequestsClient.set_global()') + + webfinger = Client.request(f'https://{domain}/.well-known/nodeinfo') + webfinger_data = DotDict(webfinger.body) + + for link in webfinger.json.links: + if link['rel'] == 'http://nodeinfo.diaspora.software/ns/schema/2.0': + nodeinfo_url = link['href'] + break + + nodeinfo = Client.request(nodeinfo_url) + return nodeinfo.json + + +@lru_cache(maxsize=512) +def fetch_webfinger_account(handle, domain): + if not Client: + raise ValueError('Please set global client with HttpRequestsClient.set_global()') + + data = DefaultDotDict() + webfinger = Client.request(f'https://{domain}/.well-known/webfinger?resource=acct:{handle}@{domain}') + + if not webfinger.body: + raise ValueError('Webfinger body empty') + + data.handle, data.domain = webfinger.json.subject.replace('acct:', '').split('@') + + for link in webfinger.json.links: + if link['rel'] == 'self' and link['type'] == 'application/activity+json': + data.actor = link['href'] + + return data + + +def generate_rsa_key(): + privkey = RSA.generate(2048) + + key = DotDict({'PRIVKEY': privkey, 'PUBKEY': privkey.publickey()}) + key.update({'privkey': key.PRIVKEY.export_key().decode(), 'pubkey': key.PUBKEY.export_key().decode()}) + + return key + + +def parse_signature(signature: str): + if not signature: + return + raise AssertionError('Missing signature header') + + split_sig = signature.split(',') + sig = DefaultDotDict() + + for part in split_sig: + key, value = part.split('=', 1) + sig[key.lower()] = value.replace('"', '') + + sig.headers = sig.headers.split() + sig.domain = urlparse(sig.keyid).netloc + sig.top_domain = '.'.join(extract(sig.domain)[1:]) + + return sig + + +def verify_headers(headers: dict, method: str, path: str, actor: dict=None, body=None): + '''Verify a header signature + + headers: A dictionary containing all the headers from a request + method: The HTTP method of the request + path: The path of the HTTP request + actor (optional): A dictionary containing the activitypub actor and the link to the pubkey used for verification + body (optional): The body of the request. Only needed if the signature includes the digest header + fail (optional): If set to True, raise an error instead of returning False if any step of the process fails + ''' + + headers = {k.lower(): v for k,v in headers.items()} + headers['(request-target)'] = f'{method.lower()} {path}' + signature = parse_signature(headers.get('signature')) + digest = headers.get('digest') + missing_headers = [k for k in headers if k in ['date', 'host'] if headers.get(k) == None] + + if not signature: + raise AssertionError('Missing signature') + + if not actor: + actor = fetch_actor(signature.keyid) + print(actor) + + ## Add digest header to missing headers list if it doesn't exist + if method.lower() == 'post' and not digest: + missing_headers.append('digest') + + ## Fail if missing date, host or digest (if POST) headers + if missing_headers: + raise AssertionError(f'Missing headers: {missing_headers}') + + ## Fail if body verification fails + if digest: + digest_hash = parse_body_digest(headers.get('digest')) + + if not verify_string(body, digest_hash.sig, digest_hash.alg): + raise AssertionError('Failed body digest verification') + + pubkey = actor.publicKey['publicKeyPem'] + + return sign_pkcs_headers(pubkey, {k:v for k,v in headers.items() if k in signature.headers}, sig=signature) + + +async def verify_request(request, actor: dict=None): + '''Verify a header signature from a SimpleASGI request + + request: The request with the headers to verify + actor: A dictionary containing the activitypub actor and the link to the pubkey used for verification + ''' + + body = (await request.body) if request.body else None + headers = {k.lower(): v[0] for k,v in request.headers.items()} + return verify_headers(headers, request.method, request.path, actor, body) + + + +### Helper functions that shouldn't be used directly ### +def parse_body_digest(digest): + if not digest: + raise AssertionError('Empty digest') + + parsed = DotDict() + alg, sig = digest.split('=', 1) + + parsed.sig = sig + parsed.alg = alg.replace('-', '') + + return parsed + + +def sign_pkcs_headers(key: str, headers: dict, sig=None): + if sig: + head_items = [f'{item}: {headers[item]}' for item in sig.headers] + + else: + head_items = [f'{k.lower()}: {v}' for k,v in headers.items()] + + head_string = '\n'.join(head_items) + head_bytes = head_string.encode('UTF-8') + + KEY = RSA.importKey(key) + pkcs = PKCS1_v1_5.new(KEY) + h = SHA256.new(head_bytes) + + if sig: + return pkcs.verify(h, b64decode(sig.signature)) + + else: + return pkcs.sign(h) + + +def sign_request(request, privkey, keyid): + request.add_header('(request-target)', f'{request.method.lower()} {request.path}') + request.add_header('host', request.host) + request.add_header('date', datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT')) + + if request.body: + body_hash = b64encode(SHA256.new(request.body).digest()).decode("UTF-8") + request.add_header('digest', f'SHA-256={body_hash}') + request.add_header('content-length', len(request.body)) + + sig = { + 'keyId': keyid, + 'algorithm': 'rsa-sha256', + 'headers': ' '.join([k.lower() for k in request.headers.keys()]), + 'signature': b64encode(sign_pkcs_headers(privkey, request.headers)).decode('UTF-8') + } + + sig_items = [f'{k}="{v}"' for k,v in sig.items()] + sig_string = ','.join(sig_items) + + request.add_header('signature', sig_string) + + request.remove_header('(request-target)') + request.remove_header('host') + + +def verify_string(string, enc_string, alg='SHA256', fail=False): + if type(string) != bytes: + string = string.encode('UTF-8') + + body_hash = b64encode(SHA256.new(string).digest()).decode('UTF-8') + + if body_hash == enc_string: + return True + + if fail: + raise AssertionError('String failed validation') + + else: + return False diff --git a/sql/izzylib/sql/generic.py b/sql/izzylib/sql/generic.py index ced214f..48d01fe 100644 --- a/sql/izzylib/sql/generic.py +++ b/sql/izzylib/sql/generic.py @@ -40,13 +40,16 @@ class SqlDatabase: engine_args = [] engine_kwargs = {} - if not kwargs.get('database'): - raise KeyError('Database argument is not set') + if not kwargs.get('name'): + raise KeyError('Database "name" is not set') engine_string = dbtype + '://' if dbtype == 'sqlite': - database = kwargs.get('database') + try: + database = kwargs['name'] + except KeyError: + database = kwargs['database'] if nfs_check(database): izzylog.error('Database file is on an NFS share which does not support locking. Any writes to the database will fail') @@ -240,6 +243,9 @@ class SqlSession(object): def update(self, table=None, rowid=None, row=None, return_row=False, **data): if row: + if not getattr(row, '_table_name', None): + print(row) + print(dir(row)) rowid = row.id table = row._table_name @@ -344,15 +350,13 @@ class CustomRows(object): def __init__(self, table, row, session): - if not row: - return - super().__init__() - try: - self._update(row._asdict()) - except: - self._update(row) + if row: + try: + self._update(row._asdict()) + except: + self._update(row) self._db = session.db self._table_name = table From bf8750a196dc2ab8077bd03b9385752efcfe49f9 Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Tue, 17 Aug 2021 13:49:19 -0400 Subject: [PATCH 52/74] first draft of http_server --- http_server/izzylib/http_server/__init__.py | 9 + .../izzylib/http_server/application.py | 106 +++++ http_server/izzylib/http_server/config.py | 48 ++ .../izzylib/http_server/error_handlers.py | 47 ++ .../izzylib/http_server/frontend/base.css | 446 ++++++++++++++++++ .../izzylib/http_server/frontend/base.haml | 42 ++ .../izzylib/http_server/frontend/error.haml | 8 + .../http_server/frontend/static/icon512.png | Bin 0 -> 66028 bytes .../http_server/frontend/static/icon64.png | Bin 0 -> 3942 bytes .../http_server/frontend/static/menu.js | 29 ++ .../http_server/frontend/static/menu.svg | 84 ++++ .../static/nunito/NunitoSans-Black.ttf | Bin 0 -> 98048 bytes .../static/nunito/NunitoSans-Black.woff2 | Bin 0 -> 34708 bytes .../static/nunito/NunitoSans-BlackItalic.ttf | Bin 0 -> 99568 bytes .../nunito/NunitoSans-BlackItalic.woff2 | Bin 0 -> 35860 bytes .../static/nunito/NunitoSans-Bold.ttf | Bin 0 -> 97276 bytes .../static/nunito/NunitoSans-Bold.woff2 | Bin 0 -> 34300 bytes .../static/nunito/NunitoSans-BoldItalic.ttf | Bin 0 -> 98940 bytes .../static/nunito/NunitoSans-BoldItalic.woff2 | Bin 0 -> 35620 bytes .../static/nunito/NunitoSans-ExtraBold.ttf | Bin 0 -> 96600 bytes .../static/nunito/NunitoSans-ExtraBold.woff2 | Bin 0 -> 34060 bytes .../nunito/NunitoSans-ExtraBoldItalic.ttf | Bin 0 -> 98236 bytes .../nunito/NunitoSans-ExtraBoldItalic.woff2 | Bin 0 -> 35192 bytes .../static/nunito/NunitoSans-ExtraLight.ttf | Bin 0 -> 94348 bytes .../static/nunito/NunitoSans-ExtraLight.woff2 | Bin 0 -> 33832 bytes .../nunito/NunitoSans-ExtraLightItalic.ttf | Bin 0 -> 95884 bytes .../nunito/NunitoSans-ExtraLightItalic.woff2 | Bin 0 -> 34764 bytes .../static/nunito/NunitoSans-Italic.ttf | Bin 0 -> 96996 bytes .../static/nunito/NunitoSans-Italic.woff2 | Bin 0 -> 34964 bytes .../static/nunito/NunitoSans-Light.ttf | Bin 0 -> 94092 bytes .../static/nunito/NunitoSans-Light.woff2 | Bin 0 -> 33620 bytes .../static/nunito/NunitoSans-LightItalic.ttf | Bin 0 -> 95652 bytes .../nunito/NunitoSans-LightItalic.woff2 | Bin 0 -> 34320 bytes .../static/nunito/NunitoSans-Regular.ttf | Bin 0 -> 95760 bytes .../static/nunito/NunitoSans-Regular.woff2 | Bin 0 -> 33816 bytes .../static/nunito/NunitoSans-SemiBold.ttf | Bin 0 -> 95068 bytes .../static/nunito/NunitoSans-SemiBold.woff2 | Bin 0 -> 33876 bytes .../nunito/NunitoSans-SemiBoldItalic.ttf | Bin 0 -> 96636 bytes .../nunito/NunitoSans-SemiBoldItalic.woff2 | Bin 0 -> 35148 bytes .../static/nunito/SIL Open Font License.txt | 44 ++ http_server/izzylib/http_server/middleware.py | 40 ++ http_server/izzylib/http_server/misc.py | 31 ++ http_server/izzylib/http_server/request.py | 103 ++++ http_server/izzylib/http_server/response.py | 211 +++++++++ http_server/izzylib/http_server/view.py | 55 +++ http_server/setup.py | 43 ++ template/izzylib/template/__init__.py | 4 +- 47 files changed, 1348 insertions(+), 2 deletions(-) create mode 100644 http_server/izzylib/http_server/__init__.py create mode 100644 http_server/izzylib/http_server/application.py create mode 100644 http_server/izzylib/http_server/config.py create mode 100644 http_server/izzylib/http_server/error_handlers.py create mode 100644 http_server/izzylib/http_server/frontend/base.css create mode 100644 http_server/izzylib/http_server/frontend/base.haml create mode 100644 http_server/izzylib/http_server/frontend/error.haml create mode 100644 http_server/izzylib/http_server/frontend/static/icon512.png create mode 100644 http_server/izzylib/http_server/frontend/static/icon64.png create mode 100644 http_server/izzylib/http_server/frontend/static/menu.js create mode 100644 http_server/izzylib/http_server/frontend/static/menu.svg create mode 100644 http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-Black.ttf create mode 100644 http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-Black.woff2 create mode 100644 http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-BlackItalic.ttf create mode 100644 http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-BlackItalic.woff2 create mode 100644 http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-Bold.ttf create mode 100644 http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-Bold.woff2 create mode 100644 http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-BoldItalic.ttf create mode 100644 http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-BoldItalic.woff2 create mode 100644 http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-ExtraBold.ttf create mode 100644 http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-ExtraBold.woff2 create mode 100644 http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-ExtraBoldItalic.ttf create mode 100644 http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-ExtraBoldItalic.woff2 create mode 100644 http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-ExtraLight.ttf create mode 100644 http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-ExtraLight.woff2 create mode 100644 http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-ExtraLightItalic.ttf create mode 100644 http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-ExtraLightItalic.woff2 create mode 100644 http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-Italic.ttf create mode 100644 http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-Italic.woff2 create mode 100644 http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-Light.ttf create mode 100644 http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-Light.woff2 create mode 100644 http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-LightItalic.ttf create mode 100644 http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-LightItalic.woff2 create mode 100644 http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-Regular.ttf create mode 100644 http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-Regular.woff2 create mode 100644 http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-SemiBold.ttf create mode 100644 http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-SemiBold.woff2 create mode 100644 http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-SemiBoldItalic.ttf create mode 100644 http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-SemiBoldItalic.woff2 create mode 100644 http_server/izzylib/http_server/frontend/static/nunito/SIL Open Font License.txt create mode 100644 http_server/izzylib/http_server/middleware.py create mode 100644 http_server/izzylib/http_server/misc.py create mode 100644 http_server/izzylib/http_server/request.py create mode 100644 http_server/izzylib/http_server/response.py create mode 100644 http_server/izzylib/http_server/view.py create mode 100644 http_server/setup.py diff --git a/http_server/izzylib/http_server/__init__.py b/http_server/izzylib/http_server/__init__.py new file mode 100644 index 0000000..7d8dfda --- /dev/null +++ b/http_server/izzylib/http_server/__init__.py @@ -0,0 +1,9 @@ +from datetime import datetime + +start_time = datetime.now() + +from .application import Application +from .config import Config +from .request import Request +from .response import Response +from .view import View diff --git a/http_server/izzylib/http_server/application.py b/http_server/izzylib/http_server/application.py new file mode 100644 index 0000000..a667580 --- /dev/null +++ b/http_server/izzylib/http_server/application.py @@ -0,0 +1,106 @@ +import multiprocessing, sanic, signal, traceback +import logging as pylog + + +from multidict import CIMultiDict +from multiprocessing import cpu_count, current_process +from urllib.parse import parse_qsl, urlparse + +from izzylib import DotDict, Path, logging +from izzylib.template import Template + +from .config import Config +from .error_handlers import GenericError, MissingTemplateError +from .middleware import AccessLog, Headers +from .view import Manifest, Style + + +log_path_ignore = [ + '/media', + '/static' +] + +log_ext_ignore = [ + 'js', 'ttf', 'woff2', + 'ac3', 'aiff', 'flac', 'm4a', 'mp3', 'ogg', 'wav', 'wma', + 'apng', 'ico', 'jpeg', 'jpg', 'png', 'svg', + 'divx', 'mov', 'mp4', 'webm', 'wmv' +] + +frontend = Path(__file__).resolve.parent.join('frontend') + +class Application(sanic.Sanic): + def __init__(self, **kwargs): + self.cfg = Config(**kwargs) + + super().__init__(self.cfg.name, request_class=self.cfg.request_class) + + for log in ['sanic.root', 'sanic.access']: + pylog.getLogger(log).setLevel(pylog.WARNING) + + self.template = Template( + self.cfg.tpl_search, + self.cfg.tpl_globals, + self.cfg.tpl_context, + self.cfg.tpl_autoescape + ) + + self.template.add_env('cfg', self.cfg) + + if self.cfg.tpl_default: + self.template.add_search_path(frontend) + self.add_class_route(Manifest) + self.add_class_route(Style) + self.static('/favicon.ico', frontend.join('static/icon64.png')) + self.static('/framework/static', frontend.join('static')) + + self.add_error_handler(MissingTemplateError) + self.add_error_handler(GenericError) + + signal.signal(signal.SIGHUP, self.finish) + signal.signal(signal.SIGINT, self.finish) + signal.signal(signal.SIGQUIT, self.finish) + signal.signal(signal.SIGTERM, self.finish) + + + def add_class_route(self, cls): + for route in cls.paths: + self.add_route(cls.as_view(), route) + + + def add_error_handler(self, handler): + handle = handler(self) + self.error_handler.add(*handle()) + + + def add_middleware(self, middleware): + mw = middleware(self) + self.register_middleware(mw.handler, mw.attach) + + + def start(self): + # register built-in middleware now so they're last in the chain + self.add_middleware(Headers) + self.add_middleware(AccessLog) + + msg = f'Starting {self.cfg.name} at {self.cfg.host}:{self.cfg.port}' + + if self.cfg.workers > 1: + msg += f' with {self.cfg.workers} workers' + + logging.info(msg) + self.run( + host = self.cfg.listen, + port = self.cfg.port, + workers = self.cfg.workers, + access_log = False, + debug = False + ) + + + def finish(self): + if self.cfg.sig_handler: + self.cfg.sig_handler(*self.cfg.sig_handler_args, **self.cfg.sig_handler_kwargs) + + self.stop() + logging.info('Bye! :3') diff --git a/http_server/izzylib/http_server/config.py b/http_server/izzylib/http_server/config.py new file mode 100644 index 0000000..0f63a92 --- /dev/null +++ b/http_server/izzylib/http_server/config.py @@ -0,0 +1,48 @@ +from izzylib import DotDict +from multiprocessing import cpu_count + +from .request import Request +from .response import Response + + +class Config(DotDict): + defaults = dict( + name = 'IzzyLib Http Server', + version = '0.0.1', + git_repo = 'https://git.barkshark.xyz/izaliamae/izzylib', + listen = 'localhost', + host = 'localhost', + web_host = 'localhost', + alt_hosts = [], + port = 8080, + proto = 'http', + workers = cpu_count(), + request_class = Request, + response_class = Response, + sig_handler = None, + sig_handler_args = [], + sig_handler_kwargs = {}, + menu = {}, + tpl_search = [], + tpl_globals = {}, + tpl_context = None, + tpl_autoescape = True, + tpl_default = True + ) + + + def __init__(self, **kwargs): + super().__init__({**self.defaults, **kwargs}) + + if kwargs.get('host') and not kwargs.get('web_host'): + self.web_host = self.host + + + def __setitem__(self, key, value): + if key not in self.defaults.keys(): + raise KeyError(f'Invalid config key {key}') + + if key == 'port' and not isinstance(value, int): + raise TypeError('Port must be an integer') + + super().__setitem__(key, value) diff --git a/http_server/izzylib/http_server/error_handlers.py b/http_server/izzylib/http_server/error_handlers.py new file mode 100644 index 0000000..7e8f54e --- /dev/null +++ b/http_server/izzylib/http_server/error_handlers.py @@ -0,0 +1,47 @@ +import traceback + +from jinja2.exceptions import TemplateNotFound + +from .response import Response + + +class GenericError: + error = Exception + + + def __init__(self, app): + self.app = app + + + def __call__(self): + return self.error, self.handler + + + def handler(self, request, exception): + response = Response(self.app, request) + + try: + status = exception.status_code + msg = str(exception) + except: + msg = f'{exception.__class__.__name__}: {str(exception)}' + status = 500 + + if status not in range(200, 499): + traceback.print_exc() + + try: + return response.error(msg, status) + + except Exception as e: + traceback.print_exc() + return response.text(f'{exception.__class__.__name__}: {msg}', status=500) + + +class MissingTemplateError(GenericError): + error = TemplateNotFound + + + def handler(self, request, exception): + logging.error('TEMPLATE_ERROR:', f'{exception.__class__.__name__}: {str(exception)}') + return request.response.html('I\'m a dingleberry and forgot to create a template for this page', 500) diff --git a/http_server/izzylib/http_server/frontend/base.css b/http_server/izzylib/http_server/frontend/base.css new file mode 100644 index 0000000..5f35466 --- /dev/null +++ b/http_server/izzylib/http_server/frontend/base.css @@ -0,0 +1,446 @@ +:root { + --text: #eee; + --hover: {{primary.desaturate(50).lighten(50)}}; + --primary: {{primary}}; + --background: {{background}}; + --ui: {{primary.desaturate(25).lighten(5)}}; + --ui-background: {{background.lighten(7.5)}}; + --shadow-color: {{black.rgba(25)}}; + --shadow: 0 4px 4px 0 var(--shadow-color), 3px 0 4px 0 var(--shadow-color); + + --negative: {{negative}}; + --negative-dark: {{negative.darken(85)}}; + --positive: {{positive}}; + --positive-dark: {{positive.darken(85)}}; + + --message: var(--positive); + --error: var(--negative); + --gap: 15px; + --easing: cubic-bezier(.6, .05, .28, .91); + --trans-speed: {{speed}}ms; +} + +body { + color: var(--text); + background-color: var(--background); + font-family: sans undertale; + font-size: 16px; + margin: 15px 0; +} + +a, a:visited { + color: var(--primary); + text-decoration: none; +} + +a:hover { + color: var(--hover); + text-decoration: underline; +} + +input:not([type='checkbox']), select, textarea { + margin: 1px 0; + color: var(--text); + background-color: var(--background); + border: 1px solid var(--background); + box-shadow: 0 2px 2px 0 var(--shadow-color); +} + +input:hover, select:hover, textarea:hover { + border-color: var(--hover); +} + +input:focus, select:focus, textarea:focus { + outline: 0; + border-color: var(--primary); +} + +details:focus, summary:focus { + outline: 0; +} + +/* Classes */ +.button { + display: inline-block; + padding: 5px; + background-color: {{primary.darken(85)}}; + text-align: center; + box-shadow: var(--shadow); +} + +.button:hover { + background-color: {{primary.darken(65)}}; + text-decoration: none; +} + +.grid-container { + display: grid; + grid-template-columns: auto; + grid-gap: var(--gap); +} + +.grid-item { + display: inline-grid; +} + +.flex-container { + display: flex; + flex-wrap; wrap; +} + +.menu { + list-style-type: none; + padding: 0; + margin: 0; +} + +.menu li { + display: inline-block; + text-align: center; + min-width: 60px; + background-color: {{background.lighten(20)}}; +} + +.menu li a { + display: block; + padding-left: 5px; + padding-right: 5px; +} + +.menu li:hover { + background-color: {{primary.lighten(25).desaturate(25)}}; +} + +.menu li a:hover { + text-decoration: none; + color: {{primary.darken(90).desaturate(50)}}; +} + +.section { + padding: 8px; + background-color: var(--ui-background); + box-shadow: var(--shadow); +} + +.shadow { + box-shadow: 0 4px 4px 0 var(--shadow-color), 3px 0 4px 0 var(--shadow-color); +} + +.message { + line-height: 2em; + display: block; +} + +/* # this is kinda hacky and needs to be replaced */ +.tooltip:hover::after { + position: relative; + padding: 8px; + bottom: 35px; + border-radius: 5px; + white-space: nowrap; + border: 1px solid var(--text); + color: var(--text); + background-color: {{primary.desaturate(50).darken(75)}}; + box-shadow: var(--shadow); + /*z-index: -1;*/ +} + + +/* ids */ +#title { + font-size: 36px; + font-weight: bold; + text-align: center; +} + +#message, #error { + padding: 10px; + color: var(--background); + margin-bottom: var(--gap); + text-align: center; +} + +#message { + background-color: var(--message); +} + +#error { + background-color: var(--error); +} + +#body { + width: 790px; + margin: 0 auto; +} + +#header { + display: flex; + margin-bottom: var(--gap); + text-align: center; + font-size: 2em; + line-height: 40px; + font-weight: bold; +} + +#header > div { + /*display: inline-block;*/ + height: 40px; +} + +#header .page-title { + text-align: {% if menu_left %}right{% else %}left{% endif %}; + white-space: nowrap; + overflow: hidden; + width: 100%; +} + +#content-body .title { + text-align: center; + font-size: 1.5em; + font-weight: bold; + color: var(--primary) +} + +#footer { + margin-top: var(--gap); + display: flex; + grid-gap: 5px; + font-size: 0.80em; + line-height: 20px; +} + +#footer > div { + height: 20px; +} + +#footer .avatar img { + margin: 0 auto; +} + +#footer .user { + white-space: nowrap; + overflow: hidden; + width: 100%; +} + +#footer .source { + white-space: nowrap; +} + +{% for name in cssfiles %} + {% include 'style/' + name + '.css' %} +{% endfor %} + + +/* responsive design */ +@media (max-width: 810px) { + body { + margin: 0; + } + + #body { + width: auto; + } +} + +@media (max-width: 610px) { + .settings .grid-container { + grid-template-columns: auto; + } + + .settings .label { + text-align: center; + } +} + +/* Main menu */ +#btn { + cursor: pointer; + transition: left 500ms var(--easing); +} + +#btn { + transition: background-color var(--trans-speed); + width: 55px; + margin-left: var(--gap); + background-image: url('{{cfg.proto}}://{{cfg.web_host}}/framework/static/menu.svg'); + background-size: 50px; + background-position: center center; + background-repeat: no-repeat; +} + +#btn div { + transition: transform var(--trans-speed) ease, opacity var(--trans-speed), background-color var(--trans-speed); +} + +#btn.active { + margin-left: 0; + position: fixed; + z-index: 5; + top: 12px; + {% if menu_left %}right: calc(100% - 250px + 12px){% else %}right: 12px;{% endif %}; + background-color: {{primary.darken(75)}}; + color: {{background}}; +} + +/*#btn.active div { + width: 35px; + height: 2px; + margin-bottom: 8px; +}*/ + +#btn.active:parent { + grid-template-columns: auto; +} + + +#menu { + position: fixed; + z-index: 4; + overflow: auto; + top: 0px; + opacity: 0; + padding: 20px 0px; + width: 250px; + height: 100%; + transition: all var(--trans-speed) ease; + {% if menu_left %}left{% else %}right{% endif %}: -250px; +} + +#menu.active { + {% if menu_left %}left{% else %}right{% endif %}: 0; + opacity: 1; +} + +#menu #items { + /*margin-top: 50px;*/ + margin-bottom: 30px; +} + +#menu a:hover { + text-decoration: none; +} + +#menu { + font-weight: bold; +} + +#menu .item { + display: block; + position: relative; + font-size: 2em; + transition: all var(--trans-speed); + padding-left: 20px; +} + +#menu .title-item { + color: var(--primary); +} + +#items .sub-item { + padding-left: 40px; +} + +#items .item:not(.title-item):hover { + padding-left: 40px; +} + +#items .sub-item:hover { + padding-left: 60px !important; +} + +/*#menu details .item:hover { + padding-left: 60px; +}*/ + +#items summary { + cursor: pointer; + color: var(--primary); +} + +#items details[open]>.item:not(details) { + animation-name: fadeInDown; + animation-duration: var(--trans-speed); +} + + +#items summary::-webkit-details-marker { + display: none; +} + +#items details summary:after { + content: " +"; +} + +#items details[open] summary:after { + content: " -"; +} + + +#btn, #btn * { + will-change: transform; +} + +#menu { + will-change: transform, opacity; +} + + +@keyframes fadeInDown { + 0% { + opacity: 0; + transform: translateY(-1.25em); + } + 100% { + opacity: 1; + transform: translateY(0); + } +} + + +/* scrollbar */ +body {scrollbar-width: 15px; scrollbar-color: var(--primary) {{background.darken(10)}};} +::-webkit-scrollbar {width: 15px;} +::-webkit-scrollbar-track {background: {{background.darken(10)}};} +/*::-webkit-scrollbar-button {background: var(--primary);} +::-webkit-scrollbar-button:hover {background: var(--text);}*/ +::-webkit-scrollbar-thumb {background: var(--primary);} +::-webkit-scrollbar-thumb:hover {background: {{primary.lighten(25)}};} + + +/* page font */ +@font-face { + font-family: 'sans undertale'; + src: local('Nunito Sans Bold'), + url('{{cfg.proto}}://{{cfg.web_host}}/framework/static/nunito/NunitoSans-SemiBold.woff2') format('woff2'), + url('{{cfg.proto}}://{{cfg.web_host}}/framework/static/nunito/NunitoSans-SemiBold.ttf') format('ttf'); + font-weight: bold; + font-style: normal; +} + +@font-face { + font-family: 'sans undertale'; + src: local('Nunito Sans Light Italic'), + url('{{cfg.proto}}://{{cfg.web_host}}/framework/static/nunito/NunitoSans-ExtraLightItalic.woff2') format('woff2'), + url('{{cfg.proto}}://{{cfg.web_host}}/framework/static/nunito/NunitoSans-ExtraLightItalic.ttf') format('ttf'); + font-weight: normal; + font-style: italic; +} + +@font-face { + font-family: 'sans undertale'; + src: local('Nunito Sans Bold Italic'), + url('{{cfg.proto}}://{{cfg.web_host}}/framework/static/nunito/NunitoSans-Italic.woff2') format('woff2'), + url('{{cfg.proto}}://{{cfg.web_host}}/framework/static/nunito/NunitoSans-Italic.ttf') format('ttf'); + font-weight: bold; + font-style: italic; +} + +@font-face { + font-family: 'sans undertale'; + src: local('Nunito Sans Light'), + url('{{cfg.proto}}://{{cfg.web_host}}/framework/static/nunito/NunitoSans-Light.woff2') format('woff2'), + url('{{cfg.proto}}://{{cfg.web_host}}/framework/static/nunito/NunitoSans-Light.ttf') format('ttf'); + font-weight: normal; + font-style: normal; +} diff --git a/http_server/izzylib/http_server/frontend/base.haml b/http_server/izzylib/http_server/frontend/base.haml new file mode 100644 index 0000000..5bf8422 --- /dev/null +++ b/http_server/izzylib/http_server/frontend/base.haml @@ -0,0 +1,42 @@ + +%html + %head + %title << {{cfg.name}}: {{page}} + %link rel='stylesheet' type='text/css' href='{{cfg.proto}}://{{cfg.web_host}}/framework/style.css' + %link rel='manifest' href='{{cfg.proto}}://{{cfg.web_host}}/framework/manifest.json' + %meta charset='UTF-8' + %meta name='viewport' content='width=device-width, initial-scale=1' + + %body + #body + #header.flex-container + -if menu_left + #btn.section + .page-title.section -> %a.title href='{{cfg.proto}}://{{cfg.web_host}}/' << {{cfg.name}} + + -else + .page-title.section -> %a.title href='{{cfg.proto}}://{{cfg.web_host}}/' << {{cfg.name}} + #btn.section + + -if message + #message.section << {{message}} + + -if error + #error.secion << {{error}} + + #menu.section + .title-item.item << Menu + #items + -for label, path in cfg.menu.items() + .item -> %a href='{{cfg.proto}}://{{cfg.web_host}}{{path}}' << {{label}} + + #content-body.section + -block content + + #footer.grid-container.section + .avatar + .user + .source + %a href='{{cfg.git_repo}}' target='_new' << {{cfg.name}}/{{cfg.version}} + + %script type='application/javascript' src='{{cfg.proto}}://{{cfg.web_host}}/framework/static/menu.js' diff --git a/http_server/izzylib/http_server/frontend/error.haml b/http_server/izzylib/http_server/frontend/error.haml new file mode 100644 index 0000000..5279a4f --- /dev/null +++ b/http_server/izzylib/http_server/frontend/error.haml @@ -0,0 +1,8 @@ +-extends 'base.haml' +-set page = 'Error' +-block content + %center + %font size='8' + HTTP {{response.status}} + %br + =error_message diff --git a/http_server/izzylib/http_server/frontend/static/icon512.png b/http_server/izzylib/http_server/frontend/static/icon512.png new file mode 100644 index 0000000000000000000000000000000000000000..dce6a505658416f521e84b13c99b86b7b72e037e GIT binary patch literal 66028 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 z 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 ArvLx| literal 0 HcmV?d00001 diff --git a/http_server/izzylib/http_server/frontend/static/icon64.png b/http_server/izzylib/http_server/frontend/static/icon64.png new file mode 100644 index 0000000000000000000000000000000000000000..1f5b602117264d183fe3125a6d2c8e196447b3a9 GIT binary patch literal 3942 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 A2mk;8 literal 0 HcmV?d00001 diff --git a/http_server/izzylib/http_server/frontend/static/menu.js b/http_server/izzylib/http_server/frontend/static/menu.js new file mode 100644 index 0000000..0f1aee0 --- /dev/null +++ b/http_server/izzylib/http_server/frontend/static/menu.js @@ -0,0 +1,29 @@ +const sidebarBox = document.querySelector('#menu'), + sidebarBtn = document.querySelector('#btn'), + pageWrapper = document.querySelector('html'); + header = document.querySelector('#header') + +sidebarBtn.addEventListener('click', event => { + sidebarBtn.classList.toggle('active'); + sidebarBox.classList.toggle('active'); +}); + +pageWrapper.addEventListener('click', event => { + itemId = event.srcElement.id + itemClass = event.srcElement.className + indexId = ['menu', 'btn', 'items'].indexOf(itemId) + indexClass = ['item', 'item name', 'items'].indexOf(itemClass) + + if (sidebarBox.classList.contains('active') && (indexId == -1 && indexClass == -1)) { + sidebarBtn.classList.remove('active'); + sidebarBox.classList.remove('active'); + } +}); + +window.addEventListener('keydown', event => { + + if (sidebarBox.classList.contains('active') && event.keyCode === 27) { + sidebarBtn.classList.remove('active'); + sidebarBox.classList.remove('active'); + } +}); diff --git a/http_server/izzylib/http_server/frontend/static/menu.svg b/http_server/izzylib/http_server/frontend/static/menu.svg new file mode 100644 index 0000000..aa7866e --- /dev/null +++ b/http_server/izzylib/http_server/frontend/static/menu.svg @@ -0,0 +1,84 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-Black.ttf b/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-Black.ttf new file mode 100644 index 0000000000000000000000000000000000000000..093fbf9682409e4d8efc8b1537be542bce63d3fb GIT binary patch literal 98048 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 QU5j{ETmecV)A8?r0pHCPNdN!< literal 0 HcmV?d00001 diff --git a/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-Black.woff2 b/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-Black.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..9b7309aadd6a49dbc6c57f3f6e635356ee0a4e87 GIT binary patch literal 34708 zcmV(|K+(Tbf>`maC6?I0F;d!y zXV@Mlm%z(m6OC>nd1b^r{t% zduUb<#ojn)nFp1VUGuWsU>lKf;xkqx#lCckPYUgrOzoS;pzve34YP>QPgh-ij4c-Y z69u!2w@4x@Y@zSQm0OM0eEq{ID=x5#kR~ZfQITMyy29G{{}ms3mz$az4BFbYKS_;L zsEmS&5f_`!`FZSBP&r4_gWBw-rQVt)3epV3R9F=QpC;YHOmZhCX+IH1+hfxg9;O)B znduJ7`gJ%;zLH9+q)Mt}^T1XqUh}H-s46?aCWCs{PnBdxmH}nlIx&*tT1lSuh5Ft< z_Pp$Nps9cO-{cWB?~ zffeW7S%1a_dZ`y>o%a^NKmYef_e`-8KFA%T`B9$=P+9B4vO;qPJ2-unrPkRTLB zBZ#l6G8Lw>Qq>z=)8{|wEZ>YqKo(hKfkh_JqP^sQcVTjXtJG{>n5&uje$76zg-4qW1o?>AxY|Fb{+mAdvO< zYSmb-avN2phcOkps#4e2_uKFDCJ%Nt&8OMC`Lo2cKm{Ph!q(NBy0WeA@q|Lvg#fgv zIY|!``wbXkwY-cf4bxbPY_hpGx=B+7q9kaIPz0rr3L~lnTL1#~eX3b^zxRFsC`}Rt zMU!$)#|=puI7F590)tx;1fRxJ_bG1R91nXmBy=m#zwIWuMQLs@cE$jVv{Lsk6=lL| z_Htp59iR^m$rJ=#P7->P(h5Ka+hWFm{zR10j=DFJjfEC zLW_U+R)CQtl0ksYlH`GTK81{Xe?@ z|7e760wMrXBEg|7k`hf4rcDyk3>tw3ps*B7d#Er$9!=@hMns?xv`Fv{h71+vtkRZ1bLJ;xhug@JV+Dq^u5BHKFA%qZyVVDl- z5VChG{jv+y%qk-5yT@fjV}vORAqpXkFlO-X{rK$uT7C^AAlA0nxE7IJPyfwnhW%21 zMD4NE9hX~^G*LkTMFBwp!K3f}?>vU{{n5xotP&!xC5pu1;3)eFVdiXBIpTr~xjb4mtiA1SuD%ev`ngdQNd3$%G%0p1%Arjap-!D^lTGpXW9PxWFmW~KrU#yT>uZBoqFDgq zXTiTLB|^d=Vc?Na(X-0Qg}-*~QKnL}E~~6FVXsLa|JyDD1jss<0Yj8ve?Ix{MJWg) zLzfYA)-W_MtZv@imlFPq;p?imq4()Pw=a`rKY$W|Z1xX|0NMO&eZejM2;TBHkbtfK z_MyN)6m)cVF27YMKkb&pf1T^gjM9UXcbVd(vJ)R(1Jjj6DS*Q+w!#>+UWFl!$;Oh+ zcPK)VSxT>#!n>z%IPpS8j2%bfevP@e;5-9&(P@-L0@)$@`LheWX%GyIjh9EfZ!If_ z$`a)s4|7g}PaX?hyhm@>T@MM8PTha>K&bsA;2*AYDyK&3dOfJw`dIS=gs?L{FoQNE!#Mm$$S52$GvsFA5I}dqMF}`6 z;87!v25~ZB!~icw)-2Yz;~06F^D5_c&YPUKIq!1b=X?r%4t)uI4SfrJ5B&)J4E+lI z4)XvF=zswQC_n%*5dF?b5&$R}1w7yZ1vtR??VNSfFVn@-5||+q?BE7BJ-g?aS*r8HhHz=|;MFm8w;o*0W0qmQQ`uP|Oi#NprGt`GCDb< zUZ(gmE4MZ82&(h5tj_r;>o1D1M%mWqLUO`@jkL@h3>wBUYlWi09+eY4K-~o5daCgy*qWP9d-Y2I z?Xo8~VCI&#~az)Tk_~uxt zb^M<4B=jx#WAMA%8L6jF4cqAy+id)#7Kw=a91*^xzU7_vM_+^wzlu#TkHPGgOxrWc zJe_eCOn^2>gOo~DHgZxlRd&&*SZ!V+T1=&(MJZQG_j0@SdK{I6=l+s!Tk18Ti%+($)&$!l2+v<6+rfwS>#(_^j{ zxO@=ez&ErFSfdInBrsM|8B0)evB+=MHBP#e#-@2C0mQoxfK`!~u#|&3y40JUYo3+O zYnylrG%U4QCKeqcP;ru}781?apgjGH$dcpZZILb-``cb2XyXC99TZ^ zw1#m!uo*?q9|k!m$SUrz35|?R9j{k2<|T_&yM2>HOQEV?=nwkXh#XhctBa} zR`Iby-M9L_HJ|DCUza1f;;RU2iq{zvTj?dXF>PRi%i}iPgBn6BodH5pQkSxInqvoG zyZkV?+@$K<`hDvrD5&@Z%QQ&sF9j3>gqmV zEq^${B!!q07_+pjF+pP`-bAv)>kSj$KcI$<-|V%atk~2xqBVSA*|=+Z`OJdLd@#}m zm{{(mHg!%7RlX<2z|NM0R-;GWZfp)_|3%vtH+K9c=A+L!WffTFxEQt_s-G3V?snuS z%kE(MC!;Y#HA4--%7xqlxE*AKCFi)GqYPmi?%L+k92T6_tbuVcdiJXK@?8dCwCZ2duf|lFLn(^usGIp<*j74e!8*%DJw?{!yrqZ6;V6OwM$ym0+*E4jH zA9e6ql(=1ByjRZsMc-eMICu0qQ4(3XS1B=8{^JYkt#aRAnshQw-o}RdvUzQVLZ!i9 z?=vHhRy%JrY=>SPf{EgF*`44A_p_ zX(t$wZft6TBJ$Z?)c9fMP&VBDrOj2`y9ENXk-|Cq$focG+*G;;Gi)}MzZHDOpAx?sfX@n){V-a*tsHSN z8K#wz2nnA?J&9&|?-n_R!VWs0p(ZzJByd3OfW&#q$J zbdCpo{W*N%hKAGW502gh9iH!LK)^Y8&%c`9d1zEmf_p-bfz^M}2LeuRI2nZc8m=A=t2bw$ZhLHdmf$?3^BB`Q*k#ig+{ zdvg&e+qwNK%~jxyfv{OA5ELFF^;kdfbC5+rh|&DRi9^hS%CNaQ2o547X~;|+TrB!{tjC;LV_biZ zyM3b{6UE;2J4bH|IQ*9&U9dg#WWH;HU>@?)8w$JeAjA}7^`4q-LNlcC9JCcoidz=I zHa)rhrE>LaMO!xx`se>7nA-X#>kX(+1rtx{oQhuQ_sXVA{%q&}q!Y(?a?G30u~WKz zAK|HKAxvVSZUGKCIK@aIg%k5cd)OG7_8u!w+ah%iidFF)vfFr+al;L_>h{d`I$0%f zskr1za%s~#1-4RX8Mk>6f4B%XchL7St~DDE5lx$K07Y&)t1{SPbDVoJdwUP_SX_rq z=SXEi8CM+~?MDu~UIQt39XX{D9~B=`H>o{!z?8NQ>YSR?QzjjX+NoIg-_Q6F%1-ah z&Y?3-9-i5AGku#ip4ow7PT#Ce=YwTd1}vi1H}pMpy8=hW&nV^jP_PWa)^^1;5ZJ%N z_QK9~f$h6xGiyB7WWz(9*mSUDTpyz^*?yN6XUT3j=6G;!(+kkSDm!}C3m$7@%YVZA z>a%HG3Fa(fhkxPfVQjYzZxk0nWPR#tHa_Fz(RWnfwI|DDH~=s>$6z_ntr)Q%(DuDfi5b*=1b|e+gTLk zE?I3^HN%AGQ<dY5h5{WrAtvi4CmMe@WZ_o ziSXs|?#1WJ`SR^$n|5!a3@#pw^W)(!0t{7~DS^Ar0O>Xhn%>JJXz=ohuW&&UTe$>k z5QKHBUmJu02a&pT>(Q%EzXA6>@X#ZV&1953MatA^(r3t+xx$KStGy+4)LB;#bW*~?kpvvl7oVFV%J4mi#pF80~aU-W>)dyW2xk@#4ABVvBCBVij(! zX0@ha1o@me$nqA^C?yH4WXZT@FN<5bV`&pvFrG2it@R5MiH94mfOwquTA!sY{g}(`wv_ z1jA7f1%8HxB>ak0i<*sAL~9N*N>FN|jG-CioI^Nusq1pDE1|B$x=QQ1yFm9Ks7~$5 zuI}1#8|C(HGKCBqFeFOprkEH#h(qLNN-(tjMKAaAgZACtQr`1@p|(FZPkXQThXD+V zEa2`drk(~xhiPG5&QOond`86I8-TGVL!JG9aTExCPQFtt{+>w#pnUM_5$cByd4h&xq-ScD=6AmK?MnUK2i{R-)x2lJAK?T+6C{2bznlapP zV=$m8>~5|{#nz--Mk&YyAErwyyA`6ZQ*WOu> zw{7-tt1*;W!;2=2R-&UlREmz3=ok!@wu(Ihhi4<<$Q_yOcA&CTC>mi`5+M9=DiQV& zC~5))b?0StI3$9iBuH@*q2vTQrD`zvyR)4T9V7~!KZ{P60m2NLAZpTeVs5xc)O|C= zJ@JHur{0kC)<;r4`Gjg6q)7+WG|&tB(Y8n^ktaGz0zMoOiv!~cj3fvQa6#(aL(YqW ziuU3He2xwZ#h}#`W5mG7Kk+Hr(N2}DS!c>BD-~Co+*P!Kt^B&~#-caMSS&6sRK@U)A{0a%fDk)9 zIg$k4zJ2@Qi-0q8X2Brvkt{b3rO=L-L5yWl*!WZyjN`N%XW)1dM>^v0M_Fc@Lvbkb zaMcU;wizYbnS0OjrjM-Y6G!?gD}7TqDw-@)!%Y7gTa40Ca?|viEk*%Z3G^UPP1%38 zj55+#EP0c;2RpL%FPoHRrXjh*bBU!!9`#((HSd08kBy|OEwJQGBLcM&=?XEdg_!AY z9Q>nXte@0nUH9<^wLyRC;riP!h}M00iUBGXyFosY#uJ^4%TYv$B1aSCyE4wW zQ3;b>FhtTmVG-f~(%9cjWw~ zlG4XDJIWPxzGjJq3#=Z;H8}BSiRXV%o>DzYl6+ypH(Hpw5Fi5s0D?g@iqLJw#G}H> z7EUlOeC>=L>^PRD>9E3tlZ0bqSAf#mbfkIB;Ng9c3$SJK1_2`(heC;Mo zHD->Eh`@xdRlwazC-aQCWmPR<^OZmP>}62+3R9lDdU3B$IuPxlr~;+g>8WX58lYp+ z9-1apS@O$k+msS5`>s%^;+BXZ>W?2=$}H-E&;t4nh^pK+D1 zShZ%|hD@3EXmwl&SM!a43Dai0_O-z;RT5z`RIB>=hoNeU#hN2`zJi4awYz#SXGyNc zh;>SWG&u?sS1X@26?s@tG3S5151sku$>&-!dpzk>P3VhJ!BVUpx9X;$^wpHg7N zoHb|Of^8G&pd+&<{uN3I5~Rsdpjf4Pt-1|X$IcTbJ@Tq)4?H#Jy|3mQi)9qPkam)V zazU6RIZT@L88NetZI^S`lqY{1rO##jsx@lWW!azG|E~zHr3~yA4DmB?H{qP?buNS0 z@OLQ0Nsyf8Hpl`Y6bu4r$f)Q93FL}quK1crk?zk8a*!*ZE1W0t4n-`sTm{={T+DU-wrpLW?oZ6^cOcX;s6L-edjYNySI8`n6+MTGX(WX*`@_I7VgS0z| zvHJ{NcRZ&1)ZHec=w^f1*{48$I97Vl0q53HU{(`3fGPx<{+~=pwjr`>CaA=*uy>A@1yC-dxI z>Anj-23A@6GKLy@m|=$-euQOD%GLkKFcJeL>U5d1$I~7 z^Ss?Ay%kpJwt@!{rUQfspN{Of^~M4dDkJzX4)J+)#}-T=4kZ91LA(MN27kLjezBi5 zKmkS!$qk(EMl`uGy-E?jplp)jL8eqNQ*I(-ws#Aa*ig;hRGV71SovB-7;t12W9!zk zbC2jE$o3OtW-u2r`cW?&L{_9A=RgV3t4)ii&s8xFZ;cg*{yQE?Zm(Y z85S#k0tDG4&heE?!ZmC>_WszP&F}MmjJL1*wcq=KG@A~}uD0(}&3qH}aU{&bf~_u&a9_wIbP#0!v-SQ$5Bp`N+!7!@+UwpwroQT2d>cv*GjM%V{A!CM-B`#vQH%vzgt*5KjsjH;E&)TCiqImux&u zQO2hd%TtX_t9IF2w7e-seNP^*57Q?K&hZER@m~FY2l_pF`;zhC|6>pyet zjO%}p{0>~=TUiKy>*d1xZZ5TNqh?PF`rj;|*T-BpqdUMikH7g62+=>V%Q9CYihgls z%vpi2Qw{#T?qkpQKX-p_2z>q+Fs~ozz6bBo87l!Ovl5gDDCcr5_e!gb$^)SCtDuI- zcU!kZyZlXb%hlVi9owZ{+iihLR=Tp4uXfE#ES8X=q)5+zKx2=+UIlt{)S0ozd)JSQ z><8D0kq-xsYZ+pujrxcSvzjcdl+FV9TX z?DqRi`*%AgpKOX*NFl>O!BCl^F)Q0*f@PB(4e0n^k|nLCz_}&MSB>eJ8TCwYr6Ks@ zcWAH_3KBpfNGGWIuFOpCPO5@cn!eJ`+(2h}{rKNbT`jfiWQqU^Uy*GdsI(9?0@5sj zYO$c(B6=mWj%0PIEW@&k$|x9@IGkc}i^nxC@5DS4+Ll>JM*b;m&16F|JF*GQQI?2u z>?%)WxpwEYzasxu>c2dqb64g_J~^Ef-yT^V$0=D^87j(BUZ%S8HFsH4g&Hc*Tcw^V zbXV?fLvGb?s0Mf9x>2v&4SLkL=Uwx{yYBhW1Mj;prK2Wmr_CUUaC<8d(dfPUsaZ|o%2PzT#|(T z^SaxLeCe!jeC;>C_})3+`pS0|CidGuCVFbce|`)*BG+!a9CgS(2dRmA@$>^(8JKMp zHjxSB5f6`@1n*o zX|F_oH3q76uVK>-m}%0(#yoDqY&U%DA<1UJO3eWwc!(BC)(#!2b}JpGaYiW{Zcz7y;vE= z$t+%4{~N2tL~W+(aJ4Si>UO;zSL!s^Eib$2Rny*dN0@uu=K=S6(9Lav*fP!?W|J-2 zd(>ECuBHF)NsoEjIO9F#1uuEoB+tufOGNp*dIinwp$|HBqbx2UHy?qPhSmRfsvm2J z*KiShA@2fKym@LmAdr#jok#Ayjb^X0el6u1#HV2};ORdMZk|%P`xJO}%=t^)AbXX(ipVUWE!{ck)#5G@Xc%RW$`FDp(b{@yNx@`d#DrYX_yu^iWz! z=GGB%_51s_m;D$i^6L;^x%9?@nixoTfy`aENYh^2T865s8C*z6(N&>qn~v9}MBZ$O zwWfpe%EVRB&XJ~;|3nz)y{|Y`2CUde*QGJ58^Im?Wf42l?Ze1w|XnMAzHd`ubjf z=w5J_*Wu~g$FLLQ2%7s8IC`%;^CYs`({by}05@N(w_uMW+fz`offvrDQkc&#K{K`z zz2ZChT^ZtDR-c9&Elsq+o5&)ke57~M0-Uuc6Y(^&7>{2D0=5cxc^Bv;kAY_LG!muC zBa+p>z0Ga19vq*)|MMpkf2)qqSj`~?K~*!Puna{KN3kTKL=q^KWHgc#lu0VeB@Gpl zzJ7sx395s@JT1lWz zlF>v`&{R^g>hWdK%hN(B0^({g~_kCJbOw)1F$x z{7bp(Ioi{QF&|XV&nlLq6=YRUlpc0bye%UO+cFuc@M{SG-N^)0Y*|b{=LCikZ!_HezDuS zpFHp8=8fo}Cgc_|q+?%EXe#n($jF>A2UlDvC8brb^MyIbqY=xBexs5C6j{f#=aia8 za+7KUmm3jt1x%AXN+2d%;;ax#f#==`Yk|umF_Rh1==KiWiGU#yku&Jfb}wFYZ&54L zN5B;Ezy%)i)s9f%PQ)jnL95~d-{UM$=6_f*ujKK}P9&F8rRgB?q}PGR_p0FO6OZmc zYj=IJ?RY|4umBZ4v8(XPy|IASnzD_mDzrYm_c!j<_NiXp$Pe)|cyMZypTnc)>Y~-H z8Ri4r2nsdaO7y})q?e9Nlvmd(9WP^#VD~E&ttfmng$n$eV$xaM18kliu+=>$+7S_B z552k`he`zOHBWg)L=)Nzt;6uTKOEiWjA^VNNx808YxBmYHz{C;Ft1U6tITc}^!BwO z8Wau2+}1)e-$8xDeET=zU1kxWt0(6-%kP8u!}8|_gTE|)4?^s(_z5;f=oYgO@pcm^ zZcS>+tX1BBnxk2LqIiQyTWU6#)LQBW(bZlzmhjed*9_hU?%MrCHfq+a|N8Zyz^C+H zoP`Van(*(ob4GAHaa=us*K^dM92GK-QU+D)#DXByP77$97NP~}JLu>;)XShjhK=tU z7EDeS%uW_8P8O^bpiKttGVFjFOE{gDa5*jEc3Q$i0eWT7Cv%CPe@()ks&3t1QtkX} ztN)AvUW0GV00L)woq+!i}fQ`Qctny1>;rigfpFn4RkFZAx0kOKeEoPJG za&8FNk`NCW3ri^&A~RdeyMtP6D`D{M=Rj1@Fe6d7Z|EflBJIvjB@3F%CFFFqpBm&F zlpA}2L|sl~%_=D-?3=W8=Pg}{1j#`l?>M`tg6=O7kgW~AYXXwMUzVU$dMzSeZ3XR@ z(O%BPd4^m;mOJ6wjzi-dU#Wjbc*)He?QF9xarS5}m%Sq>>|Te;TYRI0j6=bM`~)%< z;gFG~MtM5gP{`T_^XC5w=<>DhL68w3vWiz8!3%icLF@T}9<1&ij&Z!2eI%j;D}?pV z3;_!^RHdS_+UXI4zI=O~g$nz_awHwJ+3bxC*zBFK5z8YzMr=9~e3x#$(&45%5n~tk zkyfJQtR*5GrY)#NZK^7DEL8-k?l1M_o9B6>d>hw9w}UbmJ4T4#LX;;1Be*+>6JYD5 z<@+mSg<2qGfGy{i?>R;2Fy5kTJgZ+v6|#1Ia%U9AVEI54hzxzuR}k9+evxu|s+9M6 zw}_O+n1h4s6}L0!YOP1Z$zGX16iiorux^D2BhacOrKB4Ls&x|8=mZQWC(7wq^Ils= zz&t;l6Z39_LxtNugejbAHey_AT}G?lpFm1zoO8B-!vmoeVIjKAmw z6$RBr@+zt<@^Y?Gey?NXd4?(i1~G_)EZK!GA;KK|HS;8+q09L%&^P;cj%i0I%iZf) zpVO!SDRLaRJ8mdmPXzf8=eaaA)&{F75HjRjT3ojcx=|j183!g(Rr=sn24n!jV5_5C z_^c9NDE1%gD-8LRl2h)6KSHaukQT;4j8JF%-6r5eyd=2N=&&i_q(~KF9kN<{VdMq+ z%>xidwGwN1S3m6y;b1?AmX~A>|FCQoGPjbD=bmW$uB9$iaKH&!XO5{hA=~c0TU4|c z<8l`q_-uID<HnRtS5PgA#%D_ZXb%Gfo3!fYybYMtiKhwfIV&aCuun2e_QeYA7*sJ_;w(@;o!P+489%F{;N9&u~}R zb{D?tChv$VsMmR`9Q;9>UNB0U>=Dv&%@PMvHP)?A*2HxMKfVasgH1&&+PO=Z@4P`5 zZ)klBsphcv-fV`GFyauSRGD}0C}G=8D8=+{%erW@HJ!9(lpO6!>7H2h+0q@?La*w< zn8*`djD2hePi;>@2q+U4aF8biH?FpnGjQkQ6NsVqwx+X)apO_S;zAyr6=+ zjkd_ybz7bZbD{z_P$MT=xr&l;s^0aKSvb>;v{0s=mEl5Hi)?Vi#)U4JaWDoa7+8dZ zl?#1$GX^2iO-FSY8#-SQ`7eX!8;5zp@sI?aFh!**yB*;6aW*BTyIm2{?QV63MC+4E zhYEn1bWf&k?d=+(Lmd`)Xp9_9gC_=zckAYVT^ViEbD5Iyv@iHToRN(XU- ze)EV{<%53Fp^)jg*ae2FeT6c@{?MHD_TF#SEC#xnQL^CF)M=5-!etYQMoGsvz6Xtb z$TEQkOo33xW90%B`_WUefYbRT%*HxrNUrl5oXXRb5;?%NaS?i3S|m`^F0S>UR#C&c z=h5hV1umX|3P*A(IWfh|q4@-BLr5kO%uFn$`fAMg>YdjB@|Hh#S&%Ax^`a!rL11A_Ejv(1(Vgw1Zj>-#{O`AMmKqrZ0!%Ck;G!mvEMZ3cY6 zpSMX7az-qQru}?{p8b1>0V1Kujy;cD7eSP*plswms7hSb4LUmIUHj0pvC&andT1ER z&Dd!Q;WLm!!yB_FLrWa~U~Gv{5uq z2I7?DM4sbLN+catU7e~kS}DaE$dIz9frEz7h34}da9eYBhzw9%f(@K;Pi@GR71OcB zk1oqV;#y?eBY3}h1P2%ZVgCRreo1wXLOKOUWgyZs)cMY1*h5p*F3~Pid{`)_nj~xD zakl`D5^>R^Q%U@vQt5eSP{_n%343{jBP9Hy;*ICzyV5YyRb4t^!VLvx8;7E1Gs(rF zj_*g=q7COb?TxFhH4rxjUAuB(JXq5vsG@-q&n#T*NT*uO0|B9f8MYk8DXdje#TRcO z+p{cQG{!X#jfYyqg{h8S&@)PGn*=Wg4U~1}LmW?A+1QT}tECA1=>HsM#OO3G!826V zkyI?3isDY9A{(eDb%w2PS!`)e4lP3*K}f86Aox&GIO0#Lu_%bg5MT}*K}T~>jw4=_ z$Jah@jY&*RrTk^3Tu^et-iwVCCt8AXjsl^l9HW5JN8`b7R=Z)(@7Rbgje0tjJ8#d-CDq+YNP^tH)#3 z4m*FM^>_V&bf^ldK^sBbXN#f7V|E04x4W~TRn)6H1l5E+y>8WFn$vp&YFA7nW#5_c z-sY~}RZnP)y3hS4sp7IWq>v$*kUSl9NvY9ti6*bdONn19OlK*kb!reEJzw*LWOUeBXiM&=>@Jkzg4AvxIkqLH4ZMngsYi2G{xr8 z5;bMpCF99-Bi@PF?SjE4$(S02sx02IUx5cC9^gQ2Z}7yZ{YcA=r-MLP!hbi&Fo(5C zew(4PvQw6AX%ILAg}F1Ts20hL{h~^8gfT2*RABZgB{%-U?4N)9wV4#RXZCkVUx4TL z&utKH{jL6pP@5gP_ysCJxOTi=goCtHY8cjt&?@&VKbRV_d;j*h_$aYMm$Wp{rK!ojg9fnGZ{$a<%4RPtAnHU4w|*gkZ69DCBxe-zhyQ`)nu4$QM`UX zzQ7d(r5Q#Sc~eJxJTxY{Ey%a}NjnZ~qhZ@2Q78Zvk!7gD*lsM?V=K7)F%~MQoXV&& z7<}9cO_U_$gy-{B_@8YT=yThph;Sb4^K}l#phjoa#aZ0pMvnb(!m+%mK`-ugDn49Z z+zXsuK2FILCzA1mF`A8HQM%m;U!%J32@XynR6Ts6TOMudbBz2Wu}S^Fu@>48J_sbx zv}209dSM++&U#0wsY-qtWUwD^#085J&a5!wR<$#H8gRL3!S)o-fqt zNIBlNC_d{XI(KxSbjco6Nfl&^_W<{TFlD*M!fism)@zriYK=MzpuijRnu?J0fqpoM z4ePQqDT8Bzm5TdN z{RHeGZEcaAV~bFBEGnu!Y>2pk)R20js^p54%~ll`dt01iBaZmXU#1S8WyL2(aomie zWKa1dg~Ww3uk3+sDZze^?oveHmo8~FKNy^jREWteTiKcLZtwVX_+P1_X?r(4aBiu_ ziQD2iyJn_1^uV8i8ygwONYy=>Rkeo!C_IA5N!Pis5Ek#>-zv9%ea1}x0#4cKNK&gB zqqQiUWgge5$7<@h3Ti|bstJ0{ntrEC=!M@3LzqLpp>^~TYSgS4e}XC5I!5iH+TRFG z{Cdwy;!PR6kj6&SNHff3*ZHV^GglL~tXg(Smb( zEu5fSaJB?*|2IvZz~k*@zM7WOaq%5nMnA2(&HBVv->Ka-EkTdXpm*J0ja~3wevhUf zY_a&C6$`^;4)n-yf^7D9M_W<0AMsG__`pH_*3ajNfrdG z8R4NmxLjY(hppIwPbCyZxUC}1ZT=S(`ds7@Z#C$bB8>OFcvW-6T#UwkRZ_mC{hnLS zeapGO-J-QcON-XF{8oulqrBdJ>8Y4%f;8O~48izm0@yH2m?jitoaki0li+x#7Umh|410!CHFzh!DSsFy`SPM(Fl~Z3C2M)=xjLQg6TpK@Cg5@mgYKQWfzN~!eZdHf}71@eiFU7iHwFNuw!^Q=brGWqH>>*s4^Tc6=H$!sie#z5KVg> z&WWn(yovP{YeoQv{pIC8U%AJhKZbcVb$bHb(dPgo@=2tY-OS#TeJ5Ati)7RPq$rkA zR#S!)1JpkmKW1>r$52>*ueSQv@x${<_!&mTRkQi(tY^4;Smpe@(#!i^5&$Tg{8PZs z6w_Ju+(y5&fT2hzgP*dmS~mTBkkgYsn2x|7SzQ|FgJw4D&2et8t#a*zdyndv3dsu`y`@9y zWU}c~(-1(?q{8-#S=6NY@@WU6r=Sc$%9wi2a$AJ_J^Xh1g|DizCej-L`Sl@GB0W_e zNlm0Y;Fu9N6C~2ex39>tBb?>-h_uGLNGyb<$P*dnYO z(}B>^n^lIX>41s6?CsUn+%S<_S?SL@4a*B!`kl3>o0wl?u{x`(s+=`e5&-b)J)wPJ zWy#UfKxHko<%I_So0&`^a*{U?<5u3Gs`!-{D%W4Jc=L>qpDCeHZhInz^DSE{8a%Sz z*5fs4sE+tz1IKjy0cTU&D!OR)dKKC1x@w+VDet1%8zz~?N-gItYDl`MH;fi6~S@{FltTvKyG&aLF#kyT~y zun+^T_-9FIXRa^)#>?OVj!#>=x~c=#+-gh0%?$b2H8qi>5qItEqW=aM!~eg zJ79`G(khh^OR%f)el6bbE;Tt7d_j?yB@^X=`^lYVDhGx`ksM0rfWe_e@km0sQhesv zv7Q}khb&DrX}*|BGwita=-SRa=k_YUedkDF>7I|yeyI8#Hn6EGU(D;CS&P?AsFOAd zqKyudM)o!7&Pd6~9a375cqiQ3*9$)bU)r}c9GMZ`HNg!u`Uy@y1WasNzv0*xqtYgm z@o5;h9N#dqb$mk_{V1Qv7usOPi*jS-r@^LY@{-AbgHs!t-NU7j_2)rj(g3REV_5Y1 zx50>Yo7N)#CDsE_Or4QU4aufHx%mhxD4Ra~@6^z`-RpM`zn%JM?YYh8I@e!LJL_KP zelYQ5%aeOC?x@21V-GexxQDntg2y{{g z4W+sx!;x9`8t-FOD3v$johJr01!eG|V?TUR-7WQ{qf-RfJ8k4B9 zLl`*r#t#@=sWq2d^*<-hGLUzPH9wJY2GBE7quvK+tIEmGgV|)hpa93zQP{=J&~oU) z^jH+u3CSikj&-JUsz6r?rKJ*fy*@n*$Q>n+5SaL#=!HPBHU<15W2$ipF#3r=~iVr#@dqjith62&+q%2|G(LMtFrV~=JK3f`agU>OY*+u zVru$`Qenl?rDZa1lhMejFB8kCX0$7gqC|**j!w*>m%Ci$9v64j)Fko8a5dHeInRI9 zMdKl;U$ejw1N#ExpKLuToD@2kfcxXMzqv!}bTUwxpo>y|97rZgplRx5h1!(QR0}l$j@Bv4vEMfWy+0uiSs-=MSPLQ%OG{a5Kb& z$?3`X?WPPGId8rgN2^0PDLm17qM+=QLe`7P7ZAWt-)=jzZDDw1CW!DRk};_1lqr3C zc)lap$VEPK{=7L0mN?2@q&=I2ls(w_+2@nflUuf3z4OUW8Rts7xDGlHtm!z1e7U{M z|M4$4G64O3%_{BWH^uVCkXk+YRWahfS9V_|Y7#*lfur5DnD5|tCB8T$p=Fj=pmH{3 zk(oJcD~0D?F=E3qj1OM<`h%}+Z7+a9vZC*65IlfpaU>Du5qIx{a8NAj^ zv3$m;P(sreCpO3Z-d^=l$wJ1z^5G>ha#ZUf&ALzq001~LONX$|zZYtg>i#N339T&> zS%cXmWAJGb6`}unnu}&jN~N4S{eR(c!TJ;tV$PiQ_QE1gEn0r+Rhf)4)tsdRe@<>a zA{~Y4QLPIFV!Dh%nR2YMs!`5qG#X?{pvea6Ft`IlMjoXQJ>NR{XPzZ1Gn&h|%EYU! zWcX?Qp$V+a&&N@qREzthJ4F5$HfErPj231Sn3K(MOE-N zQp@sOC;(DGt-p#112Xf!I_$5K^Hu0nEiGEfuR4(Rv`-csqQ*j^YeTr;_* zIo!O%oXKyzc~OFHu?|$Q2~@VYEHV3{)Ul?PBM*Bs#xj#@AB2Js^+690J3mLwD9EHl z4&VMBL}xsIaY*6Tpee2be-Jr|(n(Nv2(iW?ACV`r!*=FRVo;axk~;vJKmld$gNlkQ zADn!#05!D|TKpD3_~*k9e;$7D^O;~0^z!qAx1JA`{$B9=@LKg)WpW_7z5<#S`tP&R z=^)5B&jtRobuoi7I*ven_BDN0|7zI3prsCGyf{`_>>%&>`(R=M_REPof=>B zol`R(@A!C+!}Ve^aLDpE4|E0EBL0Z_oRHJf+3zkHH2Q7JnVSy4NPQTBmXHMjL`Nl) z{{oeTth4%Ou@TYa#K`sY_xc9%oeDWKCx+#U&zCS@jW3CW$B>e=K+?nIeal&0k+Nvh zXE|%K8mj0tti*Nmx{D;mq6`8S$gdhG;36{6KN1N=$U}E-^%Xd+p_VGn z74UdAhEzAFzc6$(l)6GVJ$#PXa)>d0vz*8CDl^qpoq`!T!_h){-n?9w2}OxC z+#!MePeY;MQ z%M-|RnyDsT58`K1OBuPC{Wo6S>;I%9%&Y#V)Uy$;9!uDgk zk0Dmj-NOOestNj*_aO(iM;=(y)FJIe?8or6DvQ=Zz*kYBvV)jD5|e%p$iB4#L^OKP!^H9TEzl(|HMBFIYl z9IrwluBZ~JsTvR-pNvK);|Y-%RmI$*>Iz>`wZl5|(cXr#}QCL}t6 zpCkmI$k`AO$y6@~;}?R6&~MHHD-Y)+WZ3dlEX2Y$<*nN)1iUcsl=l*#Y2GD84g(1> zXrwx~)rNB>oJ$C9k|Q_A$G0O8IpRos{qdvglFnIo{fdaJK)H*@lKdYSmsk+mQ(+Jqi$uPn(=y{#mQ2Ahu5$Vbm{ zXJpGa-)F6P#TN2I#;^x@hwpc&7`=k6TcC?OdqB}r9VO293TbXyS-C)5P!$#W#zY0> zr|Y4*y&`dbz>)8h>?vaejh%D$a-A_d2TanW2*+h3epU(Vv*Tq}lpEP<_`_?R5!j-GldwLSfm&&SHDxIH4% zM;?`&4`x{8!}1@?;S>5hDfzPe;WPZW*voygKKNc?#r7QE_C~g9RJ9>;y|9k;QlO)O z?MqaPd`doXx^(`v_+7VDgAnJevT(!K#BM1>ndEE?o3KD(w;Htm~1Tqp> zb?_QG_pu?yK1R#`w17E4ROK=^r3Y_<1U*p5F}N2`yB-tL7tU&y_TVuA-_+Q!56&T3XyO zS0N-XJ4wEH0EPa5!t?N`AD|9oTs%QpN`H%9yp~Mc7zboP|N4)je8L=s4a!YT@MAm zs88xjjs!MDeSLm%E)8GUtBY;uZ_vdS^wRKiaf)^$)95$O4AyCN>t+mo0~7w7csy8B zTDJbNQK9}YRj-m#SvnV1;;~^f{(>(KdMdUvL5do)KJLMX(^EyQjQ|&F&E%TmaPbZt z8@-?|ZG|(1ko?KQ1-}HBTjC5FF`1KDL=ezC@IF#QvjvO<)+~&h_3|6-8y^2pRLs4Y z_h+1EvM3-hN){+S<`%2s9(<@b1Plzmo`xy4TYRi&-V2yegh+3@1|1N^SRYuw>cdr~ zUx>`NrfN1fpI6>q6*BnY(&I#CKA#}Yd9v=C^E06S{+p^*ct2TTyy>UP(_ZAalFw|8Qkm6b+%> zhqPV~y<>G&k<)C!(0H0P6Z?(bft={DnpTKD8US_ar)oGUU#?UhmonORYJGpqI?#4xS5uNMg8F0U`OKJ0ezGE-V z$#sVMol3d@&Dmr0cuA!4d&=MP(d*x3}hY(|5k#(j<}88+5$Ja)mti&a8qcUn8=2IlHd!5siHti#{`7j3C1RObCyr zil@t66Y#mK^YS?C53H}so@!r$0!=&VM zU-f>yIw|_9L-XcAbMcDCQ<_@*vp2(6?4UqV`$ree^c;86zkkvL`U1As* zG`rPhF#R^P_IO@Tl3Y+M#q*I2u1k#mKm2E^LRzG)H#RZk1wx6~rNBs(nQV@&j3jkd zepF7r3H z+WDl0f2?2(;b%w&dyRA{uW7HGK6^jChVn=b&c8^Deb`(Kmd(o*% zvD>EXGU&o~y9jmZMSHjYFuvPh&(3UVbeD<6_^8(8OQ?!3-C*K-GWmBR*!|_}0Y5JF z{CkN&v4`-3dHvp$@ko8i5qfdi>&45lb7BTJ?YV2s)=MdL)sxbVd+^yG{XmKXl9I3j ztT$fP)zVdk-ilt;*|Mu|I9*wWQmtFLtId55(6>&5!KsNvZqQ2v}s2ZL{)FzVcw2;&Ov%}wZ&885%-AcOGOLz51_-Nj|BLA&X+uLo}JE7 zWolJQd4os}EJH@2NVw^kndyLw*a$FZC4hw(~T z8wt1~;cVnQ0Q@OL1zMEG9&<{@lfvRm;(tlAzPNX$QyD0!RG=b|kl>G%?G@+gM&u?2 z@ZAz&YYb3}(OE8TLkg>)LQ;XLAZCFV31db#MS&2>Emhmef_F&pcp}+#7!QAJT1PnC z`xl6H%q?+aSXW&V7l!o4$fWQn)kVSLnB!-*o&n!@mp{J6Hx75btMqN&;|TxE@!F#C zd0ZXr_Ph8M<7M5Uy7(r@ybBx8DlXjd|5x^ozW7SuXZREKM0prm(y&QxKH`hzu%g=( ztHUHZl7o^Uyz-qLlu)YUM8(4)4|Auv^h+s;BLQ5@d~@_W_jqmQxajL83G)(%T|89N zI?6o-YD`3it85$98W{8`S<%!*+9(Vt6^nWfMYVT3k71PfD5;&WX4m5B@1@n#=egC2^fU8M>fqG2|=6(>+&-sL&_R zF2^MBNjlP5<*E&7^&0r7L)zaTc-^sLS=o13$48aXqf7ja%6>@jzOMx~=AeCM94K0a zwo1Lx-x|xWH&6GcN=ya%=NS_daTFc-5Q2VS2Wa3I+bc_)~> ze;^OD?|DhX^#FQL_JV$#l3Y~~?C73cxC6aBEqUK%{@#UVl5c-~&TE#=XLJD4Apt0? z6bGt}3aYh){lCfUO2poQWByDo^@3-AC4UZ{=LO#za$~?t-*<3et4&s1n51VWu{uj? zEk;^jC*I=u=94k(Sno(?R#?0f=&LySGUZ;8?THwb+p9=bUb12d{eU>zT}jLI*q?*v z!-dXDn6n^Ivf~i9&2$v%$xr7vDy>VK?0BQ=e=3&L>AL2=@N;o9)Cu?gtq^vIl;9zn@rT z&EneBt4ThvOtBardJ8|{37SLK6|GpN>x%ip4`6D3-5Ju&p|V#S7yBq!wH{Z{4~Vn& z6rQCK`*Y&?aKTg%=Q6dc-fUx!<1BV}r)C%`FB7%fP62A@Vaj4DzRC03;^5m8=o6^H zQF&JW1^6ZdkEd(#T-#iFyJf+uP#X0jzV`_nG|9E;d#^P&9Z8+wN0IRU#VlJHFJ8k5 z+UBaC$rpYM+Y?2cyN1=%;yOVS8BCRQR@Cg76DYNlNh$&*JKwzHHix=JCc8I6w>Z>8 z?$E4{RpkdW%a~Qv%vH+MROK->a~3IN#!KIKu+>K1rYhH1vY3U8{n(nj-qrEU_2XnISGh+?eO7&D;P_;(WhglgKv ztPPifT(KmkkQ*WCenGwGfwAOCQijykqDw&@PEBWUN34Me(yffAIvN@LEK8`>L`s*OQH*4=HHg|ThHOu= zNn$k;hKw1gpRKA@q+IMz*3&83sft=y?|yClz*X4l2k5vP+3TA3YLbiD4m2s*p$os| z%(lng7138*Ck|l0v^JYgD%R;Jo7K<3@%2zempq(y)-pA|Nf^+CwH`+?lBu=LK%~!Z z#x%#Q%NNLK*iHK9s z$rIm)Fi>Car8FfJ#IumxA3>v!i^p8)&LgeOb-MB4qsi;Pi2V^f<_QJ)*{4HF-6Rar z^p+SAc?^MsA!7#g)E_fmqx(s?jj#QQQ2cW6s~@ug9r4U&)|`0@7A;w};%AIj%~1Qo zkqdcNo|6~kMR`eHmRB6Bd1mbL`K%Q}$$EVn5lKwamp6``;|T&krr< zFIe?t`PaEwzh3~weSSW?9BsaRZ|Rfe|JAqS7QElY{Bp;Of(Yh8t-X+I!eywD=Ub#Or z7_V{v>gMC?YUN|l4^J1R;)3m(VTq~rK8W4%;_;k@sCr<>8RYqC}($c2#VH=&%_!l#9HLL{ugnorotJ0%Ys)&!GxmA z;L2{^|Mu_qsmw-zA0+VVk<=Tv$}L;(9_FkA_;Yp_JhOX7a79+jfKWGQffj+dS3yU8 zOHE7P(i=a|0P1S-g1u$xW)1VLL2xcs8o1TS^@>%5P|2y5;=&rR18bxFW^*2&KFmvTwWVBv8EX(KXEwT5 zC3iczNsY+>G9A>f*$?+;xy!V{!u7uuPCR)^JPL~^F5 ze8@$}-YOL?FL?$6{Fy_&CP}b={EB>3R;%T)pgP6tp zWQ*iQD!lhb;%2+O*zrbuG6g%x8FDph+kdMr>duM808ZDsKO-~hySZ;NX zF@t}WvdJ_SCI2wSDAQ4Doofqe^gL*ubxNb^?&C z@>`+NU0!R<0i=fc8|0lGD<7}lS{*$Kb&a%c0{n>i8E+{>1uTZWjpKxo-4B zeiSS-cC9J@bDLbnH&=eWg4ev;+8ZcZE84toioVxSw(#&-a7NamprA#3M!3dUWk)eZ z;@Ook3niuWb?pznVhx7{HknwC-s^lEtuTa2dEMf8CpOj$8VrX(qwKTEfB7%#f_1XE z-BRwE1;=K=tM!kr>Wnlf5loGx0++n`3KdaxL}5R3*D|dxQmjf$ge%Ug~te$@&fS=ky$ek2#26W<>q>fzvR5UqQ;zae68c^ zWD`gol57gj)DL>wl19jnVFsa6o=5UK<1)jau@cBzvVmq@4J#kt3P#Ko2QB4%P423_ zCX$Ixe74?TXiw|6HEd6G<1zFJt(4c1{Lc8xoR?SBob+c90QWooBZr@UipX1h4uqD! z*_Rq5X#6h~D6(y9zjS{R5sU&mdSY_0J<7zYu&Ys~84;taeh`iMh0vYUIEqA45_;mj z!OB*kKwH0D7NrU%R)JunOdu(5q@&xZr(S*;Oj>qzAZu>v9@eBUU}hlW*QKo(M{)5k zt4m-RZE7@X^ILPhmNQJdD=oE7LG6v<5`y(pA-@gT36R(RimVzZp6U=sXIQJ8zsz>` zU<6R(os9B5uzPRp0RS1dNT1K)OmcxVAu*y_h#0nWod55ao|Cg*evkis zK?QhbxMHROmT-^wS&_8zh22y^L<&#aCsK^b&mYLPk+rNac7ngT=EWMB^v1?>4pDi| z8c4DoDomj?GXTrDN5xqY4f!V!^_6nvyoC%1dUJYlVj(e!#w4Wr-JIOc2cHt`AylY| zg|HG6fI2YwpupyXb6=)&{D7;W^Y#m8m`+3RkWbh+KpqrD%rKx(PvvBtwP>BjP5*B7 z-XO6wB_6V@hr|dVe;bmG%IrKIfD}n*-Ac-?y#0KL51-hik05u#!%La(QI`7Uck}yy zT7$uj&xygG(J4mpBrq8_s;b$vLAnU1+t01-sQ^dX+)qH?Qh~m7d%QySBB@9#=%X@Z zx=Ukt=WIU<$$WYmjkQ{A=PWPzjIR9Y8{6eGs;AmcR;0XV0NpJSTDkt74`Nz?h7e~oK!n9C-}Mg|a%VS=SEs{>%79h2(l zI)QU-{A|NIKT+vH5Sf7o_an-}- zCn!-%I&+t(m$b7p6g+s_LyPA1#Vqq7@c;J|kd660Tci_Qa}I$> z9+RcPk*1>)$3U{0F&hRaa7VEK4Y$Z-{;;gaVMqw2?f-VBis_f;M-FZtV`LC}QO#mZ!hr9E+!LM18ADL+SR#2! z0A$3Y*_*@s`Fry33mWnTBP6U=(%Ce=RfJfSfu*I`E7%Hf2X|W%G1x5Wfd4<1mw9RJ zyKQm`FL3lij3cIYD{=KWXg;yVO?WI22yr_=AwNX5>!UI~B05MoO^f{EFnsOqFOxys zl8mDOn`tC|0g&oLst3=Dw9%)&1-Lwiewi8R^vHAP;1akQ&tpX#?7vw{(2+DrDo>PI z|M0=&ogs;NV_wQ3(RRc+vgSYYWng0!@au395dkhQOWb{?!P!o71v+V5r?-@%mR-|g zRD==p~1CH>#J^Z3e2SX7CObT zIuhS_$}`Vun_@8QuZ&j(mm_nUkm!|s^j+)v5m(dot&I8@xU~$(eMwwzWaFH9{BuAM zjARxo;$s?`&SxiWCeuLKTuE!GQ$?Fq6SHks0LSSS8a&LWFus=sCdm-poOe3`_Hz1K z3u4WXrrn~y7;QodV=qB{(<3{m<92c&b=f*(&{z!;!Fm4X#0DRuirp#?vsnwn1KcVx z6_27IJpdYoJph2sbIiJ#gAW+^d;hHXv$y1X+VRO1OF9Mb7>5JN_DCg{-n;{Z35O0$ zZgX&Wpu~;d)K389JF$hVObyDV1d4YluQlj456;c*RG!X+(_ z9+f>rsfX~OPs@-42^5dIX-mT_Q7){^q$jMZ?fccxynCY}Zy+)?SR+?R5%Sr?36i59R_`q^vn zqy&D?N$Z|fy)^E(I$HACW}0pE{B3z~1CUEtmVzRCTQVzh=4MlJ75eAgk! zV#3gJ(U~jdA`T|5jkUCw=dhG=YELyQsXFvgbt@z2fi@|vL|HJ?9+LTsI>GwV+Q8Ww z<=zzZ&3^YO*W2cJ#R>tsD>cjktstJLU>E=mrK})2OquGGxd^(DjF16+v$@ja4vy?c zWI?O~pqN~NBa&iX)Ypz-u1a_m!Pt&{Wz-epcPff1HnhI!lft4RC}x#2Ey39S;=B~Pt*I(k;6Zsw_1QB7iEf^xIK;SswpuL8`ml&#C~*rO11Ua@HC-JDa(Dog16@PhU_i9{!3O5z-D3n%a*Z&%=+;>(zO_I`3EK$EvN>1)qmS@98d|j8fgB=?&wrU$M@o z&BvWhGim@V3Mc1=&`-~?{p7fQL%?U=&rY9Mzt?U<{!KMHrLr3fHC zPyfEmpqna7q~O6-*2yrYF2*df@kB>ZRH0La(FPo0*0N3jfEwcL;B0>i!n$%ih>o`` zPw{wDaVhZGm(6%UNO3=MaM!$WzjDb zmR=nm2@VgBFV9bRH)HQ?Tj!|=p2dEgG@%I3(@gam79a|pkH{ah-hgS$UlZb!{`f4K zMTR87^~6IL#N6bM>gjyf^`xUTfje3VCc8xzsq-PXv&S23AEAQ5@ZEX|`R@jM)MACI zs!>D`jp8g#NT`hl1f~X^Y!{JHX2h#~>$_PFkyR#yC-n+wjs$NnplZ&N9_@h73>(=Zox7pubR7~@j^jMjirXY21hb4DtF1~r!$?fH8V*+R ze&)LcvGn{~?zPP~R!Kk*6Z#X7H}azzXXB#0bWB4@w@_ri9>?pWq4>?tS~;45RsmDt zVkQaM-Jvudwaf~OYP%B|C%$Ufx-C!pj;NDtol#cP| zcM;|m`qo=!=!4|n^^xuS5H;eFW{!(7n`99h3F^Yk5iW5Fq>V~x6=QeM96*I}!(hZ< z=y!>R(G|e5ak~=_6D1~MQP>rO;wopqcNxbqRtYI>6%)mc11Uz2nO5S%TAw4U(7V0W zmScGxia8GZ5a{#r{G!DoMY9@>thAe2Y~T%3Xe&e4vwG#QwPVf8BzQhTUth{hgE_Xa z-8okBW*TLMmjW1ghr**!^lO`HD;P!qu)t%inE3jUS#8l)X~!*OG;7r}Db^5uEgITt$ ztuI~$mQ?Mj4=Q&#%ku+7p_66@*$%Xwe$^KdU1@y63bcK6Vhfi-5netX&;JB-bTplh z1vYN6TDEphsxN^|@J*B6TCo9J`2)VrT&2;FZt(d)Kq4kgP9r)rUDCb6m}Q!I+9qU- zPg^aliB<3bQi)mYpld3=u4?xRrjO68@(IKdLQjPZ_Ob=B02a>=v@amk9cz{aQdg!~ zM!Ivf)0=olW4z<@r=A)G?(9T%j3PfkD7m)?k|9>KF%d5S8ApA9s;0rrXZ`$faaNZ} zWLAsQO}=4F6p_?p*=`0&4NAGrN(mcvLGK(Qi22sVnS7OLazS&-^4QI$D%prr@Y6B7 zVpZ4jt7E#ErZ3f}suO+UNu|8d1cz!6iCYVn}b$NQlgWG8$R2W)wz7$+YZ}ah98rf@Y{IEgmYagGR*mH-{QdNtN9jDwz^)@^E zV$%vO&^omnJTgI%bJMMTmsdirKH%)Nh8bmSeZ$wJ$6A?1!EX_Ie5v4kI(JU(N?I}a z%praigbP;iA|h>tv+e{j^d6REswCOV5#x!RcxVo(!TAcs zo83kFa_sIdp6+hu(VC{NN>jcHF5q(0G~!xE!V(y9sfbHy2$D9YR2yczH@P2QUl39I zl5BNm9RWTF;<2t7kpjP2eZ=4Pzvdt7=EH_pnP!TYaT-klg$WDE4*u_eHDgzry+Ub| z>AE5b;?{!PZJk5BqPH;<9cGt8MMDiP$FDgsv$*O#=Wmn3^l|=fz`5?Gs%znz<>wzl zsyU|{zgHX+bE$N?2uvrR#$j9{7tfwHVQ-OYX=4ZmKIn`h2ZDp6E+s}hK|x;M4<${U zv%gJNNfm<8JEe(D-DZ*Qo^;w;71OlDolUn)xO%JQBIuZyBW#TaR*MGB<5!*7ta_0% zrFvQeT+pJ7+mIkjnpbi#lpI`5b>N~x50!9hj8i@HnE04=Bxb#bMPS~}WU+(0@;si; zN;}}@45JAWlq2Dh6d}`1>h$mZF5b&~n9rkK)@o68@~%r$JK3>!DWql`?IYJSrzo%n z?ExDWoOOqc)2r^(rU=o*K>=s*CNyo=niZ;1w-PK4ZS9fY5Pq3(45kJAs?B4_pg9+{rgPLQ z3*;Vf?YrFlRn(CSP*U9T_}!hI%rl>tWq;FOpU)iIIn7AGg?4QkTUTb|_cJ>C=w<-8 zK{H?M+;XCM-(kDjt=XbEGJz(}>05*dyV@v+)8aQo0&m4Z4`zB012xH%=h|4@(*;@Mwrkvta08VI{?2NzI*GR_1 zM$u+Lwex=7mxx>W6fLAFoWVSFsY&&ySbMUeII@jt%F8n$nRmd1!-am&$^W05C(d9w za#x193;_(cQ_qHjbVMdcnYn*k=JNWocAWZ3H+={2WBH}FzWbw(jjqs>P8ClULOhA` z?ET=EC}~F{kYW}DRN`Kf-Sc(I*$0ySn}f@dqeUr{P`fz=6Mw6iY_3F6{*9p?5Incg zu@qx?=&rczOKX#<-`o!sQ*dfG%S1pU?)6?J(WCejQDpo=F}`hDfM@L(M!pu5i(zsM zRE}>Z1uicOo{x!8h#OzIpR@R1wr`>80>*{_Bd#@}F7TU~P-Lg1oAhxY_#K%0q}Z2( zaf&9|6h*kvsqOj9IhOV6s9nxvBBY1ft3~;FM>|1ZGAuQVdEb_$CT`<+X|LFW z>V6Seaql`~OfKI%?Dh*Btflogt2fkHSH&F~*xBq`TT7zE-6xWcNxQZPwv;xxH4L&X zz-&Z^fQqfv;oGaqss|_r2e&3n+{>6dPqL zl%hsnS7k}B|k6rffwckc(ciK{iUk_q$N#W5h=u)au@@J%;M)c{O6{q055PB&ik)^2O~ zlX+*t`sy=Kl5;D+K5%F$j2(TME*Ly|C+n#RB9vhIZUEjhQRd6-!;D=@& z4;vN8inqDg72nUM{a0?zXi!+@1V}Fd1nrSwdw#avW^Z zdfVxmg|U2|wSfdR#vC9aWoV?&2cVACD(5bkc6$pNe6|aK4ctdZ@W}2M5q?U@5>MXg z%f!b@=jq9PRa0^fr29i2di0%oUL-M!Lt+6L!?YttLM6Qb2=8Y}5+oqPB;!&UzQh#8)0zKWi z8tH(XR6l5QC>aALOkx=&d&!kyq}H86gwUX4aM^2EsrA}afHtg^(s{DumkQ!Y3gMXG z*_PlxQl®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 LKBMAKm-zQj+Tf$* literal 0 HcmV?d00001 diff --git a/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-BlackItalic.woff2 b/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-BlackItalic.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..7951598bbd8ceba9a6106a90ddb08a7e9db2b211 GIT binary patch literal 35860 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 A4*&oF literal 0 HcmV?d00001 diff --git a/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-Bold.ttf b/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-Bold.ttf new file mode 100644 index 0000000000000000000000000000000000000000..a3ca4b600afaf84054e7992793794dcd619bf6e2 GIT binary patch literal 97276 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 literal 0 HcmV?d00001 diff --git a/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-Bold.woff2 b/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-Bold.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..a23fbda63f215a352bb4a9f21151d1978131d645 GIT binary patch literal 34300 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 z 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 J61z+M`(IU;X!HO8 literal 0 HcmV?d00001 diff --git a/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-BoldItalic.woff2 b/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-BoldItalic.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..43622e68aebaeff9ea5195345de140d5b80febf2 GIT binary patch literal 35620 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Ξ4RjXC65o1=_xZFVik=^UCqfQID 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

|{W@3qB(}_tV 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�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 mK<$Ie zSF1hP^-)Znu^G@~t@M@J!PnSTr#qjHtD%9j%WQa`l73QMU*7<80_RCb*RI_>Wr|vT zW+tz)|fm{^QWCeR*QP{>o=4YscU z4{(-ZQS-W%fVc^xQrOYD&zdbPbRY*#2M_tIaf_eMI`tPqbX}7p4G-1(l8gGERarc3 z>bmrCwZ2)6jkA0;V>9sHsk*w>);jr_f7mb1cID2mU0v@jZ(TZc=+aZlyo3DL4?N|R zL4!_d9mI1T{Nweg27T4kZi#z@AvozW9lomv_*0Q^tyc*Dg-AHX6&UsGh=P-D(CdGe z;ETgDS+4KgQOe~gkE6`+>T8v4X zgOTRLz?f;|V~uPXZ&D%ArPj$!+NE{FZo<35U`T|h7(agVjvdESk`60r{z4GLd~Zg) zAoV|Af)f~zm+{U#j7Q)dqLa>C4ETP$VUEVB8D}(+_y2L5PO1wu?E~D$vZKRy8}PRQuZzHc%7DLy z>OPNv?=j$qfM3SzmR`?e5%A%x`w8xWUmxxAI*}8t`$1#3{Utc!2*Z5vD4h>vcj|qh z75dc(njY8T@LD3~k=HtETT{;&_nPTi50e%4R5Ej@r8+6L~(^(^l#nzG{+@wj`dd3%B0@D^2#616i7#Wkj$no1PD%Yl|X07xRpdP-%6oBhQdRr zk}b_c=jjc2TZj>)lv?v@`HZo><7>(aH@iAct1xSeOj<#a{1{b&2Gj`}NC)X{J*BtB zI-(tOBu;pIE{bMxkh|M1dZ{sILs@zqbc9nlPZ zK=tLzG2Ewp?8DY|Q9Jr{T%2T2ZKOxHAwPQ!O>jMsvE89L*Hi3nGya$H$NCyHfvLlI zzK>^`-ZJEg=3*1qWu@Mu*J6qu_l9jF9TMX{7^3^omX>OUAW&qb4f?2g^N3o!{{y!S z0#Eat_J6@N<>SrgG>-f9@#VQr`)!6}u8qh41#<>$GQ=m&2-;-OIZ=@+I)rk#P=}dQo#8hf*zeHtt>&|8w2TSitY+nu}L)o z6XnuXn_C<4ksAj1AO6NOXMh~?wFm5>K4_=FCUA=hk2rfFqMTkCM@xMMT{JRJi^1ze z%w|W23Ctr&$@XPI(>ple+=8cy4j6(D;S)e7+`{D{Wlx97e9;kWOlYwQWok&@^I?Gc zY|Q4o!m>VkvdJ;LdU0Xqgj)IS+%vEUd8*4>>-}GczCY{lEuLIj#p8l_N1{DnPG#Qh zRV0(fx(K*UbUut_5dyDw$p$`Y(>OSgRJqX~hpsA)TQev55>eX;md&UIYg5)(P#n2z z%Fo)1OM`0y)*YIg)0xhl#<~OE>u_}#aK%r#UqQHmzblB3xrgKRP(AyCaK78y`9sU-theLc!(K zRFD;7uu~uRcCCcx4)vGfFUR5=`c+$^^BeJ(k^O!p$PeZd>1isbsb>hzcJWbF3O*&{ zt&S1#mw6rG_)A=y;P}hT6i2!(6n~i!a?0v=VRheQy1i!q8lP{?h!LDFX{uYYB&P4m z5hGT%wNcu4<&}fmue=gXW6dSsX(`LbLZ&I=90YLkedzGrVIOQ1euQsU4dwl^jvol& zH$~vnK6@v(6Ire_Tn_teJP*>v`)sZc${-R>`)nPqBH&b_Fss1(Po&rO}Rt@h}kda?}{(~fFDrsbjds^f0Rc+XCj#$-ZQDx0`ufK#v z&fr6T<^#RoAoAR;Nl}0E`Mn2Z^M%Jd5diHB`jnoD5ZEwJI-%C`Fgly z3_|#{VHxR44vCA6h$X`kjWd{FECSw~T$oqzqw$grBx@OnmbAjN@m(L#*{7m-aA5`I z>WY!`f0A;3qJ8)7Hcj@|MLZykx}Ke8QEUa!zsT-*fLX8QNg{fdF)o9{b4 z&o!-e_^Q5rR}DX9dY<#N#HaJdzGoltyHU!*|QL7bDkC_#pq9*t?d3gMpM5#Z+QGRD+|FG}b~fF*_BshbCR%lxb82yp1Y z0Yig*ft^i#!7K}30RfTS-1dkd@+V#82vZn+l_NxH?NWW5=O zuXH^HcU5o_ix)^3cU9-L=uB#Y!JpMmEN3ly%nd3&xkkyul@33tym5Tr+RfJ#t}2&nV=XOJ0sN1W#*RmP zxo$I}!G~BkT>}8Ei|a%18zbPmf^b-*L|eYp@q>Fpc%o$_{+=LypeYJJxDV_D{B3xr zXRw~1Fg9f!ngj1f+R6(BO!6wE*uBJS@L32#BUaeoJ% zQaVkdU{l2DhOdn1cY7U1wCV4cmlPLIuksXS7mgY{pl(K6-R$Dx5uKjmOy}5+LCa^w z%sC7|wNUVttP~bejApWAKiQOIz8#}}Mj(CA4Ft^Cu>iQOCl&KYom(H=3%9DV-R9{Yc&dlSI6 zifeCtW@Jm=H`$UcZ;~ZT^1fT%V#~W@JC2h$iL=;=6FXj#*oot8Kmtudp)4V6VQHWt zWh2v^1xjhl14>&;TUuxz@MyvE_d9d1WI1s{`o4eP`~HFPy_!3B?#!7p zXU?2COa9pge|mg;W2_NRddCg(hQ>k}HmhAtO7tJkw$}8tk^R>Kpj+J(qVhIm*-GQ(@5+9+^^^ z*S6f8G?b8(VTg~2Om=0bm)YXeVoZrGbsjqG0d`@IohQy`u?)W0IdrAzYyfWZN%dJk z1w>hcp#i-b#j#bv-&n<)pWYe-|A97_PKrdmdJT}z#}@IvgrMZ)O@lo>H=KX|!a>bw zz?%N!n-3h={CGEgGZ^2z5Z_E<4enZwpt1O7U_jtrC>cQ0Fa%DCaaN%Er8l;bQ(M2U z!ww-KUY--sNdbAFozaBpV*&~+f~Krfnlg8;Y|P-G+8o<(9yKU$*or1$jU+f+k9Ayw zy?vXzMF(jIT17%vt@Pr;d(bo()IlW{jxK1q!zzN)&D9uosr*QOk`*Vfp}|^3Rv3b@ zh70Qw0cF?Ipv13F?aEwe^aGT5>c0CX@ALzfGCq}Zd~(?D-3ggIn5;cQf{pkxGeqDo zOwdFi);pps#qeIM-OCu9TS?2&5Y6a}<^~6ctRiTFZeS%?4df)}FN)?{iSOMI#g6pc zUUrwB{+_tttG^0r6$`lMuKDE-z0N{j9JPYNj{*5xKXmTpdzcePv+>& z1q(wfgB&zTQ52aYNl&HwRG)^MzlEUwT4P&Y&x#w;?b$9md1|sd2Zy-L^ULhasscn< zqV~)7Nc#Id*>|s8Ny#U2D<3*F-z(Qq@=30v)Z>-wxFB;RIC%5Da)eXs z@yZdDeA1Ip>QUq`3Ox5h9+AX$yF;*frNe1NT2t2M1Sl#&0y(OXF(S}D&?>|p7K(u) zaPKV7>A=PB(W&rPq?b5fhCQt{PFieAgIZPH%Wo8c(Dlm0<}b%N-50 zw;^p#bknau^_QwkpX3`czIqlT9kcpa`d0AH8h<+;_*k%6FnJsnzbHE{MJ>R8?4}R- zL>U?1WKB<~8$!}^NjyWgHl^wAnN!OX=k<}Sz-Q72pQlL<<(qdT%TVAp1O8H$LHSn5 zo@dIf{P~^-|};pc5mh_ebR*f>x*XEZw*TYC`B;OgZQlGB5u=dG0I!B_3K{`-=_4&Q`<&1pN*Hr48JVU<6KVOcmQvSpl z@}Km}U+nkYDPKOd*W2&u_WHkACJw*CtO$ZkNNV^Ub!z;@+EwI6iM~PkfV7{<#_Xw4N*ZKbnzGbV12~ zmh$BssT7^`UChp3DRU&!0Bt;4sdZ^k2Y`zu1@$Rgn%;V|-QJu4HD{SmOORCkG}vQ$ zjSEQM0=pB{rI4Z}NZhd zwzRcvt;@DIsm#I8r$v~)@gqJ#f&0@E?g7fY)F^hixriScs=!`P#<)2=SeMEJLo}@j zS;^KY+VMOR{NW4yc7hz^*|Ji8 zRc|EO&UmeQjWX8W469z_>6RD%a%LV-Q%OkeXbIGf3$lvr4Mni73 z&yM%?bD^iSjw<8%j5?37<3wclH>I3mL>bErk}RlBE9q9+5KsU-EFO?F(5{da4B&_= z(VdRT$SKqhAb;j^*qs<+r5-T0)=?p3i2`Ye&O*w-^j}GlPa&A!`|WQ(%op5njMRd6 zY|qu@xiZ9?SM`FWJ5TBckBkH&kgUjniVCd<)c(29Lr&v`MA!LZM6jiN@?Wt+Ko3cY z3BaV^3gnmg^q1Ty@6{EYUW26`6X;76znWL0-gxW+zT=KDz=S^zf;hy@#K8j7lC3$p zYqJ1S2oN@gH)guHXppWeYP2NJ$U#9f6=eI)QqJv!MlrnQOZg5DWC*v*5#ac=iZ$@b z=8j89z|n^lao3a4M5EOPrKRBbtQbQalmexN4=j&VU$TuZc*t0W2A|s4TOz&e486FlKjz&ZR9_s*)P`Fa_ z(=}_}mCQ4d_XoJZjgj%9_IaLLSC&$F#Kial zlaXJ&tgf!RyRL3oUut4;rf2nU)CA@% zZ~M-`1O0r{{VO(ae#Vim0Zar-N4-VxX&8!Ad_NpW^3ykhzjuiP#xMk3R&W49M`?XM z69=TjgL^Nz^uh}-z2qXr0KB9k_}KmTJ@(jr_aECnapCUq@!c0r$g$|a$4fAlQWumI z`$$ZMg;nw73MD$Zy^IBEAwNdxGJZ=mGzg3MEjN0KZ`@J&?%1wfyZ8-Fo3P*jKG~?x zA;_O#kvpHf+=W8dj)Y%udx~GgAX5ZZh-cK`b9l?Z46vmmk8bH0br&SzICzo{W)x?! zI^pmn{<(E^_Uhb%%zcfcdyA@W*|lrSKRW8Vtd=ob*2uCsL+(3J5x!5nZ5qDsWHs)p z6nIKV26b_Qx`5guE-GC3qIb}%Q@lV*BNj;aK|n~G4KnX^^2P`^1SX%grZgjv(s|HQ zc}OqN)WBVQdA=9SKsLQC9m7%dF7_hw}0(xTlh;J*IW1wXQhBoDZZ1! zn%wnCF!F$b8#yunPY2E&aN@h+AOgm2FuuTo9nb@=O6u@?0fbsoSaNi9jLimz1Oz5U z&rP+rP>(Tm2s9LDiG%k3jqA$l&tF)-FQcGu^_-g8GHYYfGXA{h)%;riLixJ-<_(ou zwy}mXS8)|6)ot5vNyG=#`A~v!B)d+W97J;gJ0y)T(&;rU3>2@-2>0gor0dfiAQzpe zgX}Xcsdyb;3QlpHFynkvcdA~%Eq$))(Z+8aZ29`i+VipsS1xRr7hvov4lOUw%d3DH z&5IR7b&VV6Jo=r9yOw3x#~Q{)>^Yu0tBVS&s|yQjB#eo^Wdg=p23>Bz6ygOm)a$BR zk=MjX5rf_m$F1Cw$G`AAeExGpxcqoAG zAniLPuj}WU6DVvpBZMxTpWARW6rbYE^m9usZ8H@Y=nBcu*>P?{fhQ5$QEHL#f7Bhg z@WKOi)x{N;ZryfCMbQ`Q*RS7=e}u%nBO|?a-O;gKW!;18mX$Aw{$Sbi<;y%tJ@|)4 zStSkgjaej4E2f>YVt_F10)bUtuNc$w?({LUrTctotEXjT?dWG-J42V_mV?cgsH4@` z7KqWRmV;P^@yf%vi5GpNHM-uOqYNO%4C6)PCdX_ZCdVN;X5`B*Q1L^DCldF`cUY9v zpT^z*)Q{(m9@>G3Fz{m++eC{RXYzfl3yLqi>G#1mD+7M|`%;!x-Ar*=6uCqx_FSjL z`nL-rd>QxU;=o{&h7rx+n$JZJj%JYi%w4t=rO3Q`137_Cc-% z=)gBmoLqyvsq(yUe~4`dq)0XlBKu1XfYiCAo?lz z6OwO+Ai@xQtHZAk(2o{jYz9F616Yq#OjnhnzJl}@FS*k5CNJCNc?klzhacX;cX+=3 zBV{~V0GE7xCz)tJoMveO53Gx4rTr3ry?{YA$t+3Ie#}n-55dQ4YIhpxzp1bEiXGMG zXF2({khyrOVxx^rP$(*ligNl{2eMQ(0oWiEfQWO#1FhN>Ujz2)v@X{Mq4?HinV zp4;k*i)(9(i|f#K&dM>4W=R7i-N%yUqx%w!5G^Av7>Slux?c`gl`r3hC}5BBKTk~l z94egnC-n=lMpJBZ2PF5Gb`T{Ta=w$T%4UjyU;SxSStzSogkK3G>bQsueFT~OergdxG+RzLM6ALif1I&P7_!LRWVeiweH$=_!D z?vc-}^0#T~3%*+ZMoGLMj^|rtd2H+P+l=Rf@;Btt_-#b}>tuO{{GBp2#aGGaPWd|u z^%o;*G|5N&#ad zgJWYu!(+W=b?)+VcO40Ryf8RryNBe_ zG!PX$W$yqc3hb%kTxEK-_{yCF@9~`6Yt2ijOo~lhn$ft}npZzC(0jQ9iZRhWF>&=S zn>%X`ecL-;>1@DlNWz+th&3a9#=b#0XHN8~XL+{~>gIu%821^Uf-hU<4#w^R$`8Jk z#Y;KCd!4?wkXs8^#?plu-AS?4?kZPvWpYA7d{Q;Kve?$X*lK>I*k00Ti0-l4Y-^(Q zkumzHo@hfukvT7v;3<4KN9)R2_7vWuoY@x^*g=BnDJtPxE5{#yVc@w%hk9yimhni> zr(<%=R6I^#-)*};8p4=qAhkCkP4Hnw|5st zfK=)_OCi9MT$`#}7Qf2Wt;_U|4s?pb!X+@$Bm(r6O^e^UMVznPufW{6h$pu9wL6z2 z#a7hRRofh8+{ODEcAVtbNiU zE*p9lEa=IwTddt}ZQVA@fx>uGA#C|8pPg4;Utex74hhRQm(mTO10RM}wT{*!Zi1!~6Gyp8s>sq<+qj93NO^+Uo$QtCNV3fM z8WJRE+Py*@$crIsQy6(4VMa(Kg)-Axg}Qp=x3IP;-{St?G68p1i|1H6t8$mmPCJ1) zip+%;2DTP^Kq-2O4IqJwN)l!Gi~mcK$p3gYnn>#~`mz-#lsbWR_*A&bzQ*xE`5f!= zsePq&8gO4HVSzPvmiJR&x3EgSk9B*N_oD!-4f1^;p7LDdgC*)Wp#A~*9P9cl^`CXz z@xD6l=pXo!S-x*R+gRd#bu95dt?m-9rpFr3|9=fX=#s3PdXKLW?*JdQ4}qu1&%$or zSl-9K*_To-o-LPi%Qp3%<~Ec`6Od*ytEjvQpQwhV#zDwRBm%s2K_xC?4HdG@u*Q4HR$OSkjNa|9R>m z;O69X-;LbG|LU3C%r)~g&a^MzMB573arPQti8Ar-IA8#0i}7({5#Yl@5rUAbnSvun z_{zh`T)?{dX2@HnG>(VI{^bv@2ON8HxA_o)MGYNNsZwujL@&{c9Nol?7p~hX>17733A< zQ$-qTi})4lp|*rltOIG=&U*r})X8NNjD-?m-Gx>_MlKV9D1g#!w;h)MP#5I<`1_7{ zTGr)o+vtSHD;S*a*eN~;TpF|zwRYtl%in$E$nW^u++%H^w$ZskJ9|fklYf2FfJz{D ztuuTY=qUtykzQADCfgf^A^wPnA zmx)zSl*R$@KP+K{8O!*K*iR=j3oCP%gab3fAe9v)NX5FO*^Qp7a#SEzKu;h}W8(ta z5d_ncVu?vicaj+=6#0Eh`l{$hA~MX0bULdJAbr#hi%Vy^vp1(O*88MhRJ_8+e->+?I~Hw7Klg9MvEcIl9o1>o(V{1 z@EbU!)S!(JwSgusU~drgC?9@JNT(itaeUJ(mi%eRX3;d$Yl<}UY~Qn?icAl^2KdW4 zD*GMIY;FrIR5i`BPIjYu1f@=Pb;4qhk0?`?=Dj*=(Vkgo9q9Z@P`b_Y(m?BEn7N{xR&%NmSOZ;Rw_EL|#T9BX8cu|M!e6gexcYy=T# zyaF(CPPOyP0V5m3OpS}h23-;J2?)>CIN}tk0%9Udp2bP$ZA`}7r88Y1bQ-kc$wCV! zWH@oABWUDlR)0Ak*$gm_f)$FW|i{%~epdfe7cjEP%n`-WJSTzCg z4r6tEzou!kKK>rGClc)$_qIn*3hIi)O43*5(1&O)tN<<9N_%)5SWuynWg_?n zqSd4#!NVp;MkXKLEUw**cC3YMSeJMWyJqb};dDMN&sbeXbRFH(9jU3Azc$})&tKd4 z#;d=u}%58*k!$3OACSIgdooctW#bK!fn{0-$r`Mv*E zJ8R+LXd7?->i#L;EBV>BZIa*ez9+=$S$|ivdj5O1 z>tyU0I+v*DI^=6HzEJYZ&vIc-8Fj`x1_%0^o9mCX9?8AwX22Eiv%jh3V3|kd@Sid6 zvb8NO{p;#;ZoVn^NGoU}Xc#}j4&(b9STRaqdtm_1ALPF4`t&p0mexO?seFKy7F|}>HLP$3%teYZs7kS2 zq9S=|{*KLiF50v+zdNNczuh)(;lg>g_WYJ)XVB;-S8ejcx8~pJl$qVg_4-v0PExceRM={00?$#Tx?Wi0B;862GhcD zCQL7q`XiJ@aGSxLR;V$hL*xh*IxnC=$kbTaw2L5l6EO)oxS=l6Ns#hH1#pG-?Nw$vD&KW|59)Q zoTUO!YA_x-WIvgjlmP2pGu%07f)EXkM4QA;f>nbc6Q!4`3mDMLo?_P%0%H^;{whKt zESg^9PcJenxNIOJQBgD2yQ6kFb)|m^}_LbJ!D~els>n|9K z+O#3iX&!6L$w)Bk!(*I_8auZ{ZQ2;*NFHm<%}BDvhR4`Dv1!$S_gIIhm5QJ2Om^Mr zp0aZxsw0#lPuU>|@DUQ)cZ$dCu$dmS3%~LOKp?J--V&ttV9D6q z$E2r4$Kr1|AYoIubg0yTH^Ka*4U=@?p%OgWPQ}IH56t%Yp_YO|$JWY$ON`y~IG@*T zykwwi!ckbzV#_THzwXvsuM02B-IAJ)NxEx%Wk_6H$jb2x5C}Rw)m6DNHFaf`i%14b zg#WKO&_PTj+$JSzH3X@$L8S<}*ii!EiB(MyL|bqa2bXRZB<*OoV!qQJv(z&-uwt9j&aYf*7+AR-ZNc&- zI)ST3Ht|R-R6D&s9@4R5(@6pO74<46VQaezVN!KE#r+(F*om;ZKfN3kK%>2$NXd~M z$|~_uA%ds9Dr}5p%qA|`YE^%hw3x_=J9;8IgBz<4Y`KO%>UnF+zNp%A{`d3Bt36ZP z>3I`+j^AqPDbJFyw1Q3)f=*cIR6rjU4zQscnpB)Bk(*p#jd$ls%5j48aw(Pk|ti0m$#q;I5wV1 z1Aq`rqm;6Z2pXV;HMUl(>Y&j6 zNRDwPGVwG(8#plAi&E097KU++HO*p%d?Lwalj9s6MYAlO6jmv)uabN*Y~-ejW*DJv z7|)sfcrN`bho9N=atqhAXXf07f6#gyURk};4jM#iU^!Vy_=Vv_KPy02TE$7s5JZYd zR0SfDVWAH|aO-Nk2?CO7vXFj2I<0Ocx)PU6MRBe;olMX{ zaf#O6n+Jzm@bA#A_?ME`+1oTf<0I#=bB=Swd8Bn2)FGD*FZ*L?ot)Qz`5fS)k)^p) zjj^FYSXD{41kKby(2RMF)io|IPA*W)5EE^sWeGzYA>yo2F{LixKEHou!42Wb38M+g z;WrelY}p|m-sgGU^W|%Q8;|k4!!0r6e|rsm%H9{b85=MKuNr_?32c))1Wu$Gw7aD* zL5kIF)x!A?z;uQ@qhB_f)U^fPc+%;RhJE-+Bi5 zO}_=GSk=_$0pCR1>sdSBtDHi{RNzFjl4~LzJcN`oL*NfvF_^%U@Kc|-Pst2GaWaCT zvr!k*1x5twB6dgdNTvyi1gj7c5!eHA7TXpc40*4%CoBlwGrf)wVA{$UopdV319fM4 zorQ<{UdF<6mYT@MrsnK5g{@*?VH6mT>LDlHr!~l3|1Z}7;ufbmc%WSk9r)pBHl?AV zp}nE4wWYeMtTfY^Znc;(oR;V`z12ptL-kO|;q|FN>kDoAVW=ZxYhao}fzjnsw6lP^ zJ~1=aN}9>ovD@UK8|HJsg4Xes>pC^$ufk;ZZk6jsSSKXkPdm=xMHjONqz3MNx@CAEA#3 zhKHN%xfzzE{vsHd#D(Wp)VM4Dljwnvbe84=`H^dJH-^lD+TlD5{^Y`d5TT*LJuvuy zxIzjc6<=~zOHyJ2Bw+XlEJ zL^*(%;DdJxF0RjSy4qHUg^!W8r_LM76t~7X_;BLe6lOk`cKBT)VcyXhp!0;QBVMjea zvohYkqJCMF&T64Cn_jCD89e_*gEx#J-jLQtaCdT%@-c({YfZFXSz-|NV8#M-+T!9{ zSY|9MSX3Texy84n4AX)#O;3~9Rv5@5KudfaHc7N_5<#_16UfjIF-=j!W>VBN{8lI` zmUS;hRbTLt)L3ssBN{(RRB55)Rz-e~*vrI_$|PejBaja;tUai!FSVn!ts`~S!l2gb z)KTZ0xpSPOscwbDe%G^DA+fvoUJnw;EabC)#Ka(<#RgXGu8f197~YDW!Mh?53k}3} zRs&XPKy9Eh7w{q!eiVu?5lm8i4WZWz6w|=`Ta3N56|3VnabmFbrMtfglJ0pGSbobb z_``Gm_BVp-ui0_FOP+P9XMrSJ{xzhvIN74-TX0_X{*3c7$dG@#i3>j&av96Q&PI=O zA+p*4;}o!%f`bDmfF@w;ybK*G3}vCR)rtoR@05U~-h5){#EBukaPY*5!Ka==NqoDE z{aKjdPn*suQJ1u_DG_E*Jc`irErw)JK_M|8Np>6!O9XsX^4tieNu>|0s8;w;NS}YfrL>Y`cV%5D%yvlv;+e} zR11IrES1R!{50Q}@e9vX>8kYYN1QKyTDr=xkA=M@Bl?YJ%B=f zmOd~pup~XbjMMk}J%>cD0VKC>k$PQ4WQP?w8?@Qf~-s ztb%kJ1{*82?r4xHrT+Pz2lxjf_2A~~H>~ONbWqo3c^ASR!U6d$dKce&fX_$s@ao3C zH5;zq?Ab0~^}S0t8A+OSegqpT_`puu$m%ezI4aUXDKIQDERyCrSSZ@bk@=uXu8TOn z#8(43@jtYRKj0S+?cYDNfATN*6!mWiA`9Z?MYZK7SEMJ|qVkOM&XCU!6;{N?Mn=pjEUbvrM?_TqgRXwR z)%o*Nv~3)1E0JeAnH0`4EELoQM`}Pm2pDmX?c^W{8e#mSVe_Gfl}2(JI_f!7H_%+! z#MHDI%`J%IWv4eo;tS#a51=$iXBx=ZN2e@YEXGC9W>0WBWrA&DG$O^rLpvB(LiQ2Q z9{vN*$seP6EMV#*(Isw2Uo4QIh5W#gW=SxFXdsXFGCNZCC66PeV2=~$BUv8m8GS;)K^~mMOM)c$HtnrJ@YfxIR_jg zmF;`lZR@Q3LsMx_MOH_WtGKtKv&wUvRMyd^RJKW!!_JlTrSi}wr!6TSp0HrcCl_~M zfW!kjrUFAkyJylqRv5A(v#JG!^|^@uv9q($T4ONOSQ~wJKg$Xa&q_$KSW>vap9J}n zztA(kbEVbkw65%&-$Pd%M`mX^^U~AvC^@sTl{1*-I7jkeZHd8r)+w~pnnn)C712aV zG#bS{W%I{ZwY!|oaj5HT@9;zoF56~z@{b3XOZ*`j#Q&s?;{Wvb%1BooFwy}=%KD-T zJcRl3S8+)B<>lgw$w19kLfQXYdr$3DnQ)8GU}@_87QEDeMCTVe#3Q zb^M`0&vhEOs-kaB+iZ?0d#w;mTJTw$;xW-mqCa+22-EGk5MBcRR=i=^`DJ`b=awMD_yLxFbMYAXo@Qj7RVxEs8ZY zm=mn>0ouV}2&_4WDhEiokb=u3Y|AL17fD-^1Em1%oXVO5AwWwbvxBIpfPiV!gEX^Z zy&n)65aFbFrh(v_R0Dnq3@M{mX~CKDdF>h~Wli4Gw`TE@zP=@?Ny#ZGNl7XEKKxj` zM$Jfu)(NR?dA2M1=_8}iPp>I2bJv!8c8`q=jm}hA2et!Vf%X~js$p&HJ|D~wIdU3i zc>ox8YvB0@5yuu9>EN{dpcWk(r3nrWTotK{Ks*cyxqs;m3BN+OySUg3LwB3IwW*=F zrWm2L&j8Pue*vCmRhO8yTgoO_IV|(iUs5diDme2B72uw$Xb1ptejmnxZoV4yrwu`Q zt!h0$JWe*~LN@3^AWkTQ9tqY#+yVXpv_W5_*J$)2`-M#}ys&BMRaafbjUEeshrffr zD?PV+ZYLU{f!vaduR#MP7$-6=tU*P&rVzOXx!?iHWyE2YLt>gD6QC0!?+OH#gkX{e zH|B;SM^Oo63D!7=^&3r3eAqhgFHbf<-I*Axj|dA5g6~>gd}wS^Tx?iaXs{lR08F9Z zOv*LjfBx=)ck%xva||&t5rGN2gGrt;bjaYXFy6|>bWE_1;ioHPjHN-t|F9- z@zM%eh%bMB{pJ@g+x@t~Fb+{&ELsnpXVyrW2bavh zesJz^!WE8(cJcD$jP&%rd>u{Kb(q-x*%It2Wo}$XUCvd22&jYT1V=(a9Rw<-&d-Uj!fIoZka z#t^JCSa|};=;72{4RY0$DjhNeWet*UWf^%tXK-hZeO93N2N^e{%`B(sA#-1Ha6`p_ z|59TfPEp?yjF}O)KiHTHHUUZl_(lOFQ>&Pma@=oMX2pWtZR9Tv^!EQMjz4W=)2@ z#a=W&Yw6t5?)2^L0|zJW5d98IoHHdMCn?$H(d8b_Y0N61xk_iJiqD8h(rq9H9Q)1P zSftc*9Fn0x&&W=jkU%WLfzo$Lw9)^MZ#piC_Mn|Ijs1Tf5eU zxs?jrvUH3~9yB|kSzrODUs0H53L#?zuX&>qreWIT7-pV!n>i&totSQ$;!_652{j!> zETuZamZ#&O96BH6Aku-Oa$>7NR|s%MkzSjybF5*rGsD@PnO&5ewzs)1&1|}8bW5kx z(vhB5lw#S_T>stRn2^qk10!@{o%_o&GFJ4brVN>qY^m{gWxvs6 zH5+Y_mF6WCr2!$ak(G{GjV?g1uW%3!7EXNuzVvzQ>{3}d>z8|*Wln6-OER#vE9LOu z&=$8aElq3&8BR)cAW5|JW1qhi7Y$zpCP2gIo6Qu%#$0YLD=NszvfH9kqf+7x zQfoI9D-CUhPMyQm6mn#GqDmYiCf^4mn!85KU0!^9Z}08>{olslwTmupYrA++7ya#8 zvUTe~ZfBAurreZYTAFVvkFg|o<^-<#wk%73S5?ouq^s-e^X7fMtLu_^om%0MW6aU|rB4 zVzlGfEjW-iSE{OsvI8u}JTI<-E2pxo44lf^(kuw_7AK)Wd<;Qj+TVe~&`HC|X=tG9 z5J-Au)HLA?Mx)|J3Q{WmrG!Plgv%FBA3$o>JFct?3ODY1ao(b$yqx&5hfE2k(o*q! zuLOnyn8{B^s(c{Hab6mE1HWtToV>;`ZO+hN^sxqgC+0#VPtuG^zCIRfY6un$tf_jE ziGsgRCuKLCRdTk*NWN*}8{*=@ZRLwAwhfPqMWdtS({a?Z;<3?+NeJgqK13O0TS(YM;v4B38`vb{AeDH$0ll=w}K#>}inhodnov(eF>X|`l$TFhh+!P=nj{0sEY8-Gzbo`lLITIE&M zgkE5D+Z7LMwtjiJ?8EdsI+D^UN7{IzsuofQpjtSK>ryuduGje~CpOk|uXQm~88X6iM8WKO=vC8uhpSNlU z8Ut82O?|}Q0j!h2#|J&)up;KP)IB8A9AzU-_ynOCz$T}dRp5l3lrPib;y!CHEbL#= zTGQa36Bm-25CeXuVW~F2lolE7jP7Z)uuSrVn%qn| zSrC3|f`W14tkba`xJ)7(0(F5U7q}|Lmw`OKM1Rzxn14|1l`qhuO-I_N7RMgSf^go9 zS!@=YHO*i)q$VbigK;tqL4%a&-~RigK;Wbm`_$+nCAg5p0n&@nbagLXOs=0io35Gg z+;;UA@r21pZlG@FCDU%8uHsK3j^R_D8u8Q$c!MIRP@eUqYY804W>d<>9{s7A4v&~T`mD7KuSiae(T&^mZ3(s?+gGIvUBGs2Jdj!iz@Er_Fm1rkoKjPOs zVmo}2KOivK4|txt{PHI+zg)b!Z{I%Ir>O+dI`z1qSfplI6Z9vjBI+*$c|Q9X0u3EX z{NczEga>8Z^KFqeMe#o%HIwf_gvQxkQmdH2yI!g#UxVk`=We`ijmUcGCFPryB8wHs zcN65h5%i(Gcs8L}I>@)s-of5A*WoQZ5K{qoCq=&F>oau|iln$Gz=T$sf1fp|!HD#D zZQ8~;Nc4TGi%*U4si~hxdh2Ir0qs%c>mX(K{HT7Szv~RNbF8PonANRqq!{$Y{yC{9-VsDQoWBtfrX3T2b59lstcaauaC~ zG2xjM_NiasT!?J#zj{ra#p<2_ApG{`{_Ekha8{U$38ozLdbMIDN#@40qY^z110GON+5tNSBDd%V-()(p1_5 zE3$g1rhAUh$&axl=o7;9aiUh<$HvQhacyfvWLQ|Dv4yUoCPhEh^OEReI>hYNuyeGZ zpyLG3OT0q#^}?~(R6ORzd+=8r&lbu)K<$u=FpRX#jR16h-exjRZ z9)rWbnfc2eu{!+_jJ7@mS$PnFPRqqp8#mUbj}8sB#GB$Wa$IxbajGt|65IjLU4 z*xfJY06#wj{-|T8;Ab=K9-%l&gn@Q=oXrQi%|K9Mvek2y#r_ETVOvv5XJ?8;P(GC^ zTBaUGEb(BLEn9sKy5zFGIQ3EV$=k0_w3H@m#j$aBUPDT{$xL`pwBSyd&<(*)O^U2n zAA)6}8SPXEl0KSTB*~ge;3o~If#6mS7G&;esp9_;lUW&SuUVp_deW!Lr@lY+!*ijd zbnyJ^%Py-21qLlg+}ud{o{z507?0CwdEiW1UQeVP@bUa*>fxy;r{UwZ4MgKk*R_`x zg48SUU0TITuw82;2R!co`` zGt{(kI2^DEohO56KV9L~G~%5Ic_xeC^c%qiXD_2fp*1q2URq8o2Uc1|qNPT?mq-uM zN@-DBZd0wHI5sTDl538Mi49v26cFT0H#-V~gDWCTdTrdQIT%3CGid)^ESE(w71JYt zguFFe8>pF`a7MAnOfTWoN-={`3K0rHKCPe3oi{hSDJ2<-Ai1T_%_%6F8*Gbp$uNe5 z|5M43!~W!7rq9|l(C6Q_HWPVnh6RD=rK$N$hn}1>O$twqPcSKUg87r%>+&0 z)Z?0KP{$eV&{Tdza}Dt$cZ$iWn-CitG1c9(^CBAJL$1GKP)r^=qs_vVCmO+g zy;I)H1rYx+cm+zMu$T%&*&L5N~k|m%HErUJb8Tbh0 zZO7}I_bu7CxtiXUyx6Jl5+0w%KWG%*p<8)ZbJL+iOXPQtYP2i~u`EIv&TG$sZ&dp?L-M8X0sTDDMn==vnxMbLJI3mwW>8 z3&bZ7zd*1&4slz&<{)?lyZfB@g#QkYplP3-N6;iOo#s5?+E>`Ld3gg(lFA!Q;$-U< zw7JzC0$L==eru6u3&T#4<<{PHMx zcQx<>V{|V3fbi!9{1NZ!vXYd-!W4;k#0yM<7dVQuSL~)pKs~!n8Jqx1n=%dY0Ay0u zeti`<0L`+M#S2U9CWx3Z=jS4Z!rS17e0;^Zt(()}Q^n{NGpY+w>UPLH~Ul%K)qnf`)~&Ovw+V zVg``R8w)=8STYV0FpA+~ek}Aky<1Pcay%E8CieyhX$wGG0r4cw=4#ppNO&EDHI+uz zoiFQ7hyLEFoPv*k3}@l^1ewbc4-+G~1Y*x1H7cRK27N?K`t}#q80SGm9q5t$KJ%Va zkG1GI-=34R5zm+G>8VH1OYh#8c-h6Yn!$>XwwuxcCbfYqL!R#L_I&vm@<&7ods_VU zUwBWH(0dtZ-$BsRa0b2huY&Cv;HtTrD5Tt5sc`)qqCl$C={`r8&JIt_D{{{!M-BF& zK6oP1MmD|#A0kt4iCV;{{|L5kPxklMbL9|9MjC}JC5iY#t@&Th(38No+ z^QL_BTs-T``)H~X{vmQv-^<=Snv-(gXvEXryr~aF3va+aS|gtE=COl(iv1VKJj4@9 z9@g)pn9nwi6_^&yO5H{9(aAUhf=e$F3O6JmpMVOA+^A|+V@e85XFxzebU>7y&a{k( zEP|6a?-7#}GK_Th@A;xv?}}=)+Z&@?U>n5s`zKwchQy?#L_;agwy;;UgC9}83q5Rn zmoxeG3;F!ucN!;k~u)1kp=v4$*&vWTaf`T3{!@9E!o>gV^5&G8K&6=E)5DpJPoidhXqeE4$a} z&G^g)ZEiKi=|ZET6U?z$#RV0#46mEnzJswb`XC&p1_p(~({-XgHaI9OWQSjiiP!SB zIi5)mu-3Gs!~i&%BPP%*908PYIEa%m7`iPbbx0hCL9#wSAtAw@0O2@{@oX|k$TTbD zDw5I?RkhJ-m@$%`>pH~F<( zNcq{7a;!tx!bd_#i3bc%hQjb*R2jB}u(QF~_u=pz9=sCWX5UdN4TC^f1MDt|>dJVY zT+Cbc0}{{6GgTtlfk+U$#k98U^4u~8zIn_Il>7X$%bEche^eV)0XXHXdfc8FeVM7 zlt7wZR8?CVao(P|;!L1VVq>Z4=mH(Hf1wmLH!b zBvpZyj8?%^SM0`Pv4@^2*1F1?Nf1jQyiLf$N~Ow>PQ_a|vypIYlL#B7AZ&R&5cUJL zt+Qh47TJ1l`x6j5D1n*T{zuFlPK42D@{E`YgBzUIj?KhYL`fYYQwtrbcu?O`sF-%& z8B4hx;JdXNopv`F@SvAx5)Wbo!U#uz^65Z%nB2&NIw>MN1?Ndb4D2CfpT=&<0t1PN#(0V7 zPQT_#8cOZ`r=KkfF8z$M6 za;!s0|6L)ZUqvXticDfiKfnBPmG(@6P7*GKuyr%&B*^hJy%T)&G;#;=o_~?qN#eOv zM8dQ6vQ-LAnPmME$5OpGMi#ZH@d{1EhtEv)h~@#ud^GQL9P=Z2F;PVEfL#6*Z&s|D zP#Q;T3*~9(}$Zng1#A_^;o&(c(Ge`AcAC z0K5u9x`)GJ`HvQ(|MYwdI{zJ>LsRPlGi6QcL%N7B;ZJWN-9c+sCh^hKr~mGx`C#fd zl*9w9N!-Z_&zQboO@SS(3H$X(fqUAo+aiB(8PHqcZ=6`&3-t=R4t98wv0rxHO3()cbwqO85Rr zQ?349F!eX6VYN^a9|JDK$j5cIg!$^r*XUW{{|hM~7VtfUcHM%$qD|t5xIbIEoH@n0 zrsq-D6zUvhVP{OgWp(1;mEN5CIA8^fIW>uIPkksZn0o1)(i*h?)N~vAmB#GN z0XIR3XoUfIya=%nw_zRq2o||LEJu^g@+1t0P^O!uBXx*nEF0G}BpXsG66NP1B_mmp z=BbIwbRbnDWg=xDwW#;yxYBbcd>QMJY)ED#6H>T(Z^ShPDGJGe^uJP$y)d;-a{_xr zC7Jm1@R!^=^=G&@D-dC90bMC+Lgh6b_XH1_$6rU(jMrHRVn$~$@>NP@+wkru(2LDx zjr?Zx|7P58WkX1jd^=)SZf92F+)#$0o?3Z-l+|)IiEzME#~d8mu6~K0 zE{)WA|TdEi+nJpg!a0{*12HksD3SiIB3afOH7!hp5FdDJ1tg~o?@o`WPj z0oQNiT8RY6O^x99<7&De*GZ(~NYF-`ipTX)B;-%wM2gBzrQD%YvM;l5FQHy>B3=Og5yo~aLTJxJg3+>dnB^SJuoDZeEejWXrG!|Yymls(H{ zXYaBP+2;@kMsYLG=4HGAvCdcWAwIz`;#cq+`R_!BctO0biPzXP$IXEi4SZVcQP zcp≷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 A2><{9 literal 0 HcmV?d00001 diff --git a/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-ExtraBold.woff2 b/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-ExtraBold.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..dd16c0120baecfb904c6b979f7e01b86c27fdfa1 GIT binary patch literal 34060 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 U{9nO%n-u;0r>rGHatib`=>Px# literal 0 HcmV?d00001 diff --git a/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-ExtraBoldItalic.ttf b/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-ExtraBoldItalic.ttf new file mode 100644 index 0000000000000000000000000000000000000000..05e26d691dc2217a63bb435b536399e0092ac77a GIT binary patch literal 98236 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 IJplj!083b3O8@`> literal 0 HcmV?d00001 diff --git a/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-ExtraLight.ttf b/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-ExtraLight.ttf new file mode 100644 index 0000000000000000000000000000000000000000..2ad4ac0604f5d03f04e3323343850b885ba79714 GIT binary patch literal 94348 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ð!Q(p)5{8%-SHZ{hbDCaj4b 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 literal 0 HcmV?d00001 diff --git a/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-ExtraLight.woff2 b/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-ExtraLight.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..737badc283986e256a757a3e34802dadb40577b4 GIT binary patch literal 33832 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 APXGV_ literal 0 HcmV?d00001 diff --git a/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-ExtraLightItalic.ttf b/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-ExtraLightItalic.ttf new file mode 100644 index 0000000000000000000000000000000000000000..b73b0fa93796fd1091e9fbd82be2ee606cf83b86 GIT binary patch literal 95884 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[FUQ@(a< zyv>$Zlx@Vn5>Hz16R=PRtK2>B*VKxW+kc(zTJXJ$Tvr&;7W)opoOD*@b24T$c-0B@ z)lP?at}_&lFZCXhRF6c*MMS-IOYE2Bc*v381{91dSeo;UW8=(+L*<2}T8#5kN+C7t zr?tv?nsYl1JAzl(mFtRI?X3OG2LdD~?|(R^6WSRv20gZdj1_b5rW3pJ;1ig6O3u@( z%fyk0!cyDi6-SPPUmj90uG(0Reuf+ydmaiot5oTjhr=C=ds!jZ6%CPg{hkbG6vbSZ zdb`Ovx9fhSkCD6IR#ON#h6wHU=m!_3T+4gby%}27xBiyiBi}`6?*`aaRt+8XJ89TV z_m<_bl->{L&pS7KjPzpX6QEx6oP9xWE1|z-eCX4q+JwQgT$ro(`qg)0K^x1!nw_eg zI2XH~!`W|6oi^?%>i`MA^lb5{R5NmVF?<5lYo4pNVCCS~Ik)|o39YmE#8#v&bb_zJwihS zaAO7Y+J4%?of%qdk1l0+jUBk(YNoEjaWrQubtyEn>}q_Cy@{}bw+{j|qUL&m9aesliM z03fOIFpsF$yu`jBe})|Sqd>v9qDu4e>6Xv!@?26)==2?sVKwVlw@kYTXn9W_t12DQ&0^eddj4ne)9 zIOl@SM@onVR&XI8f$L&4H52+Dz3%!{&I>>xnASwm}sHVXE~?U>7>nd^aCST2s0q8zHh zjWy+3xv_T`{P&i}yPd|vkzFc$S337w0;|LgTiR5#IojB^H=~%OBleU3e1k+GZ`3N!X>w?xDpb74D-PQYa4*2JR>JN}8Ov4IRbaDTcy#n}7? z1l^b9=gYCH%0`0uHh;!CEAz|gczB<>%m-GdQRq5)5X}$sH0pG*CjjJ_kXA(sBG)$1 z3NrHHGLgH>(=kV7mEuOqdJ0tHgl$zs(z-wfMgR@GKW7agVXO3Mo=#nnCvoJ6!^D1u zg&XLUQ8NaFdu$khfOi)jXCC$1!IAo{Jl&W~+GnJ%t%=TIJ(lelQYg(dfHEdB&Wfnu zcjtn&k=qeR?Xx_cTtu*kP@yIU!b(g4l!4Bx0yZCv`#SE~O`+nuX06Y=&ofZo=z@oQ zGG-hgS49zl0YCunZ)5xH_%JSu%)Xo7UN%exX=o8g#(D@$CBZoA{5_Ct6lUjP1IQrd zypssuPSJLw4M+aUsL+?Ua74%M{g3~Q*MFt~Fv1mckaHTTbXEX>_Ga?DIozJ+w(GFl zrqk6zeR2R`54$;=60OIz5_&14!`?c&>Ngg+{p)+U@~KQbyk>iy1b0xe^B^bBb5?5^ z8AUJ-DtmLKcm~P1u6Ik&>FO=gr&0_+{6&0!+HhJGN#qgxw5>4M;n?duQB(1O*2OrW z_GMDHzgG|X^RwD)LTAY|Q_SKdc611gbdx6MlH0OQfOS0mM@h#!V4^)-W_o#uPG4+> zuyG(mPb40lHOqbS1NTL(Df{I*uDp`TdH_h^RMZ=3nmRD+isqnVy&MmK183AL2S`QDUiC7mHC69Ez zZVIaXcpmk%-K-a*R6*oLh-05(f%a>2bN&a+&;MRj?{_!7PEgp9bP1J=N~t(29Q8+BYGpXg}e@&v6ed)4A<3byFtXhbzrXVHb6Jn&T0)QZ%TcZ$sNj%M!Vx|Nc z>X;8>89)PZ=y?#px#1O{%90R=%c7aPM)`tdKSjD35H(1**-o*PdO-aA zo$Kt{SSdW13MT6TP>T{P;s~p3Znm2cx*HJURsb^VpSfWS`Szhy@3<4FSeD}fE1PT+O8uFlQ%X?<;CbNp-MtdFIj;U@rf1^nqB8M^`TzdEwaLB)-nH_g}#!#tnUD&p9`tCu6z zDxz|Q6t0F=v1LFUdITJB>Z8;uTd&L}f7qr$tB?dQJr96!H0W_NG^mGXifZoqG-Vo|3nw7IiVnMFKY&h4ddLR5*M~H#37>Sn$)m7vrfFsv;SQJkTgl1XAna~ z!!8>sF#%hqN5mc~(6dSXokVyxcQR0ks%to^@M=Gg5e=Os*@BemLqf=AK;<=>J(3uB zKmXp-X168bddW!+bA#YjG%dGDKi?ZWS z423NST|}7T0Vc8*U{wQa0Y1p6^oBQP$MX27aiMClxilx{TnSQm3VJ2tQ%&`Dx>Ucq zf%fPrEfs?7ADyA19Ic2YNvSj<-~o$CQbV@c#^UI!tBAR?O*rQ&DFx$++9t#a;7j)C zxnCC3*Mo61m((U!4&xwAD0l=Fc2q%G0+eGp&;|;~Ij6oRfS2l&1(yA|SIIw6w2R{L zYPl#2asUoF92E)psCk6mtFM|-=BKr*k;nT)w$rt)w-?TmoDZ#q(JoPFXpX~v{)Q|6 z_5`o$eQbr>u?+73OmgOU)RIMd0*I#!bt;ENbx*X4bDsdNbOW@ zs(`0x4JLPf1o1r&z$?8XiNFOyyw1t#P&HgRne($B(qBV-)l%py+c@HwJ^K5Nmz}OC zYO#$g0w(|J|D|;Msq~-h;hBDXg-88{F3~^5SOv*mrA?NLE|du(pAD`y(0D?Y2A+LV z65PYXPA`ZsqqAhn5>sXm3Rd+2AXC>;;q0nzM@e*V(=JH0G>Jm%ykFz3?OZYIP3>sP z?(?p#IkV}uc;Sl5X=I@m5Nc8YRu3|uDiD_Pj#z`1>Rk=C@X&}_F}z|+I#Cq0QNxMX zQP)_W_H;@ui**Xa2@5=;Sk0w+rU%v4+S~N=TC7KCn3uJ8vn=Z}?juKG*y4Q`r7(gF zC=#-1HuGlJJFolSL;z6{JQDqez1kxzkh}+e?_LiRut}ui@3M4 zfahO(tZFKji;uN!CplQVyHj(bHST?7y4zdp1h{?e_SNa$`j|dGkE=z`n<`6uHhC@@ z63~IY3r(Mrc(pq zF1`mZI$Vm{0}=obTFfV;5J5Ocf2Mm`h&#AaffDAIuc$*n>Pyc$VZ7Ztw^-F70 z#cnC$u|R%ooU)qB7|*og_BbsBp)%?z(<#vsimAbApqmJeT${*tn4phT?9nEVgN-#H zdN~AKl}|?WGbE3XQG)%x1Ds0t)u&l>KZy?;oD)Y`&{(cA-yn5!gOcQuG=kMfu&A_B z3Jj<1@MuAob&Xw-*ckvxpD>_BhnNGD6kd*NhEkm=W*$I_tz7Jo#8`!Y7|ZC`E0xC3 zNO!CkD-9;ShmI1D&pi0MWuo@Y*rA(*wWKjlg4UCGJxEVHKsgZ)UCELsz0QqinjzYb z6}oaw=4tlH{9)Y_z1Yjl0^R<-|JEOWJ?RDwh_CD0XGp$Y)|`QG_KwFDtbXa9sCr#i z6<$M!SfCPcsW?Nzyax-3(!3?A*Y14scDP|{%DT}9&^dh7&jkUzgZDlX&u_LgiHtH8 z!pyzxaEWT|Y?|BGUFJNP2eR0QIjX!Y*$}+D8o3q@gE)m6N;k{wY@=7|X~{Xj^6~Px z+wujU4?QqotYe&7kK_$NqC#L{8N~po$4lJUu*ZDr&3(0k2yjBR&Vo=a9?DEbz=K$( zg5^VnUC_f$AXd!$`4&-#h&x=`ufDtk&KAz^wnJNXId>d?*?rx+uQu#!svZ5kTdb3> z#bwQ{QKx#iPsUlc=tPVu;`M*5}2ufeI?h zeL;}KCy5c7jf35Wi6WA@N33(NyFW`&=uOqkj7ylS`}$;??(D{6!N61os^RpG$JTq^w8DGm86CM zrO@J@R1sAcji@@Mb*qveW1qsV1L&^0?Q#wrSmSjA#|(bo2lHgUe}reT;0sze7^uOS zf+-b!EA82)TJ0*acBC%at~Lh}X+d<$PvBMBeQGxw#{t+}Hs?qC<(#!uS>)jsF_{7s z*eZ_vyo`C@vTz5(yuN-i*HvPbK^f^~<+SIJD^@pc+@2?my)zs|rXUZW;BpdF;VOhUoto zfG+X6`!6G4cB3PiWuWJqhlGP%o_das}9JZ-A3yzEHz&K5?9DL)Tu!eB; zn&e`X!|TIc7T8PdVejaRkSIcMLS!WlO5HfZWUlR9!eO&AD&)yVS89qgi!jcqdcpB` zNsM7ew@zJ9o=Qi|CW=XLs5VH0HroJJc3d6KF$Hxp7X$ugyBmEG8RlZ+g}*n42 zja}pQ69G{Evs5GFvogj+W8gy)o=9w#m$dNE4%YAKTZ_9CGeh!P*vMz6`D*!#Qfu znDGkZ5ERths;JkWL=Vqk39X71oareOJ$V2oG^wb*=@b={VWNpPAJy|RBJCrN*_y59 zLrmj#K7R^>*U20#GYv{*mUZNz*edI6C8s>=0rth{#Ddfd9wAS*Mc_x+R^h3q%2^eM z0{~j##K@tI|6_H5R$hrCD}1W*N5MKgvM!BN*kIVjtiNeE)%Skwn)*&tPcisICFlL$ zHcNzVz3N^ra3eti@I7R9W9S#&-NF$H$wRf(c>@4M+^?m6@LfeOvmfCH5~LXh?|^E@ z0cO%qxss`Ala{T15~;de&+?kjvmr( z0MjVjiotkb4VzcUYfOr+( zb`$&bN^DJ6NYE<2uU7V}_^IwwC%d7Kb4wR~X-KyEEe-6hX{C9)nax#J z`f5A@>j?Z{F8Y=#)GY5FPgt^N0I8|2vxF47BAcp|Jl<{BUUE2GX?c@GwY}ZMa!;^x zU+dw!03!8l(n00`p1t;z>+2;q`#Uz5BqV_aGyatU!M=A>q}PMW;BkOOHt{HnLQyxW zGXr#!H&%4Map|u4eRTW7&-X;}d?#?t87ii>adVjU0dg7a0z1pL*{nC+wv%>u8~CEr zmFkp~DFWyjN_ro`$vuv>=4*)gumrwT(@;zL7B-~d#6s5lg2Z|8y5ssOTYGGq_QND@ z6*Jyj`>r;N`*t?tY2T+-n~RZgNV_!ti(1?4!0!(|Mtii3!_-G8flikvxgT~nMcXzb zt2s;W%kwR%`(D7D)28-_%UjYC*E(0$4gi!f+6|H#Bm=T~>^2-^rjQV?X)R>uJoix{ znA6Q6@mM)2rYEh8u~p7tgXzX5s&CL6Ib@*&PR3OcgbEKedN|zG)F?AgYce7|@wfiG zHB(Gi;Kjr<0G?JfC^Wp=aev9xUEw#yfRc!KWb@LZhlPB$=Z2$UrI@yPa$@OjFtU$n z0@!D4s0CAz6~eO@F##~gYOz2n2T22!)@cKv(Ei*0>two;FLP*_byiER@HS zQ$Iz#Wdj(hyC2fju1(9>Bveb1b^Z;4O1PdMwW2mqLfo+Kc zL#-g>HrHkz#Qyt^2mSb|(i||5`VzeY-7HgnGerj&TANsn#~^HXl4#j?y1e`pN<$j^ zvUJ4)ps_?n9mK0=dE_;Dxh-zdjr|G_YkS`hXZ!bdOp`xAr`K9j-=lia#Z)} zTjD#%6S_B-aw3>9ZG|M>!BAF^1Ks-YD0N(w`D$$;+=@OeE%U0Mg#md-Vym5o($rfD z)SXgZ-Y5G7#4BtXJzmGfn#$bVtAO~3`H9V1<`N?CRe&rdU5{oDZ%fwmd1HtJpETnK zKBrJlh4a3Zrfd#0LO1QeyUB+49T?v8oRfCVN^k6_NweHr0GTuuoixa|xh5n0{ze59 z!XEEpnmeGjb8AyQ8z}$_?#53mkpu+NA!U-?6AdXL)4MJ5n~DT*T#jspIpTTTSn8e4 z$4`5Z5IaVZQE4k+q!C1IaEPy)T_$axQW{sNW~wQT>tnRT+gkHxfX=h)YS|^E{fX?oR}~pBqT# zX_n}Z!fc#9!_v?wMzZ@cbT{0eB*r&ihTVF(=Z1RV&m^At@|$D#^jCLj#v2ydT;_@v zooj*^=OH4HoHR@8bkpbQaOn73%pZSD@4or^;r?)UIrV~963?~l{_WwH`*o_%>|1L3 zvUYJc>>11~d0PjC$P)aNUa;o+F_rqK5r^*8z?H-8_m@`yul#=HgSX#=AHLnL<38t( zsEqHZLy`Q44^^6&%%Lr~%^t3A=bL%!ax4g_4;JP0#+pLmnEkI-0IT!rG#{XbI$6?R zS{o2}9>W&WwlFYc(sgx%%@T|2J)@biRP-ZzZ1TEg+;vUGyB|Z!;FCT(J{kwH!qbC% z-!p+o9y8T2Tgq%OOxi>A$Dyz<9H~{szKJBmeyXH8RQ^ui-uMdtN>3H~u7GUZp&8WA$q=L4xYgE-eqL!VN z(x&!_ze6uIzLa|ayPG`l$a7&N`L9AyWxPh+J{z(m&Wr`Cl{&5B^J36SfMFpKdy881 zXGWkdT_x&cNWdvmS{MSfoKIjhY{EKEZ?PL~pYEYWbGM1+GM1$|#3a6s(b|m&{2fZ9 z6eunzk!mEnJu#dgTM(Xhj8kxMLr!4~3X0enD;DLAU{%-;VKC0h+W}KZ+Ep?2HapLDI0r9E5jD*I#0}2X@pX;J1Rg4lSy!wk@^~H&HaUxwhiKbM9 zOA=i>E5+Yfri&`oTr#X%^;u+Pn@tN*?&;5uB?|Er2=7CkQniJ)i%8ZLJt{$nrdACU zKSxtzMD*&$X7@}FA3TUz)ZLQ!d}C_V4ucR|AsCtg!krjqZJ7R8iBhQpE^(lL!c^7n zKkuy;xJ(ixy>qZLGv?fveIQKsTB0Asv#*0_)bY!MCIS@wJgNUI8*ZECzJN7+bCJZ{s{aEWAdfikywmeq3q|77g~ z^aZ$Jv5LI;42L_??(d-b3>#iU>qJY>w#W%!`$Q#J+IvjcON(1 zZ)r!k?rqM~GyeFq`J&*DujoD|kB0kK`v#F}NBhpJ$nhe+AhN&`CmsJ+(YScMiR&IW zT7lzD2tGJIe{=CwXB3UXgjTkY@N`kwBxV^z@FrluN>>2pVO^czxeKPaft`j|JUcHs zOH$S8SF$^{#9j3TKJf5xyNp!+fAZA{MOr-Qs@}nV2Dw=#=waDu@Dfo- zjRh;*Z$oigBdNrk=deHM9Vs&;`U@>xI_~U`SkQOcsy_*&rQli`tO>9kNMnsH&e;oh zvulw1gOP2`8G}dz*@6GTuGkc>8uFTlWAJD&7ca-vxInj(;`O>Qum^V6qcCLLI5v8O z$MU+yfeo+?W?fuT5^SZ%5;oRN39rTen0vA4Q9C!T?@ZH&hrK0Plmg2csX2Rbh#7%eL$12?`Si-3UDbNdx(UvL-6zql{*q7R)g(}Ptqm|Y zv$P?#UPbk~7^3Dt#pe1WQMD;*iet4t0^#Ou7cEU=u8~p;#Q(^10Y#7^01E>XPc>(R z`H)%6EAoig0$3xOm6Y^-L?MQVq(xf@Aac!O5nRg4i8jm=W@d5%59AeLKG&&c-9Z}y zG%~}3unSoxp+@eoTvRHklB zz_vAH)uBS`N;7P@@DU>FNiRTe22r9$iyk8;J^Frx6FW}acnsnvNSKJBzRdM!;bE43 z#mb|slcz|TicxCDX)H^dE`0_*A^vVKdBr5NUG-+Gq_gPSAPQyHq>wF*b7gkE3tj9|m&+=ivRQ8`t|S3l+d5fUaCXU>YvJI1ts&G_dmS7_cfYQ>?dyel>#M(qJ+i--dtz^|_Fsby zHQY#}jd9}aXU2n1?&Ts6z}1KY%{$bm4u_CD!$BG1CPUoiOdfLiZ+-WgXMgbO&v0sg zaQ^hS#g@KEfx(fyJ1Pw^p#f(HnD~|&h?Vco1CGhniB5H(0H2 zf|825pw`pS($N=ONFTv!QFV+=%q(qS?X3|z2NM?DBc(6I)XYXr`~ou8tR;-xb0b)Ecc$Z!nt77OPFPJDe`J$LsTBZ84!QzWPRlwN_`T5L1efhfIQoTqJZX zl6X6Aqs^??U|_oE?gT3(zEdk#LZCsTc9p7ByYGP8{PoX&IrA1QcFI!qQ7l`ju@?VnGN#dj$Y*~_kG{!95=6COxhH8R;X!)mNf&a)xitv)*1t` z95%M@bDwnACiQZ(EUETQa+z9y9ThV)UK{TjlE$(qRA^=b%~~H|bb4`cs5<5Z-K^8o z0BDFhfUF-}qvBSF7`Ne#f3NXW+V+<6dI|bEOh4S0YHHOJ|E%F1-=cE4Ji@?xebE9D z1gpNsNyauxbu-M!Z`Rd7Uf*5S5PR!Y6SCI4rk;qAnSDIpJzQSQ4~zb&kQ+Pz-jPbQ z`S)v5gRpk+{^U_ttF>UAZM_U*$C$A_recq}NlmAq3vQqIsMIRb31Hwd&V#g_7 zghTio%*$EPjkE*I3xuFWX*0IxfzP{3xd0Y~ussJLj5-rnbt9i|!H~+(bA(FQ^Q2I3 zI|d=b!V)D#8FsR|C|Th^fzvjq0q_6$_4&PuQYJ;AD#KOHz=0CqS{{^TVAzf>F4mCp zpA^#D2WOcuPR?13LkNMs1Pd(#$F|#{ffsXeGHK`B$SPK_7{ZR;p$i)< zzlFhhimxaf$u5g>CM~&;)UPE|7v+toxJU(Q$E z#QVpRceNLHdZO#?t>yauNK6k==5)_g$f6si7x5UseU{S$vzxN>>XEW9RR0{0o&45C zrIX+8^VAjH{|@P>6%Ygi3kQ#Yn6SOXp$37s1cHFxGw2P2Kwt`kAfUGd2J0uTG6=jS z5Crs|L2noY0#g_S0lg(KxGzcg+qJKS6-Z5)TEM|0Aa?m(Og(jyRO7EQ1CcNySaf{Kr>u`G0Pi@BVkJYae&fWEaTbzL`qrsJr=! zCZ)OHZ4W-bKU^eGOJ>-l9fTdX8@bT2NA77al8-?BOILKaTWqb&qfrzYo?cYh%Wf($pRh$(bVk*y;D>&)~u&vIz{Cu2#rmL`Taz%Gu3i(WRaCEAEd^{ z37P!B=3coYTeh?vor4%qvG0>)Wn_D1l?)9PNi(`}4Y`+8bclzcrkBmADGy8W5Y}Oa zDNq>0I?My+MLq82!n2aPBwNO{wV3o;=qljSc?=lzQ|MR#piIM5^#F~H_C!NMDCU$js{%louh w71*F~n@-vCdmQ~$wQ()839-Dba$!b4!21#7_Og#Z8m literal 0 HcmV?d00001 diff --git a/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-Italic.ttf b/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-Italic.ttf new file mode 100644 index 0000000000000000000000000000000000000000..85269a1d98e83b7f1d16bca4a345dac43b67051a GIT binary patch literal 96996 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 literal 0 HcmV?d00001 diff --git a/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-Light.ttf b/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-Light.ttf new file mode 100644 index 0000000000000000000000000000000000000000..2f5d0493fcef3d63d21d4b404371293d12dcda8e GIT binary patch literal 94092 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 literal 0 HcmV?d00001 diff --git a/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-LightItalic.ttf b/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-LightItalic.ttf new file mode 100644 index 0000000000000000000000000000000000000000..bac17d004d26d5340245272ca051304f13bd9e7b GIT binary patch literal 95652 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 literal 0 HcmV?d00001 diff --git a/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-LightItalic.woff2 b/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-LightItalic.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..de697817e40f25e32772a7a1d1d9c1d506ac340a GIT binary patch literal 34320 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 UoNoNa-l4yVpby8{z61aO0M6{mD*ylh literal 0 HcmV?d00001 diff --git a/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-Regular.ttf b/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..9abe932d86e18c959cb54b49be1d8037164020a9 GIT binary patch literal 95760 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%0DTQ`v9NEH`D^GR%-~^flPq3vA7{umfnBVA0@p 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 PNE4rDR)LYIbo~1-Zuq$< literal 0 HcmV?d00001 diff --git a/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-Regular.woff2 b/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-Regular.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..fbc66d6c512f25e543f340c8b9b6c2ee632dba9f GIT binary patch literal 33816 zcmV(`K-0f>Pew8T0RR910E8F-5dZ)H0d@2M0E4pt0RR9100000000000000000000 z0000Qfo2=|C>)_;24Db`9teRL37QrW2nvI@Sc8Qe3yc^50X7081DFm3AO(yA2eJnY zfg@XVRgnXwhkyD}1zWP|HUz4>)bFXDHrB9BkzDV3ZsV6Vswl019ecv<;M}yG_a^)Q z|NsAAkbH?_zc;*XcL(_r5tY7B%psCwjZhRer}ZL)t{*}Iy*at4Lufa%EQHbHFC?aW z&Phs^2nk7Hb4m{3;lV5^MTiSYhljT4H!+QiHDy{!^|_gW`))H*sP(o*z-z5;xZ+EW z`NXFfX>fR9#1r1IVCg<;u&(jb4T_N)6C^YwlJJxyzN=YM9jokwT+Viup_?Q*!~lEr znxCe4gq%Wgpu!bef|W!4q+WPD}qn;`h?LgOy_K|Nb(M*IOUJRiXTbuYlYDjeyK3ATvJ8w}1|_166(?SvfAX*I*V%R7>zVnI zBia!hGNKv%4C)%7ZKexlQQDY@ARsLj2X|B)St6KNxhUJS98FpBdq4l#->i>O#&0b{`^K&-|hGXl(hzf2CejG4TH ztWn*9MEs}=M%KBW+BBsL!8DkkMlRuA`4OF{Wjffnp$ZSBv-hnQ#3!(HvMpJ*!1Ng% z!25wR3i0%rK2-@+RGA)W`VS|n##2x=8##C2TSilp$)qo!)W9Ty_h2;O&?d!he#S94n0#W>9!R+xxy_b9ZeGV=r;{8p^q)VJ=QnP+wZ&;bNNBS6MmQd`BM5*8z9<@T?l^Pvi7pfFIVAUho@ zYDs`h>Lk6ocjo~COig`&q%XDOq%RxCR1L5kN3NVuYruhuOHK0M*)wdDQ!Uh$2SxcG zR5P0mkR6~0hh(@QXoJ#GQKzWYRU?NXs<9!VneFT!BG$x0q!mhHzPVq{JaROvkm(|_ z@!jSpbGu_kZe#b8?xhmzOu%6WY z*Zr*QFZ?G2>3~sTb66s@MrebJ>%6viN%7<}R$RV_w2h!L;?vgpX6m^d4>lO>|2I{? z_PrUxgy=+WE~`SVvU z+ncuc(Rel*xx`0F2QVin0c2Z2!9kVqMIkr<2cRrW!cYhfe0{TKlYGur^s0S0eM#Rn zDzz#>&ALHy3y<&uYvK9t_j}cMR>0v{(yRt}z$Kh(vlIqT-%_P*e_D0JLFi6KW-2I%oo8oNZ`@9sc2Y`dsGgA(q-WGn zpaBc~SIZRN{p}h#W=8f&nGM5xty`sW$bh&E54lV=>$ELpc9hvRlj@ALzRGS8k-Z=x zh=hCd{c3EN=Bv=o?BiWZHWws_h$o(eu%E-h<9z!!j?|gG>m!&;Fh*#E5hjEX-0gPR zL%%x9n$-k|h!xBr(p2f*4^y95E_hF12_CYVpqD74HUZ@gC(V-m@abd)?lU_vM6q zs5Rtc!y*3~4f)@A2<0mxUSW8T>{8%hZakkhn!)meP0OyMXhm?yGj;I!A95Y*7a6-MfV$OW# z1`8G-OI3c)jsFzdQ++<_H#AcraS-Nj#$QWFJ}e?S4iSi&k?nepc?hZ2Vu^km?6BWS zZ@~V}cE$M&1gLaL77V;8_UoVacI|Y6r0FtcV;PKTmR;R~J<@CDCF3{x-)et%U(B{g zQnP&m^a7~m{tNT~)bek>B(3l{;1xf~&$#lfCYHb<4En_WdiC^uZ5^QcCv{C9gIGNloD8{>#ux#VKYEipN_%mqJZ44zN7kR;+P&OhV1sA`&_l2hCm%E zVQ$Dw0RyDx?y&jL(rmj~u^Gam-6P~|PIR1QMCxs`0 zEUlvR%D(fvDe1SzioEpvOIgEO=aVn)Dm}aJz+e2M>}^jZMFl~+27)dHdr}mZw?KHP zxcJ~8JGY{P)~5D4t#Gi_;~zL)S&dCIpkmg`KXoH zTI2~208I!3I$9kJ$s!$xy$~?2L;6rJR>&h5_qg2`ue=zDc%o8|tgJfYWO-pT?XZ5}vH7n8rR}Z?h+P3AhIlWs}=xN2d|E zbXg*z>uUgqv@v(UgNT=v^*KW2je=@e&-Ak|{^AL&C>}g(Z>yP7773mjTgl~Mof^Zl zw0NYat7gIdu;i+pcB#ym^P63gV7@!F_$j5OVMAdM`-UH z>7}2vk~5p?th*7otGldof9d!9*5K8W)lrE8cp0-MRys5q;Rq40T^f6gE|C-CQZgW& zQE6YwGC3aPxKJkA9MdaUk!OKmFUEz*UT&?#b2nfo-841;lUiMz+YdJjHKgA*BE23S zrf9Z+j$|HhMZH*iLyHjAu(;$P0^7ma7)smMqtLzS3kFf`8JvFtmxsS1q@l$qM_YY1 zlYg7VSJ(qvT}%$i2MB348cRolnI@tEw@A6})EI!5qllnxQ&3pFu0zDm44W#V5P#lK z6S?f!S*v&@$WEkzU>uT@RX{R%Dbhu2&NEOkakKxl1n;@wapy~0WEMV(Y95iXS#{j2 zK}rJAXvyXwDNt_#<3Ck_S+{;mmPeF8+_Zgov6{3^{ie!T!^2m zG~DaNpj%JXXMmyx!&bhV^SJiNTmgxxbyh?()2vVl*mx=f)QpbcSr?liM$EvXS_P-_ zsA_EoJe;bl^QT$9FV7$pHJ34wk|`%aoO-%Zb}d)-6rDJ|;dy`C zBd*-5?P!5NT%p6pgw;1?^tkSV$QYAtZc$rAa(TI=aB@gEamAjtde1{XlZS~*%9DnF ztL)aKvYo$rUw@>iLW|0k*MiI2!7n^6>TX{pco{M5$S*VBkQ|H^#J9KqWb(3*{eyLt?`g5x8mvC-<#Q-1kY1V*o zsneNHHHchdbn&Ewm5{}AwYOoR+V^a!*5s?hm-SQs7h;pXa`kMxwl(K?8-9mO?VxMx ztjV=dt3B-;R-P>KZAx{+jn-4NwI*h_(|+rN1JSWtA$Xz?ncT(jQT!o08Q!l^;r`19<(wl(bzpQ_*}2>uI0(S-JL&aJTJ>wxFN z?5*Imiih3Zh-9fu8P!@=pVEx~YlwSHlf&ek%GSB-_#<~tLjTT{w?%7}Z^U-K7l#T# zMW@<#BnbUr1eb{`mx5b7dt)KxydUM$A6(x4ktg(RZ3iFuJXzFZ)7_}oh(6x><2(L% zQ+&~a-wq(Tmz3mu)07$^U-0|Z%qq+D8%jXU&bno(3e35UaiWR3{Ju7tvf8jAbx^g5 zalsq|xfx*{m}-uQJjCb(lRMK^yx@9%Qdc9FFv>L3O)yt_Tij8}xu#V86e@?We3I`~ z`ofE|E8Etb<86ozncA!YrBrW+kJEmOx6x-Q^iMRv`%+$VhDr?M^E*0eeNv!dEnBU9)k!M}; z!`TGX1A%k!5QvKUBQkMg;#dcQk@Bc@GeK(3Jv!Fkv65KU0~ZJ>~1&DUPQB4jKl=0eN5R!Xwxn!aKS;~Z~qV>KAY5k zMK$X1jpY!s!MJF9;zKQ}VTf52FNftPzeRocrBz@HYq1#awvbhMw(>d7@vavvF~Qa- z2|WVyU6dwh&pMyLi$JC3`oQb3)UC@9@p;YIfLw^+?<*Y}R0DJx6FR{`aGbMq3w{GPvybv^MV;~wi6%{eRdC`({hP7;1xbi1*95%6MBebI}y&LGpCZVqX_Y99>p#@Uk5PJ3Vn z)0@(5Pk#u9E(Wmt zgAWRDHebb#Hphl!O#WMovvbOV7irQZ9$pQ2@UDbR+=B1r@D(-%xsQJfMt8KT3zkLqdT9T=rk*QG$ZjMZ=)y3DDMmdbAyvF6P)!l%@MIIv!U(9b?y9LGtKwNDtV(#5>?%Fi zp*KWkFw*6LhaTNOBR!tQMW@SI7|99q;m#USNLAF~nCI1Bd^x84qCchlVKB8kGLd%v zHk~01RbrT4Dl+ouSxpgEdXgA%rHP2gsErZN+L-aGjTN8TaMl>HjnEz=Yf&4De{J*x zm?1l2)E$bR9jJ}W&e~|%RU4Vzwb8Q2bJlmSs;FE;ZS;ht#D>Y+yikZvCAzBWaNJ0V zs39fNdpKFg=`|a;HwlCVb6}LmpcbZ5g4)Q5?n9CZO&ry88b`X{a?pJbc1B zJtpFbUcz2_OVm5>h~@Yi3A=pacljL<+e>iG&JMRH8%Sinz_5b0q$!9+q( zfE#(*i`Et$1M}Beq%?p+-fVHU9CY+%JC9pV9NnTA8NDnlRKggdCi!a zwN}daZkj5=@sBipo^9*)>R?1!)6-NzRaN5Dt*m*V6P&cE?$GlQR0eWoM`)LXN4$uKnoOAp!Rg&YtI=56(3}Y zrU^A(PJ9_U!=e$8Sz+iRt+xwbkbWQBff4BKW; z?{D^a*->LI7#Xr77-nX2z1ov zW@O_LQZA-R2gkoex74rS!JjQ~VM-GZjQE#hk(=|oT#`lP_un2GQDVd&U$R98Q9z`N z9FZk5MViPEDUrQmg;%81Z?%vhsh4b#WyQ*^Siu!1^sKAE&I<0<+v$KHAubnHQn$*j zwAxy_=doVzeK!O%2qOxK4sr^H5CW?GiU4W|jt&gIn?f9Ch$5T|4jYGqH?$H>9RC<6+|AYE6cKf8++p!xxl?u3bWCgJ z|NZb2;UVe?p#~lHkOq)I!Gk?&H`8%GLJPisG&Ed{B*>VLAS8+~N%AcYk|v8F+{J*? zu?TSP{@#<9)@-+h0nED%;q@%T>s`uwyQ~G@^J$#mbWU4|+RTQu^k-_1N64BA+i{!Y zuT#@K<;7pe1k|3I?k#d}q6HuA#J@0ZjghKqp7be53l_(y6~=U)&2RA(ii4yVk-2v{ zT`x3c@8bPYLCcc_)Iw$k;~m9kijRR^8wX*l%0LOxt)V~uhfHK@B5FTfsENk09v4ej zY3Uo2M~FNl(CT2m;3APE{lCl~~iU=b7)Cti_Gq=E^8qrV7#iQ7Pyf#U^Hk`(|E zRyEx)E!%NDKM14PwSD-5Kr>Ga@=-|{Tts}rC3-H#d!A{@W6CPMu;3;iM|zCxkF zuuwvpNP!51JnL=K=k#_5qEA)evM-|jxYrf;cJ8%HF_90 zmI{Ig+u#GGCZwv?e2N@TXr>`P1Gf$NUV&WZ-aQ}>6G0X@r;v)mxYNxxctn;LCR41c z$&_lxWXiRFHSrZN9VgZ3I%Qe(KnO5NseWHbnMi(8AdFL(tJ%I=Q#l+~pHv$an zPV#$zt_i4Lw88uNDgxZ(4k^bO`C3D-DQl|9JXezU_8)0lTp4M#+AH5bT--ndoCWBZ z#bb;KOkx_QV+Lko7N+oOChJ6trViP(;2?P+tUWHMIc6y=t}U28JJl41XNiiMyymhO5AZ*mj`;bcE{$wkw8{LhK}08 zdb`^o#AFMY!iY$e@bX|usDNZDRcja1tWT+GagzpXnpzD6e)1;c zaS%FfS0_9Z{)i@y49a=vu^)a1ISn<_MhAW6+UmpbE|QY0TGP5Vw7IQpXaC8Xg5eJD z&>XO&O`^wy1qUvCFyp3zS~^)tH1Q;Ji)m%{(6S9N?7MX1*}HYN+h>N^=2>8gmDbp3 za}rCH6se!)k&6@uaUA7n1Tl$s1fr~W!&X|te#uz6Ih#f4lyPUK?|zv%YpmsEswP{! z7y2UP>%!$*?pXg(vzaibg>)G+XU~}{T3q<3ri~>;5qGIcm+_?w)@xuhn` z+?paQzIlUO9QdfRE`~9M{>xh1p#QDBH($DJ-1qe(_;Gs&IWmUsmZ1zP&>6 z$@@P`9Z{aDRuF#v0^xP6-}$9p@&n{O!6O8K#85*EJ=Tbma`x)F#SOOc0C^oTpE zTrI8^Jp6#cAL?jg4h#+dcTI@RY4bNof+Wzrdt>i`&9@r`GM=Y8UjBFA>vs9A@$8Kq zw8sI`FXBy<-D+y1VGA=1R4(c zKvfk~b=0*M>}-moULF67h@>UD(N&S9kzhKOyOFRylqnlxut`i7(1j}^v6U6RpQ$2I zQ&er&>X^P;Y?UioY5FH84@G;Nv}w>AO2%|l%t6C~u#ze;7hS0pOG}CvO?E;>$xx!p zNrRONBOOj!>`a6i@e9!xpv^{FkS;f%Ft`XaOBHNYaa74(HD`6aH4D}%T#HhnIz$_G zp->0g;9Th<%Mn+egmT4KBCSfdt8l9_H{!~#NnVX|>(SmbEwwAFTU$?Xdx6($_xtEk zpZck{-}?IHWl>IdU2WQtWmaB{yQVsor^alv%gISZ(M+zpnrQzeWh%BXNfhS*<)^7f zP#c{uUt)!lyQ89~nyZptvw{}!`kZK|h{F8Wq!&vB6czif0X3v|m`Iu{f9)0j@DVZJ zFPP-#ol#7wn;%hnBpE@-fk-jrrpL`p6ikqdyc(`*d1~OVOk$|=(*P3>g<(!y}|FZC;jm%adEJ23Ia_f)J(#? zNTinuHXWnkSdB(C7Q6A7jpP6qfRG$Dmi#yh;zGw$7#k`dbsowF1UKYV%N%ZnqpftT zZpT~hNUNP`t&r9^+j^nJ_`fTv;;X4kT@N+%NMnyR^+0`JJ?o37ee=8@x>0mct$HyH zd}9Llr>Ub(sIp3@McS^zUud~ARyu2mi&EWmTZC)U#}b|^@>RXOo~b+BX!${9BFJ;| zBk1mf_}{O`IsJMK6$m6R|m^{0mFg$1YY$(Bwv}T!dB~?O8YlYCSKG-6E%>R(6#zk{& zO}q(x)DK4cwmYKmuo6~f6OZ(YG|+?C(;8&>Dv&Wx*1QujqO2l@iVD_+DLhQrtj`UH zB}_VVtm+^=lfom1$nM`KjnZm6ae5u%E0^9_P!j{mZ6FG#7Uk^`8#5rsOCwNLLaf5E zb_GFpCsM^0)l!AY%v6*E#7va9`iG?`d)6q)44AQ7?vKaF4S~JCD0WAJy&Zfag$N4G zwG(^v*5)9`+ExZ+?J0fF+99z}n6y`Y9r=++s3C?oFgUJ|49ZMCN&|W$h*PnPA_gcZ zRAYnh9UT=_CFRDfdNwz{&ukbp>f(v|_j* zacJd_hb$vA(JS7q&($HyL*%KiQRadQcrsbsl#BBYSO9jkBO+lwB1MnS1aV9%7IpS6 zP&1F7l6i_oI`fD``EO%sD)VyU^YeeK6Z|iBPFckS3dAo}OroG~WC|2Y2{f_#=QRe{=kTC&;GcR^7Ty$6Rh7FH`N&5ECfwaQ|}@7;7Blkz)s!w$}4 z7rv1vP{Q;xT-l3P`01l*EU?euH~XACT& zVC+~H1M?TWq;>anuSB}0*j=OxG*}25CalTVpo%@z$C`@$WKdHm{p|ibdzHL5<#(5$KkU<@$Q88mti;0X58B+8|1twBas*+apbr8GIDm{9_xa z$TTwvgtggAS58dwb;#3j?u`XBR+omZUaB-+eDgQ%)$jx_XXvZE z1c$*aeH9!oU^p+T^)V9RcVm4&T6l7)>0+jb-D zEc@>9ljI=~2M#;-Ae=Zx%_n&T&0$Or0?XAoei#-n7EI_y5G_pdNH$~(rgS5y7OlyI zEFEAR4k_PoGCh&y7(xv23 zL}nl4_R$6KHz0DBYI zhro-o!57muW082Isw|r}WbXQwQ2#V|2#y&5awYIfz6EI0-K5DmgZevIa1;kiZwWB> z+W<4J9&9}aP$|D`i}WoC1meZr7ftA>%@+zb6q=zaKTJL)E|jh2>tR@JBMjg@cOaD4 zGA6j&zR=yFrNbMg#>iyP|NQ*<}Y3mMI0F9TxVC6 zqvJ0SaP66aFrtOOC_yp179hIp1>*@3@R>8RbIDkZuFlL^J(C=sm|t?+GjOsc+h#+~ zKGRlC)Aj_M6>({zei25);KYriq?4r?6DJ{~NhQwlko%H{C^>uUHei3|eq$0)WEF^< zmV;~|Gh`)8t>+K=FzkV=aJASCkto3_h2U*dVaAHy=vq7WCL@}=A92>zv6)WnVeE`Y z{NyqFz-TeP(OZiJEnz}pJn=Orjw{-UC^_ed2#0p$IMR%2eZ+v}l>X}LGcA;!<8sLo zwQX@moqPm!Gyzc3pHl{0f92%1fP3f}%oSXB>*W61GXS%%;^FwYmsDSOMGaAPAS;kK z`__Y$(@EhSlxYW02S=UFzOFc z_1Y`X=B%EFi1$1#;hiuDR_BJ(?Drt+MxHD4pP=VeBT_9yTR*!6ua%2fSXH?)g|X~R z(m;T$r+k><@-Mp4ZlRK%W#_AahiI^ulRC>p>02k1mBUf4?w%rhv@j!=3fUD^-lCaTC~;-~l0_N8ckORw{MAr5_I!{x=VCeq8E(M<4|+JF48Q;l!Mk z!M>v_J`qih`Wy|1gb7#3@dUXnWDjV^AoP~{5*ZYFYh14AZsGY#gYSexPlo&FYYb8| zK}eORC`4nPfNhfSS$J#pbyx|Wqi(Sd3wyKT+7tOy8X!R@`aU8=E$2GyV!upam*s@fTGs&-dy4DYqTFb}-_OE3+ z<@c)%%JuJmyHPiGh1r{5H>g;Nt9IYpkag+Fs7%3;^pQ?Mao&C9bt;g{z)QJ!=DxdE zw^W($<{Sm-t&(}`h=?2)LDJjrV>SIql&tbkxZAbX>yoW&QiWPR5t2Uz|9%6v>M9o@ z$00%)!-AYEG&IWV{y1X_tS*u?AQfM~T!U7Voq?rGSOuyial%F9s2Gk^`ZIJ$i}o}`*jagBqJ zlL1n{-@)_H{ztuawh^KABuIw2!>k(NWs_q1JHwiwKACT$zo++MiW9q6ire$i06HZRs$?z#1=G_C#an>H99 zzqG>T#oHdd7`igOQOc(SmWf~kILZaiRo~J~7PoI)A*a>b;@b*?#TWD3k|lq19$T|y zKQ*SYNgZogP%e-MmQ!tB12zwj>w%1C7%1-l$UA$u3E99yvFgrzb4OeKx6Q+4sK4gW z&h@!zJ=r~@6SidR69Tf6a>bQ)6yZvY;nxbCtpU%m*5)L&vg4dg2bPLU7?zyMi2txD zcGfCegrvP^pK2U*zsUXMAqV4{j3R4TvvAB!@T5rJB*avP+}ewOTP;h->5B3Yq(UgP zn2$0PNS8Ym&YAS0c${x%a@8%C=YWUd|K)UaLq})LWb@E7im7snWN$K;=K~NBdKk0t z*ojRUgFza|nZB35{xWp4J&pqJ2XSg7p-CN&J%uduA8AqKnN%tpog`KQ^p(140$7OI zrqt4bGVZEdV$Q@lr%h^~;~Y4xojn})dBN{#WW}K_3pO=zG*IRG2D&kdqGIdXGO#?M zBgm3K8EYpiWfr!M)9`!nd@u^S1dnSrZ=t2GgS?92wPHXy$yFCrp6bh>&>sT%UOm+XZ-}}JjNvq3|wH0m`@?GrJ#1Zwy)jGh|30) zsJ_%=ik7qMQhD0}c{|ArRX2aLMh^jbpmTo*jK0gLd#plj?$!2grBl0rOsU1)4USbo znzdQ4Ze0nXZP}uu!FAUt>6UMt*4qXkV>2W^ z2@}UGbKseEWp93coCZh?r_B^Yo(1b5xOO|YuN@joy-W@$v7j>rnz z!yaSV+8Oob&97e(Rdx1BI{))6nbH45iog-Yf$zcdeubE=8CmMwj93M+yWE945uS=kWBiIzg+(X>- zwXV0eAL)h~ZFEK2H@|5=)DAYl#Mb3#>2iM2L_fOHeswwPtn1a6m$}-miT?^LQ>(<; zSp{!?9X85JMh1^y@wja(xEzW3rblI+M8TcQj;iRTXq4`n^pC{AS&RCaPiIcj#n38#+FY^$ctf!8ykxB{yM<}m~@Hr#f2pLfx zEm$su`Tez-w2Queu%5{?LWf123ZrY7scR+TLpNCIv`e!YZE+cL$g*DXz(Z79e3o;? zBS0d^HASd%^3VW~Ok&kVLSuE9LnCHO5hKzxdMG^JwOS_J%jSG%Jc@a*j}qpbGfE?j zNZ=i_-X0ri4bWj&H#`7bf9tqaOev&D6t22%)w1g9zdoH$(fh+%kaIM3TOzio(VH_T zR5^d@U`ewtch9no5*md4VXfBW`ExL3xg+fqWclhn`M_CY`cdU#&yX7SEmoNdt!dMG z+JPI=kMIia0tQIh`iRW0as^qrwr=>g9Kz!KJkBR2vkUL_$6xtH#ai*N6?BTuQQ;mz z_ZVgp(o@=nsZHuqMJI~O=BP-Ej{TD+xApQJTi&!X0Ury#b%gB)MZWh@NR=>@$v+pi zATm?WEtC-LzKE|01A)ZVCgz2KkpdkI6cJo!52pC|H~4sFb9On(Y>&+c8;>(rI6$eQ}IVXplBY&ro`X zjy+!6-+YUIyx`U(Z(R--#miZr!$A5Mnc&8#Kyq>k5g4yzK7~kx=6B2!KQE@-JGaGbcbwjO%Ij(qMp8U<)Qcj#a5TP&t z9=WiRCf!;-RWjiwDmOn5`TexU29t}%7(_fY@F0hvzk?NV=h zs17@kRnzKsaCtB&%DHSXiiK^vF6VLd0?D#Hx8pjNm$-hdeot+!ez%(~tZFCTyiW*X z_)Uw3`v)l4#Q%l~_ituCT~?7**ajjPPaj6Ol?8=&*eRJAH-xyX6AR|#h@_Q^6J;ys zjBvM6c%7*&DA~ATgcBY~d=euwAYvQ8ci`Na19W|758S&eOUgnf4KuO-j-Nezj6fdH z!@IYcY+9m{342oZ$lTJx-q`ESp#&}|sI z4ujFzF}Ck*fwOf0t*Z@zV0Dl2%w;0Rv3bN_1>gz(P-veRla)R($P5sEMNGc28!4+8 zu^M;R*BN$iv_{mO#EbWfLl|M};*Eo=mu^_-)*(MT28eXy@B|FL4%%5cucN5zR1y!u z1nvV(2+zBt&D6G!_6)zdc;8~cK4F^3M0_McH>I%Mc))+eCF0pAMQSecA%5Yh~337tvwYI#AR%cND^{fEO7w!d_%=zZoHiySHO)}MlIK46? zA1hK3W>gAwrrZO;88@1+N5;VkO&sd$3EnS9;&Sd2(9Bmj(YS6xyr0Eh9ZBxM`1s*t zGl6N-qrA9E<6`liEYIvaaF5!Oo5Kb#Md& z16?C^L8ZAs*~uONEur`HI}T&+Jij+U$-z!L?HZDpk7w1{oyg8}sO~i6O@;el3i;B$Ka8fxQ(1`^iPZM3IT12{V9~r?4 zOdd$Ygqfx!S8B8nQi%j2XEW76Mj&{5mR7~4#`o0@^&{+h;@!(}0j-O_V6t2xI>7Me z>o3>HvoMfWE?zvkSQb#~B|@G7Pi{HAo(Pr3PTch67 z@9+i&t(x7n_zXnblBKmvyzu?&-DGuFe^bx&u6L$)we&=U@tx1)BKh-9l&a(T(^cRq z$P8KaX=03cQPAttF&+up?-GZi2amvG(Qq^rDvd_ROh*P*t?5Hi8bw)rfx2VSUa9{2 zL&~W8fj^JLT*^CAZR;^-4n}ix=X+`umVS{m{nW+-*a*+KrDR-jOm2&JW(iMD7@v*H zuK{8{vghOGtJ+)I_pfVF_0d_;;1`6)62V#Juk69w$XNn;72_$5I+H%7!T%lQ@hpMv zhjz$b3fGC&%N`5xHIH4sV2Qy@(2+|hdJGA~v%3}}8`4n1G>*koa?n+oPtQ89H3B(F z4)@$pLD90})~5#q+=+teGxBi0M%F^jOLnG&BH4o6`FUC2pFKrkk=--56xDk8F209M zu2I)Im#q1;7c5WN(Cckm_f4t(_`OVDbJsi70^8KEl6&xF2u)W<#fJ!PKuU)(6e)q- zwFKFio-4w!t(KC5uBv=`C)Re|L1g(Vm((U6cQYg?Q>Lguy@1rAF-tO&9p1U6DBNzc zZSmuvkXf(MG8=+ofNP<7o$v%q_F8CM))`&MY1jD`3a#Ji)CLsg?zS19y;yHg)hl;4_B5^r1E zzOf04ayaEO87ErC1_KV8Qn|uBp~w=_VN{OS0QF2c#5H4Nt-5w6HeIa`KS2y@zwU@WO%B@Y|~lg+=Ks> z7BCu?t!&Y78_LCCux3&1oTKiB1Z7sdN~RZczlI#b6rd1iSE(pmm<)L1ICs35SLvn` z^@x$q?gH|_%H!C4~ilMCEAN>LxL)6idwD*fHRZ*K>sK_>IeMugMrfU^m^ZiZ+D6D zuO_e5)W%{WL>4beIg@V+duiB2AtMy?kTb zHR@bCQb|49ueH+Io8?8wmryR`G-$OX zxi*=sVv8y!QAo8uw^J8TDA?Rim)5T&A`t(l$%@Ozh!tRUp$zSnHt(ayvl{KZc}nD- z1vjW>wU8Fgo20x#*b>G+6ndT)5$mpInCQ|if>M9m&|0W`?pN}`4nkDIDVaM~Je#-` zzYEXP^4>wt66h8fPBHFbnuWeOf2XhAc#?4#CuO||Chu+_Mb>CwH7ebUBEmcSdWbKT zMFmDtMd}BK&rk~BtzI0P;hQM^97r!@wDQ;G;!CHw_;GB02`#fOAe5|~18;>bnemJK z4u>u@$GL@%Lqb-gPRFVb^2Knz<}6yrKBEoTD@&8a|4wd&=bYY!Bp_tgX*2Ix7VW{H zZx1;fdiW{FbH2lnIzejSr@?m(R-C1E#)P3MK_NO6Ga^e^E6_Rcc{u4C2}qZe8LTDl z{QC!`9Aim0I;WuAlnl<301P0aaWW8yW2?Pt_CHd~iNHGxBo0$ImoI^T}fo4Oaq@iyI8}Wr8^}k=UP)~?5wMjb(SFpGyacP#r z;Wowj0sjVgLqE{}Z(}8wU$)Mq5ozkmyX#s+E!x_>uVjvA9V8!8cVk|xB_F5M`^j#Pf`wC+`}}RVEU{ZV&j$Fi|4l06G(ttaU|^LZP;D=jLPS>mKZu z_jjY{|6cz$G;(S9QmN~{^hapmxCxc!T}jN_Y=+O@{!YF(kiA~a1-5f2F)Yx_$NxKd z7k2spU_hV0Py9pd0c?qsRxcpwb4ZUbfxof&D)?@KoTHsTgW320ynpcL2!vxM%s#wB zk;{(lcNC6i&>OBdw#}!X3DW()=4+DJ**yAHW_O2zkMC&`{fDQ#q7Tl6z2WK~-@OhT zhsbBY%pq+k%%7&3FP*<2_d*VBPC*E;05$7H3u^96@>IModM>>=JghfEAk~w}4Q3E} z*^!qA$fP$LR_xI27P?nNo10cd-9r7|@@>-TvNQUaVQG$wW`tWd0%c{x0NiRw z=rrGpkGleIeRw7Ct!m$LPq#Z=kG95l=H1Ho+N4*ee-{SQfR-0bmNelcW8vB3C!n{z zec_oC-?Nw@!_e@EzTavw3=9u{pGhsm7_?Q^E8CjZsq>v{;-is}?2735yp+C!!~=z* zNYHqHWDyw%)|Fa?tXdIt^>gYCyTm5-bX8PA3rYL$`;FBaom8@P4=j`D&5(o(3d9({ zd+qNefq}Y!Nyu}7+>)=M%FXa*xybw*__Oqpn?86x#Ab%2Ag`>7qXfFhqxXZxsM>5+ z%1u^T86W0uABAi$E@-n!VBdvOHoHtJ;YOoe$&&sP`&xkm?GCH3k$C=orVC4Phj*=? z7cG;3oQ1GeAvakenaw7X+iY@)bo@i1YPnO{*_QW{4RQnS<&pMwK8sr-bAJE|tvp*- zxVH8&myIX1(Np|-iB_wZi1^DyzWm1W<%bW${#YBY^`F>xYW0<+0)D7;mvf>Ku>_E- zS+$Vop+m4$p)gq>32R(1VRCord|9kX!Cljm-${N-tP_hG)M{~~D_1DjlW3%_h{fV6 z(`rd#e>!tVG{l&AE6@vURW35%&NcJVaZ9B;ga-_(mIBoGxDG%2(6@E@Ja-hU zfFNxC{vQuP{erI%d?(OkO7TydT)EF2yQcN~=?%;O(k@vc6*NGuo8(2_sO!UJ59S!Nz* zUeD!cO>~{0&zh}L2*nnyq{xu{`tq$j+~=5r8-*p|;(rj6j`n|O>ld6+$tr5osNf zXkDOAhgN5uSux0_u(ff9-&Pf*e0B&^cnFQYS%|q>;1I}JIzJwrs+EM&@$OFk?UMP zO%%UdyA)cgAH?__nD-=Gn!2?oi0mT#!O!@_ZYEQWG%^`B(MqT$GR;V*QjI1GEmt%d ziAIq1$@5+-QxcF+oTpMnjil7FF!1xo6j_dQ8Hr_?i5e4ok`{>;M~6{~>&jY0bf|4VSUXm{{u{7>HC0H7`={Y)caBG)f*6_NA{5#jTHCJ|M0 z{T!rKpK5*=XnxiVU~ZlIna{gl3>`8g4=BW?- zTHKuQknt-c_lcgy6b~5J{_wA}{R(D)xmzv1op|4lZtXTxFCk*-)@@UU{n_yeudRth zl!PouQ}Kb4;@XxFt4|``5BKt$UsLw>5{Z1X z>?aFeoAs-0vz-Q7EYxm4sQA^N4<4^ZekQvpqf2dXkLjo+6O9J7Ix3mWw!g2+v9-08 z-kCM>YH(^J@!WlWWf5SoON52Dpo}A$Bo9WSld_n$0P~j`dCiJ)5_sPZH)-vVkPxpx zK2RpvQ9`A#lTTEUj83nC%HVkfj0U})QS0XMOAHkErV;Ll8+NO{!^uN7n>;85RDPRX zT`InLmAj9-=5?VH-+JHPK;=Z2tw`#q;D_esDa{S>E0Q~wE{_VTNgelFop|z^oO4I{ zW2YYzW41@L&aX4Pw@klpUnj5E|MmjdZ&a5^=|ukq|C=4Wp7Zk$KAxD0d$O5IIV?>z zfLB1{#9o>C$rYc*f%Qe2)UmIjBtP<_YI#k|+?CvRM8UfIBW`?g_3*&JBeGN=Lw>ea ziUOzMmj^IH5ex-*0T32q1Ob9{I^_$bmBqrSWhj84CoI!N;Fe*2XK%RRT1KTN!Vhxh zbDA#Fq_o5Amh5@=-~@`Xa~U+VRvs%*toC_*Jl{Xig9S;-f4n@e7nHxe7x+x1@-H7C zkxWyfALGPPt*uVRDk#lz+Fj;2#av^v%VT>1PmETz)yGGr8{iEq#VcPlR?e#L*{(;D zn8WB)H-xk$sR33oMQSNzk=+G<9#nEvls5%M9)e7$zkJg{ZrUE8SAL>dAq8s zH}LvQW=J;l+JI2Ha@X$j75wlNT_6b08qF4sOa|BguxT-MHT3!BgvD+A#&q}c&-vs8 zdtdSYp4FY_p$jg*Zh?8 zRGI%=19`@O5pU*S^jzfOW2R#gewEE(*z+;b7^1%u{mO*f*=|6dt@x9VMIV1+J3bM8 zLiGClDo#j!eMyHdUwEQR=(2Y4cTmFflYXE7MoTetITa#6-cAhNz51LdH7{_9)B9XJ zpWWR?tl20&&hGtHJY}6<4=J`cfh~3SOW^L;vMpz}oK47+f~>SDGG7Buq7&^Wz@b$p z_=&h#K@`YV1yfpNe~3E#iRhEVqQjq|r1|?iXvl4337wdKcH{SJlJXkvAalJ_NcqF3 zZ{PYmv>z)bipaAnp7EG@d*%wC9TH+HtDm!CVvTNTkKSyP6SSp2>PlayRtU9*rQI5% z9>nO%UiJMK03{WCVHBWY?c{Ix6+BT?Le7UDq?Z$fGk+PC>xDw9LxWg{V>GmI{{Uxx zK-o|h3Azr0sY7S36$wc3tdg1Ej?2iDuUQ0>!)RbYp9SAAw>@l_`v`PCE6!+5dE>b$yV|MIx?Q8IpdbTyGh%f)m4?`HX7ZPRrQQB$ZjUM z9*suPz@|3ZYFA|#c2w!Xj%qlQtTw|Gz+^msbC&`cC`Zz00fR-%WHI1pAVbgoPiTMkJ0h=gT!lT4$xyCMD?^ zCr>9PzRpV4U(r1>YYW)UBt_b?&p)ltw2!=55gA{!BKGchRojv?<(^Srh}Y%flrZmb zr}Vl~=u+5Yf*7rSg@_^}?v0-XNyu~g%!1kc>}^G1qd_yU*;X6bme((8<)Z9u&|sA9`_pOoNMAp8_V5oG2qrM%D;p`Q-k zo^aT^XRr6sy2tC?PUJu~Xd2^y`t=iXjf78I%$C%l z3+o8JK3{p_Qb)hIKcbDai1_=h@mVA1}nkiNpfX)+%^qoNyg!l zu|=QPR>X0iYSuMpx*PO5y%sBm634H#)iLVYgy7*{6hD`zq)Q3Y5e$_P zK_AaqirMUNym_+(>fuGO&t$!O!3^+H(I9kov$-|&)m;E(mdoGxy3?S-^fOMY^Pok{ z19Rnk$Q{Z*f$h2O4PDP`$8zA~!JByrizi)IuSX+ zl`+kf<9ArSa`gE*{#SvU#f>gvkbX(8z()^86_a&e82D8#m78QH0V zyl;-on5|7g{`*HAjv~)Z*BElAEij(M>aS~v*NyfSP?N3`e4jal227)eLJkj`Lp)r~ z1zytA6yos5Y41Pw%pZ(YrI$=4c6dDwPky@3X>%U5KBJhhqL^D zPV5ol_us|=9+@te0W;p)e|WNo-pLX3)_7+{R$P2@`-$G@fU0&8(a69 zgasFx8+|I|%x-KAxkDKzUalB%gh$fbUvk1DjsObhg)vPOJ>pn3+}UX zi8GwZIWN8p5XjP;g8h0xNjXdd&dx~bjbGUKNh;}C);WaX7vezx3i89El){mG*i_|5jGEHE?8h< zzk4d59tfQ|=8N#Ox)dpv4hyID&j*&W>^~w)wn;eCQ^(4J0)iW^p`|Q+fNu=Tg+ztv` zY2OW|DM>uFlT|us`}A))1iR0!diSj4oy!MN9JH0H!gf3N?Y>xwQ=UOmFu~-;@uFz+ z0zf!^Y8cUA<&!>`_{MPUAT}JF5HIcpd;8<1V#$p+l>RLUf2IJEaf0u3z|Z1GjOP%XZcMuOuGek*ByQD*`=duAFQv3J0dEMVYoVJGNF&w7#}} z_3)>SHN1DiSQc&nT?Uzz^4)}2di?Up>`56d2VTRT9ooBe?`P66?8gHx}3tn-!IU_eg?KYemH|FE+w8PCKx72)$wcw6qh5V+P(1%i5Jq zC40K{+bedwb0KiGT*c1<4<9(IvEJ`oa6W}8?NIC)#pawei{aI534?Zg3`BTab4K5GOzb} zpq(u%)&zRaoNQEo9%yEV+UKLcZ%uoDNZSEC)c1mfejY}*Cno{oXp*E{-&f8C9hl~q_ zmWDe0yPQ(*U#CcjL3Waq4BUtGL}AASX6?A?2lhKZ*%~Ii%c5d-IOFDuhMHG$i)E9) zsLETY0=ArtJCwB4OxsNLV-WR=A%_*;NSj5$gc)OtqPMu1md~R*G4d^mRA%p?eMh5n+rY*0SaL^nXsMZ!5hyHCEhT}1NsRL11!nD7^|?{0 z`^ojWeb_oo#=GxFctuTSLJx9D3N;yd4$4Pi#{|X}sVA2t(U30#G54hjw|WzAvb>RY zBW-&7oOTTQ@dLm7(NLfMKctrH6bW%8!jvp>2oy}1F{ZOL$MCDW z?@Ffbt7rUgwom$*Xvkn0`$xG(qF^CY`4XbdfI6 zJ9LNMqPHz~o0dNtqrQ0Y)8!wF)35T2tryC>#l_uTPX0&gZ0o?uQ0U>GZ?=82=)Zn) zc4l&m-WT70?Yftt&c*-7-Pvf# z1rnX{{9>JT<3B{k=ALlpDBM_;E;zNw$i0&%7TdlXP_u$P8u32Z!b26}-``@9hnW{} z-~N|Rhf-}Pf!j7Q3*fhwn&I`|uVr&?dF5yCzw)MTdICm1JpL~sPNvB+hTE(zDmW89 zb13u3vk8?yTJ83ER9~7Qi-01`rAOQtWOnNfz2FE{>xnE`*J=zGLt;XvQQy3Bae zamMqrT}P{da>N{vEjr-Dt|sD879OB{PQ(_Z(6v&D_?IC$%2WBI0v0;dlF-Y#)MLWL z-n;mb5NZjc$2=CPfMGdF(1p#lc-6_z5kk$Z)d_hfJlbr^@m6Lqv<#A9txkuW{SkXO zWWz_M)3E)@UHMMb5>n|@?+I8+isIqI&r$}ajz%MSGwRW}>4S=Bu+C>>b-FN|9KWFP z3DgU1oYye>5sSV+uZo5@lG*Iu(DLhN-27gZEQ20XN28Iv8TDw~^kEm}Y-MrrpGnsL z_^i|?1sa~eom)@vK-(D*Bb%5lI4!^5O&V_jYHpA238;B|5mA$1-6LKSjLiE3*9lp& zCwr>w?ijhJWY@Xrto|zF8Q$k7ZZ-`U-3w52xOSbKRj9~5A-C~=HLq>7xK|A=&$H#k zOPgqw)HAuiXKLsrC*n182ihz&8d1OhM{=p6iqNY!MrHj_&*Yml7tKFXHGd)ty^?24 zvY{71^E4kK@JSyi40$sevBt+ht-$CoB!QQ_HR_YILGx16`;jcZ7X@!c>{*>5YDKWa z#F4+Cw#<_(=kM#0U&CbOnLbAl8+142RqHZiPveZ|!zdaJY7WKVum>_mHQc2bS6v=Z z^-wOm)!z(5uSyN0jv;S;P#PMeNJZ7}Q%xfHgWDWAkH{P25>WvtqxJGuvECAr)Iap?4{r zo=S#G8JIePH>G(q>e0CAQ!1jt0z|?i+%F4l-$jG3>~iO#B88_Nj-34%7>GU+Z6j(?nb-n< z^eQ`LI8oBmGfz3x%0uTPWqVYZLTMxeBI6MemjyTFD-@`Xlt<6If_~NBltz)DPE;aI z5@5CO^Ymd#0d}y=jn_ayScw5(Z^?OHz|6OX`yx&99?GGsrs!bMA9;d@e87xb$a!H! zU<=5(Qxr*^RH&`QSr5}{<79EU*c>O754k!5$$G`?Dh{Az+8aBasz=RE=bSa3(|M$G zHKh5BGVdVV=p!jbKM)q=ToYP6tC^`sdOS?O91u~#qc5|28(bO(ughZ%lU+?&rehJ_ zc?j--jXgsOOCzP^o}4cW)S74;ra=Cvaeq7wxNz>U>r9!)Azxo51q^o7^&-0fX}3+8 z$>NrQf5^S|Y*G)JgQreYpJq4GP$IK9;BH$7_pK4+OtTHcJ`kSu|3f^xISJ4*1LySE z>k1akWdmd@z2F{OiYG3r0r-vZo(%S(Ubrr^ujj1tTqf%PLTL1W$jS5QYnr;H*7+!q zZnP{4Rr%w!r7T(YTF}v>wdKS=?7uY%*6HOd+w}=9)_HA{;|7Fe3yvgSZ$d4pjt3@_ zc1zoKRq*^}mZ++@~OL60h zZi;>^k_QJOxuv0y5_=ojfLEYB0^XaUWZz+mbo4Q7UJu}+g494~kAz9QVd#RKgjr_< z+`EoL z54u*7)^g`uDu9H}UpW_~)<%#-r_HH0JnOv|{Nu%&nkEQO+vF5p2&0p}8i?=bTvMKO zynZ3Dn{Y265aMnUf@vVM=_G}-Zit0oCtZ}MLVEa6bmGNjGIk2Cp&(+Xlgy}TfyvmX zCL~E51bov~!IF~eVVDsQjl42(Oo&UK$03O@d#0W$k=T??|N5yqzW&bWWLJJe;=_dl zkSvn6$DO@}_fCuedeR)A1j#N%GI$`u?JAV*|Mgf)j8m4344_QH(~m4_c3B5fwRB~I z+J-)E`i%{>=HCOXr7}i7b1!mFDl_Eu@fp88%o%RHws1X9%CJ;vbW$(7VKmAXkGMByv`MMcFzr=pGI}N4+NAS_Vhb zHZXXY54HeAV4xmw09D4pMSs*G5gwzZL&|f8inn&6SsO?RP={N_xz1)x;p_|t;T))H zYmPku zeD?$?>rdM<7fcC)8aA4Zye!se(QhE~{Rip@kgfB1{UndCiTXinNL7MRRQ`p-Hxx9Uz@0oZvsKNA)Yg273q8HjkDqSVG1Z1vrE6fg+7j)D(11~$^%!kGtP zp127!C1swGL-IDXqw3CEI*b{hwYZ>mq%bv#dMbAS)(eq zIv+IVcon5gCE=B}x65|Rbc&Kng4$g>Si&@eZiApc00*Tm33O@{U6v+4%22+ z+;gcb@+Dd@g>@{K?qVU5VzhA=^mc4rc&sgxadG7?%!aoFhtLIWj(Q-;sw7nF(#nRE zOgpQE?=t~d(yXZb0_~Msav{r0iqVx9T_Fp^MingNqTH-T;_2C_u-C|q2*v;niKXj! zbZ*eXB}hP{DkpWHANv=B8e_JXb2dGixMw-u61%?1<#C_JY1A~pLO#@xZtxMCP}MY& z(X_cy3)fTo1GTP;rfs7)MQ=OhZc>SM70Qyi{eIijGmy%aA7#lo;mSS3yJy$Sm-6{? z+HZ|+n`JY4eB)g3%yZ_7Oiv$K#59S>6uonJL(nk>ZAGNsmeRT?U6JY~X%puB`Q7gN z@A~)0^X{@cN7RTRDsETBzsg3j>Jz1`PpK4ft^GnmmGts}|7ZcGo_Z4_L2&yv$`X>2 zBtqK!cx?~F!l!sjvb9lzxwyIIgmI4pa!XqA+Jni&qOmvcDWJ z-EOO@aBfT8z4F$Fb$J`>+REF3kwz|7<+{<;1yPo0w7K^Ol7aJQ_gmL&yRVua$t?`j zoDGS2*1T2#NS^W8(ZY14VUlhH6T7O+b6V`a>~D@62pKgRK4_uLbaG#HT3TEa)_paY zStiZ!aiL|y*i6X;<7*AEioLb&AHG;Xg$luVr zXk+FqYtZ9&)bi-ls&wP4^Q+<4Yq%l)wO@p5yYcP6e_o#4-)UfTPtc-yYH&gleayZY zZjX}a*z^;bf$U~}3pHuO_2{ONXDoY2KkF>gF04}E%n0KHk-~OB8FM2UagrTx1yQuwjF))89r*gy`G|4 zn65#Abf)L%7;D8v7%c&JGYp=kgeXVL+zCS*A6SZ%5Jh)2{b`8Nhd4x4A16)I|=Znq`x4Wo&bHp=wlE?|JH z4XLiIpn=_|u(V~4UJWqXT7~Tzy#gD+2SBoM#oz&-eKMH`I>UsF<|&i7r!E#-#J*;7 z?11QLOn4ulpu5W{hwB}w9OYoEXj zFp9SB7%Bd>vkoIBr%H|`7#YP1(@EPGbVwR%W666{iP;HAD7)f;2{EQiMw4U!4!g$L zJW)?x*Pz|RYW0M%g)-6)3}|UMU%rj&WAWoQxuv>6}<9+e;S#CBext>a<4SOd!J6v%%|Y*Z%XY`hnw%hh$b%0BsnEd10g;z z7)x#k00ozbz!t`GT^2rm3(B3PPH!Ao<|`{)9NC=m0GlEkl3LHes_|^oTvZ!fqLXt^ zl}3uVL0efk{_-~*vQ$B4fo*^>MFqNoU8IX|ndERxC;$IE)LHrq@9gwUCp8DrZp1@TYyz1<7_x##TEKBaEM(u(VlBV^zM zLQ~QwsOvWl%#x7uB{cLk2@&n^#jY!<)^a6^y<%+v`?B*jvD#5lb;u)4Q6=OBQ|sC^ zm4)_{lK&Eep@7|}GgPFzS!P7Tj^3eE@pcwk^qb%EJhTIS%U_(4V(CkiE>^v0C8o|E zzGW@5$=s!;W%@ID+bHK)V6#LGXHd$jICl^s$5-_F(`(B%b1GzhQcgJg$L0RPd1^9A zBYXV>SP}n7)+41K6dgGUJ?3BMnI%WrRSQumM=?u~P}&6bUe9#IgGDK9FZ~tdoW5mv zWx=|rbK&M$yaqm@^)%FwN%R@DramybgNmJ6FfEHjiD8<>)nF&;1SQ8Z7qDpMOqaLW zu7geK21nv}H*G3v&0ainswx1&nd_%t&$sGm4!9dpH8qq_BoT>;00p|J^UC5z1J0|U z)}IEp%EG#!*x$lScsj|ImMx_uAjzWZm2mnY)#eLDJ#9&TiY%(71K#^{9(L7<*AWRn zL+$2Q(gUxspj5cSQK4)v!2=&F3j*9UsIAGANoPQ49Qjj@LFc_km`fC6_Gw?##9Q@f zC4bH)(A5mV0fJ@kH{sxmyY4AJbqeXV{LY}QTA3;XcgY;Ldb8F;RL|M0GMt92C!e#A!FEx?i zt=9C;A2<`PPSK_dq+ZG-8Nt*~~us@oX=7?-0-gyEF2|iV%J9df%Bb0;@ z_u?g^0GOTUj0U^$5TD01edt!Jv+djnjOKsF;Gvm!!>3BMO-mCJZnaG6K^r-j5i_4& zZdByrxGww3&Na)i?B5DNwR}-&jo0K$Yu;P*a!%(o;xY2)0=A`teJa;t^ODft^v6&kvnq2vZw290b%m9W!O)PUTan5y~KVf$S)4nR#g zX7>b|IG%1fX1wecm=(UjPva^U+To@wyQK7yee|)X)F^V!Vg8cM79`Wxh1&({I#x*| z#by4GwY;%njKyqS%CiV1&Zk8x5?LnV6zYKD0Znt|ZP1_F^kE!H`A}{t=R6uLbdS^Y zahIyPBn7J%g7gflUNf)=4JuFnN?7BkO*GL)v^3?MM^Ugx3ChvvEeYm09-*f#;iJtE z>j7hP+py-CmwQiB?icz~ocjU1+)EfY3jU;>{PB&a$;AyPOI*D6YYb^qn#@7LZ!sZnbjd&TS%4A>7p)6#wtC0xKTHk&VeEqlQ4!%nPGtrP4}+{pza7voxZX zMKTLeq&t$7GF?%46fcO3n?Hlac}fd4&E>1cg3R>pf2SMQRoa7Syb#bmAg>nuV9?_o zDgkci|82H;f+zutDp@ucFmTtfv3t#wZPWf3 zVNpWfi!t)3Fx!*SSPo~_9R|D6Y&rCMGlcaN`j&p3=cNV}by&(i@fbh7CN2AHRI3)LA)17Y*;38Smw3xAF8xbXBbXWX%yb;ZQ6Hfq}4(z;hjz=K{IalsrHD8ZTrYoAi68`{j!nFSQU1z)G$27;PVL$ZbO`H z8AU6t=~~(TKj}3at+#|#Q@7G)5FcOH)RNOHFTe?@iv@1j0csta%C$^?rwA9@Dd`bg zIP5}}G#3iu7-kMiU69oIN+wt^7z{40wVqllFf6E&fJ6xRGWHiI?)Z(g^s!gZx!{Nx z8t=Sd^zzd0Eq3M;uy=3$N_cbwxOsE~>{*)Sw2Q?HYYuE+HjAF!r_z>`wn0lN1uZN^ zXW7T6u3klx<(q6U>6uK{*V(!wxex^rD>iWf%aJZn8%(FCu?doGx?8JEeU0>B3W+wn zuO|5i(hs)|_IJtr+K>H9-AV!k)Tx9vHr8kxA{XJwK0_0jPi&xVA44LBl`_*qO@&&P zMV4@TtAbELO*?jx+M+;;LG|^J0+qkng)QHK60ECRAm(CI1F(#~uZmV)zmsqliRul5 zDK-0y+aVbleb1Y=6o}~AoTbMF4IYj6J4$KvpZtc+)|nrDv%HHEw`X*91p<;7v@UPG*B-ixnrBQ8!0#JhX7OCFy}#I%pQqj`f7c#g`lYIX$U?C{Cq}vz!W9N=PHq0k zAtB&Rw1T62nOu+~NAyh=HFZvxk#!Jg==_|m=}-Z|Z$FTc)!|6yX>?g3vvKr3b1C}I z^lS$hn@t?`MqWJkufH62;1~5NehKgO*>gSpL!GGhF}z`s)nyFPq;ZWI{x^miI-_Q0 zFV^fx_d@NjHlH1l-Ocsx?c2X!KU%_*nLkZ->b3m+-pJ>)-Qa5?bN!i=I?)PEvx}f*-BIwH-z!Buicrx{av_Ko&yU7HSgC z-j?}T$G1&GIDTP!ZN_FGHFaoc-#oB9q(tf3L7G!0WgUiAazJ;Ec1xxA|LAW!p^S<5UPC+)$7Hj#5(#=FIW zbHd_s`+PZRm=xadI*q*+de^-r^}8P;UgISn1!3W~^AO6^NJgo-41tR98lz89tn{VE z`SZuu^ZfPeub(gb?Kt#St2SKyTYoe!K^YXN`(bH!MJ=lA06wjn8Qr*)RmloO;?r)j zlWZ+_q2z3m?gako^8k|LGp{^95G^_lhB)qZYtNCFWg|{_k@R`8AC?r`>BcHgXcb2@ zm2oDlR_fqCyd2d*-R%^SHov~qgx=^OtvIe%&XPEmVwhXmRSR)_j}R$J#fiQqk<*gy z6UT&hi9=AwGH%QK&S`7&OpmxvCTO*30Y3cx+6w}20H$;-a)e)ET5c!P^0dPk(3){( zHHmxc0m(M-)@#9-GAG{)%fkr+dol|D)jrG8)yHW@DfZ@vhtU(&yYh<$z)THSw&YbU1w1aF6&P^p3A`hK6c9 zG&a00gfLd?0ZVvzNV^BR8;#fnv}CXRd6auzr<@3De5UDpQ3D>MrJG{7=dOmE%>U+f zU-`g*w3RzAdraD;be~mp!uY|`qKD3zrHDCikApgl0T(93#~HVN-Ml^}#N_Eb`Dhbj zPMlz{8FBFi1)-G(M4dK+hc(Zo%bEZ4&&!w8O+w-?Kt;CyT_?1_ zS&|_6eje<}Ob?HL&M3Q6$&b?a0X$L1H>wCsm`XHkA--~H12~s;n~^m`c&2-DzY_S= zjtMs?tY!pZ#NQAIH~M&YvLnqfKhW$k*)D~HveC(1ZV!6k=;d|OURR}8#!lpGgO-*Y zNjawnQvcqOQ@*Rltt6m3{hEv3!YA0Cqzu|A(*MH0fy5nYu6uXDL$7P7-8mHWBaR9D zqXj+$g1U<-og2?lMo_()+5g@M9&?|kT?--L7X#bnz#%#wXSWL|+*(i>l?8+cRjF9r|?UcWYM!M>LvP`?2w+yktwBIuSC<_b^* z9XlY2zf5`dC8jvU*t-3eW?_zsQ8(F=No@zM4yT52epwW^7JGBaF#!T%=_;=+=38Qd zf0zW(AMoK!#{VE(2Hc#>S*Tn1Zy0k~1V%7GfnQ)PII&XUUfc(bO;hsUH0AT(e0ltv zI-ex^a7z2`{12MU{If6nx}Wl&D2U}@%+*_f(C{UGJD%^k_Q}ulZwq4L<)n&R zu=oxS;71h;3t(GyhlxMvYxwAw2~*qXs}Y{6oKTCQnz_;c$5kR##v;wFO${vbu3TYZ<|g2*vtDe}-Dj9_*h_%5BweZf-#m`Mjp*SzNTBN>irSvV#uCb-`w=;5l(r_ zuW$Cn8RBleFb6V=4J()%>97LJVTo1D^_z_Q!st!pyl#{0)~XYd3iMvQ;Vs{HHymX|ukvL%_%QjR>GHVdrS7mAjE zEP&Hk1}m7Y^oo7Oa%0q*5HaRatTB#pY*F?w9$su!U8x$pp+%}NgeLT%^tV)uJWt8( zYx^WM-0ZDX3VAQSam;M^r}(QrhGf1Ywe@u|u;)wHz8t*s+Z$!w%NUDU`t2xxCU}Bb zHXQ^Ldt$ZrYf$fi?3VL7bX$aa?D_2LY=$)rn6i2xM}pDe_!t}nrUwS#PY;W`KlVJ$UAX2usZ1gKtGr+9X38JmnAOs!{xZPDAR$N zf4?{r|7`Y!aX;wRf_uu-Aj1M@kNec!3>rFB_k@z^vXnL1KDXOZzY?SF@kCU{)7B%X zGwqOH?mp_Q`|BaL-LQ*+b6;*INWv)|+i|*e?^BU5js@aoS07da8YpA*etX22;Q2Gn z)5o>?CkV9ZzzfA24W`aQc;NCkBqJeU-V&8V)&^juuq`7PJZKd7G7xi=2?8!MNmMLT zaAeg~l`$O|O*Or`nL$i{?=zCEg%P?9taZ^O10tC$Fu|BWu!$IwX4;{V%}(gla~>w? zd{ZnvgUz(fDUQSll=9YJg3O1tPcvm}V$c(z-9&I2{4Psyex+kQS*x-7Egx@%U(4{G zq|O)4B=>LnomaJ&k$L}5O2rb17t&RODKZ(zS477|Qoe$57U$O{eX`YqUkX#D{I6P)el~-3kQH9G*#KQIi z?Y~dn;9p2&3kX3lJjK_dGnklJ@c(ARmJ?1ni@IaGd6W>gK$7H2rF66y5@EvjUyEXC z(q&X6v){frY6@Xs6~T3b4njBSAtE88prVD3(BDjzU|?cZjE#ef z7qMGxyUngU?E9BP?{Nf>kOCutB9lcSr=X;wrlF8akd?_cD*EQIlpZTD579r9)>w zJJX9B#aYE)_s%)*LQAZ0$z@kubuFtt7FLh&_8P2Lq$ts1#EKIyL82tdQlv_AJ?nV3 zx#^bM*(T@@={3oaDND8-x!D`-yL<%-TTz8Wij^o;rd&n)om8b-jaqdba85&kE@;Bl z+##1c*eV8==#j^sblm%%b<~Gm=+>jx zOMPDDlDdDqR=~L>H#tY{eO8d4I^pO3Q=_@8f2EO!H1d??dC8e4O!g&jfA^1nRLXtF z%$c_UqD9PbK`Hi>Q$*!U` z2Ke$zj$C>2RaZ7zD}#NLE1Q#tRNS@vLqtMGK}AFFm)FcCg);9Pi_V6nKI#B29zFr+ z5fKC6DIo=dT4#M^T(|1dE#o}t<$cdFT%=;8IfgeOQ# zBCFE7PNOr_=Y7(+JbvR@O4#;pQDTX-t%-?}PSzWYCUdM@p+09#t+6`2{Qrb#W7&@D z`9T=PNt)$FS=CM3^}{&L%ew8ydEL+Z{rYg+#$X&KK!BqTS5hFPC{k8*B2;BYLs2AZ zSq`+>Rt}u7aa2{QP*K7;tfYbpYpJ!ns;jBCy6&V@nQ|2>RjKZxnwn#zR$aMG;(84l zHQ{R3q7_eDm$a9p!<_^T8iM+iMW;eZVhP2U*EZSi7S|2;+%K)va_~!u>7E9isbRU= z<-!Xqq6=-&@4T*le?Mtyx2B`3r*B}W^7Kz;6##@_Dvi!yve+Ch&kw>VPSPwdN<#lD zh-(_i1arqm>n)ZfyoD;&hoX;;ZasSS1p|8!fEv8qN_PAZ17vUP|MBKx>mqjo7&OXelxOMTNGE)GPg2MV{P zLZhG|8`kc%ONMQxTjpCMn|UK!|A&St>Nr_9voqhS)_Pe1w^0E&_tP8fynTzArV+(o ztl2}_QTfp*z>UMXNjG>irFZ^Zky#MS+k*{A?~RiPOc=uS66XUKI5wo6aliHNNYIUK zh>+in6%(%ckG9CsnXNx(ay&P+JgfM#$^_{E(U@|~{>v3>qFbk@ysMkWI;%c!qXFHT zaou!RoFieB7IygHg5FznrGs92jhgDIqoD=6W_=+2ukDxqMvl;b8jwFp*TTOII=Eoa z4~^2_Sk?jkbx^|>mKis(w`<&79OG{X;wJLbV5YCS6d z$>qo|k_GF_*a{!zB{5N4XzR%qFmVo-ruQ6UduhTn>it&J5&NX`{qw_nzfXu`h7)fu z9?)5r00Rm)t;^d28XksOWKRDx>O*ZeC_LjvYtHB_oSRk3~}VBV(eLWfiGbo%5@wJ+=j4K5hSf(6%_*9EzMNtFEH69eStD)3==3(nLdl^0WB=s; zuPGJ%i~c|TS{zjj&FN;a(yYJA{*rUgaE#*OXF-cU&oHR&y}m$ozaT{`$vB3$W9>;s2_zu;r9ZC#xLx12=pKjDEx~;b_#(&{U`(qzZWR9 zEP4IuI>zh-hdQBBsZ{Ey_D|XlwTR_X-zT2B_Rosn(5JDSa$k{5gj9zy?GdX*SaSpE zF3YsTWCDYB!2~{1a{Ryb=bh|U&+h@Db-#^yyBDLpV?j0?zIO=Olqd<=v|M*_iK(!& zPD$5q`PFq|&%nIu=Im);?(Oz~(^?8`|nPi5M^)QSY^ zi`g$uO>OX}Anz64!;8R@NWcWA4}!@FSaF{^>ix`7?$jH=(N00LPa`ulH0;qGmH=mU kcRimvJ0|Ysl$WP+bbm#Qm)E;~S1ee%cHV{O;P=f!Bxf#|y=n#UX+q9BhVQrqOU|Bu#^kjh3Nhs(A@(j= z*fD!v;uVKFgslD)_v;n{Vf}-pQOFt}e)|?KU42%`O>MLAyG4kklqJjO&Mtas`a&W5 zO%lSAwRHAbD@@ap|0U#LD#yKS_R@|IXC$QH_qDh`eZ}%stCQW=y&z=k7eaKiu2|Wz zqIccMW|Ts1Tz7#|ZEs=78DXRdhCF&;o$Tq-{avIHE2lNIFYhs_UdKAh5F(X3?fG%5=EwH6!HD140ekl1N)D2 zi}r!-fHPYAPjQPgMvQ86i?t)$2D!y0?W0Dx#fEW2bIZ8)R=2pv$VEb$P9v>EGNh^J zu89=U%}AR>s>n9dX6Qzak+z6*NM5J6iVTrwq~nAQoa*>^VHf#EIzc#uTX+_CtXw8u zVE8J-y$laBJk0P5hQ|m>!7z?t8bfH&%Ei*nu!vy=!)k^N44WAaVmO@PXoeFQPFuQo z>0&vD;Sz>x8D7M29mDGx-p24ghL14Z%J4bJKh#eD+uzd2S(6Ys^oR4J2PIl>AEXz!-WOPEh{R71yz$3%k=NcM}+GB z0O@znxSlscE7PDgNBQrK;FrN|!B<2=@a5pf;FqXXc8`#YbBx*ml=I0<`ev! zas#S9_%7WD9^qeM8u}Id4$s8{MRL=rBlrJ_(!WIh;e0#sA%cg3u+ouF@D1egIq{G0 zf8u&0_#WyYf-mEG5x=&DXoH84H&OounEt^Rk=h0dd>bFsG5AgJL6H*t47m}HsesHS zC=!8_oa-B~2z`+9BKN-s-$p)1LRkRwqDT$y4c-e(qz<131HoM=?PXjyiE5-v+O>JwTJ1{hMs1h&vbI+{q=sOKnQQX@q-HBt0elW|QI{Tbr|rXHAjVCorD2}}ww zDZr#KrWlxFV2Xh$?gFFXej@HC;(j9E@Bf1*DA(9>yueiBscJk`4c}v;7>!?}@oTh5 zl+|dp-{HCk*S)yz!*xHd2XMi<$cJzp#q|w%RBB-G1ZtQ36H-)eA<8X8xrIWLqtI_g z;~E1WLE)FcFIbmwiYVp*HxCr^PJ=$x=#3#AEJoWDN9ka_9D&+G50UR8MV4c4VZpK)$Gx!)VpX1lV zxcd^U@p0k8ShhL%F~)`fMz9}zbR3UDG@5?J1p3&aV9$?XlsKV36nQ$53S|c#j_6}% z@GF$`CCbGIm`^aW(rAm>2+GL7h-2nakH*_CdGw}HH}pvgo&fG!Dl>S@C|_7$m^Uag>hH6yxd9;K#sLa^7EpYM0Ip zJX15%<0gG*gaqw(#%NAnHDMtY!UGU@(KVnOU!!;MxPNI}-dfxF2JGQt(k|<9DJQ8n-j}p3V!^1lkvp6Upo#-3h*h z>vK@P6{-VE&P;bHMNdTJ6-w#S=jW*;t_9#B=**{Rk0PYs4}K_|!9DopME=jQ2clTp zzGPlMM=v=l;;Chkj~O)#kc^q)IO`gDm!G3VjdhN60<$3C0{nLr&yz+*eGHu-dBJzY zv&WG)as~kQg-uS^^A)SomK+K1mt2jY=aPe3@ph>|B%PdAIRl% z^hN#!NuxI-4?A!#!jJ7nvVnA-M{SQlKMz48*@Fh=dHB07$mMzNO?K!S>C`c5EtUcG z@6VyRAA>ixFR&4I^owqw{FqykT9m9=i04onr306WJg8?Ri1grr;CAqljy8&ieR&j5 zQyXpJw%G*>+^LOF3alizFEXGHS`7UUtwX(?cpcOZ`)tS?7{@33Z2 zPu~F>NIjb@m+?Ujw;BC~EZu(G{g8F*J6Mt*$dK#>`Y5#}ak)!4Aj_lR{3!a>%Si8{ zZ0Q^2sQhE3H${QsotTYh;Rb1~LMtff5vAkt>r0YT*B@@L03;8efcc6?jlP1Weh$k= zHkNE?^rsgnzvq@5f*uR)0_=nD9Pn3-xg0)tB0a40qz|DS5>PWP2e{Xe+DjIXIf$mB z96lvK0UUe{y+6VB^eDF>`2j~+zHC20+C(LWKasvjdfz{c*Awy4zj?IbksliM57wd| zw1vSP$tMB5|4VMW0NUapG; z$TkRe6LKO=)yK)ullZ2VfgVAAc$)75!ei@H%4mx6Q0)*0Oh;6*8si>~Xz3Vx%%~T| zuJkw=C%OV5tMEfz1$6-~vQ0vi!dltzoq}=Ni73wJVrW?JT);;@spuWBps>znXirk` z8)zzGH|z_M#?i>YF!Ts)0gc{}IQNNvv(9{kc4O^iebD8javP{WhCy^BDI% zJ82}!IEcC=b8@n?grh-?@}%&zx#8aJstkK;@|<)YBSe}Qjc?L zD^fc-^#W2ahf{BMkvjEV{fT#x%SRap0YAm{A5IbO7^ec^yWy10qSDO0CISAzUboy+OmrCd&@G~zyzU-vNgoZ?@dbLoYeHu4=mQbWS2wv(pXPf0fk zcjwt=0G<&}5pG2%+*;dtwoAASN?rM1r#5tY;`*PF-!0(p4$hBK_i*YVq#ohaU&5)U zk-EgT%eLD_sVl=N9rtR?-OjkTad#g-5urN-++i-`vvBGNQr{BJE^t}+E^zjw*pxjZ zL}v@%jo|EAc*4cGbVcX0SJ~_AW%fRHN)0%TRLg17oh-kR;WG3T<#%!p#)11f=AKdm zI5njUT;y&fbutbjwd}+T=dPFL3ztDDz1-ORIz7ws({Z!##C*g}WE< zT}oZnDYdSPyQjuoizja6Tqt#GICW<@6~WyX#&v$;;VyEC;3%c%@+YLWa4y@C+GBqX zkW#OQQ#x*M_-)?r`dXE>fqyt3RSLa*;&ZC(ox|5lJD=nPL{E4Yt<`6EU z4XO5UDuO%R)TB<&&WOqRbaOH2z-c69a23YQL+T7JZACa0!L$Ig%zc@! zW**9<)Zx=eeRi63C(G|hxC}i-`JI9T=h4i4%>8bp4s+_WE^v{%Q7Pnn>Kb+8g>&c9 zI;He-V{6puS(cxU`xZ|N%E4*Dm2|QcX^u04?s6)tQ))vOcTb6Py6}XLa^X~2I8_x+ zMR0XtT<0hH;Lgc$bXU)108%5JEzWVyu2NHC?#^Pm2riPE?_9$6ex;LA58$cOPo4E6 z&l)2Maz4sAA9bFE)ZHlKXcR7TH#+qryf`m76{p7C%RsY^OS=~E#&GJ^(@5P3n){gU zVZc9yQ(I0W1%L9teBwFi;2E4VQqDamO}!qX%e)?T_ZFtx>pbB6Fr512q^U1Jck;WG z%jw+x-^=B6cs?ap*hO^)B6Bjhgy9*8zyTvaC8&1rUF@`y%jvFqjPA;*#v_V z0BKEE$|HNsro%A zhfrD}ZcJ&;Z3t5iVIGEuV>0lOnE-z&*vSj=kwk3bv)6C%jvFo zfJza}vtXXZ<&?j;oG8UBO!EpoD_+s?6!y&EDLIgH8_2oUG3E@eqmA)(gjcr`Ufs$y zx|?b4=DTz)XiZI&al-3^SyQ{dA)kLGsV*D)5;bKb5OSqITSTYwg{p}1d=BF;^ zoG&&>qSWb`6N)TLmBExl89$WMlQ=y|Pje2FI0sr6kg|#KO@tTEYiAP1L^(Gx&6!NI zmT9_kx;yjMUB_^4-IUFQL0iFL4ReEYWE=XYBJv{xg`Sl+xHsNAx93i5=It z+f#>xmpvKZlXIZ;04d8DU&ihHimN~JJ=1UvPHjOFoX3X7;sbb1D z#vpnP%3Mz8@?GXlmWrdmml9r;a=E3HkA`S7;25U#@w1n5iFVGxuH(5xyS7wFaTC#q zoA_=y)0gXMrt~nzLuH9`xD*dPE6&ko1D?gt-bVS0vxy$Nz$v%0DF<;j=YJNLMQasO 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�q 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 DIobj9 literal 0 HcmV?d00001 diff --git a/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-SemiBold.woff2 b/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-SemiBold.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..21314cf043996aa31383a8f830af276ad8ed5153 GIT binary patch literal 33876 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 literal 0 HcmV?d00001 diff --git a/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-SemiBoldItalic.ttf b/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-SemiBoldItalic.ttf new file mode 100644 index 0000000000000000000000000000000000000000..59b6402dced2c650e316d0c36f11d50194fede6f GIT binary patch literal 96636 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 literal 0 HcmV?d00001 diff --git a/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-SemiBoldItalic.woff2 b/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-SemiBoldItalic.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..1abd05c8bd2826b652b2a2e91e1dace9fe067362 GIT binary patch literal 35148 zcmV(}K+wN;Pew8T0RR910EtWh5dZ)H0eNHq0Ep)R0RR9100000000000000000000 z0000Qfo2=}EF7PH24Db`9teRL37QrW2nvI~0E3GZ3yc^50X7081DFm3AO(#n2eJnY zfg@Y8Sdjze?*3;QBr1Bdsyg`DO+KiG&8aQuciVt?#iPSMDq*+6gYLkuBHctQ`~Uy{ z|KE~KWVkK?E=dce05G>HV^h_CP%(o!C=DbLDMui&_n>1aR#Gzf=(3h+3@}r%UY(cJ zbIp#(m^RCM>Su9@%}L=%V;p@e9 zWSRv{5C&^t`|%Ku;ndE40G|`0y*pb>sG=7yZ5K(QSU$TkeUYam>dR!d!a(JyzxV^S9h4?1DM?WkzPEZCJwi5M^q5qcM5Ix)*_2U~jg3gx7o^&# z5oIJ6Hs%-qNvFR1(wFU%th1a8C_qXq1xQIs%p=iGyo~Ky9=idKh;#V{c-!` z#&K}RIL3|1aolZgu6Jv2lW}((aO|Z*x-nC6lEzMtg+9tnNrdhcv3)}v%rT!Y6 z7joVy7JvZ%JlxCfd99^THa0;ZndW2R6iXd#VW+~0m&he9z_W8sJGcLx%hcxE zBgl#e$m6%P(Q-loxg#6^{NH}__iRbH6j%Bn1q@X94l; z&PuDZj^)(lfUZ{YHw-A*S3pj{FaZDmP1WwbFZ@3JHa*CTHsd1ni9#-&B zs|ClEtPQ0PHb70|84GG^O?!2hG|8&Z^FX>NFk%^8g{#83zp3 zY%^8UR)!+ca=Smz903jxPtLCS@5z}<$+bNE|1xLiCSAtGQnuI#$%%0kK8HuTe-O5@RqDCs#=AiT{kNH4qCyXb-}ybIFH^7H@O>$2RulQWbm(MXKSuXK;Y*x%1*4os+3)!pt& zo02xkcH!a>X5|Vk7ou{axH@K$97_PAosepo9~svFf1PDYeSclU*>RSFq#*Q?Hw5Di zmuWit>3@4=>DfbCFf1V2n#nn`Lq4hkSZ-?WfT&DSbbeR8gTyKE27v^7BpVT3Uu z1b17OG1p)N@f1q*6#jyWc5?y&Ww7&9!+vUC)U46oNS84R2#BB{2sk>w?(5$8f4}zs zi_$Z7hC2?G;#`4(f{Yub-u-^|^;6Z}MPV|y^k)SKq8z24FwJHD)9^bq-u58CSpe|i zFnmaqK=2WQ5FrAgk534{R)z>GI>hQWhS=Qh5PPc&alQHwH+m34j07Yd(E-Usavj$~qD99LJ0-0+r$b4Hsw)q+1SHB|s?sr7>J%#AcP(XlTR9_Rg zmU_YUcN^5*?tyyH15gip3T|w%z@P98MyCjThdX%&g5)zEyKMugLISWo18^n^%!PH^ zhdBvwKC}xI;D6{JC}8=q-C_Z2PJKKD>^Spu6tMrw>?I)WroMRb#^#ZE2)7U%6u)~I z36y#SlFaInNTJ-LAq}rbM+Sb6fh;OLCUU6uSa4C3@N^1!1gJkfa?1wjeRI#SCnkL= ze^w|7Oy+*%e@lf*;88K~h$-n=xHkKrxpuuealOW^qRP(5P@qcV|E(K<0OG2j0zp`Y zEq`8K@9{kp%W4=jL2=H- zmEiG}$S92&C-uPW_X^>`4(R8iE*TYI<>SU6K`5)7#zta6Fwa*IODvEkhM`>C|bwKBNAQhBoM*_BCrZ zS}gsOcb#=|=Ap4=v05`tGRaz#%>D9Q_VOlNZpN=gvs$vUQg5iClS6g!`IEj_EM6`S zD{#53Tiav&8sc*)L{e#+_M2zkv-7xP3V(8^JoyR~DpIV(boJvGjh4f<%S3*uDYa^S zwv{zL6vrZ!^(YGPHVUiSRHX8I)z(xlo%Y3V#|B;>I!0U*OS{@$Ccl60Qs&M1(b0(` zR#_EAzJwmzZ0Pv;c2tT0x>Bsy38|ue2-5a7X(VXxikLM-kNR4723JpR)i=}iasz`@ zHt)Rb=@X6vBQ>$b1|eE&0Bqi@9*qsqWH~ZurM~wSYmtG6iKJw1a3k&|CB!SPa|Dtx zq&$+`yrBsY{ySw$uh>d8*~wL9a+zofI#LCu9K(ZDv0?}Vx^Oi*LV6|-pbWD)*|b0x z2DxrshB>{USX!&l28O<2{=WpapDY5HJ5$};iv;cSw9g_9sb{S#N+%$FRT52Q( zlFQa0iqPc^RAI6Wu51sIqFZgN)UKbOsa-I(zSgQ*JQc6csSg7Q?d%HF74 zq*QSs`AniJna@O_D3-KvNrFm{@_{vQ;Eae?s727b1$;?*1z*w?02I3j6TFrdAH6r=_j>l9$3XCowKNbP?rEojjQXE zGTC;|fuv}kLp^rcPD_dX6y`Eb>4L>=@i3BLi_(bKg)NCqlyrSvfV4*jrX(f2-4~Qd zEjVb)k#5}lYq1{;=!7KJa@`6rX5A}!O?%aH}wcIYyqo95L0RCz!oi!8d4 z9mRlTKJSihdu@n5N&At0pEg9+nrsW51@N)MWUdsEBAU2E`eo6G^937-{JNZw_K7tz zKHp9^vkg;R4 z;y9Qb&Y%%UKR_@gHe!|3D_2d+XgtYbLO;RBtw=)GTG$ZZ;}0mPa;zX!llQIVtcDtF zXH`O$*$)s-YVPW(Suse@<@K04+CWQ+Cg!G86(x%{%C(xbG8N#-!0+@Mf#*ypL_xAq z<7*=`V4no7btyZb$dPY0F~kubZ<*`lH0C2KiOV}^l%S1r@XQzD@gfF)=qhgn^*?H=!tVv&0ZvKmYQxsTPnINM zdLqd^7;zio=o_D8Zg6W#gyKSks)aL_rC6fcOi$-kHZ;6T0JX`lu@l;jDYDd=DW9i0 zt0fX#Do;Y3`JdA6SNQyolg)d6gx2Uk&}ZjMkv%1QUP<{* zp1oyQd;8-=w)|m#M+jD(WzI(CwNa^;v@a!|MaB>6ABzM0#Cik zgy+HwJ;QUEex^HOK@erZ7PioozWusN*2AkPr3m%2H_+aefoCcV4{kJ(9-Z26df~(H zrJgC+746pPTfIF?9Qa^&%@3mLGR+q*{z&U zta>-c{sFf?gNEw)J8!;W&(o!+HnP)BeXM&u76N(A2g zQaNK+Vg`5<2(e#fZ}n+dgbQzeQJ0yC!G{s8FS-$fh;h74(HeE0PC=;S@%QTk#Pe2} z8A9x&eR!Fjta(j4$iN$G-$z_VTy^^tU(o%#?+`yBej7^&<1hNBu?5E0_(?8AN%u9| z%1xa-(~!#w!zcrBij_;NR;5QL>AgA^%(YqR5f%*A)-J5xH!0(LWWKcvf_CcV!xR*m z`xUuMbJwZ*LN2}yC9vD+0FLrkO2s*W$S&BuE$>yBwfiXZ?#UjXed1+gD*$@(F!h&3(59N9o z$4SVy1*VQed2*o@Gj(!c=S|z!z-kbEyfZJJ*Ke(()GYs!<5hXn-_3XOHWS=yUF;ak ze@-N#*V^wm%F&$ur+IsW^3dYPRi2sR{IlN#-lZ$}gx&Icx3>?{{D<#pnUr*^KQ6O|eo&DSwdT4O-; zfo2g+?yZh}&&|rdr#}ku)v>ANWI3rf<=}8uId?TH`<_v@IRaT;dk$oSn_h}QK}XIRT7l2$YfT$E%CxxJ$Gyk|Etwd)%B-id9A}I zxqetZqY74n{1jt0K@_UT^jY9dUNf<7ELPbT8Jnj?xU9D1%XwPf91MoyfRfmJ;+?7_ zK-HO+A!tJtpJqi~qzsqOA?om#%5VI$UTD_G3JRWQ2fORmmErS45f-f_G%Ia>uIOCI ziGanYU}89*#5Fx-kUF(m9uGdldN9><(1g)DA85I zMuJWTN4s2%ZRNcoGrzS5+#YVG3r=3U)~ct^K?DQf8ZWii`@Ncu@_ogu7w%Z;<-6i2 zzU~aKDKGKzNpiW%7kB54*>Jz~+gkSE#3k;jG!jLs73RJa1yTR)rRV;JBm#B3rug~G zC&_OwU)<}G#_)bI=GEzt!7y^52?=p2{^HopR+na^}kO z9DGA@Flc0; z?NfLHmy(+4^l~+Zl!SZXP9i(BL529C7ixn1h>=#8)Nt`b z7U73hq#v>z!DaEG+J-T{u9<1DGVaiR9aayFxYFm!c9|w-{9^e%O`ykpPq5XYL}ZCTNQoE^jOtBM8Qr2qYQ?Is%3uC@`}iI3eK2 z)4>Q)K@|eE(TxzG14cJd2)pIc!vG4yZUu~Rj=<&fNL=%dMtBi1h%725(Laer%!v$E zw?0;=u?j}-Y806yf@_IQR+1w7EQ*|p<8b%tlHflQo$Eh~qP~_SX{|SD`nr=0cNDJ#{TwR&wY_L2FaJP4msJtJPVPTc%KgdB@LDPx~;apEeLcN!rOaSTEX zesU@bydy`B!iRuZh($08e8kL+6Dzbi29aY?xOi=gh7c_wM#7sYWT!jPS&Z0Fn?vIh zwYel^i+YKS`Ars=%<|8yQU` z-6ZmMN!9ls8?ac20ueVC;_764`slhH<-I0M#&Wd<)`{x^qY~K_-M*&v`)jRoJjwnV%Q9tXhWW{AAEV*Ee zptV7wl<1;T7cCaCUdz;3qZw+ha%c?c3*bfr1rAoh$YE##ki8$u^%wb_zm0YJgl8MA z=o^hn9Ngsmm_7K=RM@k4iuEXp(#?@y6HL44KnN@V2u71^fJUX0hA%>CgqceIi z5RPG(aK?mKLbw`4S8cp+DNgg~H{+aJ<#ukWmjjk*UcN-E*qO}JbyT?|Q zt-B4GE!8s#6v{ouFqSp|VelcNw86{}MiZf$FUDCt?a_|=JN)ot*`@h=cm zkSWu)+2^=(F1zBU`<*|mYiy{6JT9M9&?JB~*^tn%$er|fTYVhLAta||;^0-&8Ex%p z>4e60>Nje+RiD*vj0BrutfN)XZU z_De@96`*C};8i0ku2a9!o0mVaPywq<+iZuu4ms|O^AZE^4z#=C6Sv&;zz-hzqkLA? z;ZQB#upzjgCoL%mCZc^Pn#f%5OFsqE<-bAWh!y3bzk(%jAWbx?P_()&``VUV{A~(z z>bSpxQ?O+Zx7?#&_1x{kT-BJRHz zwizzipN5trB$628-?m67q)~uBNl-VMfodEKxQ;=9>w;E2EB}o5Z#(@zHn21>j5Ih@ z8Xs2u5eNbuZ4pg_K%w+0==liJpAg|stN1YLuSy@IJpwc*T%_-F)0%8?wAep%^znH1 zKvG?kObdhhx*nP}Fue%Ng%0@_3ds}m@U6uJ=O_BtawS z1cP7_EP?`*7z7gx9gfqGHvS121g;eozjWLQANklPKJ}T;ec?-A`Pxa}_||v6_k&Y@ z^pl_c;#a@P|%~f$uZk}IoRu}ou%OKb3_(-^jtq!tPTTBQI8!}`AY#a=OIy6=Bw{NAY$}OQr=pNe z0k0)=5#WQ7foubw-G-?2VHy=C{>a)KsSj*M)#lBpxpOlD4^5&@8XDZ^G*gL54Bp3w zp^6wWxA1^1@11fDcwvJ!*17Q&!z;1@@R9*ocGV z%$Fh4DkYk==`?7K&93u=C%s^pQBqlqzb9j&X65d7f3OhiXg zh$qQn@ygVxP-T;G2W+*+m6lm!g;iBn*0!c9%DKblR8n!JedtRkP~qZS=xk>?-O;X< z)zvZr{91qe$A7ZWk$f^VQ)YYG+?B!$r>h-#_*^biYRmE$tFfk6e;Q- z{-`>q;x)7n4i?auj}1YEw5Vkzv~TiAsjZHB*!I7EHQiKS``M?y_oI)H#}okHE-^a3 z0cT@Gyh=x1?=X=kh(nvoVb2SbJ%!Ua ztuyz>mYzbNV8ntA7asg$$44V=3^B=ZPIHb7ehCKacEoh-)`NH7wmaZTubE@Mg_c@n ztqnGXTr?tM9P2D)mwk>|&rXty{L7k*jAm&A5~rVW(l~Y3mMP<$6%ab^uajLN23~*p`UUWo7nZZ_k|Eg+VVT3L^$PdweJByn zq}dDb^Ir&Fhx+y2I$Qw&bCanWAux9va7;5jr{;X#chuL+<;j?$shLJk^pbn$R7~A8 zPV=-*`*cqC^iKZ_&#Rf7e~Tn3lDl#Nc%yfp`So>ReS3*H14L22&#&GuxxT#m!=L`a zGvcEFRv*SgVY*Ej0@;Okw4#cN`Z9~Z3vZ^djy7G{ZGlz1em<1KoO+a{Pm4&FGC|x}+OO6OW_CqH8la5$O3h7x8 ze2>#9Ys;}oi)(eIKDl)s5oN3Ya`KkPy@Qevp!11PD5#qb+Ge3+HX1GgkqBm+i#;kP z7P3GBPAV|92oD_Gu<*je6BmCXd$YqS$q?nv1nOtl?&zYBmY5 zT`fC>*`eM#_Glp80TQj}jD2KECD$qPogvR@N?oMNRVrmr?lO%ExFMegc?@XhzGm8$ zBi6=UjXc!Ks2-lU&C}i(wg2V7k231qxlB3A- zKb0>kIv-VTqEJe=Isgiq|sFq2SLS};NbIcB|N+HQkUU}H_p7pv{ zeePp#d(mVsdo#ksfAmYs8)LHIiV=fwRd;*B^ zBV;i(>v`G8&lVweiLhIgSdCnfM22L}JH$B$DU?pJ^VGOTtt`r1qQVvGWYese79|Yo z;DHv#^)aHGF}*xc1QzsT^J9AA-q!{s|!zA#22w#Yc6 zV`&N2mN7>RbH!q1Da+|uN=vd`q}s!N8#!n*hiu`ntsJn4<6=1}o>LMyEs+!A=vGay zTKfIRE%n^iz#TWZ={hgm=ec{l^nlmIt*@<)TI(!0PmrP2Cd6)lxcE=DbAaed9Hxv-TuHzNxtc=vkZu_TrM9T>s|q9^bay2;zJy4xVoD zHtt2v>Qk!xIl5g`yZhb_1l-3-lHUHq>h)Wk+fR{!BZSZSNG0eAlKy{|=BZrR+<6Z? z1GVu0Ce5J%0YNxwz|c~(ZeiO`L&Awp789I2dI(87pQAVLO6WPhSJ7kp?1c5xdh6$; zirLdINn(}?v|Pr*7z?!y(2+_~{2@xqi4f!q>d9q^EF(GDlmj^*Gayx0@0WT50Zjxc z{Zi0$E5at=nBcrmh|oa7ym>7vr=VOAHsrX&uNYP^Jy;E2x$~+b_^n`9jb~1fc01-R z*YBig$tPiZ8!_U%V7wLFmIfGlYk-Q95M5=6lnKz89!f`~l_mx^Oo9Q`GoP)Ce>SDM zvL(ia1k5~+_r}D)SR$Q-n_lgRW$lI##UPHHl~UM}gZ>glEmdW}kvaqC>LY9w6vL8c zXiR@J?6Of>1~691M}-$bMkL z(;0bC3KjHJjrR6iL0dLPDCiG}dG}TzhhueA^1X;MK@(gPkOm?IWkmcPY#e8md?@Sw zinBM4xuZ*|fr|=Tw;JS8(dD605JyoWN|Ko+Ey~ivlM%kmsK|Qj!BqYiC%oN@rWW+x zJ8sjrs9>#V-`BI(Qv3O7RUBjMnuZ#u2*xGq;%G=jQ!-l8qAfi-GNLOpLRlnF>qDK1 zB7^))5Hzx@9O+RNo9MLDh#?xPGtZtzgAt^eIeL zyqlzxCQ7NUC~XQo5>+$fTm|w9k_cC^ZQed%_ZJWmWzTG_nsO!Clf@kBG^=e4sQymW zV1f2r*I$?2_C={8bVtm})J)2WtC1Tq1vgjne@N^P&>PdY!@JD;^DHz|1098*;^F=IB( zx~{sS$exUj8IxemOM}pUIji*2+$pjbtB8NIdXpfnP5U)xFm(!vBpj|XD-i}XD~hav zI8Az25g~zX8zZF#iVto1$ud4_x`*egKvQ8k&4QS9Yx$OWCQO(*1*i}@E<8Vm*_9I=tXS6wme|5C0YA4eB{F=QhL z6L#&=ZK?65Or5m8#&CcmDsx)qs};MOkBFJgLIc1*J$z?t&RfTFpTt8>tDt#H1)6gZ zSeAQRutso+u}f&DcN+uTSUpwpm^YTjHRFZ~e2HR#s(V|rdLfTJ!S2M=YFeVGB*PQt z8)fDX(a8$~P^R#f55phE8@(qh&Q_;K?5TZ$k+$u?T1WH958$0pxG0L%$_)`fpG-LI104iG5oWpD-+d4 zVcwrP0Y^gXKD)-?|J(os+B2LRfH@NYjxGfFA8@HF09^eO02lct;9NHV?r{ec=f{Hf zZUg~w$?lm+P_|}DgLrs#FHbXt*pt`-6xH(pu>Tp}y9fpdZrd;#(&Y}3bjvS#u%WbB zC^ycga;2)3rO|>}ZIeCsAqw@dsI3((1;N1w{&B?zuO>rm1XSH;HC3YZ-2|HF69Zu+ zF??8p+WhK3eEA2)J4JxE?2+wTb`)*37tZ^+=J3YjQr)2pr_z;WwjkRSN@X)K6*z-X zH?B{R>-Z1AO5%q^E1kq;5lOody|kdwq63eH5-kB$?OOK%-M^P?v;>T5o_+O~kU z6V5SY??k5A0iBYIw0O9B?bP80o&g`>khJC-_ZolP@DiZ4CpfoXcY7HB96+r)J83O}!eL=`5f-!#Owp9g0_=OOH3sg5fCE;>FTmGwz|1JPqPTROYmrHLC7IWZN`Af69#yx_I zMdVv)<_<0oRN_GmDtKWlMV}mAWv>H4$qXq3R$9sjDR6FaJBMGu9|-PYQSF5380BvfsX211>c5q{)oMqBUkZr> zLms=gAZa5o<1AFkH@4J|7~(KGLHPeJ@R6`%F~#pfgZr4ogTl&4MbD$6N>pn9pvM19 zA6?Z4{1kk6tr&X*haP0fH5BU6anYhzp_OZvlZlnxD$X)VVyfdb>Z;*|Zb~>Lhq4)4 zm4aTyNO+Gz>A?^W9C4Uare>i8jN3%M2ah}y9NSDxRl2E}T3Cn}w^QMlQ;Jo&F7OQpFxN;=5a8#ITJ-L0m&b?+B;(c6o~60yG$-p0Ocf4zO%s`h}DH|3AUEQIpK zy9ONgWRN4yV6Az6?8Al!*a_Rx8`(HeE z2CbD6rkj4+1I)Vc__o_9h@=B3Ox#2n0#j4s(J4b`$RejUz_FbOD&`+EsRDd^4m*$UF2go{+*+Vr;wHwBTdO`3eOjKl${?hH(BcjG83w3m`6UjuM0$x4?> z$%5>5;r~vV9VZW*&}p+7xD82%*@0v)Jjql#hd&D!st~!(jazt5ajz_R(v(}WqAln{ zubAe|7(j<5l)M}3L{=|FZH%lfv6{E9S%||{PYi(qWmkze%Z`0Vih$K>mf;*)W{0*B zcRB!^&rYpT>&$9O$Wl<|<%eV4c^N8!-x%+A9|&iZ_toA~^sTP=2ljNI4i3qKLV940 zz)bF+L2a9{FR3^rfpR&0!X0db?suYe13~nj2>1hs;kEzYx1cMY(tBDOW}%|@uZTDEI>gpcy)`a^ruZ0C*+YI}n`l++aw)IzM4zYYYjOj#WW^-Vu zKu?*+MtA?E0$kyCcl4a=t9SKXj7#jP+HI9If@99$*4)w(q&~js1a%V`bo6%Yr1M(O zRdGl8B>)4chvdp}N-9{`A66K}FopYB+r0qy;)M{JhymM?ma!X^+<-dUIXMOg?|!3W zd*w(3W0`#}%xD^}csdCisaLUXr)66H+Z(Vycuj!j40WH37}nB?7fEP9j3x!|YI-6_ zl{&TXtb`Kg!OPjh4WEZBUB)okJ4ifUf%zC=<&DZclFKozFzEXUa6#QFgqZ&aGA}!p z>Y1-n>YI0ka*aG=vS~;X_y7CnKe-NBxS#jpj+6V%PCox-(eG$$G$;)w1vXQ1b1!u1G4r(mQb!#=wd$=N%yx&)i ztX~qdHHty$)=WFPQjHs#qHgOAhu3%nBOqkk1XTNWN_-8v0*H9sx_8L+n)LG8W7AQN zVXvgJGL>2==3xc9a%`rNd@4$(KPke_J!jZ{I(R2*v;iYWZb8U^z!AkYPiUK@tSEP; zwfC-TiZQ!$pEvnFpXb`!a%wr`QZqqGw#FJ;#GqdO!en=yIDuUD7&Z0KR7YrsxLg_W zP5M>Lk{LHa8zT zOM4}J-K4vKCrXc(+8OF4g>}z!Qdwhw<6>ndmKK{f^=$Q#LltqhiDCvQ~ zMjj-78q!Pmk)+1Y6-XwNXzZx_8 zjv%-#9l3-to(a`DZ8kvhH^E7*TQl0mf(fzpO?a#&s$wx=8IY87&7V|+YY*i)$KoPsCDws?+0#h$AKV!*l75`skY&bX# z8Uvd|eTSj{Ma2rOP&b0h3pu=JVUrD@X2DA3+Ir(mYG+ig7bffLzd$2fcsQX+h!R__ ztsv~$0mF7B-*Onz)yGdF?9^`9rxH?qv~3L(*-LYq+`bgqK=NLeCQ4yEunymMgg|A) zDL+qa$VWir(MarJYs+A0DS0ww!-JoJTn0QB20fL3kC| zl`|4ffcR2~Mux7B4LwKSWhG$s9u zYL=JjPPD=H(D2|pji1g{w$nf_o3^FEu^(7p#IR_FHq~N;hw|if4)=kjPU(3t(ZF13 z(plsTWaKN)<^m7ZJkpxfBqA{N{^`|0=1!5F-E5~?sx@z76XcmM$e)T)*F&ENHrxlh zYo}zS{mzV7HR!6beerj<5LD*R@Wz_yYw$_>Z9*xvlAH4Dt=}LuOJE4MI6z;Wi%e={ zr`O1IF!dc~Zc6KX0IB;5gqIn!U9>VrZFb*CgLTyA_Q1sEdTveFkk-%%(cpRQ*Lz>wV`uHUeDrukTYBE zaCc68kjyCHLXulgy?39bM*B5G+MS8Y-wp0=uu-|-{GU;}5|RHr^WzVK(gLA1hy@E_ zifnr*^7^^h>qTF91TqZ!FE+Y!CU3Iqvxi^}1U_Qc3x<#=pdQ1z5CFou?58lt6s-9O z)@qmyp(6do@`D%cl$oe6P0Bq0KC|-f$^sh5i}R*8QIjYXsMDol?-c(_EY|bCjzKR7 z3S0{dbWICxATgl2&JuI+JyIQl7^v6PYVXaB{Gii&4?Qjkv6xayuj_OHy6>oP-J*+( zm^tKG?tYHFuq7Lr3P@a|F5&4UM4_QqdPyyMx!(F^f^cFqm23VB>QuLL|J!cn4Z0L1 zT`qRroFpzhGvGh%duVk(p?kCe-K4q=1AZgvY|}W6kXe z*TTfa439?Yl_Qfh_QP_*>RRRtw;rknRNcqA<`NP&S_z6&Q0Wm^ zg|!on-F!}>sJ+`~6G`3QmO``coZZqNUCqr0tHd4a64~FsHy@R}+HBYy?QxuVG1v%> zQfA49he3>}du;c*zShx(#u^Z9czuMbqft7qe=Xe7Lsc%QwWMO6FTwviw;>UKS&Kzo z%S4rBZplnn4=h=AY%RU-F0J@wn`dU^Ei+fknEXsN^&}qeI&oxcpY!lOZ};Lw&Z((Q z8+!Zt`d5;2@cD_{Jt2iYz~aqgJPxjb{!C}yz5rM*WPP_;$ZrW}-LU|6bN0h9)HcgW z%-TI(N61&EK(=^xAze7_Xa=MR`)j z`?;Xt-`Ydv>_5xroR;>K(rp@A+>>=%g(($M5KUfJ3C&GC3sL%;lLhh}FCW|5?>@CB z)Uq|`A{$^qtgt_6`RU%Su`az9nekRGJ(7rW6H%mKCE4zydGuAK%!Ll9$wq|aloBBI zP*XiD9zEo$O{V)TSobQJFO_f-4FxFJ3zPq@)}BWrR7+WhF3L1}qbf&%PD96Sdrg zDF!FOYdHyXEDL=u!FdJn)z{WQ6_7=id1h|qLiZEM%%m)CF>KllZf@wYo!A@-*PqSC z*&}LaRKr~n>~9;3H4pAt*Z1Bv6$blt+`}Y;@C48KF~aqP-`CqijrsEq&8j3FRI89b zUZR0_PUvmncbjlObreJm5K)my6 z+FrBySzEmM?QT{-_iJe)>#IxVm_35FYO-%|23{d_=!@JR4n%oRNC~*%FmGu0aLfxDd1r5D)M)0a@=^aP8ghS9;3lvuini* zc>Yz*1HR?4qFTDxtL5_UZ06Od>@pEQ)W}vgm_=An%TvkJN-P9@;{(q>FH?c%c<)&uUl2hxGpL($c+O< z-RY56V3wjS8T?Ed?08~e^USZ#(1&`^79OLq=ggBZHojnTVleviiVGV|G_@q$|0LFa zATE%|FNJ9d=f>jii=7t}v1!^bG=0+ZN)IFoy^kWh&LY1?4iRJDx%-c&-k|V%66`*d zwgIJi+P^hX`g3WiHUZTiEL{QE7eEaMOGW@Y?z8zLIVrj1S}3U1lj*vkNzCQTMvI!U zNZtc3!H()jsl9C_>;)&ZI(|W+$(FgO7y}~@+#bWf!~9vUbHvQm8Az4dz(KysIGu(k zVVc=lR!?KTJ@avi`md7JXp9|dvGD#bG`L+(d5%Q=nM(Q+p`s7%$Uz)KJ7W*$AVt+9~3ac^-)g4HqVi{@ns*KKS600;4mELQRDz!4syNO6%&(t=Yl5m0i z^*Mf*=^DUz$r$`8_{_M@$nS4dD(*6=D=tEHhsPE<6fYL5kN6BKqg)2odqA~SIx;-p zvbiOX?6r!6bSl{>^^cKKwzipH)vPfK2U`^yZnyuOT)03bQgfw$DnjL%(k-P<5OZ*C zL!LY&6&TFKkIt;WB&*X$J_%ZPdUz=cuQ#611IU46j65|%ZK(j(!-_g;QM+_wC+{{XshK*D|i>b32C)Mf{<)Q^Du}UDl zGj|AToGjTIDc%}{8iQ~k6c05)FCjx`y@FeTo-2D3);-wPG2xeBv`bw1tjUx$hHg8N zDG70y5e3NajmcCzJFOZD23CLpn^tX*DZ!v!tv1My9hr9oIdW2RDUn<}uq0Y1*6JWK z1i~F2tw}qPRS7L3W4utEx066$M#?B=M#99;MULI0V0D*zV6pCG&kv=AQ-Liw4{1g{ z7W+}{E(3y@)Z`kUCkFi*>lb2|RN{Y(pfbPv^M{vzMuz5O<~aA4oq6zuUN$i}C(CeP zB+M4p~ls`}kQLnJ3lM=ZKFZwj*Kq~uZ~ zxy0m*Iu~E6g{X6~Od%mTlW~H|TOh;_Ec|!%5E;`{&()Ma-R7im{LP&NKUWV`O*zPH zThkM4|AB%iNUjO_8-UALzo;ymfhik(2x^{4IM6E7X&bBfP1+OnPo`IybqyYa(j-;C z4+tuaGAay4%I4_*U!fJ?6o)nCP}{c|5}ut#`Bk6cDf%R7i3aYUnbK1q8J!}hT|udg1R%>Ka8nq0 zk=Kzs@M?X`b7h;pp<259oDzh|R^st|bD(y)j?v(!P}Z?eCTiI-Rjlp@unGrTWLi~- zIejn0l6Ys=KPk4fM!T&uC`=M5>L2pY-{v_$gtrg|!y+RK)1$Oo%OiHt-YV{aiyYb<9ryZaKD^_6j}mt9->4CAcg85!2nBI7M&uqo(g!C*VpuOA&* z1avL*=TDJzjcc)-M)R$4%5yWNcWHmCEhw*|zOm_tR}lGc+&d8ulU0o_AG5whh|!vP zW-_+4;L3vIUJHRZ)0O@wO64MHa`86&-ALoxXOaR-5uK@q?tGWmX39*?nhPkg#m`5M z@1rTGajN>utw5j?s_O)Co{-r9)fs>Q;uHft3G&OlB`+&)5$#ac1E$W23U?xp(bMoJ zHp|PvsVcKX`3?2v6v&+RTs>4bWg{`Ic9$a?mPd@_l`V+X3RF6X6p>|J+E64=fK6qu zV%%#H8zac@!>%3b8xJ0?$-+jwDG}VEy1Ns)y8VSTDJHsia150{xUzC-N*tgX8xZ=20xXPP21pzHwFB<+7`T2n{UI< z@4U9e&qYeMemp9jyeG+^@!GukW^Zy+uT=3)M;efJ&?ea@CfDIBOhi9&NePGX^ruo; zW-0KyoS%xUsL9Q&hd&xRV+JLL>S|DNnao>lASgSim|Qeg{=o^L4Ptw9aScFK)hC0PHM&{2U5Fe?-Tt^wpqm0Fw}?vjGdXcfs@GtFV0Me&-K?hdIooH znUI|8t8v=wwqu7{$Gq>*0gkH>FeSNx z?xI$_%8k~6MTT3$6m_Vr&M6YM>U89f++wppA_%p!jG7_JEt27nT5YZdl!@Bcy8s)g zwJJpwpK=>QV3FayQK~A?5j05@f!FxlZvbm7bwhOV1`!18`pSvDEx3VXG48iyeSR2} zgqSS9&>(5+5`wBh%0sfj55_chyGE!}i);BBdC7|>0Gnd^%^EhlMxqkNn?#C{sht}~ zwdbcIUTLog@1yVd@#W6Q>eR`!T>)+tuEStgigY@W#A26=j0TCUHgSgrwso~OH^)&V z>6lRB?X9#7EU)*;j5YGCg)9?CDD<>d7&-<64v{jj?A3IGNWfC_6&k%%$WpMCB$7iS z5Nf$rt6ePNf_$Us@cYm4U-Y@-qpMS#54pQbx=(&j)O);V)fd!g5 zJ#H>m*z{_)JIQS#af`+%>+4n+wC#x0p8lTqKApu?@6g-aDvc{_Gg#d!YO8TO)VKp` z+?GdLX2dD34d^ldPhYuog8&7X4ny?Ez%4^EyoTwnWg|6rdP{`fs7YOZZki8rg(7bY zT`TD+zJt*g1W^pRUMyg$S!x5+Bm^xA5%oCR79#lnN_3WR{Beg~AgPH+3QSN_ApLah zlGA)B7~bYAp5c9l$foa`Z(bizN}?S+J-@T$HdY&CJJfbi!B;4%{9=u$c+GCWEXlm~ zwo5Kfz3$B*n^hxG3R+?!S^wm&=f`yanXLEnV#UWWS}WV`imXo=hmQyNJWRLVsgh{* z0-@Qdkbt02>7Dz42G*J5VKCHvcVXlImhYVI)E%7)R`X&d$1oZ@+vB*$~ApHUQG zu|g81Al@jF^E%Cr`79tPtO6Y$ocbzd<3dx7zr#Il)|+d59i9mjUO@=>TVw=cz}G4x z|E}?ZXnuoejPPe_-CvjMr3uuOi+%FBQLIL=h!AArpsJd`~F- zuL&b?Db*A!>Ya<93$QPu*%}d4$-u8e=fMh#zD50?_o@nf4<%AN4UvnXMjO<4!E_g; zK_D)*FMg4hmZ6sOX=J4iTTZf|-nrN>Aiat$w3JqiR=}SwfvDe14nxR28EGn|K!Ms{AOGj@^S^bFg6Q6 zI>^%M9#}kOajnYkza)h_r;^XW2g0$0Dd(A^sHfL^{{XLZ^{b)!p2yNyQXjmPGqVQJ z_dcMQWcYXel4gCPNP}anIcXRSAXD|hdi#+#-F6z?Qc0s(ZIw*AjaF%4(CHRiMJ3ue zSIzWg|J}#(6Bi%q1uSAL*uC__BfKzyuI$ZG{}A(FQxw?WNq#co{3PU^>mw-JmFcF` zn8c79aRm7%0paZ~h;pLhr2df8amoTw1~aHTwY2<@UdZVvW`0t=KY!p#Xlp5G(-h zdfyl0L##enb06|=HS>?}jtMfa16YI>Y7ADbW@KI`z9jn^qW{fG5HqejA7sQ!ehng= zTgp~Zp!%<^5H6m~YK_MtRLU=JUdkUgj|$!$l+qIr_F0+w(~$a}Pm@#!|5hgq!o6|& z2GrQed%5j5il=>)bD`pw9?R9FW8yzo>=m3=6#xtOEPB)h6_M&BMf?5$k{aGa6WXK4 zNGY$x_~CDUUjdd9z=D3>?A*nO?^2@fBB0Bd%@S|dvo3bNsr4O?0HGiTOXd^x$<3F|Uud-|%|TGxislUtpzxEr<+t5LFb zI?G2g+elFYJAdVm{~@Yv;PY18&`o1dR|!V{7A8Pet2h1aYc178+Egc3L_-Aa1%rZ zVHMxkz?Cm*?EIGZYDka%>0&jGDNGX1Ngq)|A%+3lAXr|>cX2DC3LAGctdcQ6DlujC z3lP~0fHML(HJK&4Ccmo6z>$KD9;MXE{N@%Zdj%q!ws$$~aLZw+;shCa9IDu#vHv-o zlW+rVh;-2_o5q%=_eCL!0GjQEDr!)Dt0o%cEtDp*!DRHAU2g*xT1E4v4|hUjlVh*u zx!UadD!@`vKK#+>sa}X|`Mo?>tKGm3{sP!@WGa0qC!-cAIDr(@aS{ii4prtC#{riQ z3R3OSE_2TVlzyKd)v4oYx{oevmK_;xa3$ZJ7EV*C?zr4B&a<^p6L66$=3L4i{&M1i%$t$yM>0`#23!Jbb6~qt z+iEY=K7qoUJ?|*{8UM3KsMUd5owim(+C6fVJR|;n89%D-R@6eZ0+zPZUfrQ!v@R=j zR+~(j$=N^3a*actY7P9ih-Knvq^%{KEO?9cb~ge6N3$L#H`OiPa9|BsK&k90Mg1g8 z2Q#&DhPu`1VfagLW7KMnmZB*|Za-$A>{I_&s>~xO|1Fm+GA3sgm<>>c|5m%itj_)| z!fO@?e%)bM|3PDe$Xoktf!1nM-%&_&2@36XGSqeysyv$dd}Q)fLzTjY_tt{4-f!=# z^~wZw&1}s&#ZsMFqY`R)#tu>K@CB}c-Cd7&90v9Ac0ib<*amHIG=-F%OD-9(6vPVk)*jr<7FEtXBn3YoDr5Z#gR zw0lt9KeuEnU_#xzK^p(ML9@&p894%QP=|nrTS{ZV7l)z7-w(^e6%*YPm{}-W4c0-@ zfr9pVqqDFL#JnxneCk@-Uj4*QraUwEdO4&WAuX%Ccq)7^l*RdX)hm2|+&#j>-RazW zwPpZG7>>6yBg?Vk9U%>v2ORNDWtShy${d`iT7Z^Z~5+h@)E8MOy0<~VG zF?tmkdHTKVn;)h_vmA0vgjnV)MnuUa-r~Z?A)ZT?+TQjDXM@CGoOsS;cWB6_@VqJF zKt-bvG*3(!EP6H87|B@vSI|b%z!!wYbgZN37QcZf3QH&@rfV4iBtLa=f@Y)BeyAj) zpsuLhQ3bUweIyicjXCUZE-yc_Nt6jleNSl7e93I5Ek8#Ey#4*b)BJl*#|2a4#X6{N zyJt<-b=jNRS7%_&KRez&b7}h1W%1$hcDH0%hep>zGcM}u9&I5*4g2wi|7e)RkX)^? z3U%&ytxn?-!?ICQ@{JGVoil87)dkvvqYj(9F4z$qc2X5Izq_iBOe^B7M+ybr+2+i+}(PClUHHM2Vt27UD3Y9Ij?1Bn^>>Bnw)$f1x{T) zwPo?Pq{3afCU@!L?*OTRt(O{OiIJ(c_ug7FIB_--I8+^s_pY*$EW3)obw z-jG^MQ;_y7OqCkTAtG4mmEwForUta=pW9@MM|OFyLP(b)*i}Sl%zgl>s^3U z@XCA)Hi23$LRY6Y|INuK!V{c^J#)$P}mEzHFtgVCsd^v3sYD5IDV4Z3AL&I~FuV z9RDX4??0*7r!V2ODIcl3yJ~BPY$B}oMRR^R_pOSO!l?*XNf4RX6r4WgOD$(lT_B0| zQX<5tttvm!I;t)BXk3XFx0TTz!NC&j2g5h`)u%kTCWSOXW&olf_<892<*UaISwx;k@50( zK*5WLOhSr6{e3+CJ`M|du{_pkXI0z)R81$!7(#O;{xl2qfA2H>UQBiL#`{PX}Tqtdx;Q>0nC1tG}8T78WmWufUtqrZc^A#W8 z1z1X;mUBkPnP6~NC{%OsbfjqGqkgeiMMgO4gXytp0Gd?b)1Hsr|yf&ae`a-$%>G{{KQOxvt^tkpt>txFZ3g zIhX7t^v_0}v&BAwqHVSlwU1E2opl$@e*O`{feV=F7mV-=gz6QuirB1^KUGTk?dJ%m z7Wb0ny9sN~RH`YZoTnAyY3cr&C!)dFyH<@Fn)^1mUbTf7bkYBZGI_BWu?k zeX-I6y8&N^fpqO@i*zq_*=LJ(C+VcBiy%_7Sq8y<<7`Y0H64fv=LqEGxbWrw8ywWRi>UV3f7Hfl8~CuffqFYsK-c=TDwrQ;DC{9YIjL*#U* z9A9zML^t6pzdvBf{4nWLMJd-4=uR|tBiB9~JYVaZ$um5Yub*kjntsOio3W?O_!3*u zsb|hZGt%7Vj;dPJg16FtL6R|3G4WqJgPZ=7==-NFyrHH+43$Gt<0i1qOM)4Fm zC(zu~e=>xTvANQ2W_8jx5LgpkwWhLRa=oN=y=^&cvzNKxdSrNwSH8w~<5`g;T^|=t zXg5BrL8I_bobltlu9{8qgM$x8B&g4Qy`laEQ-AFg4KUg$?49dx96WaYzK{%`V zeaTG0#&H3caaBt@a6PBEfm`lkHI5W23mdZ~FS;-#c?l_xo@S^BAMx;5`f6Qr%4kKc zH|j6e61z*g57ge;!=JT(tRSc34D_(GTHlw<#Bl?+*qvwPNKmLOY-z4tyPnZEWSX=e zvgF#0UTPRUEx)7};d@5r{GJ@mM2?*D8ECBODCOkRE3wdvLSP#7e~~v zraT^fVPBWBTkXPMo{bCRQv7zmA0E5cZ(@vE=N*@+xtp$+qvXEpzB-pI=<`cdgx^S6 z!1ns1?wXET^3j<~#f|}XR_o{ZkzyP-;ugE}tm!E2Re#B8?RE}>e}&G@Q>|zn`0PYV zTzA;InChYvTg)f0Oj-I^*LJuj>jHtTfsDZO7ACl>eumr;n} zTXj5rM5e5V7a|pz;IB_xc8V8@bxPz6GtgK$Qm9t+0ZE~<#PouWZJCj>HW)`js%6u!fZ(obJ|Kzti|@9TN{2A)I*+JoAk?Cg|ow=H+$LB zA03F}A)dTw)F1z+O!cplxWp_DLW=gDNPg^ava!_lCRh)7s%p+zuh6K5lFP%3&8Pf^ zTAOdo+!d6kEMFF#Ms5B@KR6%%t0XSS=Q#+#GG!o=A3L0Bt6jU!?DfnM^+Q(O>~fZu zj7H^+XianTw`cR8nI68|7A!MFrc*gmka7(|&rBJqERrrEv2(In4ZiARD*uNMXB6aL z-+~6dY322t^rDIF?~At>{5=Z>?Q^j_eKWPMywc6teLfp^>|I&k@j+~&{LX6H&CZr- z+N!UezdYH|sm*_DEj#0XmEeMWo+AZm?Mw4w<{a2im{vsUtZOfsL1K@!E^ctfb^_}J z5024~j@&@373kQl!@-)LELLafXx(Oa#NjhI?c*29FQ-)*XBPN^D(D#2s^jUdtkJU8 za!L{XG)7Ef&mHxCZGS_1BQf+9z3dZ8e3b$-3&u3=(^+b#a3;ZBq6|mrC4} zp>{}Hhq1cu^N9P7N-)yRoNc2LhGhl$NxmBV7rlH;T4=zHL%R!F-1%w4noC2%!fN)S&^*=UuC6H5yS*cWx4g=W13N z=|FqIG-35-`L|BUDHd#z{eHT&|1N*)Pj~wtd>Y(| zJ$pOS?`>f-HmNp`FA6DGKPPDy$L7bKcMSW5OJ`{UHe?T1AaZ>~NG<(ZZ85vyBB`wB zt}pae+(v=b&dse?&6m+G$=^R!5B$him;8>V74SIPWzl$h26qsPI9xQ zi~q1bGZUy{-44GpOMIPX>ptgGZz==$=vj@txT`?ku?wB~cbwtiS^5q9Z4xlrU}D;k z1Ng=2Ij>-_b3WAI<-Cv2soZ_lZf^EeX5EPjRuJR1GUTNReJ66!=GmUsemA5nwzDR` z$xE{7yR4EuQ8iAuTeo6lE_O$|CSkvb9-OE)D7hD39MG6QlNQc$tQVJ%fu#B~@}mEv z_aOBJXmk|48dA*l!^=|fWM)v3F&|&z%>2Tu!VBd=)e~Ka6iJ%|n+vI?Z$qmXagy%? zF~%^7O(LLkIzqH`dzUDyYLYzf6R%v9kX$HT#2SdsrY_DJ0}s?iy`mZoS~bEcGS`QT zFLdbaLCX@mU_C^mtTEghtmNJTVvU6Cc1o%(!bM)s+$4D3U5UUL%WkOMAFoOFG}zMj zebxNuJ()W>stxpVjF6i1UyOFqa9^kL8L4`~6!~}ydpQQ&VnI7eev9OEXS50WE0{OY zo$;9+MLU0Qg&+IvI|8brBbO-R51jt4CyuYH^BweP)tmouRNMT)WRk{Ugj+0VC&_OS zrg;KcaoXRhuC&kT4tg6EcfS>w4=34hdEb+m?eGP=VOWk5hMC8IOzkS(ulYT^_^#dG z!n=kTZj3*ZMV{+bySU=9b9$tyz5!*ke9Eo3_%xp0jf-#7o$bHr2A$kJ;O)D*56moN z6H-}wBAFF-@)5Hc^_b_OcMolAY*6lcvnN}=HZiTum|`C@krh2nS2j>oYtO3w+&w$U zILW_rXCC`Rwf-l45PZj7kw$8e4Kf%tTZV{DjYvY@GIH8C?mcKdhDJxxt6?Ij(A|mZ zcseuajx`cip{or(a8+5~NLM~(93`JQOuc zZ|^|_fcNkS(%ZCPAr*H#&V%qG5GoP9n>HeoOS2Y_H!;u7-o?^<>v{)mIosbQIh$(} z%wmLTC%VxYLkI2aqr#%PTC1pe{Z&`Omden6*_@u%>6SWRM)yglo>?c8r3>)&svW5P z*csaq?oF|Toq4%wVm$=A=F!?n9ieT_Q%GsF`)Ebgp`rU$oL_Yp*)`RCuicyHUM#Cb z#@E)QwUfKBr<67uAE5vH^7&fRRZ0dU25!5J!tEE{e6F>nxky-xN>CA{Kyiryuo{+Mh1eJWiY$hhsTu=lCz=4NiWP}84 z=(D12O&a?`sH^+C)&Gw=gOG0Ukw_}^4AKV7&S^jKPrbdzz%cf7dbXD0mI!TdU#_3e z+Ak?$IMM|zk_fF>mG#KSMLQW%j~Myp$W#gItGnwQE!$INhH|6;Qt&{;xtNgiN<$LC zcgQk!*&(vi+r_L&6M_hN$Ykg$;*5P-^m$>*UCEfrxkwt#R$DKkN4zOlH^O}jIc zLl>PFcOCFj7d+%!iy1eNGZ_+r4WQzouIKyXb&#d;{Mucv3`QN&*ENB?3<6h4#m~9B zN0JQzW*52v8`@E-KIR-hUq2h!QJ#>xoZ*NCa*qxzTrozJk^`CNf`AN=YeDXMk(ZRF zdd15p0$@jB+^uhj-}kR3Ygh9Y_BU6!${Cs7ClK62ggpx-y^JYMQwM4l?e&M*T2N*T zL|obq3=sUpe7>!KFY-9_ocXS;Fxa&Ayl8d z`{OaLG9%M^fC${md9k)_HZ;wQ)}Us-8w?m32kt2mSc-`Wyxsk`l9?YI@v3=(tMy4V zIj%uYcHoF$F58l5YBu8?lS#Ls>t=%7W0Mdu7gTE*DCN@2ss3=^)5mtR?ivMUk^EJi zVlMSw-|Rdu_ln=W>F#jZn|{}kuqo-1Djid+1ygB`9PB4|&vbN-qQ)?0`5c|4B8mD4 zNX~Vu(AW2J&}y+0jJ>LnYg<*I0qLAB;x5Pwx)?zUl}}Y*Ach_SOhESfqD3pSUuUye zv@Udkhn%kWf}OSzncy=bWwRTBzYn{!m?>WdrWL|SCNMm#m)~o(Ty!Zgi7=B?MB7}< zV90~gIaY^2^tHX`DRc!ygm%aUs#m4cgGG5fRtT{VwES+)0H`ROBSAauU76Jgp|rlz zl-(D=Ag0;$ad~tERLmT-O(MGAr0{m-rxZ=mv@3F=1pL@Guv~1qlJxK}doTR%aSc^j zDcfdv3MW{uM?k)Exz5VfzrD=tCOks~LfmzWvaoJ$m&PGN>Y`?>pwIM4;>1k?7_!L? zxPpR+ok?_S;WPrRQX&O^^aidsSgmbP3U_^d%t*vu_PJalmYtJ^K3d@LEvG+s!1Xxz zle_f)M{O@>?SeQ?y-y*9=E9;3P1~CyQvE!a0RtS`2H3JJqG|znU6RzSXDhq6I;$#= zt9s~V<=mbwY&k-O#692N*BTj!=1c{90!O_i>V0-4ato`(bV(rs{+z#b?CNe(M(U4`y-=w76uRV zhmZgyum$~qc?0CL=G;3dLpRMMXkt|vUTDX(lI}uv9k8J66yVO^tPD5^hW1U(5#O~J}<{BP13Fh-mf05{duR+wxUhaN6yZ20o)CbvVI%)U zZWuEP#zF4$02J&oL?W%1Wb7s*U00zzEALD?3>>!t-_vzqF39xL_rpW5iR4#yJAhw# zweEYRE-yMs0Zqb!X{{$zU`*XRa35gcPm>D&!cE4E?0l4oMg1)c*}fv1nBxPjU>v}p zw|E$SazzNR*AQufP+x>9Oh=S__JadDbhtMF*2id$GJ|}lHRLBfE4^~e z`8sBzoRi{&DOlkU;=Yn`d^rX&zBxZZF$h3#=;Re9>vQtAIbwUwD_)`wKS)8x4tc9+ zXUNaSnD$9zEgw?!ig9yVsVag5ra(m;4CJhpj`tuy{S_WHe~Mg(1O{C7x$V7JpUY`Y zQr66RZj-;D#Gm5&lQ&%D*GIfGV(8m>lmZ1nWEiJ^xV;6GQiqgUS2Ce(eK7AWzNLOT zLDvwEkdP@HTHnN3$DfaRethrv+wHgfB0m>WgkViI4H&rkIqlyR&U|x&BaSK(6N=vZ zDLxzX)+RTZd^(qU>8J?a5_F7tR74J$SLRA)l}HU5X+2kQ?vPf~G|A`?{+*e1`TlIP zLA?L@Y`XlkIo+J>cj!6KPOv99oqL=jtD{>xrKK$z&WCIoa++6R32Aj146K$SaG!Qy zy7CaKotMWUDsavVO*ghnKpdwO7f9wewaXUTx2&7sXXXo#iciki`GW->Wl8X)qxm6a zDdCv~p|0T5D#bfCF7gY!{$nq*{-~y!cN&`B#{SkCS2-s$?XzWAP4K>!qAZe#60#s+ zI}D)TtqeY;ZM2EkgX0VYg3O$Z6}5>JU# zo;By4bzWnrkVZLJ;6b^pM77p-{}xTtMls*Xib+#Dv@WoT9xc48+D*4%ju2N zXu82{Av)AR&l?p76KKtnOhRqxK0haH2yG{-EJ+VDeT>amoDI|N3&9;NchL#5PZY$| zh;7N^oRw^=U?0<+0fbl^%Xx*M`T^IBDyr~GUp4^KWt|89;CcO(H&Am6TPkPO?SUc) z8FiRfEyWT$wp4+lFqeWI|LLJ|efpB;DHIc$7^o!BdC38UQa;pLP{^9wSV*FaWxXDy z;3cCrT{_;=If*NetQ*NF9bw_l+gSbfIjRIAz$EGxHcoVtSp>oiKaMT8-(`}t1z2XB zC8`1o!l@=35U3Ev-z^7Va zVkJP>m!4)!+Ndk&b%TM1Swg6^ZIeRRkj%##&l_@oiY}<3YuwZrf zp_s!ByE%4B?%jr^zRUjr-aOe>vL9WQ3ZI^aB0J_gs%VB}ZPH(vTHVz_2rrE) z(PkeKE2c=8L=&;T$updiyc$$1_CJ_)aq9pOxA)!YZUZeel|lo@vw2vXUi_q;w3m4c zJmtIe^6doemfplY;Svqev53r`A!^)eqe@iFxPloxth6#o21^iqqHsFeD`04D`*)1=I@(TyAn z>p*I1sS#`0_6lrEfj#?O-lP;^kHGfvd6gS#a)jzjUxAE45@Ueh4~K+vnX3xMG2lI9 ztk|WB$VT8dL7z*>eAB8*oL&GOn<3nV;nMjodV+7KcbBx^``wc7zb-0NY< z4KpZ&Xa*A!3xK`ghI`Sy==+WE@Woo1j4;g7o(WyrMl;;YOd33(gs^{e-b1e0qDmch zNl>fRJ4b?I&JTEj^OMTGS!rAvN+O+%9aXESLg#Br)*XP6aj z1McWa#+o`T5Qc11j|4g_f*HMFd;#mWp3Bd6@Ki0VTSimM@R7`_zL&|TF}QvUw_e^^ zP)nvbQfm&~Mkb7QOw+Kg*I#4HbRv^7BXD=0P5ayodON0R0_5W_w-X>NPhQWalU#%S29CK}jWg_`DvVd5BIb9{5(Q`y^J7Mm!JaI8QGkNhF@<7W(zd@GDxz)nQHmmI>~*8jSTxo2{w+ zP(f^nIT3UN!0C9Nluz!&|BpJ<>E&-0lVO7*6u+AvebithX?%X1cvJ3dwgIw5ed`^R zqJ6{7d3la9q)*CY2zu|{dSi&{XI0@yx(shD+dhOvci~XFjGVS&aM6e_tS&EIP_($Z z+X`|WJ~)fkoXd>m;{|K-vt5qmZ$oPvd1oJzA-q*{z8F(9j!Z}yFhB4nhg%_By>W7J z9T2n7$#Z_zp+$Q{V%W@<+Q9JWQ0l);xXD~QfOgmzlDTq%>n|*{QRoPO;-dzOZwi8? zrQsV~stb>~D};Zn-h^&{l1K*bualrgQ*r;twarKx_gJY$)F1G4ietHzo34o=7Hx;b zjm#yqTcbWC(x7A1$~pCHyX2PLkxSlH*7x-q=pm0IkG_bBs!wO7Vx?Atp(wr z;X63Rz%6_%jY+%Dj0*b<4pJ14&nG4T7-e2J-fb^usu3}@Gd5w}2m`k~9UPG!TduL3 z&JgqHy`BgYx16h5XDxoTZbn#x;e1hnGZ|w7)>4&OEJWm4M~U?isidNYdXRtw9b&}V zt@P@AX%gP7BJxBV5iCjeSsX=78b^pRffbcoM;asqSftA|a2O(~!>q_u*bs^J3 zuDh)V1;HDjAY6J~hETATt*r?=fp9OW3E@hSV|j(^Ar}REqkwAaI*nFzT^9uSHD#q0 ze9x9VEzJ^^2lwu@Qgc`ZHh5SrY)n_g1}sRYXVRx;wX^Di%p$kk$?8QOJL@7&N0>3n ztUKfztVu(*-gW@_P2)M4fv#??T2k6gpmB%`FT2#~NhR87>@ep*cCGgoU6LSZ@ydKG zqWSJZTz*BM=u!cyf09`;WmkjI+|Zt0dvE{#Td%rq-5bZ}^(ak*s@UO~*jE%wmV%zI zvI~wW}q%cRjw}oO#e^%S|J+WG~bMenuLW z=Pvx{>@4>TPjPtFwl6xW`4gU1S4f*}!K=!-N~v4$QW!S1qquUegZochd%&*ko(1{q zOrilszt7F10v4Ubl1oLAs@=D5>gWL1%>StzvH4oZL2F`A{kNVF!Kb}#GrF!FXxnoj z6;W znUxKPILLDn?h#?628Vf8gMs0W-nANR5s?OmB}>+9D~iXNM8f0G2RZ3?xKB3Z>x+|$ zeYLlKnZv^lUlZbHwn9j*ES4EIy1TA$*PoPoEKJxZpdl!Vnu^Hd_VEya=m5eS_dGjr z+@^C}@WJcN_OtXM_2x^H(TFbHH!KC$#1J;!cmK3uzD!>`U8q&CfiP}kQj=9cpD$ts z)@F_<&r9LmBQvi*p=k<+0MRB&Okb?94Dx>`OBdy@tKy+Rd9EwPuWzVT0jwijwI4uC zgqz?AZDEGAGkoxCSboD!?`h3oP!s)5%%`3^b{us}-q>c$^UnDvk#eg}v2jrH<$^<4 zb7)%*4j_(ACqYsffIT>64~7i_dT1cd3O;lr4|XYLOM9au7HYqe5mK?M;cA`UE(~5t zwlReSs2|Dxuyg(F{ZBvnNZ))uUoUG#h|dW31vuQ<^`6y-OzWpi< z>ghIou>?ZO`G#J)#T#4kHCWQ-l(az(DP<%47O@wL2vPcZ6x@NR+x>0h#mvyda6A~j z3P3;;TZ2hFec~M&__jzGt}}SR7bgkCC65fA$L8p-T*HgDM-V2_DQN14E`UTgEH8 zN77Pl>3+I7(w!b-+l!Ty191iEe)bcB{mlK;Lm;E5SKt~)n&%i}l`O^)_Lg@198M0r zwtc;3nd6x8&R4x(FQG2#(>$BG_rrH;{m*)v8e!vqPp; zx=EkBZQ(o2@9*`;@4tKU3hdP^dHKz{dUlEXS;?e+&u@F81YQ;%7H+!)LWLSBXliM;85Q9*#+0$UA|*B6zS({cKYchHPmZgu zZE7WW8_msz|E(I72^}lXEj?YgaR+u#K9ntw@>|TZZsThS89Uof;9XV&ih3o+s8QNr zTPD+yeC%;Grk0RoD@R89W^SO`S17KZ+e!0R#}&Y?AE z1h5=|({Z!mc~}ibPx=A{Vj*mwjD*k+(;%{T!V!BC{8CS~3c z#=F&ddUzJ52KL=>{=0pCOw8~f*&cW-lSnk0#JBV$we0i_vF&!WaD8$DIq~(P_u>W}Kn* zSxp}!HEY$$tu$0BBIE0#LS00t$pN+L-=F5mBvBj_5hJ71U2B>XXpl0FuA8I|D(t;I zuIX-QJol+ZGRHADaZ2nIvpIf`i%==QmV2M=F(2v)+7rPrbVeNdOf>xh4Txcc(j-LM zT+~hJsC3|1?Gy;n4{h)P{ka>gBDemL8ev22@DMwC_Y-2fo(`!6PEvxV=bk`ePiDHi z3Nb6Y35-RQd^0;w+Ht^3U_xJ_)hO<~_Xd4w0QU`T<>uMk4B+M39xgoTa8LQFvi%zL z5(0`CF?T1Ktd=v(&yk1es>z0py0C>Z0U3)L%|XAz4|!%5*#`&^mAGp)#59g%DS1a` z8DdJ7o6QDMw5Tjl%UUdu7{RPcAc!zz-#gGUXcr*;pRw70R?@qVVdKjWWe2n!ur7l= zLz*cQZ(Zwcy_a5`;`*{34J!#+ptRMTT(u(pf3a>2Z9%*?QV+`HyJHGOW(%v9)J@#@ zR_~-f+uzU#@c8&FuVkPgjOy|N@+`ox&e zBXSh@q^lN1q3zJKF_fkD2l5Lrzz*2I2VP#~=l>W5p0@(+TcAwhbm|TJjNfq?_-lReo3xKpWx~|OCPa)NJ!`>fUx_ch@2JY7XCegm;~Va2gZN*3hn*A0RDN$ zzxRXI;(*P{f~23^E^@e0!!t9h95niLQ`G;wfq%Tv@%^8`e!0c23kRonp6w#O-pa$K z{n*d{0hxAIZ9VT>1ICg0S#(K6tcG-H*67^IcQzNQOu!nK6gIq7lA!ItB6x(4K~qP z1b(GzeBpE<_>Oj#h5d}(1Q6~1c;3Q$_jP>}^<~BG8+_L7cHyu-_W*c*TGU`u9tOK3 z$MW@*88g2@)S5ZLM@SY#myVCzEPVZG>w=pdy*4RkItdqRJHDWG53xYbi=;tbnpiY$ z=w9Mp_&}aUG%%}}XPPGQ;@D;%OtHT-+@I}x+7aATUTtt)hCKjJ2v$F?o#)HllwH_O zAs8&F&?k#v%!*R-RH@#QT_>6AN98PsEM-$RY0tx(y_mHN{TwU^hhQo&<-vKg1EH<@2@5()P0ZE^_Xic1 z9Ge+!N2A*(D}8e>octH;MJ3@{EKXC+y0?I%ghBb}y=HYs|7qsUa`cPW=tJ9moT=+k zE@;m5&YOi0STaLKhZ~!Y9=tha-EJQGI5O>5OPlMeQ)W0}ZQk`OXvt7jocrbE!LmH^ zCL_38Vp~aY^1EBqFf#xBA0dD_6TGAFi3Uas3z7p~y{7;P0=R@OB6MySIF_)nw?Yap zYtUk;wcwFx9gyIXb;K+RtYbK|iPO04ompeVI}3cV&gKO6_n!-8w?lvy3xF4@-B}1> zd<(;Al||q>E$c}vQ?+O)_oGF}bf6X!rQv!kVD{LG29E=_S`rH8!}XGwuly`&6b{8Z zWKcb@ncXF`CiZS=UF|0ISgot0NdUDGZux{iy7>R|M!y?QvxJhXIzEl-#hcYJ6q;Ad z%Gq^UnSOk`6}87Fc@2JnqU&$=3f(COk-cWN(9L4{OReCQA7V4OuXQvlfMf!^h|13F zsLKZ)v3ptBX7>uCfn8kRHDl_q-tNZK8{So^>)40&?wgTL*GJ9)q`}9G(096@q$+wl zcNet`mxsJp>2I9CzkOt4H8)zSj(mLo;VVg!fF|kl`m)rzW*Z6Ocu<*M#*Lo1!ZcnB zT5_VHBs*T!{%;oWvdy1n2|>PXxUS+9S&!Rbi9@l&m$_U}G%ZiX>BqP4IhOun_OH6zj8n&xe${3{t#!KbMMZ7#2Y8`ww4>xq z;(XA!&JFKjQ;t?hRRPL`5q>Kf|E!=)vQ1;4RU%u307t&{wI-{_zQ1wW?OisM%Wt=1 z-Q!C0KVgVAX95^t2($s}2o?9}Lm(2-5FIfP6MC=^h1iILB#z2_=DU>xJWw>NkP8p4=3Tj(B6iAF`{LSF@b(*P4W`R&7 zmSC=27mZQQQy+VF=iY-yPc?YExDrJp|HCmnCV60h{*fJ)viacz8d{*y5+Vz?$)~JezgZ45*sjR$gq)U`u_H}KJKn;>i{`@ zR_A$x7mcgjZm746T+7I_8Z%qdPl&!L@H4AlD?a|wF)YVpv@2T!gWJ0rT(el~^|{lY z;RqDB+;PuC((R@F!Ej_xU}XMu<`lbMfOFB}V!5(xgUgEeRO*sz ztX>6gzJFkF$da||R=T_~GP+@P%deaGmaP)@#qD0Sv)s9Bx9#9^Amqw}gp#j7;s5vU zTit5g;GyKmQS1K_qO|e+AdKQ9&GMqG>Za}bVVve=wcCE2*ZsWT?}P);=$r4RNwD#j z=cvd~jFgQ|Mwz{6D5|o_gO*!qAt^SFYE_{y=}lCjBF$QKIipsc|8&OUiDW9BaWJb1 zBbS%w$H!u+T&dRTji$+#&FzjQK6>Ojf%ViC+vJSX@~x8NRM(DP-!>QI4$NTc_WBS; zilYuomL$aiD@`9B&-eH54~C=hM6guaSm!N6 z03m@PwXvS|sNvEY&!NYS_N0kMRyzIy5Nv`&NDz{Q6d^rXlRfZd`c2Qid;w#>3H{sj zeR+yCR${R7$wPxon~uov2&uSElh)n}n1V_W8pT&g9Kh}8XP&6;yDk?p}&TT z|5hE8x#3HdjrHC*n&NtCkXawyTz185VU^CG@?QzVc}c*TxGJ<9teZFq>zJwrOf_Xx z6p0XKPtYK?HD6)Jbrp0n4zkkdw(r-C)7i6^i)=|XR;#u$Y-=;5whdgo-kv)pWhIT< zVm6ZQcKd$qdQnunMB3l7KpU#7!Qoh?Wr!T2N+Hu~2DDlq475AFI5<>Rb)?;^^%jHE zN0Z>xet7MKk9Ur!GD71oIe2y1p{1a91TPQMvwJ!oTiWKIt;^#iocu2i;1AxgXo&!V zW#8f;V}xSe^fU6lb>*w;yQ>tszV(_DGS{FnJuyq$vB&e>!{x>Nu;gEA^!YD<&=Cc? z`WtIhe%m{IfAUffZI)c?*3J-V#*Ca1g@>rKScS3{ATzLx zqz?+MOZM{}B;S2hqjEW_bEX$pV8f8H{CX8H@++p{ks89Ly%mjf#w*l`$tR)j*%(Jq zLwI7vmXk?f16hZ(0$l53NL{!8p`+a6%vje`V=M960b!mz92%eoQfTL@Ay_W&+-Jp@H{ ztrL*aE*-L<9EF`)cv7m!frhl&pnJUY=hx>;PQ;>A3Rzd2^$aYv9$GJEb*P{{D_vX@ zYU(eDNqZmiWx~w+^2OMegCR(51Leply@-*`jd#~KCx@}h$6o5V>}Ul)g9RD6NC1Hl z7&tHr5)fr{TOkq*3fjZrgvG5#7~sN_LKL*q3N&W3fCh*JQ`De^8_lX+KnsLvO4lvG zjt<65d0{SiNrQeNhO5wvdDQ~~L_&F(HuW^&dQm>mkiDZnO<=T-nb8~z&uB#sW-!cY z0!zW=H1p!rcDCo+`+JRw2Wf{oN`co4bhmwv#13>AI5l^>7REdhUY?dT)~(mDZy!C-Kk<(;Wed7mRzcSx+w z@z2N(>e_?({zNH6Cv~Y)v3Ntx0+B-$G{j7;z zV30Kc!?Om!zp9!fp$?ejVIuc#qN+cPLOST+$uzx15Z3L@7fS#WA;V9^VdVCt-NQ}_ zug@7>?Uq49h)AF?1NEYy51heK1hEAzcWzBUhY!j$?*sP0K%zU9{>OV literal 0 HcmV?d00001 diff --git a/http_server/izzylib/http_server/frontend/static/nunito/SIL Open Font License.txt b/http_server/izzylib/http_server/frontend/static/nunito/SIL Open Font License.txt new file mode 100644 index 0000000..3a7ebff --- /dev/null +++ b/http_server/izzylib/http_server/frontend/static/nunito/SIL Open Font License.txt @@ -0,0 +1,44 @@ +Copyright 2016 The Nunito Project Authors (contact@sansoxygen.com), +This Font Software is licensed under the SIL Open Font License, Version 1.1. + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others. + +The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the copyright statement(s). + +"Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, or substituting -- in part or in whole -- any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment. + +"Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission. + +5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. \ No newline at end of file diff --git a/http_server/izzylib/http_server/middleware.py b/http_server/izzylib/http_server/middleware.py new file mode 100644 index 0000000..e241f96 --- /dev/null +++ b/http_server/izzylib/http_server/middleware.py @@ -0,0 +1,40 @@ +import multiprocessing + +from datetime import datetime, timedelta, timezone +from izzylib import logging + +from . import start_time + + +class MiddlewareBase: + attach = 'request' + + def __init__(self, app): + self.app = app + self.cfg = app.cfg + + + async def handler(self, request): + pass + + +class Headers(MiddlewareBase): + attach = 'response' + + async def handler(self, request, response): + if request.path.startswith('/framework') or request.path == '/favicon.ico': + max_age = int(timedelta(weeks=2).total_seconds()) + response.headers['Cache-Control'] = f'immutable,private,max-age={max_age}' + + response.headers['Server'] = f'{self.cfg.name}/{self.cfg.version}' + response.headers['Trans'] = 'Rights' + + +class AccessLog(MiddlewareBase): + attach = 'response' + + async def handler(self, request, response): + uagent = request.headers.get('user-agent', 'None') + address = request.headers.get('x-real-ip', request.forwarded.get('for', request.remote_addr)) + + logging.info(f'({multiprocessing.current_process().name}) {address} {request.method} {request.path} {response.status} "{uagent}"') diff --git a/http_server/izzylib/http_server/misc.py b/http_server/izzylib/http_server/misc.py new file mode 100644 index 0000000..b1f000c --- /dev/null +++ b/http_server/izzylib/http_server/misc.py @@ -0,0 +1,31 @@ +from izzylib import LowerDotDict + + +def ReplaceHeader(headers, key, value): + for k,v in headers.items(): + if k.lower() == header.lower(): + del headers[k] + + +class Headers(LowerDotDict): + def __init__(self, headers): + super().__init__() + + for k,v in headers.items(): + if not self.get(k): + self[k] = [] + + self[k].append(v) + + + def getone(self, key, default=None): + value = self.get(key) + + if not value: + return default + + return value[0] + + + def getall(self, key, default=[]): + return self.get(key.lower(), default) diff --git a/http_server/izzylib/http_server/request.py b/http_server/izzylib/http_server/request.py new file mode 100644 index 0000000..7923881 --- /dev/null +++ b/http_server/izzylib/http_server/request.py @@ -0,0 +1,103 @@ +import sanic + +from .misc import Headers + + +class Request(sanic.request.Request): + def __init__(self, url_bytes, headers, version, method, transport, app): + super().__init__(url_bytes, headers, version, method, transport, app) + + self.Headers = Headers(headers) + self.Data = Data(self) + self.template = self.app.template + self.setup() + + + def setup(self): + pass + + + def response(self, tpl, *args, **kwargs): + return self.template.response(self, tpl, *args, **kwargs) + + + def alldata(self): + return DotDict( + **self.content.json, + **self.data.query, + **self.data.form + ) + + + def json_check(self): + if self.path.endswith('.json'): + return True + + accept = self.headers.getone('Accept', None) + + if accept: + mimes = [v.strip() for v in accept.split(',')] + + if any(mime in ['application/json', 'application/activity+json'] for mime in mimes): + return True + + return False + + +class Data(object): + def __init__(self, request): + self.request = request + + + @property + def combined(self): + return DotDict(**self.form.asDict(), **self.query.asDict(), **self.json.asDict()) + + + @property + def query(self): + data = {k: v for k,v in parse_qsl(self.request.query_string)} + return DotDict(data) + + + @property + def form(self): + data = {k: v[0] for k,v in self.request.form.items()} + return DotDict(data) + + + @property + def files(self): + return DotDict({k:v[0] for k,v in self.request.files.items()}) + + + ### body functions + @property + def raw(self): + try: + return self.request.body + except Exception as e: + logging.verbose('IzzyLib.http_server.Data.raw: failed to get body') + logging.debug(f'{e.__class__.__name__}: {e}') + return b'' + + + @property + def text(self): + try: + return self.raw.decode() + except Exception as e: + logging.verbose('IzzyLib.http_server.Data.text: failed to get body') + logging.debug(f'{e.__class__.__name__}: {e}') + return '' + + + @property + def json(self): + try: + return DotDict(self.text) + except Exception as e: + logging.verbose('IzzyLib.http_server.Data.json: failed to get body') + logging.debug(f'{e.__class__.__name__}: {e}') + data = '{}' + return {} diff --git a/http_server/izzylib/http_server/response.py b/http_server/izzylib/http_server/response.py new file mode 100644 index 0000000..cce236b --- /dev/null +++ b/http_server/izzylib/http_server/response.py @@ -0,0 +1,211 @@ +import json, sanic + +from izzylib import DotDict +from izzylib.template import Color +from sanic.compat import Header +from sanic.cookies import CookieJar + + +class Response: + content_types = DotDict({ + 'text': 'text/plain', + 'html': 'text/html', + 'css': 'text/css', + 'javascript': 'application/javascript', + 'json': 'application/json', + 'activitypub': 'application/activity+json' + }) + + default_theme = DotDict({ + 'primary': Color('#e7a'), + 'secondary': Color('#a7e'), + 'background': Color('#191919'), + 'positive': Color('#aea'), + 'negative': Color('#e99'), + 'white': Color('#eee'), + 'black': Color('#111'), + 'speed': 250 + }) + + + def __init__(self, app, request, body=None, headers={}, cookies={}, status=200, content_type='text/html'): + # server objects + self.app = app + self.cfg = app.cfg + self.request = request + + # init vars + self._body = None + self._content_type = content_type + + self.headers = Header(headers) + self.cookies = CookieJar(self.headers) + self.body = body + self.status = status + + for cookie in cookies.items(): + pass + + + def __str__(self): + return self.body + + + def __bytes__(self): + return self.body.encode('utf-8') + + + def __repr__(self): + return self.get_response() + + + @property + def body(self): + return self._body + + + @body.setter + def body(self, body): + if not body: + self._body = b'' + return + + if self.content_type in [self.content_types.json, self.content_types.activitypub]: + body = json.dumps(body) + + if isinstance(body, str): + self._body = body.encode('utf-8') + + elif isinstance(body, bytes): + self._body = body + + else: + raise TypeError(f'Response body must be a string or bytes, not {body.__class__.__name__}') + + + @property + def content_type(self): + return self._content_type + + + @content_type.setter + def content_type(self, ctype): + self._content_type = self.content_types.get(ctype, ctype) + + + def set_headers(self, data: dict): + try: + self.set_content_type(headers.pop('content-type')) + + except: + pass + + self.headers.clear() + self.headers.update(data) + + + def set_cookie(self, key, value, data={}, **kwargs): + self.cookies[key] = value + + data.update(kwargs) + + for k,v in data.items(): + if k.lower() == 'max-age': + if isinstance(v, timedelta): + v = int(v.total_seconds()) + + elif not isinstance(v, int): + raise TypeError('Max-Age must be an integer or timedelta') + + elif k.lower() == 'expires': + if isinstance(v, datetime): + v = v.strftime('%a, %d-%b-%Y %T GMT') + + elif not isinstance(v, str): + raise TypeError('Expires must be a string or datetime') + + self.cookies[key][k] = v + + + def get_cookie(self, key): + try: + cookie = self.cookies[key] + except KeyError: + return None + + return + + + def del_cookie(self, key): + del self.cookies[key] + + + def template(self, tplfile, context={}, headers={}, status=200, content_type='text/html', cookies={}, pprint=False): + self.status = status + context.update({ + 'response': self, + **self.default_theme + }) + + html = self.app.template.render(tplfile, context, request=self, pprint=pprint) + return self.html(html, headers=headers, status=status, content_type=content_type, cookies=cookies) + + + def error(self, message, status=500, **kwargs): + if self.request and 'json' in self.request.headers.get('accept', ''): + return self.json({f'error {status}': message}, status=status, **kwargs) + + return self.template('error.haml', {'error_message': message}, status=status, **kwargs) + + + def json(self, body={}, headers={}, status=200, content_type='application/json', cookies={}): + body = json.dumps(body) + return self.get_response(body, headers, status, content_type, cookies) + + + def text(self, body, headers={}, status=200, content_type='text/plain', cookies={}): + return self.get_response(body, headers, status, content_type, cookies) + + + def html(self, *args, **kwargs): + self.content_type = 'text/html' + return self.text(*args, **kwargs) + + + def css(self, *args, **kwargs): + self.content_type = 'text/css' + return self.text.text(*args, **kwargs) + + + def javascript(self, *args, **kwargs): + self.content_type = 'application/javascript' + return self.text.text(*args, **kwargs) + + + def activitypub(self, *args, **kwargs): + self.content_type = 'application/activity+json' + return self.text.text(*args, **kwargs) + + + def redir(self, path, status=302, headers={}): + return sanic.response.redirect(path, status=status, headers={}) + + + def set_data(self, body=None, headers={}, status=200, content_type='text/html', cookies={}): + ctype = self.content_types.get(content_type, content_type) + + self.body = body + self.headers = headers + self.status = status + self.content_type = content_type + self.headers = headers + self.headers.pop('content-type', None) + + + def get_response(self, *args, **kwargs): + self.set_data(*args, **kwargs) + + response = sanic.response.HTTPResponse(self.body, self.status, self.headers, self.content_type) + response._cookies = self.cookies + + return response diff --git a/http_server/izzylib/http_server/view.py b/http_server/izzylib/http_server/view.py new file mode 100644 index 0000000..a561c5d --- /dev/null +++ b/http_server/izzylib/http_server/view.py @@ -0,0 +1,55 @@ +from izzylib.template import Color +from sanic.views import HTTPMethodView + +from .response import Response + + +class View(HTTPMethodView): + routes = [] + + + def dispatch_request(self, request, *args, **kwargs): + self.app = request.app + self.cfg = request.app.cfg + + handler = getattr(self, request.method.lower(), None) + return handler(request, Response(self.app, request), *args, **kwargs) + + +class Manifest(View): + paths = ['/framework/manifest.json'] + + + async def get(self, request, response): + data = { + 'name': self.cfg.name, + 'short_name': self.cfg.name.replace(' ', ''), + 'description': 'UvU', + 'icons': [ + { + 'src': "/framework/static/icon512.png", + 'sizes': '512x512', + 'type': 'image/png' + }, + { + 'src': "/framework/static/icon64.png", + 'sizes': '64x64', + 'type': 'image/png' + } + ], + 'theme_color': str(response.default_theme.primary), + 'background_color': str(response.default_theme.background), + 'display': 'standalone', + 'start_url': '/', + 'scope': f'{self.cfg.proto}://{self.cfg.web_host}' + } + + return response.json(data) + + +class Style(View): + paths = ['/framework/style.css'] + + async def get(self, request, response): + return response.template('base.css', content_type='text/css') + diff --git a/http_server/setup.py b/http_server/setup.py new file mode 100644 index 0000000..696621d --- /dev/null +++ b/http_server/setup.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python3 +from setuptools import setup, find_namespace_packages + + +requires = [ + 'sanic==20.12.3', + 'sanic-cors==1.0.0', +] + + +setup( + name="IzzyLib HTTP Server", + version='0.6.0', + packages=find_namespace_packages(include=['izzylib.http_requests_client']), + python_requires='>=3.7.0', + install_requires=requires, + include_package_data=False, + author='Zoey Mae', + author_email='admin@barkshark.xyz', + description='An HTTP server based on Sanic', + keywords='web http server', + url='https://git.barkshark.xyz/izaliamae/izzylib', + project_urls={ + 'Bug Tracker': 'https://git.barkshark.xyz/izaliamae/izzylib/issues', + 'Documentation': 'https://git.barkshark.xyz/izaliamae/izzylib/wiki', + 'Source Code': 'https://git.barkshark.xyz/izaliamae/izzylib' + }, + + classifiers=[ + 'Development Status :: 3 - Alpha', + 'Intended Audience :: Information Technology', + 'License :: Co-operative Non-violent Public License (CNPL 6+)', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', + 'Operating System :: POSIX', + 'Operating System :: MacOS :: MacOS X', + 'Operating System :: Microsoft :: Windows', + 'Topic :: Internet :: WWW/HTTP', + 'Topic :: Software Development :: Libraries', + 'Topic :: Software Development :: Libraries :: Python Modules' + ] +) diff --git a/template/izzylib/template/__init__.py b/template/izzylib/template/__init__.py index 452c105..108c4b7 100644 --- a/template/izzylib/template/__init__.py +++ b/template/izzylib/template/__init__.py @@ -107,13 +107,13 @@ class Template(Environment): def update_filter(self, data): - if not isinstance(context, dict): + if not isinstance(data, dict): raise ValueError(f'Filter data not a dict') self.filters.update(data) - def render(self, tplfile, context={}, headers={}, cookies={}, request=None, pprint=False, **kwargs): + def render(self, tplfile, context={}, headers={}, cookies={}, request=None, pprint=False): if not isinstance(context, dict): raise TypeError(f'context for {tplfile} not a dict: {type(context)} {context}') From f5b2eb11934a6e20dfd006d076c12c7e45617b32 Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Tue, 17 Aug 2021 14:50:50 -0400 Subject: [PATCH 53/74] add web frontend menu management --- http_server/izzylib/http_server/__init__.py | 2 +- .../izzylib/http_server/application.py | 30 ++++++++++++++++++- http_server/izzylib/http_server/config.py | 23 ++++++++++++-- http_server/izzylib/http_server/view.py | 1 + http_server/setup.py | 4 +-- 5 files changed, 54 insertions(+), 6 deletions(-) diff --git a/http_server/izzylib/http_server/__init__.py b/http_server/izzylib/http_server/__init__.py index 7d8dfda..aabd388 100644 --- a/http_server/izzylib/http_server/__init__.py +++ b/http_server/izzylib/http_server/__init__.py @@ -3,7 +3,7 @@ from datetime import datetime start_time = datetime.now() from .application import Application -from .config import Config +from .config import Config, UserLevel from .request import Request from .response import Response from .view import View diff --git a/http_server/izzylib/http_server/application.py b/http_server/izzylib/http_server/application.py index a667580..e53f581 100644 --- a/http_server/izzylib/http_server/application.py +++ b/http_server/izzylib/http_server/application.py @@ -9,7 +9,7 @@ from urllib.parse import parse_qsl, urlparse from izzylib import DotDict, Path, logging from izzylib.template import Template -from .config import Config +from .config import Config, UserLevel from .error_handlers import GenericError, MissingTemplateError from .middleware import AccessLog, Headers from .view import Manifest, Style @@ -67,6 +67,9 @@ class Application(sanic.Sanic): for route in cls.paths: self.add_route(cls.as_view(), route) + if cls.menu: + self.set_menu_item(*cls.menu) + def add_error_handler(self, handler): handle = handler(self) @@ -78,6 +81,18 @@ class Application(sanic.Sanic): self.register_middleware(mw.handler, mw.attach) + def get_menu_item(self, name, level=0): + return self.cfg.menu[parse_level(level)][name] + + + def set_menu_item(self, name, path, level=0): + self.cfg.menu[parse_level(level)][name] = path + + + def del_menu_item(self, name, level=0): + del self.cfg.menu[parse_level(level)][name] + + def start(self): # register built-in middleware now so they're last in the chain self.add_middleware(Headers) @@ -104,3 +119,16 @@ class Application(sanic.Sanic): self.stop() logging.info('Bye! :3') + + +def parse_level(level): + if type(level) == int: + new_level = UserLevel(level) + + elif type(level) == str: + new_level = UserLevel[level.upper()] + + elif type(level) != UserLevel: + raise TypeError(f'User level must be a string, integer, or UserLevel, not a {level.__class__.__name__}') + + return new_level diff --git a/http_server/izzylib/http_server/config.py b/http_server/izzylib/http_server/config.py index 0f63a92..3d9e50a 100644 --- a/http_server/izzylib/http_server/config.py +++ b/http_server/izzylib/http_server/config.py @@ -1,3 +1,4 @@ +from enum import Enum from izzylib import DotDict from multiprocessing import cpu_count @@ -5,6 +6,13 @@ from .request import Request from .response import Response +class UserLevel(Enum): + GUEST = 0 + USER = 10 + MODERATOR = 20 + ADMIN = 30 + + class Config(DotDict): defaults = dict( name = 'IzzyLib Http Server', @@ -22,16 +30,24 @@ class Config(DotDict): sig_handler = None, sig_handler_args = [], sig_handler_kwargs = {}, - menu = {}, tpl_search = [], tpl_globals = {}, tpl_context = None, tpl_autoescape = True, - tpl_default = True + tpl_default = True, + menu = { + UserLevel.GUEST: {}, + UserLevel.USER: {}, + UserLevel.MODERATOR: {}, + UserLevel.ADMIN: {} + } ) def __init__(self, **kwargs): + if kwargs.pop('menu', None): + raise ValueError('Use the Application.set_menu_item function to set menu items') + super().__init__({**self.defaults, **kwargs}) if kwargs.get('host') and not kwargs.get('web_host'): @@ -39,6 +55,9 @@ class Config(DotDict): def __setitem__(self, key, value): + if key == 'menu': + raise KeyError('Use the Application.set_menu_item function to set menu items') + if key not in self.defaults.keys(): raise KeyError(f'Invalid config key {key}') diff --git a/http_server/izzylib/http_server/view.py b/http_server/izzylib/http_server/view.py index a561c5d..0eaa691 100644 --- a/http_server/izzylib/http_server/view.py +++ b/http_server/izzylib/http_server/view.py @@ -6,6 +6,7 @@ from .response import Response class View(HTTPMethodView): routes = [] + menu = None # example: ("Home", "\", 0) def dispatch_request(self, request, *args, **kwargs): diff --git a/http_server/setup.py b/http_server/setup.py index 696621d..f80899e 100644 --- a/http_server/setup.py +++ b/http_server/setup.py @@ -3,8 +3,8 @@ from setuptools import setup, find_namespace_packages requires = [ - 'sanic==20.12.3', - 'sanic-cors==1.0.0', + 'sanic=>20.12.3', + 'sanic-cors=>1.0.0', ] From c8663acc45d7c8ba83588826fdf5acdc5ecf022f Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Tue, 17 Aug 2021 14:51:37 -0400 Subject: [PATCH 54/74] oops! --- http_server/setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/http_server/setup.py b/http_server/setup.py index f80899e..46a3668 100644 --- a/http_server/setup.py +++ b/http_server/setup.py @@ -3,8 +3,8 @@ from setuptools import setup, find_namespace_packages requires = [ - 'sanic=>20.12.3', - 'sanic-cors=>1.0.0', + 'sanic>=20.12.3', + 'sanic-cors>=1.0.0', ] From 11aaaf349902997bb4baf68f8aca0ecb631cbe9e Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Tue, 17 Aug 2021 15:39:15 -0400 Subject: [PATCH 55/74] use izzylog and a few fixes --- base/izzylib/logging.py | 8 ++++---- http_server/izzylib/http_server/application.py | 18 +++++++++--------- http_server/izzylib/http_server/config.py | 14 +++----------- .../izzylib/http_server/error_handlers.py | 11 +++++------ .../izzylib/http_server/frontend/base.haml | 5 +++-- http_server/izzylib/http_server/middleware.py | 4 ++-- http_server/izzylib/http_server/request.py | 1 + http_server/izzylib/http_server/response.py | 5 ++--- 8 files changed, 29 insertions(+), 37 deletions(-) diff --git a/base/izzylib/logging.py b/base/izzylib/logging.py index 22e0825..0b9a821 100644 --- a/base/izzylib/logging.py +++ b/base/izzylib/logging.py @@ -2,10 +2,10 @@ import sys from os import getppid, environ as env from datetime import datetime -from enum import Enum +from enum import IntEnum -class Levels(Enum): +class Levels(IntEnum): CRITICAL = 60, ERROR = 50 WARNING = 40 @@ -55,7 +55,7 @@ class Log: def set_config(self, key, value): - if key == 'level' and type(value) == str: + if key == 'level' and type(value) in [str, int]: value = self.parse_level(value) setattr(self, key, value) @@ -73,7 +73,7 @@ class Log: if isinstance(level, str): Levels[level.upper()] - if level.value < self.level.value: + if level < self.level: return default = self.name == 'Default' diff --git a/http_server/izzylib/http_server/application.py b/http_server/izzylib/http_server/application.py index e53f581..40179f7 100644 --- a/http_server/izzylib/http_server/application.py +++ b/http_server/izzylib/http_server/application.py @@ -6,7 +6,7 @@ from multidict import CIMultiDict from multiprocessing import cpu_count, current_process from urllib.parse import parse_qsl, urlparse -from izzylib import DotDict, Path, logging +from izzylib import DotDict, Path, izzylog as logging from izzylib.template import Template from .config import Config, UserLevel @@ -81,16 +81,16 @@ class Application(sanic.Sanic): self.register_middleware(mw.handler, mw.attach) - def get_menu_item(self, name, level=0): - return self.cfg.menu[parse_level(level)][name] + def get_menu_item(self, name): + return self.cfg.menu[name] def set_menu_item(self, name, path, level=0): - self.cfg.menu[parse_level(level)][name] = path + self.cfg.menu[name] = (path, parse_level(level)) - def del_menu_item(self, name, level=0): - del self.cfg.menu[parse_level(level)][name] + def del_menu_item(self, name): + del self.cfg.menu[name] def start(self): @@ -123,12 +123,12 @@ class Application(sanic.Sanic): def parse_level(level): if type(level) == int: - new_level = UserLevel(level) + level = UserLevel(level) elif type(level) == str: - new_level = UserLevel[level.upper()] + level = UserLevel[level.upper()] elif type(level) != UserLevel: raise TypeError(f'User level must be a string, integer, or UserLevel, not a {level.__class__.__name__}') - return new_level + return level diff --git a/http_server/izzylib/http_server/config.py b/http_server/izzylib/http_server/config.py index 3d9e50a..ebcf6ec 100644 --- a/http_server/izzylib/http_server/config.py +++ b/http_server/izzylib/http_server/config.py @@ -1,4 +1,4 @@ -from enum import Enum +from enum import IntEnum from izzylib import DotDict from multiprocessing import cpu_count @@ -6,7 +6,7 @@ from .request import Request from .response import Response -class UserLevel(Enum): +class UserLevel(IntEnum): GUEST = 0 USER = 10 MODERATOR = 20 @@ -35,12 +35,7 @@ class Config(DotDict): tpl_context = None, tpl_autoescape = True, tpl_default = True, - menu = { - UserLevel.GUEST: {}, - UserLevel.USER: {}, - UserLevel.MODERATOR: {}, - UserLevel.ADMIN: {} - } + menu = {} ) @@ -55,9 +50,6 @@ class Config(DotDict): def __setitem__(self, key, value): - if key == 'menu': - raise KeyError('Use the Application.set_menu_item function to set menu items') - if key not in self.defaults.keys(): raise KeyError(f'Invalid config key {key}') diff --git a/http_server/izzylib/http_server/error_handlers.py b/http_server/izzylib/http_server/error_handlers.py index 7e8f54e..602fb78 100644 --- a/http_server/izzylib/http_server/error_handlers.py +++ b/http_server/izzylib/http_server/error_handlers.py @@ -1,5 +1,6 @@ import traceback +from izzylib import izzylog as logging from jinja2.exceptions import TemplateNotFound from .response import Response @@ -14,12 +15,10 @@ class GenericError: def __call__(self): - return self.error, self.handler + return self.error, lambda request, exception: self.handler(request, Response(self.app, request), exception) - def handler(self, request, exception): - response = Response(self.app, request) - + def handler(self, request, response, exception): try: status = exception.status_code msg = str(exception) @@ -42,6 +41,6 @@ class MissingTemplateError(GenericError): error = TemplateNotFound - def handler(self, request, exception): + def handler(self, request, response, exception): logging.error('TEMPLATE_ERROR:', f'{exception.__class__.__name__}: {str(exception)}') - return request.response.html('I\'m a dingleberry and forgot to create a template for this page', 500) + return response.error('I\'m a dingleberry and forgot to create a template for this page', 500) diff --git a/http_server/izzylib/http_server/frontend/base.haml b/http_server/izzylib/http_server/frontend/base.haml index 5bf8422..87a3754 100644 --- a/http_server/izzylib/http_server/frontend/base.haml +++ b/http_server/izzylib/http_server/frontend/base.haml @@ -27,8 +27,9 @@ #menu.section .title-item.item << Menu #items - -for label, path in cfg.menu.items() - .item -> %a href='{{cfg.proto}}://{{cfg.web_host}}{{path}}' << {{label}} + -for label, data in cfg.menu.items() + -if request.user_level >= data[1] + .item -> %a href='{{cfg.proto}}://{{cfg.web_host}}{{data[0]}}' << {{label}} #content-body.section -block content diff --git a/http_server/izzylib/http_server/middleware.py b/http_server/izzylib/http_server/middleware.py index e241f96..6c7c86f 100644 --- a/http_server/izzylib/http_server/middleware.py +++ b/http_server/izzylib/http_server/middleware.py @@ -1,7 +1,7 @@ import multiprocessing from datetime import datetime, timedelta, timezone -from izzylib import logging +from izzylib import izzylog as logging, logging as applog from . import start_time @@ -37,4 +37,4 @@ class AccessLog(MiddlewareBase): uagent = request.headers.get('user-agent', 'None') address = request.headers.get('x-real-ip', request.forwarded.get('for', request.remote_addr)) - logging.info(f'({multiprocessing.current_process().name}) {address} {request.method} {request.path} {response.status} "{uagent}"') + applog.info(f'({multiprocessing.current_process().name}) {address} {request.method} {request.path} {response.status} "{uagent}"') diff --git a/http_server/izzylib/http_server/request.py b/http_server/izzylib/http_server/request.py index 7923881..4590388 100644 --- a/http_server/izzylib/http_server/request.py +++ b/http_server/izzylib/http_server/request.py @@ -10,6 +10,7 @@ class Request(sanic.request.Request): self.Headers = Headers(headers) self.Data = Data(self) self.template = self.app.template + self.user_level = 0 self.setup() diff --git a/http_server/izzylib/http_server/response.py b/http_server/izzylib/http_server/response.py index cce236b..5b9e69e 100644 --- a/http_server/izzylib/http_server/response.py +++ b/http_server/izzylib/http_server/response.py @@ -147,7 +147,7 @@ class Response: **self.default_theme }) - html = self.app.template.render(tplfile, context, request=self, pprint=pprint) + html = self.app.template.render(tplfile, context, request=self.request, pprint=pprint) return self.html(html, headers=headers, status=status, content_type=content_type, cookies=cookies) @@ -195,10 +195,9 @@ class Response: ctype = self.content_types.get(content_type, content_type) self.body = body - self.headers = headers self.status = status self.content_type = content_type - self.headers = headers + self.headers.update(headers) self.headers.pop('content-type', None) From cd20eaea97a6ca1c776abaa32f363ad0caeef0c7 Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Sun, 29 Aug 2021 22:14:55 -0400 Subject: [PATCH 56/74] a lot --- .gitignore | 3 + base/izzylib/__init__.py | 3 +- base/izzylib/cache.py | 18 + base/izzylib/dotdict.py | 7 + base/izzylib/misc.py | 8 + base/izzylib/path.py | 6 +- http_server/izzylib/http_server/__init__.py | 1 + .../izzylib/http_server/application.py | 9 +- http_server/izzylib/http_server/config.py | 2 + .../izzylib/http_server/frontend/base.css | 19 +- .../izzylib/http_server/frontend/base.haml | 23 +- .../izzylib/http_server/frontend/menu.haml | 1 + http_server/izzylib/http_server/middleware.py | 37 +- http_server/izzylib/http_server/request.py | 6 +- http_server/izzylib/http_server/response.py | 52 ++- http_server/izzylib/http_server/view.py | 8 + http_server/setup.py | 1 + sql/izzylib/sql/__init__.py | 6 +- sql/izzylib/sql/config.py | 100 +++++ sql/izzylib/sql/database.py | 360 +++++++++++++++ sql/izzylib/sql/error.py | 10 + sql/izzylib/sql/generic.py | 86 +++- sql/izzylib/sql/queries.py | 415 ++++++++++++++++++ sql/izzylib/sql/row.py | 19 + sql/izzylib/sql/types.py | 19 + 25 files changed, 1155 insertions(+), 64 deletions(-) create mode 100644 http_server/izzylib/http_server/frontend/menu.haml create mode 100644 sql/izzylib/sql/config.py create mode 100644 sql/izzylib/sql/database.py create mode 100644 sql/izzylib/sql/error.py create mode 100644 sql/izzylib/sql/queries.py create mode 100644 sql/izzylib/sql/row.py create mode 100644 sql/izzylib/sql/types.py diff --git a/.gitignore b/.gitignore index 8c8a459..73dcf22 100644 --- a/.gitignore +++ b/.gitignore @@ -117,10 +117,13 @@ dmypy.json test*.py reload.cfg +# symlinks /izzylib /base/izzylib/dbus /base/izzylib/hasher /base/izzylib/http_requests_client +/base/izzylib/http_server +/base/izzylib/mbus /base/izzylib/sql /base/izzylib/template /base/izzylib/tinydb diff --git a/base/izzylib/__init__.py b/base/izzylib/__init__.py index 0d710f8..c8f8bfe 100644 --- a/base/izzylib/__init__.py +++ b/base/izzylib/__init__.py @@ -4,7 +4,7 @@ Licensed under the CNPL: https://git.pixie.town/thufie/CNPL https://git.barkshark.xyz/izaliamae/izzylib ''' -import sys, traceback +import os, sys, traceback assert sys.version_info >= (3, 7) __version_tpl__ = (0, 6, 0) @@ -13,6 +13,7 @@ __version__ = '.'.join([str(v) for v in __version_tpl__]) from . import logging izzylog = logging.logger['IzzyLib'] +izzylog.set_config('level', os.environ.get('IZZYLOG_LEVEL', 'INFO')) from .path import Path from .dotdict import DotDict, LowerDotDict, DefaultDotDict, MultiDotDict, JsonEncoder diff --git a/base/izzylib/cache.py b/base/izzylib/cache.py index ed9e1e2..a8d746f 100644 --- a/base/izzylib/cache.py +++ b/base/izzylib/cache.py @@ -42,6 +42,10 @@ def parse_ttl(ttl): return multiplier * int(amount) +class DefaultValue(object): + pass + + class BaseCache(OrderedDict): _get = OrderedDict.get _items = OrderedDict.items @@ -120,6 +124,20 @@ class BaseCache(OrderedDict): 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 + + ## This doesn't work for some reason def CacheDecorator(cache): def decorator(func): diff --git a/base/izzylib/dotdict.py b/base/izzylib/dotdict.py index d44222e..34003a4 100644 --- a/base/izzylib/dotdict.py +++ b/base/izzylib/dotdict.py @@ -59,6 +59,13 @@ class DotDict(dict): raise AttributeError(f'{self.__class__.__name__} object has no attribute {k}') from None + @classmethod + def new_from_json_file(cls, path): + data = cls() + data.load_json(path) + return data + + def copy(self): return DotDict(self) diff --git a/base/izzylib/misc.py b/base/izzylib/misc.py index 94a428b..e3cedc0 100644 --- a/base/izzylib/misc.py +++ b/base/izzylib/misc.py @@ -22,6 +22,7 @@ __all__ = [ 'print_methods', 'prompt', 'random_gen', + 'remove', 'signal_handler', 'time_function', 'time_function_pprint', @@ -348,6 +349,13 @@ def random_gen(length=20, letters=True, numbers=True, extra=None): return ''.join(random.choices(characters, k=length)) +def remove(string: str, junk: list): + for line in junk: + string = string.replace(line, '') + + return string + + def signal_handler(func, *args, original_args=True, **kwargs): if original_args: handler = lambda signum, frame: func(signum, frame, *args, **kwargs) diff --git a/base/izzylib/path.py b/base/izzylib/path.py index 0b6ada7..db11acb 100644 --- a/base/izzylib/path.py +++ b/base/izzylib/path.py @@ -1,4 +1,4 @@ -import os, shutil +import json, os, shutil from datetime import datetime from functools import cached_property @@ -105,9 +105,9 @@ class Path(str): return json.load(s) - def json_dump(self, data): + def json_dump(self, data, indent=None): with self.open('w') as s: - s.write(json.dumps(data)) + s.write(json.dumps(data, indent=indent)) def link(self, path): diff --git a/http_server/izzylib/http_server/__init__.py b/http_server/izzylib/http_server/__init__.py index aabd388..e9b50b5 100644 --- a/http_server/izzylib/http_server/__init__.py +++ b/http_server/izzylib/http_server/__init__.py @@ -4,6 +4,7 @@ start_time = datetime.now() from .application import Application from .config import Config, UserLevel +from .middleware import MiddlewareBase, Headers, AccessLog from .request import Request from .response import Response from .view import View diff --git a/http_server/izzylib/http_server/application.py b/http_server/izzylib/http_server/application.py index 40179f7..9502747 100644 --- a/http_server/izzylib/http_server/application.py +++ b/http_server/izzylib/http_server/application.py @@ -12,7 +12,7 @@ from izzylib.template import Template from .config import Config, UserLevel from .error_handlers import GenericError, MissingTemplateError from .middleware import AccessLog, Headers -from .view import Manifest, Style +from .view import Manifest, Robots, Style log_path_ignore = [ @@ -46,10 +46,12 @@ class Application(sanic.Sanic): ) self.template.add_env('cfg', self.cfg) + self.template.add_env('len', len) if self.cfg.tpl_default: self.template.add_search_path(frontend) self.add_class_route(Manifest) + self.add_class_route(Robots) self.add_class_route(Style) self.static('/favicon.ico', frontend.join('static/icon64.png')) self.static('/framework/static', frontend.join('static')) @@ -93,6 +95,11 @@ class Application(sanic.Sanic): del self.cfg.menu[name] + def get_route_by_path(self, path, method='get', host=None,): + route, handler, _ = self.router.get(path, method, host) + return handler + + def start(self): # register built-in middleware now so they're last in the chain self.add_middleware(Headers) diff --git a/http_server/izzylib/http_server/config.py b/http_server/izzylib/http_server/config.py index ebcf6ec..e6e508a 100644 --- a/http_server/izzylib/http_server/config.py +++ b/http_server/izzylib/http_server/config.py @@ -11,6 +11,7 @@ class UserLevel(IntEnum): USER = 10 MODERATOR = 20 ADMIN = 30 + AUTH = 1000 class Config(DotDict): @@ -25,6 +26,7 @@ class Config(DotDict): port = 8080, proto = 'http', workers = cpu_count(), + access_log = True, request_class = Request, response_class = Response, sig_handler = None, diff --git a/http_server/izzylib/http_server/frontend/base.css b/http_server/izzylib/http_server/frontend/base.css index 5f35466..e61122f 100644 --- a/http_server/izzylib/http_server/frontend/base.css +++ b/http_server/izzylib/http_server/frontend/base.css @@ -39,7 +39,6 @@ a:hover { } input:not([type='checkbox']), select, textarea { - margin: 1px 0; color: var(--text); background-color: var(--background); border: 1px solid var(--background); @@ -263,7 +262,7 @@ details:focus, summary:focus { transition: background-color var(--trans-speed); width: 55px; margin-left: var(--gap); - background-image: url('{{cfg.proto}}://{{cfg.web_host}}/framework/static/menu.svg'); + background-image: url('/framework/static/menu.svg'); background-size: 50px; background-position: center center; background-repeat: no-repeat; @@ -412,8 +411,8 @@ body {scrollbar-width: 15px; scrollbar-color: var(--primary) {{background.darken @font-face { font-family: 'sans undertale'; src: local('Nunito Sans Bold'), - url('{{cfg.proto}}://{{cfg.web_host}}/framework/static/nunito/NunitoSans-SemiBold.woff2') format('woff2'), - url('{{cfg.proto}}://{{cfg.web_host}}/framework/static/nunito/NunitoSans-SemiBold.ttf') format('ttf'); + url('/framework/static/nunito/NunitoSans-SemiBold.woff2') format('woff2'), + url('/framework/static/nunito/NunitoSans-SemiBold.ttf') format('ttf'); font-weight: bold; font-style: normal; } @@ -421,8 +420,8 @@ body {scrollbar-width: 15px; scrollbar-color: var(--primary) {{background.darken @font-face { font-family: 'sans undertale'; src: local('Nunito Sans Light Italic'), - url('{{cfg.proto}}://{{cfg.web_host}}/framework/static/nunito/NunitoSans-ExtraLightItalic.woff2') format('woff2'), - url('{{cfg.proto}}://{{cfg.web_host}}/framework/static/nunito/NunitoSans-ExtraLightItalic.ttf') format('ttf'); + url('/framework/static/nunito/NunitoSans-ExtraLightItalic.woff2') format('woff2'), + url('/framework/static/nunito/NunitoSans-ExtraLightItalic.ttf') format('ttf'); font-weight: normal; font-style: italic; } @@ -430,8 +429,8 @@ body {scrollbar-width: 15px; scrollbar-color: var(--primary) {{background.darken @font-face { font-family: 'sans undertale'; src: local('Nunito Sans Bold Italic'), - url('{{cfg.proto}}://{{cfg.web_host}}/framework/static/nunito/NunitoSans-Italic.woff2') format('woff2'), - url('{{cfg.proto}}://{{cfg.web_host}}/framework/static/nunito/NunitoSans-Italic.ttf') format('ttf'); + url('/framework/static/nunito/NunitoSans-Italic.woff2') format('woff2'), + url('/framework/static/nunito/NunitoSans-Italic.ttf') format('ttf'); font-weight: bold; font-style: italic; } @@ -439,8 +438,8 @@ body {scrollbar-width: 15px; scrollbar-color: var(--primary) {{background.darken @font-face { font-family: 'sans undertale'; src: local('Nunito Sans Light'), - url('{{cfg.proto}}://{{cfg.web_host}}/framework/static/nunito/NunitoSans-Light.woff2') format('woff2'), - url('{{cfg.proto}}://{{cfg.web_host}}/framework/static/nunito/NunitoSans-Light.ttf') format('ttf'); + url('/framework/static/nunito/NunitoSans-Light.woff2') format('woff2'), + url('/framework/static/nunito/NunitoSans-Light.ttf') format('ttf'); font-weight: normal; font-style: normal; } diff --git a/http_server/izzylib/http_server/frontend/base.haml b/http_server/izzylib/http_server/frontend/base.haml index 87a3754..d2da0e6 100644 --- a/http_server/izzylib/http_server/frontend/base.haml +++ b/http_server/izzylib/http_server/frontend/base.haml @@ -2,20 +2,21 @@ %html %head %title << {{cfg.name}}: {{page}} - %link rel='stylesheet' type='text/css' href='{{cfg.proto}}://{{cfg.web_host}}/framework/style.css' - %link rel='manifest' href='{{cfg.proto}}://{{cfg.web_host}}/framework/manifest.json' + %link rel='stylesheet' type='text/css' href='/framework/style.css' + %link rel='manifest' href='/framework/manifest.json' %meta charset='UTF-8' %meta name='viewport' content='width=device-width, initial-scale=1' + -block head %body #body #header.flex-container -if menu_left #btn.section - .page-title.section -> %a.title href='{{cfg.proto}}://{{cfg.web_host}}/' << {{cfg.name}} + .page-title.section -> %a.title href='/' << {{cfg.name}} -else - .page-title.section -> %a.title href='{{cfg.proto}}://{{cfg.web_host}}/' << {{cfg.name}} + .page-title.section -> %a.title href='/' << {{cfg.name}} #btn.section -if message @@ -27,9 +28,15 @@ #menu.section .title-item.item << Menu #items - -for label, data in cfg.menu.items() - -if request.user_level >= data[1] - .item -> %a href='{{cfg.proto}}://{{cfg.web_host}}{{data[0]}}' << {{label}} + -if not len(cfg.menu): + -include 'menu.haml' + + -else: + -for label, path_data in cfg.menu.items() + -if path_data[1] == 1000 and request.user_level == 0: + .item -> %a href='{{path_data[0]}}' << {{label}} + -elif request.user_level >= path_data[1] + .item -> %a href='{{path_data[0]}}' << {{label}} #content-body.section -block content @@ -40,4 +47,4 @@ .source %a href='{{cfg.git_repo}}' target='_new' << {{cfg.name}}/{{cfg.version}} - %script type='application/javascript' src='{{cfg.proto}}://{{cfg.web_host}}/framework/static/menu.js' + %script type='application/javascript' src='/framework/static/menu.js' diff --git a/http_server/izzylib/http_server/frontend/menu.haml b/http_server/izzylib/http_server/frontend/menu.haml new file mode 100644 index 0000000..c883b18 --- /dev/null +++ b/http_server/izzylib/http_server/frontend/menu.haml @@ -0,0 +1 @@ +.item => %a(href='/') << Home diff --git a/http_server/izzylib/http_server/middleware.py b/http_server/izzylib/http_server/middleware.py index 6c7c86f..8555d87 100644 --- a/http_server/izzylib/http_server/middleware.py +++ b/http_server/izzylib/http_server/middleware.py @@ -6,6 +6,34 @@ from izzylib import izzylog as logging, logging as applog from . import start_time +cache_types = [ + 'text/css', + 'application/javascript', +] + +cache_base_types = [ + 'image', + 'audio', + 'video' +] + + +def cache_check(request, response): + content_type = response.headers.get('content-type') + + if request.path.startswith('/framework'): + return True + + if not content_type: + return False + + if content_type in cache_types: + return True + + if any(map(content_type.startswith, cache_base_types)): + return True + + class MiddlewareBase: attach = 'request' @@ -22,7 +50,14 @@ class Headers(MiddlewareBase): attach = 'response' async def handler(self, request, response): - if request.path.startswith('/framework') or request.path == '/favicon.ico': + if not response.headers.get('content-type'): + if request.path.endswith('.css'): + response.headers['content-type'] = 'text/css' + + elif request.path.endswith('.js'): + response.headers['content-type'] = 'application/javascript' + + if cache_check(request, response): max_age = int(timedelta(weeks=2).total_seconds()) response.headers['Cache-Control'] = f'immutable,private,max-age={max_age}' diff --git a/http_server/izzylib/http_server/request.py b/http_server/izzylib/http_server/request.py index 4590388..7d288f8 100644 --- a/http_server/izzylib/http_server/request.py +++ b/http_server/izzylib/http_server/request.py @@ -1,14 +1,16 @@ import sanic +from izzylib import DotDict + from .misc import Headers class Request(sanic.request.Request): - def __init__(self, url_bytes, headers, version, method, transport, app): + def __init__(self, url_bytes, headers, version, method, transport, app, **kwargs): super().__init__(url_bytes, headers, version, method, transport, app) self.Headers = Headers(headers) - self.Data = Data(self) + self.data = Data(self) self.template = self.app.template self.user_level = 0 self.setup() diff --git a/http_server/izzylib/http_server/response.py b/http_server/izzylib/http_server/response.py index 5b9e69e..5e7f5b0 100644 --- a/http_server/izzylib/http_server/response.py +++ b/http_server/izzylib/http_server/response.py @@ -1,6 +1,7 @@ import json, sanic -from izzylib import DotDict +from datetime import datetime +from izzylib import DotDict, izzylog from izzylib.template import Color from sanic.compat import Header from sanic.cookies import CookieJar @@ -27,6 +28,18 @@ class Response: 'speed': 250 }) + cookie_keys = { + 'expires': 'Expires', + 'path': 'Path', + 'comment': 'Comment', + 'domain': 'Domain', + 'max_age': 'Max-Age', + 'secure': 'Secure', + 'httponly': 'HttpOnly', + 'version': 'Version', + 'samesite': 'SameSite' + } + def __init__(self, app, request, body=None, headers={}, cookies={}, status=200, content_type='text/html'): # server objects @@ -110,6 +123,8 @@ class Response: data.update(kwargs) for k,v in data.items(): + k = self.cookie_keys.get(k, k) + if k.lower() == 'max-age': if isinstance(v, timedelta): v = int(v.total_seconds()) @@ -118,13 +133,16 @@ class Response: raise TypeError('Max-Age must be an integer or timedelta') elif k.lower() == 'expires': - if isinstance(v, datetime): - v = v.strftime('%a, %d-%b-%Y %T GMT') + if isinstance(v, str): + v = datetime.strptime(v, '%a, %d-%b-%Y %T GMT') - elif not isinstance(v, str): + elif not isinstance(v, datetime): raise TypeError('Expires must be a string or datetime') - self.cookies[key][k] = v + try: + self.cookies[key][k] = v + except KeyError as e: + izzylog.error('Invalid cookie key:', k) def get_cookie(self, key): @@ -140,7 +158,7 @@ class Response: del self.cookies[key] - def template(self, tplfile, context={}, headers={}, status=200, content_type='text/html', cookies={}, pprint=False): + def template(self, tplfile, context={}, headers={}, status=200, content_type='text/html', pprint=False): self.status = status context.update({ 'response': self, @@ -148,7 +166,7 @@ class Response: }) html = self.app.template.render(tplfile, context, request=self.request, pprint=pprint) - return self.html(html, headers=headers, status=status, content_type=content_type, cookies=cookies) + return self.html(html, headers=headers, status=status, content_type=content_type) def error(self, message, status=500, **kwargs): @@ -158,13 +176,13 @@ class Response: return self.template('error.haml', {'error_message': message}, status=status, **kwargs) - def json(self, body={}, headers={}, status=200, content_type='application/json', cookies={}): + def json(self, body={}, headers={}, status=200, content_type='application/json'): body = json.dumps(body) - return self.get_response(body, headers, status, content_type, cookies) + return self.get_response(body, headers, status, content_type) - def text(self, body, headers={}, status=200, content_type='text/plain', cookies={}): - return self.get_response(body, headers, status, content_type, cookies) + def text(self, body, headers={}, status=200, content_type='text/plain'): + return self.get_response(body, headers, status, content_type) def html(self, *args, **kwargs): @@ -174,24 +192,26 @@ class Response: def css(self, *args, **kwargs): self.content_type = 'text/css' - return self.text.text(*args, **kwargs) + return self.text(*args, **kwargs) def javascript(self, *args, **kwargs): self.content_type = 'application/javascript' - return self.text.text(*args, **kwargs) + return self.text(*args, **kwargs) def activitypub(self, *args, **kwargs): self.content_type = 'application/activity+json' - return self.text.text(*args, **kwargs) + return self.text(*args, **kwargs) def redir(self, path, status=302, headers={}): - return sanic.response.redirect(path, status=status, headers={}) + headers.update(dict(location=path)) + return self.text(body=None, status=status, headers=headers) + #return sanic.response.redirect(path, status=status, headers={}) - def set_data(self, body=None, headers={}, status=200, content_type='text/html', cookies={}): + def set_data(self, body=None, headers={}, status=200, content_type='text/html'): ctype = self.content_types.get(content_type, content_type) self.body = body diff --git a/http_server/izzylib/http_server/view.py b/http_server/izzylib/http_server/view.py index 0eaa691..5db3de3 100644 --- a/http_server/izzylib/http_server/view.py +++ b/http_server/izzylib/http_server/view.py @@ -48,6 +48,14 @@ class Manifest(View): return response.json(data) +class Robots(View): + paths = ['/robots.txt'] + + async def get(self, request, response): + data = '# Disallow all\nUser-agent: *\nDisallow: /' + return response.text(data) + + class Style(View): paths = ['/framework/style.css'] diff --git a/http_server/setup.py b/http_server/setup.py index 46a3668..d3dd724 100644 --- a/http_server/setup.py +++ b/http_server/setup.py @@ -5,6 +5,7 @@ from setuptools import setup, find_namespace_packages requires = [ 'sanic>=20.12.3', 'sanic-cors>=1.0.0', + 'envbash>=1.0.0' ] diff --git a/sql/izzylib/sql/__init__.py b/sql/izzylib/sql/__init__.py index 5228cfa..3aa54d0 100644 --- a/sql/izzylib/sql/__init__.py +++ b/sql/izzylib/sql/__init__.py @@ -1,2 +1,6 @@ -from .generic import SqlColumn, CustomRows, SqlSession, SqlDatabase, Tables +# old sql classes +from .generic import SqlColumn, CustomRows, SqlSession, SqlDatabase, Tables, OperationalError, ProgrammingError from .sqlite_server import SqliteClient, SqliteColumn, SqliteServer, SqliteSession + +from .database import Database, Session +from .queries import Column, Insert, Select, Table, Tables, Update diff --git a/sql/izzylib/sql/config.py b/sql/izzylib/sql/config.py new file mode 100644 index 0000000..8202a1b --- /dev/null +++ b/sql/izzylib/sql/config.py @@ -0,0 +1,100 @@ +import importlib, sqlite3, ssl + +from getpass import getuser +from izzylib import DotDict, Path, izzylog + + +defaults = { + 'name': (None, str), + 'host': (None, str), + 'port': (None, int), + 'username': (getuser(), str), + 'password': (None, str), + 'ssl': ('allow', str), + 'ssl_context': (ssl.create_default_context(), ssl.SSLContext), + 'ssl_key': (None, Path), + 'ssl_cert': (None, Path), + 'max_connections': (25, int), + 'type': ('sqlite', str), + 'module': (sqlite3, None), + 'mod_name': ('sqlite3', str), + 'timeout': (5, int), + 'args': ([], list), + 'kwargs': ({}, dict) +} + +modtypes = { + 'sqlite': ['sqlite3'], + 'postgresql': ['pg8000', 'psycopg2', 'psycopg3', 'pgdb'], + 'mysql': ['mysqldb', 'trio_mysql'], + 'mssql': ['pymssql', 'adodbapi'] +} + +sslmodes = ['disable', 'allow', 'prefer', 'require', 'verify-ca', 'verify-full'] + + +class Config(DotDict): + def __init__(self, **kwargs): + super().__init__({k: v[0] for k,v in defaults.items()}) + + module = kwargs.pop('module', None) + + if module: + self.parse_module(module) + + self.update(kwargs) + + if self.ssl != 'disable' and (self.ssl_key or self.ssl_cert): + self.ssl_context.load_cert_chain(self.ssl_cert, self.ssl_key) + + + def __setitem__(self, key, value): + if key not in defaults: + raise KeyError(f'Invalid config option: {key}') + + valtype = defaults[key][1] + + if valtype and value and not isinstance(value, valtype): + raise TypeError(f'{key} should be a {valtype}, not a {value.__class__.__name__}') + + if key == 'ssl' and value == True: + value = ssl.create_default_context() + + super().__setitem__(key, value) + + + def parse_module(self, name): + module = None + module_type = None + module_name = None + + if name == 'sqlite3': + name = 'sqlite' + + for mtype, modules in modtypes.items(): + if name == mtype: + module_type = name + + for mod in modules: + try: + module = importlib.import_module(mod) + module_name = mod + break + except ImportError: + izzylog.verbose(f'Database module not installed:', mod) + + elif name in modules: + try: + module = importlib.import_module(name) + module_type = mtype + module_name = name + break + except ImportError: + izzylog.error(f'Database module not installed:', name) + + if None in (module, module_name, module_type): + raise ValueError(f'Failed to find module for {name}') + + self.module = module + self.mod_name = module_name + self.type = module_type diff --git a/sql/izzylib/sql/database.py b/sql/izzylib/sql/database.py new file mode 100644 index 0000000..2f2ce9e --- /dev/null +++ b/sql/izzylib/sql/database.py @@ -0,0 +1,360 @@ +import sqlite3, traceback + +from functools import partial +from getpass import getuser +from izzylib import DotDict, izzylog, boolean, random_gen + +from . import error +from .config import Config +from .queries import Column, Delete, Insert, Select, Table, Tables, Update + + +class Database: + def __init__(self, tables=None, **kwargs): + self.tables = tables + self.cfg = Config(**kwargs) + self.sessions = DotDict() + + + @property + def session(self): + return self.get_session(False) + + + @property + def session_trans(self): + return self.get_session(True) + + + def connect(self, sid, session): + if len(self.sessions) >= self.cfg.max_connections: + raise error.MaxConnectionsError(f'Cannot start a new session with id {sid}. Reach max connection count of {self.cfg.max_connections}.') + + self.sessions[sid] = session + + + def disconnect(self, sid): + self.sessions[sid].disconnect() + del self.sessions[sid] + + + def disconnect_all(self): + sids = [] + + for sid in self.sessions.keys(): + sids.append(sid) + + for sid in sids: + self.disconnect(sid) + + + def get_session(self, trans=True): + session = Session(self, trans) + self.sessions[session.id] = session + return session + + + def execute(self, *args): + with self.session as s: + s.execute(*args) + + + def load_tables(self, path): + self.tables = Tables.new_from_json_file(path) + + + def pre_setup(self): + if self.cfg.type != 'postgresql': + izzylog.verbose(f'Database not supported for pre_setup: {self.cfg.type}') + return + + original_database = self.cfg.name + self.cfg.name = 'postgres' + + with self.session as s: + s.conn.autocommit = True + s.rollback() + + if original_database not in s.get_databases(): + #s.execute('SET AUTOCOMMIT = OFF') + s.cursor.execute(f'CREATE DATABASE {original_database}') + + s.conn.autocommit = False + + self.cfg.name = original_database + + + def set_row_class(self, table, row_class): + pass + + +class Session: + def __init__(self, db, trans): + self.id = random_gen() + self.db = db + self.cfg = db.cfg + self.trans = trans + self.trans_state = False + self.conn = None + self.cursor = None + + + def __del__(self): + try: + izzylog.verbose('Deleting session:', self.id) + except ModuleNotFoundError: + if izzylog.get_config('level') >= 20: + print('[izzylib] VERBOSE: Deleting session:', self.id) + + self.db.sessions.pop(self.id, None) + + if self.conn: + self.disconnect() + + + def __enter__(self): + self.connect() + + if self.trans: + self.begin() + + return self + + + def __exit__(self, exc_type, exc_value, exc_traceback): + if exc_traceback: + self.rollback() + + else: + self.commit() + + self.disconnect() + self.db.disconnect(self.id) + + + def connect(self): + if self.conn: + return + + self.db.connect(self.id, self) + + if self.cfg.type == 'sqlite': + self.conn = self.cfg.module.connect(self.cfg.name, self.cfg.timeout, check_same_thread=True) + + elif self.cfg.type == 'postgresql': + options = dict( + host = self.cfg.host or '/var/run/postgresql', + port = self.cfg.port or 5432, + database = self.cfg.name or 'postgresql', + user = self.cfg.username or getuser(), + password = self.cfg.password, + ) + + if self.cfg.mod_name == 'pg8000': + if options['host'] in [None, '/var/run/postgresql']: + port = options.pop('port') + options['unix_sock'] = options.pop('host') + f'/.s.PGSQL.{port}' + + ## SSL is a pain in the ass tbh. Gonna deal with this later + #if self.cfg.mod_name == 'pg8000': + #options['sslmode'] = self.cfg.ssl + #options['ssl_context'] = self.cfg.ssl_context + + #elif self.cfg.mod_name == 'psycopg2': + #options['sslcert'] = self.cfg.ssl_cert + #options['sslkey'] = self.cfg.ssl_key + + self.conn = self.cfg.module.connect(**options) + + else: + raise error.DatabaseNotSupportedError(f'Database not supported yet: {self.cfg.type}') + + try: + self.conn.autocommit = False + except: + izzylog.verbose('Failed to turn off autocommit') + + self.cursor = self.conn.cursor() + + + def disconnect(self): + if not self.conn: + return + + self.cursor.close() + self.conn.close() + + self.cursor = None + self.conn = None + + + def begin(self): + if self.trans_state: + return + + #self.conn.begin() + self.execute('BEGIN TRANSACTION') + self.trans_state = True + + + def rollback(self): + if not self.trans_state: + return + + self.conn.rollback() + #self.execute('ROLLBACK TRANSACTION') + self.trans_state = False + + + def commit(self): + if not self.trans_state: + return + + self.conn.commit() + #self.execute('COMMIT TRANSACTION') + self.trans_state = False + + + ## data management functions + def execute(self, string, values=[]): + if any(map(string.lower().startswith, ['insert', 'update', 'remove', 'create', 'drop'])) and not self.trans_state: + raise error.NoTransactionError('Please start a transaction with "session.begin()" before using a write command.') + + self.cursor.execute(string, values) + return self.cursor + + + def fetch(self, table, single=True, **kwargs): + rows = [] + data = Select(table, type=self.cfg.type, **kwargs).exec(self) + + for line in data: + row = Row(table, self.cursor.description, line) + + if single: + return row + + rows.append(row) + + return rows if not single else None + + + def search(self, table, **kwargs): + return self.fetch(table, single=False, **kwargs) + + + def insert(self, table, **kwargs): + if not self.trans_state: + raise error.NoTransactionError('Please start a transaction with "session.begin()" before using a write command.') + + Insert(table, type=self.cfg.type, **kwargs).exec(self) + return self.fetch(table, **kwargs) + + + def update(self, table, rowid, **kwargs): + if not self.trans_state: + raise error.NoTransactionError('Please start a transaction with "session.begin()" before using a write command.') + + Update(table, rowid, type=self.cfg.type, **kwargs).exec(self) + return self.fetch(table, id=rowid) + + + def delete(self, table, **kwargs): + if not self.trans_state: + raise error.NoTransactionError('Please start a transaction with "session.begin()" before using a write command.') + + Delete(table, type=self.cfg.type, **kwargs).exec(self) + + + ## helper functions + def get_columns(self, table): + if table not in self.get_tables(): + raise KeyError(f'Not an existing table: {table}') + + if self.cfg.type == 'sqlite': + rows = self.execute(f'PRAGMA table_info({table})') + return [row[1] for row in rows] + + elif self.cfg.type == 'postgresql': + rows = self.execute(f"SELECT column_name FROM information_schema.columns WHERE table_name = '{table}'") + return [row[0] for row in rows] + + else: + raise error.DatabaseNotSupportedError(f'Database not supported yet: {self.cfg.type}') + + + def get_tables(self): + if self.cfg.type == 'sqlite': + rows = self.execute("SELECT name FROM sqlite_master WHERE type IN ('table','view') and name NOT LIKE 'sqlite_%'") + + elif self.cfg.type == 'postgresql': + rows = self.execute("SELECT table_name FROM information_schema.tables WHERE table_schema = 'public' ORDER BY table_name") + + else: + raise error.DatabaseNotSupportedError(f'Database not supported yet: {self.cfg.type}') + + return [row[0] for row in rows] + + + def get_databases(self): + if self.cfg.type == 'sqlite': + izzylog.verbose('This function is useless with sqlite') + return + + elif self.cfg.type == 'postgresql': + databases = [row[0] for row in self.execute('SELECT datname FROM pg_database')] + + else: + raise error.DatabaseNotSupportedError(f'Database not supported yet: {self.cfg.type}') + + return databases + + + def cursor_description(self): + return [row[0] for row in self.cursor.description] + + + def setup_database(self): + if not self.db.tables: + raise ValueError('Tables have not been specified.') + + current_tables = self.get_tables() + + for name, table in self.db.tables.items(): + if name in current_tables: + izzylog.verbose(f'Skipping table creation since it already exists: {name}') + continue + + izzylog.verbose(f'Creating table: {name}') + self.execute(table.build(self.cfg.type)) + + +class Row(DotDict): + def __init__(self, table, keys, values): + self._db = None + self._table = table + + super().__init__() + + for idx, key in enumerate([key[0] for key in keys]): + self[key] = values[idx] + + + def update(self, data): + for k, v in data.items(): + if k not in self: + raise KeyError(f'Not a column for {self._table}') + + self[k] = v + + + def delete(self): + with self._db.session as s: + s.delete(self._table, id=self.id) + + + def update(self, **kwargs): + self.update(kwargs) + + with self._db.session as s: + s.update(self._table, id=self.id, **kwargs) diff --git a/sql/izzylib/sql/error.py b/sql/izzylib/sql/error.py new file mode 100644 index 0000000..4c60314 --- /dev/null +++ b/sql/izzylib/sql/error.py @@ -0,0 +1,10 @@ +class MaxConnectionsError(Exception): + 'raise when the max amount of connections has been reached' + + +class NoTransactionError(Exception): + 'raise when a write command is executed outside a transaction' + + +class DatabaseNotSupportedError(Exception): + 'raise when the action being performed is not supported by the database in use' diff --git a/sql/izzylib/sql/generic.py b/sql/izzylib/sql/generic.py index 48d01fe..aa313ed 100644 --- a/sql/izzylib/sql/generic.py +++ b/sql/izzylib/sql/generic.py @@ -3,7 +3,7 @@ import json, sys, threading, time from contextlib import contextmanager from datetime import datetime from sqlalchemy import create_engine, ForeignKey, MetaData, Table -from sqlalchemy import Column, types as Types +from sqlalchemy import Column as sqlalchemy_column, types as Types from sqlalchemy.exc import OperationalError, ProgrammingError from sqlalchemy.orm import scoped_session, sessionmaker @@ -57,6 +57,12 @@ class SqlDatabase: engine_string += f'/{database}' engine_kwargs['connect_args'] = {'check_same_thread': False} + elif dbtype == 'postgresql': + ssl_context = kwargs.get('ssl') + + if ssl_context: + engine_kwargs['ssl_context'] = ssl_context + else: user = kwargs.get('user') password = kwargs.get('pass') @@ -124,9 +130,9 @@ class SqlDatabase: self.table_names = tables.keys() - def execute(self, *args, **kwargs): + def execute(self, string, values=[]): with self.session as s: - return s.execute(*args, **kwargs) + s.execute(string, values) class SqlSession(object): @@ -267,7 +273,7 @@ class SqlSession(object): if not rowid or not table: raise ValueError('Missing row ID or table') - row = self.execute(f'DELETE FROM {table} WHERE id={rowid}') + self.execute(f'DELETE FROM {table} WHERE id={rowid}') def drop_table(self, name): @@ -284,12 +290,28 @@ class SqlSession(object): self.drop_table(table) + def get_columns(self, table): + if table not in self.get_tables(): + raise KeyError(f'Not an existing table: {table}') + + rows = self.execute('PRAGMA table_info(user)') + return [row[1] for row in rows] + + def get_tables(self): rows = self.execute("SELECT name FROM sqlite_master WHERE type IN ('table','view') and name NOT LIKE 'sqlite_%'") return [row[0] for row in rows] - def append_column(self, tbl, col): + def append_column(self, table, column): + if column.name in self.get_columns(table): + logging.warning(f'Table "{table}" already has column "{column.name}"') + return + + self.execute(f'ALTER TABLE {table} ADD COLUMN {column.compile()}') + + + def append_column2(self, tbl, col): table = self.table[tbl] try: @@ -301,7 +323,7 @@ class SqlSession(object): columns = [row[1] for row in self.execute(f'PRAGMA table_info({tbl})')] - if col in columns: + if col in self.get_columns(tbl): izzylog.info(f'Column "{col}" already exists') return @@ -436,29 +458,51 @@ class Tables(DotDict): def __setup_table(self, name, table): - columns = [col if type(col) == Column else Column(*col.get('args'), **col.get('kwargs')) for col in table] + columns = [col if type(col) == SqlColumn else SqlColumn(*col.get('args'), **col.get('kwargs')) for col in table] self[name] = Table(name, self.meta, *columns) -def SqlColumn(name, stype=None, fkey=None, **kwargs): - if not stype and not kwargs: - if name == 'id': - return Column('id', SqlTypes['integer'], primary_key=True, autoincrement=True) +class SqlColumn(sqlalchemy_column): + def __init__(self, name, stype=None, fkey=None, **kwargs): + if not stype and not kwargs: + if name == 'id': + stype = 'integer' + kwargs['primary_key'] = True + kwargs['autoincrement'] = True - elif name == 'timestamp': - return Column('timestamp', SqlTypes['datetime']) + elif name == 'timestamp': + stype = 'datetime' - raise ValueError('Missing column type and options') + else: + raise ValueError('Missing column type and options') - else: - try: - stype = stype or 'string' - options = [name, SqlTypes[stype.lower()]] + stype = (stype.lower() if type(stype) == str else stype) or 'string' - except KeyError: - raise KeyError(f'Invalid SQL data type: {stype}') + if type(stype) == str: + try: + stype = SqlTypes[stype.lower()] + + except KeyError: + raise KeyError(f'Invalid SQL data type: {stype}') + + options = [name, stype] if fkey: options.append(ForeignKey(fkey)) - return Column(*options, **kwargs) + super().__init__(*options, **kwargs) + + + def compile(self): + sql = f'{self.name} {self.type}' + + if not self.nullable: + sql += ' NOT NULL' + + if self.primary_key: + sql += ' PRIMARY KEY' + + if self.unique: + sql += ' UNIQUE' + + return sql diff --git a/sql/izzylib/sql/queries.py b/sql/izzylib/sql/queries.py new file mode 100644 index 0000000..b780e9b --- /dev/null +++ b/sql/izzylib/sql/queries.py @@ -0,0 +1,415 @@ +from datetime import datetime +from functools import partial +from izzylib import DotDict, Path + +from .types import BaseType, Type + + +placeholders = dict( + sqlite = '?', + postgresql = '%s' +) + + +## Data queries +class Delete: + def __init__(self, table, type='sqlite', **kwargs): + self.table = table + self.placeholder = placeholders[type] + self.keys = [] + self.values = [] + + for k,v in kwargs.items(): + self.keys.append(k) + self.values.append(v) + + + def __str__(self): + self.build(embed_values=True) + + + def build(self, comp_type='AND', embed_values=False): + sql = 'DELETE FROM {table} WHERE {kstring}' + + if not embed_values: + kstring = f' {comp_type.upper()} '.join([f'{k} = {self.placeholder}' for k in self.keys]) + return sql.format(table=self.table, kstring=kstring), self.values + + values = [] + + for idx, value in enumerate(self.values): + if type(value) == str: + values.append(f"{self.keys[idx]} = '{value}'") + + else: + values.append(f"{self.keys[idx]} = {value}") + + kstring = ','.join(values) + return sql.format(table=self.table, kstring=kstring, rowid=self.rowid) + + + def exec(self, session, comp_type='AND'): + return session.execute(*self.build(comp_type)) + + +class Insert: + def __init__(self, table, type='sqlite', **kwargs): + self.table = table + self.placeholder = placeholders[type] + self.keys = [] + self.values = [] + + for k, v in kwargs.items(): + self.keys.append(k) + self.values.append(v) + + + def __str__(self): + return self.build(embed_values=True) + + + def build(self, embed_values=False): + kstring = ','.join(self.keys) + + if not embed_values: + vstring = ','.join([self.placeholder for k in self.keys]) + return f'INSERT INTO {self.table} ({kstring}) VALUES({vstring})', self.values + + else: + vstring = ','.join(self.values) + return f'INSERT INTO {self.table} ({kstring}) VALUES({vstring})' + + + def exec(self, session): + return session.execute(*self.build()) + + +class Select: + def __init__(self, table, columns=[], type='sqlite', **kwargs): + self.placeholder = placeholders[type] + self.columns = columns + self.table = table + self.where = [] + self.where_build = [] + self._order = [] + self.keys = [] + self.values = [] + + self.equals = partial(self.__comparison, '=') + self.less = partial(self.__comparison, '<') + self.greater = partial(self.__comparison, '>') + self.like = partial(self.__comparison, 'LIKE') + + for k,v in kwargs.items(): + self.equals(k, v) + + + def __str__(self): + return self.build(embed_values=True) + + + def __comparison(self, comp, key, value): + self.values.append(value) + self.keys.append(key) + self.where.append(f'{key} {comp.upper()} {self.placeholder}') + self.where_build.append(f"{key} {comp.upper()} '{value}'" if type(key) == str else f"{key} {comp.upper()} {value}") + return self + + + def order(self, column, asc=True): + self._order = [column, 'ASC' if asc else 'DESC'] + return self + + + def build(self, comp_type='AND', embed_values=False): + if not self.columns: + cols = '*' + + else: + cols = ','.join('columns') + + sql_query = f'SELECT {cols} FROM {self.table}' + + if self.where: + where = f' {comp_type.upper()} '.join(self.where if not embed_values else self.where_build) + sql_query += f' WHERE {where}' + + if self._order: + col, order = self._order + sql_query += f' ORDER BY {col} {order}' + + if embed_values: + return sql_query + + return sql_query, self.values + + + def exec(self, session, comp_type='AND'): + return session.execute(*self.build(comp_type)) + + +class Update: + def __init__(self, table, rowid, type='sqlite', **kwargs): + self.placeholder = placeholders[type] + self.table = table + self.rowid = rowid + self.keys = [] + self.values = [] + + for k,v in kwargs.items(): + self.keys.append(k) + self.values.append(v) + + + def __str__(self): + return self.build(embed_values=True) + + + def build(self, embed_values=False): + sql = 'UPDATE {table} SET {kstring} WHERE id={rowid}' + + if not embed_values: + kstring = ','.join([f'{k} = {self.placeholder}' for k in self.keys]) + return sql.format(table=self.table, kstring=kstring, rowid=self.rowid), self.values + + values = [] + + for idx, value in enumerate(self.values): + if type(value) == str: + values.append(f"{self.keys[idx]} = '{value}'") + + else: + values.append(f"{self.keys[idx]} = {value}") + + kstring = ','.join(values) + return sql.format(table=self.table, kstring=kstring, rowid=self.rowid) + + + def exec(self, session): + return session.execute(*self.build()) + + +## Database objects +class Column: + def __init__(self, name, type='STRING', unique=False, nullable=True, default=None, primary_key=False, autoincrement=False, foreign_key=None): + self.name = name + self.type = type + self.nullable = nullable + self.default = default + self.primary_key = primary_key + self.autoincrement = autoincrement + self.unique = unique + + if any(map(isinstance, [foreign_key], [list, tuple, set])): + self.foreign_key = foreign_key + + else: + self.foreign_key = foreign_key.split('.') if foreign_key else None + + if autoincrement: + self.primary_key = True + self.type = Type['INTEGER'] + + if isinstance(self.type, BaseType): + self.type = self.type.name + + else: + if self.type.upper() in Type.keys(): + self.type = self.type.upper() + + else: + raise TypeError(f'Invalid SQL type: {self.type}') + + if foreign_key and len(self.foreign_key) != 2: + raise ValueError('Invalid foreign key. Must be in the format "table.column".') + + + def __str__(self): + return self.build() + + + def build(self, dbtype='sqlite'): + if dbtype == 'postgresql': + if self.type.lower() == 'string': + self.type = 'TEXT' + + elif self.type.lower() == 'datetime': + self.type = 'TIMESTAMPTZ' + + if self.autoincrement: + self.type = 'SERIAL' + self.autoincrement = False + + sql = f'{self.name} {self.type}' + + if self.primary_key: + sql += ' PRIMARY KEY' + + if self.autoincrement: + sql += ' AUTOINCREMENT' + + if self.unique: + sql += ' UNIQUE' + + if not self.nullable: + sql += ' NOT NULL' + + if self.default: + def_type = type(self.default) + + if self.default == 'CURRENT_TIMESTAMP': + if dbtype == 'sqlite': + sql += " DEFAULT (datetime('now', 'localtime'))" + + elif dbtype == 'postgresql': + sql += ' DEFAULT now()' + + else: + sql += f' DEFAULT {datetime.now().timestamp()}' + + elif def_type == str: + sql += f" DEFAULT '{self.default}'" + + elif def_type in [int, float]: + sql += f' DEFAULT {self.default}' + + elif def_type == bool and dbtype == 'sqlite': + sql += f' DEFAULT {int(self.default)}' + + else: + sql += f' DEFAULT {self.default}' + + print(sql) + return sql + + + def json(self): + return DotDict({ + 'type': self.type, + 'nullable': self.nullable, + 'default': self.default, + 'primary_key': self.primary_key, + 'autoincrement': self.autoincrement, + 'unique': self.unique, + 'foreign_key': self.foreign_key + }) + + +class Table(DotDict): + def __init__(self, name, *columns): + super().__init__() + self._name = name + self._foreign_keys = {} + + self.add_column(Column('id', autoincrement=True)) + + for column in columns: + self.add_column(column) + + + def __str__(self): + return self.build() + + + # this'll be useful later + def __call__(self, *args, **kwargs): + pass + + + @property + def name(self): + return self._name + + + def add_column(self, column): + self[column.name] = column + + if column.foreign_key: + self._foreign_keys[column.name] = column.foreign_key + + + def build(self, dbtype='sqlite'): + column_string = ',\n'.join([f'\t{col.build(dbtype)}' for col in self.values()]) + + if self._foreign_keys: + column_string += ',\n' + column_string += ',\n'.join([f'\tFOREIGN KEY ({column}) REFERENCES {key[0]} ({key[1]})' for column, key in self._foreign_keys.items()]) + + return f'''CREATE TABLE {self.name} ( +{column_string} +);''' + + + def json(self): + data = {} + + for name, column in self.items(): + data[name] = column.json() + + return data + + +class Tables(DotDict): + def __init__(self, *tables, data={}): + super().__init__() + + for table in tables: + self.add_table(table) + + if data: + self.from_dict(data) + + + def __str__(self): + return self.build() + + + @classmethod + def new_from_json_file(cls, path): + return cls(data=DotDict.new_from_json_file(path)) + + + def add_table(self, table): + self[table.name] = table + + + def build(self): + return '\n\n'.join([str(table) for table in self.values()]) + + + def load_json(self, path): + data = DotDict() + data.load_json(path) + + self.from_dict(data) + + + def save_json(self, path, indent='\t'): + self.to_dict().save_json(path, indent=indent) + + + def from_dict(self, data): + for name, columns in data.items(): + table = Table(name) + + for col, kwargs in columns.items(): + table.add_column(Column(col, + type = kwargs.get('type', 'STRING'), + nullable = kwargs.get('nullable', True), + default = kwargs.get('default'), + primary_key = kwargs.get('primary_key', False), + autoincrement = kwargs.get('autoincrement', False), + unique = kwargs.get('unique', False), + foreign_key = kwargs.get('foreign_key') + )) + + self.add_table(table) + + + def to_dict(self): + data = DotDict() + + for name, table in self.items(): + data[name] = table.json() + + return data diff --git a/sql/izzylib/sql/row.py b/sql/izzylib/sql/row.py new file mode 100644 index 0000000..2a5416d --- /dev/null +++ b/sql/izzylib/sql/row.py @@ -0,0 +1,19 @@ +from izzylib import DotDict + + +class DbRow(DotDict): + def __init__(self, table, keys, values): + self.table = table + + super().__init__() + + for idx, key in enumerate(keys): + self[key] = values[idx] + + + def delete(self): + pass + + + def update(self, **kwargs): + pass diff --git a/sql/izzylib/sql/types.py b/sql/izzylib/sql/types.py new file mode 100644 index 0000000..e53b400 --- /dev/null +++ b/sql/izzylib/sql/types.py @@ -0,0 +1,19 @@ +from enum import Enum +from izzylib import DotDict + + +class BaseType(Enum): + INTEGER = int + TEXT = str + BLOB = bytes + REAL = float + NUMERIC = float + + +Type = DotDict( + **{v: BaseType.INTEGER for v in ['INT', 'INTEGER', 'TINYINT', 'SMALLINT', 'MEDIUMINT', 'BIGINT', 'UNSIGNED BIG INT', 'INT2', 'INT8']}, + **{v: BaseType.TEXT for v in ['CHARACTER', 'VARCHAR', 'VARYING CHARACTER', 'NCHAR', 'NATIVE CHARACTER', 'NVARCHAR', 'TEXT', 'CLOB', 'STRING', 'JSON']}, + **{v: BaseType.BLOB for v in ['BYTES', 'BLOB']}, + **{v: BaseType.REAL for v in ['REAL', 'DOUBLE', 'DOUBLE PRECISION', 'FLOAT']}, + **{v: BaseType.NUMERIC for v in ['NUMERIC', 'DECIMAL', 'BOOLEAN', 'DATE', 'DATETIME']} +) From 5efee0ffd208700f9f8aa2fe6c94d6048b977a1f Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Thu, 2 Sep 2021 17:27:05 -0400 Subject: [PATCH 57/74] template: merge context and globals before context function, http_server: start adding fediverse views --- README.md | 6 ++- .../izzylib/http_server/application.py | 17 +++++-- http_server/izzylib/http_server/view.py | 48 +++++++++++++++++++ template/izzylib/template/__init__.py | 15 ++++-- 4 files changed, 77 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 26a4023..4fb66f8 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,10 @@ You only need to install the base and whatever sub-modules you want to use $(venv)/bin/python -m pip install -e "git+https://git.barkshark.xyz/izaliamae/izzylib.git@rework#egg=izzylib-base&subdirectory=base" + $(venv)/bin/python -m pip install -e "git+https://git.barkshark.xyz/izaliamae/izzylib.git@rework#egg=izzylib-dbus&subdirectory=dbus" + + $(venv)/bin/python -m pip install -e "git+https://git.barkshark.xyz/izaliamae/izzylib.git@rework#egg=izzylib-hasher&subdirectory=hasher" + $(venv)/bin/python -m pip install -e "git+https://git.barkshark.xyz/izaliamae/izzylib.git@rework#egg=izzylib-http-server&subdirectory=http_server" $(venv)/bin/python -m pip install -e "git+https://git.barkshark.xyz/izaliamae/izzylib.git@rework#egg=izzylib-http-requests-client&subdirectory=requests_client" @@ -22,7 +26,7 @@ You only need to install the base and whatever sub-modules you want to use ### From Source - $(venv)/bin/python setup.py install ['all' or a combination of these: http_server requests_client sql template tinydb] + $(venv)/bin/python setup.py install ['all' or a combination of these: dbus hasher http_server requests_client sql template tinydb] ## Documentation diff --git a/http_server/izzylib/http_server/application.py b/http_server/izzylib/http_server/application.py index 9502747..3e08bcd 100644 --- a/http_server/izzylib/http_server/application.py +++ b/http_server/izzylib/http_server/application.py @@ -30,7 +30,7 @@ log_ext_ignore = [ frontend = Path(__file__).resolve.parent.join('frontend') class Application(sanic.Sanic): - def __init__(self, **kwargs): + def __init__(self, class_views=[], **kwargs): self.cfg = Config(**kwargs) super().__init__(self.cfg.name, request_class=self.cfg.request_class) @@ -45,6 +45,7 @@ class Application(sanic.Sanic): self.cfg.tpl_autoescape ) + self.template.add_env('app', self) self.template.add_env('cfg', self.cfg) self.template.add_env('len', len) @@ -56,6 +57,9 @@ class Application(sanic.Sanic): self.static('/favicon.ico', frontend.join('static/icon64.png')) self.static('/framework/static', frontend.join('static')) + for view in class_views: + self.add_class_route(view) + self.add_error_handler(MissingTemplateError) self.add_error_handler(GenericError) @@ -64,6 +68,9 @@ class Application(sanic.Sanic): signal.signal(signal.SIGQUIT, self.finish) signal.signal(signal.SIGTERM, self.finish) + ## compat + self.start = self.run + def add_class_route(self, cls): for route in cls.paths: @@ -100,10 +107,12 @@ class Application(sanic.Sanic): return handler - def start(self): + def run(self): # register built-in middleware now so they're last in the chain self.add_middleware(Headers) - self.add_middleware(AccessLog) + + if self.cfg.access_log: + self.add_middleware(AccessLog) msg = f'Starting {self.cfg.name} at {self.cfg.host}:{self.cfg.port}' @@ -111,7 +120,7 @@ class Application(sanic.Sanic): msg += f' with {self.cfg.workers} workers' logging.info(msg) - self.run( + super().run( host = self.cfg.listen, port = self.cfg.port, workers = self.cfg.workers, diff --git a/http_server/izzylib/http_server/view.py b/http_server/izzylib/http_server/view.py index 5db3de3..887d376 100644 --- a/http_server/izzylib/http_server/view.py +++ b/http_server/izzylib/http_server/view.py @@ -17,6 +17,8 @@ class View(HTTPMethodView): return handler(request, Response(self.app, request), *args, **kwargs) +### Frontend Template Views ### + class Manifest(View): paths = ['/framework/manifest.json'] @@ -62,3 +64,49 @@ class Style(View): async def get(self, request, response): return response.template('base.css', content_type='text/css') + +### ActivityPub Views ### + +class Actor(View): + paths = ['/actor', '/actor/', '/inbox'] + + def get(self, request, response, actor=None): + if not actor: + actor = 'system' + + pass + + + def post(self, request, response, actor=None): + if not actor: + actor = 'system' + + pass + + +class Nodeinfo(View): + paths = ['/nodeinfo/2.0.json'] + + def get(self, request, response): + pass + + +class Webfinger(View): + paths = ['/.well-known/webfinger'] + + def get(self, request, response): + pass + + +class WkHostMeta(View): + paths = ['/.well-known/host-meta'] + + def get(self, request, response): + pass + + +class WkNodeinfo(View): + paths = ['/.well-known/nodeinfo'] + + def get(self, request, response): + pass diff --git a/template/izzylib/template/__init__.py b/template/izzylib/template/__init__.py index 108c4b7..25bf1c7 100644 --- a/template/izzylib/template/__init__.py +++ b/template/izzylib/template/__init__.py @@ -69,7 +69,7 @@ class Template(Environment): izzylog.error('Context is not callable') return - if not isinstance(context({}, {}), dict): + if not isinstance(context({}), dict): izzylog.error('Context does not return a dict or dict-like object') return @@ -113,14 +113,21 @@ class Template(Environment): self.filters.update(data) - def render(self, tplfile, context={}, headers={}, cookies={}, request=None, pprint=False): - if not isinstance(context, dict): + def render(self, tplfile, context_data={}, headers={}, cookies={}, request=None, pprint=False): + if not isinstance(context_data, dict): raise TypeError(f'context for {tplfile} not a dict: {type(context)} {context}') + context = DotDict(self.globals) + context.update(context_data) context['request'] = request if request else {'headers': headers, 'cookies': cookies} if self.func_context: - context.update(self.func_context(DotDict(context), DotDict(self.globals))) + # Backwards compat + try: + context = self.func_context(context) + + except TypeError: + context = self.func_context(context, {}) result = self.get_template(tplfile).render(context) From c2796a5075d34b6a3db98216669bae77b122b47e Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Sun, 12 Sep 2021 04:11:45 -0400 Subject: [PATCH 58/74] heck --- .../izzylib/http_server/activitypub.py | 15 ++++ .../izzylib/http_server/error_handlers.py | 2 +- .../izzylib/http_server/frontend/base.css | 82 +++++++++++-------- .../izzylib/http_server/frontend/base.haml | 20 ++--- .../izzylib/http_server/frontend/menu.haml | 2 +- http_server/izzylib/http_server/request.py | 2 +- http_server/izzylib/http_server/response.py | 4 +- http_server/izzylib/http_server/view.py | 3 +- sql/izzylib/sql/__init__.py | 4 +- sql/izzylib/sql/generic.py | 5 +- template/izzylib/template/__init__.py | 4 + 11 files changed, 89 insertions(+), 54 deletions(-) create mode 100644 http_server/izzylib/http_server/activitypub.py diff --git a/http_server/izzylib/http_server/activitypub.py b/http_server/izzylib/http_server/activitypub.py new file mode 100644 index 0000000..831ac21 --- /dev/null +++ b/http_server/izzylib/http_server/activitypub.py @@ -0,0 +1,15 @@ +from . import view + + +class ActivityPub: + def __init__(self, app): + self.app = app + self.cfg = app.cfg + + + def setup_views(self): + self.app.add_class_route(view.Actor) + self.app.add_class_route(view.Nodeinfo) + self.app.add_class_route(view.Webfinger) + self.app.add_class_route(view.WkHostMeta) + self.app.add_class_route(view.WkNodeinfo) diff --git a/http_server/izzylib/http_server/error_handlers.py b/http_server/izzylib/http_server/error_handlers.py index 602fb78..932993d 100644 --- a/http_server/izzylib/http_server/error_handlers.py +++ b/http_server/izzylib/http_server/error_handlers.py @@ -30,7 +30,7 @@ class GenericError: traceback.print_exc() try: - return response.error(msg, status) + return response.error(msg, status, pprint=True) except Exception as e: traceback.print_exc() diff --git a/http_server/izzylib/http_server/frontend/base.css b/http_server/izzylib/http_server/frontend/base.css index e61122f..40454a1 100644 --- a/http_server/izzylib/http_server/frontend/base.css +++ b/http_server/izzylib/http_server/frontend/base.css @@ -43,6 +43,7 @@ input:not([type='checkbox']), select, textarea { background-color: var(--background); border: 1px solid var(--background); box-shadow: 0 2px 2px 0 var(--shadow-color); + padding: 5px; } input:hover, select:hover, textarea:hover { @@ -195,9 +196,9 @@ details:focus, summary:focus { #content-body .title { text-align: center; - font-size: 1.5em; + font-size: 2em; font-weight: bold; - color: var(--primary) + color: var(--primary); } #footer { @@ -226,32 +227,16 @@ details:focus, summary:focus { white-space: nowrap; } -{% for name in cssfiles %} - {% include 'style/' + name + '.css' %} -{% endfor %} - - -/* responsive design */ -@media (max-width: 810px) { - body { - margin: 0; - } - - #body { - width: auto; - } +#logreg input, textarea { + display: block; + margin: 8px auto; } -@media (max-width: 610px) { - .settings .grid-container { - grid-template-columns: auto; - } - - .settings .label { - text-align: center; - } +#logreg textarea, input:not([type='submit']) { + width: 50%; } + /* Main menu */ #btn { cursor: pointer; @@ -277,7 +262,7 @@ details:focus, summary:focus { position: fixed; z-index: 5; top: 12px; - {% if menu_left %}right: calc(100% - 250px + 12px){% else %}right: 12px;{% endif %}; + {% if menu_left %}right: calc(100% - 250px + 12px){% else %}right: 12px{% endif %}; background-color: {{primary.darken(75)}}; color: {{background}}; } @@ -386,14 +371,45 @@ details:focus, summary:focus { @keyframes fadeInDown { - 0% { - opacity: 0; - transform: translateY(-1.25em); - } - 100% { - opacity: 1; - transform: translateY(0); - } + 0% { + opacity: 0; + transform: translateY(-1.25em); + } + 100% { + opacity: 1; + transform: translateY(0); + } +} + + +{% for name in cssfiles %} + {% include 'style/' + name + '.css' %} +{% endfor %} + + +/* responsive design */ +@media (max-width: 810px) { + body { + margin: 0; + } + + #body { + width: auto; + } +} + +@media (max-width: 610px) { + .settings .grid-container { + grid-template-columns: auto; + } + + .settings .label { + text-align: center; + } + + #logreg textarea, input:not([type='submit']) { + width: calc(100% - 16px); + } } diff --git a/http_server/izzylib/http_server/frontend/base.haml b/http_server/izzylib/http_server/frontend/base.haml index d2da0e6..47831c4 100644 --- a/http_server/izzylib/http_server/frontend/base.haml +++ b/http_server/izzylib/http_server/frontend/base.haml @@ -2,10 +2,10 @@ %html %head %title << {{cfg.name}}: {{page}} - %link rel='stylesheet' type='text/css' href='/framework/style.css' - %link rel='manifest' href='/framework/manifest.json' - %meta charset='UTF-8' - %meta name='viewport' content='width=device-width, initial-scale=1' + %link(rel='stylesheet' type='text/css' href='/framework/style.css') + %link(rel='manifest' href='/framework/manifest.json') + %meta(charset='UTF-8') + %meta(name='viewport' content='width=device-width, initial-scale=1') -block head %body @@ -13,10 +13,10 @@ #header.flex-container -if menu_left #btn.section - .page-title.section -> %a.title href='/' << {{cfg.name}} + .page-title.section -> %a.title(href='/') << {{cfg.name}} -else - .page-title.section -> %a.title href='/' << {{cfg.name}} + .page-title.section -> %a.title(href='/') << {{cfg.name}} #btn.section -if message @@ -34,9 +34,9 @@ -else: -for label, path_data in cfg.menu.items() -if path_data[1] == 1000 and request.user_level == 0: - .item -> %a href='{{path_data[0]}}' << {{label}} + .item -> %a(href='{{path_data[0]}}') << {{label}} -elif request.user_level >= path_data[1] - .item -> %a href='{{path_data[0]}}' << {{label}} + .item -> %a(href='{{path_data[0]}}') << {{label}} #content-body.section -block content @@ -45,6 +45,6 @@ .avatar .user .source - %a href='{{cfg.git_repo}}' target='_new' << {{cfg.name}}/{{cfg.version}} + %a(href='{{cfg.git_repo}}' target='_new') << {{cfg.name}}/{{cfg.version}} - %script type='application/javascript' src='/framework/static/menu.js' + %script(type='application/javascript' src='/framework/static/menu.js') diff --git a/http_server/izzylib/http_server/frontend/menu.haml b/http_server/izzylib/http_server/frontend/menu.haml index c883b18..20d9e66 100644 --- a/http_server/izzylib/http_server/frontend/menu.haml +++ b/http_server/izzylib/http_server/frontend/menu.haml @@ -1 +1 @@ -.item => %a(href='/') << Home +.item -> %a(href='/') << Home diff --git a/http_server/izzylib/http_server/request.py b/http_server/izzylib/http_server/request.py index 7d288f8..8ebab4d 100644 --- a/http_server/izzylib/http_server/request.py +++ b/http_server/izzylib/http_server/request.py @@ -6,7 +6,7 @@ from .misc import Headers class Request(sanic.request.Request): - def __init__(self, url_bytes, headers, version, method, transport, app, **kwargs): + def __init__(self, url_bytes, headers, version, method, transport, app): super().__init__(url_bytes, headers, version, method, transport, app) self.Headers = Headers(headers) diff --git a/http_server/izzylib/http_server/response.py b/http_server/izzylib/http_server/response.py index 5e7f5b0..31ab18b 100644 --- a/http_server/izzylib/http_server/response.py +++ b/http_server/izzylib/http_server/response.py @@ -5,6 +5,7 @@ from izzylib import DotDict, izzylog from izzylib.template import Color from sanic.compat import Header from sanic.cookies import CookieJar +from sanic.response import text as Raw class Response: @@ -171,6 +172,7 @@ class Response: def error(self, message, status=500, **kwargs): if self.request and 'json' in self.request.headers.get('accept', ''): + kwargs.pop('pprint', None) return self.json({f'error {status}': message}, status=status, **kwargs) return self.template('error.haml', {'error_message': message}, status=status, **kwargs) @@ -224,7 +226,7 @@ class Response: def get_response(self, *args, **kwargs): self.set_data(*args, **kwargs) - response = sanic.response.HTTPResponse(self.body, self.status, self.headers, self.content_type) + response = sanic.response.raw(self.body, self.status, self.headers, self.content_type) response._cookies = self.cookies return response diff --git a/http_server/izzylib/http_server/view.py b/http_server/izzylib/http_server/view.py index 887d376..0c1995b 100644 --- a/http_server/izzylib/http_server/view.py +++ b/http_server/izzylib/http_server/view.py @@ -62,7 +62,8 @@ class Style(View): paths = ['/framework/style.css'] async def get(self, request, response): - return response.template('base.css', content_type='text/css') + resp = response.template('base.css', content_type='text/css') + return resp ### ActivityPub Views ### diff --git a/sql/izzylib/sql/__init__.py b/sql/izzylib/sql/__init__.py index 3aa54d0..88638bb 100644 --- a/sql/izzylib/sql/__init__.py +++ b/sql/izzylib/sql/__init__.py @@ -2,5 +2,5 @@ from .generic import SqlColumn, CustomRows, SqlSession, SqlDatabase, Tables, OperationalError, ProgrammingError from .sqlite_server import SqliteClient, SqliteColumn, SqliteServer, SqliteSession -from .database import Database, Session -from .queries import Column, Insert, Select, Table, Tables, Update +#from .database import Database, Session +#from .queries import Column, Insert, Select, Table, Tables, Update diff --git a/sql/izzylib/sql/generic.py b/sql/izzylib/sql/generic.py index aa313ed..b83c1e9 100644 --- a/sql/izzylib/sql/generic.py +++ b/sql/izzylib/sql/generic.py @@ -46,10 +46,7 @@ class SqlDatabase: engine_string = dbtype + '://' if dbtype == 'sqlite': - try: - database = kwargs['name'] - except KeyError: - database = kwargs['database'] + database = kwargs['name'] if nfs_check(database): izzylog.error('Database file is on an NFS share which does not support locking. Any writes to the database will fail') diff --git a/template/izzylib/template/__init__.py b/template/izzylib/template/__init__.py index 25bf1c7..7f92192 100644 --- a/template/izzylib/template/__init__.py +++ b/template/izzylib/template/__init__.py @@ -129,6 +129,10 @@ class Template(Environment): except TypeError: context = self.func_context(context, {}) + if context == None: + izzylog.warning('Template context was set to "None"') + context = {} + result = self.get_template(tplfile).render(context) if pprint and any(map(tplfile.endswith, ['haml', 'html', 'xml'])): From 24ae540ea5fc9772bcac7ca4dc125d02e57af492 Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Tue, 14 Sep 2021 11:34:57 -0400 Subject: [PATCH 59/74] a lot of changes --- .../izzylib/http_server/application.py | 2 +- http_server/izzylib/http_server/config.py | 5 +++++ .../izzylib/http_server/error_handlers.py | 3 +++ .../izzylib/http_server/frontend/base.haml | 6 +++--- http_server/izzylib/http_server/middleware.py | 10 +++++++++- http_server/izzylib/http_server/misc.py | 10 ++++++++++ http_server/izzylib/http_server/request.py | 1 + http_server/izzylib/http_server/response.py | 4 ++-- .../izzylib/http_requests_client/client.py | 9 +++++---- .../izzylib/http_requests_client/signature.py | 20 ++++++++++++++----- 10 files changed, 54 insertions(+), 16 deletions(-) diff --git a/http_server/izzylib/http_server/application.py b/http_server/izzylib/http_server/application.py index 3e08bcd..7c140b8 100644 --- a/http_server/izzylib/http_server/application.py +++ b/http_server/izzylib/http_server/application.py @@ -87,7 +87,7 @@ class Application(sanic.Sanic): def add_middleware(self, middleware): mw = middleware(self) - self.register_middleware(mw.handler, mw.attach) + self.register_middleware(mw, mw.attach) def get_menu_item(self, name): diff --git a/http_server/izzylib/http_server/config.py b/http_server/izzylib/http_server/config.py index e6e508a..e7297fd 100644 --- a/http_server/izzylib/http_server/config.py +++ b/http_server/izzylib/http_server/config.py @@ -14,9 +14,11 @@ class UserLevel(IntEnum): AUTH = 1000 +# Note: sub-classing the Request class breaks things for some reason class Config(DotDict): defaults = dict( name = 'IzzyLib Http Server', + title = None, version = '0.0.1', git_repo = 'https://git.barkshark.xyz/izaliamae/izzylib', listen = 'localhost', @@ -50,6 +52,9 @@ class Config(DotDict): if kwargs.get('host') and not kwargs.get('web_host'): self.web_host = self.host + if self.name and not self.title: + self.title = self.name + def __setitem__(self, key, value): if key not in self.defaults.keys(): diff --git a/http_server/izzylib/http_server/error_handlers.py b/http_server/izzylib/http_server/error_handlers.py index 932993d..e82172b 100644 --- a/http_server/izzylib/http_server/error_handlers.py +++ b/http_server/izzylib/http_server/error_handlers.py @@ -30,6 +30,9 @@ class GenericError: traceback.print_exc() try: + if 'json' in request.headers.get('accept', ''): + return response.json(msg, status=status) + return response.error(msg, status, pprint=True) except Exception as e: diff --git a/http_server/izzylib/http_server/frontend/base.haml b/http_server/izzylib/http_server/frontend/base.haml index 47831c4..e173cc4 100644 --- a/http_server/izzylib/http_server/frontend/base.haml +++ b/http_server/izzylib/http_server/frontend/base.haml @@ -1,7 +1,7 @@ %html %head - %title << {{cfg.name}}: {{page}} + %title << {{cfg.title}}: {{page}} %link(rel='stylesheet' type='text/css' href='/framework/style.css') %link(rel='manifest' href='/framework/manifest.json') %meta(charset='UTF-8') @@ -13,10 +13,10 @@ #header.flex-container -if menu_left #btn.section - .page-title.section -> %a.title(href='/') << {{cfg.name}} + .page-title.section -> %a.title(href='/') << {{cfg.title}} -else - .page-title.section -> %a.title(href='/') << {{cfg.name}} + .page-title.section -> %a.title(href='/') << {{cfg.title}} #btn.section -if message diff --git a/http_server/izzylib/http_server/middleware.py b/http_server/izzylib/http_server/middleware.py index 8555d87..e081a2f 100644 --- a/http_server/izzylib/http_server/middleware.py +++ b/http_server/izzylib/http_server/middleware.py @@ -4,6 +4,7 @@ from datetime import datetime, timedelta, timezone from izzylib import izzylog as logging, logging as applog from . import start_time +from .response import Response cache_types = [ @@ -42,7 +43,14 @@ class MiddlewareBase: self.cfg = app.cfg - async def handler(self, request): + async def __call__(self, request, response=None): + if not response: + response = Response(self.app, request) + + return await self.handler(request, response) + + + async def handler(self, request, response): pass diff --git a/http_server/izzylib/http_server/misc.py b/http_server/izzylib/http_server/misc.py index b1f000c..2051570 100644 --- a/http_server/izzylib/http_server/misc.py +++ b/http_server/izzylib/http_server/misc.py @@ -1,3 +1,5 @@ +import json + from izzylib import LowerDotDict @@ -29,3 +31,11 @@ class Headers(LowerDotDict): def getall(self, key, default=[]): return self.get(key.lower(), default) + + + def to_json(self, indent=None): + return json.dumps(self.to_dict(), indent=indent) + + + def to_dict(self): + return {k: self.getone(k) for k in self} diff --git a/http_server/izzylib/http_server/request.py b/http_server/izzylib/http_server/request.py index 8ebab4d..f8f5dd3 100644 --- a/http_server/izzylib/http_server/request.py +++ b/http_server/izzylib/http_server/request.py @@ -1,6 +1,7 @@ import sanic from izzylib import DotDict +from urllib.parse import parse_qsl from .misc import Headers diff --git a/http_server/izzylib/http_server/response.py b/http_server/izzylib/http_server/response.py index 31ab18b..cad9de4 100644 --- a/http_server/izzylib/http_server/response.py +++ b/http_server/izzylib/http_server/response.py @@ -62,11 +62,11 @@ class Response: def __str__(self): - return self.body + return str(self.body) def __bytes__(self): - return self.body.encode('utf-8') + return self.body if isinstance(self.body, bytes) else self.body.encode('utf-8') def __repr__(self): diff --git a/requests_client/izzylib/http_requests_client/client.py b/requests_client/izzylib/http_requests_client/client.py index 4eea6a8..c7ada17 100644 --- a/requests_client/izzylib/http_requests_client/client.py +++ b/requests_client/izzylib/http_requests_client/client.py @@ -11,7 +11,7 @@ from izzylib.exceptions import HttpFileDownloadedError from ssl import SSLCertVerificationError from urllib.parse import urlparse -from .signature import sign_request +from .signature import sign_request, set_client Client = None @@ -111,7 +111,7 @@ class HttpRequestsClient(object): class HttpRequestsRequest(object): - def __init__(self, client, url, data=None, headers={}, query={}, method='get'): + def __init__(self, client, url, data=b'', headers={}, query={}, method='get'): parsed = urlparse(url) self.args = [url] self.kwargs = DotDict({'params': query}) @@ -119,6 +119,7 @@ class HttpRequestsRequest(object): self.client = client self.path = parsed.path self.host = parsed.netloc + self.body = data new_headers = client.headers.copy() new_headers.update(headers) @@ -129,7 +130,6 @@ class HttpRequestsRequest(object): parsed_headers['user-agent'] = client.agent self.kwargs['headers'] = DotDict(new_headers) - self.kwargs['data'] = data if client.proxy.enabled: self.kwargs['proxies'] = DotDict({self.proxy.ptype: f'{self.proxy.ptype}://{self.proxy.host}:{self.proxy.port}'}) @@ -142,7 +142,7 @@ class HttpRequestsRequest(object): @body.setter def body(self, data): - self.kwargs.data = data + self.kwargs.data = data.encode('utf-8') if isinstance(data, str) else data @property @@ -224,3 +224,4 @@ class HttpRequestsResponse(object): def set_requests_client(client=None): global Client Client = client or RequestsClient() + set_client(Client) diff --git a/requests_client/izzylib/http_requests_client/signature.py b/requests_client/izzylib/http_requests_client/signature.py index 98a6b55..452d0c0 100644 --- a/requests_client/izzylib/http_requests_client/signature.py +++ b/requests_client/izzylib/http_requests_client/signature.py @@ -6,6 +6,7 @@ from Crypto.Hash import SHA256 from Crypto.PublicKey import RSA from Crypto.Signature import PKCS1_v1_5 from base64 import b64decode, b64encode +from datetime import datetime from functools import lru_cache from izzylib import DefaultDotDict, DotDict from izzylib import izzylog as logging @@ -13,6 +14,15 @@ from tldextract import extract from urllib.parse import urlparse +Client = None + + +def set_client(client): + global Client + + Client = client + + @lru_cache(maxsize=512) def fetch_actor(url): if not Client: @@ -126,6 +136,7 @@ def parse_signature(signature: str): sig.headers = sig.headers.split() sig.domain = urlparse(sig.keyid).netloc sig.top_domain = '.'.join(extract(sig.domain)[1:]) + sig.actor = sig.keyid.split('#')[0] return sig @@ -152,7 +163,6 @@ def verify_headers(headers: dict, method: str, path: str, actor: dict=None, body if not actor: actor = fetch_actor(signature.keyid) - print(actor) ## Add digest header to missing headers list if it doesn't exist if method.lower() == 'post' and not digest: @@ -181,9 +191,7 @@ async def verify_request(request, actor: dict=None): actor: A dictionary containing the activitypub actor and the link to the pubkey used for verification ''' - body = (await request.body) if request.body else None - headers = {k.lower(): v[0] for k,v in request.headers.items()} - return verify_headers(headers, request.method, request.path, actor, body) + return verify_headers(request.Headers.to_dict(), request.method, request.path, actor, request.body) @@ -223,6 +231,8 @@ def sign_pkcs_headers(key: str, headers: dict, sig=None): def sign_request(request, privkey, keyid): + assert isinstance(request.body, bytes) + request.add_header('(request-target)', f'{request.method.lower()} {request.path}') request.add_header('host', request.host) request.add_header('date', datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT')) @@ -230,7 +240,7 @@ def sign_request(request, privkey, keyid): if request.body: body_hash = b64encode(SHA256.new(request.body).digest()).decode("UTF-8") request.add_header('digest', f'SHA-256={body_hash}') - request.add_header('content-length', len(request.body)) + request.add_header('content-length', str(len(request.body))) sig = { 'keyId': keyid, From 56e3e30db166e202e14e6c012093ef8a5e24c156 Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Wed, 15 Sep 2021 08:37:41 -0400 Subject: [PATCH 60/74] sql.generic.SqlDatabase: raise an error when no tables specified --- sql/izzylib/sql/generic.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sql/izzylib/sql/generic.py b/sql/izzylib/sql/generic.py index b83c1e9..f85815c 100644 --- a/sql/izzylib/sql/generic.py +++ b/sql/izzylib/sql/generic.py @@ -97,6 +97,9 @@ class SqlDatabase: def create_tables(self, *tables): + if not tables: + raise ValueError('No tables specified') + new_tables = [self.table[table] for table in tables] self.table.meta.create_all(bind=self.db, tables=new_tables) From f401cc7e1a3ed8e620a860a78504048c852ac076 Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Fri, 17 Sep 2021 08:59:29 -0400 Subject: [PATCH 61/74] rework external http client and database --- .gitignore | 2 +- README.md | 4 +- base/izzylib/__init__.py | 6 +- base/izzylib/dotdict.py | 14 +- .../{http_urllib_client.py => http_client.py} | 6 +- base/izzylib/misc.py | 27 +- http_server/izzylib/http_server/middleware.py | 3 +- http_server/izzylib/http_server/request.py | 1 + .../izzylib/http_urllib_client/__init__.py | 30 ++ .../izzylib/http_urllib_client/client.py | 128 +++++ .../izzylib/http_urllib_client/request.py | 111 ++++ .../izzylib/http_urllib_client/response.py | 97 ++++ .../izzylib/http_urllib_client/signatures.py | 0 .../setup.py | 8 +- .../izzylib/http_requests_client/__init__.py | 33 -- .../izzylib/http_requests_client/client.py | 227 -------- .../izzylib/http_requests_client/error.py | 0 sql/izzylib/sql/__init__.py | 17 +- sql/izzylib/sql/column.py | 54 ++ sql/izzylib/sql/config.py | 100 ---- sql/izzylib/sql/database.py | 466 +++++----------- sql/izzylib/sql/error.py | 10 - sql/izzylib/sql/generic.py | 508 ------------------ sql/izzylib/sql/queries.py | 415 -------------- sql/izzylib/sql/row.py | 19 - sql/izzylib/sql/rows.py | 90 ++++ sql/izzylib/sql/session.py | 179 ++++++ sql/izzylib/sql/types.py | 19 - 28 files changed, 892 insertions(+), 1682 deletions(-) rename base/izzylib/{http_urllib_client.py => http_client.py} (97%) create mode 100644 http_urllib_client/izzylib/http_urllib_client/__init__.py create mode 100644 http_urllib_client/izzylib/http_urllib_client/client.py create mode 100644 http_urllib_client/izzylib/http_urllib_client/request.py create mode 100644 http_urllib_client/izzylib/http_urllib_client/response.py rename requests_client/izzylib/http_requests_client/signature.py => http_urllib_client/izzylib/http_urllib_client/signatures.py (100%) rename {requests_client => http_urllib_client}/setup.py (84%) delete mode 100644 requests_client/izzylib/http_requests_client/__init__.py delete mode 100644 requests_client/izzylib/http_requests_client/client.py delete mode 100644 requests_client/izzylib/http_requests_client/error.py create mode 100644 sql/izzylib/sql/column.py delete mode 100644 sql/izzylib/sql/config.py delete mode 100644 sql/izzylib/sql/error.py delete mode 100644 sql/izzylib/sql/generic.py delete mode 100644 sql/izzylib/sql/queries.py delete mode 100644 sql/izzylib/sql/row.py create mode 100644 sql/izzylib/sql/rows.py create mode 100644 sql/izzylib/sql/session.py delete mode 100644 sql/izzylib/sql/types.py diff --git a/.gitignore b/.gitignore index 73dcf22..d383997 100644 --- a/.gitignore +++ b/.gitignore @@ -121,7 +121,7 @@ reload.cfg /izzylib /base/izzylib/dbus /base/izzylib/hasher -/base/izzylib/http_requests_client +/base/izzylib/http_urllib_client /base/izzylib/http_server /base/izzylib/mbus /base/izzylib/sql diff --git a/README.md b/README.md index 4fb66f8..5b6417b 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ You only need to install the base and whatever sub-modules you want to use $(venv)/bin/python -m pip install -e "git+https://git.barkshark.xyz/izaliamae/izzylib.git@rework#egg=izzylib-http-server&subdirectory=http_server" - $(venv)/bin/python -m pip install -e "git+https://git.barkshark.xyz/izaliamae/izzylib.git@rework#egg=izzylib-http-requests-client&subdirectory=requests_client" + $(venv)/bin/python -m pip install -e "git+https://git.barkshark.xyz/izaliamae/izzylib.git@rework#egg=izzylib-http-urllib-client&subdirectory=http_urllib_client" $(venv)/bin/python -m pip install -e "git+https://git.barkshark.xyz/izaliamae/izzylib.git@rework#egg=izzylib-sql&subdirectory=sql" @@ -26,7 +26,7 @@ You only need to install the base and whatever sub-modules you want to use ### From Source - $(venv)/bin/python setup.py install ['all' or a combination of these: dbus hasher http_server requests_client sql template tinydb] + $(venv)/bin/python setup.py install ['all' or a combination of these: dbus hasher http_server http_urllib_client sql template tinydb] ## Documentation diff --git a/base/izzylib/__init__.py b/base/izzylib/__init__.py index c8f8bfe..71cace8 100644 --- a/base/izzylib/__init__.py +++ b/base/izzylib/__init__.py @@ -21,7 +21,7 @@ from .misc import * from .cache import CacheDecorator, LruCache, TtlCache from .connection import Connection -from .http_urllib_client import HttpUrllibClient, HttpUrllibResponse +from .http_client import HttpClient, HttpResponse def log_import_error(package, *message): @@ -48,10 +48,10 @@ except ImportError: log_import_error('template', 'Failed to import http template classes. Jinja and HAML templates disabled') try: - from izzylib.http_requests_client import * + from izzylib.http_urllib_client import * except ImportError: - log_import_error('http_requests_client', 'Failed to import Requests http client classes. Requests http client is disabled') + log_import_error('http_urllib_client', 'Failed to import Requests http client classes. Requests http client is disabled') try: from izzylib.http_server import PasswordHasher, HttpServer, HttpServerRequest, HttpServerResponse diff --git a/base/izzylib/dotdict.py b/base/izzylib/dotdict.py index 34003a4..0076d5b 100644 --- a/base/izzylib/dotdict.py +++ b/base/izzylib/dotdict.py @@ -110,18 +110,12 @@ class DefaultDotDict(DotDict): class LowerDotDict(DotDict): - def __getattr__(self, key): - return super().__getattr__(self, key.lower()) + def __getitem__(self, key): + return super().__getitem__(key.lower()) - def __setattr__(self, key, value): - return super().__setattr__(key.lower(), value) - - - def update(self, data): - data = {k.lower(): v for k,v in self.items()} - - return super().update(data) + def __setitem__(self, key, value): + return super().__setitem__(key.lower(), value) class MultiDotDict(DotDict): diff --git a/base/izzylib/http_urllib_client.py b/base/izzylib/http_client.py similarity index 97% rename from base/izzylib/http_urllib_client.py rename to base/izzylib/http_client.py index ece6a5d..38a6f21 100644 --- a/base/izzylib/http_urllib_client.py +++ b/base/izzylib/http_client.py @@ -22,7 +22,7 @@ except ImportError: methods = ['connect', 'delete', 'get', 'head', 'options', 'patch', 'post', 'put', 'trace'] -class HttpUrllibClient: +class HttpClient: def __init__(self, headers={}, useragent=f'IzzyLib/{__version__}', appagent=None, proxy_type='https', proxy_host=None, proxy_port=None): proxy_ports = { 'http': 80, @@ -74,7 +74,7 @@ class HttpUrllibClient: except HTTPError as e: response = e.fp - return HttpUrllibResponse(response) + return HttpResponse(response) def file(self, url, filepath, *args, filename=None, size=2048, create_dirs=True, **kwargs): @@ -141,7 +141,7 @@ class HttpUrllibClient: return self.request(*args, headers=headers, **kwargs) -class HttpUrllibResponse(object): +class HttpResponse(object): def __init__(self, response): self.body = response.read() self.headers = DefaultDotDict({k.lower(): v.lower() for k,v in response.headers.items()}) diff --git a/base/izzylib/misc.py b/base/izzylib/misc.py index e3cedc0..5927884 100644 --- a/base/izzylib/misc.py +++ b/base/izzylib/misc.py @@ -4,6 +4,7 @@ from datetime import datetime from getpass import getpass, getuser from importlib import util from pathlib import Path +from urllib.parse import urlparse from . import izzylog from .dotdict import DotDict @@ -27,7 +28,8 @@ __all__ = [ 'time_function', 'time_function_pprint', 'timestamp', - 'var_name' + 'var_name', + 'Url' ] @@ -460,3 +462,26 @@ def var_name(single=True, **kwargs): keys = list(kwargs.keys()) return key[0] if single else keys + + +class Url(str): + protocols = { + 'http': 80, + 'https': 443, + 'ftp': 21, + 'ftps': 990 + } + + def __init__(self, url): + str.__new__(Url, url) + + parsed = urlparse(url) + + self.__parsed = parsed + self.proto = parsed.scheme + self.host = parsed.netloc + self.path = parsed.path + self.query = parsed.query + self.username = parsed.username + self.password = parsed.password + self.port = self.protocols.get(self.proto) if not parsed.port else None diff --git a/http_server/izzylib/http_server/middleware.py b/http_server/izzylib/http_server/middleware.py index e081a2f..21d4b80 100644 --- a/http_server/izzylib/http_server/middleware.py +++ b/http_server/izzylib/http_server/middleware.py @@ -78,6 +78,5 @@ class AccessLog(MiddlewareBase): async def handler(self, request, response): uagent = request.headers.get('user-agent', 'None') - address = request.headers.get('x-real-ip', request.forwarded.get('for', request.remote_addr)) - applog.info(f'({multiprocessing.current_process().name}) {address} {request.method} {request.path} {response.status} "{uagent}"') + applog.info(f'({multiprocessing.current_process().name}) {request.address} {request.method} {request.path} {response.status} "{uagent}"') diff --git a/http_server/izzylib/http_server/request.py b/http_server/izzylib/http_server/request.py index f8f5dd3..dde7d2a 100644 --- a/http_server/izzylib/http_server/request.py +++ b/http_server/izzylib/http_server/request.py @@ -11,6 +11,7 @@ class Request(sanic.request.Request): super().__init__(url_bytes, headers, version, method, transport, app) self.Headers = Headers(headers) + self.address = self.headers.get('x-real-ip', self.forwarded.get('for', self.remote_addr)) self.data = Data(self) self.template = self.app.template self.user_level = 0 diff --git a/http_urllib_client/izzylib/http_urllib_client/__init__.py b/http_urllib_client/izzylib/http_urllib_client/__init__.py new file mode 100644 index 0000000..d3a9112 --- /dev/null +++ b/http_urllib_client/izzylib/http_urllib_client/__init__.py @@ -0,0 +1,30 @@ +from .signatures import ( + verify_request, + verify_headers, + parse_signature, + fetch_actor, + fetch_instance, + fetch_nodeinfo, + fetch_webfinger_account, + generate_rsa_key +) + + +from .client import HttpUrllibClient, set_default_client +from .request import HttpUrllibRequest +from .response import HttpUrllibResponse + +#__all__ = [ + #'HttpRequestsClient', + #'HttpRequestsRequest', + #'HttpRequestsResponse', + #'fetch_actor', + #'fetch_instance', + #'fetch_nodeinfo', + #'fetch_webfinger_account', + #'generate_rsa_key', + #'parse_signature', + #'set_requests_client', + #'verify_headers', + #'verify_request', +#] diff --git a/http_urllib_client/izzylib/http_urllib_client/client.py b/http_urllib_client/izzylib/http_urllib_client/client.py new file mode 100644 index 0000000..4002331 --- /dev/null +++ b/http_urllib_client/izzylib/http_urllib_client/client.py @@ -0,0 +1,128 @@ +import json, sys, urllib3 + +from PIL import Image + +from base64 import b64encode +from datetime import datetime +from functools import cached_property +from io import BytesIO +from izzylib import DefaultDotDict, DotDict, LowerDotDict, Path, izzylog as logging, __version__ +from izzylib.exceptions import HttpFileDownloadedError +from ssl import SSLCertVerificationError +from urllib.parse import urlparse + +from .request import HttpUrllibRequest +from .response import HttpUrllibResponse +from .signatures import set_client + + +Client = None + +proxy_ports = { + 'http': 80, + 'https': 443 +} + + +class HttpUrllibClient: + def __init__(self, headers={}, useragent=None, appagent=None, proxy_type='https', proxy_host=None, proxy_port=None, num_pools=20): + if not useragent: + useragent = f'IzzyLib/{__version__}' + + self.headers = {k:v.lower() for k,v in headers.items()} + self.agent = f'{useragent} ({appagent})' if appagent else useragent + + if proxy_type not in ['http', 'https']: + raise ValueError(f'Not a valid proxy type: {proxy_type}') + + if proxy_host: + proxy = f'{proxy_type}://{proxy_host}:{proxy_ports[proxy_type] if not proxy_port else proxy_port}' + self.pool = urllib3.ProxyManager(proxy, num_pools=num_pools) + + else: + self.pool = urllib3.PoolManager(num_pools=num_pools) + + + @property + def agent(self): + return self.headers['user-agent'] + + + @agent.setter + def agent(self, value): + self.headers['user-agent'] = value + + + def set_global(self): + set_default_client(self) + + + def build_request(self, *args, **kwargs): + return HttpUrllibRequest(*args, **kwargs) + + + def handle_request(self, request): + request.headers.update(self.headers) + response = self.pool.urlopen(*request._args, **request._kwargs) + return HttpUrllibResponse(response) + + + def request(self, *args, **kwargs): + return self.handle_request(self.build_request(*args, **kwargs)) + + + def signed_request(self, privkey, keyid, *args, **kwargs): + return self.request(*args, privkey=privkey, keyid=keyid, **kwargs) + + + def download(self, url, filepath, *args, filename=None, **kwargs): + resp = self.request(url, *args, **kwargs) + + if resp.status != 200: + raise HttpFileDownloadedError(f'Failed to download {url}: Status: {resp.status}, Body: {resp.body}') + + return resp.save(filepath) + + + def image(self, url, filepath, *args, filename=None, ext='png', dimensions=(50, 50), **kwargs): + if not Image: + izzylog.error('Pillow module is not installed') + return + + resp = self.request(url, *args, **kwargs) + + if resp.status != 200: + izzylog.error(f'Failed to download {url}:', resp.status, resp.body) + return False + + if not filename: + filename = Path(url).stem() + + path = Path(filepath) + + if not path.exists: + izzylog.error('Path does not exist:', path) + return False + + byte = BytesIO() + image = Image.open(BytesIO(resp.body)) + image.thumbnail(dimensions) + image.save(byte, format=ext.upper()) + + with path.join(filename).open('wb') as fd: + fd.write(byte.getvalue()) + + + def json(self, *args, headers={}, activity=True, **kwargs): + json_type = 'activity+json' if activity else 'json' + headers.update({ + 'accept': f'application/{json_type}' + }) + + return self.request(*args, headers=headers, **kwargs) + + +def set_default_client(client=None): + global Client + Client = client or HttpClient() + set_client(Client) diff --git a/http_urllib_client/izzylib/http_urllib_client/request.py b/http_urllib_client/izzylib/http_urllib_client/request.py new file mode 100644 index 0000000..ad8b63b --- /dev/null +++ b/http_urllib_client/izzylib/http_urllib_client/request.py @@ -0,0 +1,111 @@ +import json + +from Crypto.Hash import SHA256 +from izzylib import DotDict, LowerDotDict, Url, boolean +from base64 import b64decode, b64encode +from datetime import datetime +from izzylib import izzylog as logging + +from .signatures import sign_pkcs_headers + + +methods = ['delete', 'get', 'head', 'options', 'patch', 'post', 'put'] + + +class HttpUrllibRequest: + def __init__(self, url, **kwargs): + self._body = b'' + + method = kwargs.get('method', 'get').lower() + + if method not in methods: + raise ValueError(f'Invalid method: {method}') + + self.url = Url(url) + self.body = kwargs.get('body') + self.method = method + self.headers = LowerDotDict(kwargs.get('headers', {})) + self.redirect = boolean(kwargs.get('redirect', True)) + self.retries = int(kwargs.get('retries', 10)) + self.timeout = int(kwargs.get('timeout', 5)) + + privkey = kwargs.get('privkey') + keyid = kwargs.get('keyid') + + if privkey and keyid: + self.sign(privkey, keyid) + + + @property + def _args(self): + return [self.method.upper(), self.url] + + + @property + def _kwargs(self): + return { + 'body': self.body, + 'headers': self.headers, + 'redirect': self.redirect, + 'retries': self.retries, + 'timeout': self.timeout + } + + + @property + def body(self): + return self._body + + + @body.setter + def body(self, data): + if isinstance(data, dict): + data = DotDict(data).to_json() + + elif any(map(isinstance, [data], [list, tuple])): + data = json.dumps(data) + + if data == None: + data = b'' + + elif not isinstance(data, bytes): + data = bytes(data, 'utf-8') + + self._body = data + + + def set_header(self, key, value): + self.headers[key] = value + + + def unset_header(self, key): + self.headers.pop(key, None) + + + def sign(self, privkey, keyid): + self.unset_header('signature') + + self.set_header('(request-target)', f'{self.method.lower()} {self.url.path}') + self.set_header('host', self.url.host) + self.set_header('date', datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT')) + + if self.body: + body_hash = b64encode(SHA256.new(self.body).digest()).decode("UTF-8") + + self.set_header('digest', f'SHA-256={body_hash}') + self.set_header('content-length', str(len(self.body))) + + sig = { + 'keyId': keyid, + 'algorithm': 'rsa-sha256', + 'headers': ' '.join([k.lower() for k in self.headers.keys()]), + 'signature': b64encode(sign_pkcs_headers(privkey, self.headers)).decode('UTF-8') + } + + sig_items = [f'{k}="{v}"' for k,v in sig.items()] + sig_string = ','.join(sig_items) + + self.set_header('signature', sig_string) + + self.unset_header('(request-target)') + self.unset_header('host') diff --git a/http_urllib_client/izzylib/http_urllib_client/response.py b/http_urllib_client/izzylib/http_urllib_client/response.py new file mode 100644 index 0000000..a05ab14 --- /dev/null +++ b/http_urllib_client/izzylib/http_urllib_client/response.py @@ -0,0 +1,97 @@ +import json + +from io import BytesIO +from izzylib import DefaultDotDict, DotDict, Path, Url + + +class HttpUrllibResponse: + def __init__(self, response): + self.response = response + + self._dict = None + + + def __getitem__(self, key): + return self.dict[key] + + + def __setitem__(self, key, value): + self.dict[key] = value + + + @property + def encoding(self): + for line in self.headers.get('content-type', '').split(';'): + try: + k,v = line.split('=') + + if k.lower == 'charset': + return v.lower() + + except: + pass + + return 'utf-8' + + + @property + def headers(self): + return self.response.headers + + + @property + def status(self): + return self.response.status + + + @property + def url(self): + return Url(self.response.geturl()) + + + @property + def body(self): + data = self.response.read(cache_content=True) + + if not data: + data = self.response.data + + return data + + + @property + def text(self): + return self.body.decode(self.encoding) + + + @property + def dict(self): + if not self._dict: + self._dict = DotDict(self.text) + + return self._dict + + + def json_pretty(self, indent=4): + return self.dict.to_json(indent) + + + def chunks(self, size=1024): + return self.response.stream(amt=size) + + + def save(self, path, overwrite=True, create_parents=True): + path = Path(path) + + if not path.parent.exists: + if not create_parents: + raise ValueError(f'Path does not exist: {path.parent}') + + path.parent.mkdir() + + if overwrite and path.exists: + path.delete() + + with path.open('wb') as fd: + for chunk in self.chunks(): + fd.write(chunk) diff --git a/requests_client/izzylib/http_requests_client/signature.py b/http_urllib_client/izzylib/http_urllib_client/signatures.py similarity index 100% rename from requests_client/izzylib/http_requests_client/signature.py rename to http_urllib_client/izzylib/http_urllib_client/signatures.py diff --git a/requests_client/setup.py b/http_urllib_client/setup.py similarity index 84% rename from requests_client/setup.py rename to http_urllib_client/setup.py index 187d62b..492532a 100644 --- a/requests_client/setup.py +++ b/http_urllib_client/setup.py @@ -5,21 +5,21 @@ from setuptools import setup, find_namespace_packages requires = [ 'pillow==8.2.0', 'pycryptodome==3.10.1', - 'requests==2.25.1', + 'urllib==1.26.5', 'tldextract==3.1.0' ] setup( - name="IzzyLib Requests Client", + name="IzzyLib Urllib3 Client", version='0.6.0', - packages=find_namespace_packages(include=['izzylib.http_requests_client']), + packages=find_namespace_packages(include=['izzylib.http_urllib_client']), python_requires='>=3.7.0', install_requires=requires, include_package_data=False, author='Zoey Mae', author_email='admin@barkshark.xyz', - description='A Requests client with support for http header signing and verifying', + description='A Urllib3 client with support for http header signing and verifying', keywords='web http client', url='https://git.barkshark.xyz/izaliamae/izzylib', project_urls={ diff --git a/requests_client/izzylib/http_requests_client/__init__.py b/requests_client/izzylib/http_requests_client/__init__.py deleted file mode 100644 index af8cb1f..0000000 --- a/requests_client/izzylib/http_requests_client/__init__.py +++ /dev/null @@ -1,33 +0,0 @@ -from .signature import ( - verify_request, - verify_headers, - parse_signature, - fetch_actor, - fetch_instance, - fetch_nodeinfo, - fetch_webfinger_account, - generate_rsa_key -) - - -from .client import ( - HttpRequestsClient, - HttpRequestsRequest, - HttpRequestsResponse, - set_requests_client -) - -__all__ = [ - 'HttpRequestsClient', - 'HttpRequestsRequest', - 'HttpRequestsResponse', - 'fetch_actor', - 'fetch_instance', - 'fetch_nodeinfo', - 'fetch_webfinger_account', - 'generate_rsa_key', - 'parse_signature', - 'set_requests_client', - 'verify_headers', - 'verify_request', -] diff --git a/requests_client/izzylib/http_requests_client/client.py b/requests_client/izzylib/http_requests_client/client.py deleted file mode 100644 index c7ada17..0000000 --- a/requests_client/izzylib/http_requests_client/client.py +++ /dev/null @@ -1,227 +0,0 @@ -import json, requests, sys - -from PIL import Image - -from base64 import b64encode -from datetime import datetime -from functools import cached_property -from io import BytesIO -from izzylib import DefaultDotDict, DotDict, Path, izzylog as logging, __version__ -from izzylib.exceptions import HttpFileDownloadedError -from ssl import SSLCertVerificationError -from urllib.parse import urlparse - -from .signature import sign_request, set_client - - -Client = None -methods = ['connect', 'delete', 'get', 'head', 'options', 'patch', 'post', 'put', 'trace'] - - -class HttpRequestsClient(object): - def __init__(self, headers={}, useragent=f'IzzyLib/{__version__}', appagent=None, proxy_type='https', proxy_host=None, proxy_port=None): - proxy_ports = { - 'http': 80, - 'https': 443 - } - - if proxy_type not in ['http', 'https']: - raise ValueError(f'Not a valid proxy type: {proxy_type}') - - self.headers=headers - self.agent = f'{useragent} ({appagent})' if appagent else useragent - self.proxy = DotDict({ - 'enabled': True if proxy_host else False, - 'ptype': proxy_type, - 'host': proxy_host, - 'port': proxy_ports[proxy_type] if not proxy_port else proxy_port - }) - - - def set_global(self): - set_requests_client(self) - - - def build_request(self, *args, method='get', privkey=None, keyid=None, **kwargs): - if method.lower() not in methods: - raise ValueError(f'Invalid method: {method}') - - request = HttpRequestsRequest(self, *args, method=method.lower(), **kwargs) - - if privkey and keyid: - request.sign(privkey, keyid) - - return request - - - def request(self, *args, **kwargs): - request = self.build_request(*args, **kwargs) - return HttpRequestsResponse(request.send()) - - - def signed_request(self, privkey, keyid, *args, **kwargs): - return self.request(*args, privkey=privkey, keyid=keyid, **kwargs) - - - def download(self, url, filepath, *args, filename=None, **kwargs): - resp = self.request(url, *args, **kwargs) - - if resp.status != 200: - raise HttpFileDownloadedError(f'Failed to download {url}: Status: {resp.status}, Body: {resp.body}') - - return resp.save(filepath) - - - def image(self, url, filepath, *args, filename=None, ext='png', dimensions=(50, 50), **kwargs): - if not Image: - izzylog.error('Pillow module is not installed') - return - - resp = self.request(url, *args, **kwargs) - - if resp.status != 200: - izzylog.error(f'Failed to download {url}:', resp.status, resp.body) - return False - - if not filename: - filename = Path(url).stem() - - path = Path(filepath) - - if not path.exists: - izzylog.error('Path does not exist:', path) - return False - - byte = BytesIO() - image = Image.open(BytesIO(resp.body)) - image.thumbnail(dimensions) - image.save(byte, format=ext.upper()) - - with path.join(filename).open('wb') as fd: - fd.write(byte.getvalue()) - - - def json(self, *args, headers={}, activity=True, **kwargs): - json_type = 'activity+json' if activity else 'json' - headers.update({ - 'accept': f'application/{json_type}' - }) - - return self.request(*args, headers=headers, **kwargs) - - -class HttpRequestsRequest(object): - def __init__(self, client, url, data=b'', headers={}, query={}, method='get'): - parsed = urlparse(url) - self.args = [url] - self.kwargs = DotDict({'params': query}) - self.method = method.lower() - self.client = client - self.path = parsed.path - self.host = parsed.netloc - self.body = data - - new_headers = client.headers.copy() - new_headers.update(headers) - - parsed_headers = {k.lower(): v for k,v in new_headers.items()} - - if not parsed_headers.get('user-agent'): - parsed_headers['user-agent'] = client.agent - - self.kwargs['headers'] = DotDict(new_headers) - - if client.proxy.enabled: - self.kwargs['proxies'] = DotDict({self.proxy.ptype: f'{self.proxy.ptype}://{self.proxy.host}:{self.proxy.port}'}) - - - @property - def body(self): - return self.kwargs.data - - - @body.setter - def body(self, data): - self.kwargs.data = data.encode('utf-8') if isinstance(data, str) else data - - - @property - def headers(self): - return self.kwargs.headers - - - def add_header(self, key, value): - self.kwargs.headers[key] = value - - - def remove_header(self, key): - self.kwargs.headers.pop(key, None) - - - def send(self): - func = getattr(requests, self.method) - return func(*self.args, **self.kwargs) - - - def sign(self, privkey, keyid): - sign_request(self, privkey, keyid) - - -class HttpRequestsResponse(object): - def __init__(self, response): - self.response = response - self.data = b'' - self.headers = DefaultDotDict({k.lower(): v.lower() for k,v in response.headers.items()}) - self.status = response.status_code - self.url = response.url - - - def chunks(self, size=256): - return self.response.iter_content(chunk_size=256) - - - @property - def body(self): - for chunk in self.chunks(): - self.data += chunk - - return self.data - - - @cached_property - def text(self): - return self.data.decode(self.response.encoding) - - - @cached_property - def json(self): - try: - return DotDict(self.text) - - except: - return DotDict(self.body) - - - @cached_property - def json_pretty(self, indent=4): - return json.dumps(self.json, indent=indent) - - - def save(self, path, overwrite=True): - path = Path(path) - - if not path.parent.exists: - raise ValueError(f'Path does not exist: {path.parent}') - - if overwrite and path.exists: - path.delete() - - with path.open('wb') as fd: - for chunk in self.chunks(): - fd.write(chunk) - - -def set_requests_client(client=None): - global Client - Client = client or RequestsClient() - set_client(Client) diff --git a/requests_client/izzylib/http_requests_client/error.py b/requests_client/izzylib/http_requests_client/error.py deleted file mode 100644 index e69de29..0000000 diff --git a/sql/izzylib/sql/__init__.py b/sql/izzylib/sql/__init__.py index 88638bb..1c9d708 100644 --- a/sql/izzylib/sql/__init__.py +++ b/sql/izzylib/sql/__init__.py @@ -1,6 +1,13 @@ -# old sql classes -from .generic import SqlColumn, CustomRows, SqlSession, SqlDatabase, Tables, OperationalError, ProgrammingError -from .sqlite_server import SqliteClient, SqliteColumn, SqliteServer, SqliteSession +## Normal SQL client +from .database import Database, OperationalError, ProgrammingError +from .session import Session +from .column import Column -#from .database import Database, Session -#from .queries import Column, Insert, Select, Table, Tables, Update +## Sqlite server +#from .sqlite_server import SqliteClient, SqliteColumn, SqliteServer, SqliteSession + + +## Compat +SqlDatabase = Database +SqlSession = Session +SqlColumn = Column diff --git a/sql/izzylib/sql/column.py b/sql/izzylib/sql/column.py new file mode 100644 index 0000000..cab364d --- /dev/null +++ b/sql/izzylib/sql/column.py @@ -0,0 +1,54 @@ +from sqlalchemy import ForeignKey +from sqlalchemy import ( + Column as sqlalchemy_column, + types as Types +) + + +SqlTypes = {t.lower(): getattr(Types, t) for t in dir(Types) if not t.startswith('_')} + + +class Column(sqlalchemy_column): + def __init__(self, name, stype=None, fkey=None, **kwargs): + if not stype and not kwargs: + if name == 'id': + stype = 'integer' + kwargs['primary_key'] = True + kwargs['autoincrement'] = True + + elif name == 'timestamp': + stype = 'datetime' + + else: + raise ValueError('Missing column type and options') + + stype = (stype.lower() if type(stype) == str else stype) or 'string' + + if type(stype) == str: + try: + stype = SqlTypes[stype.lower()] + + except KeyError: + raise KeyError(f'Invalid SQL data type: {stype}') + + options = [name, stype] + + if fkey: + options.append(ForeignKey(fkey)) + + super().__init__(*options, **kwargs) + + + def compile(self): + sql = f'{self.name} {self.type}' + + if not self.nullable: + sql += ' NOT NULL' + + if self.primary_key: + sql += ' PRIMARY KEY' + + if self.unique: + sql += ' UNIQUE' + + return sql diff --git a/sql/izzylib/sql/config.py b/sql/izzylib/sql/config.py deleted file mode 100644 index 8202a1b..0000000 --- a/sql/izzylib/sql/config.py +++ /dev/null @@ -1,100 +0,0 @@ -import importlib, sqlite3, ssl - -from getpass import getuser -from izzylib import DotDict, Path, izzylog - - -defaults = { - 'name': (None, str), - 'host': (None, str), - 'port': (None, int), - 'username': (getuser(), str), - 'password': (None, str), - 'ssl': ('allow', str), - 'ssl_context': (ssl.create_default_context(), ssl.SSLContext), - 'ssl_key': (None, Path), - 'ssl_cert': (None, Path), - 'max_connections': (25, int), - 'type': ('sqlite', str), - 'module': (sqlite3, None), - 'mod_name': ('sqlite3', str), - 'timeout': (5, int), - 'args': ([], list), - 'kwargs': ({}, dict) -} - -modtypes = { - 'sqlite': ['sqlite3'], - 'postgresql': ['pg8000', 'psycopg2', 'psycopg3', 'pgdb'], - 'mysql': ['mysqldb', 'trio_mysql'], - 'mssql': ['pymssql', 'adodbapi'] -} - -sslmodes = ['disable', 'allow', 'prefer', 'require', 'verify-ca', 'verify-full'] - - -class Config(DotDict): - def __init__(self, **kwargs): - super().__init__({k: v[0] for k,v in defaults.items()}) - - module = kwargs.pop('module', None) - - if module: - self.parse_module(module) - - self.update(kwargs) - - if self.ssl != 'disable' and (self.ssl_key or self.ssl_cert): - self.ssl_context.load_cert_chain(self.ssl_cert, self.ssl_key) - - - def __setitem__(self, key, value): - if key not in defaults: - raise KeyError(f'Invalid config option: {key}') - - valtype = defaults[key][1] - - if valtype and value and not isinstance(value, valtype): - raise TypeError(f'{key} should be a {valtype}, not a {value.__class__.__name__}') - - if key == 'ssl' and value == True: - value = ssl.create_default_context() - - super().__setitem__(key, value) - - - def parse_module(self, name): - module = None - module_type = None - module_name = None - - if name == 'sqlite3': - name = 'sqlite' - - for mtype, modules in modtypes.items(): - if name == mtype: - module_type = name - - for mod in modules: - try: - module = importlib.import_module(mod) - module_name = mod - break - except ImportError: - izzylog.verbose(f'Database module not installed:', mod) - - elif name in modules: - try: - module = importlib.import_module(name) - module_type = mtype - module_name = name - break - except ImportError: - izzylog.error(f'Database module not installed:', name) - - if None in (module, module_name, module_type): - raise ValueError(f'Failed to find module for {name}') - - self.module = module - self.mod_name = module_name - self.type = module_type diff --git a/sql/izzylib/sql/database.py b/sql/izzylib/sql/database.py index 2f2ce9e..cbdd20e 100644 --- a/sql/izzylib/sql/database.py +++ b/sql/izzylib/sql/database.py @@ -1,360 +1,186 @@ -import sqlite3, traceback +import json, pkgutil, sys, threading, time -from functools import partial -from getpass import getuser -from izzylib import DotDict, izzylog, boolean, random_gen +from contextlib import contextmanager +from datetime import datetime +from izzylib import LruCache, DotDict, Path, nfs_check, izzylog +from sqlalchemy import Table, create_engine +from sqlalchemy.exc import OperationalError, ProgrammingError +from sqlalchemy.engine import URL +from sqlalchemy.schema import MetaData -from . import error -from .config import Config -from .queries import Column, Delete, Insert, Select, Table, Tables, Update +from .rows import RowClasses +from .session import Session + + +modules = dict( + postgresql = ['pygresql', 'pg8000', 'psycopg2', 'psycopg3'] +) class Database: - def __init__(self, tables=None, **kwargs): - self.tables = tables - self.cfg = Config(**kwargs) - self.sessions = DotDict() + def __init__(self, dbtype='sqlite', **kwargs): + self._connect_args = [dbtype, kwargs] + self.db = None + self.cache = None + self.config = DotDict() + self.meta = MetaData() + self.classes = RowClasses(*kwargs.get('row_classes', [])) + self.cache = None + + self.session_class = kwargs.get('session_class', Session) + self.sessions = {} + + self.open() + + + def _setup_cache(self): + self.cache = DotDict({table: LruCache() for table in self.get_tables()}) @property def session(self): - return self.get_session(False) + return self.session_class(self) @property - def session_trans(self): - return self.get_session(True) + def dbtype(self): + return self.db.url.get_backend_name() - def connect(self, sid, session): - if len(self.sessions) >= self.cfg.max_connections: - raise error.MaxConnectionsError(f'Cannot start a new session with id {sid}. Reach max connection count of {self.cfg.max_connections}.') - - self.sessions[sid] = session - - - def disconnect(self, sid): - self.sessions[sid].disconnect() - del self.sessions[sid] - - - def disconnect_all(self): - sids = [] - - for sid in self.sessions.keys(): - sids.append(sid) - - for sid in sids: - self.disconnect(sid) - - - def get_session(self, trans=True): - session = Session(self, trans) - self.sessions[session.id] = session - return session - - - def execute(self, *args): - with self.session as s: - s.execute(*args) - - - def load_tables(self, path): - self.tables = Tables.new_from_json_file(path) - - - def pre_setup(self): - if self.cfg.type != 'postgresql': - izzylog.verbose(f'Database not supported for pre_setup: {self.cfg.type}') - return - - original_database = self.cfg.name - self.cfg.name = 'postgres' - - with self.session as s: - s.conn.autocommit = True - s.rollback() - - if original_database not in s.get_databases(): - #s.execute('SET AUTOCOMMIT = OFF') - s.cursor.execute(f'CREATE DATABASE {original_database}') - - s.conn.autocommit = False - - self.cfg.name = original_database - - - def set_row_class(self, table, row_class): - pass - - -class Session: - def __init__(self, db, trans): - self.id = random_gen() - self.db = db - self.cfg = db.cfg - self.trans = trans - self.trans_state = False - self.conn = None - self.cursor = None - - - def __del__(self): - try: - izzylog.verbose('Deleting session:', self.id) - except ModuleNotFoundError: - if izzylog.get_config('level') >= 20: - print('[izzylib] VERBOSE: Deleting session:', self.id) - - self.db.sessions.pop(self.id, None) - - if self.conn: - self.disconnect() - - - def __enter__(self): - self.connect() - - if self.trans: - self.begin() - - return self - - - def __exit__(self, exc_type, exc_value, exc_traceback): - if exc_traceback: - self.rollback() - - else: - self.commit() - - self.disconnect() - self.db.disconnect(self.id) - - - def connect(self): - if self.conn: - return - - self.db.connect(self.id, self) - - if self.cfg.type == 'sqlite': - self.conn = self.cfg.module.connect(self.cfg.name, self.cfg.timeout, check_same_thread=True) - - elif self.cfg.type == 'postgresql': - options = dict( - host = self.cfg.host or '/var/run/postgresql', - port = self.cfg.port or 5432, - database = self.cfg.name or 'postgresql', - user = self.cfg.username or getuser(), - password = self.cfg.password, - ) - - if self.cfg.mod_name == 'pg8000': - if options['host'] in [None, '/var/run/postgresql']: - port = options.pop('port') - options['unix_sock'] = options.pop('host') + f'/.s.PGSQL.{port}' - - ## SSL is a pain in the ass tbh. Gonna deal with this later - #if self.cfg.mod_name == 'pg8000': - #options['sslmode'] = self.cfg.ssl - #options['ssl_context'] = self.cfg.ssl_context - - #elif self.cfg.mod_name == 'psycopg2': - #options['sslcert'] = self.cfg.ssl_cert - #options['sslkey'] = self.cfg.ssl_key - - self.conn = self.cfg.module.connect(**options) - - else: - raise error.DatabaseNotSupportedError(f'Database not supported yet: {self.cfg.type}') - - try: - self.conn.autocommit = False - except: - izzylog.verbose('Failed to turn off autocommit') - - self.cursor = self.conn.cursor() - - - def disconnect(self): - if not self.conn: - return - - self.cursor.close() - self.conn.close() - - self.cursor = None - self.conn = None - - - def begin(self): - if self.trans_state: - return - - #self.conn.begin() - self.execute('BEGIN TRANSACTION') - self.trans_state = True - - - def rollback(self): - if not self.trans_state: - return - - self.conn.rollback() - #self.execute('ROLLBACK TRANSACTION') - self.trans_state = False - - - def commit(self): - if not self.trans_state: - return - - self.conn.commit() - #self.execute('COMMIT TRANSACTION') - self.trans_state = False - - - ## data management functions - def execute(self, string, values=[]): - if any(map(string.lower().startswith, ['insert', 'update', 'remove', 'create', 'drop'])) and not self.trans_state: - raise error.NoTransactionError('Please start a transaction with "session.begin()" before using a write command.') - - self.cursor.execute(string, values) - return self.cursor - - - def fetch(self, table, single=True, **kwargs): - rows = [] - data = Select(table, type=self.cfg.type, **kwargs).exec(self) - - for line in data: - row = Row(table, self.cursor.description, line) - - if single: - return row - - rows.append(row) - - return rows if not single else None - - - def search(self, table, **kwargs): - return self.fetch(table, single=False, **kwargs) - - - def insert(self, table, **kwargs): - if not self.trans_state: - raise error.NoTransactionError('Please start a transaction with "session.begin()" before using a write command.') - - Insert(table, type=self.cfg.type, **kwargs).exec(self) - return self.fetch(table, **kwargs) - - - def update(self, table, rowid, **kwargs): - if not self.trans_state: - raise error.NoTransactionError('Please start a transaction with "session.begin()" before using a write command.') - - Update(table, rowid, type=self.cfg.type, **kwargs).exec(self) - return self.fetch(table, id=rowid) - - - def delete(self, table, **kwargs): - if not self.trans_state: - raise error.NoTransactionError('Please start a transaction with "session.begin()" before using a write command.') - - Delete(table, type=self.cfg.type, **kwargs).exec(self) - - - ## helper functions - def get_columns(self, table): - if table not in self.get_tables(): - raise KeyError(f'Not an existing table: {table}') - - if self.cfg.type == 'sqlite': - rows = self.execute(f'PRAGMA table_info({table})') - return [row[1] for row in rows] - - elif self.cfg.type == 'postgresql': - rows = self.execute(f"SELECT column_name FROM information_schema.columns WHERE table_name = '{table}'") - return [row[0] for row in rows] - - else: - raise error.DatabaseNotSupportedError(f'Database not supported yet: {self.cfg.type}') + @property + def table(self): + return DotDict(self.meta.tables) def get_tables(self): - if self.cfg.type == 'sqlite': - rows = self.execute("SELECT name FROM sqlite_master WHERE type IN ('table','view') and name NOT LIKE 'sqlite_%'") + return list(self.table.keys()) - elif self.cfg.type == 'postgresql': - rows = self.execute("SELECT table_name FROM information_schema.tables WHERE table_schema = 'public' ORDER BY table_name") + + def get_columns(self, table): + return list(col.name for col in self.table[table].columns) + + + def new_session(self, trans=True): + return self.session_class(self, trans=trans) + + + ## Leaving link to example code for read-only sqlite for later use + ## https://github.com/pudo/dataset/issues/136#issuecomment-128693122 + def open(self): + dbtype, kwargs = self._connect_args + engine_kwargs = { + 'future': True, + #'maxconnections': 25 + } + + if not kwargs.get('name'): + raise KeyError('Database "name" is not set') + + if dbtype == 'sqlite': + database = kwargs['name'] + + if nfs_check(database): + izzylog.warning('Database file is on an NFS share which does not support locking. Any writes to the database will fail') + + engine_kwargs['connect_args'] = {'check_same_thread': False} + + elif dbtype == 'postgresql': + ssl_context = kwargs.get('ssl') + + if ssl_context: + engine_kwargs['ssl_context'] = ssl_context + + if not kwargs.get('host'): + kwargs['unix_socket'] = '/var/run/postgresql' + + if kwargs.get('host') and Path(kwargs['host']).exists(): + kwargs['unix_socket'] = kwargs.pop('host') else: - raise error.DatabaseNotSupportedError(f'Database not supported yet: {self.cfg.type}') + raise TypeError(f'Unsupported database type: {dbtype}') - return [row[0] for row in rows] + self.config.update(kwargs) - - def get_databases(self): - if self.cfg.type == 'sqlite': - izzylog.verbose('This function is useless with sqlite') - return - - elif self.cfg.type == 'postgresql': - databases = [row[0] for row in self.execute('SELECT datname FROM pg_database')] + if dbtype == 'sqlite': + url = URL.create( + drivername='sqlite', + database=kwargs.pop('name') + ) else: - raise error.DatabaseNotSupportedError(f'Database not supported yet: {self.cfg.type}') + try: + for module in modules[dbtype]: + if pkgutil.get_loader(module): + dbtype = f'{dbtype}+{module}' - return databases + except KeyError: + pass + + url = URL.create( + drivername = dbtype, + username = kwargs.pop('user', None), + password = kwargs.pop('password', None), + host = kwargs.pop('host', None), + port = kwargs.pop('port', None), + database = kwargs.pop('name'), + ) + + self.db = create_engine(url, **engine_kwargs) + self.meta = MetaData() + self.meta.reflect(bind=self.db, resolve_fks=True, views=True) + self._setup_cache() - def cursor_description(self): - return [row[0] for row in self.cursor.description] + def close(self): + for sid in list(self.sessions): + self.sessions[sid].commit() + self.sessions[sid].close() + + self.config = DotDict() + self.cache = DotDict() + self.meta = None + self.db = None - def setup_database(self): - if not self.db.tables: - raise ValueError('Tables have not been specified.') + def load_tables(self, **tables): + self.meta = MetaData() - current_tables = self.get_tables() + for name, columns in tables.items(): + Table(name, self.meta, *columns) - for name, table in self.db.tables.items(): - if name in current_tables: - izzylog.verbose(f'Skipping table creation since it already exists: {name}') - continue - - izzylog.verbose(f'Creating table: {name}') - self.execute(table.build(self.cfg.type)) + self._setup_cache() -class Row(DotDict): - def __init__(self, table, keys, values): - self._db = None - self._table = table + def create_database(self, tables={}): + if tables: + self.load_tables(**tables) - super().__init__() + if self.db.url.get_backend_name() == 'postgresql': + predb = create_engine(self.db.engine_string.replace(self.config.name, 'postgres', -1), future=True) + conn = predb.connect() - for idx, key in enumerate([key[0] for key in keys]): - self[key] = values[idx] + try: + conn.execute(text(f'CREATE DATABASE {database}')) + + except ProgrammingError: + 'The database already exists, so just move along' + + except Exception as e: + conn.close() + raise e from None + + conn.close() + + self.meta.create_all(bind=self.db) - def update(self, data): - for k, v in data.items(): - if k not in self: - raise KeyError(f'Not a column for {self._table}') + def drop_tables(self, *tables): + if not tables: + raise ValueError('No tables specified') - self[k] = v + self.meta.drop_all(bind=self.db, tables=tables) - def delete(self): - with self._db.session as s: - s.delete(self._table, id=self.id) - - - def update(self, **kwargs): - self.update(kwargs) - - with self._db.session as s: - s.update(self._table, id=self.id, **kwargs) + def execute(self, string, **kwargs): + with self.session as s: + s.execute(string, **kwargs) diff --git a/sql/izzylib/sql/error.py b/sql/izzylib/sql/error.py deleted file mode 100644 index 4c60314..0000000 --- a/sql/izzylib/sql/error.py +++ /dev/null @@ -1,10 +0,0 @@ -class MaxConnectionsError(Exception): - 'raise when the max amount of connections has been reached' - - -class NoTransactionError(Exception): - 'raise when a write command is executed outside a transaction' - - -class DatabaseNotSupportedError(Exception): - 'raise when the action being performed is not supported by the database in use' diff --git a/sql/izzylib/sql/generic.py b/sql/izzylib/sql/generic.py deleted file mode 100644 index f85815c..0000000 --- a/sql/izzylib/sql/generic.py +++ /dev/null @@ -1,508 +0,0 @@ -import json, sys, threading, time - -from contextlib import contextmanager -from datetime import datetime -from sqlalchemy import create_engine, ForeignKey, MetaData, Table -from sqlalchemy import Column as sqlalchemy_column, types as Types -from sqlalchemy.exc import OperationalError, ProgrammingError -from sqlalchemy.orm import scoped_session, sessionmaker - -from izzylib import ( - LruCache, - DotDict, - Path, - random_gen, - nfs_check, - izzylog -) - -SqlTypes = DotDict({t.lower(): getattr(Types, t) for t in dir(Types) if not t.startswith('_')}) - - -class SqlDatabase: - def __init__(self, dbtype='sqlite', tables={}, **kwargs): - self.db = self.__create_engine(dbtype, kwargs) - self.table = None - self.table_names = None - self.classes = kwargs.get('row_classes', CustomRows()) - self.cache = None - - self.session_class = kwargs.get('session_class', SqlSession) - self.sessions = {} - - self.setup_tables(tables) - self.setup_cache() - - - ## Leaving link to example code for read-only sqlite for later use - ## https://github.com/pudo/dataset/issues/136#issuecomment-128693122 - def __create_engine(self, dbtype, kwargs): - engine_args = [] - engine_kwargs = {} - - if not kwargs.get('name'): - raise KeyError('Database "name" is not set') - - engine_string = dbtype + '://' - - if dbtype == 'sqlite': - database = kwargs['name'] - - if nfs_check(database): - izzylog.error('Database file is on an NFS share which does not support locking. Any writes to the database will fail') - - engine_string += f'/{database}' - engine_kwargs['connect_args'] = {'check_same_thread': False} - - elif dbtype == 'postgresql': - ssl_context = kwargs.get('ssl') - - if ssl_context: - engine_kwargs['ssl_context'] = ssl_context - - else: - user = kwargs.get('user') - password = kwargs.get('pass') - host = kwargs.get('host', '/var/run/postgresql') - port = kwargs.get('port', 5432) - name = kwargs.get('name', 'postgres') - maxconn = kwargs.get('maxconnections', 25) - - if user: - if password: - engine_string += f'{user}:{password}@' - else: - engine_string += user + '@' - - if host == '/var/run/postgresql': - engine_string += f'/{name}:{port}/{name}' - - else: - engine_string += f'{host}:{port}/{name}' - - return create_engine(engine_string, *engine_args, **engine_kwargs) - - - @property - def session(self): - return self.session_class(self) - - - def close(self): - self.setup_cache() - - - def setup_cache(self): - self.cache = DotDict({table: LruCache() for table in self.table_names}) - - - def create_tables(self, *tables): - if not tables: - raise ValueError('No tables specified') - - new_tables = [self.table[table] for table in tables] - self.table.meta.create_all(bind=self.db, tables=new_tables) - - - def create_database(self): - if self.db.url.get_backend_name() == 'postgresql': - predb = create_engine(db.engine_string.replace(config.db.name, 'postgres', -1)) - conn = predb.connect() - conn.execute('commit') - - try: - conn.execute(f'CREATE DATABASE {config.db.name}') - - except ProgrammingError: - 'The database already exists, so just move along' - - except Exception as e: - conn.close() - raise e from None - - conn.close() - - self.table.meta.create_all(self.db) - - - def setup_tables(self, tables): - self.table = Tables(self, tables) - self.table_names = tables.keys() - - - def execute(self, string, values=[]): - with self.session as s: - s.execute(string, values) - - -class SqlSession(object): - def __init__(self, db): - self.closed = False - - self.database = db - self.classes = db.classes - self.session = sessionmaker(bind=db.db)() - self.table = db.table - self.cache = db.cache - - # session aliases - self.s = self.session - self.begin = self.s.begin - self.commit = self.s.commit - self.rollback = self.s.rollback - self.query = self.s.query - self.execute = self.s.execute - - # remove in the future - self.db = db - - self._setup() - - - def __enter__(self): - self.open() - return self - - - def __exit__(self, exctype, value, tb): - if tb: - self.rollback() - - self.close() - - - def open(self): - self.sessionid = random_gen(10) - self.db.sessions[self.sessionid] = self - - - def close(self): - self.commit() - self.s.close() - self.closed = True - - del self.db.sessions[self.sessionid] - - self.sessionid = None - - - def _setup(self): - pass - - - @property - def dirty(self): - return any([self.s.new, self.s.dirty, self.s.deleted]) - - - def count(self, table_name, **kwargs): - return self.query(self.table[table_name]).filter_by(**kwargs).count() - - - def fetch(self, table_name, single=True, orderby=None, orderdir='asc', **kwargs): - table = self.table[table_name] - RowClass = self.classes.get(table_name.capitalize()) - - query = self.query(table).filter_by(**kwargs) - - if not orderby: - rows = query.all() - - else: - if orderdir == 'asc': - rows = query.order_by(getattr(table.c, orderby).asc()).all() - - elif orderdir == 'desc': - rows = query.order_by(getattr(table.c, orderby).desc()).all() - - else: - raise ValueError(f'Unsupported order direction: {orderdir}') - - if single: - return RowClass(table_name, rows[0], self) if len(rows) > 0 else None - - return [RowClass(table_name, row, self) for row in rows] - - - def search(self, *args, **kwargs): - kwargs.pop('single', None) - return self.fetch(*args, single=False, **kwargs) - - - def insert(self, table_name, return_row=False, **kwargs): - row = self.fetch(table_name, **kwargs) - - if row: - row.update_session(self, **kwargs) - return - - table = self.table[table_name] - - if getattr(table, 'timestamp', None) and not kwargs.get('timestamp'): - kwargs['timestamp'] = datetime.now() - - self.execute(table.insert().values(**kwargs)) - - if return_row: - return self.fetch(table_name, **kwargs) - - - def update(self, table=None, rowid=None, row=None, return_row=False, **data): - if row: - if not getattr(row, '_table_name', None): - print(row) - print(dir(row)) - rowid = row.id - table = row._table_name - - if not rowid or not table: - raise ValueError('Missing row ID or table') - - tclass = self.table[table] - self.execute(tclass.update().where(tclass.c.id == rowid).values(**data)) - - if return_row: - return self.fetch(table, id=rowid) - - - def remove(self, table=None, rowid=None, row=None): - if row: - rowid = row.id - table = row._table_name - - if not rowid or not table: - raise ValueError('Missing row ID or table') - - self.execute(f'DELETE FROM {table} WHERE id={rowid}') - - - def drop_table(self, name): - if name not in self.get_tables(): - raise KeyError(f'Table does not exist: {name}') - - self.execute(f'DROP TABLE {name}') - - - def drop_tables(self): - tables = self.get_tables() - - for table in tables: - self.drop_table(table) - - - def get_columns(self, table): - if table not in self.get_tables(): - raise KeyError(f'Not an existing table: {table}') - - rows = self.execute('PRAGMA table_info(user)') - return [row[1] for row in rows] - - - def get_tables(self): - rows = self.execute("SELECT name FROM sqlite_master WHERE type IN ('table','view') and name NOT LIKE 'sqlite_%'") - return [row[0] for row in rows] - - - def append_column(self, table, column): - if column.name in self.get_columns(table): - logging.warning(f'Table "{table}" already has column "{column.name}"') - return - - self.execute(f'ALTER TABLE {table} ADD COLUMN {column.compile()}') - - - def append_column2(self, tbl, col): - table = self.table[tbl] - - try: - column = getattr(table.c, col) - - except AttributeError: - izzylog.error(f'Table "{tbl}" does not have column "{col}"') - return - - columns = [row[1] for row in self.execute(f'PRAGMA table_info({tbl})')] - - if col in self.get_columns(tbl): - izzylog.info(f'Column "{col}" already exists') - return - - sql = f'ALTER TABLE {tbl} ADD COLUMN {col} {column.type}' - - if not column.nullable: - sql += ' NOT NULL' - - if column.primary_key: - sql += ' PRIMARY KEY' - - if column.unique: - sql += ' UNIQUE' - - self.execute(sql) - - - def remove_column(self, tbl, col): - table = self.table[tbl] - column = getattr(table, col, None) - columns = [row[1] for row in self.execute(f'PRAGMA table_info({tbl})')] - - if col not in columns: - izzylog.info(f'Column "{col}" already exists') - return - - columns.remove(col) - coltext = ', '.join(columns) - - self.execute(f'CREATE TABLE {tbl}_temp AS SELECT {coltext} FROM {tbl}') - self.execute(f'DROP TABLE {tbl}') - self.execute(f'ALTER TABLE {tbl}_temp RENAME TO {tbl}') - - - def clear_table(self, table): - self.execute(f'DELETE FROM {table}') - - -class CustomRows(object): - def get(self, name): - return getattr(self, name, self.Row) - - - class Row(DotDict): - #_filter_columns = lambda self, row: [attr for attr in dir(row) if not attr.startswith('_') and attr != 'metadata'] - - - def __init__(self, table, row, session): - super().__init__() - - if row: - try: - self._update(row._asdict()) - except: - self._update(row) - - self._db = session.db - self._table_name = table - self._columns = self.keys() - - self.__run__(session) - - - ## Subclass Row and redefine this function - def __run__(self, s): - pass - - - def _filter_data(self): - data = {k: v for k,v in self.items() if k in self._columns} - - for k,v in self.items(): - if v.__class__ == DotDict: - data[k] = v.asDict() - - return data - - - def asDict(self): - return self._filter_data() - - - def _update(self, new_data={}, **kwargs): - kwargs.update(new_data) - - for k,v in kwargs.items(): - if type(v) == dict: - self[k] = DotDict(v) - - self[k] = v - - - def delete(self, s=None): - if s: - return self.delete_session(s) - - with self._db.session as s: - return self.delete_session(s) - - - def delete_session(self, s): - return s.remove(table=self._table_name, row=self) - - - def update(self, dict_data={}, s=None, **data): - dict_data.update(data) - self._update(dict_data) - - if s: - return self.update_session(s, **self._filter_data()) - - with self._db.session as s: - s.update(row=self, **self._filter_data()) - - - def update_session(self, s, dict_data={}, **data): - dict_data.update(data) - self._update(dict_data) - return s.update(table=self._table_name, row=self, **dict_data) - - -class Tables(DotDict): - def __init__(self, db, tables={}): - '"tables" should be a dict with the table names for keys and a list of Columns for values' - super().__init__() - - self.db = db - self.meta = MetaData() - - for name, table in tables.items(): - self.__setup_table(name, table) - - - def __setup_table(self, name, table): - columns = [col if type(col) == SqlColumn else SqlColumn(*col.get('args'), **col.get('kwargs')) for col in table] - self[name] = Table(name, self.meta, *columns) - - -class SqlColumn(sqlalchemy_column): - def __init__(self, name, stype=None, fkey=None, **kwargs): - if not stype and not kwargs: - if name == 'id': - stype = 'integer' - kwargs['primary_key'] = True - kwargs['autoincrement'] = True - - elif name == 'timestamp': - stype = 'datetime' - - else: - raise ValueError('Missing column type and options') - - stype = (stype.lower() if type(stype) == str else stype) or 'string' - - if type(stype) == str: - try: - stype = SqlTypes[stype.lower()] - - except KeyError: - raise KeyError(f'Invalid SQL data type: {stype}') - - options = [name, stype] - - if fkey: - options.append(ForeignKey(fkey)) - - super().__init__(*options, **kwargs) - - - def compile(self): - sql = f'{self.name} {self.type}' - - if not self.nullable: - sql += ' NOT NULL' - - if self.primary_key: - sql += ' PRIMARY KEY' - - if self.unique: - sql += ' UNIQUE' - - return sql diff --git a/sql/izzylib/sql/queries.py b/sql/izzylib/sql/queries.py deleted file mode 100644 index b780e9b..0000000 --- a/sql/izzylib/sql/queries.py +++ /dev/null @@ -1,415 +0,0 @@ -from datetime import datetime -from functools import partial -from izzylib import DotDict, Path - -from .types import BaseType, Type - - -placeholders = dict( - sqlite = '?', - postgresql = '%s' -) - - -## Data queries -class Delete: - def __init__(self, table, type='sqlite', **kwargs): - self.table = table - self.placeholder = placeholders[type] - self.keys = [] - self.values = [] - - for k,v in kwargs.items(): - self.keys.append(k) - self.values.append(v) - - - def __str__(self): - self.build(embed_values=True) - - - def build(self, comp_type='AND', embed_values=False): - sql = 'DELETE FROM {table} WHERE {kstring}' - - if not embed_values: - kstring = f' {comp_type.upper()} '.join([f'{k} = {self.placeholder}' for k in self.keys]) - return sql.format(table=self.table, kstring=kstring), self.values - - values = [] - - for idx, value in enumerate(self.values): - if type(value) == str: - values.append(f"{self.keys[idx]} = '{value}'") - - else: - values.append(f"{self.keys[idx]} = {value}") - - kstring = ','.join(values) - return sql.format(table=self.table, kstring=kstring, rowid=self.rowid) - - - def exec(self, session, comp_type='AND'): - return session.execute(*self.build(comp_type)) - - -class Insert: - def __init__(self, table, type='sqlite', **kwargs): - self.table = table - self.placeholder = placeholders[type] - self.keys = [] - self.values = [] - - for k, v in kwargs.items(): - self.keys.append(k) - self.values.append(v) - - - def __str__(self): - return self.build(embed_values=True) - - - def build(self, embed_values=False): - kstring = ','.join(self.keys) - - if not embed_values: - vstring = ','.join([self.placeholder for k in self.keys]) - return f'INSERT INTO {self.table} ({kstring}) VALUES({vstring})', self.values - - else: - vstring = ','.join(self.values) - return f'INSERT INTO {self.table} ({kstring}) VALUES({vstring})' - - - def exec(self, session): - return session.execute(*self.build()) - - -class Select: - def __init__(self, table, columns=[], type='sqlite', **kwargs): - self.placeholder = placeholders[type] - self.columns = columns - self.table = table - self.where = [] - self.where_build = [] - self._order = [] - self.keys = [] - self.values = [] - - self.equals = partial(self.__comparison, '=') - self.less = partial(self.__comparison, '<') - self.greater = partial(self.__comparison, '>') - self.like = partial(self.__comparison, 'LIKE') - - for k,v in kwargs.items(): - self.equals(k, v) - - - def __str__(self): - return self.build(embed_values=True) - - - def __comparison(self, comp, key, value): - self.values.append(value) - self.keys.append(key) - self.where.append(f'{key} {comp.upper()} {self.placeholder}') - self.where_build.append(f"{key} {comp.upper()} '{value}'" if type(key) == str else f"{key} {comp.upper()} {value}") - return self - - - def order(self, column, asc=True): - self._order = [column, 'ASC' if asc else 'DESC'] - return self - - - def build(self, comp_type='AND', embed_values=False): - if not self.columns: - cols = '*' - - else: - cols = ','.join('columns') - - sql_query = f'SELECT {cols} FROM {self.table}' - - if self.where: - where = f' {comp_type.upper()} '.join(self.where if not embed_values else self.where_build) - sql_query += f' WHERE {where}' - - if self._order: - col, order = self._order - sql_query += f' ORDER BY {col} {order}' - - if embed_values: - return sql_query - - return sql_query, self.values - - - def exec(self, session, comp_type='AND'): - return session.execute(*self.build(comp_type)) - - -class Update: - def __init__(self, table, rowid, type='sqlite', **kwargs): - self.placeholder = placeholders[type] - self.table = table - self.rowid = rowid - self.keys = [] - self.values = [] - - for k,v in kwargs.items(): - self.keys.append(k) - self.values.append(v) - - - def __str__(self): - return self.build(embed_values=True) - - - def build(self, embed_values=False): - sql = 'UPDATE {table} SET {kstring} WHERE id={rowid}' - - if not embed_values: - kstring = ','.join([f'{k} = {self.placeholder}' for k in self.keys]) - return sql.format(table=self.table, kstring=kstring, rowid=self.rowid), self.values - - values = [] - - for idx, value in enumerate(self.values): - if type(value) == str: - values.append(f"{self.keys[idx]} = '{value}'") - - else: - values.append(f"{self.keys[idx]} = {value}") - - kstring = ','.join(values) - return sql.format(table=self.table, kstring=kstring, rowid=self.rowid) - - - def exec(self, session): - return session.execute(*self.build()) - - -## Database objects -class Column: - def __init__(self, name, type='STRING', unique=False, nullable=True, default=None, primary_key=False, autoincrement=False, foreign_key=None): - self.name = name - self.type = type - self.nullable = nullable - self.default = default - self.primary_key = primary_key - self.autoincrement = autoincrement - self.unique = unique - - if any(map(isinstance, [foreign_key], [list, tuple, set])): - self.foreign_key = foreign_key - - else: - self.foreign_key = foreign_key.split('.') if foreign_key else None - - if autoincrement: - self.primary_key = True - self.type = Type['INTEGER'] - - if isinstance(self.type, BaseType): - self.type = self.type.name - - else: - if self.type.upper() in Type.keys(): - self.type = self.type.upper() - - else: - raise TypeError(f'Invalid SQL type: {self.type}') - - if foreign_key and len(self.foreign_key) != 2: - raise ValueError('Invalid foreign key. Must be in the format "table.column".') - - - def __str__(self): - return self.build() - - - def build(self, dbtype='sqlite'): - if dbtype == 'postgresql': - if self.type.lower() == 'string': - self.type = 'TEXT' - - elif self.type.lower() == 'datetime': - self.type = 'TIMESTAMPTZ' - - if self.autoincrement: - self.type = 'SERIAL' - self.autoincrement = False - - sql = f'{self.name} {self.type}' - - if self.primary_key: - sql += ' PRIMARY KEY' - - if self.autoincrement: - sql += ' AUTOINCREMENT' - - if self.unique: - sql += ' UNIQUE' - - if not self.nullable: - sql += ' NOT NULL' - - if self.default: - def_type = type(self.default) - - if self.default == 'CURRENT_TIMESTAMP': - if dbtype == 'sqlite': - sql += " DEFAULT (datetime('now', 'localtime'))" - - elif dbtype == 'postgresql': - sql += ' DEFAULT now()' - - else: - sql += f' DEFAULT {datetime.now().timestamp()}' - - elif def_type == str: - sql += f" DEFAULT '{self.default}'" - - elif def_type in [int, float]: - sql += f' DEFAULT {self.default}' - - elif def_type == bool and dbtype == 'sqlite': - sql += f' DEFAULT {int(self.default)}' - - else: - sql += f' DEFAULT {self.default}' - - print(sql) - return sql - - - def json(self): - return DotDict({ - 'type': self.type, - 'nullable': self.nullable, - 'default': self.default, - 'primary_key': self.primary_key, - 'autoincrement': self.autoincrement, - 'unique': self.unique, - 'foreign_key': self.foreign_key - }) - - -class Table(DotDict): - def __init__(self, name, *columns): - super().__init__() - self._name = name - self._foreign_keys = {} - - self.add_column(Column('id', autoincrement=True)) - - for column in columns: - self.add_column(column) - - - def __str__(self): - return self.build() - - - # this'll be useful later - def __call__(self, *args, **kwargs): - pass - - - @property - def name(self): - return self._name - - - def add_column(self, column): - self[column.name] = column - - if column.foreign_key: - self._foreign_keys[column.name] = column.foreign_key - - - def build(self, dbtype='sqlite'): - column_string = ',\n'.join([f'\t{col.build(dbtype)}' for col in self.values()]) - - if self._foreign_keys: - column_string += ',\n' - column_string += ',\n'.join([f'\tFOREIGN KEY ({column}) REFERENCES {key[0]} ({key[1]})' for column, key in self._foreign_keys.items()]) - - return f'''CREATE TABLE {self.name} ( -{column_string} -);''' - - - def json(self): - data = {} - - for name, column in self.items(): - data[name] = column.json() - - return data - - -class Tables(DotDict): - def __init__(self, *tables, data={}): - super().__init__() - - for table in tables: - self.add_table(table) - - if data: - self.from_dict(data) - - - def __str__(self): - return self.build() - - - @classmethod - def new_from_json_file(cls, path): - return cls(data=DotDict.new_from_json_file(path)) - - - def add_table(self, table): - self[table.name] = table - - - def build(self): - return '\n\n'.join([str(table) for table in self.values()]) - - - def load_json(self, path): - data = DotDict() - data.load_json(path) - - self.from_dict(data) - - - def save_json(self, path, indent='\t'): - self.to_dict().save_json(path, indent=indent) - - - def from_dict(self, data): - for name, columns in data.items(): - table = Table(name) - - for col, kwargs in columns.items(): - table.add_column(Column(col, - type = kwargs.get('type', 'STRING'), - nullable = kwargs.get('nullable', True), - default = kwargs.get('default'), - primary_key = kwargs.get('primary_key', False), - autoincrement = kwargs.get('autoincrement', False), - unique = kwargs.get('unique', False), - foreign_key = kwargs.get('foreign_key') - )) - - self.add_table(table) - - - def to_dict(self): - data = DotDict() - - for name, table in self.items(): - data[name] = table.json() - - return data diff --git a/sql/izzylib/sql/row.py b/sql/izzylib/sql/row.py deleted file mode 100644 index 2a5416d..0000000 --- a/sql/izzylib/sql/row.py +++ /dev/null @@ -1,19 +0,0 @@ -from izzylib import DotDict - - -class DbRow(DotDict): - def __init__(self, table, keys, values): - self.table = table - - super().__init__() - - for idx, key in enumerate(keys): - self[key] = values[idx] - - - def delete(self): - pass - - - def update(self, **kwargs): - pass diff --git a/sql/izzylib/sql/rows.py b/sql/izzylib/sql/rows.py new file mode 100644 index 0000000..23f3fda --- /dev/null +++ b/sql/izzylib/sql/rows.py @@ -0,0 +1,90 @@ +from izzylib import DotDict + + +class RowClasses(DotDict): + def __init__(self, *classes): + super().__init__() + + for rowclass in classes: + self.update({rowclass.__name__.lower(): rowclass}) + + + def get_class(self, name): + return self.get(name, Row) + + +class Row(DotDict): + def __init__(self, table, row, session): + super().__init__() + + if row: + try: + self._update(row._asdict()) + except: + self._update(row) + + self.__db = session.db + self.__table_name = table + + self.__run__(session) + + + @property + def db(self): + return self.__db + + + @property + def table(self): + return self.__table_name + + + @property + def columns(self): + return self.keys() + + + ## Subclass Row and redefine this function + def __run__(self, s): + pass + + + def _update(self, *args, **kwargs): + super().update(*args, **kwargs) + + + def delete(self, s=None): + izzylog.warning('deprecated function: Row.delete') + + if s: + return self.delete_session(s) + + with self.db.session as s: + return self.delete_session(s) + + + def delete_session(self, s): + izzylog.warning('deprecated function: Row.delete_session') + + return s.remove(table=self.table, row=self) + + + def update(self, dict_data={}, s=None, **data): + izzylog.warning('deprecated function: Row.update') + + dict_data.update(data) + self._update(dict_data) + + if s: + return self.update_session(s, **self) + + with self.db.session as s: + s.update(row=self, **self) + + + def update_session(self, s, dict_data={}, **data): + izzylog.warning('deprecated function: Row.update_session') + + dict_data.update(data) + self._update(dict_data) + return s.update(table=self.table, row=self, **dict_data) diff --git a/sql/izzylib/sql/session.py b/sql/izzylib/sql/session.py new file mode 100644 index 0000000..99dd7c3 --- /dev/null +++ b/sql/izzylib/sql/session.py @@ -0,0 +1,179 @@ +from izzylib import DotDict, random_gen, izzylog +from sqlalchemy import text +from sqlalchemy.orm import sessionmaker +from sqlalchemy.orm.session import Session as sqlalchemy_session + + +class Session(sqlalchemy_session): + def __init__(self, db, trans=False): + super().__init__(bind=db.db, future=True) + + self.closed = False + self.trans = trans + + self.database = db + self.classes = db.classes + self.cache = db.cache + + self.sessionid = random_gen(10) + self.database.sessions[self.sessionid] = self + + # remove in the future + self.db = db + + self._setup() + + + def __enter__(self): + if self.trans: + self.begin() + + return self + + + def __exit__(self, exctype, value, tb): + if self.in_transaction(): + if tb: + self.rollback() + + self.commit() + + self.close() + + + def _setup(self): + pass + + + @property + def table(self): + return self.db.table + + + def commit(self): + if not self.in_transaction(): + return + + super().commit() + + + def close(self): + super().close() + self.closed = True + + del self.db.sessions[self.sessionid] + + self.sessionid = None + + + def run(self, expression, **kwargs): + result = self.execute(text(expression), params=kwargs) + + try: + return result.mappings().all() + except Exception as e: + izzylog.verbose(f'Session.run: {e.__class__.__name__}: {e}') + return result + + + def count(self, table_name, **kwargs): + return self.query(self.table[table_name]).filter_by(**kwargs).count() + + + def fetch(self, table, single=True, orderby=None, orderdir='asc', **kwargs): + RowClass = self.classes.get_class(table.lower()) + + query = self.query(self.table[table]).filter_by(**kwargs) + + if not orderby: + rows = query.all() + + else: + if orderdir == 'asc': + rows = query.order_by(getattr(self.table[table].c, orderby).asc()).all() + + elif orderdir == 'desc': + rows = query.order_by(getattr(self.table[table].c, orderby).desc()).all() + + else: + raise ValueError(f'Unsupported order direction: {orderdir}') + + if single: + return RowClass(table, rows[0], self) if len(rows) > 0 else None + + return [RowClass(table, row, self) for row in rows] + + + def search(self, *args, **kwargs): + kwargs.pop('single', None) + return self.fetch(*args, single=False, **kwargs) + + + def insert(self, table, return_row=False, **kwargs): + row = self.fetch(table, **kwargs) + + if row: + row.update_session(self, **kwargs) + return + + if getattr(self.table[table], 'timestamp', None) and not kwargs.get('timestamp'): + kwargs['timestamp'] = datetime.now() + + return self.execute(self.table[table].insert().values(**kwargs)) + + if return_row: + return self.fetch(table, **kwargs) + + + def update(self, table=None, rowid=None, row=None, return_row=False, **kwargs): + if row: + rowid = row.id + table = row.table + + if not rowid or not table: + raise ValueError('Missing row ID or table') + + self.execute(self.table[table].update().where(self.table[table].c.id == rowid).values(**kwargs)) + + if return_row: + return self.fetch(table, id=rowid) + + + def remove(self, table=None, rowid=None, row=None): + if row: + rowid = row.id + table = row.table + + if not rowid or not table: + raise ValueError('Missing row ID or table') + + self.run(f'DELETE FROM {table} WHERE id=:id', id=rowid) + + + def append_column(self, table, column): + if column.name in self.db.get_columns(table): + logging.warning(f'Table "{table}" already has column "{column.name}"') + return + + self.run(f'ALTER TABLE {table} ADD COLUMN {column.compile()}') + + + def remove_column(self, tbl, col): + table = self.table[tbl] + column = getattr(table, col, None) + columns = self.db.get_columns(tbl) + + if col not in columns: + izzylog.info(f'Column "{col}" already exists') + return + + columns.remove(col) + coltext = ','.join(columns) + + self.run(f'CREATE TABLE {tbl}_temp AS SELECT {coltext} FROM {tbl}') + self.run(f'DROP TABLE {tbl}') + self.run(f'ALTER TABLE {tbl}_temp RENAME TO {tbl}') + + + def clear_table(self, table): + self.run(f'DELETE FROM {table}') diff --git a/sql/izzylib/sql/types.py b/sql/izzylib/sql/types.py deleted file mode 100644 index e53b400..0000000 --- a/sql/izzylib/sql/types.py +++ /dev/null @@ -1,19 +0,0 @@ -from enum import Enum -from izzylib import DotDict - - -class BaseType(Enum): - INTEGER = int - TEXT = str - BLOB = bytes - REAL = float - NUMERIC = float - - -Type = DotDict( - **{v: BaseType.INTEGER for v in ['INT', 'INTEGER', 'TINYINT', 'SMALLINT', 'MEDIUMINT', 'BIGINT', 'UNSIGNED BIG INT', 'INT2', 'INT8']}, - **{v: BaseType.TEXT for v in ['CHARACTER', 'VARCHAR', 'VARYING CHARACTER', 'NCHAR', 'NATIVE CHARACTER', 'NVARCHAR', 'TEXT', 'CLOB', 'STRING', 'JSON']}, - **{v: BaseType.BLOB for v in ['BYTES', 'BLOB']}, - **{v: BaseType.REAL for v in ['REAL', 'DOUBLE', 'DOUBLE PRECISION', 'FLOAT']}, - **{v: BaseType.NUMERIC for v in ['NUMERIC', 'DECIMAL', 'BOOLEAN', 'DATE', 'DATETIME']} -) From 9a2f0323beb375bbcaf8fe9a77561b96b6bcfd1d Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Fri, 17 Sep 2021 09:08:54 -0400 Subject: [PATCH 62/74] fix urllib3 client --- http_urllib_client/setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/http_urllib_client/setup.py b/http_urllib_client/setup.py index 492532a..66ad835 100644 --- a/http_urllib_client/setup.py +++ b/http_urllib_client/setup.py @@ -5,13 +5,13 @@ from setuptools import setup, find_namespace_packages requires = [ 'pillow==8.2.0', 'pycryptodome==3.10.1', - 'urllib==1.26.5', + 'urllib3==1.26.5', 'tldextract==3.1.0' ] setup( - name="IzzyLib Urllib3 Client", + name="IzzyLib HTTP Urllib Client", version='0.6.0', packages=find_namespace_packages(include=['izzylib.http_urllib_client']), python_requires='>=3.7.0', From a1abd0e4c772e705e969dc089ff8676b99c7fcee Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Fri, 17 Sep 2021 09:22:45 -0400 Subject: [PATCH 63/74] fix http_server --- http_server/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/http_server/setup.py b/http_server/setup.py index d3dd724..166b806 100644 --- a/http_server/setup.py +++ b/http_server/setup.py @@ -12,7 +12,7 @@ requires = [ setup( name="IzzyLib HTTP Server", version='0.6.0', - packages=find_namespace_packages(include=['izzylib.http_requests_client']), + packages=find_namespace_packages(include=['izzylib.http_http_server']), python_requires='>=3.7.0', install_requires=requires, include_package_data=False, From ab4b6b0cfb660d714ea788e91726982a08b4d8a9 Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Fri, 17 Sep 2021 09:25:53 -0400 Subject: [PATCH 64/74] really fix http_server this time --- http_server/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/http_server/setup.py b/http_server/setup.py index 166b806..cc64200 100644 --- a/http_server/setup.py +++ b/http_server/setup.py @@ -12,7 +12,7 @@ requires = [ setup( name="IzzyLib HTTP Server", version='0.6.0', - packages=find_namespace_packages(include=['izzylib.http_http_server']), + packages=find_namespace_packages(include=['izzylib.http_server']), python_requires='>=3.7.0', install_requires=requires, include_package_data=False, From 78417a89532cf3e9db6d1f040ee4baa0157df223 Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Fri, 17 Sep 2021 09:26:52 -0400 Subject: [PATCH 65/74] REALLY really fix http_server this time --- http_server/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/http_server/setup.py b/http_server/setup.py index cc64200..3c6de44 100644 --- a/http_server/setup.py +++ b/http_server/setup.py @@ -15,7 +15,7 @@ setup( packages=find_namespace_packages(include=['izzylib.http_server']), python_requires='>=3.7.0', install_requires=requires, - include_package_data=False, + include_package_data=True, author='Zoey Mae', author_email='admin@barkshark.xyz', description='An HTTP server based on Sanic', From 02c7d16cc5659d0fdca4100eedd32d1ae8a05ba7 Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Fri, 17 Sep 2021 09:30:56 -0400 Subject: [PATCH 66/74] really hoping it actually works this time --- http_server/MANIFEST.in | 1 + 1 file changed, 1 insertion(+) create mode 100644 http_server/MANIFEST.in diff --git a/http_server/MANIFEST.in b/http_server/MANIFEST.in new file mode 100644 index 0000000..7f7f569 --- /dev/null +++ b/http_server/MANIFEST.in @@ -0,0 +1 @@ +recursive-include izzylib/http_server/frontend From 6d5a38a4d0492e6fa12936f8ff3d4cdf805f3ebb Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Fri, 17 Sep 2021 09:32:38 -0400 Subject: [PATCH 67/74] heck --- http_server/MANIFEST.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/http_server/MANIFEST.in b/http_server/MANIFEST.in index 7f7f569..8b1396a 100644 --- a/http_server/MANIFEST.in +++ b/http_server/MANIFEST.in @@ -1 +1 @@ -recursive-include izzylib/http_server/frontend +recursive-include izzylib/http_server/frontend * From 96f3e8a2d3386e2ffc7c72bbf2a7cca7a17ea86f Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Fri, 17 Sep 2021 09:49:43 -0400 Subject: [PATCH 68/74] fix link creation and deletion --- Makefile | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 4768b4f..9720d73 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,8 @@ setup-deps: rmlinks: rm base/izzylib/dbus rm base/izzylib/hasher - rm base/izzylib/http_requests_client + rm base/izzylib/http_urllib_client + rm base/izzylib/http_server rm base/izzylib/sql rm base/izzylib/template rm base/izzylib/tinydb @@ -16,7 +17,8 @@ rmlinks: mklinks: ln -sr dbus/izzylib/dbus base/izzylib/ ln -sr hasher/izzylib/hasher base/izzylib/ - ln -sr requests_client/izzylib/http_requests_client base/izzylib/ + ln -sr http_urllib_client/izzylib/http_urllib_client base/izzylib/ + ln -sr http_server/izzylib/http_server base/izzylib/ ln -sr sql/izzylib/sql base/izzylib/ ln -sr template/izzylib/template base/izzylib/ ln -sr tinydb/izzylib/tinydb base/izzylib/ From 3d0c813a32528f92c4541f179b479c93d76c2e7f Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Fri, 17 Sep 2021 12:52:47 -0400 Subject: [PATCH 69/74] fix http_server.Request --- http_server/izzylib/http_server/request.py | 6 +++--- .../izzylib/http_urllib_client/signatures.py | 10 ++++++++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/http_server/izzylib/http_server/request.py b/http_server/izzylib/http_server/request.py index dde7d2a..90bb7db 100644 --- a/http_server/izzylib/http_server/request.py +++ b/http_server/izzylib/http_server/request.py @@ -7,10 +7,10 @@ from .misc import Headers class Request(sanic.request.Request): - def __init__(self, url_bytes, headers, version, method, transport, app): - super().__init__(url_bytes, headers, version, method, transport, app) + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) - self.Headers = Headers(headers) + self.Headers = Headers(self.headers) self.address = self.headers.get('x-real-ip', self.forwarded.get('for', self.remote_addr)) self.data = Data(self) self.template = self.app.template diff --git a/http_urllib_client/izzylib/http_urllib_client/signatures.py b/http_urllib_client/izzylib/http_urllib_client/signatures.py index 452d0c0..e73c043 100644 --- a/http_urllib_client/izzylib/http_urllib_client/signatures.py +++ b/http_urllib_client/izzylib/http_urllib_client/signatures.py @@ -9,7 +9,7 @@ from base64 import b64decode, b64encode from datetime import datetime from functools import lru_cache from izzylib import DefaultDotDict, DotDict -from izzylib import izzylog as logging +from izzylib import izzylog from tldextract import extract from urllib.parse import urlparse @@ -191,7 +191,13 @@ async def verify_request(request, actor: dict=None): actor: A dictionary containing the activitypub actor and the link to the pubkey used for verification ''' - return verify_headers(request.Headers.to_dict(), request.method, request.path, actor, request.body) + return verify_headers( + request.Headers.to_dict(), + request.method, + request.path, + actor = actor, + body = request.body + ) From e36fcef79005c4765c28101687ce4aa1a403e135 Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Fri, 17 Sep 2021 13:25:28 -0400 Subject: [PATCH 70/74] sql: fix result returning in Session.insert --- sql/izzylib/sql/session.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/izzylib/sql/session.py b/sql/izzylib/sql/session.py index 99dd7c3..a5773f1 100644 --- a/sql/izzylib/sql/session.py +++ b/sql/izzylib/sql/session.py @@ -119,7 +119,7 @@ class Session(sqlalchemy_session): if getattr(self.table[table], 'timestamp', None) and not kwargs.get('timestamp'): kwargs['timestamp'] = datetime.now() - return self.execute(self.table[table].insert().values(**kwargs)) + self.execute(self.table[table].insert().values(**kwargs)) if return_row: return self.fetch(table, **kwargs) From a8f1b832569fe3d0135f169a5acb88f3d960af28 Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Fri, 17 Sep 2021 13:41:49 -0400 Subject: [PATCH 71/74] http_urllib_client: include exceptions --- .../izzylib/http_urllib_client/__init__.py | 1 + .../izzylib/http_urllib_client/error.py | 36 +++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 http_urllib_client/izzylib/http_urllib_client/error.py diff --git a/http_urllib_client/izzylib/http_urllib_client/__init__.py b/http_urllib_client/izzylib/http_urllib_client/__init__.py index d3a9112..df69254 100644 --- a/http_urllib_client/izzylib/http_urllib_client/__init__.py +++ b/http_urllib_client/izzylib/http_urllib_client/__init__.py @@ -10,6 +10,7 @@ from .signatures import ( ) +from . import error from .client import HttpUrllibClient, set_default_client from .request import HttpUrllibRequest from .response import HttpUrllibResponse diff --git a/http_urllib_client/izzylib/http_urllib_client/error.py b/http_urllib_client/izzylib/http_urllib_client/error.py new file mode 100644 index 0000000..958074d --- /dev/null +++ b/http_urllib_client/izzylib/http_urllib_client/error.py @@ -0,0 +1,36 @@ +from urllib3.exceptions import ( + HTTPError, + PoolError, + RequestError, + SSLError, + ProxyError, + DecodeError, + ProtocolError, + MaxRetryError, + HostChangedError, + TimeoutStateError, + TimeoutError, + ReadTimeoutError, + NewConnectionError, + EmptyPoolError, + ClosedPoolError, + LocationValueError, + LocationParseError, + URLSchemeUnknown, + ResponseError, + SecurityWarning, + InsecureRequestWarning, + SystemTimeWarning, + InsecurePlatformWarning, + SNIMissingWarning, + DependencyWarning, + ResponseNotChunked, + BodyNotHttplibCompatible, + IncompleteRead, + InvalidChunkLength, + InvalidHeader, + ProxySchemeUnknown, + ProxySchemeUnsupported, + HeaderParsingError, + UnrewindableBodyError +) From 782f83fbd4e36a6866d3b39ce904a77ac230b259 Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Fri, 17 Sep 2021 14:36:39 -0400 Subject: [PATCH 72/74] merge back into one module --- .gitignore | 11 -- MANIFEST.in | 1 + README.md | 34 ++-- base/setup.py | 36 ---- dbus/setup.py | 41 ----- hasher/setup.py | 44 ----- http_server/MANIFEST.in | 1 - http_server/setup.py | 44 ----- http_urllib_client/setup.py | 45 ----- {base/izzylib => izzylib}/__init__.py | 0 {base/izzylib => izzylib}/cache.py | 0 {base/izzylib => izzylib}/connection.py | 0 {dbus/izzylib => izzylib}/dbus/__init__.py | 0 izzylib/dbus/types.py | 85 +++++++++ {base/izzylib => izzylib}/dotdict.py | 0 {base/izzylib => izzylib}/exceptions.py | 0 .../izzylib => izzylib}/hasher/__init__.py | 0 {hasher/izzylib => izzylib}/hasher/hasher.py | 0 {base/izzylib => izzylib}/http_client.py | 0 .../http_server/__init__.py | 0 .../http_server/activitypub.py | 0 .../http_server/application.py | 0 .../izzylib => izzylib}/http_server/config.py | 0 .../http_server/error_handlers.py | 0 .../http_server/frontend/base.css | 0 .../http_server/frontend/base.haml | 0 .../http_server/frontend/error.haml | 0 .../http_server/frontend/menu.haml | 0 .../http_server/frontend/static/icon512.png | Bin .../http_server/frontend/static/icon64.png | Bin .../http_server/frontend/static/menu.js | 0 .../http_server/frontend/static/menu.svg | 0 .../static/nunito/NunitoSans-Black.ttf | Bin .../static/nunito/NunitoSans-Black.woff2 | Bin .../static/nunito/NunitoSans-BlackItalic.ttf | Bin .../nunito/NunitoSans-BlackItalic.woff2 | Bin .../static/nunito/NunitoSans-Bold.ttf | Bin .../static/nunito/NunitoSans-Bold.woff2 | Bin .../static/nunito/NunitoSans-BoldItalic.ttf | Bin .../static/nunito/NunitoSans-BoldItalic.woff2 | Bin .../static/nunito/NunitoSans-ExtraBold.ttf | Bin .../static/nunito/NunitoSans-ExtraBold.woff2 | Bin .../nunito/NunitoSans-ExtraBoldItalic.ttf | Bin .../nunito/NunitoSans-ExtraBoldItalic.woff2 | Bin .../static/nunito/NunitoSans-ExtraLight.ttf | Bin .../static/nunito/NunitoSans-ExtraLight.woff2 | Bin .../nunito/NunitoSans-ExtraLightItalic.ttf | Bin .../nunito/NunitoSans-ExtraLightItalic.woff2 | Bin .../static/nunito/NunitoSans-Italic.ttf | Bin .../static/nunito/NunitoSans-Italic.woff2 | Bin .../static/nunito/NunitoSans-Light.ttf | Bin .../static/nunito/NunitoSans-Light.woff2 | Bin .../static/nunito/NunitoSans-LightItalic.ttf | Bin .../nunito/NunitoSans-LightItalic.woff2 | Bin .../static/nunito/NunitoSans-Regular.ttf | Bin .../static/nunito/NunitoSans-Regular.woff2 | Bin .../static/nunito/NunitoSans-SemiBold.ttf | Bin .../static/nunito/NunitoSans-SemiBold.woff2 | Bin .../nunito/NunitoSans-SemiBoldItalic.ttf | Bin .../nunito/NunitoSans-SemiBoldItalic.woff2 | Bin .../static/nunito/SIL Open Font License.txt | 0 .../http_server/middleware.py | 0 .../izzylib => izzylib}/http_server/misc.py | 0 .../http_server/request.py | 0 .../http_server/response.py | 0 .../izzylib => izzylib}/http_server/view.py | 0 .../http_urllib_client/__init__.py | 0 .../http_urllib_client/client.py | 0 .../http_urllib_client/error.py | 0 .../http_urllib_client/request.py | 0 .../http_urllib_client/response.py | 0 .../http_urllib_client/signatures.py | 0 {base/izzylib => izzylib}/logging.py | 0 {base/izzylib => izzylib}/misc.py | 0 {base/izzylib => izzylib}/path.py | 0 {sql/izzylib => izzylib}/sql/__init__.py | 0 {sql/izzylib => izzylib}/sql/column.py | 0 {sql/izzylib => izzylib}/sql/database.py | 0 {sql/izzylib => izzylib}/sql/rows.py | 0 {sql/izzylib => izzylib}/sql/session.py | 0 {sql/izzylib => izzylib}/sql/sqlite_server.py | 0 .../izzylib => izzylib}/template/__init__.py | 0 pyproject.toml | 3 + requirements.txt | 16 -- setup.cfg | 63 +++++++ setup.py | 94 ---------- sql/setup.py | 43 ----- template/setup.py | 46 ----- tinydb/izzylib/tinydb/__init__.py | 1 - tinydb/izzylib/tinydb/tiny.py | 174 ------------------ tinydb/setup.py | 45 ----- 91 files changed, 164 insertions(+), 663 deletions(-) create mode 100644 MANIFEST.in delete mode 100755 base/setup.py delete mode 100644 dbus/setup.py delete mode 100644 hasher/setup.py delete mode 100644 http_server/MANIFEST.in delete mode 100644 http_server/setup.py delete mode 100644 http_urllib_client/setup.py rename {base/izzylib => izzylib}/__init__.py (100%) rename {base/izzylib => izzylib}/cache.py (100%) rename {base/izzylib => izzylib}/connection.py (100%) rename {dbus/izzylib => izzylib}/dbus/__init__.py (100%) create mode 100644 izzylib/dbus/types.py rename {base/izzylib => izzylib}/dotdict.py (100%) rename {base/izzylib => izzylib}/exceptions.py (100%) rename {hasher/izzylib => izzylib}/hasher/__init__.py (100%) rename {hasher/izzylib => izzylib}/hasher/hasher.py (100%) rename {base/izzylib => izzylib}/http_client.py (100%) rename {http_server/izzylib => izzylib}/http_server/__init__.py (100%) rename {http_server/izzylib => izzylib}/http_server/activitypub.py (100%) rename {http_server/izzylib => izzylib}/http_server/application.py (100%) rename {http_server/izzylib => izzylib}/http_server/config.py (100%) rename {http_server/izzylib => izzylib}/http_server/error_handlers.py (100%) rename {http_server/izzylib => izzylib}/http_server/frontend/base.css (100%) rename {http_server/izzylib => izzylib}/http_server/frontend/base.haml (100%) rename {http_server/izzylib => izzylib}/http_server/frontend/error.haml (100%) rename {http_server/izzylib => izzylib}/http_server/frontend/menu.haml (100%) rename {http_server/izzylib => izzylib}/http_server/frontend/static/icon512.png (100%) rename {http_server/izzylib => izzylib}/http_server/frontend/static/icon64.png (100%) rename {http_server/izzylib => izzylib}/http_server/frontend/static/menu.js (100%) rename {http_server/izzylib => izzylib}/http_server/frontend/static/menu.svg (100%) rename {http_server/izzylib => izzylib}/http_server/frontend/static/nunito/NunitoSans-Black.ttf (100%) rename {http_server/izzylib => izzylib}/http_server/frontend/static/nunito/NunitoSans-Black.woff2 (100%) rename {http_server/izzylib => izzylib}/http_server/frontend/static/nunito/NunitoSans-BlackItalic.ttf (100%) rename {http_server/izzylib => izzylib}/http_server/frontend/static/nunito/NunitoSans-BlackItalic.woff2 (100%) rename {http_server/izzylib => izzylib}/http_server/frontend/static/nunito/NunitoSans-Bold.ttf (100%) rename {http_server/izzylib => izzylib}/http_server/frontend/static/nunito/NunitoSans-Bold.woff2 (100%) rename {http_server/izzylib => izzylib}/http_server/frontend/static/nunito/NunitoSans-BoldItalic.ttf (100%) rename {http_server/izzylib => izzylib}/http_server/frontend/static/nunito/NunitoSans-BoldItalic.woff2 (100%) rename {http_server/izzylib => izzylib}/http_server/frontend/static/nunito/NunitoSans-ExtraBold.ttf (100%) rename {http_server/izzylib => izzylib}/http_server/frontend/static/nunito/NunitoSans-ExtraBold.woff2 (100%) rename {http_server/izzylib => izzylib}/http_server/frontend/static/nunito/NunitoSans-ExtraBoldItalic.ttf (100%) rename {http_server/izzylib => izzylib}/http_server/frontend/static/nunito/NunitoSans-ExtraBoldItalic.woff2 (100%) rename {http_server/izzylib => izzylib}/http_server/frontend/static/nunito/NunitoSans-ExtraLight.ttf (100%) rename {http_server/izzylib => izzylib}/http_server/frontend/static/nunito/NunitoSans-ExtraLight.woff2 (100%) rename {http_server/izzylib => izzylib}/http_server/frontend/static/nunito/NunitoSans-ExtraLightItalic.ttf (100%) rename {http_server/izzylib => izzylib}/http_server/frontend/static/nunito/NunitoSans-ExtraLightItalic.woff2 (100%) rename {http_server/izzylib => izzylib}/http_server/frontend/static/nunito/NunitoSans-Italic.ttf (100%) rename {http_server/izzylib => izzylib}/http_server/frontend/static/nunito/NunitoSans-Italic.woff2 (100%) rename {http_server/izzylib => izzylib}/http_server/frontend/static/nunito/NunitoSans-Light.ttf (100%) rename {http_server/izzylib => izzylib}/http_server/frontend/static/nunito/NunitoSans-Light.woff2 (100%) rename {http_server/izzylib => izzylib}/http_server/frontend/static/nunito/NunitoSans-LightItalic.ttf (100%) rename {http_server/izzylib => izzylib}/http_server/frontend/static/nunito/NunitoSans-LightItalic.woff2 (100%) rename {http_server/izzylib => izzylib}/http_server/frontend/static/nunito/NunitoSans-Regular.ttf (100%) rename {http_server/izzylib => izzylib}/http_server/frontend/static/nunito/NunitoSans-Regular.woff2 (100%) rename {http_server/izzylib => izzylib}/http_server/frontend/static/nunito/NunitoSans-SemiBold.ttf (100%) rename {http_server/izzylib => izzylib}/http_server/frontend/static/nunito/NunitoSans-SemiBold.woff2 (100%) rename {http_server/izzylib => izzylib}/http_server/frontend/static/nunito/NunitoSans-SemiBoldItalic.ttf (100%) rename {http_server/izzylib => izzylib}/http_server/frontend/static/nunito/NunitoSans-SemiBoldItalic.woff2 (100%) rename {http_server/izzylib => izzylib}/http_server/frontend/static/nunito/SIL Open Font License.txt (100%) rename {http_server/izzylib => izzylib}/http_server/middleware.py (100%) rename {http_server/izzylib => izzylib}/http_server/misc.py (100%) rename {http_server/izzylib => izzylib}/http_server/request.py (100%) rename {http_server/izzylib => izzylib}/http_server/response.py (100%) rename {http_server/izzylib => izzylib}/http_server/view.py (100%) rename {http_urllib_client/izzylib => izzylib}/http_urllib_client/__init__.py (100%) rename {http_urllib_client/izzylib => izzylib}/http_urllib_client/client.py (100%) rename {http_urllib_client/izzylib => izzylib}/http_urllib_client/error.py (100%) rename {http_urllib_client/izzylib => izzylib}/http_urllib_client/request.py (100%) rename {http_urllib_client/izzylib => izzylib}/http_urllib_client/response.py (100%) rename {http_urllib_client/izzylib => izzylib}/http_urllib_client/signatures.py (100%) rename {base/izzylib => izzylib}/logging.py (100%) rename {base/izzylib => izzylib}/misc.py (100%) rename {base/izzylib => izzylib}/path.py (100%) rename {sql/izzylib => izzylib}/sql/__init__.py (100%) rename {sql/izzylib => izzylib}/sql/column.py (100%) rename {sql/izzylib => izzylib}/sql/database.py (100%) rename {sql/izzylib => izzylib}/sql/rows.py (100%) rename {sql/izzylib => izzylib}/sql/session.py (100%) rename {sql/izzylib => izzylib}/sql/sqlite_server.py (100%) rename {template/izzylib => izzylib}/template/__init__.py (100%) create mode 100644 pyproject.toml delete mode 100644 requirements.txt create mode 100644 setup.cfg delete mode 100644 setup.py delete mode 100644 sql/setup.py delete mode 100644 template/setup.py delete mode 100644 tinydb/izzylib/tinydb/__init__.py delete mode 100644 tinydb/izzylib/tinydb/tiny.py delete mode 100644 tinydb/setup.py diff --git a/.gitignore b/.gitignore index d383997..a893c51 100644 --- a/.gitignore +++ b/.gitignore @@ -116,14 +116,3 @@ dmypy.json test*.py reload.cfg - -# symlinks -/izzylib -/base/izzylib/dbus -/base/izzylib/hasher -/base/izzylib/http_urllib_client -/base/izzylib/http_server -/base/izzylib/mbus -/base/izzylib/sql -/base/izzylib/template -/base/izzylib/tinydb diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..e83fa28 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1 @@ +recursive-include izzylib * diff --git a/README.md b/README.md index 5b6417b..4e9cdd3 100644 --- a/README.md +++ b/README.md @@ -4,29 +4,19 @@ These are just a number of functions I keep reusing over and over again in most ## Installation -You only need to install the base and whatever sub-modules you want to use - ### From Git - $(venv)/bin/python -m pip install -e "git+https://git.barkshark.xyz/izaliamae/izzylib.git@rework#egg=izzylib-base&subdirectory=base" + $(venv)/bin/python -m pip install -e "git+https://git.barkshark.xyz/izaliamae/izzylib.git@rework" - $(venv)/bin/python -m pip install -e "git+https://git.barkshark.xyz/izaliamae/izzylib.git@rework#egg=izzylib-dbus&subdirectory=dbus" +optional dependencies - $(venv)/bin/python -m pip install -e "git+https://git.barkshark.xyz/izaliamae/izzylib.git@rework#egg=izzylib-hasher&subdirectory=hasher" - - $(venv)/bin/python -m pip install -e "git+https://git.barkshark.xyz/izaliamae/izzylib.git@rework#egg=izzylib-http-server&subdirectory=http_server" - - $(venv)/bin/python -m pip install -e "git+https://git.barkshark.xyz/izaliamae/izzylib.git@rework#egg=izzylib-http-urllib-client&subdirectory=http_urllib_client" - - $(venv)/bin/python -m pip install -e "git+https://git.barkshark.xyz/izaliamae/izzylib.git@rework#egg=izzylib-sql&subdirectory=sql" - - $(venv)/bin/python -m pip install -e "git+https://git.barkshark.xyz/izaliamae/izzylib.git@rework#egg=izzylib-templates&subdirectory=template" - - $(venv)/bin/python -m pip install -e "git+https://git.barkshark.xyz/izaliamae/izzylib.git@rework#egg=izzylib-tinydb&subdirectory=tinydb" - -### From Source - - $(venv)/bin/python setup.py install ['all' or a combination of these: dbus hasher http_server http_urllib_client sql template tinydb] +- dbus +- hasher +- http_server +- http_urllib_client +- sql +- template +- tinydb ## Documentation @@ -36,13 +26,13 @@ Most useful classes and functions are imported in the module root, so you don't This is fine: - from izzylib import SqlDatabase + from izzylib import Database and points to: - from izzylib.sql.generic import SqlDatabase + from izzylib.sql.database import Database -Or even simply do `import izzylib` and use `izzylib.SqlDatabase()`. +Or even simply do `import izzylib` and use `izzylib.Database()`. ### Usage diff --git a/base/setup.py b/base/setup.py deleted file mode 100755 index 6b78e70..0000000 --- a/base/setup.py +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env python3 -from setuptools import setup, find_namespace_packages - - -setup( - name="IzzyLib Base", - version='0.6.0', - packages=find_namespace_packages(include=['izzylib']), - python_requires='>=3.7.0', - include_package_data=False, - author='Zoey Mae', - author_email='admin@barkshark.xyz', - description='a collection of often-used functions and classes', - keywords='web http client', - url='https://git.barkshark.xyz/izaliamae/izzylib', - project_urls={ - 'Bug Tracker': 'https://git.barkshark.xyz/izaliamae/izzylib/issues', - 'Documentation': 'https://git.barkshark.xyz/izaliamae/izzylib/wiki', - 'Source Code': 'https://git.barkshark.xyz/izaliamae/izzylib' - }, - - classifiers=[ - 'License :: Co-operative Non-violent Public License (CNPL 6+)', - 'Development Status :: 3 - Alpha', - 'Intended Audience :: Information Technology', - 'Programming Language :: Python :: 3.7', - 'Programming Language :: Python :: 3.8', - 'Programming Language :: Python :: 3.9', - 'Operating System :: POSIX', - 'Operating System :: MacOS :: MacOS X', - 'Operating System :: Microsoft :: Windows', - 'Topic :: Internet :: WWW/HTTP', - 'Topic :: Software Development :: Libraries', - 'Topic :: Software Development :: Libraries :: Python Modules' - ] -) diff --git a/dbus/setup.py b/dbus/setup.py deleted file mode 100644 index 826eab4..0000000 --- a/dbus/setup.py +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/env python3 -from setuptools import setup, find_namespace_packages - - -requires = [ - 'dasbus==1.6' -] - - -setup( - name="IzzyLib DBus", - version='0.6.0', - packages=find_namespace_packages(include=['izzylib.dbus']), - python_requires='>=3.7.0', - install_requires=requires, - include_package_data=False, - author='Zoey Mae', - author_email='admin@barkshark.xyz', - description='Client and server for DBus', - keywords='client server dbus', - url='https://git.barkshark.xyz/izaliamae/izzylib', - project_urls={ - 'Bug Tracker': 'https://git.barkshark.xyz/izaliamae/izzylib/issues', - 'Documentation': 'https://git.barkshark.xyz/izaliamae/izzylib/wiki', - 'Source Code': 'https://git.barkshark.xyz/izaliamae/izzylib' - }, - - classifiers=[ - 'Development Status :: 3 - Alpha', - 'Intended Audience :: Information Technology', - 'License :: Co-operative Non-violent Public License (CNPL 6+)', - 'Programming Language :: Python :: 3.7', - 'Programming Language :: Python :: 3.8', - 'Programming Language :: Python :: 3.9', - 'Operating System :: POSIX', - 'Operating System :: MacOS :: MacOS X', - 'Operating System :: Microsoft :: Windows', - 'Topic :: Software Development :: Libraries', - 'Topic :: Software Development :: Libraries :: Python Modules' - ] -) diff --git a/hasher/setup.py b/hasher/setup.py deleted file mode 100644 index 35ac1d7..0000000 --- a/hasher/setup.py +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env python3 -from setuptools import setup, find_namespace_packages - - -requires = [ - 'argon2-cffi==20.1.0' -] - - -setup( - name="IzzyLib Password Hasher", - version='0.6.0', - packages=find_namespace_packages(include=['izzylib.hasher']), - python_requires='>=3.7.0', - install_requires=requires, - include_package_data=False, - author='Zoey Mae', - author_email='admin@barkshark.xyz', - description='a collection of often-used functions and classes', - keywords='web http server templates argon2 jinja haml', - url='https://git.barkshark.xyz/izaliamae/izzylib', - project_urls={ - 'Bug Tracker': 'https://git.barkshark.xyz/izaliamae/izzylib/issues', - 'Documentation': 'https://git.barkshark.xyz/izaliamae/izzylib/wiki', - 'Source Code': 'https://git.barkshark.xyz/izaliamae/izzylib' - }, - - classifiers=[ - 'Development Status :: 3 - Alpha', - 'Intended Audience :: Information Technology', - 'License :: Co-operative Non-violent Public License (CNPL 6+)', - 'Programming Language :: Python :: 3.7', - 'Programming Language :: Python :: 3.8', - 'Programming Language :: Python :: 3.9', - 'Operating System :: POSIX', - 'Operating System :: MacOS :: MacOS X', - 'Operating System :: Microsoft :: Windows', - 'Topic :: Internet :: WWW/HTTP', - 'Topic :: Internet :: WWW/HTTP :: Dynamic Content', - 'Topic :: Internet :: WWW/HTTP :: HTTP Servers', - 'Topic :: Software Development :: Libraries', - 'Topic :: Software Development :: Libraries :: Python Modules' - ] -) diff --git a/http_server/MANIFEST.in b/http_server/MANIFEST.in deleted file mode 100644 index 8b1396a..0000000 --- a/http_server/MANIFEST.in +++ /dev/null @@ -1 +0,0 @@ -recursive-include izzylib/http_server/frontend * diff --git a/http_server/setup.py b/http_server/setup.py deleted file mode 100644 index 3c6de44..0000000 --- a/http_server/setup.py +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env python3 -from setuptools import setup, find_namespace_packages - - -requires = [ - 'sanic>=20.12.3', - 'sanic-cors>=1.0.0', - 'envbash>=1.0.0' -] - - -setup( - name="IzzyLib HTTP Server", - version='0.6.0', - packages=find_namespace_packages(include=['izzylib.http_server']), - python_requires='>=3.7.0', - install_requires=requires, - include_package_data=True, - author='Zoey Mae', - author_email='admin@barkshark.xyz', - description='An HTTP server based on Sanic', - keywords='web http server', - url='https://git.barkshark.xyz/izaliamae/izzylib', - project_urls={ - 'Bug Tracker': 'https://git.barkshark.xyz/izaliamae/izzylib/issues', - 'Documentation': 'https://git.barkshark.xyz/izaliamae/izzylib/wiki', - 'Source Code': 'https://git.barkshark.xyz/izaliamae/izzylib' - }, - - classifiers=[ - 'Development Status :: 3 - Alpha', - 'Intended Audience :: Information Technology', - 'License :: Co-operative Non-violent Public License (CNPL 6+)', - 'Programming Language :: Python :: 3.7', - 'Programming Language :: Python :: 3.8', - 'Programming Language :: Python :: 3.9', - 'Operating System :: POSIX', - 'Operating System :: MacOS :: MacOS X', - 'Operating System :: Microsoft :: Windows', - 'Topic :: Internet :: WWW/HTTP', - 'Topic :: Software Development :: Libraries', - 'Topic :: Software Development :: Libraries :: Python Modules' - ] -) diff --git a/http_urllib_client/setup.py b/http_urllib_client/setup.py deleted file mode 100644 index 66ad835..0000000 --- a/http_urllib_client/setup.py +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/env python3 -from setuptools import setup, find_namespace_packages - - -requires = [ - 'pillow==8.2.0', - 'pycryptodome==3.10.1', - 'urllib3==1.26.5', - 'tldextract==3.1.0' -] - - -setup( - name="IzzyLib HTTP Urllib Client", - version='0.6.0', - packages=find_namespace_packages(include=['izzylib.http_urllib_client']), - python_requires='>=3.7.0', - install_requires=requires, - include_package_data=False, - author='Zoey Mae', - author_email='admin@barkshark.xyz', - description='A Urllib3 client with support for http header signing and verifying', - keywords='web http client', - url='https://git.barkshark.xyz/izaliamae/izzylib', - project_urls={ - 'Bug Tracker': 'https://git.barkshark.xyz/izaliamae/izzylib/issues', - 'Documentation': 'https://git.barkshark.xyz/izaliamae/izzylib/wiki', - 'Source Code': 'https://git.barkshark.xyz/izaliamae/izzylib' - }, - - classifiers=[ - 'Development Status :: 3 - Alpha', - 'Intended Audience :: Information Technology', - 'License :: Co-operative Non-violent Public License (CNPL 6+)', - 'Programming Language :: Python :: 3.7', - 'Programming Language :: Python :: 3.8', - 'Programming Language :: Python :: 3.9', - 'Operating System :: POSIX', - 'Operating System :: MacOS :: MacOS X', - 'Operating System :: Microsoft :: Windows', - 'Topic :: Internet :: WWW/HTTP', - 'Topic :: Software Development :: Libraries', - 'Topic :: Software Development :: Libraries :: Python Modules' - ] -) diff --git a/base/izzylib/__init__.py b/izzylib/__init__.py similarity index 100% rename from base/izzylib/__init__.py rename to izzylib/__init__.py diff --git a/base/izzylib/cache.py b/izzylib/cache.py similarity index 100% rename from base/izzylib/cache.py rename to izzylib/cache.py diff --git a/base/izzylib/connection.py b/izzylib/connection.py similarity index 100% rename from base/izzylib/connection.py rename to izzylib/connection.py diff --git a/dbus/izzylib/dbus/__init__.py b/izzylib/dbus/__init__.py similarity index 100% rename from dbus/izzylib/dbus/__init__.py rename to izzylib/dbus/__init__.py diff --git a/izzylib/dbus/types.py b/izzylib/dbus/types.py new file mode 100644 index 0000000..c79e536 --- /dev/null +++ b/izzylib/dbus/types.py @@ -0,0 +1,85 @@ +import typing + + +class DBusType(typing.NewType): + def __init__(self, name, type, string): + super().__init__(name, type) + + self.name = name + self.type = type + self.string = string + + + def __str__(self): + return self.string + + +class Dict(DBusType): + def __init__(key=Str, value=Str): + super().__init__('Dict', dict, None) + + self.key = key + self.value = value + + + # I'm pretty sure there's an easier way to do f-strings without parsing curly brackets, but I'm not sure how atm + def __str__(self): + return '{' + f'{self.key}{self.value}' + '}' + + +class List(DBusType): + def __init__(*types): + super().__init__('List', list, None) + + self.types = types + + + def __str__(self): + types = ''.join(self.types) + return f'a{types}' + + +def Set(List): + def __init__(*types): + super().__init__('Set', set, None) + + self.types = types + + +def Tuple(List): + def __init__(*types): + super().__init__('Tuple', Tuple, None) + + self.types = types + + +Str = DBusType('String', str, 's') +Byte = DBusType('Byte', bytes, 'y') +Bool = DBusType('Boolean', bool, 'b') +Float = DBusType('Float', float, 'd') +Int = DbusType('Int64', int, 'x') +Int16 = DBusType('Int16', int, 'n') +Int32 = DbusType('Int32', int, 'i') +Int64 = DbusType('Int64', int, 'x') +Uint16 = DBusType('Uint16', int, 'q') +Uint32 = DBusType('Uint32', int, 'u') +Uint64 = DBusType('Uint64', int, 't') + + +__all__ = [ + 'Any', + 'Bytes', + 'Dict', + 'Float', + 'Int', + 'Int16', + 'Int32', + 'Int64', + 'List', + 'Set', + 'Str', + 'Tuple', + 'Uint16', + 'Uint32', + 'Uint64' +] diff --git a/base/izzylib/dotdict.py b/izzylib/dotdict.py similarity index 100% rename from base/izzylib/dotdict.py rename to izzylib/dotdict.py diff --git a/base/izzylib/exceptions.py b/izzylib/exceptions.py similarity index 100% rename from base/izzylib/exceptions.py rename to izzylib/exceptions.py diff --git a/hasher/izzylib/hasher/__init__.py b/izzylib/hasher/__init__.py similarity index 100% rename from hasher/izzylib/hasher/__init__.py rename to izzylib/hasher/__init__.py diff --git a/hasher/izzylib/hasher/hasher.py b/izzylib/hasher/hasher.py similarity index 100% rename from hasher/izzylib/hasher/hasher.py rename to izzylib/hasher/hasher.py diff --git a/base/izzylib/http_client.py b/izzylib/http_client.py similarity index 100% rename from base/izzylib/http_client.py rename to izzylib/http_client.py diff --git a/http_server/izzylib/http_server/__init__.py b/izzylib/http_server/__init__.py similarity index 100% rename from http_server/izzylib/http_server/__init__.py rename to izzylib/http_server/__init__.py diff --git a/http_server/izzylib/http_server/activitypub.py b/izzylib/http_server/activitypub.py similarity index 100% rename from http_server/izzylib/http_server/activitypub.py rename to izzylib/http_server/activitypub.py diff --git a/http_server/izzylib/http_server/application.py b/izzylib/http_server/application.py similarity index 100% rename from http_server/izzylib/http_server/application.py rename to izzylib/http_server/application.py diff --git a/http_server/izzylib/http_server/config.py b/izzylib/http_server/config.py similarity index 100% rename from http_server/izzylib/http_server/config.py rename to izzylib/http_server/config.py diff --git a/http_server/izzylib/http_server/error_handlers.py b/izzylib/http_server/error_handlers.py similarity index 100% rename from http_server/izzylib/http_server/error_handlers.py rename to izzylib/http_server/error_handlers.py diff --git a/http_server/izzylib/http_server/frontend/base.css b/izzylib/http_server/frontend/base.css similarity index 100% rename from http_server/izzylib/http_server/frontend/base.css rename to izzylib/http_server/frontend/base.css diff --git a/http_server/izzylib/http_server/frontend/base.haml b/izzylib/http_server/frontend/base.haml similarity index 100% rename from http_server/izzylib/http_server/frontend/base.haml rename to izzylib/http_server/frontend/base.haml diff --git a/http_server/izzylib/http_server/frontend/error.haml b/izzylib/http_server/frontend/error.haml similarity index 100% rename from http_server/izzylib/http_server/frontend/error.haml rename to izzylib/http_server/frontend/error.haml diff --git a/http_server/izzylib/http_server/frontend/menu.haml b/izzylib/http_server/frontend/menu.haml similarity index 100% rename from http_server/izzylib/http_server/frontend/menu.haml rename to izzylib/http_server/frontend/menu.haml diff --git a/http_server/izzylib/http_server/frontend/static/icon512.png b/izzylib/http_server/frontend/static/icon512.png similarity index 100% rename from http_server/izzylib/http_server/frontend/static/icon512.png rename to izzylib/http_server/frontend/static/icon512.png diff --git a/http_server/izzylib/http_server/frontend/static/icon64.png b/izzylib/http_server/frontend/static/icon64.png similarity index 100% rename from http_server/izzylib/http_server/frontend/static/icon64.png rename to izzylib/http_server/frontend/static/icon64.png diff --git a/http_server/izzylib/http_server/frontend/static/menu.js b/izzylib/http_server/frontend/static/menu.js similarity index 100% rename from http_server/izzylib/http_server/frontend/static/menu.js rename to izzylib/http_server/frontend/static/menu.js diff --git a/http_server/izzylib/http_server/frontend/static/menu.svg b/izzylib/http_server/frontend/static/menu.svg similarity index 100% rename from http_server/izzylib/http_server/frontend/static/menu.svg rename to izzylib/http_server/frontend/static/menu.svg diff --git a/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-Black.ttf b/izzylib/http_server/frontend/static/nunito/NunitoSans-Black.ttf similarity index 100% rename from http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-Black.ttf rename to izzylib/http_server/frontend/static/nunito/NunitoSans-Black.ttf diff --git a/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-Black.woff2 b/izzylib/http_server/frontend/static/nunito/NunitoSans-Black.woff2 similarity index 100% rename from http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-Black.woff2 rename to izzylib/http_server/frontend/static/nunito/NunitoSans-Black.woff2 diff --git a/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-BlackItalic.ttf b/izzylib/http_server/frontend/static/nunito/NunitoSans-BlackItalic.ttf similarity index 100% rename from http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-BlackItalic.ttf rename to izzylib/http_server/frontend/static/nunito/NunitoSans-BlackItalic.ttf diff --git a/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-BlackItalic.woff2 b/izzylib/http_server/frontend/static/nunito/NunitoSans-BlackItalic.woff2 similarity index 100% rename from http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-BlackItalic.woff2 rename to izzylib/http_server/frontend/static/nunito/NunitoSans-BlackItalic.woff2 diff --git a/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-Bold.ttf b/izzylib/http_server/frontend/static/nunito/NunitoSans-Bold.ttf similarity index 100% rename from http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-Bold.ttf rename to izzylib/http_server/frontend/static/nunito/NunitoSans-Bold.ttf diff --git a/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-Bold.woff2 b/izzylib/http_server/frontend/static/nunito/NunitoSans-Bold.woff2 similarity index 100% rename from http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-Bold.woff2 rename to izzylib/http_server/frontend/static/nunito/NunitoSans-Bold.woff2 diff --git a/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-BoldItalic.ttf b/izzylib/http_server/frontend/static/nunito/NunitoSans-BoldItalic.ttf similarity index 100% rename from http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-BoldItalic.ttf rename to izzylib/http_server/frontend/static/nunito/NunitoSans-BoldItalic.ttf diff --git a/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-BoldItalic.woff2 b/izzylib/http_server/frontend/static/nunito/NunitoSans-BoldItalic.woff2 similarity index 100% rename from http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-BoldItalic.woff2 rename to izzylib/http_server/frontend/static/nunito/NunitoSans-BoldItalic.woff2 diff --git a/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-ExtraBold.ttf b/izzylib/http_server/frontend/static/nunito/NunitoSans-ExtraBold.ttf similarity index 100% rename from http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-ExtraBold.ttf rename to izzylib/http_server/frontend/static/nunito/NunitoSans-ExtraBold.ttf diff --git a/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-ExtraBold.woff2 b/izzylib/http_server/frontend/static/nunito/NunitoSans-ExtraBold.woff2 similarity index 100% rename from http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-ExtraBold.woff2 rename to izzylib/http_server/frontend/static/nunito/NunitoSans-ExtraBold.woff2 diff --git a/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-ExtraBoldItalic.ttf b/izzylib/http_server/frontend/static/nunito/NunitoSans-ExtraBoldItalic.ttf similarity index 100% rename from http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-ExtraBoldItalic.ttf rename to izzylib/http_server/frontend/static/nunito/NunitoSans-ExtraBoldItalic.ttf diff --git a/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-ExtraBoldItalic.woff2 b/izzylib/http_server/frontend/static/nunito/NunitoSans-ExtraBoldItalic.woff2 similarity index 100% rename from http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-ExtraBoldItalic.woff2 rename to izzylib/http_server/frontend/static/nunito/NunitoSans-ExtraBoldItalic.woff2 diff --git a/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-ExtraLight.ttf b/izzylib/http_server/frontend/static/nunito/NunitoSans-ExtraLight.ttf similarity index 100% rename from http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-ExtraLight.ttf rename to izzylib/http_server/frontend/static/nunito/NunitoSans-ExtraLight.ttf diff --git a/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-ExtraLight.woff2 b/izzylib/http_server/frontend/static/nunito/NunitoSans-ExtraLight.woff2 similarity index 100% rename from http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-ExtraLight.woff2 rename to izzylib/http_server/frontend/static/nunito/NunitoSans-ExtraLight.woff2 diff --git a/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-ExtraLightItalic.ttf b/izzylib/http_server/frontend/static/nunito/NunitoSans-ExtraLightItalic.ttf similarity index 100% rename from http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-ExtraLightItalic.ttf rename to izzylib/http_server/frontend/static/nunito/NunitoSans-ExtraLightItalic.ttf diff --git a/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-ExtraLightItalic.woff2 b/izzylib/http_server/frontend/static/nunito/NunitoSans-ExtraLightItalic.woff2 similarity index 100% rename from http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-ExtraLightItalic.woff2 rename to izzylib/http_server/frontend/static/nunito/NunitoSans-ExtraLightItalic.woff2 diff --git a/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-Italic.ttf b/izzylib/http_server/frontend/static/nunito/NunitoSans-Italic.ttf similarity index 100% rename from http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-Italic.ttf rename to izzylib/http_server/frontend/static/nunito/NunitoSans-Italic.ttf diff --git a/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-Italic.woff2 b/izzylib/http_server/frontend/static/nunito/NunitoSans-Italic.woff2 similarity index 100% rename from http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-Italic.woff2 rename to izzylib/http_server/frontend/static/nunito/NunitoSans-Italic.woff2 diff --git a/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-Light.ttf b/izzylib/http_server/frontend/static/nunito/NunitoSans-Light.ttf similarity index 100% rename from http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-Light.ttf rename to izzylib/http_server/frontend/static/nunito/NunitoSans-Light.ttf diff --git a/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-Light.woff2 b/izzylib/http_server/frontend/static/nunito/NunitoSans-Light.woff2 similarity index 100% rename from http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-Light.woff2 rename to izzylib/http_server/frontend/static/nunito/NunitoSans-Light.woff2 diff --git a/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-LightItalic.ttf b/izzylib/http_server/frontend/static/nunito/NunitoSans-LightItalic.ttf similarity index 100% rename from http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-LightItalic.ttf rename to izzylib/http_server/frontend/static/nunito/NunitoSans-LightItalic.ttf diff --git a/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-LightItalic.woff2 b/izzylib/http_server/frontend/static/nunito/NunitoSans-LightItalic.woff2 similarity index 100% rename from http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-LightItalic.woff2 rename to izzylib/http_server/frontend/static/nunito/NunitoSans-LightItalic.woff2 diff --git a/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-Regular.ttf b/izzylib/http_server/frontend/static/nunito/NunitoSans-Regular.ttf similarity index 100% rename from http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-Regular.ttf rename to izzylib/http_server/frontend/static/nunito/NunitoSans-Regular.ttf diff --git a/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-Regular.woff2 b/izzylib/http_server/frontend/static/nunito/NunitoSans-Regular.woff2 similarity index 100% rename from http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-Regular.woff2 rename to izzylib/http_server/frontend/static/nunito/NunitoSans-Regular.woff2 diff --git a/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-SemiBold.ttf b/izzylib/http_server/frontend/static/nunito/NunitoSans-SemiBold.ttf similarity index 100% rename from http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-SemiBold.ttf rename to izzylib/http_server/frontend/static/nunito/NunitoSans-SemiBold.ttf diff --git a/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-SemiBold.woff2 b/izzylib/http_server/frontend/static/nunito/NunitoSans-SemiBold.woff2 similarity index 100% rename from http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-SemiBold.woff2 rename to izzylib/http_server/frontend/static/nunito/NunitoSans-SemiBold.woff2 diff --git a/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-SemiBoldItalic.ttf b/izzylib/http_server/frontend/static/nunito/NunitoSans-SemiBoldItalic.ttf similarity index 100% rename from http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-SemiBoldItalic.ttf rename to izzylib/http_server/frontend/static/nunito/NunitoSans-SemiBoldItalic.ttf diff --git a/http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-SemiBoldItalic.woff2 b/izzylib/http_server/frontend/static/nunito/NunitoSans-SemiBoldItalic.woff2 similarity index 100% rename from http_server/izzylib/http_server/frontend/static/nunito/NunitoSans-SemiBoldItalic.woff2 rename to izzylib/http_server/frontend/static/nunito/NunitoSans-SemiBoldItalic.woff2 diff --git a/http_server/izzylib/http_server/frontend/static/nunito/SIL Open Font License.txt b/izzylib/http_server/frontend/static/nunito/SIL Open Font License.txt similarity index 100% rename from http_server/izzylib/http_server/frontend/static/nunito/SIL Open Font License.txt rename to izzylib/http_server/frontend/static/nunito/SIL Open Font License.txt diff --git a/http_server/izzylib/http_server/middleware.py b/izzylib/http_server/middleware.py similarity index 100% rename from http_server/izzylib/http_server/middleware.py rename to izzylib/http_server/middleware.py diff --git a/http_server/izzylib/http_server/misc.py b/izzylib/http_server/misc.py similarity index 100% rename from http_server/izzylib/http_server/misc.py rename to izzylib/http_server/misc.py diff --git a/http_server/izzylib/http_server/request.py b/izzylib/http_server/request.py similarity index 100% rename from http_server/izzylib/http_server/request.py rename to izzylib/http_server/request.py diff --git a/http_server/izzylib/http_server/response.py b/izzylib/http_server/response.py similarity index 100% rename from http_server/izzylib/http_server/response.py rename to izzylib/http_server/response.py diff --git a/http_server/izzylib/http_server/view.py b/izzylib/http_server/view.py similarity index 100% rename from http_server/izzylib/http_server/view.py rename to izzylib/http_server/view.py diff --git a/http_urllib_client/izzylib/http_urllib_client/__init__.py b/izzylib/http_urllib_client/__init__.py similarity index 100% rename from http_urllib_client/izzylib/http_urllib_client/__init__.py rename to izzylib/http_urllib_client/__init__.py diff --git a/http_urllib_client/izzylib/http_urllib_client/client.py b/izzylib/http_urllib_client/client.py similarity index 100% rename from http_urllib_client/izzylib/http_urllib_client/client.py rename to izzylib/http_urllib_client/client.py diff --git a/http_urllib_client/izzylib/http_urllib_client/error.py b/izzylib/http_urllib_client/error.py similarity index 100% rename from http_urllib_client/izzylib/http_urllib_client/error.py rename to izzylib/http_urllib_client/error.py diff --git a/http_urllib_client/izzylib/http_urllib_client/request.py b/izzylib/http_urllib_client/request.py similarity index 100% rename from http_urllib_client/izzylib/http_urllib_client/request.py rename to izzylib/http_urllib_client/request.py diff --git a/http_urllib_client/izzylib/http_urllib_client/response.py b/izzylib/http_urllib_client/response.py similarity index 100% rename from http_urllib_client/izzylib/http_urllib_client/response.py rename to izzylib/http_urllib_client/response.py diff --git a/http_urllib_client/izzylib/http_urllib_client/signatures.py b/izzylib/http_urllib_client/signatures.py similarity index 100% rename from http_urllib_client/izzylib/http_urllib_client/signatures.py rename to izzylib/http_urllib_client/signatures.py diff --git a/base/izzylib/logging.py b/izzylib/logging.py similarity index 100% rename from base/izzylib/logging.py rename to izzylib/logging.py diff --git a/base/izzylib/misc.py b/izzylib/misc.py similarity index 100% rename from base/izzylib/misc.py rename to izzylib/misc.py diff --git a/base/izzylib/path.py b/izzylib/path.py similarity index 100% rename from base/izzylib/path.py rename to izzylib/path.py diff --git a/sql/izzylib/sql/__init__.py b/izzylib/sql/__init__.py similarity index 100% rename from sql/izzylib/sql/__init__.py rename to izzylib/sql/__init__.py diff --git a/sql/izzylib/sql/column.py b/izzylib/sql/column.py similarity index 100% rename from sql/izzylib/sql/column.py rename to izzylib/sql/column.py diff --git a/sql/izzylib/sql/database.py b/izzylib/sql/database.py similarity index 100% rename from sql/izzylib/sql/database.py rename to izzylib/sql/database.py diff --git a/sql/izzylib/sql/rows.py b/izzylib/sql/rows.py similarity index 100% rename from sql/izzylib/sql/rows.py rename to izzylib/sql/rows.py diff --git a/sql/izzylib/sql/session.py b/izzylib/sql/session.py similarity index 100% rename from sql/izzylib/sql/session.py rename to izzylib/sql/session.py diff --git a/sql/izzylib/sql/sqlite_server.py b/izzylib/sql/sqlite_server.py similarity index 100% rename from sql/izzylib/sql/sqlite_server.py rename to izzylib/sql/sqlite_server.py diff --git a/template/izzylib/template/__init__.py b/izzylib/template/__init__.py similarity index 100% rename from template/izzylib/template/__init__.py rename to izzylib/template/__init__.py diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..9787c3b --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["setuptools", "wheel"] +build-backend = "setuptools.build_meta" diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 2162886..0000000 --- a/requirements.txt +++ /dev/null @@ -1,16 +0,0 @@ -dasbus==1.6 -argon2-cffi==20.1.0 -pillow==8.2.0 -pycryptodome==3.10.1 -requests==2.25.1 -tldextract==3.1.0 -SQLAlchemy==1.4.7 -SQLAlchemy-Paginator==0.2 -colour==0.1.5 -Hamlish-Jinja==0.3.3 -Jinja2==3.0.1 -Markdown==3.3.3 -tinydb==4.4.0 -tinydb-serialization==2.1.0 -tinydb-smartcache==2.0.0 -tinyrecord==0.2.0 diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..64bf9c1 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,63 @@ +[metadata] +name = IzzyLib +version = 0.7.0 +author = Zoey Mae +author_email = zoey@barkshark.xyz +url = https://git.barkshark.xyz/izaliamae/izzylib +description = Functions and classes that I use often +license = CNPL +license_file = LICENSE +platform = any +keywords = python http activitypub sql database html css +classifiers = + Development Status :: 3 - Alpha + Intended Audience :: Developers + Operating System :: OS Independent + Programming Language :: Python + Programming Language :: Python 3.6 + Programming Language :: Python 3.7 + Programming Language :: Python 3.8 + Programming Language :: Python 3.9 + Topic :: Software Development :: Libraries :: Python Modules +project_urls = + Bug Tracker = https://git.barkshark.xyz/izaliamae/izzylib/issues + Documentation = https://git.barkshark.xyz/izaliamae/izzylib/wiki + Source Code = https://git.barkshark.xyz/izaliamae/izzylib + +[options] +include_package_data = true +packages = izzylib +python_requires = >= 3.6 +setup_requires = + setuptools >= 38.3.0 + +[options.package_data] +izzylib = izzylib/* + +[options.extras_require] +dbus = + dasbus==1.6 +hasher = + argon2-cffi == 21.1.0 +http_server = + sanic == 21.6.2 + envbash == 1.2.0 +http_urllib_client = + pillow == 8.3.2 + pycryptodome == 3.10.1 + urllib3 == 1.26.6 + tldextract == 3.1.2 +sql = + SQLAlchemy == 1.4.23 + SQLAlchemy-Paginator == 0.2 +template = + colour == 0.1.5 + Hamlish-Jinja == 0.3.3 + Jinja2 == 3.0.1 + Markdown == 3.3.4 + +[bdist_wheel] +universal = true + +[sdist] +formats = zip, gztar diff --git a/setup.py b/setup.py deleted file mode 100644 index 209d21f..0000000 --- a/setup.py +++ /dev/null @@ -1,94 +0,0 @@ -import subprocess, sys - - -submodules = [ - 'http_server', - 'requests_client', - 'sql', - 'template', - 'tinydb' -] - -submodule_names = [ - 'IzzyLib-Base', - 'IzzyLib-Database', - 'IzzyLib-HTTP-Server', - 'IzzyLib-Requests-Client', - 'IzzyLib-SQL', - 'IzzyLib-Templates', - 'IzzyLib-TinyDB', -] - - -def main(*args): - if not len(args): - print('Missing command') - return cmd_help() - - command = args[0] - - if command not in ['install', 'uninstall', 'dev']: - print('Invalid command:', command) - return cmd_help() - - if command == 'uninstall': - subprocess.run([sys.executable, '-m', 'pip', 'uninstall', '-y', *submodule_names]) - return - - submodule_args = [] - - if len(args) > 1: - if args[1] == 'all': - submodule_args = [f'./{module}' for module in modinstall] - - else: - submodule_args = [f'./{module}' for module in args[1:]] - - for mod in submodules: - if mod not in submodules: - print('Invalid submodule:', mod) - return cmd_help() - - options = ['-m', 'pip', 'install', './base', *submodule_args] - - if command == 'dev': - options.insert(3, '--use-feature=in-tree-build') - - print(options) - - subprocess.run([sys.executable, *options]) - - -def cmd_help(*args): - text = f'''IzzyLib manager - -Commands: - install [submodules: space-separated list]: - Install IzzyLib as well as any sub-modules if any are required - - uninstall [submodules] - Uninstall IzzyLib and any installed submodules - -Valid Submodules: - {', '.join(submodules)} -''' - - print(text) - - -if __name__ == '__main__': - try: - args = sys.argv[1:] - - except IndexError: - args = [] - - try: - if not args: - cmd_help() - - else: - main(*args) - - except KeyboardInterrupt: - print('Bye! UvU') diff --git a/sql/setup.py b/sql/setup.py deleted file mode 100644 index e118755..0000000 --- a/sql/setup.py +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env python3 -from setuptools import setup, find_namespace_packages - - -requires = [ - 'SQLAlchemy==1.4.7', - 'SQLAlchemy-Paginator==0.2' -] - - -setup( - name="IzzyLib SQL", - version='0.6.0', - packages=find_namespace_packages(include=['izzylib.sql']), - python_requires='>=3.7.0', - install_requires=requires, - include_package_data=False, - author='Zoey Mae', - author_email='admin@barkshark.xyz', - description='a collection of often-used functions and classes', - keywords='database postgresql sqlite tinydb', - url='https://git.barkshark.xyz/izaliamae/izzylib', - project_urls={ - 'Bug Tracker': 'https://git.barkshark.xyz/izaliamae/izzylib/issues', - 'Documentation': 'https://git.barkshark.xyz/izaliamae/izzylib/wiki', - 'Source Code': 'https://git.barkshark.xyz/izaliamae/izzylib' - }, - - classifiers=[ - 'Development Status :: 3 - Alpha', - 'Intended Audience :: Information Technology', - 'License :: Co-operative Non-violent Public License (CNPL 6+)', - 'Programming Language :: Python :: 3.7', - 'Programming Language :: Python :: 3.8', - 'Programming Language :: Python :: 3.9', - 'Operating System :: POSIX', - 'Operating System :: MacOS :: MacOS X', - 'Operating System :: Microsoft :: Windows', - 'Topic :: Database', - 'Topic :: Software Development :: Libraries', - 'Topic :: Software Development :: Libraries :: Python Modules' - ] -) diff --git a/template/setup.py b/template/setup.py deleted file mode 100644 index 36c6a77..0000000 --- a/template/setup.py +++ /dev/null @@ -1,46 +0,0 @@ -#!/usr/bin/env python3 -from setuptools import setup, find_namespace_packages - - -requires = [ - 'colour==0.1.5', - 'Hamlish-Jinja==0.3.3', - 'Jinja2==3.0.1', - 'Markdown==3.3.3', -] - - -setup( - name="IzzyLib Templates", - version='0.6.0', - packages=find_namespace_packages(include=['izzylib.template']), - python_requires='>=3.7.0', - install_requires=requires, - include_package_data=False, - author='Zoey Mae', - author_email='admin@barkshark.xyz', - description='A template engine based on Jinja2 and HAMLish-Jinja', - keywords='web http templates jinja haml', - url='https://git.barkshark.xyz/izaliamae/izzylib', - project_urls={ - 'Bug Tracker': 'https://git.barkshark.xyz/izaliamae/izzylib/issues', - 'Documentation': 'https://git.barkshark.xyz/izaliamae/izzylib/wiki', - 'Source Code': 'https://git.barkshark.xyz/izaliamae/izzylib' - }, - - classifiers=[ - 'Development Status :: 3 - Alpha', - 'Intended Audience :: Information Technology', - 'License :: Co-operative Non-violent Public License (CNPL 6+)', - 'Programming Language :: Python :: 3.7', - 'Programming Language :: Python :: 3.8', - 'Programming Language :: Python :: 3.9', - 'Operating System :: POSIX', - 'Operating System :: MacOS :: MacOS X', - 'Operating System :: Microsoft :: Windows', - 'Topic :: Internet :: WWW/HTTP', - 'Topic :: Internet :: WWW/HTTP :: Dynamic Content', - 'Topic :: Software Development :: Libraries', - 'Topic :: Software Development :: Libraries :: Python Modules' - ] -) diff --git a/tinydb/izzylib/tinydb/__init__.py b/tinydb/izzylib/tinydb/__init__.py deleted file mode 100644 index d7a8b4e..0000000 --- a/tinydb/izzylib/tinydb/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .tiny import TinyDatabase, TinyRow, TinyRows diff --git a/tinydb/izzylib/tinydb/tiny.py b/tinydb/izzylib/tinydb/tiny.py deleted file mode 100644 index ae10a5f..0000000 --- a/tinydb/izzylib/tinydb/tiny.py +++ /dev/null @@ -1,174 +0,0 @@ -# incomplete -import base64 -import json -import operator -import queue -import threading -import time - -import tinydb -import tinydb_serialization - -from concurrent.futures import ThreadPoolExecutor, as_completed -from izzylib import Path, random_gen - - -class AwaitingResult(object): - pass - - -class TinyDatabase(tinydb.TinyDB): - def __init__(self, dbfile: Path, queue_limit: int=64, serializers: list=[]): - options = { - 'indent': 2 - } - - serialization = tinydb_serialization.SerializationMiddleware(ThreadSupport) - serialization.register_serializer(tinydb_serialization.serializers.DateTimeSerializer(), 'TinyDate') - serialization.register_serializer(ByteSerializer(), 'TinyBytes') - serialization.register_serializer(PathSerialize(), 'IzzyLibPath') - serialization.register_serializer(DotDictSerialize(), 'IzzyLibDotDict') - - for serializer in serializers: - serialization.register_serializer(serializer(), serializer.__class__.__name__) - - options['storage'] = serialization - - super().__init__(dbfile, **options) - - self.dbfile = dbfile - self.queue = queue.Queue(maxsize=queue_limit) - self.sessions = {} - - - @property - def session(self): - return TinySession(self) - - - def fetch(self, table, single=True, orderby=None, reverse=False, **kwargs): - query = tinydb.Query() - - if not kwargs: - rows = TinyRows(self, self.table(table).all()) - single = False - - else: - rows = TinyRows(self, self.table(table).search(query.fragment(kwargs))) - - if single: - return rows[0] if rows else None - - return rows if not orderby else sorted(rows, key=operator.itemgetter(orderby), reverse=reverse) - - - def insert(self, table, row=None, rowid=None, **kwargs): - if row: - rowid = row.doc_id - - elif not rowid: - row = self.fetch(table, **kwargs) - rowid = row.doc_id if row else None - - if rowid: - return self.table(table).update(kwargs, doc_ids=[rowid]) - - return self.table(table).insert(kwargs) - - - def remove(self, table, row=None, rowid=None, **kwargs): - query = tinydb.Query() - - if row or rowid: - rowid = rowid or row.doc_id - return self.table(table).remove(doc_ids=[row.doc_id]) - - return self.table(table).remove(query.fragment(kwargs)) - - -def TinyRows(db, rows): - return [TinyRow(db, row) for row in rows] - - -class TinyRow(DotDict): - def __init__(self, db, row): - super().__init({'id': row.doc_id}) - super().update({k: v for k,v in row.items()}) - - - def update(self, data={}): - db.update(rowid=self.id, **data) - super().update(data) - - - def remove(self): - db.remove(rowid=self.id) - - -class ThreadSupport(tinydb.storages.JSONStorage): - def __init__(self, filename, *args, **kwargs): - super().__init__(filename, *args, **kwargs) - - self.pool = ThreadPoolExecutor(max_workers=8) - - ## send all storage commands to the queue - def read(self): - data = self.queue_put('read') - return data - - - def write(self, data): - for future in as_completed(self.pool.submit(super().write, data)): - self.queue_put('write', data) - - - def close(self): - self.pool.shutdown(wait=False) - - -class ByteSerializer(tinydb_serialization.Serializer): - OBJ_CLASS = bytes - - def encode(self, obj): - #print('encode', self.__class__.__name__, obj) - return base64.b64encode(obj).decode('ascii') - - def decode(self, obj): - #print('decode', self.__class__.__name__, obj) - return base64.b64decode(obj) - - -class DictSerializer(tinydb_serialization.Serializer): - OBJ_CLASS = dict - - def encode(self, obj): - #print('encode', self.__class__.__name__, obj) - return json.dumps(obj) - - def decode(self, obj): - #print('decode', self.__class__.__name__, obj) - return json.loads(obj) - - -class DotDictSerialize(tinydb_serialization.Serializer): - OBJ_CLASS = DotDict - - def encode(self, obj): - #print('encode', self.__class__.__name__, obj) - return obj.toJson() - - def decode(self, obj): - #print('decode', self.__class__.__name__, obj) - return DotDict(obj) - - -class PathSerialize(tinydb_serialization.Serializer): - OBJ_CLASS = Path - - def encode(self, obj): - #print('encode', self.__class__.__name__, obj) - return obj.str() - - def decode(self, obj): - #print('decode', self.__class__.__name__, obj) - return Path(obj) diff --git a/tinydb/setup.py b/tinydb/setup.py deleted file mode 100644 index c02d993..0000000 --- a/tinydb/setup.py +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/env python3 -from setuptools import setup, find_namespace_packages - - -requires = [ - 'tinydb==4.4.0', - 'tinydb-serialization==2.1.0', - 'tinydb-smartcache==2.0.0', - 'tinyrecord==0.2.0' -] - - -setup( - name="IzzyLib TinyDB", - version='0.6.0', - packages=find_namespace_packages(include=['izzylib.tinydb']), - python_requires='>=3.7.0', - install_requires=requires, - include_package_data=False, - author='Zoey Mae', - author_email='admin@barkshark.xyz', - description='a collection of often-used functions and classes', - keywords='database postgresql sqlite tinydb', - url='https://git.barkshark.xyz/izaliamae/izzylib', - project_urls={ - 'Bug Tracker': 'https://git.barkshark.xyz/izaliamae/izzylib/issues', - 'Documentation': 'https://git.barkshark.xyz/izaliamae/izzylib/wiki', - 'Source Code': 'https://git.barkshark.xyz/izaliamae/izzylib' - }, - - classifiers=[ - 'Development Status :: 3 - Alpha', - 'Intended Audience :: Information Technology', - 'License :: Co-operative Non-violent Public License (CNPL 6+)', - 'Programming Language :: Python :: 3.7', - 'Programming Language :: Python :: 3.8', - 'Programming Language :: Python :: 3.9', - 'Operating System :: POSIX', - 'Operating System :: MacOS :: MacOS X', - 'Operating System :: Microsoft :: Windows', - 'Topic :: Database', - 'Topic :: Software Development :: Libraries', - 'Topic :: Software Development :: Libraries :: Python Modules' - ] -) From 85a7aeebadb58e11b7fd665c38e898c47f28af66 Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Fri, 17 Sep 2021 15:11:45 -0400 Subject: [PATCH 73/74] make building and setup easier --- MANIFEST.in | 2 +- Makefile | 25 ++++++------------------- pyproject.toml | 5 ++++- setup.cfg | 11 +++++++++-- setup.py | 2 ++ 5 files changed, 22 insertions(+), 23 deletions(-) create mode 100644 setup.py diff --git a/MANIFEST.in b/MANIFEST.in index e83fa28..8b1396a 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1 +1 @@ -recursive-include izzylib * +recursive-include izzylib/http_server/frontend * diff --git a/Makefile b/Makefile index 9720d73..2dbc85b 100644 --- a/Makefile +++ b/Makefile @@ -2,24 +2,11 @@ install: setup-deps mklinks uninstall: rmlinks setup-deps: - python3 -m pip install -r requirements.txt + python3 -m pip install -U pip setuptools build -rmlinks: - rm base/izzylib/dbus - rm base/izzylib/hasher - rm base/izzylib/http_urllib_client - rm base/izzylib/http_server - rm base/izzylib/sql - rm base/izzylib/template - rm base/izzylib/tinydb - rm izzylib +build: + python3 -m build --sdist + python3 -m build --wheel -mklinks: - ln -sr dbus/izzylib/dbus base/izzylib/ - ln -sr hasher/izzylib/hasher base/izzylib/ - ln -sr http_urllib_client/izzylib/http_urllib_client base/izzylib/ - ln -sr http_server/izzylib/http_server base/izzylib/ - ln -sr sql/izzylib/sql base/izzylib/ - ln -sr template/izzylib/template base/izzylib/ - ln -sr tinydb/izzylib/tinydb base/izzylib/ - ln -s base/izzylib +clean: + rm -rf build dist IzzyLib.egg-info diff --git a/pyproject.toml b/pyproject.toml index 9787c3b..11d6cbb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,3 +1,6 @@ [build-system] -requires = ["setuptools", "wheel"] +requires = [ + "setuptools >= 38.3.0", + "wheel" +] build-backend = "setuptools.build_meta" diff --git a/setup.cfg b/setup.cfg index 64bf9c1..064e5b3 100644 --- a/setup.cfg +++ b/setup.cfg @@ -26,8 +26,15 @@ project_urls = [options] include_package_data = true -packages = izzylib python_requires = >= 3.6 +packages = + izzylib + izzylib.dbus + izzylib.hasher + izzylib.http_server + izzylib.http_urllib_client + izzylib.sql + izzylib.template setup_requires = setuptools >= 38.3.0 @@ -57,7 +64,7 @@ template = Markdown == 3.3.4 [bdist_wheel] -universal = true +universal = false [sdist] formats = zip, gztar diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..a4f49f9 --- /dev/null +++ b/setup.py @@ -0,0 +1,2 @@ +import setuptools +setuptools.setup() From 80ad6f58237c815ecdba31ad76ab1bd7e9187b8b Mon Sep 17 00:00:00 2001 From: Izalia Mae Date: Fri, 17 Sep 2021 15:23:21 -0400 Subject: [PATCH 74/74] remove whitespace --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 064e5b3..44e00cf 100644 --- a/setup.cfg +++ b/setup.cfg @@ -27,7 +27,7 @@ project_urls = [options] include_package_data = true python_requires = >= 3.6 -packages = +packages = izzylib izzylib.dbus izzylib.hasher