Giter Club home page Giter Club logo

cfgman's Introduction

cfgman

A configuration manager for Python application.

Features

  • Configure from files (yaml, toml, json).
  • Environment variables.
  • Custom variables (e.g. command line arguments).
  • Type annotations.

Usage

from cfgman import (
    configclass,
    load_config,
    get_default_config,
    env_loader,
    file_loader,
    MISSING,
)
from apischema.metadata import conversion


def from_isoformat(s: str) -> datetime:
    return datetime.fromisoformat(s)


def to_isoformat(d: datetime) -> str:
    return d.isoformat()


@configclass
class WebServerConfig:
    host: str = "localhost"
    port: int = 80
    timeout: int = 30


@configclass
class Config:
    web: WebServerConfig  # nest configs
    start: datetime = field(
        default_factory=lambda: datetime.now(datetime.utc),
        metadata=conversion(from_isoformat, to_isoformat),
    )


argparser = ArgumentParser(Config)
argparser.add_argument(
    "-c",
    "--config",
    dest="config_files",
    metavar="FILENAME",
    action="append",
    default=["~/.config/myapp/config.yaml"],
)
argparser.add_argument("--host", metavar="HOSTNAME", default=MISSING)
argparser.add_argument("-p", "--port", metavar="PORT", type=int, default=MISSING)
argparser.add_argument("-s", "--start", metavar="ISODATETIME", default=MISSING)
args = argparser.parse_args()

config = load_config(
    Config,
    file_loader(
        files=args.config_files, supported_formats=(FileFormat.YAML, FileFormat.TOML)
    ),
    env_loader(
        prefix="APP_",
        mapping={"HOST": "web.host", "PORT": "web.port"},
    ),
    {
        "web": {
            "host": args.host,
            "port": args.port,
        },
        "start": args.start,
    },
)

time.sleep((datetime.now(datetime.utc) - config.start).total_seconds)


async def run_server():
    # you can retrieve your module specific config without depending on the rest of the configuration
    webconfig = get_default_config(WebServerConfig)
    server = start_server(webconfig.host, webconfig.port)
    await server.serve_forever()


async def request_handler(request):
    experiment = select_experiment()
    with replace_default(WebServerConfig, changes=experiment.changes):
        webconfig = get_default_config(WebServerConfig)
        response = await prepare_response(
            headers={"X-Experiment-Name": webconfig.experiment}
        )

cfgman's People

Contributors

duilio avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.