A Python library for using INI files to instantiate classes.
Project description
Vivify
Overview
Vivify is a lightweight Python library for INI style object initialisation. Using Vivify, you can instantiate classes and set attributes using values provided from an external configuration. Vivify supports both POD types as well as more complex objects and relationships. This is particularly useful in domains where the configuration is very closely coupled to the objects.
Installation
Installing Vivify is easy! Vivify is available on the Python Packaging Index. If you're using Poetry then poetry add vivify
, otherwise:
pip install vivify
Usage
The snippets shown below are provided in full in the examples directory and demonstrate using an external configuration to instantiate some pre-defined classes. Further examples are also supplied in the examples directory.
This example showcases how Vivify supports complex relationships between classes. In this case, there is a bidirectional associative relationship between classes A
and B
and B
has an additional variable of type V
.
class V(list[int], Vivifiable):
@classmethod
def vivify(cls, object):
return cls(map(int, object.split(",")))
class A(object):
b: B
class B(object):
a: A
v: V
Note that in the code above we should specify the types of any instance variables. This is so that Vivify can instantiate the correct type for a specified variable, e.g. to distinguish between a string and a reference to another object in the configuration. It is also important that any attributes specified in the configuration should be settable (or at the very least an attempt to set the attribute should not fail).
The following configuration INI file (example.ini
) contains the options we want to use to instantiate two instances of these classes named foo
and bar
.
[main]
foo = A
bar = B
[foo]
i = 1
b = bar
[bar]
a = foo
v = 1, 2, 3
The main
section where variables are named can be given any valid section name other than that which is reserved for supplying default values for sections - this is defined as "DEFAULT"
in the standard configuration file parsing library. Note how the other section names correspond to the variable names provided in the main
section.
# initialise the config parser and read the ini file
config = ConfigParser()
with open("example.ini") as f:
config.read_file(f)
# specify the valid objects for vivification
vivifier = Vivifier(types=[A, B])
vivified = vivifier.vivify(instances="main", config=config)
# verify that the vivification occurred as expected
assert isinstance(vivified["foo"], A)
assert isinstance(vivified["bar"], B)
assert vivified["foo"].b == vivified["bar"]
assert vivified["bar"].a == vivified["foo"]
assert vivified["bar"].v == [1, 2, 3]
Limitations
Most simple cases should work without issue. Things get complicated and more care should be taken when there are multiple possible types for a value. Consider an attribute with the type annotation Union[list[int], Optional[str]]
. With a configuration value of None
, there are two possible ways this could be interpreted: (i) None
, and (ii) "None"
(because str(None)
returns "None"
). The list[int]
annotation will be skipped because it is a parameterised generic and cannot be instantiated. Currently, the actual type chosen for the is entirely dependent on the ordering of the result of a call to get_args
from the typing extensions library. The first valid matching type is picked for setting the attributes value.
from typing import Optional, Union
from typing_extensions import get_args
logging.basicConfig(
level=logging.DEBUG,
format="%(asctime)s [%(levelname)s] %(message)s",
handlers=[logging.StreamHandler(sys.stdout)],
)
assert (
str(get_args(Union[list[int], Optional[str]]))
== "(list[int], <class 'str'>, <class 'NoneType'>)"
)
In this case, the value would be set to the string "None"
because this matches first (after the invalid list[int]
) and the permissive str
type coercion accepts None as an argument.
If you are especially concerned about which type is used then it is a good idea to either make the typing more strict or use Vivifiable
objects (preferred approaches) or alternatively check a call to get_args
yourself on the type to verify that the implementation will work as you expect. Vivify provides extensive logging so you can see how variables are handled internally.
Licence
Copyright © 2022 Adam D Walker
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file vivify-1.0.1.tar.gz
.
File metadata
- Download URL: vivify-1.0.1.tar.gz
- Upload date:
- Size: 11.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.1.14 CPython/3.9.12 Linux/5.17.5-051705-generic
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 92e872b563ab201174a21eb67d8650580bd34b9bf306af154d168d0759284f6d |
|
MD5 | 11e857f142bfab19bcaa3b6336f009f1 |
|
BLAKE2b-256 | c3dbfe18cb5351adbb383b8fb1fbc55cee02cdcc762ea3e8751a5c6e6076aa0d |
File details
Details for the file vivify-1.0.1-py3-none-any.whl
.
File metadata
- Download URL: vivify-1.0.1-py3-none-any.whl
- Upload date:
- Size: 11.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.1.14 CPython/3.9.12 Linux/5.17.5-051705-generic
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | c9ec75268f95ce2c46ea7d9fc11d6f29589fb22cfbdb94139db51535d8e1097d |
|
MD5 | 4fc0c40c167cb5dcbbe20d4484e26e1b |
|
BLAKE2b-256 | 3c87851dd3b821b849025787c7d988891961c263222fa55ef6b25a5edca7017f |