psyplus


Namepsyplus JSON
Version 0.9.5 PyPI version JSON
download
home_pageNone
SummaryA helper module that builds upon pydantic-settings to generate, read and comment a config file in yaml
upload_time2024-08-21 12:49:24
maintainerNone
docs_urlNone
authorNone
requires_python>=3.10
licenseMIT
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"
}
        
Elapsed time: 1.79200s