22
.gitea/workflows/build.yaml
Normal file
22
.gitea/workflows/build.yaml
Normal file
@@ -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}
|
35
pyproject.toml
Normal file
35
pyproject.toml
Normal file
@@ -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
|
288
requirements.txt
Normal file
288
requirements.txt
Normal file
@@ -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
|
75
src/pwo/maybe.py
Normal file
75
src/pwo/maybe.py
Normal file
@@ -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)
|
Reference in New Issue
Block a user