Skip to main content

InfoScout GarlicConfig

Project description

CircleCI codecov

GarlicConfig

GarlicConfig is a framework that makes it easy to deal with configurations in an easy yet flexible way. The core of this package is written in C++ and this Python package wraps the native code to provide an easy access to the configuration and some extra feature on top of it. The native library allows for quick retrieval of the configurations which can be used on any platform, this wrapper, however allows for defining advanced validation and config retrieval logic. For example, you could define your own conventions for getting localized version of configs.

The whole thing starts by defining the structure of your configs using models.

You can define models by inheriting from ConfigModel:

from garlicconfig import models

class DatabaseConfig(models.ConfigModel):
    pass

By adding attributes (or properties), you can define what this model recognizes and what format should each one of these attributes have.

For properties, you can use ConfigField. There are a set of built-in fields:

  • StringField
  • IntegerField
  • ArrayField
  • ModelField
  • BooleanField

You can also make your own custom ConfigModel and/or ConfigField.

for example:

from garlicconfig import fields
from garlicconfig.exceptions import ValidationError

class EvenIntegerField(IntegerField):

    def validate(self, value):
        if value % 2 != 0:
            raise ValidationError('bad integer')
    
    def to_model_value(self, value):
        return int(value)
        
    def to_garlic_value(self, value):
        return str(value)

The field class above stores str in the python dictionary representation. However, for the materialized config model, int is used. It also invalidates unaccepted values by raising ValidationError, in this case odd values.

Note that to_model_value is responsible for converting a basic type to a more complicated python type, perhaps constructing a Python-defined class.

to_garlic_value does the exact opposite, it should convert the value to a basic value. Basic value is defined to be one of the following types:

  • str
  • int
  • float
  • dict
  • set & list

This is primarily used for ease of encoding/decoding. By default, both of these methods return the given value without making any changes and I'd recommend not creating very complicated objects since it'll limit the accessibility of them in different platforms should you need to support them.

Next, you can define your own config model and use the custom ConfigField we just created.

for example:

class SomeRandomConfig(ConfigModel):

	value = EvenIntegerField(nullable=False, default=2)

You can use py_value method on config models to get a python dictionary with basic value types in it. This is handy to cache it in memory, or to use it for serialization.

from_dict will create a new config model from a python dictionary.

Furthermore, you can use garlic_value to construct a GarlicValue from the current config model and use from_garlic to construct a model from a GarlicValue.

GarlicValue is a type that keeps configuration objects in the native code and loads them in Python lazily. This allows you to lower memory usage while speeding up all operations. It also comes with a set of handy methods:

resolve

Allows for requested a specific value by providing a dot separated path.

for example:

class ParentConfig(models.ConfigModel):
    
    random_config_field = models.ModelField(SomeRandomConfig)


foo = ParentConfig()
foo.random_config_field.value = 8
garlic_value = foo.garlic_value()
print(garlic_value.resolve('random_config_field.value'))

In the above code, if value to the given path exists, the python representation of the value gets returned. Otherwise, None gets returned. This is helpful because you can simply give the path to the final value and get the requested value. Since all of this is happening in the native code, it's significantly faster to use GarlicValue over python dictionary or regular models.

Your goal should be to validate models using ConfigModel and store/read configurations using GarlicValue.

clone

Copy operations, specially deep copies in Python are very expensive. You can, however, clone GarlicValue instances much faster by using the native clone which copies the object without the need to use deep copy yet accomplish the same result.

for example:

garlic_value_1 = foo.garlic_value()
garlic_value_2 = foo.clone()

Serialization

You can use the following code to encode/decode configs. The default encoder is Json. However, you can write your own encoder and support other formats as needed.

from garlicconfig import encoding

config = DatabaseConfig()
serialized_string = encoding.encode(config, pretty=True)

Merging layers

You merge two configuration layers in order to support inheritance. Something that will come very handy if you plan to use localization or multi-layered configurations.

Any GarlicValue instance will have a apply method that will basically applies a second GarlicValue on top of itself.

for example:

from garlicconfig import models
from garlicconfig import fields


class ExtraConfig(models.ConfigModel):

    has_id = fields.BooleanField(default=False)
    has_degree = fields.BooleanField(default=False)


class DumbConfig(models.ConfigModel):

    name = fields.StringField(nullable=False)
    numbers = fields.ArrayField(IntegerField())
    extra = models.ModelField(ExtraConfig)
    
    def validate(self):
        super(DumbConfig, self).validate()
        if not self.name and not self.numbers:
            raise garlicconfig.exceptions.ValidationError('invalid config for some reason!')


config_1 = DumbConfig.from_dict({
    'name': 'Peyman',
    'numbers': [1, 2, 3]
    'extra': {
        'has_id': True
    }
}).garlic_value()

