Metadata-Version: 2.4
Name: cfgrw
Version: 1.2.0
Summary: Python library for reading and writing properties in configuration files
License: Apache-2.0
License-File: LICENSE
Keywords: cfgrw,configuration
Author: Cliffano Subagio
Author-email: cliffano@gmail.com
Requires-Python: >=3.10,<4.0
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Requires-Dist: Jinja2 (>=3.1.6,<3.2.0)
Requires-Dist: PyYAML (>=6.0.3,<6.1.0)
Project-URL: Documentation, https://github.com/cliffano/cfg-rw
Project-URL: Homepage, https://github.com/cliffano/cfg-rw
Project-URL: Repository, https://github.com/cliffano/cfg-rw
Description-Content-Type: text/markdown

<!-- BEGIN:AVATAR -->
![Avatar](avatar.jpg)
<!-- END:AVATAR -->

<!-- BEGIN:BADGES -->
[![Build Status](https://github.com/cliffano/cfg-rw/workflows/CI/badge.svg)](https://github.com/cliffano/cfg-rw/actions?query=workflow%3ACI)
[![Code Scanning Status](https://github.com/cliffano/cfg-rw/workflows/CodeQL/badge.svg)](https://github.com/cliffano/cfg-rw/actions?query=workflow%3ACodeQL)
[![Dependencies Status](https://img.shields.io/librariesio/release/pypi/cfgrw)](https://libraries.io/github/cliffano/cfg-rw)
[![Security Status](https://snyk.io/test/github/cliffano/cfg-rw/badge.svg)](https://snyk.io/test/github/cliffano/cfg-rw)
[![Published Version](https://img.shields.io/pypi/v/cfgrw.svg)](https://pypi.python.org/pypi/cfgrw)
<!-- END:BADGES -->

# CFG-RW

CFG-RW is a Python library for reading and writing properties in configuration files.

## Installation

```shell
pip3 install cfgrw
```

## Usage

### Configuration file

CFG-RW can read configuration properties from YAML, JSON, INI, and XML files.

Create a configuration file, e.g. `cfgrw.yaml`:

```yaml
---
handlers: "stream,file"
datefmt: "%Y-%m-%d %H:%M:%S"
filename: "stage/test-integration/test-yaml-conf.log"
filemode: "w"
format: "%(levelname)s %(message)s"
level: "info"
```

Create CFGRW object with specific conf_file, and read the values of the configuration properties:

```python
from cfgrw import CFGRW

cfgrw = CFGRW(conf_file='path/to/cfgrw.yaml')
values = cfgrw.read(['handlers', 'filemode', 'level'])
print(values['handlers']) # will print stream,file
print(values['filemode']) # will print w
print(values['level']) # will print info
```

### Environment variables

CFG-RW can also read configuration properties from environment variables with a given prefix.

For example, here are the environment variables with prefix `CFGRW_` :

```shell
export CFGRW_HANDLERS="stream,file"
export CFGRW_DATEFMT="%Y-%m-%d %H:%M:%S"
export CFGRW_FILENAME="stage/test-integration/test-yaml-conf.log"
export CFGRW_FILEMODE="w"
export CFGRW_FORMAT="%(levelname)s %(message)s"
export CFGRW_LEVEL="info"
```

Create CFGRW object without conf_file, and read the value of the configuration properties with specified prefix:

```python
cfgrw = CFGRW()
values = cfgrw.read(['handlers', 'filemode', 'level'], { 'prefix': 'CFGRW_' })
print(values['handlers']) # will print stream,file
print(values['filemode']) # will print w
print(values['level']) # will print info
```

### Configuration file with environment variable fallback

If a property is not found in the configuration file, CFG-RW will fall back to reading it from an environment variable. This requires a `prefix` to be passed in the options.

For example, given a configuration file `cfgrw.yaml` that only contains `handlers` and `level`:

```yaml
---
handlers: "stream,file"
level: "info"
```

and the following environment variable for the missing `filemode` property:

```shell
export CFGRW_FILEMODE="w"
```

CFG-RW will read `handlers` and `level` from the file, then fall back to the environment variable for `filemode`:

```python
from cfgrw import CFGRW

cfgrw = CFGRW(conf_file='path/to/cfgrw.yaml')
values = cfgrw.read(['handlers', 'filemode', 'level'], { 'prefix': 'CFGRW_' })
print(values['handlers']) # will print stream,file
print(values['filemode']) # will print w (from environment variable)
print(values['level'])    # will print info
```

If a property is missing from both the configuration file and the environment variables, it will simply be absent from the returned `values` dict — no error is raised.

### Configuration file with Jinja template

CFG-RW can read configuration properties with YAML, JSON, INI, and XML within a Jinja template. You just need to add a `.j2` to the configuration file name.

Create a configuration Jinja template, e.g. `cfgrw.yaml.j2`:

```yaml
---
handlers: "{{ env.FOOBAR_HANDLERS }}"
datefmt: "%Y-%m-%d %H:%M:%S"
filename: "stage/test-integration/test-yaml-conf.log"
filemode: "{{ env.FOOBAR_FILEMODE }}"
format: "%(levelname)s %(message)s"
level: "{{ env.FOOBAR_LEVEL }}"
```

and the following environment variables:

```shell
export FOOBAR_HANDLERS="stream,file"
export FOOBAR_FILEMODE="w"
export FOOBAR_LEVEL="info"
```

Create CFGRW object with specific conf_file, and read the values of the configuration properties:

```python
from cfgrw import CFGRW

cfgrw = CFGRW(conf_file='path/to/cfgrw.yaml.j2')
values = cfgrw.read(['handlers', 'level', 'level'])
print(values['handlers']) # will print stream,file
print(values['filemode']) # will print w
print(values['level']) # will print info
```

## Configuration

CFG-RW automatically loads the configuration file based on the extension.

| Format | Extension |
|--------|-----------|
| [INI](https://en.wikipedia.org/wiki/INI_file) | `.ini` |
| [JSON](https://www.json.org/) | `.json` |
| [XML](https://www.w3.org/XML/) | `.xml` |
| [YAML](https://yaml.org/) | `.yaml` or `.yml` |
| [Jinja](https://jinja.palletsprojects.com/en/stable/) | `.ini.j2` or `.json.j2` or `.xml.j2` or `.yaml.j2` or `.yml.j2` |

## Colophon

<!-- BEGIN:DEVELOPERS_GUIDE -->
[Developer's Guide](https://cliffano.github.io/developers-guide-python.html)
<!-- END:DEVELOPERS_GUIDE -->

<!-- BEGIN:BUILD_REPORTS -->
Build reports:

* [Lint report](https://cliffano.github.io/cfg-rw/lint/pylint/index.html)
* [Code complexity report](https://cliffano.github.io/cfg-rw/complexity/radon/index.html)
* [Unit tests report](https://cliffano.github.io/cfg-rw/test/pytest/index.html)
* [Test coverage report](https://cliffano.github.io/cfg-rw/coverage/coverage/index.html)
* [Integration tests report](https://cliffano.github.io/cfg-rw/test-integration/pytest/index.html)
* [API Documentation](https://cliffano.github.io/cfg-rw/doc/sphinx/index.html)

<!-- END:BUILD_REPORTS -->

