Name | psyplus JSON |
Version |
0.9.5
JSON |
| download |
home_page | None |
Summary | A helper module that builds upon pydantic-settings to generate, read and comment a config file in yaml |
upload_time | 2024-08-21 12:49:24 |
maintainer | None |
docs_url | None |
author | None |
requires_python | >=3.10 |
license | MIT |
keywords |
dzd
pydantic
pydantic-settings
|
VCS |
|
bugtrack_url |
|
requirements |
No requirements were recorded.
|
Travis-CI |
No Travis.
|
coveralls test coverage |
No coveralls.
|
# pydantic-settings-yaml-plus
A helper module that builds upon [pydantic-settings](https://docs.pydantic.dev/latest/concepts/pydantic_settings/) to generate, read and comment a config file in yaml ~~and improve ENV var capabilities~~
> [!WARNING]
> work in progress. please ignore this repo for now
- [pydantic-settings-yaml-plus](#pydantic-settings-yaml-plus)
- [Target use cases](#target-use-cases)
- [Features](#features)
- [Known Issues](#known-issues)
- [Goals](#goals)
- [ToDo / ToInvestigate](#todo--toinvestigate)
- [Ideas/Roadmap](#ideasroadmap)
- [How to use](#how-to-use)
## Target use cases
* **Config File Provisioning** The idea is to use this module during the build/release- (deploy on pypi.org) or init(First start)-process of your python module to generate a documented yaml file the user can understand.
* ~~**Extended Nested Env Var Parsing** Provide complex configs via env var without the need to write json~~ Needs a rewrite with pydantic-settings 2.x
## Features
* Generate a commented/documented yaml file based on your `pydantic-settings`.`BaseSettings` class
* ~~Support for nested listed and dict and var. E.g. `MYLIST__0__MYKEY=val` -> `config`.`MYLIST``[0]`.`MYKEY`=`val`~~ Needs a rewrite with pydantic-settings 2.x
## Known Issues
* Multiline values are crippled
## Goals
* Have a single source of truth for config and all its meta-data/documentation (type, descpription, examples)
* ~~All keys/values are addressable by env vars~~
### ToDo / ToInvestigate
* What about date(times) support?
* Make indexed env vars work again!
* Remove debug prints
* Write some more test
* Make pypi package
### Ideas/Roadmap
* Generate a mark down doc of all settings
* Generate template (minimal with required values only or maximum with all values listed) and example config files (all YAML only!)
* generate diff betwen current config and config model (when config model changed after update)
* update existing config files metadata
* Update info, descs
* Add missing/new required values
## How to use
Lets have the following examplary pydantic-settings config.py file:
```python
from typing import List, Dict, Optional, Literal, Annotated
from pydantic import Field
from pydantic_settings import BaseSettings
from pathlib import Path, PurePath
class DatabaseServerSettings(BaseSettings):
host: Optional[str] = Field(
default="localhost",
description="The Hostname the database will be available at",
)
port: Optional[int] = Field(
default=5678, description="The port to connect to the database"
)
database_names: List[str] = Field(
description="The names of the databases to use",
examples=[["mydb", "theotherdb"]],
)
class MyAppConfig(BaseSettings):
log_level: Optional[Literal["INFO", "DEBUG"]] = "INFO"
app_name: Optional[str] = Field(
default="THE APP",
description="The display name of the app",
examples=["THAT APP", "THIS APP"],
)
storage_dir: Optional[str] = Field(
description="A directory to store the file of the apps.",
default_factory=lambda: str(Path(PurePath(Path().home(), ".config/myapp/"))),
)
admin_pw: Annotated[str, Field(description="The init password the admin account")]
database_server: DatabaseServerSettings = Field(
description="The settings for the database server",
examples=[
DatabaseServerSettings(
host="db.company.org", port=1234, database_names=["db1", "db2"]
)
],
)
init_values: Dict[str, str]
```
With the help of psyplus we can generate a fully documented
```python
from psyplus import YamlSettingsPlus
from config import MyAppConfig
yaml_handler = YamlSettingsPlus(MyAppConfig, "test.config.yaml")
yaml_handler.generate_config_file(overwrite_existing=True)
```
which will generate a yaml file `./test.config.yaml` that looks like the following:
```yaml
# ## log_level ###
# Type: Enum
# Required: False
# Default: '"INFO"'
# Allowed vals: ['INFO', 'DEBUG']
# Env-var: 'LOG_LEVEL'
log_level: INFO
# ## app_name ###
# Type: str
# Required: False
# Default: '"THE APP"'
# Env-var: 'APP_NAME'
# Description: The display name of the app
# Example No. 1:
# >app_name: THAT APP
# >
# Example No. 2:
# >app_name: THIS APP
app_name: THE APP
# ## storage_dir ###
# Type: str
# Required: False
# Env-var: 'STORAGE_DIR'
# Description: A directory to store the file of the apps.
storage_dir: /home/tim/.config/myapp
# ## admin_pw ###
# Type: str
# Required: True
# Env-var: 'ADMIN_PW'
# Description: The init password the admin account
admin_pw: ''
# ## database_server ###
# Type: Object
# Required: True
# Env-var: 'DATABASE_SERVER'
# Description: The settings for the database server
# Example:
# >database_server:
# > database_names:
# > - db1
# > - db2
# > host: db.company.org
# > port: 1234
database_server:
# ## host ###
# YAML-path: database_server.host
# Type: str
# Required: False
# Default: '"localhost"'
# Env-var: 'DATABASE_SERVER__HOST'
# Description: The Hostname the database will be available at
host: localhost
# ## port ###
# YAML-path: database_server.port
# Type: int
# Required: False
# Default: '5678'
# Env-var: 'DATABASE_SERVER__PORT'
# Description: The port to connect to the database
port: 5678
# ## database_names ###
# YAML-path: database_server.database_names
# Type: List of str
# Required: True
# Env-var: 'DATABASE_SERVER__DATABASE_NAMES'
# Description: The names of the databases to use
# Example:
# >database_names:
# >- mydb
# >- theotherdb
database_names: []
```
To use this yaml file you just psyplus: need to parse it and validate on your pydantic-setting model.
```python
from psyplus import YamlSettingsPlus
yaml_handler = YamlSettingsPlus(MyAppConfig, "test.config.yaml")
config: MyAppConfig = yaml_handler.get_config()
print(config.database_server.host)
```
Alternativly you can parse and validate the pydantic-settings model yourself:
```python
import yaml # pip install PyYAML
with open("test.config.yaml") as file:
raw_yaml_str = file.read()
obj: Dict = yaml.safe_load(raw_yaml_str)
config: MyAppConfig = MyAppConfig.model_validate(obj)
```
Raw data
{
"_id": null,
"home_page": null,
"name": "psyplus",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.10",
"maintainer_email": null,
"keywords": "DZD, pydantic, pydantic-settings",
"author": null,
"author_email": "Tim Bleimehl <bleimehl@helmholtz-munich.de>",
"download_url": "https://files.pythonhosted.org/packages/7b/da/f71136244ddbea39a11da9eb46888a98b0d0422c5eb42264fbe600b977f8/psyplus-0.9.5.tar.gz",
"platform": null,
"description": "# pydantic-settings-yaml-plus\nA helper module that builds upon [pydantic-settings](https://docs.pydantic.dev/latest/concepts/pydantic_settings/) to generate, read and comment a config file in yaml ~~and improve ENV var capabilities~~ \n \n> [!WARNING] \n> work in progress. please ignore this repo for now\n\n\n- [pydantic-settings-yaml-plus](#pydantic-settings-yaml-plus)\n - [Target use cases](#target-use-cases)\n - [Features](#features)\n - [Known Issues](#known-issues)\n - [Goals](#goals)\n - [ToDo / ToInvestigate](#todo--toinvestigate)\n - [Ideas/Roadmap](#ideasroadmap)\n - [How to use](#how-to-use)\n\n\n## Target use cases\n\n* **Config File Provisioning** The idea is to use this module during the build/release- (deploy on pypi.org) or init(First start)-process of your python module to generate a documented yaml file the user can understand.\n* ~~**Extended Nested Env Var Parsing** Provide complex configs via env var without the need to write json~~ Needs a rewrite with pydantic-settings 2.x\n\n\n\n## Features\n\n* Generate a commented/documented yaml file based on your `pydantic-settings`.`BaseSettings` class\n* ~~Support for nested listed and dict and var. E.g. `MYLIST__0__MYKEY=val` -> `config`.`MYLIST``[0]`.`MYKEY`=`val`~~ Needs a rewrite with pydantic-settings 2.x\n\n## Known Issues\n* Multiline values are crippled\n\n## Goals\n\n* Have a single source of truth for config and all its meta-data/documentation (type, descpription, examples)\n* ~~All keys/values are addressable by env vars~~\n\n### ToDo / ToInvestigate\n* What about date(times) support?\n* Make indexed env vars work again!\n* Remove debug prints\n* Write some more test\n* Make pypi package\n\n### Ideas/Roadmap\n* Generate a mark down doc of all settings\n* Generate template (minimal with required values only or maximum with all values listed) and example config files (all YAML only!)\n* generate diff betwen current config and config model (when config model changed after update)\n* update existing config files metadata\n * Update info, descs\n * Add missing/new required values\n \n\n\n\n## How to use\n\nLets have the following examplary pydantic-settings config.py file:\n \n```python\nfrom typing import List, Dict, Optional, Literal, Annotated\n\nfrom pydantic import Field\nfrom pydantic_settings import BaseSettings\n\nfrom pathlib import Path, PurePath\n\n\nclass DatabaseServerSettings(BaseSettings):\n host: Optional[str] = Field(\n default=\"localhost\",\n description=\"The Hostname the database will be available at\",\n )\n port: Optional[int] = Field(\n default=5678, description=\"The port to connect to the database\"\n )\n database_names: List[str] = Field(\n description=\"The names of the databases to use\",\n examples=[[\"mydb\", \"theotherdb\"]],\n )\n\n\nclass MyAppConfig(BaseSettings):\n log_level: Optional[Literal[\"INFO\", \"DEBUG\"]] = \"INFO\"\n app_name: Optional[str] = Field(\n default=\"THE APP\",\n description=\"The display name of the app\",\n examples=[\"THAT APP\", \"THIS APP\"],\n )\n storage_dir: Optional[str] = Field(\n description=\"A directory to store the file of the apps.\",\n default_factory=lambda: str(Path(PurePath(Path().home(), \".config/myapp/\"))),\n )\n admin_pw: Annotated[str, Field(description=\"The init password the admin account\")]\n database_server: DatabaseServerSettings = Field(\n description=\"The settings for the database server\",\n examples=[\n DatabaseServerSettings(\n host=\"db.company.org\", port=1234, database_names=[\"db1\", \"db2\"]\n )\n ],\n )\n init_values: Dict[str, str]\n```\n \nWith the help of psyplus we can generate a fully documented \n \n\n```python\nfrom psyplus import YamlSettingsPlus\nfrom config import MyAppConfig\n\nyaml_handler = YamlSettingsPlus(MyAppConfig, \"test.config.yaml\")\nyaml_handler.generate_config_file(overwrite_existing=True)\n```\n \nwhich will generate a yaml file `./test.config.yaml` that looks like the following:\n \n```yaml\n# ## log_level ###\n# Type: Enum\n# Required: False\n# Default: '\"INFO\"'\n# Allowed vals: ['INFO', 'DEBUG']\n# Env-var: 'LOG_LEVEL'\nlog_level: INFO\n\n# ## app_name ###\n# Type: str\n# Required: False\n# Default: '\"THE APP\"'\n# Env-var: 'APP_NAME'\n# Description: The display name of the app\n# Example No. 1:\n# >app_name: THAT APP\n# >\n# Example No. 2:\n# >app_name: THIS APP\napp_name: THE APP\n\n# ## storage_dir ###\n# Type: str\n# Required: False\n# Env-var: 'STORAGE_DIR'\n# Description: A directory to store the file of the apps.\nstorage_dir: /home/tim/.config/myapp\n\n# ## admin_pw ###\n# Type: str\n# Required: True\n# Env-var: 'ADMIN_PW'\n# Description: The init password the admin account\nadmin_pw: ''\n\n# ## database_server ###\n# Type: Object\n# Required: True\n# Env-var: 'DATABASE_SERVER'\n# Description: The settings for the database server\n# Example:\n# >database_server:\n# > database_names:\n# > - db1\n# > - db2\n# > host: db.company.org\n# > port: 1234\ndatabase_server:\n\n # ## host ###\n # YAML-path: database_server.host\n # Type: str\n # Required: False\n # Default: '\"localhost\"'\n # Env-var: 'DATABASE_SERVER__HOST'\n # Description: The Hostname the database will be available at\n host: localhost\n\n # ## port ###\n # YAML-path: database_server.port\n # Type: int\n # Required: False\n # Default: '5678'\n # Env-var: 'DATABASE_SERVER__PORT'\n # Description: The port to connect to the database\n port: 5678\n\n # ## database_names ###\n # YAML-path: database_server.database_names\n # Type: List of str\n # Required: True\n # Env-var: 'DATABASE_SERVER__DATABASE_NAMES'\n # Description: The names of the databases to use\n # Example:\n # >database_names:\n # >- mydb\n # >- theotherdb\n database_names: []\n```\n \nTo use this yaml file you just psyplus: need to parse it and validate on your pydantic-setting model.\n \n```python\nfrom psyplus import YamlSettingsPlus\n\nyaml_handler = YamlSettingsPlus(MyAppConfig, \"test.config.yaml\")\nconfig: MyAppConfig = yaml_handler.get_config()\nprint(config.database_server.host)\n```\n \nAlternativly you can parse and validate the pydantic-settings model yourself:\n \n```python\nimport yaml # pip install PyYAML\n\nwith open(\"test.config.yaml\") as file:\n raw_yaml_str = file.read()\nobj: Dict = yaml.safe_load(raw_yaml_str)\nconfig: MyAppConfig = MyAppConfig.model_validate(obj)\n\n```\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "A helper module that builds upon pydantic-settings to generate, read and comment a config file in yaml",
"version": "0.9.5",
"project_urls": {
"Issues": "https://github.com/DZD-eV-Diabetes-Research/pydantic-settings-yaml-plus/issues",
"Source": "https://github.com/DZD-eV-Diabetes-Research/pydantic-settings-yaml-plus"
},
"split_keywords": [
"dzd",
" pydantic",
" pydantic-settings"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "3dc2207a25a6631c5221bf2e48ef34e4e0da47765a68e4cbeac91be019f878e6",
"md5": "7df8aa3f5e9c8e91fff715ec4d97c309",
"sha256": "4d8b8b3703535bbe62adc9cd80f70d5e44f9538715a84dab7ea41b07858d91de"
},
"downloads": -1,
"filename": "psyplus-0.9.5-py3-none-any.whl",
"has_sig": false,
"md5_digest": "7df8aa3f5e9c8e91fff715ec4d97c309",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.10",
"size": 15752,
"upload_time": "2024-08-21T12:49:23",
"upload_time_iso_8601": "2024-08-21T12:49:23.407191Z",
"url": "https://files.pythonhosted.org/packages/3d/c2/207a25a6631c5221bf2e48ef34e4e0da47765a68e4cbeac91be019f878e6/psyplus-0.9.5-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "7bdaf71136244ddbea39a11da9eb46888a98b0d0422c5eb42264fbe600b977f8",
"md5": "5dc8d5ece77486021d3b092160ce0352",
"sha256": "7522e9c2148d4bcee86df8b254562f7bc48a21f88d2eb4f3748cc543d277071b"
},
"downloads": -1,
"filename": "psyplus-0.9.5.tar.gz",
"has_sig": false,
"md5_digest": "5dc8d5ece77486021d3b092160ce0352",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.10",
"size": 16332,
"upload_time": "2024-08-21T12:49:24",
"upload_time_iso_8601": "2024-08-21T12:49:24.369261Z",
"url": "https://files.pythonhosted.org/packages/7b/da/f71136244ddbea39a11da9eb46888a98b0d0422c5eb42264fbe600b977f8/psyplus-0.9.5.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-08-21 12:49:24",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "DZD-eV-Diabetes-Research",
"github_project": "pydantic-settings-yaml-plus",
"github_not_found": true,
"lcname": "psyplus"
}