Skip to content

Problematic work with Configuration provider and it's inconsistent behavior and interface #725

Open
@alexted

Description

@alexted

I encountered a strange behaviour of Configuration depending on which source the Configuration object took data from during its initialisation. This leads to a radically different interface of this class for each case.
This is unintuitive and confusing and the documentation does not cover this aspect fully.

standard behaviour (loading config from dict):

import boto3
from dependency_injector import containers, providers


class Container(containers.DeclarativeContainer):

    config = providers.Configuration()

    s3_client_factory = providers.Factory(
        boto3.client,
        "s3",
        aws_access_key_id=config.aws.access_key_id,           
        aws_secret_access_key=config.aws.secret_access_key,
        # Notice how here we get direct access to the configuration field data directly
        # after initialising the config object. No additional action is needed!
    )

behaviour specific to loading configurations from pydantic settings object:

import boto3
from dependency_injector import containers, providers


class Container(containers.DeclarativeContainer):

    config = providers.Configuration()
    # But we can't do that here! Because our config object does not contain fields with configuration data 
    # To fill the fields of our object we will have to make one more call:
    config.load()
    # which now isn't working and throws an error, lol: 
    # https://github.com/ets-labs/python-dependency-injector/issues/726

    # The second option is to make another call that will return a pydantic settings object:
    config, = config.get_pydantic_settings()  

    s3_client_factory = providers.Factory(
        boto3.client,
        "s3",
        aws_access_key_id=config.aws.access_key_id,                   
        aws_secret_access_key=config.aws.secret_access_key, 
    )

behaviour specific to loading configurations from INI file:

import boto3
from dependency_injector import containers, providers


class Container(containers.DeclarativeContainer):

    config = providers.Configuration()
    # But we can't do that here! Because our config object does not contain fields with configuration data 
    # To fill the fields of our object we will have to make one more call:
    config.load()
    # which now isn't working and throws an error, lol: 
    # https://github.com/ets-labs/python-dependency-injector/issues/726

    # The second option is to make another call that will return a raw config object:
    config, = config.get_ini_files()

    s3_client_factory = providers.Factory(
        boto3.client,
        "s3",
        aws_access_key_id=config.aws.access_key_id,
        aws_secret_access_key=config.aws.secret_access_key,
    )

behaviour specific to loading configurations from YAML file:

import boto3
from dependency_injector import containers, providers


class Container(containers.DeclarativeContainer):

    config = providers.Configuration()
    # But we can't do that here! Because our config object does not contain fields with configuration data 
    # To fill the fields of our object we will have to make one more call:
    config.load()
    # which now isn't working and throws an error, lol: 
    # https://github.com/ets-labs/python-dependency-injector/issues/726

    # The second option is to make another call that will return a raw config object:
    config, = config.get_yaml_files() 

    s3_client_factory = providers.Factory(
        boto3.client,
        "s3",
        aws_access_key_id=config.aws.access_key_id,
        aws_secret_access_key=config.aws.secret_access_key,
    )

And so on. I think the principle is clear.....

Summary:
As you can see, a non-unique interface leads to sub-optimal code, full of extra calls and actions that could have been avoided.
Can you bring the Configuration to a consistent behaviour and a unified interface?

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions