vendredi 6 décembre 2019

Python Environment Variables Through Reflection

In Python 3.7, I wrote an Environment helper class which allows me to load OS environment variables through reflection. It also converts the environment variable into a native bool or tuple, based on type hints declared in a derived class.

It works, but the linter in Visual Studio Code gives me this problem report:

Class 'Environment' has no '__annotations__' member

Here is the helper class.

import os
from abc import ABC

class Environment(ABC):

    @classmethod
    def from_os(cls):
        convert = {
            bool: lambda d: d == "1",
            (): lambda d: tuple(d.split(',')),
            str: lambda d: d
        }
        values = [ 
            convert[value](os.environ[key]) 
            for key,value in cls.__annotations__.items() 
            ]
        return cls(*values)

Again, the code actually works. What can I do to make the linter happy? Perhaps there is a different way I can iterate over the attributes (and attribute type hints) in order to achieve the same result without using __annotations__?

In case it helps, here is an example of how my helper class is used to fetch an arbitrary set of environment variables:

from dataclasses import dataclass

@dataclass
class FWMonitoringEnv(Environment):
    # The names of these attributes are used
    # to find and load a corresponding environment variable.
    # This happens when "FWMonitoringEnv.from_os()" is called.
    preempt : bool
    split_routes : bool
    tag_key : str
    vpc_summary_route : str
    route_table_id : str
    fw_trust_enis : ()
    fw_mgmt_ips : ()
    api_key_name : str
    region : str

Elsewhere in the code I simply execute this:

env = FWMonitoringEnv.from_os()

While I'm at it, there is another code hygiene issue I'd like to fix. Is there a way I can make my Environment class force the derived class to be a @dataclass? For example, could that be accomplished with Python 3.7 type hints?





Aucun commentaire:

Enregistrer un commentaire