Metadata-Version: 2.1
Name: configlayer
Version: 0.1
Summary: Package for simplified work with configurations (as dataclass), manage their profiles, and export/import possibilities
Author-email: Timoshenko Maxim <cooold.tm@gmail.com>
Project-URL: Homepage, https://github.com/c0oo1d/configlayer
Project-URL: Bug Tracker, https://github.com/c0oo1d/configlayer/issues
Classifier: Programming Language :: Python :: 3.10
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE

## Configlayer: an attempt to simplify working with configurations

----

![PyPI](https://img.shields.io/pypi/v/configlayer)
![PyPI - Python Version](https://img.shields.io/pypi/pyversions/configlayer)

### Features

Initially positioned as a convenient bridge between `dataclass` and `ConfigParser`,  
but later was split into optional modules and added extra functionality:
- **Profiles** module (cfg.profiles) - a lot of functions for config profiles manipulation:
  - Profiles: get, set, clear, rename and switch 
  - Groups: get and del, set at init only ('group' keyword)
- **I/O** module (cfg.io) - export/import functions, if needed custom save/load
- **File** module (cfg.file) - save/load functions for ini config files (use **I/O**)
- Config groups - simultaneous switch/rename of several configs profiles (use **profiles**)
- On set handlers (cfg.*_on_set) - calling a user-defined function for changed field(s)
- Options (cfg.options) - change defaults in several functions (waits rewrite in future)
- Data validation (implemented in **utils** module, but maybe `pydantic` should be used)
- Batch fields get (cfg.get_\*) - data, defaults, types, changed states, params, on_set handlers
- Batch fields set (cfg.set_\*) - data and defaults only
- Besides ConfigBase, there is also LanguageBase - use fixed 'language' group, and 'str' type

### Todo list

- Add docs..
- Add optional autosave (time interval, at exit)
- Add optional get_value_func and pooling_sec to Field (for environment variables, etc.)
- Add optional history of fields/profiles changes (for undo/redo)
- Add config versions (import from older configs by dev-provided functions)
- Add multiple configs in single file (if profiles disabled)
- Add modules support, for example \_\_init__(modules={'db': DataBaseBridge}) (cfg.db)
- Add several active profiles support (with different active fields, override by last one)
- Add logging..
- Do something with utils module - make a separate library or simplify it
- Rebuilt Options to set default methods params at init and change it during execution

----

### Installing

```sh
pip install configlayer
```

----

### Examples

#### Common part

```python
from ast import literal_eval                # Needed only for custom fields import from str
from configlayer import ConfigBase, Field   # Field is needed only for custom fields I/O


# Configuration fields with types and factory defaults
class Config(ConfigBase):
    """Main"""  # optional verbose config name at first __doc__ line
    auto: bool = False
    tab: int = 0
    param: str = 'factory default'
    items: list = []
    items_custom_io: list = Field([], lambda x: f'{x}custom', lambda x: literal_eval(x[:-6]))
```

#### Simple config file

```python 
# Init config from file, if it exists
data = Config('config simple.ini')

# Set fields ways
data.param = 'field'
data.cfg.set_fields({'auto': True, 'items': ['some']})

# Set user defaults 
data.cfg.set_defaults({'tab': 1, 'items_custom_io': ['default']})

# Save changes to file (no autosave yet, planned)
data.cfg.file.save()
```

#### Profiles config file

```python

# Init config with profiles support (file has additional internal section)
data = Config('config profiles.ini', profiles=True)
profiles = data.cfg.profiles

# Set defaults ways (at this stage - default profile selected, set fields ways change defaults)
data.param = 'default'
data.cfg.set_fields({'auto': True, 'tab': 2})
data.cfg.set_defaults({'items': ['default'], 'items_custom_io': ['default']})

# Add new profiles and switch to it ways
profiles.set('Profile 1', {'auto': False, 'tab': 0})

## 'auto' and 'tab' at factory defaults, 'items' and 'items_custom_io' at user defaults
profiles.switch('Profile 1')

## the same as 'Profile 1', due to copy from currently selected profile
profiles.switch('Profile 2', add=True, add_current=True)

## all fields copied from user defaults
profiles.switch('Profile 3', add=True)

# Rename current profile
profiles.rename('New profile')

# Rename selected profile
profiles.rename('New profile 2', 'Profile 2')

# Save changes to file (no autosave yet, planned)
data.cfg.file.save()
```

#### Simple RAM-only config, with I/O operations

```python
# Init config only in RAM with export/import functions access
data1 = Config(io=True)
data1.param = 'field'
exported = data1.cfg.io.export_config()

data2 = Config(io=True)
data2.cfg.io.import_config(exported)
assert data1 == data2
```
