From da946981b1b8737231e62ab6bbf69bf6a17c1c68 Mon Sep 17 00:00:00 2001 From: Tobias Date: Mon, 16 Jun 2025 23:57:11 +0200 Subject: [PATCH] added pytest n fixes --- .gitignore | 3 ++ func_py/__init__.py | 3 +- func_py/debug.py | 20 ---------- func_py/func.py | 64 ++++++++++++++------------------ func_py/lib.py | 49 ------------------------- poetry.lock | 89 +++++++++++++++++++++++++++++++++++++++++++++ pyproject.toml | 2 +- tests/__init__.py | 1 + tests/test_basic.py | 41 +++++++++++++++++++++ 9 files changed, 165 insertions(+), 107 deletions(-) delete mode 100644 func_py/debug.py delete mode 100644 func_py/lib.py create mode 100644 poetry.lock create mode 100644 tests/__init__.py create mode 100644 tests/test_basic.py diff --git a/.gitignore b/.gitignore index 0d20b64..c324620 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,4 @@ *.pyc +*__pycache__ +.pytest_cache +try.py diff --git a/func_py/__init__.py b/func_py/__init__.py index 561bec1..e7c1685 100644 --- a/func_py/__init__.py +++ b/func_py/__init__.py @@ -1,5 +1,6 @@ -from .func import * +from .func import function + #from .list import * #from .string import * #from .io import * diff --git a/func_py/debug.py b/func_py/debug.py deleted file mode 100644 index d9a99c0..0000000 --- a/func_py/debug.py +++ /dev/null @@ -1,20 +0,0 @@ - -""" -def log(func): - def new_func(*args): - r = func(*args) - print(">>> " + str(func).split(" ")[1] + str(list(args)) + " -> " + str(r)) - return r - return new_func -""" - - - -def log(f): - def g(*args): - r = f(*args) - print("Calculating: %s(%s) = %s" % ( str(f).split(" ")[1], str(",".join(map(str,list(args)))), str(r)) ) - return r - return g - - diff --git a/func_py/func.py b/func_py/func.py index 2c3bfaf..05e6607 100644 --- a/func_py/func.py +++ b/func_py/func.py @@ -2,16 +2,26 @@ from inspect import signature, Parameter, _empty from functools import partial from typing import Any -class Function: - #@staticmethod - #def add_missing_signature(f): +def flyweight(cls): + + def f(*args, **kwargs): + + return cls(*args, **kwargs) + + + return f + + + +#@flyweight +class function: __match_args__ = ["signature", "is_pure"] @staticmethod def compose(f, g): - if type(g) == Function: + if type(g) == function: g = g.original_func else: #whatif lambda? @@ -25,13 +35,11 @@ class Function: pass #its a functools.partial func with no name... - - if type(f) == Function: + if type(f) == function: f = f.original_func sig_g = signature(g) g_req_params = [v for k, v in sig_g.parameters.items() if v.default == _empty] - g_typed_req_params = [p if p.annotation == _empty else Parameter(name=p.name, annotation=Any, kind=Parameter.POSITIONAL_ONLY) for p in g_req_params] def h(*args, **kwargs): @@ -39,7 +47,10 @@ class Function: f_ret_type = signature(f).return_annotation h.__signature__ = sig_g.replace(parameters=g_typed_req_params, return_annotation=Any if f_ret_type == _empty else f_ret_type) - return Function(h) + return function(h) + + + #TODO: implement fly weight pattern def __init__(self, f): self.original_func = f @@ -49,30 +60,33 @@ class Function: self.is_pure = True def __str__(self): - return str(signature(self.original_func)) + return str(signature(self.original_func)).replace(", /)", ")") def __repr__(self): return str(self) def __mul__(self, g): - return Function.compose(self, g) + return function.compose(self, g) def __rmul__(self, g): - return Function.compose(g, self) + return function.compose(g, self) + + def __eq__(self, other): + return self.original_func == other.original_func + @property def required_args(self): return [(k, v) for k, v in signature(self.original_func).parameters.items() if v.default == _empty] def __call__(self, *args, **kwargs): - #currying: if less than the needed args are given return a partial function if len(args) < len(self.required_args): sig = signature(self.original_func) f = partial(self.original_func, *args) req_params = [v for k, v in sig.parameters.items() if v.default == _empty] remaining_params = req_params[len(args):] f.__signature__ = sig.replace(parameters=remaining_params, return_annotation=Any if sig.return_annotation == _empty else sig.return_annotation) - return Function(f) + return function(f) r = self.original_func(*args, **kwargs) if self.is_pure: @@ -83,31 +97,9 @@ class Function: -@Function -def inc(x: int) -> int: - return x + 1 - -@Function -def multi(a: int, b: int) -> int: - return a * b - -@Function -def add(a: int, b: int) -> int: - return a + b -#print(add(2,3)) -#print((inc * add)(2,3)) -#print((inc * add)) - -#print(add(99)) -print((add(99) * multi(100) * add(2) * (lambda x: x + 1))) - -print(Function.compose(lambda x: x + 1, lambda x: x * 3)) - -print(signature(Function.compose(lambda x: x + 1, lambda x: x * 3))) -#print(inspect.signature(add)) -#print(inspect.signature(add).parameters) + diff --git a/func_py/lib.py b/func_py/lib.py deleted file mode 100644 index b737fdb..0000000 --- a/func_py/lib.py +++ /dev/null @@ -1,49 +0,0 @@ -#======= Decoration ======== -def log(f): - def g(*args): - r = f(*args) - print(">> %s %s -> %s" % (str(f).split(" ")[1], str(list(args)), str(r))) - return r - return g - -#========= Composition ========= -def fix1(f, v): - def g(*args): - r = f(*([v]+list(args))) - return r - return g - -def curry(func, numArgs): - if numArgs == 1: return func - def f1(v): - return curry(fix1(func, v), numArgs-1) - return f1 - -def comp(g,f): - def r(*args, **kwargs): - return g(f(*args, **kwargs)) - return r - -#======== Operations =========== -def add(a, b): - return a + b - -def multi(a, b): - return a * b - - - - -def Monade(): - #Monade, (M a -> (a -> M b) -> M a) - def returm(x): - return [x] - def bind(m, f): - return returm(list(map(f,m))) - return returm, bind - - - - - - diff --git a/poetry.lock b/poetry.lock new file mode 100644 index 0000000..68d533b --- /dev/null +++ b/poetry.lock @@ -0,0 +1,89 @@ +# This file is automatically @generated by Poetry 1.8.4 and should not be changed by hand. + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] + +[[package]] +name = "iniconfig" +version = "2.1.0" +description = "brain-dead simple config-ini parsing" +optional = false +python-versions = ">=3.8" +files = [ + {file = "iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760"}, + {file = "iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7"}, +] + +[[package]] +name = "packaging" +version = "25.0" +description = "Core utilities for Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484"}, + {file = "packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f"}, +] + +[[package]] +name = "pluggy" +version = "1.6.0" +description = "plugin and hook calling mechanisms for python" +optional = false +python-versions = ">=3.9" +files = [ + {file = "pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746"}, + {file = "pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3"}, +] + +[package.extras] +dev = ["pre-commit", "tox"] +testing = ["coverage", "pytest", "pytest-benchmark"] + +[[package]] +name = "pygments" +version = "2.19.1" +description = "Pygments is a syntax highlighting package written in Python." +optional = false +python-versions = ">=3.8" +files = [ + {file = "pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c"}, + {file = "pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f"}, +] + +[package.extras] +windows-terminal = ["colorama (>=0.4.6)"] + +[[package]] +name = "pytest" +version = "8.4.0" +description = "pytest: simple powerful testing with Python" +optional = false +python-versions = ">=3.9" +files = [ + {file = "pytest-8.4.0-py3-none-any.whl", hash = "sha256:f40f825768ad76c0977cbacdf1fd37c6f7a468e460ea6a0636078f8972d4517e"}, + {file = "pytest-8.4.0.tar.gz", hash = "sha256:14d920b48472ea0dbf68e45b96cd1ffda4705f33307dcc86c676c1b5104838a6"}, +] + +[package.dependencies] +colorama = {version = ">=0.4", markers = "sys_platform == \"win32\""} +iniconfig = ">=1" +packaging = ">=20" +pluggy = ">=1.5,<2" +pygments = ">=2.7.2" + +[package.extras] +dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "requests", "setuptools", "xmlschema"] + +[metadata] +lock-version = "2.0" +python-versions = "^3.12" +content-hash = "b758df875e7c5835fb6160e4d2f49f9e3a2fef076e22613be6664aa81e2db2c2" diff --git a/pyproject.toml b/pyproject.toml index cffcebe..31f14eb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,6 +8,7 @@ readme = "README.md" [tool.poetry.dependencies] python = "^3.12" +pytest = "^8.4.0" [build-system] @@ -15,4 +16,3 @@ requires = ["poetry-core"] build-backend = "poetry.core.masonry.api" - diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/tests/__init__.py @@ -0,0 +1 @@ + diff --git a/tests/test_basic.py b/tests/test_basic.py new file mode 100644 index 0000000..6c548b6 --- /dev/null +++ b/tests/test_basic.py @@ -0,0 +1,41 @@ +from inspect import signature + +from func_py import function + + +@function +def inc(x: int) -> int: + return x + 1 + +@function +def multi(a: int, b: int) -> int: + return a * b + +@function +def add(a: int, b: int) -> int: + return a + b + + + +def test_abc(): + + #print(add(2,3)) + #print((inc * add)(2,3)) + #print((inc * add)) + + #print(add(99)) + print((add(99) * multi(100) * add(2) * (lambda x: x + 1))) + + print(function.compose(lambda x: x + 1, lambda x: x * 3)) + + print(signature(function.compose(lambda x: x + 1, lambda x: x * 3))) + + + #print(inspect.signature(add)) + #print(inspect.signature(add).parameters) + + assert True + + + +