From e560119bb02559eb8896e8c0d5272ec475caa000 Mon Sep 17 00:00:00 2001 From: raj_mathe Date: Mon, 10 Oct 2022 11:17:47 +0200 Subject: [PATCH] main > main: src - init --- src/__init__.py | 0 src/core/__init__.py | 0 src/core/calls.py | 215 +++++++++++++++++++++++++++++++++++++ src/core/env.py | 61 +++++++++++ src/core/log.py | 163 ++++++++++++++++++++++++++++ src/core/utils.py | 36 +++++++ src/thirdparty/__init__.py | 0 src/thirdparty/code.py | 51 +++++++++ src/thirdparty/config.py | 32 ++++++ src/thirdparty/io.py | 16 +++ src/thirdparty/log.py | 18 ++++ src/thirdparty/maths.py | 22 ++++ src/thirdparty/misc.py | 24 +++++ src/thirdparty/render.py | 27 +++++ src/thirdparty/run.py | 16 +++ src/thirdparty/system.py | 20 ++++ src/thirdparty/types.py | 84 +++++++++++++++ 17 files changed, 785 insertions(+) create mode 100644 src/__init__.py create mode 100644 src/core/__init__.py create mode 100644 src/core/calls.py create mode 100644 src/core/env.py create mode 100644 src/core/log.py create mode 100644 src/core/utils.py create mode 100644 src/thirdparty/__init__.py create mode 100644 src/thirdparty/code.py create mode 100644 src/thirdparty/config.py create mode 100644 src/thirdparty/io.py create mode 100644 src/thirdparty/log.py create mode 100644 src/thirdparty/maths.py create mode 100644 src/thirdparty/misc.py create mode 100644 src/thirdparty/render.py create mode 100644 src/thirdparty/run.py create mode 100644 src/thirdparty/system.py create mode 100644 src/thirdparty/types.py diff --git a/src/__init__.py b/src/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/core/__init__.py b/src/core/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/core/calls.py b/src/core/calls.py new file mode 100644 index 0000000..9b8dc3f --- /dev/null +++ b/src/core/calls.py @@ -0,0 +1,215 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# IMPORTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +from __future__ import annotations; + +from src.thirdparty.code import *; +from src.thirdparty.config import *; +from src.thirdparty.types import *; + +from src.core.utils import *; + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# EXPORTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +__all__ = [ + 'CallState', + 'GetState', + 'CallValue', + 'CallError', + 'keep_calm_and_carry_on', + 'run_safely', + 'to_async', +]; + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# CONSTANTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +# local usage only +T = TypeVar('T'); +V = TypeVar('V'); +ARGS = ParamSpec('ARGS'); + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Class State for keeping track of results in the course of a computation +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +@dataclass +class CallState(Generic[V]): + ''' + An auxiliary class which keeps track of the latest state of during calls. + ''' + tag: Option[str] = field(default=None); + result: Optional[V] = field(default=None, repr=False); + timestamp: str = field(default_factory=get_timestamp_string); + has_action: bool = field(default=False); + no_action: bool = field(default=False); + has_error: bool = field(default=False); + values: list[tuple[bool, dict]] = field(default_factory=list, repr=False); + errors: list[str] = field(default_factory=list, repr=False); + + def __copy__(self) -> CallState: + return CallState(**asdict(self)); + + def __add__(self, other) -> CallState: + ''' + Combines states sequentially: + - takes on latest `timestamp`. + - takes on lates `value`. + - takes on `tag` of latest non-null value. + - takes on latest value of `no_action` + - `has_action` = `true` <==> at least one action taken, + unless `no_action` = `true`. + - `has_error` = `true` <==> at least one error occurred. + ''' + if isinstance(other, CallState): + no_action = other.no_action; + has_action = False if no_action else (self.has_action or other.has_action); + return CallState( + tag = other.tag or self.tag, + value = other.value, + timestamp = other.timestamp, + has_action = has_action, + no_action = no_action, + has_error = self.has_error or other.has_error, + values = self.values + other.values, + errors = self.errors + other.errors, + ); + raise Exception('Cannot add states!'); + + ## NOTE: only need __radd__ for additions of form + + def __radd__(self, other) -> CallState: + if other == 0: + return self.__copy__(); + raise Exception('Cannot add a CallState to the right of a non-zero object!'); + + def get_result(self) -> V: + if self.result is not None: + return self.result; + raise Exception('No result set!'); + + @property + def first_data(self) -> dict: + ''' + Returns data in first value collected or else defaults to empty dictionary. + ''' + return self.values[0][1] if len(self.values) > 0 else dict(); + + @property + def data(self) -> list[dict]: + ''' + Returns the data collected. + ''' + return [ data for _, data in self.values ]; + + @property + def data_log(self) -> list[dict]: + ''' + Returns the data to be logged. + ''' + return [ data for log, data in self.values if log == True ]; + + @property + def data_log_json(self) -> list[str]: + ''' + Returns the data to be logged as json. + ''' + return list(map(json.dumps, self.data_log)); + +def GetState(result: Result[CallState, CallState]) -> CallState: + if isinstance(result, Ok): + return result.unwrap(); + return result.unwrap_err(); + +def CallValue( + tag: str = None, + result: Optional[V] = None, + has_action: bool = True, + no_action: bool = False, + value: Option[tuple[bool, dict] | list[tuple[bool, dict]]] = Nothing(), +) -> CallState[V]: + x = []; + if isinstance(value, Some): + x = value.unwrap() or []; + x = x if isinstance(x, list) else [ x ]; + X = CallState(tag=tag, result=result, values=x, has_action=has_action, no_action=no_action, has_error=False); + return X; + +def CallError( + tag: str = None, + has_action: bool = True, + error: Option[str | BaseException | list[str | BaseException]] = Nothing(), +) -> CallState[V]: + x = []; + if isinstance(error, Some): + x = error.unwrap() or []; + x = x if isinstance(x, list) else [ x ]; + x = list(map(str, x)); + return CallState(tag=tag, errors=x, has_action=has_action, has_error=True); + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# DECORATOR - forces methods to run safely +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +def run_safely(tag: str | None = None, error_message: str | None = None): + ''' + Creates a decorator for an action to perform it safely. + + @inputs (parameters) + - `tag` - optional string to aid error tracking. + - `error_message` - optional string for an error message. + + ### Example usage ### + ```py + @run_safely(tag='recognise int', error_message='unrecognise string') + def action1(x: str) -> Result[int, CallState]: + return Ok(int(x)); + + assert action1('5') == Ok(5); + result = action1('not a number'); + assert isinstance(result, Err); + err = result.unwrap_err(); + assert isinstance(err, CallState); + assert err.tag == 'recognise int'; + assert err.errors == ['unrecognise string']; + + @run_safely('recognise int') + def action2(x: str) -> Result[int, CallState]: + return Ok(int(x)); + + assert action2('5') == Ok(5); + result = action2('not a number'); + assert isinstance(result, Err); + err = result.unwrap_err(); + assert isinstance(err, CallState); + assert err.tag == 'recognise int'; + assert len(err.errors) == 1; + ``` + NOTE: in the second example, err.errors is a list containing + the stringified Exception generated when calling `int('not a number')`. + ''' + def dec(action: Callable[ARGS, Result[V, CallState]]) -> Callable[ARGS, Result[V, CallState]]: + ''' + Wraps action with return type Result[..., CallState], + so that it is performed safely a promise, + catching any internal exceptions as an Err(...)-component of the Result. + ''' + @wraps(action) + def wrapped_action(*_, **__) -> Result[V, CallState]: + # NOTE: intercept Exceptions first, then flatten: + return Result.of(lambda: action(*_, **__)) \ + .or_else( + lambda err: Err(CallError( + tag = tag or action.__name__, + error = Some(error_message or err), + )) + ) \ + .flatmap(lambda value: value); # necessary to flatten result. + return wrapped_action; + return dec; diff --git a/src/core/env.py b/src/core/env.py new file mode 100644 index 0000000..c3dfcaa --- /dev/null +++ b/src/core/env.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# IMPORTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +from src.thirdparty.code import *; +from src.thirdparty.config import *; +from src.thirdparty.system import *; +from src.thirdparty.types import *; + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# EXPORTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +__all__ = [ + 'get_env_string', + 'get_env_optional_string', + 'get_env_int', + 'get_env_optional_int', + 'get_env_float', + 'get_env_optional_float', +]; + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# AUXILIARY METHODS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +def get_env_value(env: dict, key: str, default: Any = None) -> Any: # pragma: no cover + return env[key] if key in env else default; + +def get_env_string(env: dict, key: str, default: Optional[str] = None) -> str: + result = Result.of(lambda: str(env[key] or default)); + if default is None: + return result.unwrap(); + return result.unwrap_or(default); + +def get_env_optional_string(env: dict, key: str) -> Optional[str]: + result = Result.of(lambda: str(env[key])); + return result.unwrap_or(None); + +def get_env_int(env: dict, key: str, default: Optional[int] = None) -> int: + result = Result.of(lambda: int(env[key] or default)); + if default is None: + return result.unwrap(); + return result.unwrap_or(default); + +def get_env_optional_int(env: dict, key: str) -> Optional[int]: + result = Result.of(lambda: int(env[key])); + return result.unwrap_or(None); + +def get_env_float(env: dict, key: str, default: Optional[float] = None) -> float: + result = Result.of(lambda: float(env[key] or default)); + if default is None: + return result.unwrap(); + return result.unwrap_or(default); + +def get_env_optional_float(env: dict, key: str) -> Optional[float]: + result = Result.of(lambda: float(env[key])); + return result.unwrap_or(None); diff --git a/src/core/log.py b/src/core/log.py new file mode 100644 index 0000000..4484a3d --- /dev/null +++ b/src/core/log.py @@ -0,0 +1,163 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# IMPORTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +from src.thirdparty.code import *; +from src.thirdparty.io import *; +from src.thirdparty.log import *; +from src.thirdparty.misc import *; +from src.thirdparty.types import *; + +from src.core.calls import *; + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# EXPORTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +__all__ = [ + 'LOG_LEVELS', + 'configure_logging', + 'log_info', + 'log_debug', + 'log_warn', + 'log_error', + 'log_fatal', + 'log_result', + 'log_dev', + 'catch_fatal', + 'prompt_user_input', + 'prompt_secure_user_input', + 'prompt_confirmation', +]; + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# CONSTANTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class LOG_LEVELS(Enum): # pragma: no cover + INFO = logging.INFO; + DEBUG = logging.DEBUG; + +# local usage only +_LOGGING_DEBUG_FILE: str = 'logs/debug.log'; +T = TypeVar('T'); + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# METHODS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +def configure_logging(level: LOG_LEVELS): # pragma: no cover + logging.basicConfig( + format = '%(asctime)s [\x1b[1m%(levelname)s\x1b[0m] %(message)s', + level = level.value, + datefmt = r'%Y-%m-%d %H:%M:%S', + ); + return; + +def log_debug(*messages: Any): + logging.debug(*messages); + +def log_info(*messages: Any): + logging.info(*messages); + +def log_warn(*messages: Any): + logging.warning(*messages); + +def log_error(*messages: Any): + logging.error(*messages); + +def log_fatal(*messages: Any): + logging.fatal(*messages); + exit(1); + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Special Methods +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +# Intercept fatal errors +def catch_fatal(method: Callable[[], T]) -> T: + try: + return method(); + except Exception as e: + log_fatal(e); + +def log_result(result: Result[CallState, CallState], debug: bool = False): + ''' + Logs safely encapsulated result of call as either debug/info or error. + + @inputs + - `result` - the result of the call. + - `debug = False` (default) - if the result is okay, will be logged as an INFO message. + - `debug = True` - if the result is okay, will be logged as a DEBUG message. + ''' + if isinstance(result, Ok): + value = result.unwrap(); + log_debug(value); + for x in value.data_log: + log_info(x); + else: + err = result.unwrap_err(); + log_debug(err); + for e in err.errors: + log_error(e); + return; + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# DEBUG LOGGING FOR DEVELOPMENT +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +def log_dev(*messages: Any): # pragma: no cover + with open(_LOGGING_DEBUG_FILE, 'a') as fp: + print(*messages, file=fp); + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# User Input +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +def prompt_user_input(message: str, expectedformat: Callable) -> Optional[str]: + answer = None; + while True: + try: + answer = input(f'{message}: '); + ## Capture Meta+C: + except KeyboardInterrupt: + print(''); + return None; + ## Capture Meta+D: + except EOFError: + print(''); + return None; + except: + continue; + if expectedformat(answer): + break; + return answer; + +def prompt_secure_user_input(message: str, expectedformat: Callable) -> Optional[str]: + answer = None; + while True: + try: + ## TODO: zeige **** ohne Zeilenumbruch an. + answer = getpass(f'{message}: ', stream=None); + ## Capture Meta+C: + except KeyboardInterrupt: + print(''); + return None; + ## Capture Meta+D: + except EOFError: + print(''); + return None; + except: + continue; + if expectedformat(answer): + break; + return answer; + +def prompt_confirmation(message: str, default: bool = False) -> bool: + answer = prompt_user_input(message, lambda x: not not re.match(r'^(y|yes|j|ja|n|no|nein)$', x)); + if isinstance(answer, str): + return True if re.match(r'^(y|yes|j|ja)$', answer) else False; + return default; diff --git a/src/core/utils.py b/src/core/utils.py new file mode 100644 index 0000000..35061e4 --- /dev/null +++ b/src/core/utils.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# IMPORTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +from src.thirdparty.code import *; +from src.thirdparty.misc import *; +from src.thirdparty.types import *; + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# EXPORTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +__all__ = [ + 'flatten', + 'get_timestamp_string', +]; + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# METHODS - date, time +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +def get_timestamp() -> datetime: # pragma: no cover + return datetime.now(); + +def get_timestamp_string() -> str: # pragma: no cover + return str(get_timestamp()); + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# METHODS arrays +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +def flatten(X: list[list[Any]]) -> list[Any]: + return list(itertools_chain.from_iterable(X)); diff --git a/src/thirdparty/__init__.py b/src/thirdparty/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/thirdparty/code.py b/src/thirdparty/code.py new file mode 100644 index 0000000..1650362 --- /dev/null +++ b/src/thirdparty/code.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# IMPORTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +from functools import partial; +from functools import reduce; +from functools import wraps; +from dataclasses import Field; +from dataclasses import MISSING; +from dataclasses import asdict; +from dataclasses import dataclass; +from dataclasses import field; +from itertools import chain as itertools_chain; +from itertools import product as itertools_product; +from operator import itemgetter; +from pydantic import BaseModel; +# cf. https://github.com/mplanchard/safetywrap +from safetywrap import Ok; +from safetywrap import Err; +from safetywrap import Nothing; +from safetywrap import Result; +from safetywrap import Option; +from safetywrap import Some; + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# EXPORTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +__all__ = [ + 'partial', + 'reduce', + 'wraps', + 'asdict', + 'dataclass', + 'field', + 'Field', + 'MISSING', + 'itertools_chain', + 'itertools_product', + 'itemgetter', + 'BaseModel', + 'Err', + 'Nothing', + 'Ok', + 'Option', + 'Result', + 'Some', +]; diff --git a/src/thirdparty/config.py b/src/thirdparty/config.py new file mode 100644 index 0000000..214b216 --- /dev/null +++ b/src/thirdparty/config.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# IMPORTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +from dotenv import load_dotenv; +from dotenv import dotenv_values; +import json; +import jsonschema; +from lazy_load import lazy; +from yaml import add_constructor; +from yaml import load as yaml_load; +from yaml import FullLoader as yaml_FullLoader; +from yaml import add_path_resolver as yaml_add_path_resolver; + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# EXPORTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +__all__ = [ + 'load_dotenv', + 'dotenv_values', + 'json', + 'jsonschema', + 'lazy', + 'add_constructor', + 'yaml_load', + 'yaml_FullLoader', + 'yaml_add_path_resolver', +]; diff --git a/src/thirdparty/io.py b/src/thirdparty/io.py new file mode 100644 index 0000000..34d0292 --- /dev/null +++ b/src/thirdparty/io.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# IMPORTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +from getpass import getpass; + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# EXPORTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +__all__ = [ + 'getpass', +]; diff --git a/src/thirdparty/log.py b/src/thirdparty/log.py new file mode 100644 index 0000000..03d159d --- /dev/null +++ b/src/thirdparty/log.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# IMPORTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +import logging; +from logging import LogRecord; + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# EXPORTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +__all__ = [ + 'logging', + 'LogRecord', +]; diff --git a/src/thirdparty/maths.py b/src/thirdparty/maths.py new file mode 100644 index 0000000..b7fbf06 --- /dev/null +++ b/src/thirdparty/maths.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# IMPORTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +from fractions import Fraction; +import math; +import numpy as np; +import random; + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# EXPORTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +__all__ = [ + 'Fraction', + 'math', + 'np', + 'random', +]; diff --git a/src/thirdparty/misc.py b/src/thirdparty/misc.py new file mode 100644 index 0000000..af351b7 --- /dev/null +++ b/src/thirdparty/misc.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# IMPORTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +from datetime import datetime; +from datetime import timedelta; +import lorem; +import re; +from textwrap import dedent; + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# EXPORTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +__all__ = [ + 'lorem', + 're', + 'datetime', + 'timedelta', + 'dedent', +]; diff --git a/src/thirdparty/render.py b/src/thirdparty/render.py new file mode 100644 index 0000000..e41c841 --- /dev/null +++ b/src/thirdparty/render.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# IMPORTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +from IPython.display import Latex; +from IPython.display import display_latex; +from IPython.display import display_png; +from IPython.display import display_markdown; +from IPython.display import display; +# from array_to_latex import to_ltx as array_to_latex; # <- has issues +from qiskit.visualization import array_to_latex; + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# EXPORTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +__all__ = [ + 'Latex', + 'display', + 'display_latex', + 'display_png', + 'display_markdown', + 'array_to_latex', +]; diff --git a/src/thirdparty/run.py b/src/thirdparty/run.py new file mode 100644 index 0000000..f6a7081 --- /dev/null +++ b/src/thirdparty/run.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# IMPORTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +from codetiming import Timer; + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# EXPORTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +__all__ = [ + 'Timer', +]; diff --git a/src/thirdparty/system.py b/src/thirdparty/system.py new file mode 100644 index 0000000..75bc198 --- /dev/null +++ b/src/thirdparty/system.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# IMPORTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +import os; +from pathlib import Path; +import sys; + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# EXPORTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +__all__ = [ + 'os', + 'Path', + 'sys', +]; diff --git a/src/thirdparty/types.py b/src/thirdparty/types.py new file mode 100644 index 0000000..cfaf601 --- /dev/null +++ b/src/thirdparty/types.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# IMPORTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +from enum import Enum; +from io import BytesIO; +from nptyping import NDArray; +from nptyping import Shape; +from nptyping import Bool; +from nptyping import UInt; +from nptyping import UInt8; +from nptyping import UInt32; +from nptyping import UInt64; +from nptyping import Int; +from nptyping import Int32; +from nptyping import Int64; +from nptyping import Float; +from nptyping import Float32; +from nptyping import Float64; +from numpy import uint8; +from numpy import int32; +from numpy import int64; +from numpy import float32; +from numpy import float64; +from numpy import complex64; +from numpy import complex128; +from pydantic import conint; +from typing import Any; +from typing import Awaitable; +from typing import Callable; +from typing import ClassVar; +from typing import Coroutine; +from typing import Generator; +from typing import Generic; +from typing import Optional; +from typing import Type; +from typing import TypeVar; +from typing_extensions import Concatenate; +from typing_extensions import ParamSpec; + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# EXPORTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +__all__ = [ + 'Enum', + 'BytesIO', + 'NDArray', + 'Shape', + 'Bool', + 'UInt', + 'UInt8', + 'UInt32', + 'UInt64', + 'Int', + 'Int32', + 'Int64', + 'Float', + 'Float32', + 'Float64', + 'uint8', + 'int32', + 'int64', + 'float32', + 'float64', + 'complex64', + 'complex128', + 'conint', + 'Any', + 'Awaitable', + 'Callable', + 'ClassVar', + 'Coroutine', + 'Generator', + 'Generic', + 'Optional', + 'Type', + 'TypeVar', + 'Concatenate', + 'ParamSpec', +];