https://github.com/cidrblock/modelsettings
Modelsettings is a straight-forward, easy to use python application settings manager that includes ini file, environment variable, and command-line parameter support.
https://github.com/cidrblock/modelsettings
argparse docker environment-variables ini-parser python twelve-factor
Last synced: 10 months ago
JSON representation
Modelsettings is a straight-forward, easy to use python application settings manager that includes ini file, environment variable, and command-line parameter support.
- Host: GitHub
- URL: https://github.com/cidrblock/modelsettings
- Owner: cidrblock
- License: mit
- Created: 2018-03-22T16:29:34.000Z (about 8 years ago)
- Default Branch: master
- Last Pushed: 2021-03-25T21:46:23.000Z (about 5 years ago)
- Last Synced: 2025-02-27T04:47:44.540Z (about 1 year ago)
- Topics: argparse, docker, environment-variables, ini-parser, python, twelve-factor
- Language: Python
- Homepage:
- Size: 20.5 KB
- Stars: 3
- Watchers: 3
- Forks: 0
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
[](https://travis-ci.org/cidrblock/modelsettings)
# Model Settings
## Overview
Modelsettings is a straight-forward, easy to use python application settings manager that includes ini file, environment variable, and command-line parameter support.
The necessary settings variables are declared in a yaml model, which is then used to parse an .ini file, environment variables, and finally command-line arguments.
In addition to reading settings from the three sources, modelsettings also includes sample configuration generator support for:
- command-line
- environment variables (e.g., export statements)
- ini file
- docker run
- docker compose
- kubernetes
- drone plugins
## Quick start
### Build the model
Modelsettings looks for a `model_settings.yml` in the current working directory. A simple `model_settings.yml` file might look like this:
```
env_prefix: CF
model:
cream:
choices:
- True
- False
default: False
example: True
help: Would you like cream in your coffee?
required: True
sugar:
choices:
- True
- False
default: True
example: True
help: Would you like sugar in your coffee?
required: True
size:
choices:
- 10
- 12
- 16
default: 12
example: 16
help: What size cup would you like in ounces?
required: True
```
`env_prefix` is used as a prefix for the environment variables, this helps avoid name collision when running multiple python applications in the same shell.
`model` is a dictionary of required settings values.
### Import and use the module
In your application, simply import modelsettings.
```
$ python3 -m venv venv
$ source venv/bin/activate
$ pip install modelsettings
```
app.py
```
from modelsettings import settings
def main():
output = f"You ordered a {settings.SIZE} oz. cup of coffee"
modifiers = []
if settings.CREAM: modifiers.append("cream")
if settings.SUGAR: modifiers.append("sugar")
if modifiers:
output += " with " + " and ".join(modifiers)
output += "."
print(output)
if __name__ == "__main__":
main()
```
All settings are converted to uppercase and available as `settings.XXXXX`
## Additional command-line parameters
### `--help`
Argparse help is generated from the model:
```
$ python app.py --help
usage: app.py [-h]
[--generate {command,docker-run,docker-compose,ini,env,kubernetes,readme,drone-plugin}]
[--settings SETTINGS] [--cream {True,False}]
[--sugar {True,False}] [--size {10,12,16}]
optional arguments:
-h, --help show this help message and exit
--generate {command,docker-run,docker-compose,ini,env,kubernetes,readme,drone-plugin}
Generate a template
--settings SETTINGS Specify a settings file. (ie settings.dev)
--cream {True,False} Would you like cream in your coffee? e.g., True
--sugar {True,False} Would you like sugar in your coffee? e.g., True
--size {10,12,16} What size cup would you like in ounces? e.g., 16
```
### `--generate`
A command-line parameter of generate is added to the application which, when used, will generate sample settings in a number of formats.
```
$ python app.py --generate env
export CF_CREAM=True
export CF_SIZE=16
export CF_SUGAR=True
```
### `--generate readme`
Markdown can be generated which includes all the available generate formats.
```
$ python app.py --generate readme >> README.md
```
## Order of operations
The .ini file is read first, then the environment variables, then the command-line parameters.
### .ini file support
The application will now support loading settings from a `settings.ini` file.
```
$ cat settings.ini
[settings]
cream=True
size=16
sugar=True
$ python app.py
You ordered a 16 oz. cup of coffee with cream and sugar.
```
An alternate settings file can be specified with the command line, this is useful during development of the application.
```
$ cat settings.dev
[settings]
cream=True
size=10
sugar=False
$ python app.py --settings settings.dev
You ordered a 10 oz. cup of coffee with cream.
$ python app.py --settings settings.dev --size 16
You ordered a 16 oz. cup of coffee with cream.
```
### Environment variable support
All settings can be stored as environment variables. The environment variables should be prefaced with the `env_prefix` from the `model_settings.yml` file and capitalized.
```
$ export CF_CREAM=False
$ export CF_SIZE=12
$ export CF_SUGAR=True
$ python app.py
You ordered a 12 oz. cup of coffee with sugar.
$ export CF_CREAM=True
$ python app.py
You ordered a 12 oz. cup of coffee with cream and sugar.
```
### Command-line parameter support
Command line parameters take precedence over `.ini` files and environment variables.
```
$ python app.py --size 10 --sugar False --cream False
You ordered a 10 oz. cup of coffee.
$ python app.py --size 12 --sugar True --cream False
You ordered a 12 oz. cup of coffee with sugar.
$ python app.py --size 16 --sugar True --cream True
You ordered a 16 oz. cup of coffee with cream and sugar.
```
## model_settings.yml
1) The model support 5 basic python types:
- `bool`
- `int`
- `float`
- `string`
- `list`
- `dict`
The type is derived from the example given, and the settings variable is cast to that type.
In the example below, each supported type is shown with a corresponding yaml native example.
`example` is therefore a required property for every entry in the model.
```
bool:
choices:
- True
- False
default: False
help: This is an integer setting
required: False
example: True
integer:
choices:
- 10
- 20
default: 60
help: This is an integer setting
required: False
example: 30
float:
default: 60.5
help: This is an integer setting
required: False
example: 30.5
string:
default: string
help: This is a string setting
required: False
example: string
dictionary:
default:
key: value
help: This is a dict setting
required: False
example:
key: value
list:
default:
- item1
- item2
help: This is a list setting
required: False
example:
- item1
- item2
```
## Dictionaries and lists objects in `.ini` and environment variables.
Dictionary and lists should be represented as json in `.ini` files and environment variables:
```
$ more complex.yml
env_prefix: RM
model:
dictionary:
default:
key: value
help: This is a dict setting
required: False
example:
key: value
list:
default:
- item1
- item2
help: This is a list setting
required: False
example:
- item1
- item2
$ export MODEL_SETTINGS=complex.yml
$ python app.py --generate env
export RM_DICTIONARY='{"key": "value"}'
export RM_LIST='["item1", "item2"]'
$ python app.py --generate ini
[settings]
dictionary={"key": "value"}
list=["item1", "item2"]
```
## Docker
Because all settings are supported as environment variables, transitioning a python application to a docker container is simple.
Dockerfile
```
FROM python:3.6.4-alpine
RUN apk add -U \
ca-certificates \
&& rm -rf /var/cache/apk/* \
&& pip install --no-cache-dir --upgrade pip
WORKDIR /usr/src/app/
ADD model_settings.yml .
ADD app.py .
ADD requirements.txt .
RUN pip install -r requirements.txt
ENTRYPOINT ["python", "app.py"]
```
Build
```
$ docker build -t coffee .
<...>
Successfully built 74938ac5902a
Successfully tagged coffee:latest
```
Generate
```
$ python app.py --generate docker-run
docker run -it \
-e CF_CREAM=True \
-e CF_SIZE=16 \
-e CF_SUGAR=True \
```
Run
```
$ docker run -it \
-e CF_CREAM=True \
-e CF_SIZE=16 \
-e CF_SUGAR=True \
coffee
You ordered a 16 oz. cup of coffee with cream and sugar.
$ docker run -it \
-e CF_CREAM=False \
-e CF_SIZE=12 \
-e CF_SUGAR=True \
coffee
You ordered a 12 oz. cup of coffee with sugar.
```