veridret-plugins-core 1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (22) hide show
  1. veridret_plugins_core-1/.gitignore +14 -0
  2. veridret_plugins_core-1/LICENSE.md +50 -0
  3. veridret_plugins_core-1/PKG-INFO +20 -0
  4. veridret_plugins_core-1/README.md +4 -0
  5. veridret_plugins_core-1/pyproject.toml +95 -0
  6. veridret_plugins_core-1/src/veridret_plugins/core/__init__.py +11 -0
  7. veridret_plugins_core-1/src/veridret_plugins/core/_plugin.py +63 -0
  8. veridret_plugins_core-1/src/veridret_plugins/core/call.py +64 -0
  9. veridret_plugins_core-1/src/veridret_plugins/core/cmptools/__init__.py +8 -0
  10. veridret_plugins_core-1/src/veridret_plugins/core/cmptools/reverse.py +66 -0
  11. veridret_plugins_core-1/src/veridret_plugins/core/cmptools/unordered.py +48 -0
  12. veridret_plugins_core-1/src/veridret_plugins/core/functools/__init__.py +8 -0
  13. veridret_plugins_core-1/src/veridret_plugins/core/functools/call.py +43 -0
  14. veridret_plugins_core-1/src/veridret_plugins/core/functools/call_right.py +65 -0
  15. veridret_plugins_core-1/src/veridret_plugins/core/functools/compose_left.py +66 -0
  16. veridret_plugins_core-1/src/veridret_plugins/core/functools/compose_right.py +66 -0
  17. veridret_plugins_core-1/src/veridret_plugins/core/functools/identity.py +38 -0
  18. veridret_plugins_core-1/src/veridret_plugins/core/iterator.py +49 -0
  19. veridret_plugins_core-1/src/veridret_plugins/core/itertools/__init__.py +8 -0
  20. veridret_plugins_core-1/src/veridret_plugins/core/itertools/filter.py +50 -0
  21. veridret_plugins_core-1/src/veridret_plugins/core/itertools/fold_left.py +60 -0
  22. veridret_plugins_core-1/src/veridret_plugins/core/itertools/map.py +49 -0
@@ -0,0 +1,14 @@
1
+ # SPDX-License-Identifier: BSD-3-Clause
2
+
3
+ # Ignore Vim swap files.
4
+ .sw*
5
+ .*.sw*
6
+
7
+ # Ignore build & install artifacts.
8
+ /build*/
9
+ /dist*/
10
+ /install*/
11
+ /*.whl
12
+
13
+ # Ignore Python bytecode cache files.
14
+ __pycache__/
@@ -0,0 +1,50 @@
1
+ <!-- SPDX-License-Identifier: BSD-3-Clause -->
2
+
3
+ Copyright &copy; 2026 Jonathan Gruber.
4
+
5
+ Redistribution and use in source and binary forms,
6
+ with or without modification,
7
+ are permitted provided that the following conditions are met:
8
+
9
+ 1. Redistributions of source code must retain the above copyright notice,
10
+ this list of conditions
11
+ and the following disclaimer.
12
+
13
+ 2. Redistributions in binary form must reproduce the above copyright notice,
14
+ this list of conditions
15
+ and the following disclaimer
16
+ in the documentation and/or other materials
17
+ provided with the distribution.
18
+
19
+ 3. Neither the name of the copyright holder nor the names of its contributors
20
+ may be used to endorse or promote products derived from this software
21
+ without specific prior written permission.
22
+
23
+ THIS SOFTWARE IS PROVIDED
24
+ BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25
+ &ldquo;AS IS&rdquo;
26
+ AND ANY EXPRESS OR IMPLIED WARRANTIES,
27
+ INCLUDING,
28
+ BUT NOT LIMITED TO,
29
+ THE IMPLIED WARRANTIES OF MERCHANTABILITY
30
+ AND FITNESS FOR A PARTICULAR PURPOSE
31
+ ARE DISCLAIMED.
32
+ IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
33
+ FOR ANY DIRECT,
34
+ INDIRECT,
35
+ INCIDENTAL,
36
+ SPECIAL,
37
+ EXEMPLARY,
38
+ OR CONSEQUENTIAL DAMAGES
39
+ (INCLUDING,
40
+ BUT NOT LIMITED TO,
41
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
42
+ LOSS OF USE, DATA, OR PROFITS;
43
+ OR BUSINESS INTERRUPTION)
44
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
45
+ WHETHER IN CONTRACT,
46
+ STRICT LIABILITY,
47
+ OR TORT
48
+ (INCLUDING NEGLIGENCE OR OTHERWISE)
49
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
50
+ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,20 @@
1
+ Metadata-Version: 2.5
2
+ Name: veridret-plugins-core
3
+ Version: 1
4
+ Import-Name: veridret_plugins.core
5
+ Import-Namespace: veridret_plugins
6
+ Summary: The *official* Python package of the *official* standard core VerIdRet plugins
7
+ Project-URL: homepage, https://codeberg.org/jonathan-gruber-jg/veridret-plugins-core.git
8
+ Project-URL: source, https://codeberg.org/jonathan-gruber-jg/veridret-plugins-core.git
9
+ Author-email: Jonathan Gruber <jonathan.gruber.jg@gmail.com>
10
+ License-Expression: BSD-3-Clause
11
+ License-File: LICENSE.md
12
+ Requires-Python: ~=3.14.6
13
+ Requires-Dist: pydantic~=2.13
14
+ Requires-Dist: veridret~=1.0
15
+ Description-Content-Type: text/markdown
16
+
17
+ <!-- SPDX-License-Identifier: BSD-3-Clause -->
18
+
19
+ `veridret-plugins-core` is the *official* Python package
20
+ of the *official* standard core VerIdRet plugins.
@@ -0,0 +1,4 @@
1
+ <!-- SPDX-License-Identifier: BSD-3-Clause -->
2
+
3
+ `veridret-plugins-core` is the *official* Python package
4
+ of the *official* standard core VerIdRet plugins.
@@ -0,0 +1,95 @@
1
+ # SPDX-License-Identifier: BSD-3-Clause
2
+
3
+ [build-system]
4
+ requires = [
5
+ 'hatchling',
6
+ ]
7
+ build-backend = 'hatchling.build'
8
+
9
+ [project]
10
+ name = 'veridret-plugins-core'
11
+ dynamic = [
12
+ 'version',
13
+ ]
14
+ description = """\
15
+ The *official* Python package \
16
+ of the *official* standard core VerIdRet plugins\
17
+ """
18
+ readme = 'README.md'
19
+ license = 'BSD-3-Clause'
20
+ license-files = [
21
+ 'LICENSE.md',
22
+ ]
23
+ import-names = [
24
+ 'veridret_plugins.core',
25
+ ]
26
+ import-namespaces = [
27
+ 'veridret_plugins',
28
+ ]
29
+ requires-python = '~= 3.14.6'
30
+ dependencies = [
31
+ 'pydantic ~= 2.13',
32
+ 'veridret ~= 1.0',
33
+ ]
34
+
35
+ [[project.authors]]
36
+ name = 'Jonathan Gruber'
37
+ email = 'jonathan.gruber.jg@gmail.com'
38
+
39
+ [project.urls]
40
+ homepage = 'https://codeberg.org/jonathan-gruber-jg/veridret-plugins-core.git'
41
+ source = 'https://codeberg.org/jonathan-gruber-jg/veridret-plugins-core.git'
42
+
43
+ [tool.hatch.build.targets.wheel]
44
+ packages = [
45
+ 'src/veridret_plugins',
46
+ ]
47
+
48
+ [tool.hatch.version]
49
+ path = 'src/veridret_plugins/core/__init__.py'
50
+
51
+ [tool.pylint.main]
52
+ disable = [
53
+ 'missing-class-docstring',
54
+ 'missing-function-docstring',
55
+ 'too-few-public-methods',
56
+ 'too-many-instance-attributes',
57
+ 'unspecified-encoding',
58
+ ]
59
+
60
+ [tool.pylint.format]
61
+ max-line-length = 79
62
+
63
+ [tool.pylint.variables]
64
+ init-import = false
65
+
66
+ [tool.mypy]
67
+ mypy_path = [
68
+ '${MYPY_CONFIG_FILE_DIR}/src',
69
+ ]
70
+ packages = [
71
+ 'veridret_plugins',
72
+ ]
73
+ strict = true
74
+ strict_equality_for_none = true
75
+ warn_return_any = false
76
+
77
+ [tool.pyrefly]
78
+ project-includes = [
79
+ 'src',
80
+ ]
81
+ min-severity = 'warn'
82
+ preset = 'strict'
83
+ enabled-ignores = [
84
+ 'pyrefly',
85
+ ]
86
+
87
+ [tool.pyrefly.errors]
88
+ implicit-any-lambda = 'ignore'
89
+
90
+ [tool.pyright]
91
+ include = [
92
+ 'src',
93
+ ]
94
+ #typeCheckingMode = 'strict'
95
+ enableTypeIgnoreComments = false
@@ -0,0 +1,11 @@
1
+ # SPDX-License-Identifier: BSD-3-Clause
2
+
3
+ """
4
+ The *official* Python package
5
+ of the *official* standard core VerIdRet plugins.
6
+ """
7
+
8
+ __all__: list[str] = [
9
+ ]
10
+
11
+ __version__ = '1'
@@ -0,0 +1,63 @@
1
+ # SPDX-License-Identifier: BSD-3-Clause
2
+
3
+ """
4
+ Plugin utilities.
5
+ """
6
+
7
+ from typing import Annotated, Any, ClassVar
8
+
9
+ import pydantic
10
+
11
+ import veridret.plugin
12
+
13
+ __all__ = [
14
+ 'AnnotatedCall',
15
+ 'Call',
16
+ 'evaluate_call',
17
+ ]
18
+
19
+ class Call(pydantic.BaseModel):
20
+ """
21
+ A plugin call.
22
+ """
23
+
24
+ model_config: ClassVar = pydantic.ConfigDict(frozen=True)
25
+
26
+ plugin: str
27
+ args: dict[str, object] = pydantic.Field(
28
+ default_factory=dict,
29
+ validation_alias=pydantic.AliasChoices('arguments', 'args'),
30
+ serialization_alias='arguments',
31
+ )
32
+
33
+ def evaluate_call(call: Call) -> Any:
34
+ """
35
+ Evaluate a plugin call.
36
+
37
+ :param call: The plugin call,
38
+ :return: The result of the plugin call.
39
+ :raise Exception:
40
+ If the plugin cannot be loaded
41
+ or the call to it fails.
42
+ """
43
+
44
+ return veridret.plugin.load(call.plugin)(call.args)
45
+
46
+ def _inst_anno_call(value: Call | str) -> Call:
47
+ match value:
48
+ case Call():
49
+ return value
50
+ case str():
51
+ return Call(plugin=value)
52
+
53
+ type AnnotatedCall = Annotated[
54
+ Call,
55
+ pydantic.ValidateAs(
56
+ Call | str, # pyright: ignore[reportArgumentType]
57
+ _inst_anno_call,
58
+ ),
59
+ ]
60
+ """
61
+ :class:`Call` but annotated for Pydantic to instantiate the type
62
+ from a string ``x`` via ``Call(plugin=x)``.
63
+ """
@@ -0,0 +1,64 @@
1
+ # SPDX-License-Identifier: BSD-3-Clause
2
+
3
+ """
4
+ Evaluate a call expression.
5
+
6
+ In particular,
7
+ the plugin evaluates ``id a[1] a[2] ... a[n]``,
8
+ where ``id`` is the identity function
9
+ and each operand ``a[i]`` is the result of a plugin call.
10
+ """
11
+
12
+ from collections.abc import Callable
13
+ import functools
14
+ from typing import Any, cast, overload
15
+
16
+ import pydantic
17
+
18
+ from veridret_plugins.core import _plugin
19
+
20
+ __all__ = [
21
+ 'call',
22
+ ]
23
+
24
+ class _Args(pydantic.BaseModel):
25
+ operands: tuple[_plugin.AnnotatedCall, ...] = pydantic.Field(
26
+ (),
27
+ validation_alias=pydantic.AliasChoices('operands', 'items'),
28
+ serialization_alias='operands',
29
+ )
30
+
31
+ @overload
32
+ def _try_call[T, U](func: Callable[[T], U], arg: T) -> U:
33
+ ...
34
+ @overload
35
+ def _try_call(func: object, arg: object) -> Any:
36
+ ...
37
+ def _try_call(func: object, arg: object) -> Any:
38
+ return cast(Callable[[Any], Any], func)(arg)
39
+
40
+ def _identity[T](obj: T, /) -> T:
41
+ return obj
42
+
43
+ def call(args: dict[str, object]) -> Any:
44
+ """
45
+ Call the plugin.
46
+
47
+ :param args: A dictionary of the plugin's arguments.
48
+ :return: The result of the call expression specified by ``args``.
49
+ :raise Exception:
50
+ If ``args`` is invalid,
51
+ evaluating any of the plugin calls
52
+ that evaluate to the operands of the call expression
53
+ fails,
54
+ or any of the individual calls
55
+ made in evaluating the whole call expression
56
+ fails.
57
+ """
58
+
59
+ validated_args = _Args.model_validate(args, strict=True, by_name=False)
60
+ return functools.reduce(
61
+ _try_call,
62
+ map(_plugin.evaluate_call, validated_args.operands),
63
+ initial=_identity,
64
+ )
@@ -0,0 +1,8 @@
1
+ # SPDX-License-Identifier: BSD-3-Clause
2
+
3
+ """
4
+ Utilities for comparing values.
5
+ """
6
+
7
+ __all__: list[str] = [
8
+ ]
@@ -0,0 +1,66 @@
1
+ # SPDX-License-Identifier: BSD-3-Clause
2
+
3
+ """
4
+ Reflect/reverse rich comparisons upon an object.
5
+ """
6
+
7
+ from collections.abc import Callable
8
+ import dataclasses
9
+ import operator
10
+ import types
11
+ from typing import Any, final, Never, override
12
+
13
+ __all__ = [
14
+ 'call',
15
+ 'Reverse',
16
+ ]
17
+
18
+ @final
19
+ @dataclasses.dataclass(frozen=True)
20
+ class Reverse[T]:
21
+ """
22
+ A comparison key that reflects/reverses rich comparisons.
23
+ """
24
+
25
+ value: T
26
+
27
+ def _cmp_impl(
28
+ self, other: object, op: Callable[[Any, Any], object],
29
+ ) -> Any | types.NotImplementedType:
30
+ if not isinstance(other, Reverse):
31
+ return NotImplemented
32
+ return op(other.value, self.value)
33
+
34
+ def __lt__(self, other: object) -> Any | types.NotImplementedType:
35
+ return self._cmp_impl(other, operator.lt)
36
+
37
+ def __gt__(self, other: object) -> Any | types.NotImplementedType:
38
+ return self._cmp_impl(other, operator.gt)
39
+
40
+ def __le__(self, other: object) -> Any | types.NotImplementedType:
41
+ return self._cmp_impl(other, operator.le)
42
+
43
+ def __ge__(self, other: object) -> Any | types.NotImplementedType:
44
+ return self._cmp_impl(other, operator.ge)
45
+
46
+ @override
47
+ @classmethod
48
+ def __init_subclass__(cls) -> Never:
49
+ raise TypeError(
50
+ f'type {Reverse.__qualname__!r} is not an acceptable base type',
51
+ )
52
+
53
+ def call(args: dict[str, object]) -> type[Reverse[Any]]:
54
+ """
55
+ Call the plugin.
56
+
57
+ :param args:
58
+ A dictionary of the plugin's arguments;
59
+ unused.
60
+ :return: :class:`Reverse`.
61
+ """
62
+
63
+ # Unused.
64
+ del args
65
+
66
+ return Reverse
@@ -0,0 +1,48 @@
1
+ # SPDX-License-Identifier: BSD-3-Clause
2
+
3
+ """
4
+ Disable ordering comparisons
5
+ (``<``, ``<=``, ``>``, and ``>=``)
6
+ upon an object.
7
+ """
8
+
9
+ import dataclasses
10
+ from typing import Any, final, Never, override
11
+
12
+ __all__ = [
13
+ 'call',
14
+ 'Unordered',
15
+ ]
16
+
17
+ @final
18
+ @dataclasses.dataclass(frozen=True)
19
+ class Unordered[T]:
20
+ """
21
+ A comparison key that disables comparisons
22
+ with ``<``, ``<=``, ``>``, or ``>=``
23
+ while preserving those with ``==`` or ``!=``.
24
+ """
25
+
26
+ value: T
27
+
28
+ @override
29
+ @classmethod
30
+ def __init_subclass__(cls) -> Never:
31
+ raise TypeError(
32
+ f'type {Unordered.__qualname__!r} is not an acceptable base type',
33
+ )
34
+
35
+ def call(args: dict[str, object]) -> type[Unordered[Any]]:
36
+ """
37
+ Call the plugin.
38
+
39
+ :param args:
40
+ A dictionary of the plugin's arguments;
41
+ unused.
42
+ :return: :class:`Unordered`.
43
+ """
44
+
45
+ # Unused.
46
+ del args
47
+
48
+ return Unordered
@@ -0,0 +1,8 @@
1
+ # SPDX-License-Identifier: BSD-3-Clause
2
+
3
+ """
4
+ Utilities for manipulating functions.
5
+ """
6
+
7
+ __all__: list[str] = [
8
+ ]
@@ -0,0 +1,43 @@
1
+ # SPDX-License-Identifier: BSD-3-Clause
2
+
3
+ """
4
+ The function call operator.
5
+
6
+ The operator is in fact the identity function over the functions;
7
+ letting ``op`` denote the operator,
8
+ we have ``op f x = (op f) x = f x``.
9
+ """
10
+
11
+ from collections.abc import Callable
12
+ from typing import Any, Protocol
13
+
14
+ __all__ = [
15
+ 'Call',
16
+ 'call',
17
+ ]
18
+
19
+ class Call(Protocol):
20
+ """
21
+ A protocol for the function call operator.
22
+ """
23
+
24
+ def __call__[F: Callable[[Any], Any]](self, obj: F, /) -> F:
25
+ ...
26
+
27
+ def _identity[F: Callable[[Any], Any]](func: F, /) -> F:
28
+ return func
29
+
30
+ def call(args: dict[str, object]) -> Call:
31
+ """
32
+ Call the plugin.
33
+
34
+ :param args:
35
+ A dictionary of the plugin's arguments;
36
+ unused.
37
+ :return: The function call operator.
38
+ """
39
+
40
+ # Unused.
41
+ del args
42
+
43
+ return _identity
@@ -0,0 +1,65 @@
1
+ # SPDX-License-Identifier: BSD-3-Clause
2
+
3
+ """
4
+ The reverse or rightist function call operator.
5
+
6
+ The operator is in fact the normal function call operator
7
+ with the first two arguments switched;
8
+ letting ``op`` denote the operator,
9
+ we have ``op x f = f x``.
10
+ Since,
11
+ in an expression like ``operator a b``,
12
+ the normal function call operator calls
13
+ the *left* operand ``a`` upon the right operand ``b``
14
+ while the reverse function call operator calls
15
+ the *right* operand ``b`` upon the left operand ``a``,
16
+ we refer to the latter operator as also
17
+ the *right*\\ ist function call operator.
18
+ """
19
+
20
+ from collections.abc import Callable
21
+ from typing import Protocol
22
+
23
+ __all__ = [
24
+ 'call',
25
+ 'CallRight',
26
+ 'CallRightOne'
27
+ ]
28
+
29
+ class CallRightOne[T](Protocol):
30
+ """
31
+ A protocol for the reverse function call operator
32
+ with the first argument bound to an object of type ``T``.
33
+ """
34
+
35
+ def __call__[U](self, func: Callable[[T], U], /) -> U:
36
+ ...
37
+
38
+ class CallRight(Protocol):
39
+ """
40
+ A protocol for the reverse function call operator.
41
+ """
42
+
43
+ def __call__[T](self, obj: T, /) -> CallRightOne[T]:
44
+ ...
45
+
46
+ def _call_right[T](obj: T, /) -> CallRightOne[T]:
47
+ def call_right_one[U](func: Callable[[T], U], /) -> U:
48
+ return func(obj)
49
+
50
+ return call_right_one
51
+
52
+ def call(args: dict[str, object]) -> CallRight:
53
+ """
54
+ Call the plugin.
55
+
56
+ :param args:
57
+ A dictionary of the plugin's arguments;
58
+ unused.
59
+ :return: A curried reverse unary-function-call operator.
60
+ """
61
+
62
+ # Unused.
63
+ del args
64
+
65
+ return _call_right
@@ -0,0 +1,66 @@
1
+ # SPDX-License-Identifier: BSD-3-Clause
2
+
3
+ """
4
+ The leftist function composition operator.
5
+
6
+ The order of the composed functions is opposite
7
+ that of the usual function composition operator in mathematics;
8
+ letting ``op`` denote the operator,
9
+ we have ``op f g x = (op f g) x = g (f x)``.
10
+ Since the function ``g`` with which ``f`` is composed
11
+ thus ends up on the *left* of ``f``
12
+ in the preceding evaluation of ``op f g x``,
13
+ we call the operator the *left*\\ ist function composition operator.
14
+ """
15
+
16
+ from collections.abc import Callable
17
+ from typing import Protocol
18
+
19
+ __all__ = [
20
+ 'call',
21
+ 'ComposeLeft',
22
+ 'ComposeLeftOne',
23
+ ]
24
+
25
+ class ComposeLeftOne[T, U](Protocol):
26
+ """
27
+ A protocol for the leftist function composition operator
28
+ with the first argument bound to a function of type ``T -> U``.
29
+ """
30
+
31
+ def __call__[V](self, func: Callable[[U], V], /) -> Callable[[T], V]:
32
+ ...
33
+
34
+ class ComposeLeft(Protocol):
35
+ """
36
+ A protocol for the leftist function composition operator.
37
+ """
38
+
39
+ def __call__[T, U](
40
+ self, func: Callable[[T], U], /,
41
+ ) -> ComposeLeftOne[T, U]:
42
+ ...
43
+
44
+ def _compose_left[T, U](func1: Callable[[T], U], /) -> ComposeLeftOne[T, U]:
45
+ def compose_left_one[V](func2: Callable[[U], V], /) -> Callable[[T], V]:
46
+ def compose_left_two(obj: T, /) -> V:
47
+ return func2(func1(obj))
48
+
49
+ return compose_left_two
50
+
51
+ return compose_left_one
52
+
53
+ def call(args: dict[str, object]) -> ComposeLeft:
54
+ """
55
+ Call the plugin.
56
+
57
+ :param args:
58
+ A dictionary of the plugin's arguments;
59
+ unused.
60
+ :return: The leftist function composition operator.
61
+ """
62
+
63
+ # Unused.
64
+ del args
65
+
66
+ return _compose_left
@@ -0,0 +1,66 @@
1
+ # SPDX-License-Identifier: BSD-3-Clause
2
+
3
+ """
4
+ The rightist function composition operator.
5
+
6
+ The operator corresponds to the usual function composition operator
7
+ in mathematics;
8
+ letting ``op`` denote the operator,
9
+ we have ``op f g x = (op f g) x = f (g x)``.
10
+ Since the function ``g`` with which ``f`` is composed
11
+ thus ends up on the *right* of ``f``
12
+ in the preceding evaluation of ``op f g x``,
13
+ we call the operator the *right*\\ ist function composition operator.
14
+ """
15
+
16
+ from collections.abc import Callable
17
+ from typing import Protocol
18
+
19
+ __all__ = [
20
+ 'call',
21
+ 'ComposeRight',
22
+ 'ComposeRightOne',
23
+ ]
24
+
25
+ class ComposeRightOne[T, U](Protocol):
26
+ """
27
+ A protocol for the rightist function composition operator
28
+ with the first argument bound to a function of type ``T -> U``.
29
+ """
30
+
31
+ def __call__[V](self, func: Callable[[V], T], /) -> Callable[[V], U]:
32
+ ...
33
+
34
+ class ComposeRight(Protocol):
35
+ """
36
+ A protocol for the rightist function composition operator.
37
+ """
38
+
39
+ def __call__[T, U](
40
+ self, func: Callable[[T], U], /,
41
+ ) -> ComposeRightOne[T, U]:
42
+ ...
43
+
44
+ def _compose_right[T, U](func1: Callable[[T], U], /) -> ComposeRightOne[T, U]:
45
+ def compose_right_one[V](func2: Callable[[V], T], /) -> Callable[[V], U]:
46
+ def compose_right_two(obj: V, /) -> U:
47
+ return func1(func2(obj))
48
+
49
+ return compose_right_two
50
+
51
+ return compose_right_one
52
+
53
+ def call(args: dict[str, object]) -> ComposeRight:
54
+ """
55
+ Call the plugin.
56
+
57
+ :param args:
58
+ A dictionary of the plugin's arguments;
59
+ unused.
60
+ :return: The rightist function composition operator.
61
+ """
62
+
63
+ # Unused.
64
+ del args
65
+
66
+ return _compose_right
@@ -0,0 +1,38 @@
1
+ # SPDX-License-Identifier: BSD-3-Clause
2
+
3
+ """
4
+ The identity function.
5
+ """
6
+
7
+ from typing import Protocol
8
+
9
+ __all__ = [
10
+ 'call',
11
+ 'Identity',
12
+ ]
13
+
14
+ class Identity(Protocol):
15
+ """
16
+ A protocol for the identity function.
17
+ """
18
+
19
+ def __call__[T](self, obj: T, /) -> T:
20
+ ...
21
+
22
+ def _identity[T](obj: T, /) -> T:
23
+ return obj
24
+
25
+ def call(args: dict[str, object]) -> Identity:
26
+ """
27
+ Call the plugin.
28
+
29
+ :param args:
30
+ A dictionary of the plugin's arguments;
31
+ unused.
32
+ :return: The identity function.
33
+ """
34
+
35
+ # Unused.
36
+ del args
37
+
38
+ return _identity
@@ -0,0 +1,49 @@
1
+ # SPDX-License-Identifier: BSD-3-Clause
2
+
3
+ """
4
+ Construct an iterator over a fixed sequence.
5
+
6
+ In particular,
7
+ the plugin constructs an iterator
8
+ over the sequence ``(a[0], a[1], ..., a[n])``,
9
+ where each ``a[i]`` is the result of a plugin call
10
+ and is computed only once the iterator is made to yield it.
11
+ """
12
+
13
+ from collections.abc import Iterator
14
+ from typing import Any
15
+
16
+ import pydantic
17
+
18
+ from veridret_plugins.core import _plugin
19
+
20
+ __all__ = [
21
+ 'call',
22
+ ]
23
+
24
+ class _Args(pydantic.BaseModel):
25
+ operands: tuple[_plugin.AnnotatedCall, ...] = pydantic.Field(
26
+ (),
27
+ validation_alias=pydantic.AliasChoices('operands', 'items'),
28
+ serialization_alias='operands',
29
+ )
30
+
31
+ def call(args: dict[str, object]) -> Iterator[Any]:
32
+ """
33
+ Call the plugin.
34
+
35
+ :param args: A dictionary of the plugin's arguments.
36
+ :return: An iterator of the sequence specified by ``args``.
37
+ :raise Exception:
38
+ If ``args`` is invalid.
39
+
40
+ Since the plugin calls that evaluate to the items yielded by the iterator
41
+ are each only evaluated once the iterator is made to yield them,
42
+ if evaluating any of those plugin calls fails,
43
+ then attempting to yield the item
44
+ to which the plugin call would have evaluated
45
+ raises an exception.
46
+ """
47
+
48
+ validated_args = _Args.model_validate(args, strict=True, by_name=False)
49
+ return map(_plugin.evaluate_call, validated_args.operands)
@@ -0,0 +1,8 @@
1
+ # SPDX-License-Identifier: BSD-3-Clause
2
+
3
+ """
4
+ Utilities for manipulating iterators and other iterables.
5
+ """
6
+
7
+ __all__: list[str] = [
8
+ ]
@@ -0,0 +1,50 @@
1
+ # SPDX-License-Identifier: BSD-3-Clause
2
+
3
+ """
4
+ The ``filter`` higher-order function over the iterables.
5
+
6
+ Letting ``filter_`` denote the function,
7
+ ``filter_ p it`` is equivalent to the Python ``filter(p, it)``,
8
+ including the special case where ``p`` is ``None``.
9
+ """
10
+
11
+ from collections.abc import Callable, Iterable, Iterator
12
+ from typing import Protocol
13
+
14
+ __all__ = [
15
+ 'call',
16
+ 'Filter',
17
+ ]
18
+
19
+ class Filter(Protocol):
20
+ """
21
+ A protocol for the ``filter`` higher-order function over the iterables.
22
+ """
23
+
24
+ def __call__[T](
25
+ self, pred: Callable[[T], object] | None, /,
26
+ ) -> Callable[[Iterable[T]], Iterator[T]]:
27
+ ...
28
+
29
+ def _filter[T](
30
+ pred: Callable[[T], object] | None, /,
31
+ ) -> Callable[[Iterable[T]], Iterator[T]]:
32
+ def filter_one(iterable: Iterable[T], /) -> Iterator[T]:
33
+ return filter(pred, iterable)
34
+
35
+ return filter_one
36
+
37
+ def call(args: dict[str, object]) -> Filter:
38
+ """
39
+ Call the plugin.
40
+
41
+ :param args:
42
+ A dictionary of the plugin's arguments;
43
+ unused.
44
+ :return: The ``filter`` higher-order function over the iterables.
45
+ """
46
+
47
+ # Unused.
48
+ del args
49
+
50
+ return _filter
@@ -0,0 +1,60 @@
1
+ # SPDX-License-Identifier: BSD-3-Clause
2
+
3
+ """
4
+ The left-associative variant of the ``fold`` higher-order over the iterables.
5
+
6
+ Letting ``fold_left`` denote the function,
7
+ ``fold_left f z it`` is equivalent to the Python
8
+ ``functools.reduce(lambda x, y: f(x)(y), it, initial=z)``.
9
+ """
10
+
11
+ from collections.abc import Callable, Iterable
12
+ import functools
13
+ from typing import Protocol
14
+
15
+ __all__ = [
16
+ 'call',
17
+ 'FoldLeft',
18
+ ]
19
+
20
+ class FoldLeft(Protocol):
21
+ """
22
+ A protocol for the left-associative variant of the ``fold`` higher-order
23
+ over the iterables.
24
+ """
25
+
26
+ def __call__[T, U](
27
+ self, func: Callable[[T], Callable[[U], T]], /,
28
+ ) -> Callable[[T], Callable[[Iterable[U]], T]]:
29
+ ...
30
+
31
+ def _fold_left[T, U](
32
+ func: Callable[[T], Callable[[U], T]], /,
33
+ ) -> Callable[[T], Callable[[Iterable[U]], T]]:
34
+ def uncurried_func(x: T, y: U) -> T:
35
+ return func(x)(y)
36
+
37
+ def fold_left_one(seed: T, /) -> Callable[[Iterable[U]], T]:
38
+ def fold_left_two(iterable: Iterable[U], /) -> T:
39
+ return functools.reduce(uncurried_func, iterable, initial=seed)
40
+
41
+ return fold_left_two
42
+
43
+ return fold_left_one
44
+
45
+ def call(args: dict[str, object]) -> FoldLeft:
46
+ """
47
+ Call the plugin.
48
+
49
+ :param args:
50
+ A dictionary of the plugin's arguments;
51
+ unused.
52
+ :return:
53
+ The left-associative variant of the ``fold`` higher-order
54
+ over the iterables.
55
+ """
56
+
57
+ # Unused.
58
+ del args
59
+
60
+ return _fold_left
@@ -0,0 +1,49 @@
1
+ # SPDX-License-Identifier: BSD-3-Clause
2
+
3
+ """
4
+ The ``map`` higher-order function over the iterables.
5
+
6
+ Letting ``map_`` denote the function,
7
+ ``map_ f it`` is equivalent to the Python ``map(f, it)``.
8
+ """
9
+
10
+ from collections.abc import Callable, Iterable, Iterator
11
+ from typing import Protocol
12
+
13
+ __all__ = [
14
+ 'call',
15
+ 'Map',
16
+ ]
17
+
18
+ class Map(Protocol):
19
+ """
20
+ A protocol for the ``map`` higher-order function over the iterables.
21
+ """
22
+
23
+ def __call__[T, U](
24
+ self, func: Callable[[T], U], /
25
+ ) -> Callable[[Iterable[T]], Iterator[U]]:
26
+ ...
27
+
28
+ def _map[T, U](
29
+ func: Callable[[T], U], /,
30
+ ) -> Callable[[Iterable[T]], Iterator[U]]:
31
+ def map_one(iterable: Iterable[T], /) -> Iterator[U]:
32
+ return map(func, iterable)
33
+
34
+ return map_one
35
+
36
+ def call(args: dict[str, object]) -> Map:
37
+ """
38
+ Call the plugin.
39
+
40
+ :param args:
41
+ A dictionary of the plugin's arguments;
42
+ unused.
43
+ :return: A ``map`` higher-order function over the iterables.
44
+ """
45
+
46
+ # Unused.
47
+ del args
48
+
49
+ return _map