From 87856cfb42f988494d1ee4f29b62082021e4edc3 Mon Sep 17 00:00:00 2001 From: maxime Date: Wed, 2 Aug 2023 08:16:30 +0200 Subject: [PATCH] [cli-conf] halfapi domain : the file provided as argument is a toml file of the format of .halfapi/config, + better config handling --- halfapi/app.py | 12 ++++++----- halfapi/cli/domain.py | 38 +++++++++++++--------------------- halfapi/conf.py | 15 +++++++------- halfapi/halfapi.py | 2 ++ halfapi/testing/test_domain.py | 3 ++- tests/cli/test_cli_proj.py | 7 ++++++- 6 files changed, 38 insertions(+), 39 deletions(-) diff --git a/halfapi/app.py b/halfapi/app.py index 1b4c70f..b215332 100644 --- a/halfapi/app.py +++ b/halfapi/app.py @@ -1,9 +1,11 @@ +import os from .halfapi import HalfAPI -from .conf import CONFIG, SCHEMA from .logging import logger +from .conf import read_config -logger.info('CONFIG: %s', CONFIG) -logger.info('SCHEMA: %s', SCHEMA) +def application(): + config_file = os.environ.get('HALFAPI_CONF_FILE', '.halfapi/config') -application = HalfAPI( - CONFIG, SCHEMA or None).application + CONFIG = read_config([config_file]) + + return HalfAPI(CONFIG).application diff --git a/halfapi/cli/domain.py b/halfapi/cli/domain.py index 942e1db..6b4e1e3 100644 --- a/halfapi/cli/domain.py +++ b/halfapi/cli/domain.py @@ -9,6 +9,7 @@ import importlib import subprocess import json +import toml import click import orjson @@ -16,7 +17,6 @@ import uvicorn from .cli import cli -from ..conf import CONFIG from ..half_domain import HalfDomain @@ -145,6 +145,14 @@ def domain(domain, config_file, delete, update, create, read, run, dry_run): #, # TODO: Connect to the create_domain function raise NotImplementedError raise Exception('Missing domain name') + + if config_file: + CONFIG = toml.load(config_file.name) + + os.environ['HALFAPI_CONF_FILE'] = config_file.name + else: + from halfapi.conf import CONFIG + if create: raise NotImplementedError elif update: @@ -152,14 +160,8 @@ def domain(domain, config_file, delete, update, create, read, run, dry_run): #, elif delete: raise NotImplementedError elif read: - from ..conf import CONFIG from ..halfapi import HalfAPI - if config_file: - CONFIG = json.loads(''.join( - [ line.decode() for line in config_file.readlines() ] - )) - halfapi = HalfAPI(CONFIG) click.echo(orjson.dumps( halfapi.domains[domain].schema(), @@ -168,25 +170,13 @@ def domain(domain, config_file, delete, update, create, read, run, dry_run): #, ) else: - from ..conf import CONFIG - if 'domain' not in CONFIG: - CONFIG['domain'] = {} - - if domain not in CONFIG['domain']: - CONFIG['domain'][domain] = { - 'enabled': True, - 'name': domain - } - - if dry_run: - CONFIG['dryrun'] = True - - CONFIG['domain'][domain]['enabled'] = True - port = CONFIG['domain'][domain].get('port', 3000) - + port = CONFIG.get('port', + CONFIG.get('domain', {}).get('port') + ) uvicorn.run( 'halfapi.app:application', - port=port + port=port, + factory=True ) diff --git a/halfapi/conf.py b/halfapi/conf.py index 3a57aff..3d83706 100644 --- a/halfapi/conf.py +++ b/halfapi/conf.py @@ -36,7 +36,7 @@ It follows the following format : """ -import logging +from .logging import logger import os from os import environ import sys @@ -46,8 +46,6 @@ import uuid import toml -from .logging import logger - PRODUCTION = True LOGLEVEL = 'info' CONF_FILE = os.environ.get('HALFAPI_CONF_FILE', '.halfapi/config') @@ -77,17 +75,18 @@ except FileNotFoundError: logger.error('Cannot find a configuration file under %s', HALFAPI_DOT_FILE) -def read_config(): +def read_config(filenames=HALFAPI_CONFIG_FILES): """ The highest index in "filenames" are the highest priorty """ d_res = {} - logger.info('Reading config files %s', HALFAPI_CONFIG_FILES) - for CONF_FILE in HALFAPI_CONFIG_FILES: - d_res.update( toml.load(HALFAPI_CONFIG_FILES) ) + logger.info('Reading config files %s', filenames) + for CONF_FILE in filenames: + if os.path.isfile(CONF_FILE): + d_res.update( toml.load(CONF_FILE) ) - logger.info('Reading config files (result) %s', d_res) + logger.info('Read config files (result) %s', d_res) return { **d_res.get('project', {}), 'domain': d_res.get('domain', {}) } CONFIG = read_config() diff --git a/halfapi/halfapi.py b/halfapi/halfapi.py index d26f1e1..0118abc 100644 --- a/halfapi/halfapi.py +++ b/halfapi/halfapi.py @@ -9,6 +9,7 @@ It defines the following globals : - application (the asgi application itself - a starlette object) """ +import sys import logging import time import importlib @@ -48,6 +49,7 @@ class HalfAPI(Starlette): d_routes=None): config_logging(logging.DEBUG) self.config = config + logger.debug('HalfAPI.config: %s', self.config) SECRET = self.config.get('secret') PRODUCTION = self.config.get('production', True) diff --git a/halfapi/testing/test_domain.py b/halfapi/testing/test_domain.py index 7134ffd..295d11c 100644 --- a/halfapi/testing/test_domain.py +++ b/halfapi/testing/test_domain.py @@ -4,6 +4,7 @@ import os import sys import json from json.decoder import JSONDecodeError +import toml from unittest import TestCase from starlette.testclient import TestClient from click.testing import CliRunner @@ -79,7 +80,7 @@ class TestDomain(TestCase): _, self.config_file = tempfile.mkstemp() with open(self.config_file, 'w') as fh: - fh.write(json.dumps(self.halfapi_conf)) + fh.write(toml.dumps(self.halfapi_conf)) self.halfapi = HalfAPI(self.halfapi_conf) diff --git a/tests/cli/test_cli_proj.py b/tests/cli/test_cli_proj.py index 86fc9f6..ff14ccb 100644 --- a/tests/cli/test_cli_proj.py +++ b/tests/cli/test_cli_proj.py @@ -5,6 +5,7 @@ import importlib import tempfile from unittest.mock import patch import json +import toml import pytest from click.testing import CliRunner @@ -29,12 +30,16 @@ class TestCliProj(): _, tmp_conf = tempfile.mkstemp() with open(tmp_conf, 'w') as fh: fh.write( - json.dumps({ + toml.dumps({ 'domain': { 'dummy_domain': { + 'port': 4242, 'name': 'dummy_domain', 'enabled': True } + }, + 'project': { + 'dryrun': True } }) )