bwindsor / typed-config

Typed, extensible, dependency free configuration reader for Python projects for multiple config sources and working well in IDEs for great autocomplete performance.
MIT License
25 stars 6 forks source link

Post configuration read transformations #6

Closed rpocase closed 3 years ago

rpocase commented 3 years ago

I have a use case that has a very narrow set of supported values. Additionally, some configuration items may be inferred based on other values. Specifically, I'm looking at integrating scrapy-redis into a project and maintain the ability to swap between schedulers.

@section('my_config')
class Scrapy(Config):
    scheduler = key(cast=str)
    scheduler_persist = key(cast=bool)
    scheduler_dupefilter_class = key(required=False, cast=str)

In the context of scrapy-redis, I would like to support a use case that allows just overwriting the scheduler, then automatically set scheduler_dupefilter_class to the right string if it isn't set.

The cleanest way I can think to handle this today would be to use a custom ConfigSource and do an initial application config read, add the custom ConfigSource with read config, and then read again.

class ScrapyTransformationConfigSource(ConfigSource):
    def __init__(self, scrapy_config: Scrapy):
        # override based on currently set config

config = Scrapy(sources=[
    EnvironmentConfigSource(prefix="EXAMPLE")
])
config.read()
config.add_source(ScrapyTransformationConfigSource(config.scrapy))
config.read()

This isn't an ideal workflow, and doesn't scale great if this needs to be done for multiple configs. A built in post config read transformation would make this much more seamless.

bwindsor commented 3 years ago

@rpocase This sounds like a useful addition - take a look at the PR I've just created.

The new section in the README might be the most useful to see how it works: https://github.com/bwindsor/typed-config/blob/post_read_hook/README.md#configuration-variables-which-depend-on-other-configuration-variables

rpocase commented 3 years ago

The initial implementation looks good to me and seems like it should satisfy my initial use case. Thanks!

bwindsor commented 3 years ago

This is included in version 0.3.0 - hope it helps!