commit 1b03bddd30718bac90118c6cd243dff2f9b455e8 Author: Walter Oggioni Date: Sat Jun 22 08:13:48 2024 +0800 initial commit diff --git a/.gitea/workflows/build.yaml b/.gitea/workflows/build.yaml new file mode 100644 index 0000000..da88806 --- /dev/null +++ b/.gitea/workflows/build.yaml @@ -0,0 +1,22 @@ +name: CI +on: + push: + branches: [ master ] +jobs: + build: + runs-on: woryzen + steps: + - name: Checkout sources + uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + cache: 'pip' + - name: Execute build + env: + TWINE_REPOSITORY_URL: ${{ vars.PYPI_REGISTRY_URL }} + TWINE_USERNAME: ${{ vars.PUBLISHER_USERNAME }} + TWINE_PASSWORD: ${{ secrets.PUBLISHER_TOKEN }} + run: | + pip install -r requirements.txt + python -m build + python -m twine upload --repository gitea dist/*{.whl,rag.gz} \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..e120b74 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,35 @@ +[build-system] +requires = ["setuptools>=61.0"] +build-backend = "setuptools.build_meta" + +[project] +name = "pwo" +version = "0.0.1" +authors = [ + { name="Walter Oggioni", email="oggioni.walter@gmail.com" }, +] +description = "Python language utilities" +readme = "README.md" +requires-python = ">=3.10" +classifiers = [ + "Programming Language :: Python :: 3", + "License :: OSI Approved :: MIT License", + "Operating System :: OS Independent", +] +dependencies = [ + 'typing_extensions==4.7.1' +] + +[project.urls] +"Homepage" = "https://gitea.woggioni.net/woggioni/pwo" +"Bug Tracker" = "https://gitea.woggioni.net/woggioni/pwo/issues" + +[tool.mypy] +python_version = "3.12" +disallow_untyped_defs = true +show_error_codes = true +no_implicit_optional = true +warn_return_any = true +warn_unused_ignores = true +exclude = ["scripts", "docs", "test"] +strict = true \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..941b612 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,288 @@ +alabaster==0.7.16 +annotated-types==0.7.0 +anyio==4.4.0 +appdirs==1.4.4 +apsw==3.45.2.0 +argcomplete==3.1.3.dev0+g140fa51.d20240618 +argon2-cffi==23.1.0 +argon2-cffi-bindings==21.2.0 +asciidoc==10.2.0 +astroid==3.2.2 +asttokens==2.4.1 +async-lru==2.0.4 +async-timeout==4.0.3 +attrs==23.2.1.dev0 +Authlib==1.2.1 +autocommand==2.2.2 +Babel==2.14.0 +bcrypt==4.1.3 +beautifulsoup4==4.12.3 +black==24.4.2 +bleach==6.1.0 +botocore==1.34.106 +bottle==0.12.25 +breezy==3.3.7 +Brlapi==0.8.5 +Brotli==1.1.0 +brotlicffi==1.1.0.0 +btrfsutil==6.9 +build==1.2.1 +CacheControl==0.14.0 +certifi==2024.6.2 +cffi==1.16.0 +chardet==5.2.0 +charset-normalizer==3.3.2 +click==8.1.7 +colorama==0.4.6 +comm==0.2.2 +commonmark==0.9.1 +configobj==5.0.8 +construct==2.10.70 +contourpy==1.2.1 +coverage==7.5.1 +cryptography==42.0.6 +css-parser==1.0.10 +cssselect==1.2.0 +cycler==0.12.1 +Cython==3.0.10 +dbus-python==1.3.2 +decorator==5.1.1 +defusedxml==0.7.1 +dill==0.3.8 +distlib==0.3.8 +distro==1.9.0 +dnspython==2.6.1 +docker==7.1.0 +docutils==0.21.2 +dulwich==0.22.1 +executing==2.0.0 +fastbencode==0.2 +fastjsonschema==2.20.0 +faust-cchardet==2.1.19 +feedparser==6.0.11 +fido2==1.1.3 +filelock==3.13.3 +fonttools==4.53.0 +future==1.0.0 +gbinder-python==1.1.2 +gevent==24.2.1 +Glances==4.0.8 +gpg==1.23.2 +greenlet==3.0.3 +h11==0.14.0 +html2text==2020.1.16 +html5-parser==0.4.12 +html5lib==1.1 +httpcore==1.0.5 +httpx==0.27.0 +idna==3.6 +ifaddr==0.2.0 +imagesize==1.4.1 +importlib_metadata==5.1.0 +inflate64==1.0.0 +inflect==7.2.1 +installer==0.7.0 +ipykernel==6.29.4 +ipython==8.25.0 +isort==5.13.2 +jaraco.classes==3.4.0 +jaraco.context==4.3.0 +jaraco.functools==4.0.1 +jaraco.text==3.12.1 +jedi==0.19.1 +jeepney==0.8.0 +Jinja2==3.1.4 +jmespath==1.0.1 +json5==0.9.25 +jsonschema==4.22.0 +jsonschema-specifications==2023.12.1 +jupyter-events==0.10.0 +jupyter_client==8.6.2 +jupyter_core==5.7.2 +jupyter_server==2.14.1 +jupyterlab==4.2.2 +jupyterlab_pygments==0.3.0 +jupyterlab_server==2.27.2 +keyring==25.2.1 +kiwisolver==1.4.5 +lazy-object-proxy==1.10.0 +lensfun==0.3.4 +libfdt==1.7.0 +lit==17.0.6.dev0 +louis==3.30.0 +lxml==5.2.2 +lxml_html_clean==0.1.1 +Mako==1.3.5.dev0 +Markdown==3.6 +markdown-it-py==3.0.0 +MarkupSafe==2.1.5 +matplotlib==3.8.3 +matplotlib-inline==0.1.7 +mccabe==0.7.0 +mdurl==0.1.2 +mechanize==0.4.10 +merge3==0.0.15 +meson==1.4.1 +mistune==3.0.2 +more-itertools==10.2.0 +msgpack==1.0.5 +multivolumefile==0.2.3 +mutagen==1.47.0 +mypy_extensions==1.0.0 +nbclient==0.10.0 +nbconvert==7.16.4 +nbformat==5.10.4 +nest_asyncio==1.6.0 +netifaces==0.11.0 +netsnmp-python==1.0a1 +nftables==0.1 +nose==1.3.7 +notebook==7.2.1 +notebook_shim==0.2.4 +nspektr==0.5.0 +numpy==1.26.4 +ordered-set==4.1.0 +orjson==3.10.5 +overrides==7.7.0 +packaging==24.0 +pandocfilters==1.5.1 +paramiko==3.4.0 +parso==0.8.4 +pathspec==0.12.1 +patiencediff==0.2.15 +pbr==6.0.0 +pdftotext==2.2.2 +pefile==2023.2.7 +pexpect==4.9.0 +pickleshare==0.7.5 +pillow==10.3.0 +pipx==1.6.0 +platformdirs==4.2.0 +ply==3.11 +prometheus_client==0.20.0 +prompt_toolkit==3.0.47 +psutil==5.9.8 +ptyprocess==0.7.0 +pure_eval==0.2.2 +pwquality==1.4.5 +py7zr==0.21.0 +pyalpm==0.10.6 +pyasn1==0.5.1 +pybcj==1.0.2 +pycairo==1.26.0 +pychm==0.8.6 +pycodestyle==2.11.1 +pycparser==2.22 +pycryptodome==3.20.0 +pycryptodomex==3.20.0 +pycurl==7.45.2 +pydantic==2.7.4 +pydantic_core==2.18.4 +pyflakes==3.2.0 +Pygments==2.17.2 +PyGObject==3.48.2 +PyKCS11==1.5.16 +pykeepass==4.0.7 +pylint==3.2.3 +PyNaCl==1.5.0 +pyOpenSSL==24.1.0 +pyotp==2.9.0 +pyparsing==3.1.2 +pyppmd==1.1.0 +pyproject_hooks==1.1.0 +PyQt5==5.15.10 +PyQt5_sip==12.13.0 +PyQt6==6.7.0 +PyQt6-WebEngine==6.7.0 +PyQt6_sip==13.6.0 +PyQtWebEngine==5.15.6 +pyrsistent==0.19.3 +pyscard==2.0.8 +PySocks==1.7.1 +pystache==0.6.5 +python-dateutil==2.9.0 +python-json-logger==2.0.7 +python-xlib==0.33 +python-yubico==1.3.3 +pytz==2024.1 +pyusb==1.2.1 +pyxdg==0.28 +PyYAML==6.0.1 +pyzmq==25.1.2 +pyzstd==0.16.0 +qrtools==2.1 +referencing==0.35.1 +Reflector==2023.6.28.0.36.1 +regex==2024.5.15 +requests==2.32.3 +resolvelib==1.0.1 +retrying==1.3.4 +rich==13.7.1 +rpds-py==0.18.1 +rsa==4.9 +ruamel.yaml==0.18.6 +ruamel.yaml.clib==0.2.8 +s3transfer==0.10.1 +SecretStorage==3.3.3 +Send2Trash==1.8.2 +setproctitle==1.3.3 +setuptools==69.0.3 +setuptools-scm==8.1.0 +sgmllib3k==1.0.0 +simplejson==3.19.2 +six==1.16.0 +sniffio==1.3.1 +snowballstemmer==2.2.0 +soupsieve==2.5 +speedtest-cli==2.1.3 +Sphinx==7.3.7 +sphinx_rtd_theme==1.3.0 +sphinxcontrib-applehelp==1.0.8 +sphinxcontrib-devhelp==1.0.6 +sphinxcontrib-htmlhelp==2.0.5 +sphinxcontrib-jquery==4.1 +sphinxcontrib-jsmath==1.0.1 +sphinxcontrib-qthelp==1.0.7 +sphinxcontrib-serializinghtml==1.1.10 +stack_data==0.6.3 +TBB==0.2 +tenacity==8.3.0 +texttable==1.7.0 +tinycss2==1.3.0 +toml==0.10.2 +tomli==2.0.1 +tomlkit==0.12.5 +torbrowser-launcher==0.3.7 +tornado==6.4 +tqdm==4.66.2 +traitlets==5.14.3 +trove-classifiers==2024.5.23 +typeguard==4.3.0 +typing_extensions==4.12.2 +tzlocal==5.2 +uc-micro-py==1.0.3 +ufw==0.36.2 +ujson==5.10.0 +unrardll==0.1.7 +urllib3==1.26.18 +userpath==1.9.2 +validate==5.0.8 +validate-pyproject==0.16 +validators==0.20.0 +vdf==3.4 +wcwidth==0.2.13 +webencodings==0.5.1 +websocket-client==1.8.0 +websockets==12.0 +wheel==0.43.0 +wrapt==1.16.0 +xxhash==3.4.1 +yt-dlp==2024.5.27 +yubikey-manager==5.4.0 +zeroconf==0.63.0 +zipfile-deflate64==0.2.0 +zipp==3.18.1 +zope.event==5.0 +zope.interface==6.3 +zstandard==0.22.0 +zxcvbn==4.4.28 diff --git a/src/pwo/maybe.py b/src/pwo/maybe.py new file mode 100644 index 0000000..f0d00d6 --- /dev/null +++ b/src/pwo/maybe.py @@ -0,0 +1,75 @@ +from __future__ import annotations +from typing import TypeVar, Generic, Optional, Callable, Any + +T = TypeVar('T') +U = TypeVar('U') + + +class Maybe(Generic[T]): + + def __init__(self, value: Optional[T] = None): + self._value: Optional[T] = value + + @staticmethod + def of(obj: T) -> Maybe[T]: + return Maybe(obj) + + @staticmethod + def of_nullable(obj: Optional[T]) -> Maybe[T]: + return Maybe(obj) + + @staticmethod + def empty() -> Maybe[U]: + return _empty + + @property + def value(self) -> T: + value = self._value + if not value: + raise ValueError('Empty Maybe') + else: + return value + + @property + def is_present(self) -> bool: + return self._value is not None + + @property + def is_empty(self) -> bool: + return not self.is_present + + def map(self, transformer: Callable[[T], U]) -> Maybe[U]: + result: Maybe[U] + if self.is_present: + result = Maybe(transformer(self.value)) + else: + result = Maybe.empty() + return result + + def filter(self, predicate: Callable[[T], bool]) -> Maybe[T]: + return self if self.is_present and predicate(self.value) else Maybe.empty() + + def flat_map(self, transformer: Callable[[T], Maybe[U]]) -> Maybe[U]: + return transformer(self.value) if self.is_present else Maybe.empty() + + def or_else(self, alt: T) -> T: + return self.value if self.is_present else alt + + def or_none(self) -> Optional[T]: + return self.value if self.is_present else None + + def or_else_throw(self, supplier: Callable[[], Exception]) -> T: + if self.is_present: + return self.value + else: + raise supplier() + + def or_else_get(self, supplier: Callable[[], T]) -> Maybe[T]: + return self if self.is_present else Maybe.of_nullable(supplier()) + + def if_present(self, callback: Callable[[T], U]) -> None: + if self.is_present: + callback(self.value) + + +_empty: Maybe[Any] = Maybe(None)