Compare commits
4 Commits
Author | SHA1 | Date | |
---|---|---|---|
69800f01b6 | |||
b2eaa12a0e | |||
fe7c821605 | |||
d07cf9949b |
@ -33,7 +33,7 @@ repos:
|
|||||||
- id: pyupgrade
|
- id: pyupgrade
|
||||||
args: [--py38-plus]
|
args: [--py38-plus]
|
||||||
- repo: https://github.com/pre-commit/mirrors-autopep8
|
- repo: https://github.com/pre-commit/mirrors-autopep8
|
||||||
rev: v2.0.0
|
rev: v2.0.1
|
||||||
hooks:
|
hooks:
|
||||||
- id: autopep8
|
- id: autopep8
|
||||||
- repo: https://github.com/PyCQA/flake8
|
- repo: https://github.com/PyCQA/flake8
|
||||||
@ -42,6 +42,6 @@ repos:
|
|||||||
- id: flake8
|
- id: flake8
|
||||||
additional_dependencies: [flake8-encodings, flake8-warnings, flake8-builtins, flake8-length, flake8-print]
|
additional_dependencies: [flake8-encodings, flake8-warnings, flake8-builtins, flake8-length, flake8-print]
|
||||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||||
rev: v0.991
|
rev: v1.0.1
|
||||||
hooks:
|
hooks:
|
||||||
- id: mypy
|
- id: mypy
|
||||||
|
45
settngs.py
45
settngs.py
@ -93,11 +93,35 @@ class Setting:
|
|||||||
metavar: str | None = None,
|
metavar: str | None = None,
|
||||||
dest: str | None = None,
|
dest: str | None = None,
|
||||||
# ComicTagger
|
# ComicTagger
|
||||||
|
display_name: str = '',
|
||||||
cmdline: bool = True,
|
cmdline: bool = True,
|
||||||
file: bool = True,
|
file: bool = True,
|
||||||
group: str = '',
|
group: str = '',
|
||||||
exclusive: bool = False,
|
exclusive: bool = False,
|
||||||
):
|
):
|
||||||
|
"""
|
||||||
|
|
||||||
|
Args:
|
||||||
|
*names: Passed directly to argparse
|
||||||
|
action: Passed directly to argparse
|
||||||
|
nargs: Passed directly to argparse
|
||||||
|
const: Passed directly to argparse
|
||||||
|
default: Passed directly to argparse
|
||||||
|
type: Passed directly to argparse
|
||||||
|
choices: Passed directly to argparse
|
||||||
|
required: Passed directly to argparse
|
||||||
|
help: Passed directly to argparse
|
||||||
|
metavar: Passed directly to argparse, defaults to `dest` uppercased
|
||||||
|
dest: This is the name used to retrieve the value from a `Config` object as a dictionary
|
||||||
|
display_name: This is not used by settngs. This is a human-readable name to be used when generating a GUI.
|
||||||
|
Defaults to `dest`.
|
||||||
|
cmdline: If this setting can be set via the commandline
|
||||||
|
file: If this setting can be set via a file
|
||||||
|
group: The group this option is in.
|
||||||
|
This is an internal argument and should only be set by settngs
|
||||||
|
exclusive: If this setting is exclusive to other settings in this group.
|
||||||
|
This is an internal argument and should only be set by settngs
|
||||||
|
"""
|
||||||
if not names:
|
if not names:
|
||||||
raise ValueError('names must be specified')
|
raise ValueError('names must be specified')
|
||||||
# We prefix the destination name used by argparse so that there are no conflicts
|
# We prefix the destination name used by argparse so that there are no conflicts
|
||||||
@ -130,6 +154,7 @@ class Setting:
|
|||||||
self.argparse_args = args
|
self.argparse_args = args
|
||||||
self.group = group
|
self.group = group
|
||||||
self.exclusive = exclusive
|
self.exclusive = exclusive
|
||||||
|
self.display_name = display_name or dest
|
||||||
|
|
||||||
self.argparse_kwargs = {
|
self.argparse_kwargs = {
|
||||||
'action': action,
|
'action': action,
|
||||||
@ -150,6 +175,11 @@ class Setting:
|
|||||||
def __repr__(self) -> str: # pragma: no cover
|
def __repr__(self) -> str: # pragma: no cover
|
||||||
return self.__str__()
|
return self.__str__()
|
||||||
|
|
||||||
|
def __eq__(self, other: object) -> bool:
|
||||||
|
if not isinstance(other, Setting):
|
||||||
|
return NotImplemented
|
||||||
|
return self.__dict__ == other.__dict__
|
||||||
|
|
||||||
def get_dest(self, prefix: str, names: Sequence[str], dest: str | None) -> tuple[str, str, bool]:
|
def get_dest(self, prefix: str, names: Sequence[str], dest: str | None) -> tuple[str, str, bool]:
|
||||||
dest_name = None
|
dest_name = None
|
||||||
flag = False
|
flag = False
|
||||||
@ -496,13 +526,15 @@ class Manager:
|
|||||||
|
|
||||||
def add_group(self, name: str, group: Callable[[Manager], None], exclusive_group: bool = False) -> None:
|
def add_group(self, name: str, group: Callable[[Manager], None], exclusive_group: bool = False) -> None:
|
||||||
"""
|
"""
|
||||||
The primary way to add define options on this class
|
The primary way to add define options on this class.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
name: The name of the group to define
|
name: The name of the group to define
|
||||||
group: A function that registers individual options using :meth:`add_setting`
|
group: A function that registers individual options using :meth:`add_setting`
|
||||||
exclusive_group: If this group is an argparse exclusive group
|
exclusive_group: If this group is an argparse exclusive group
|
||||||
"""
|
"""
|
||||||
|
if self.current_group_name != '':
|
||||||
|
raise ValueError('Sub groups are not allowed')
|
||||||
self.current_group_name = name
|
self.current_group_name = name
|
||||||
self.exclusive_group = exclusive_group
|
self.exclusive_group = exclusive_group
|
||||||
group(self)
|
group(self)
|
||||||
@ -511,16 +543,23 @@ class Manager:
|
|||||||
|
|
||||||
def add_persistent_group(self, name: str, group: Callable[[Manager], None], exclusive_group: bool = False) -> None:
|
def add_persistent_group(self, name: str, group: Callable[[Manager], None], exclusive_group: bool = False) -> None:
|
||||||
"""
|
"""
|
||||||
The primary way to add define options on this class
|
The primary way to add define options on this class.
|
||||||
|
This group allows existing values to persist even if there is no corresponding setting defined for it.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
name: The name of the group to define
|
name: The name of the group to define
|
||||||
group: A function that registers individual options using :meth:`add_setting`
|
group: A function that registers individual options using :meth:`add_setting`
|
||||||
exclusive_group: If this group is an argparse exclusive group
|
exclusive_group: If this group is an argparse exclusive group
|
||||||
"""
|
"""
|
||||||
|
if self.current_group_name != '':
|
||||||
|
raise ValueError('Sub groups are not allowed')
|
||||||
self.current_group_name = name
|
self.current_group_name = name
|
||||||
self.exclusive_group = exclusive_group
|
self.exclusive_group = exclusive_group
|
||||||
self.definitions[self.current_group_name] = Group(True, {})
|
if self.current_group_name in self.definitions:
|
||||||
|
if not self.definitions[self.current_group_name].persistent:
|
||||||
|
raise ValueError('Group already existis and is not persistent')
|
||||||
|
else:
|
||||||
|
self.definitions[self.current_group_name] = Group(True, {})
|
||||||
group(self)
|
group(self)
|
||||||
self.current_group_name = ''
|
self.current_group_name = ''
|
||||||
self.exclusive_group = False
|
self.exclusive_group = False
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[metadata]
|
[metadata]
|
||||||
name = settngs
|
name = settngs
|
||||||
version = 0.5.0
|
version = 0.6.0
|
||||||
description = A library for managing settings
|
description = A library for managing settings
|
||||||
long_description = file: README.md
|
long_description = file: README.md
|
||||||
long_description_content_type = text/markdown
|
long_description_content_type = text/markdown
|
||||||
|
@ -78,6 +78,7 @@ success = [
|
|||||||
'const': None,
|
'const': None,
|
||||||
'default': None,
|
'default': None,
|
||||||
'dest': 'test_setting', # dest is calculated by Setting and is not used by argparse
|
'dest': 'test_setting', # dest is calculated by Setting and is not used by argparse
|
||||||
|
'display_name': 'test_setting', # defaults to dest
|
||||||
'exclusive': False,
|
'exclusive': False,
|
||||||
'file': True,
|
'file': True,
|
||||||
'group': 'tst',
|
'group': 'tst',
|
||||||
@ -117,6 +118,7 @@ success = [
|
|||||||
'const': None,
|
'const': None,
|
||||||
'default': None,
|
'default': None,
|
||||||
'dest': 'testing', # dest is calculated by Setting and is not used by argparse
|
'dest': 'testing', # dest is calculated by Setting and is not used by argparse
|
||||||
|
'display_name': 'testing', # defaults to dest
|
||||||
'exclusive': False,
|
'exclusive': False,
|
||||||
'file': True,
|
'file': True,
|
||||||
'group': 'tst',
|
'group': 'tst',
|
||||||
@ -155,6 +157,7 @@ success = [
|
|||||||
'const': None,
|
'const': None,
|
||||||
'default': None,
|
'default': None,
|
||||||
'dest': 'test', # dest is calculated by Setting and is not used by argparse
|
'dest': 'test', # dest is calculated by Setting and is not used by argparse
|
||||||
|
'display_name': 'test', # defaults to dest
|
||||||
'exclusive': False,
|
'exclusive': False,
|
||||||
'file': True,
|
'file': True,
|
||||||
'group': 'tst',
|
'group': 'tst',
|
||||||
@ -194,6 +197,7 @@ success = [
|
|||||||
'const': None,
|
'const': None,
|
||||||
'default': None,
|
'default': None,
|
||||||
'dest': 'test', # dest is calculated by Setting and is not used by argparse
|
'dest': 'test', # dest is calculated by Setting and is not used by argparse
|
||||||
|
'display_name': 'test', # defaults to dest
|
||||||
'exclusive': False,
|
'exclusive': False,
|
||||||
'file': True,
|
'file': True,
|
||||||
'group': 'tst',
|
'group': 'tst',
|
||||||
@ -232,6 +236,7 @@ success = [
|
|||||||
'const': None,
|
'const': None,
|
||||||
'default': None,
|
'default': None,
|
||||||
'dest': 'test',
|
'dest': 'test',
|
||||||
|
'display_name': 'test', # defaults to dest
|
||||||
'exclusive': False,
|
'exclusive': False,
|
||||||
'file': True,
|
'file': True,
|
||||||
'group': 'tst',
|
'group': 'tst',
|
||||||
@ -270,6 +275,7 @@ success = [
|
|||||||
'const': None,
|
'const': None,
|
||||||
'default': None,
|
'default': None,
|
||||||
'dest': 'test',
|
'dest': 'test',
|
||||||
|
'display_name': 'test', # defaults to dest
|
||||||
'exclusive': False,
|
'exclusive': False,
|
||||||
'file': True,
|
'file': True,
|
||||||
'group': 'tst',
|
'group': 'tst',
|
||||||
@ -306,6 +312,7 @@ success = [
|
|||||||
'const': None,
|
'const': None,
|
||||||
'default': None,
|
'default': None,
|
||||||
'dest': 'test',
|
'dest': 'test',
|
||||||
|
'display_name': 'test', # defaults to dest
|
||||||
'exclusive': False,
|
'exclusive': False,
|
||||||
'file': True,
|
'file': True,
|
||||||
'group': '',
|
'group': '',
|
||||||
|
@ -2,6 +2,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import json
|
import json
|
||||||
|
from collections import defaultdict
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
@ -141,7 +142,7 @@ def test_clean_config(settngs_manager):
|
|||||||
assert cleaned['persistent']['hello'] == 'success'
|
assert cleaned['persistent']['hello'] == 'success'
|
||||||
|
|
||||||
|
|
||||||
def test_parse_cmdline(settngs_manager, tmp_path):
|
def test_parse_cmdline(settngs_manager):
|
||||||
settngs_manager.add_group('tst', lambda parser: parser.add_setting('--test', default='hello', cmdline=True))
|
settngs_manager.add_group('tst', lambda parser: parser.add_setting('--test', default='hello', cmdline=True))
|
||||||
|
|
||||||
normalized, _ = settngs_manager.parse_cmdline(['--test', 'success'])
|
normalized, _ = settngs_manager.parse_cmdline(['--test', 'success'])
|
||||||
@ -150,7 +151,7 @@ def test_parse_cmdline(settngs_manager, tmp_path):
|
|||||||
assert normalized['tst']['test'] == 'success'
|
assert normalized['tst']['test'] == 'success'
|
||||||
|
|
||||||
|
|
||||||
def test_parse_cmdline_with_namespace(settngs_manager, tmp_path):
|
def test_parse_cmdline_with_namespace(settngs_manager):
|
||||||
settngs_manager.add_group('tst', lambda parser: parser.add_setting('--test', default='hello', cmdline=True))
|
settngs_manager.add_group('tst', lambda parser: parser.add_setting('--test', default='hello', cmdline=True))
|
||||||
|
|
||||||
normalized, _ = settngs_manager.parse_cmdline(
|
normalized, _ = settngs_manager.parse_cmdline(
|
||||||
@ -286,6 +287,42 @@ def test_cli_explicit_default(settngs_manager, tmp_path):
|
|||||||
assert normalized['tst']['test'] == 'success'
|
assert normalized['tst']['test'] == 'success'
|
||||||
|
|
||||||
|
|
||||||
|
def test_adding_to_existing_group(settngs_manager, tmp_path):
|
||||||
|
def default_to_regular(d):
|
||||||
|
if isinstance(d, defaultdict):
|
||||||
|
d = {k: default_to_regular(v) for k, v in d.items()}
|
||||||
|
return d
|
||||||
|
settngs_manager.add_group('tst', lambda parser: parser.add_setting('--test', default='success'))
|
||||||
|
settngs_manager.add_group('tst', lambda parser: parser.add_setting('--test2', default='success'))
|
||||||
|
|
||||||
|
def tst(parser):
|
||||||
|
parser.add_setting('--test', default='success')
|
||||||
|
parser.add_setting('--test2', default='success')
|
||||||
|
|
||||||
|
settngs_manager2 = settngs.Manager()
|
||||||
|
settngs_manager2.add_group('tst', tst)
|
||||||
|
|
||||||
|
assert default_to_regular(settngs_manager.definitions) == default_to_regular(settngs_manager2.definitions)
|
||||||
|
|
||||||
|
|
||||||
|
def test_adding_to_existing_persistent_group(settngs_manager, tmp_path):
|
||||||
|
def default_to_regular(d):
|
||||||
|
if isinstance(d, defaultdict):
|
||||||
|
d = {k: default_to_regular(v) for k, v in d.items()}
|
||||||
|
return d
|
||||||
|
settngs_manager.add_persistent_group('tst', lambda parser: parser.add_setting('--test', default='success'))
|
||||||
|
settngs_manager.add_persistent_group('tst', lambda parser: parser.add_setting('--test2', default='success'))
|
||||||
|
|
||||||
|
def tst(parser):
|
||||||
|
parser.add_setting('--test', default='success')
|
||||||
|
parser.add_setting('--test2', default='success')
|
||||||
|
|
||||||
|
settngs_manager2 = settngs.Manager()
|
||||||
|
settngs_manager2.add_persistent_group('tst', tst)
|
||||||
|
|
||||||
|
assert default_to_regular(settngs_manager.definitions) == default_to_regular(settngs_manager2.definitions)
|
||||||
|
|
||||||
|
|
||||||
def test_example(capsys, tmp_path, monkeypatch):
|
def test_example(capsys, tmp_path, monkeypatch):
|
||||||
monkeypatch.chdir(tmp_path)
|
monkeypatch.chdir(tmp_path)
|
||||||
settings_file = tmp_path / 'settings.json'
|
settings_file = tmp_path / 'settings.json'
|
||||||
|
Reference in New Issue
Block a user