# Zookeeper
[![GitHub Actions](https://github.com/larq/zookeeper/workflows/Unittest/badge.svg)](https://github.com/larq/zookeeper/actions?workflow=Unittest) [![Codecov](https://img.shields.io/codecov/c/github/larq/zookeeper)](https://codecov.io/github/larq/zookeeper?branch=main) [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/zookeeper.svg)](https://pypi.org/project/zookeeper/) [![PyPI](https://img.shields.io/pypi/v/zookeeper.svg)](https://pypi.org/project/zookeeper/) [![PyPI - License](https://img.shields.io/pypi/l/zookeeper.svg)](https://github.com/plumerai/zookeeper/blob/main/LICENSE) [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/ambv/black)
A small library for configuring modular applications.
### Installation
```console
pip install zookeeper
```
### Components
The fundamental building blocks of Zookeeper are components. The
[`@component`](zookeeper/component.py) decorator is used to turn classes into
components. These component classes can have configurable fields, which are
declared with the `Field` constructor and class-level type annotations. Fields
can be created with or without default values. Components can also be nested,
with `ComponentField`s, such that child componenents can access the field values
defined on their parents.
For example:
```python
from zookeeper import component
@component
class ChildComponent:
a: int = Field() # An `int` field with no default set
b: str = Field("foo") # A `str` field with default value `"foo"`
@component
class ParentComponent:
a: int = Field() # The same `int` field as the child
child: ChildComponent = ComponentField() # A nested component field, of type `ChildComponent`
```
After instantiation, components can be 'configured' with a configuration
dictionary, containing values for a tree of nested fields. This process
automatically injects the correct values into each field.
If a child sub-component declares a field which already exists in some
containing ancestor component, then it will pick up the value that's set on the
parent, unless a 'scoped' value is set on the child.
For example:
```
from zookeeper import configure
p = ParentComponent()
configure(
p,
{
"a": 5,
"child.a": 4,
}
)
>>> 'ChildComponent' is the only concrete component class that satisfies the type
>>> of the annotated parameter 'ParentComponent.child'. Using an instance of this
>>> class by default.
print(p)
>>> ParentComponent(
>>> a = 5,
>>> child = ChildComponent(
>>> a = 4,
>>> b = "foo"
>>> )
>>> )
```
### Tasks and the CLI
The [`@task`](zookeeper/task.py) decorator is used to define Zookeeper tasks and
can be applied to any class that implements an argument-less `run` method. Such
tasks can be run through the Zookeeper CLI, with parameter values passed in
through CLI arguments (`configure` is implicitly called).
For example:
```python
from zookeeper import cli, task
@task
class UseChildA:
parent: ParentComponent = ComponentField()
def run(self):
print(self.parent.child.a)
@task
class UseParentA(UseChildA):
def run(self):
print(self.parent.a)
if __name__ == "__main__":
cli()
```
Running the above file then gives a nice CLI interface:
```
python test.py use_child_a
>>> ValueError: No configuration value found for annotated parameter 'UseChildA.parent.a' of type 'int'.
python test.py use_child_a a=5
>>> 5
python test.py use_child_a a=5 child.a=3
>>> 3
python test.py use_parent_a a=5 child.a=3
>>> 5
```
### Using Zookeeper to define Larq or Keras experiments
See [examples/larq_experiment.py](examples/larq_experiment.py) for an example of
how to use Zookeeper to define all the necessary components (dataset,
preprocessing, and model) of a Larq experiment: training a BinaryNet on
MNIST. This example can be easily adapted to other Larq or Keras models and
other datasets.
Raw data
{
"_id": null,
"home_page": "https://github.com/larq/zookeeper",
"name": "zookeeper",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": "",
"keywords": "",
"author": "Plumerai",
"author_email": "opensource@plumerai.com",
"download_url": "https://files.pythonhosted.org/packages/cd/74/26a11ba0ef29a1c3e943ac393417f55ed88d00714f64f1274ecfee4906aa/zookeeper-1.3.4.tar.gz",
"platform": null,
"description": "# Zookeeper\n\n[![GitHub Actions](https://github.com/larq/zookeeper/workflows/Unittest/badge.svg)](https://github.com/larq/zookeeper/actions?workflow=Unittest) [![Codecov](https://img.shields.io/codecov/c/github/larq/zookeeper)](https://codecov.io/github/larq/zookeeper?branch=main) [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/zookeeper.svg)](https://pypi.org/project/zookeeper/) [![PyPI](https://img.shields.io/pypi/v/zookeeper.svg)](https://pypi.org/project/zookeeper/) [![PyPI - License](https://img.shields.io/pypi/l/zookeeper.svg)](https://github.com/plumerai/zookeeper/blob/main/LICENSE) [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/ambv/black)\n\nA small library for configuring modular applications.\n\n### Installation\n\n```console\npip install zookeeper\n```\n\n### Components\n\nThe fundamental building blocks of Zookeeper are components. The\n[`@component`](zookeeper/component.py) decorator is used to turn classes into\ncomponents. These component classes can have configurable fields, which are\ndeclared with the `Field` constructor and class-level type annotations. Fields\ncan be created with or without default values. Components can also be nested,\nwith `ComponentField`s, such that child componenents can access the field values\ndefined on their parents.\n\nFor example:\n\n```python\nfrom zookeeper import component\n\n@component\nclass ChildComponent:\n a: int = Field() # An `int` field with no default set\n b: str = Field(\"foo\") # A `str` field with default value `\"foo\"`\n\n@component\nclass ParentComponent:\n a: int = Field() # The same `int` field as the child\n child: ChildComponent = ComponentField() # A nested component field, of type `ChildComponent`\n```\n\nAfter instantiation, components can be 'configured' with a configuration\ndictionary, containing values for a tree of nested fields. This process\nautomatically injects the correct values into each field.\n\nIf a child sub-component declares a field which already exists in some\ncontaining ancestor component, then it will pick up the value that's set on the\nparent, unless a 'scoped' value is set on the child.\n\nFor example:\n\n```\nfrom zookeeper import configure\n\np = ParentComponent()\n\nconfigure(\n p,\n {\n \"a\": 5,\n \"child.a\": 4,\n }\n)\n\n>>> 'ChildComponent' is the only concrete component class that satisfies the type\n>>> of the annotated parameter 'ParentComponent.child'. Using an instance of this\n>>> class by default.\n\nprint(p)\n\n>>> ParentComponent(\n>>> a = 5,\n>>> child = ChildComponent(\n>>> a = 4,\n>>> b = \"foo\"\n>>> )\n>>> )\n```\n\n### Tasks and the CLI\n\nThe [`@task`](zookeeper/task.py) decorator is used to define Zookeeper tasks and\ncan be applied to any class that implements an argument-less `run` method. Such\ntasks can be run through the Zookeeper CLI, with parameter values passed in\nthrough CLI arguments (`configure` is implicitly called).\n\nFor example:\n\n```python\nfrom zookeeper import cli, task\n\n@task\nclass UseChildA:\n parent: ParentComponent = ComponentField()\n def run(self):\n print(self.parent.child.a)\n\n@task\nclass UseParentA(UseChildA):\n def run(self):\n print(self.parent.a)\n\nif __name__ == \"__main__\":\n cli()\n```\n\nRunning the above file then gives a nice CLI interface:\n\n```\npython test.py use_child_a\n>>> ValueError: No configuration value found for annotated parameter 'UseChildA.parent.a' of type 'int'.\n\npython test.py use_child_a a=5\n>>> 5\n\npython test.py use_child_a a=5 child.a=3\n>>> 3\n\npython test.py use_parent_a a=5 child.a=3\n>>> 5\n```\n\n### Using Zookeeper to define Larq or Keras experiments\n\nSee [examples/larq_experiment.py](examples/larq_experiment.py) for an example of\nhow to use Zookeeper to define all the necessary components (dataset,\npreprocessing, and model) of a Larq experiment: training a BinaryNet on\nMNIST. This example can be easily adapted to other Larq or Keras models and\nother datasets.\n",
"bugtrack_url": null,
"license": "Apache 2.0",
"summary": "A small library for managing deep learning models, hyper-parameters and datasets",
"version": "1.3.4",
"project_urls": {
"Homepage": "https://github.com/larq/zookeeper"
},
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "c77e76ced4b92d1e18468af916058de479c156dc4264eb4723dda760b5529733",
"md5": "bcecaae5e5afa334f6edb739e613cbb6",
"sha256": "8b9cfd03f525875f3bd8988f5080721e6bac83e2f3df71bc1c30f3e0b9f99a0d"
},
"downloads": -1,
"filename": "zookeeper-1.3.4-py3-none-any.whl",
"has_sig": false,
"md5_digest": "bcecaae5e5afa334f6edb739e613cbb6",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 43189,
"upload_time": "2023-07-11T14:27:32",
"upload_time_iso_8601": "2023-07-11T14:27:32.745707Z",
"url": "https://files.pythonhosted.org/packages/c7/7e/76ced4b92d1e18468af916058de479c156dc4264eb4723dda760b5529733/zookeeper-1.3.4-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "cd7426a11ba0ef29a1c3e943ac393417f55ed88d00714f64f1274ecfee4906aa",
"md5": "00864e1c4b659e1b311e19158aaeff86",
"sha256": "5fee9df9dc7c525df94f253ee1e06507329d34b288ddac0461538f900b27335d"
},
"downloads": -1,
"filename": "zookeeper-1.3.4.tar.gz",
"has_sig": false,
"md5_digest": "00864e1c4b659e1b311e19158aaeff86",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 37509,
"upload_time": "2023-07-11T14:27:34",
"upload_time_iso_8601": "2023-07-11T14:27:34.376233Z",
"url": "https://files.pythonhosted.org/packages/cd/74/26a11ba0ef29a1c3e943ac393417f55ed88d00714f64f1274ecfee4906aa/zookeeper-1.3.4.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-07-11 14:27:34",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "larq",
"github_project": "zookeeper",
"travis_ci": false,
"coveralls": true,
"github_actions": true,
"lcname": "zookeeper"
}