Skip to content
Snippets Groups Projects
Verified Commit c8210a71 authored by Dominik Rimpf's avatar Dominik Rimpf :chipmunk:
Browse files

deprecate old flags

parent 4b471fd5
No related branches found
No related tags found
1 merge request!1Click support and argument deprecation
File moved
import click
from netdb_client.api41 import APIEndpoint, APISession, dns
from netdb_client import api41
from netdb_client.api41 import APISession, dns
from netdb_client.util.click import netdb_api_options
@click.command(context_settings={'help_option_names': ['-h', '--help'], 'max_content_width': 160})
@netdb_api_options()
@netdb_api_options(api41)
def main(netdb_api_endpoint):
netdb_api = APISession(netdb_api_endpoint)
......
......@@ -10,11 +10,11 @@ app = typer.Typer()
@app.command(context_settings={'help_option_names': ['-h', '--help'], 'max_content_width': 120})
def main(
_netdb_config: Path = typer.Option(Path('~/.config/netdb_client.ini'), '--netdb-config', help='netdb auth config file path', callback=netdb_config_callback, is_eager=True, expose_value=False),
endpoint: str = typer.Option(None, '--endpoint', envvar='NETDB_ENDPOINT', help='endpoint to use. Config: [DEFAULT]: endpoint', callback=netdb_endpoint_callback, expose_value=False),
base_url: str = typer.Option(None, '--base-url', envvar='NETDB_BASE_URL', help='webapi server. Config: [$endpoint]: base_url'),
token: str = typer.Option(None, '--token', envvar='NETDB_TOKEN', show_default=False, help='user API token. Config: [$endpoint]: token'),
netdb_endpoint: str = typer.Option(None, '--netdb-endpoint', envvar='NETDB_ENDPOINT', help='endpoint to use. Config: [DEFAULT]: endpoint', callback=netdb_endpoint_callback, expose_value=False),
netdb_base_url: str = typer.Option(None, '--netdb-base-url', envvar='NETDB_BASE_URL', help='webapi server. Config: [$endpoint]: base_url'),
netdb_token: str = typer.Option(None, '--netdb-token', envvar='NETDB_TOKEN', show_default=False, help='user API token. Config: [$endpoint]: token'),
):
netdb_enpoint = APIEndpoint(base_url=base_url, token=token)
netdb_enpoint = APIEndpoint(base_url=netdb_base_url, token=netdb_token)
netdb_api = APISession(netdb_enpoint)
fqdn = dns.Fqdn.list(netdb_api, value_old='net.scc.kit.edu')
......
......@@ -15,7 +15,7 @@ def list_to_generator_map_one2many(array, key_name):
(1 to n Mapping). Returns a generator object."""
res = {}
for item in array:
if not item[key_name] in res:
if item[key_name] not in res:
res[item[key_name]] = []
res[item[key_name]].append(item)
for key, value in res.items():
......
"""Argparse Wrapper Class for automatic config loading"""
import argparse
import os
import sys
from pathlib import Path
from .config import NETDBConfig, NETDBConfigError
class DeprecateAction(argparse.Action):
def __init__(self, *args, **kwargs):
self.call_count = 0
if 'help' in kwargs:
kwargs['help'] = f'[DEPRECATED] {kwargs["help"]}'
super().__init__(*args, **kwargs)
def __call__(self, parser, namespace, values, option_string=None):
if self.call_count == 0:
sys.stderr.write(f"The option `{option_string}` is deprecated. Help:\n")
sys.stderr.write(f"{self.help}\n")
sys.exit(1)
class ArgumentParser(argparse.ArgumentParser):
"""Argument parser with default common arguments for NetDB-api cli
......@@ -22,18 +37,27 @@ class ArgumentParser(argparse.ArgumentParser):
**kwargs
):
super().__init__(formatter_class=formatter_class, epilog=epilog, **kwargs)
self.add_argument('--auth-config',
default=os.path.expanduser('~/.config/netdb_client.ini'),
self.register('action', 'deprecated', DeprecateAction)
self.add_argument('--auth-config', action='deprecated',
help='please use --netdb-config instead')
self.add_argument('--endpoint', '-e', action='deprecated',
help='please use --netdb-enpoint instead')
self.add_argument('--base-url', '-b', action='deprecated',
help='please use --netdb-base-url instead')
self.add_argument('--token', '-t', action='deprecated',
help='please use --netdb-token instead')
self.add_argument('--netdb-config',
default='~/.config/netdb_client.ini',
help='config file path (default: %(default)s)')
self.add_argument('--endpoint', '-e',
self.add_argument('--netdb-endpoint',
help='endpoint to use.\n'
'Environment: "NETDB_ENDPOINT"\n'
'Config: [DEFAULT]: endpoint')
self.add_argument('--base-url', '-b',
self.add_argument('--netdb-base-url',
help='webapi server.\n'
'Environment: "NETDB_BASE_URL"\n'
'Config: [$endpoint]: base_url')
self.add_argument('--token', '-t',
self.add_argument('--netdb-token',
help='user API token.\n'
'Environment: "NETDB_TOKEN"\n'
'Config: [$endpoint]: token')
......@@ -41,46 +65,39 @@ class ArgumentParser(argparse.ArgumentParser):
def parse_args(self, args=None, namespace=None):
args = super().parse_args(args, namespace)
try:
config = NETDBConfig(args.auth_config)
config = NETDBConfig(Path(args.netdb_config))
except NETDBConfigError as err:
self.error(str(err))
def load_config(option_name):
def load_config(option_name, config_key):
"""load config for an option"""
# if value is already set, we can stop here
if getattr(args, option_name) is not None:
return
envvar_name = f'NETDB_{option_name.upper()}'
envvar_name = f'{option_name.upper()}'
# try to load option from environment
value = os.getenv(envvar_name, None)
if value is None:
# endpoint should be loaded from DEFAULT section
if option_name == 'endpoint':
section = 'DEFAULT'
# everything else loads from the $endpoint section
else:
section = getattr(args, 'endpoint')
# load value from config section
value = config.get(section, option_name, fallback=None)
value = getattr(config, config_key)(args.netdb_endpoint)
# For backwards compatibility:
# if base_url is still unknown use endpoint instead
if option_name == 'base_url' and value is None:
value = section
value = args.netdb_endpoint
if value is None:
self.error(
f'No {option_name} specified (looked in args, environment variable '
f'"{envvar_name}", config-file in "{args.auth_config} section {section}")')
f'"{envvar_name}", config-file in "{args.netdb_config} section {args.netdb_endpoint}")')
# we have a value now and can use it
setattr(args, option, value)
# start with endpoint to get the right config section
for option in ['endpoint', 'base_url', 'token']:
load_config(option)
for option, config_key in [('netdb_endpoint', 'endpoint'), ('netdb_base_url', 'base_url'), ('netdb_token', 'token')]:
load_config(option, config_key)
return args
"""click framework helper functions for config loading"""
import configparser
import importlib
import stat
import types
from pathlib import Path
import click
......@@ -14,7 +14,7 @@ def load_config_section_values(config: configparser.ConfigParser, endpoint: str)
token = config.get(endpoint, 'token', fallback=None)
return {'base_url': base_url, 'token': token}
return {'netdb_base_url': base_url, 'netdb_token': token}
def netdb_config_callback(ctx: click.Context, _param: click.Parameter, config_path: Path):
......@@ -37,7 +37,7 @@ def netdb_config_callback(ctx: click.Context, _param: click.Parameter, config_pa
return
ctx.default_map = ctx.default_map or {} # preserve existing defaults
ctx.default_map['endpoint'] = endpoint
ctx.default_map['netdb_endpoint'] = endpoint
config_options = load_config_section_values(config, endpoint)
ctx.default_map.update(config_options)
......@@ -58,7 +58,7 @@ def netdb_endpoint_callback(ctx: click.Context, _param: click.Parameter, endpoin
def netdb_config_option(*param_decls, **kwargs):
if not param_decls:
param_decls = ('--netdb-config',) # TODO this makes more sense IMHO
param_decls = ('--netdb-config', 'netdb_config')
kwargs.setdefault('callback', netdb_config_callback)
kwargs.setdefault('is_eager', True)
......@@ -71,10 +71,9 @@ def netdb_config_option(*param_decls, **kwargs):
return click.option(*param_decls, **kwargs)
# TODO: should we really provide short options???
def netdb_endpoint_option(*param_decls, **kwargs):
if not param_decls:
param_decls = ('--endpoint', '-e', 'endpoint')
param_decls = ('--netdb-endpoint', 'netdb_endpoint')
kwargs.setdefault('callback', netdb_endpoint_callback)
kwargs.setdefault('type', click.STRING)
......@@ -89,7 +88,7 @@ def netdb_endpoint_option(*param_decls, **kwargs):
def netdb_base_url_option(*param_decls, **kwargs):
if not param_decls:
param_decls = ('--base-url', '-b', 'base_url')
param_decls = ('--netdb-base-url', 'netdb_base_url')
kwargs.setdefault('type', click.STRING)
kwargs.setdefault('envvar', 'NETDB_BASE_URL')
......@@ -102,7 +101,7 @@ def netdb_base_url_option(*param_decls, **kwargs):
def netdb_token_option(*param_decls, **kwargs):
if not param_decls:
param_decls = ('--token', '-t', 'token')
param_decls = ('--netdb-token', 'netdb_token')
kwargs.setdefault('type', click.STRING)
kwargs.setdefault('envvar', 'NETDB_TOKEN')
......@@ -113,23 +112,16 @@ def netdb_token_option(*param_decls, **kwargs):
return click.option(*param_decls, **kwargs)
def netdb_api_options(target: str = 'netdb_api_endpoint', client_lib_version: str = None):
if client_lib_version is None:
client_lib_module_path = 'netdb_client'
else:
client_lib_module_path = f'netdb_client.api{client_lib_version.replace(".", "")}'
api_lib = importlib.import_module(client_lib_module_path)
def netdb_api_options(client_lib_module: types.ModuleType, target: str = 'netdb_api_endpoint'):
def decorator(func):
@netdb_config_option()
@netdb_endpoint_option()
@netdb_base_url_option()
@netdb_token_option()
def _decorator(*args, **kwargs):
api_endpoint = api_lib.APIEndpoint(
base_url=kwargs.pop('base_url'),
token=kwargs.pop('token')
api_endpoint = client_lib_module.APIEndpoint(
base_url=kwargs.pop('netdb_base_url'),
token=kwargs.pop('netdb_token')
)
kwargs[target] = api_endpoint
return func(*args, **kwargs)
......
......@@ -17,24 +17,27 @@ class NETDBConfig:
self.default_endpoint = self.config.get('DEFAULT', 'endpoint', fallback=None)
@property
def base_url(self, endpoint: str = None):
def endpoint(self, endpoint: str = None) -> str:
if endpoint is None:
endpoint = self.default_endpoint
if endpoint is None:
raise NETDBConfigError('No enpoint was provided.')
raise NETDBConfigError('No endpoint was provided.')
base_url = self.config.get(endpoint, 'base_url', fallback=None)
return endpoint
def base_url(self, endpoint: str = None) -> str:
base_url = self.config.get(self.endpoint(endpoint), 'base_url', fallback=None)
if base_url is None:
base_url = endpoint
return base_url
@property
def token(self, endpoint: str = None):
token = self.config.get(endpoint, 'token', fallback=None)
def token(self, endpoint: str = None) -> str:
token = self.config.get(self.endpoint(endpoint), 'token', fallback=None)
if token is None:
raise NETDBConfigError('No token was provided')
return token
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment