pulpo-config
Overview
The Config class provides a robust and flexible way to manage configuration settings in Python applications. It offers a simple interface to load, retrieve, and set configuration parameters, making it ideal for projects that require dynamic configuration handling.
Key Features
Easy Initialization
- Initialize with a dictionary of options or a JSON file.
- Automatically loads options from a file if a file path is provided.
Flexible Option Retrieval
- Retrieve configuration values with support for nested keys.
- Environment variable substitution for values starting with
$ENV.
Command-Line Argument Processing
- Seamlessly integrates with
argparseto update configurations from command-line arguments. - Accepts arguments as a dictionary or
argparse.Namespaceobject.
JSON and String Representation
- Convert configurations to a JSON string or a standard string representation for easy debugging and logging.
Specialized Value Retrieval
- Get configuration values as boolean or integer types with
getAsBoolandgetAsInt. - Handles type conversion and validation internally.
Dynamic Configuration Setting
- Set configuration values with support for nested keys.
- Automatically creates intermediate dictionaries if needed.
Benefits
Flexibility: Easily manage configurations with varying levels of complexity.Simplicity: Streamline configuration management without extensive boilerplate code.Compatibility: Works seamlessly with common Python libraries likeargparse.Extensibility: Customize and extend for more complex use cases or specific project needs.
Basic Usage
from pulpo_config import Config
# Can load values manually through a dictionary..
config = Config(options={"database": {"host": "localhost", "port": 3306}})
# Or can load values manually..
config.set("api_key", "your-api-key")
config.set('database.host', 'localhost')
# Or can load options from a JSON config file
config = Config(json_file_path="config.json")
# Or can load from command line parameters
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--debug_mode', type=str)
config.process_args(parser)
# Retrieve a simple configuration value
api_key = config.get("api_key")
# Retrieve a simple configuration value
is_debug_mode = config.getAsBool("debug_mode")
# Retrieve a nested configuration value
db_host = config.get("database.host")
API
Terms: Config vs Options
In this library, I use the following terms:
config: higher level class that offers ability toset/get, but also ability to load from a variety of sources or convenience methodsoptions: low level dictionary of key-value pairs, used to initializeConfig. Anoptionsdictionary is used as the internal data store for the Config implementation
Constructor
Config can be initialized with a dictionary or json formatted config file
Config(options: dict = None, json_file_path: str = None)- With no parameters, will create a
Configwith no values - If
optionssupplied, will initialize with the supplied key-value pairs. Note that this does support nest key-value structures. - What if
optionsis modified after being used to initializeConfig? Read here. - If
json_file_pathwill load values from json formatted config file
- With no parameters, will create a
Load from sources
There are a set of methods to load from others sources. Each for these will copy key-value pairs from parameter to Config and return the instance of Config (to support chain calls). For example:
config = Config().fromOptions(options).fromKeyValue('k', 'v').fromJsonFile('config.json')
fromOptions(self, options: dict = None)- load
Configwith the supplied key-value pairs. Note that this does support nest key-value structures.
- load
fromKeyValue(self, key: str, value: typing.Any)- load
Configwith the supplied key-value pair.
- load
fromJsonFile(self, file_path: str)- load
Configwith the content from the supplied json file
- load
fromYamlFile(self, file_path: str)- load
Configwith the content from the supplied yaml file
- load
fromArgumentParser(self, args: dict)- load
Configwith command line arguments. argscan be eitherargparserorargparser.namepspace(the output fromargparser.parse())
- load
Load from sources
There are a set of methods to load from others sources. Each for these will copy key-value pairs from parameter to Config and return the instance of Config (to support chain calls). For example:
config = Config().fromOptions(options).fromKeyValue('k', 'v').fromJsonFile('config.json')
fromOptions(self, options: dict = None)- load
Configwith the supplied key-value pairs. Note that this does support nest key-value structures.
- load
fromKeyValue(self, key: str, value: typing.Any)- load
Configwith the supplied key-value pair.
- load
fromKeyValueList(self, key_value_list)- load
Configwith supplied key-value pairs.
- load
fromJsonFile(self, file_path: str)- load
Configwith the content from the supplied json file.
- load
fromYamlFile(self, file_path: str)- load
Configwith the content from the supplied yaml file.
- load
fromArgumentParser(self, args: dict)- load
Configwith command line arguments. argscan be eitherargparserorargparser.namepspace(the output fromargparser.parse())
- load
process_args
Passing a standard argparser or argparser.namepspace will integrate command line params into the config values
process_args(self, args: dict)
Set
set(key: str, value: typing.Any)- Will set key=value
valuecan be of any type, and would be returned as set- To set a nested value (such as if database option has child option of host), use a
.:config.set('database.host', 'localhost') - If nested value parent(s) (such as database in the above example) does not exist, those parent(s) will be created.
Get
get(key: str, default_value: typing.Any = None)- Will return the value associated the key
- If there is not a set value, the the
default_valueis returned - To get a nested value, use a
.:config.get('database.host')
- There are also specialized get methods to cast values to specific types
getAsBool(self, key: str, default_value: typing.Any = None) -> boolgetAsInt(self, key: str, default_value: int = None) -> int
Keys, Values, Iterator
keys: returns a list of keys. If the options are nested, will return in dot notation (i.e.['parent.k1', 'parent.k2'])values: returns a dictionary with all key-value pairs.If the options are nested, will return in dot notation (i.e.{'parent.k1': 'v1', 'parent.k2': 'v2'})__iter__: iterates over the list of keys (for key in config)
More Usage Patterns
Loading from dictionary
Using fromOptions
from pulpo_config import Config
options={"api_key": "your-api-key", "database": {"host": "localhost", "port": 3306}}
config = Config().fromOptions(options)
api_key = config.get("api_key")
host = config.get("database.host")
Using constructor
from pulpo_config import Config
config = Config(options={"api_key": "your-api-key", "database": {"host": "localhost", "port": 3306}}
api_key = config.get("api_key")
host = config.get("database.host")
Manually setting config
from pulpo_config import Config
config = Config()
config.set("api_key", "your-api-key")
config.set("database.host", "localhost")
config.set("database.port", 3306)
api_key = config.get("api_key")
host = config.get("database.host")
Loading from json config file
Most use cases will utilize a config file to store options. Below is a sample config
{
"api_key": "your-api-key",
"database": {
"host": "localhost",
"port": 3306
}
}
Load this config file named config.json using the following:
from pulpo_config import Config
config = Config().fromJsonFile(file_path='config.json')
api_key = config.get("api_key")
host = config.get("database.host")
Loading from command line parameters
In a scenario in which you are using commandline params with argparser, use the following:
from pulpo_config import Config
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--api_key', type=str)
config = Config().fromArgumentParser(parser)
api_key = config.get("api_key")
Get bool values
The getAsBool will cast the value to a bool. For this purpose, the following are considered true: [True, 'TRUE', 'T', '1', 1] (case-insensitive)
if config.getAsBool("enable_feature_x"):
# do stuff
Get in values
The getAsInt will cast the value to an int.
port = config.getAsInt("database.host")
Extending the Config class
For many application, I prefer to create an application-specific config class, extending from the provided config class. Example:
class MyApplicationConfig(Config):
def __init__(self, options: dict = None, json_file_path: str = None):
super().__init__(options=options, json_file_path=json_file_path)
@property
def api_key(self: Config) -> str:
return self.get('api_key')
@property
def debug_mode(self: Config) -> str:
return self.getAsBool('debug_mode', False)
Installation
Pulpo-config is avaiable on PyPi: https://pypi.org/project/pulpo-config/
Install using
pip install pulpo-config
Metadata
Release files for pulpo-config 2.0.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pulpo-config-2.0.2.tar.gz | 6.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pulpo_config-2.0.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 13.5 kB
Release files / pulpo-config-2.0.2.tar.gz
| Download URL | pulpo-config-2.0.2.tar.gz |
|---|---|
| Size | 6.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
2b8d6a1912fa0c302af27254432632186d46bedb3379d14e36bea2ae65d31576
|
|
BLAKE2b-256 checksum How to use checksums |
0f6ce58ddfaf32fa4c7e46d611d1500ca322994b343aa95123a459bad7cb7e8c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/4.0.2 CPython/3.9.18
|
Release files / pulpo_config-2.0.2-py3-none-any.whl
| Download URL | pulpo_config-2.0.2-py3-none-any.whl |
|---|---|
| Size | 6.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9fbc80bb1b20d16e64efb3e48ff643c837ca68cca73743017dee200f280cb0a1
|
|
BLAKE2b-256 checksum How to use checksums |
c574fdd8078ab9af5e5c1a151971f7ceb73fc403393bef223a8044640d0a6ad6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/4.0.2 CPython/3.9.18
|