Name | python-adjudicator JSON |
Version |
0.5.0
JSON |
| download |
home_page | |
Summary | |
upload_time | 2024-01-07 21:13:07 |
maintainer | |
docs_url | None |
author | Niklas Rosenstein |
requires_python | >=3.10,<4.0 |
license | MIT |
keywords |
|
VCS |
|
bugtrack_url |
|
requirements |
No requirements were recorded.
|
Travis-CI |
No Travis.
|
coveralls test coverage |
No coveralls.
|
# adjudicator
> __Adjudicator__ _(nount_): An adjudicator is a person or body that makes formal judgments on a disputed matter. They
> are the ones who settle disputes or decide who is right in a disagreement. This could be a judge in a courtroom, an
> arbitrator in a negotiation, or any person or system given the power to make decisions of this type.
Adjudicator is a framework for implementing type-based rule engines largely inspired by the Pants build system. The
rule graph consists of nodes which are concrete Python types and edges which are functions that take a set of input
types and produce an output type.
Rules are matched on a set of facts, which populate the possible input types of a rule. Deriving a type may require
chained execution of rules, which is supported. Global facts may be used to populate a potential input type for all
rule executions.
The Adjudicator rule engine is designed to be used in a request-response fashion. A request is a set of facts that
should be used to derive a type. A response is the derived type. The rule engine will execute the rules necessary to
derive the type and return the response. If a rule was already executed with the same inputs, it will not be executed
again. For optimal use of the caching mechanism, all types participating in the rule evaluation should be immutable
and implement a stable hash (e.g. using `@dataclass(frozen=True)` and `tuple` instead of `list`, etc.).
When a mutable type should intentionally participate in the rule evaluation, usually this works automatically because
the hash of a Python object that does not provide a custom `__hash__()` implementation or disables its hashing is based
on the object's identity. This means that the hash is stable for the memory allocation of the object, and will not
change if the object is mutated. For types that do not _support_ hashing, support can be enabled explicitly using the
`RuleEngine.hashsupport` object.
__Table of Contents__
<!-- toc -->
* [Quickstart](#quickstart)
* [Installation](#installation)
* [Future Extensions](#future-extensions)
<!-- end toc -->
## Quickstart
The following example shows how to use Adjudicator to implement a simple "Hello World" application. The rule engine
invokes the `say_hello()` production rule because a `HelloResponse` is requested and a `HelloRequest` is provided,
which matches the rule's signature.
<!-- include code:python examples/hello.py -->
```python
from dataclasses import dataclass
from adjudicator import Params, RuleEngine, rule
@dataclass(frozen=True)
class HelloRequest:
name: str
@dataclass(frozen=True)
class HelloResponse:
greeting: str
@rule()
def say_hello(request: HelloRequest) -> HelloResponse:
return HelloResponse(greeting=f"Hello {request.name}!")
engine = RuleEngine()
engine.load_module(__name__)
response = engine.get(HelloResponse, Params(HelloRequest(name="World")))
print(response.greeting)
```
<!-- end include -->
A more complex example can be found in the [mksync](https://github.com/NiklasRosenstein/mksync) project.
## Installation
Adjudicator is available on PyPI. You need at least Python 3.10.
```bash
pip install python-adjudicator
```
## Future Extensions
* Currently the rule graph stores rules as connections between types and rules on edges. A more efficient
representation would be the one illustrated above, where types are connected to rules which are connected to types.
* The ability to mark facts as required to be consumed. If such a fact is not consumed during the execution of a
request, an error will be raised.
Raw data
{
"_id": null,
"home_page": "",
"name": "python-adjudicator",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.10,<4.0",
"maintainer_email": "",
"keywords": "",
"author": "Niklas Rosenstein",
"author_email": "rosensteinniklas@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/2f/21/bcf9371e4cc0a833c57fd80222d447e9a96734a601b62b941c2c93a8e5a1/python_adjudicator-0.5.0.tar.gz",
"platform": null,
"description": "# adjudicator\n\n> __Adjudicator__ _(nount_): An adjudicator is a person or body that makes formal judgments on a disputed matter. They\n> are the ones who settle disputes or decide who is right in a disagreement. This could be a judge in a courtroom, an\n> arbitrator in a negotiation, or any person or system given the power to make decisions of this type.\n\nAdjudicator is a framework for implementing type-based rule engines largely inspired by the Pants build system. The\nrule graph consists of nodes which are concrete Python types and edges which are functions that take a set of input\ntypes and produce an output type.\n\nRules are matched on a set of facts, which populate the possible input types of a rule. Deriving a type may require\nchained execution of rules, which is supported. Global facts may be used to populate a potential input type for all\nrule executions.\n\nThe Adjudicator rule engine is designed to be used in a request-response fashion. A request is a set of facts that\nshould be used to derive a type. A response is the derived type. The rule engine will execute the rules necessary to\nderive the type and return the response. If a rule was already executed with the same inputs, it will not be executed\nagain. For optimal use of the caching mechanism, all types participating in the rule evaluation should be immutable\nand implement a stable hash (e.g. using `@dataclass(frozen=True)` and `tuple` instead of `list`, etc.).\n\nWhen a mutable type should intentionally participate in the rule evaluation, usually this works automatically because\nthe hash of a Python object that does not provide a custom `__hash__()` implementation or disables its hashing is based\non the object's identity. This means that the hash is stable for the memory allocation of the object, and will not\nchange if the object is mutated. For types that do not _support_ hashing, support can be enabled explicitly using the\n`RuleEngine.hashsupport` object.\n\n__Table of Contents__\n\n<!-- toc -->\n* [Quickstart](#quickstart)\n* [Installation](#installation)\n* [Future Extensions](#future-extensions)\n<!-- end toc -->\n\n## Quickstart\n\nThe following example shows how to use Adjudicator to implement a simple \"Hello World\" application. The rule engine\ninvokes the `say_hello()` production rule because a `HelloResponse` is requested and a `HelloRequest` is provided,\nwhich matches the rule's signature.\n\n<!-- include code:python examples/hello.py -->\n```python\nfrom dataclasses import dataclass\nfrom adjudicator import Params, RuleEngine, rule\n\n@dataclass(frozen=True)\nclass HelloRequest:\n name: str\n\n@dataclass(frozen=True)\nclass HelloResponse:\n greeting: str\n\n@rule()\ndef say_hello(request: HelloRequest) -> HelloResponse:\n return HelloResponse(greeting=f\"Hello {request.name}!\")\n\nengine = RuleEngine()\nengine.load_module(__name__)\nresponse = engine.get(HelloResponse, Params(HelloRequest(name=\"World\")))\nprint(response.greeting)\n```\n<!-- end include -->\n\nA more complex example can be found in the [mksync](https://github.com/NiklasRosenstein/mksync) project.\n\n## Installation\n\nAdjudicator is available on PyPI. You need at least Python 3.10.\n\n```bash\npip install python-adjudicator\n```\n\n## Future Extensions\n\n* Currently the rule graph stores rules as connections between types and rules on edges. A more efficient\n representation would be the one illustrated above, where types are connected to rules which are connected to types.\n* The ability to mark facts as required to be consumed. If such a fact is not consumed during the execution of a\n request, an error will be raised.\n\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "",
"version": "0.5.0",
"project_urls": {
"Bug Tracker": "https://github.com/NiklasRosenstein/python-adjudicator/issues",
"Homepage": "https://github.com/NiklasRosenstein/python-adjudicator",
"Repository": "https://github.com/NiklasRosenstein/python-adjudicator"
},
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "b9433f08d6a2efc8e00754d419880fb802e2fcc37252e4ebe0e64a00c7fc9f6c",
"md5": "7a40e79bb306ab559be0c558b28e57e3",
"sha256": "b6abe4fc22e14159bdac7c6be8ef6fe337c132dc2ac8b49a40ddd31c43464483"
},
"downloads": -1,
"filename": "python_adjudicator-0.5.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "7a40e79bb306ab559be0c558b28e57e3",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.10,<4.0",
"size": 21509,
"upload_time": "2024-01-07T21:12:58",
"upload_time_iso_8601": "2024-01-07T21:12:58.895970Z",
"url": "https://files.pythonhosted.org/packages/b9/43/3f08d6a2efc8e00754d419880fb802e2fcc37252e4ebe0e64a00c7fc9f6c/python_adjudicator-0.5.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "2f21bcf9371e4cc0a833c57fd80222d447e9a96734a601b62b941c2c93a8e5a1",
"md5": "5777e479123039fdd0219c81ed35e96a",
"sha256": "cfd17ff4851ea93e22fcbd6a696e9e0494076ed27f8e98f2c9189e40a7301c6a"
},
"downloads": -1,
"filename": "python_adjudicator-0.5.0.tar.gz",
"has_sig": false,
"md5_digest": "5777e479123039fdd0219c81ed35e96a",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.10,<4.0",
"size": 17823,
"upload_time": "2024-01-07T21:13:07",
"upload_time_iso_8601": "2024-01-07T21:13:07.095107Z",
"url": "https://files.pythonhosted.org/packages/2f/21/bcf9371e4cc0a833c57fd80222d447e9a96734a601b62b941c2c93a8e5a1/python_adjudicator-0.5.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-01-07 21:13:07",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "NiklasRosenstein",
"github_project": "python-adjudicator",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "python-adjudicator"
}