config_2 = DumbConfig.from_dict({
    'name': 'Patrick',
    'numbers': [4, 5, 6]
    'extra': {
        'has_degree': True
    }
}).garlic_value()

config_1.apply(config_2)
config_1.resolve('numbers')  # returns [4, 5, 6]
config_1.resolve('name')  # returns 'Patrick'
config_1.resolve('extra.has_id')  # returns True (from config_1)
config_1.resolve('extra.has_degree')  # returns True (from config_2)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

garlicconfig-1.2.6-cp39-cp39-macosx_12_0_x86_64.whl (452.4 kB view details)

Uploaded CPython 3.9 macOS 12.0+ x86-64

garlicconfig-1.2.6-cp37-cp37m-win_amd64.whl (430.8 kB view details)

Uploaded CPython 3.7m Windows x86-64

garlicconfig-1.2.6-cp36-cp36m-win_amd64.whl (453.4 kB view details)

Uploaded CPython 3.6m Windows x86-64

garlicconfig-1.2.6-cp36-cp36m-manylinux_2_24_x86_64.whl (1.4 MB view details)

Uploaded CPython 3.6m manylinux: glibc 2.24+ x86-64

File details

Details for the file garlicconfig-1.2.6-cp39-cp39-macosx_12_0_x86_64.whl.

File metadata

File hashes

Hashes for garlicconfig-1.2.6-cp39-cp39-macosx_12_0_x86_64.whl
Algorithm Hash digest
SHA256 cc96f3e516153b4d512e7920676c61f4e2e050efa2cd9bd831e146c9d84bd70e
MD5 13d29c670711e4589cfe62f82d955f5c
BLAKE2b-256 e5c485c3c8f35a6dc4f3d794466f23b1c144cccf1e0340788c77059c83e99c78

See more details on using hashes here.

File details

Details for the file garlicconfig-1.2.6-cp37-cp37m-win_amd64.whl.

File metadata

File hashes

Hashes for garlicconfig-1.2.6-cp37-cp37m-win_amd64.whl
Algorithm Hash digest
SHA256 994e52b113c5286f57ed71e187ec784159c3f5f3db159cf84d2f2cef6690c569
MD5 e20e41142bdefc1ce9406e020a408c72
BLAKE2b-256 277069713326377045f5bcb54f976f1ac5d0672fa86e293c4884f72c36f41995

See more details on using hashes here.

File details

Details for the file garlicconfig-1.2.6-cp36-cp36m-win_amd64.whl.

File metadata

  • Download URL: garlicconfig-1.2.6-cp36-cp36m-win_amd64.whl
  • Upload date:
  • Size: 453.4 kB
  • Tags: CPython 3.6m, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.8.0 pkginfo/1.9.6 readme-renderer/34.0 requests/2.27.1 requests-toolbelt/0.10.1 urllib3/1.26.14 tqdm/4.64.1 importlib-metadata/4.8.3 keyring/23.4.1 rfc3986/1.5.0 colorama/0.4.5 CPython/3.6.8

File hashes

Hashes for garlicconfig-1.2.6-cp36-cp36m-win_amd64.whl
Algorithm Hash digest
SHA256 e7a78f2d742417b7285d6877ccca06641d803ab7f5fc9b333dc5122d6adba34b
MD5 517b4610dffb65aa6b5f84cfc44cce3f
BLAKE2b-256 b37205184b84aca181429eaa8b9cf6bad263df2c959edcbda792bff4dddeff49

See more details on using hashes here.

File details

Details for the file garlicconfig-1.2.6-cp36-cp36m-manylinux_2_24_x86_64.whl.

File metadata

  • Download URL: garlicconfig-1.2.6-cp36-cp36m-manylinux_2_24_x86_64.whl
  • Upload date:
  • Size: 1.4 MB
  • Tags: CPython 3.6m, manylinux: glibc 2.24+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.8.0 pkginfo/1.9.6 readme-renderer/34.0 requests/2.27.1 requests-toolbelt/0.10.1 urllib3/1.26.14 tqdm/4.64.1 importlib-metadata/4.8.3 keyring/23.4.1 rfc3986/1.5.0 colorama/0.4.5 CPython/3.6.8

File hashes

Hashes for garlicconfig-1.2.6-cp36-cp36m-manylinux_2_24_x86_64.whl
Algorithm Hash digest
SHA256 5ab6231143ab4652acd1ccfa510739a3ece0fb3ed29a941476e071f55b3dd535
MD5 2cbeb9510fe2163f2f693041f27a76d1
BLAKE2b-256 d5de57a99a0dd7e5d37405fe7c3c2c2ef6094b652c5d3d6cfe3fea26867a8886

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page