# python-manifest




Manifest is a flexible and dynamic Python library designed for managing application manifests including configurations in Python projects. By using the `pydantic` library for data validation, it allows you to define your own models, support dynamic configurations via expressions, and even instantiate Python objects directly from the configuration.
---
For more information, check out the [Documentation](https://docs.emergentmethods.ai/manifest/).
---
## Features
- Load manifests and configurations from various sources including files and environment variables.
- Define manifests as Pydantic models.
- Supports dynamic configurations through the use of expressions.
- Instantiate Python objects directly from the configuration using Instantiable model.
- Supports YAML, JSON, and TOML files out of the box.
- Built on top of `asyncio`.
- Support for multiple file systems using `fsspec`.
## Getting Started
Install the library using pip:
```bash
pip install python-manifest
```
## Usage
### Manifest Object
The Manifest class allows you to load and process manifests and configurations from various sources. It is designed to be subclassed, allowing you to define your own configuration models.
```python
class MyConfiguration(Manifest):
my_value: str
```
### Building the Manifest
Manifest instances can be created just like any other Pydantic model. You can create one from keyword arguments, from a dictionary, etc.
```python
config = MyConfiguration(my_value="Hello, World!")
config = MyConfiguration.parse_obj({"my_value": "Hello, World!"})
```
It supports a variety of ways to build the Manifest using methods like `from_files`, `from_env`, `from_key_values`, and more. They make it easy
to load and validate configurations from various sources, but often times you'll want to use a combination of them. This can be accomplished using the `build` method:
```python
config = await MyConfiguration.build(
files=["path/to/config.yaml"],
dotenv_files=["path/to/.env"],
key_values=["key=value"],
env_prefix="MY_CONFIGURATION",
pre_process_hooks=[do_something_with_raw_text_func],
post_process_hooks=[do_something_with_deserialized_text_func],
)
```
Most cases will only require a subset of these arguments, but they are all available for you to use. The `build` method will automatically decide which serializer to use based on the file extension. You will most often just use `build` when working with Manifests, but you can use the other methods if you need more control.
Files can be loaded from various sources including local files, remote files, and even compressed files. The `fsspec` library is used to support multiple file systems.
```python
config = await MyConfiguration.from_files(
files=["s3://path/to/config.yaml"],
)
```
### Saving the Manifest
While a Manifest can be built from many different files, you can only persist a Manifest to a single file. To save it use the `to_file` method. It will automatically decide the serializer based on the file extension.
```python
await config.to_file("s3://path/to/config.yaml")
```
### Expressions
Manifest supports dynamic configurations through the use of expressions, providing a way to inject dynamic values into your configuration.
```yaml
my_value: $reverse{sometext}
```
### Instantiable Class
Instantiable is a generic model that can be used to instantiate objects from a model. It allows for direct instantiation of Python objects from the configuration, working in tandem with the Manifest.
```python
class MyObj:
def __init__(self, n: int):
self.n = n
class MyConfiguration(Manifest):
my_obj: Instantiable[MyObj]
config = MyConfiguration(my_obj={"target": "my_module.MyObj", "n": 7})
obj = config.my_obj.instantiate()
print(obj.n) # Output: 7
```
Instantiable objects can be instantiated from a dictionary or a Manifest. The `target` key is required and must be a string representing the path to the class. Any additional fields are treated as keyword arguments to the class constructor.
## Contributing
Merge requests are always welcome! Feel free to open a new issue if you have any questions or suggestions.
Raw data
{
"_id": null,
"home_page": "https://github.com/emergentmethods/python-manifest",
"name": "python-manifest",
"maintainer": null,
"docs_url": null,
"requires_python": "<4.0,>=3.10",
"maintainer_email": null,
"keywords": null,
"author": "Timothy Pogue",
"author_email": "tim@emergentmethods.ai",
"download_url": null,
"platform": null,
"description": "# python-manifest\n\n\n\n\n\n\nManifest is a flexible and dynamic Python library designed for managing application manifests including configurations in Python projects. By using the `pydantic` library for data validation, it allows you to define your own models, support dynamic configurations via expressions, and even instantiate Python objects directly from the configuration.\n\n---\n\nFor more information, check out the [Documentation](https://docs.emergentmethods.ai/manifest/).\n\n---\n\n## Features\n\n- Load manifests and configurations from various sources including files and environment variables.\n- Define manifests as Pydantic models.\n- Supports dynamic configurations through the use of expressions.\n- Instantiate Python objects directly from the configuration using Instantiable model.\n- Supports YAML, JSON, and TOML files out of the box.\n- Built on top of `asyncio`.\n- Support for multiple file systems using `fsspec`.\n\n## Getting Started\n\nInstall the library using pip:\n\n```bash\npip install python-manifest\n```\n\n## Usage\n\n### Manifest Object\n\nThe Manifest class allows you to load and process manifests and configurations from various sources. It is designed to be subclassed, allowing you to define your own configuration models.\n\n```python\nclass MyConfiguration(Manifest):\n my_value: str\n```\n\n### Building the Manifest\n\nManifest instances can be created just like any other Pydantic model. You can create one from keyword arguments, from a dictionary, etc.\n\n```python\nconfig = MyConfiguration(my_value=\"Hello, World!\")\nconfig = MyConfiguration.parse_obj({\"my_value\": \"Hello, World!\"})\n```\n\nIt supports a variety of ways to build the Manifest using methods like `from_files`, `from_env`, `from_key_values`, and more. They make it easy\nto load and validate configurations from various sources, but often times you'll want to use a combination of them. This can be accomplished using the `build` method:\n\n```python\nconfig = await MyConfiguration.build(\n files=[\"path/to/config.yaml\"],\n dotenv_files=[\"path/to/.env\"],\n key_values=[\"key=value\"],\n env_prefix=\"MY_CONFIGURATION\",\n pre_process_hooks=[do_something_with_raw_text_func],\n post_process_hooks=[do_something_with_deserialized_text_func],\n)\n```\n\nMost cases will only require a subset of these arguments, but they are all available for you to use. The `build` method will automatically decide which serializer to use based on the file extension. You will most often just use `build` when working with Manifests, but you can use the other methods if you need more control.\n\nFiles can be loaded from various sources including local files, remote files, and even compressed files. The `fsspec` library is used to support multiple file systems.\n\n```python\nconfig = await MyConfiguration.from_files(\n files=[\"s3://path/to/config.yaml\"],\n)\n```\n\n### Saving the Manifest\n\nWhile a Manifest can be built from many different files, you can only persist a Manifest to a single file. To save it use the `to_file` method. It will automatically decide the serializer based on the file extension.\n\n```python\nawait config.to_file(\"s3://path/to/config.yaml\")\n```\n\n### Expressions\n\nManifest supports dynamic configurations through the use of expressions, providing a way to inject dynamic values into your configuration.\n\n```yaml\nmy_value: $reverse{sometext}\n```\n\n### Instantiable Class\n\nInstantiable is a generic model that can be used to instantiate objects from a model. It allows for direct instantiation of Python objects from the configuration, working in tandem with the Manifest.\n\n```python\nclass MyObj:\n def __init__(self, n: int):\n self.n = n\n\nclass MyConfiguration(Manifest):\n my_obj: Instantiable[MyObj]\n\nconfig = MyConfiguration(my_obj={\"target\": \"my_module.MyObj\", \"n\": 7})\nobj = config.my_obj.instantiate()\n\nprint(obj.n) # Output: 7\n```\n\nInstantiable objects can be instantiated from a dictionary or a Manifest. The `target` key is required and must be a string representing the path to the class. Any additional fields are treated as keyword arguments to the class constructor.\n\n\n## Contributing\nMerge requests are always welcome! Feel free to open a new issue if you have any questions or suggestions.",
"bugtrack_url": null,
"license": "MIT",
"summary": "A modern toolkit for working with application manifests and configurations.",
"version": "2.3.0",
"project_urls": {
"Homepage": "https://github.com/emergentmethods/python-manifest",
"Repository": "https://github.com/emergentmethods/python-manifest"
},
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "09045ddc23dc52e6500b34cd22d8a6ff42367d8b4ee6de27cda14b3a228e62b6",
"md5": "c2bae1ba865b7cb70aa386cbcc94d3bd",
"sha256": "6f39eee4c68fe624839b2079cb9b199dc7d55b3a97b5d6c3a9299e1b2be36779"
},
"downloads": -1,
"filename": "python_manifest-2.3.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "c2bae1ba865b7cb70aa386cbcc94d3bd",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": "<4.0,>=3.10",
"size": 22345,
"upload_time": "2024-08-24T06:43:29",
"upload_time_iso_8601": "2024-08-24T06:43:29.383300Z",
"url": "https://files.pythonhosted.org/packages/09/04/5ddc23dc52e6500b34cd22d8a6ff42367d8b4ee6de27cda14b3a228e62b6/python_manifest-2.3.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-08-24 06:43:29",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "emergentmethods",
"github_project": "python-manifest",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "python-manifest"
}