diff --git a/README.md b/README.md index 12e42ee..73fdb86 100644 --- a/README.md +++ b/README.md @@ -168,14 +168,23 @@ except StultusUnavailable as err: ### `StultusUnavailable` -If the server is unreachable, every function will raise a `StultusUnavailable` exception. -This helps avoid silent logic failures when the sacred squirrel cloud is down. +Every function in `multinut.stultus` relies on a sacred remote endpoint: +`https://stultus.chipperfluff.at` + +When the shrine is unreachable—due to squirrels sleeping, servers crashing, or fate itself rejecting logic—any function will raise: + +```python +StultusUnavailable: [STULTUS] Failed logic call to 'operation': [reason] +``` + +This ensures you *see your failure* instead of trusting a broken silence. +Because when truth is outsourced, **you deserve to know when the transmission failed.** --- -### ping() +### `ping()` -You can check if the Stultus server is alive: +Use `ping()` to determine whether the squirrel logic shrine is currently active: ```python from multinut.stultus import ping @@ -186,31 +195,139 @@ else: print("The fluff has left the network.") ``` +Returns `True` only when the `/ping` endpoint returns `{ "status": "ok" }`. +False means the fluff is silent. Prepare your backup shrine. + +--- + ### Latin Class Hierarchy -| Class | Translation | Description | -|---------------|------------------|-------------| -| `StultusMixin` | Mixin of the Fool | Injects foolish logic into all descendants | -| `StultusInt` | Foolish Integer | Integer that compares via HTTP | -| `StultusFloat` | Foolish Float | Float that uses a server for > / < | -| `StultusStr` | Foolish String | String that checks equality by prayer | -| `StultusBool` | Foolish Truth | Boolean logic outsourced to ChipperFluff | +This module replaces standard Python primitives with HTTP-wrapped equivalents. +They override operators (`==`, `>=`, `+`, `[]`, etc.) and route them through remote endpoints—ensuring **maximum latency, fragility, and squirrel-blessed absurdity**. -> *Veritas non localis est.* -> *Truth is not local.* +| Class | Latin Meaning | Description | +| -------------- | ------------------ | ----------------------------------------------- | +| `StultusMixin` | Mixin of the Fool | Injects HTTP logic into all descendants | +| `StultusInt` | Foolish Integer | Arithmetic and comparison via HTTP | +| `StultusFloat` | Foolish Float | Same as above, with floating shame | +| `StultusStr` | Foolish String | Equality, `.upper()`, `.invert()` all delegated | +| `StultusBool` | Foolish Truth | Truth is no longer local | +| `StultusList` | Foolish List | Push, pop, index via remote POST | +| `StultusDict` | Foolish Dictionary | Dictionary access through divine lookup | -### Disclaimer +Example: -> **⚠️ WARNING:** -> This module outsources logical operators (like `==`, `<`, `>`, etc.) to a remote HTTPS server. It is intentionally slow, insecure, and exposes your data. Do **not** use in production—this is a joke for chaos and fun only. +```python +from multinut.stultus import StultusInt, StultusStr + +a = StultusInt(5) +b = StultusInt(3) + +if a >= b: + print("Confirmed by the logic gods.") + +word = StultusStr("uwu") +print(word.invert()) # 'uwu' reversed, via HTTP +``` + +--- + +### Available Remote Functions + +Every operation is offloaded via HTTPS. + +#### Logic + +```python +EQUALS(a, b) +GREATER(a, b) +LESSER(a, b) +GREATER_EQUAL(a, b) # makes 3 HTTPS requests +LESSER_EQUAL(a, b) +NOT(x) +AND(*args) +OR(*args) +``` + +#### Math + +```python +ADD(a, b) +SUB(a, b) +MUL(a, b) +DIV(a, b) # division by zero = "division by fluff" +RANDINT(a, b) # has artificial delay +RANGE(n, shuffle=True) # shuffled server-side +``` + +#### List Operations + +```python +LEN(list) +LIST_INDEX(list, index) +LIST_PUSH(list, item) +LIST_POP(list) +``` + +#### Dictionary Access + +```python +DICT_GET(dict, key) +``` + +#### String Tools + +```python +UPPER(str) +INVERT(str) +``` + +#### Truthiness + +```python +TRUTH(x) +BOOLIFY(str) # wraps eval (yes, really) +``` + +#### Time & Crypto + +```python +TIME() # epoch + ISO + fluff-certainty +HASH_PASSWORD(pw, algo) # e.g. sha256, sha1, md5 (pls no) +``` + +--- + +## Disclaimer + +> **⚠️ WARNING:** +> This module is deliberately slow, unsafe, and ridiculous. +> It outsources core logic to a remote web server. +> Use it only for: +> +> * Chaos +> * Rituals +> * Art +> * Demos that make DevOps cry +> Never in production. Never with real data. +> Do not test this on anyone you love. + +--- ## Contributing to `multinut.stultus` -Pull requests welcome. Must include at least one: -- Inefficient API call -- Questionable Latin -- Intentionally broken logic pattern +Pull requests are **gloriously welcome** if they contain any of the following: -Do not fix things. The project is working *as irrationally designed.* +* Inefficient use of the network +* Operators reimplemented in Latin +* Dumb ideas with great commitment +* Broken logic wrapped in elegant lies +* New subclasses like `StultusComplex`, `StultusPath`, or `StultusEnum` + +Please **do not fix performance, security, or clarity**. +The project is working *as irrationally designed.* + +> *Veritas non localis est.* +> *Truth is not local.* --- diff --git a/multinut/stultus/__init__.py b/multinut/stultus/__init__.py index ee0a7ea..cdf6a9e 100644 --- a/multinut/stultus/__init__.py +++ b/multinut/stultus/__init__.py @@ -1,20 +1,54 @@ -from .opperators import ( +from .custom import ( EQUALS, GREATER, LESSER, GREATER_EQUAL, LESSER_EQUAL, NOT, AND, OR ) -from .custom import ( +from .logic import ( StultusMixin, StultusInt, StultusFloat, - StultusStr, StultusBool + StultusStr, StultusBool, StultusList, StultusDict ) from .handler import ping, StultusUnavailable +from .math_ops import ADD, SUB, MUL, DIV, RANDINT, RANGE +from .lists import LEN, LIST_INDEX, LIST_PUSH, LIST_POP +from .dicts import DICT_GET +from .strings import UPPER, INVERT +from .truthy import TRUTH, BOOLIFY +from .crypto import HASH_PASSWORD +from .time_utils import TIME + __all__ = [ + # logic "EQUALS", "GREATER", "LESSER", "GREATER_EQUAL", "LESSER_EQUAL", "NOT", "AND", "OR", + + # types "StultusMixin", "StultusInt", "StultusFloat", - "StultusStr", "StultusBool", - "ping", "StultusUnavailable" + "StultusStr", "StultusBool", "StultusList", "StultusDict", + + # base + "ping", "StultusUnavailable", + + # math + "ADD", "SUB", "MUL", "DIV", "RANDINT", "RANGE", + + # lists + "LEN", "LIST_INDEX", "LIST_PUSH", "LIST_POP", + + # dicts + "DICT_GET", + + # strings + "UPPER", "INVERT", + + # truthiness + "TRUTH", "BOOLIFY", + + # crypto + "HASH_PASSWORD", + + # time + "TIME" ] diff --git a/multinut/stultus/crypto.py b/multinut/stultus/crypto.py new file mode 100644 index 0000000..cb62316 --- /dev/null +++ b/multinut/stultus/crypto.py @@ -0,0 +1,5 @@ +from .handler import _post + +def HASH_PASSWORD(password: str, algo: str = "sha256"): + result = _post("hash_password", {"password": password, "algo": algo}) + return result.get("hash") diff --git a/multinut/stultus/custom.py b/multinut/stultus/custom.py index 1bdeb8a..7468dbe 100644 --- a/multinut/stultus/custom.py +++ b/multinut/stultus/custom.py @@ -1,20 +1,54 @@ -from multinut.stultus import ( +from .logic import ( EQUALS, GREATER, LESSER, GREATER_EQUAL, LESSER_EQUAL, NOT, AND, OR ) +from .math_ops import ADD, SUB, MUL, DIV +from .strings import UPPER, INVERT +from .truthy import TRUTH +from .lists import LIST_INDEX, LIST_PUSH, LIST_POP +from .dicts import DICT_GET +# Core mixin for logic + math class StultusMixin: def __eq__(self, other): return EQUALS(self, other) + def __ne__(self, other): return NOT(EQUALS(self, other)) def __gt__(self, other): return GREATER(self, other) def __lt__(self, other): return LESSER(self, other) def __ge__(self, other): return GREATER_EQUAL(self, other) def __le__(self, other): return LESSER_EQUAL(self, other) - def __ne__(self, other): return NOT(EQUALS(self, other)) def __and__(self, other): return AND(self, other) def __or__(self, other): return OR(self, other) + def __bool__(self): return TRUTH(self) -class StultusInt(StultusMixin, int): pass -class StultusFloat(StultusMixin, float): pass -class StultusStr(StultusMixin, str): pass -class StultusBool(StultusMixin, bool): pass +# Math extensions +class StultusInt(StultusMixin, int): + def __add__(self, other): return ADD(self, other) + def __sub__(self, other): return SUB(self, other) + def __mul__(self, other): return MUL(self, other) + def __truediv__(self, other): return DIV(self, other) +class StultusFloat(StultusMixin, float): + def __add__(self, other): return ADD(self, other) + def __sub__(self, other): return SUB(self, other) + def __mul__(self, other): return MUL(self, other) + def __truediv__(self, other): return DIV(self, other) + +# String extensions +class StultusStr(StultusMixin, str): + def upper(self): return UPPER(self) + def invert(self): return INVERT(self) + def __getitem__(self, index): return LIST_INDEX(list(self), index) + +# Bool wrapper +class StultusBool(StultusMixin, bool): + pass # already supports logic + +# List wrapper +class StultusList(StultusMixin, list): + def push(self, item): return LIST_PUSH(self.copy(), item) + def pop(self): return LIST_POP(self.copy()) + def __getitem__(self, index): return LIST_INDEX(self, index) + +# Dict wrapper +class StultusDict(StultusMixin, dict): + def __getitem__(self, key): return DICT_GET(self, key) diff --git a/multinut/stultus/dicts.py b/multinut/stultus/dicts.py new file mode 100644 index 0000000..6b4d476 --- /dev/null +++ b/multinut/stultus/dicts.py @@ -0,0 +1,3 @@ +from .handler import _post + +def DICT_GET(dct, key): return _post("dict_get", {"dict": dct, "key": key}) diff --git a/multinut/stultus/handler.py b/multinut/stultus/handler.py index 7c454ba..36850fc 100644 --- a/multinut/stultus/handler.py +++ b/multinut/stultus/handler.py @@ -3,16 +3,23 @@ import requests BASE_URL = "https://stultus.chipperfluff.at" class StultusUnavailable(Exception): - """Raised when the stultus server is unreachable or returns an error.""" pass -def _get(path: str, params: dict | list = None) -> bool: +def _get(path: str, params: dict | list = None) -> any: try: r = requests.get(f"{BASE_URL}/{path}", params=params, timeout=5) r.raise_for_status() - return r.json().get("result", False) + return r.json().get("result") except Exception as e: - raise StultusUnavailable(f"[STULTUS] Failed logic call to '{path}': {e}") + raise StultusUnavailable(f"[STULTUS] Failed GET {path}: {e}") + +def _post(path: str, json: dict = None) -> any: + try: + r = requests.post(f"{BASE_URL}/{path}", json=json, timeout=5) + r.raise_for_status() + return r.json().get("result") or r.json() + except Exception as e: + raise StultusUnavailable(f"[STULTUS] Failed POST {path}: {e}") def ping() -> bool: try: diff --git a/multinut/stultus/lists.py b/multinut/stultus/lists.py new file mode 100644 index 0000000..7e96f0c --- /dev/null +++ b/multinut/stultus/lists.py @@ -0,0 +1,6 @@ +from .handler import _post + +def LEN(value): return _post("len", {"value": value}).get("length") +def LIST_INDEX(lst, index): return _post("list_index", {"list": lst, "index": index}) +def LIST_PUSH(lst, item): return _post("list_push", {"list": lst, "item": item}) +def LIST_POP(lst): return _post("list_pop", {"list": lst}) diff --git a/multinut/stultus/opperators.py b/multinut/stultus/logic.py similarity index 88% rename from multinut/stultus/opperators.py rename to multinut/stultus/logic.py index 111a233..a97579b 100644 --- a/multinut/stultus/opperators.py +++ b/multinut/stultus/logic.py @@ -8,4 +8,4 @@ def AND(*args): return _get("and", [("val", str(v).lower()) for v in args]) def OR(*args): return _get("or", [("val", str(v).lower()) for v in args]) def GREATER_EQUAL(a, b): return OR(GREATER(a, b), EQUALS(a, b)) -def LESSER_EQUAL(a, b): return OR(LESSER(a, b), EQUALS(a, b)) \ No newline at end of file +def LESSER_EQUAL(a, b): return OR(LESSER(a, b), EQUALS(a, b)) diff --git a/multinut/stultus/math_ops.py b/multinut/stultus/math_ops.py new file mode 100644 index 0000000..b2d5b6c --- /dev/null +++ b/multinut/stultus/math_ops.py @@ -0,0 +1,8 @@ +from .handler import _get + +def ADD(a, b): return _get("add", {"a": a, "b": b}) +def SUB(a, b): return _get("sub", {"a": a, "b": b}) +def MUL(a, b): return _get("mul", {"a": a, "b": b}) +def DIV(a, b): return _get("div", {"a": a, "b": b}) +def RANDINT(a, b): return _get("randint", {"a": a, "b": b}) +def RANGE(n, shuffle=False): return _get("range", {"n": n, "shuffle": str(shuffle).lower()}) diff --git a/multinut/stultus/strings.py b/multinut/stultus/strings.py new file mode 100644 index 0000000..57907b4 --- /dev/null +++ b/multinut/stultus/strings.py @@ -0,0 +1,4 @@ +from .handler import _get + +def UPPER(value: str): return _get("upper", {"value": value}) +def INVERT(value: str): return _get("invert_string", {"value": value}) diff --git a/multinut/stultus/time_utils.py b/multinut/stultus/time_utils.py new file mode 100644 index 0000000..22d7a0e --- /dev/null +++ b/multinut/stultus/time_utils.py @@ -0,0 +1,5 @@ +from .handler import _get + +def TIME(): + data = _get("time") + return data # epoch, iso, certainty diff --git a/multinut/stultus/truthy.py b/multinut/stultus/truthy.py new file mode 100644 index 0000000..9270d0f --- /dev/null +++ b/multinut/stultus/truthy.py @@ -0,0 +1,4 @@ +from .handler import _post, _get + +def TRUTH(value): return _post("truth", {"value": value}).get("truth") +def BOOLIFY(value: str): return _get("boolify", {"value": value}) diff --git a/setup.py b/setup.py index 019e2fe..235061b 100644 --- a/setup.py +++ b/setup.py @@ -2,9 +2,12 @@ from setuptools import setup, find_packages setup( name='multinut', - version='0.2.8', + version='0.2.9', packages=find_packages(), - install_requires=["python-dotenv"], + install_requires=[ + "requests>=2.25.0", + "python-dotenv>=0.21.0" + ], author='Chipperfluff', author_email='contact@chipperfluff.at', description='A completely unnecessary multitool module.',