{"id":15628936,"url":"https://github.com/pwwang/python-simpleconf","last_synced_at":"2026-03-06T18:13:39.966Z","repository":{"id":57457536,"uuid":"181103246","full_name":"pwwang/python-simpleconf","owner":"pwwang","description":"Simple configuration management with python","archived":false,"fork":false,"pushed_at":"2025-08-29T23:26:41.000Z","size":242,"stargazers_count":7,"open_issues_count":0,"forks_count":2,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-12-13T03:09:54.338Z","etag":null,"topics":["configuration","configuration-management"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pwwang.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2019-04-13T00:58:45.000Z","updated_at":"2025-09-22T01:09:18.000Z","dependencies_parsed_at":"2024-06-21T16:44:42.007Z","dependency_job_id":"0d4b1e32-962a-4d10-a721-98b33deaf500","html_url":"https://github.com/pwwang/python-simpleconf","commit_stats":null,"previous_names":["pwwang/simpleconf"],"tags_count":44,"template":false,"template_full_name":null,"purl":"pkg:github/pwwang/python-simpleconf","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pwwang%2Fpython-simpleconf","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pwwang%2Fpython-simpleconf/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pwwang%2Fpython-simpleconf/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pwwang%2Fpython-simpleconf/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pwwang","download_url":"https://codeload.github.com/pwwang/python-simpleconf/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pwwang%2Fpython-simpleconf/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29811531,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-25T03:30:18.102Z","status":"ssl_error","status_checked_at":"2026-02-25T03:30:17.799Z","response_time":61,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["configuration","configuration-management"],"created_at":"2024-10-03T10:24:53.514Z","updated_at":"2026-03-06T18:13:39.953Z","avatar_url":"https://github.com/pwwang.png","language":"Python","readme":"# simpleconf\n\nSimple configuration management for python\n\n## Installation\n```shell\n# released version\npip install python-simpleconf\n\n# Install support for ini\npip install python-simpleconf[ini]\n\n# Install support for dotenv\npip install python-simpleconf[dotenv]\n\n# Install support for yaml\npip install python-simpleconf[yaml]\n\n# Install support for toml\npip install python-simpleconf[toml]\n\n# Install support for all supported formats\npip install python-simpleconf[all]\n```\n\n## Features\n- Multiple formats supported\n- Type casting\n- Profile support\n- Simple APIs\n- Async loading support\n- Templated configuration files support (jinja2 and liquid)\n\n## Usage\n\n### Loading configurations\n\n```python\nimport asyncio\nfrom simpleconf import Config\n\n\nasync def main():\n  # Load a single file\n  conf = Config.load('~/xxx.ini')\n  # load multiple files, later files override previous ones\n  conf = Config.load(\n    '~/xxx.ini', '~/xxx.env', '~/xxx.yaml', '~/xxx.toml',\n    '~/xxx.json', 'simpleconf.osenv', {'a': 3}\n  )\n\n  # Load a single file with a different loader\n  conf = Config.load('~/xxx.ini', loader=\"toml\")\n\n  # Async loading\n  conf = await Config.a_load('~/xxx.ini')\n\nif __name__ == \"__main__\":\n  asyncio.run(main())\n```\n\n### Accessing configuration values\n\n```python\nfrom simpleconf import Config\n\nconf = Config.load({'a': 1, 'b': {'c': 2}})\n# conf.a == 1\n# conf.b.c == 2\n```\n\n### Supported formats\n\n- `.ini/.cfg/.config` (parsed by `iniconfig`).\n  - For confiurations without profiles, an ini-like configuration like must have a `default` (case-insensitive) section.\n- `.env` (using `python-dotenv`). A file with environment variables.\n- `.yaml/.yml` (using `pyyaml`). A file with YAML data.\n- `.toml` (using `rtoml`). A file with TOML data.\n- `.json` (using `json`). A file with JSON data.\n- `XXX.osenv`: System environment variables with prefix `XXX_` (case-sensitive) is used.\n  - `XXX_A=1` will be loaded as `conf.A = 1`.\n- python dictionary.\n- Strings format of the above formats are also supported.\n  - `\"{'a': 1}\"` will be loaded as `conf.a = 1`.\n\n### Profile support\n\n#### Loading configurations\n\n##### Loading dictionaries\n\n```python\nfrom simpleconf import ProfileConfig\n\nconf = ProfileConfig.load({'default': {'a': 1})\n# conf.a == 1\n\n# Asynchronous loading\n# conf = await ProfileConfig.a_load({'default': {'a': 1})\n# conf.a == 1\n```\n\n##### Loading a `.env` file\n\n`config.env`\n```env\n# config.env\ndefault_a=1\n```\n\n```python\nfrom simpleconf import ProfileConfig\n\nconf = ProfileConfig.load('config.env')\n# conf.a == 1\n```\n\n##### Loading ini-like configuration files\n\n```ini\n# config.ini\n[default]\na = 1\n```\n\n```python\nfrom simpleconf import ProfileConfig\n\nconf = ProfileConfig.load('config.ini')\n# conf.a == 1\n```\n\n##### Loading JSON files\n\n`config.json`\n```json\n{\n  \"default\": {\n    \"a\": 1\n  }\n}\n```\n\n```python\nfrom simpleconf import ProfileConfig\n\nconf = ProfileConfig.load('config.json')\n# conf.a == 1\n```\n\n##### Loading system environment variables\n\n```python\nfrom os import environ\nfrom simpleconf import ProfileConfig\n\nenviron['XXX_DEFAULT_A'] = '1'\n\nconf = ProfileConfig.load('XXX.osenv')\n# conf.a == 1\n```\n\n##### Loading TOML files\n\n```toml\n# config.toml\n[default]\na = 1\n```\n\n```python\nfrom simpleconf import ProfileConfig\n\nconf = ProfileConfig.load('config.toml')\n# conf.a == 1\n```\n\n##### Loading YAML files\n\n```yaml\n# config.yaml\ndefault:\n  a: 1\n```\n\n```python\nfrom simpleconf import ProfileConfig\n\nconf = ProfileConfig.load('config.yaml')\n# conf.a == 1\n```\n\n#### Switching profile\n\n```python\nfrom simpleconf import ProfileConfig\n\nconf = ProfileConfig.load(\n   {'default': {'a': 1, 'b': 2}, 'dev': {'a': 3}, 'prod': {'a': 4}}\n)\n# conf.a == 1; conf.b == 2\n# ProfileConfig.profiles(conf) == ['default', 'dev', 'prod']\n# ProfileConfig.pool(conf) == {'default': {'a': 1, 'b': 2}, 'dev': {'a': 3}, 'prod': {'a': 4}}\n# ProfileConfig.current_profile(conf) == 'default'\n# ProfileConfig.base_profile(conf) == 'default'\n\nProfileConfig.use_profile(conf, 'dev')\n# conf.a == 3; conf.b == 2\n# ProfileConfig.current_profile(conf) == 'dev'\n# ProfileConfig.base_profile(conf) == 'default'\n\n# use a different base profile\nProfileConfig.use_profile(conf, 'prod', base='dev')\n# conf.a == 4   # No 'b' in conf\n# ProfileConfig.current_profile(conf) == 'prod'\n# ProfileConfig.base_profile(conf) == 'dev'\n\n# Copy configuration instead of inplace modification\nconf2 = ProfileConfig.use_profile(conf, 'dev', copy=True)\n# conf2 is not conf\n# conf2.a == 3; conf2.b == 2\n\n# Use a context manager\nwith ProfileConfig.use_profile(conf2, 'default'):\n    conf2.a == 3\n    conf2.b == 2\n# conf2.a == 3; conf2.b == 2\n```\n\n### Type casting\n\nFor configuration formats with type support, including dictionary, no type casting is done by this library, except that for TOML files.\n\nTOML does not support `None` value in python. We use `rtoml` library to parse TOML files, which dumps `None` as `\"null\"`. So a `null_caster` is used to cast `\"null\"` to `None`.\n\nA `none_caster` is also enabled for TOML files, a pure string of `\"@none\"` is casted to `None`.\n\nFor other formats, following casters are supported:\n\n#### Int caster\n\n```python\nfrom os import environ\nfrom simpleconf import Config\n\nenviron['XXX_A'] = '@int:1'\n\nconf = Config.load('XXX.osenv')\n# conf.a == 1 # int\n```\n\n#### Float caster\n\n`@float:1.0` -\u003e `1.0`\n\n### Bool caster\n\n`@bool:true` -\u003e `True`\n`@bool:false` -\u003e `False`\n\n#### Python caster\n\nValues are casted by `ast.literal_eval()`.\n\n```python\n\"@python:1\" =\u003e 1  # or\n\"@py:1\" =\u003e 1\n\"@py:1.0` -\u003e `1.0`\n\"@py:[1, 2, 3]\" =\u003e [1, 2, 3]\n```\n\n#### JSON caster\n\n`@json:{\"a\": 1}` -\u003e `{\"a\": 1}`\n\n#### TOML caster\n\n`@toml:a = 1` -\u003e `{\"a\": 1}`\n\n### Templated configuration files\n\n`jinja2` and `liquid` templating engines are supported. The templating engine is determined by the file extension, which can be either the primary or secondary suffix. For example, `config.toml.j2` and `config.j2.toml` are both treated as TOML files with Jinja2 templating.\n\n`config.toml.j2`\n\n```toml\na = {{ 1 + 2 }}\n```\n\n```python\nfrom simpleconf import Config\n\nconf = Config.load('config.toml.j2')\n# conf.a == 3\n```\n\n`config.liq.toml`\n\n```toml\n{% for i in range(1, 3) %}\n[section{{i}}]\na = {{i}}\n{% endfor %}\n```\n\n```python\nfrom simpleconf import Config\n\nconf = Config.load('config.liq.toml')\n# conf.section1.a == 1\n# conf.section2.a == 2\n```\n#### Loader directive in the first line\n\nInstead of using a special file extension, you can embed a loader directive in the **first line** of a configuration file as a comment. This allows a plain `config.toml` to be processed by the Liquid engine without renaming the file.\n\nThe directive format is:\n\n```\n# simpleconf-loader: \u003cloader\u003e\n```\n\nSupported comment prefixes: `#`, `;`, `//` (case-insensitive).\n\nThe `\u003cloader\u003e` value can be:\n\n| Value | Meaning |\n|---|---|\n| `liq` or `liquid` | Use the Liquid loader for this file's format |\n| `j2`, `jinja`, or `jinja2` | Use the Jinja2 loader for this file's format |\n| A full extension (e.g. `toml.liq`) | Use the exact loader specified |\n\n**Example — Liquid in a plain `.toml` file:**\n\n`config.toml`\n```toml\n# simpleconf-loader: liq\n{% set x = 10 %}\n[default]\na = {{ 1 + 1 }}\nb = {{ x + 2 }}\n```\n\n```python\nfrom simpleconf import Config\n\nconf = Config.load('config.toml')\n# conf.default.a == 2\n# conf.default.b == 12\n```\n\n**Example — Jinja2 in a plain `.yaml` file:**\n\n`config.yaml`\n```yaml\n# simpleconf-loader: j2\ndefault:\n  a: {{ 1 + 1 }}\n```\n\n```python\nfrom simpleconf import Config\n\nconf = Config.load('config.yaml')\n# conf.default.a == 2\n```","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpwwang%2Fpython-simpleconf","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpwwang%2Fpython-simpleconf","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpwwang%2Fpython-simpleconf/lists"}