Compare commits
14 Commits
Author | SHA1 | Date | |
---|---|---|---|
78ac274e31 | |||
05c2196fcf | |||
e2ff779c30 | |||
e9d0e874f3 | |||
c9f5d57ed1 | |||
ea5be60c63 | |||
391f65c71f | |||
ba645eb7c6 | |||
69800f01b6 | |||
b2eaa12a0e | |||
fe7c821605 | |||
d07cf9949b | |||
41cf2dc7cd | |||
577b43c4e8 |
2
.github/workflows/build.yaml
vendored
2
.github/workflows/build.yaml
vendored
@ -33,7 +33,7 @@ jobs:
|
||||
|
||||
- name: Build and install wheel
|
||||
run: |
|
||||
python -m build
|
||||
tox run -m build
|
||||
python -m pip install dist/*.whl
|
||||
|
||||
- name: tox
|
||||
|
90
.gitignore
vendored
90
.gitignore
vendored
@ -1,7 +1,85 @@
|
||||
*.egg-info
|
||||
*.py[co]
|
||||
/.coverage
|
||||
/.tox
|
||||
/dist
|
||||
.vscode/
|
||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion
|
||||
|
||||
*.iml
|
||||
|
||||
## Directory-based project format:
|
||||
.idea/
|
||||
|
||||
### Other editors
|
||||
.*.swp
|
||||
nbproject/
|
||||
.vscode
|
||||
|
||||
*.exe
|
||||
*.zip
|
||||
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
share/python-wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
MANIFEST
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.nox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
*.py,cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
cover/
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
dmypy.json
|
||||
|
||||
# Pyre type checker
|
||||
.pyre/
|
||||
|
||||
# pytype static type analyzer
|
||||
.pytype/
|
||||
|
||||
# for testing
|
||||
temp/
|
||||
tmp/
|
||||
|
@ -33,7 +33,7 @@ repos:
|
||||
- id: pyupgrade
|
||||
args: [--py38-plus]
|
||||
- repo: https://github.com/pre-commit/mirrors-autopep8
|
||||
rev: v2.0.0
|
||||
rev: v2.0.2
|
||||
hooks:
|
||||
- id: autopep8
|
||||
- repo: https://github.com/PyCQA/flake8
|
||||
@ -42,6 +42,6 @@ repos:
|
||||
- id: flake8
|
||||
additional_dependencies: [flake8-encodings, flake8-warnings, flake8-builtins, flake8-length, flake8-print]
|
||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||
rev: v0.991
|
||||
rev: v1.2.0
|
||||
hooks:
|
||||
- id: mypy
|
||||
|
6
pyproject.toml
Normal file
6
pyproject.toml
Normal file
@ -0,0 +1,6 @@
|
||||
[build-system]
|
||||
requires = ["setuptools>=42", "wheel", "setuptools_scm[toml]>=3.4"]
|
||||
build-backend = "setuptools.build_meta"
|
||||
|
||||
[tool.setuptools_scm]
|
||||
local_scheme = "no-local-version"
|
@ -93,11 +93,35 @@ class Setting:
|
||||
metavar: str | None = None,
|
||||
dest: str | None = None,
|
||||
# ComicTagger
|
||||
display_name: str = '',
|
||||
cmdline: bool = True,
|
||||
file: bool = True,
|
||||
group: str = '',
|
||||
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:
|
||||
raise ValueError('names must be specified')
|
||||
# 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.group = group
|
||||
self.exclusive = exclusive
|
||||
self.display_name = display_name or dest
|
||||
|
||||
self.argparse_kwargs = {
|
||||
'action': action,
|
||||
@ -150,6 +175,11 @@ class Setting:
|
||||
def __repr__(self) -> str: # pragma: no cover
|
||||
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]:
|
||||
dest_name = None
|
||||
flag = False
|
||||
@ -167,7 +197,7 @@ class Setting:
|
||||
if dest:
|
||||
dest_name = dest
|
||||
if not dest_name.isidentifier():
|
||||
raise Exception('Cannot use {dest_name} in a namespace')
|
||||
raise Exception(f'Cannot use {dest_name} in a namespace')
|
||||
|
||||
internal_name = f'{prefix}_{dest_name}'.lstrip('_')
|
||||
return internal_name, dest_name, flag
|
||||
@ -201,7 +231,7 @@ if TYPE_CHECKING:
|
||||
|
||||
|
||||
def sanitize_name(name: str) -> str:
|
||||
return re.sub('[' + re.escape(' -_,.!@#$%^&*(){}[]\',."<>;:') + ']+', '-', name).strip('-')
|
||||
return re.sub('[' + re.escape(' -_,.!@#$%^&*(){}[]\',."<>;:') + ']+', '_', name).strip('_')
|
||||
|
||||
|
||||
def get_option(options: Values | Namespace, setting: Setting) -> tuple[Any, bool]:
|
||||
@ -274,10 +304,15 @@ def normalize_config(
|
||||
if (setting.cmdline and cmdline) or (setting.file and file):
|
||||
# Ensures the option exists with the default if not already set
|
||||
value, default = get_option(options, setting)
|
||||
if not default or default and defaults:
|
||||
if not default or (default and defaults):
|
||||
# User has set a custom value or has requested the default value
|
||||
group_options[setting_name] = value
|
||||
elif setting_name in group_options:
|
||||
# defaults have been requested to be removed
|
||||
del group_options[setting_name]
|
||||
elif setting_name in group_options:
|
||||
# Setting type (file or cmdline) has not been requested and should be removed for persistent groups
|
||||
del group_options[setting_name]
|
||||
normalized[group_name] = group_options
|
||||
return Config(normalized, definitions)
|
||||
|
||||
@ -344,7 +379,7 @@ def get_namespace(config: Config[T], defaults: bool = True, persistent: bool = T
|
||||
"""
|
||||
|
||||
if isinstance(config.values, Namespace):
|
||||
options, definitions = normalize_config(config)
|
||||
options, definitions = normalize_config(config, True, True, defaults=defaults, persistent=persistent)
|
||||
else:
|
||||
options, definitions = config
|
||||
namespace = Namespace()
|
||||
@ -429,7 +464,7 @@ def parse_cmdline(
|
||||
description: str,
|
||||
epilog: str,
|
||||
args: list[str] | None = None,
|
||||
config: Namespace | Config[T] | None = None,
|
||||
config: ns[T] = None,
|
||||
) -> Config[Values]:
|
||||
"""
|
||||
Creates an `argparse.ArgumentParser` from cmdline settings in `self.definitions`.
|
||||
@ -496,13 +531,15 @@ class Manager:
|
||||
|
||||
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:
|
||||
name: The name of the group to define
|
||||
group: A function that registers individual options using :meth:`add_setting`
|
||||
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.exclusive_group = exclusive_group
|
||||
group(self)
|
||||
@ -511,16 +548,23 @@ class Manager:
|
||||
|
||||
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:
|
||||
name: The name of the group to define
|
||||
group: A function that registers individual options using :meth:`add_setting`
|
||||
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.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)
|
||||
self.current_group_name = ''
|
||||
self.exclusive_group = False
|
6
settngs/__main__.py
Normal file
6
settngs/__main__.py
Normal file
@ -0,0 +1,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from settngs import _main
|
||||
|
||||
if __name__ == '__main__':
|
||||
_main()
|
0
settngs/py.typed
Normal file
0
settngs/py.typed
Normal file
58
setup.cfg
58
setup.cfg
@ -1,6 +1,5 @@
|
||||
[metadata]
|
||||
name = settngs
|
||||
version = 0.4.0
|
||||
description = A library for managing settings
|
||||
long_description = file: README.md
|
||||
long_description_content_type = text/markdown
|
||||
@ -17,16 +16,69 @@ classifiers =
|
||||
Programming Language :: Python :: Implementation :: PyPy
|
||||
|
||||
[options]
|
||||
py_modules = settngs
|
||||
packages = find:
|
||||
install_requires =
|
||||
typing-extensions;python_version < '3.11'
|
||||
typing-extensions>=4.3.0;python_version < '3.11'
|
||||
python_requires = >=3.8
|
||||
include_package_data = True
|
||||
|
||||
[options.packages.find]
|
||||
exclude =
|
||||
tests*
|
||||
testing*
|
||||
|
||||
[options.package_data]
|
||||
settngs = py.typed
|
||||
|
||||
[tox:tox]
|
||||
envlist = py3.8,py3.9,py3.10,py3.11,pypy3
|
||||
|
||||
[testenv]
|
||||
deps = -rrequirements-dev.txt
|
||||
commands =
|
||||
coverage erase
|
||||
coverage run -m pytest {posargs:tests}
|
||||
coverage report
|
||||
|
||||
[testenv:wheel]
|
||||
description = Generate wheel and tar.gz
|
||||
labels =
|
||||
release
|
||||
build
|
||||
skip_install = true
|
||||
deps =
|
||||
build
|
||||
commands_pre =
|
||||
-python -c 'import shutil,pathlib; \
|
||||
shutil.rmtree("./build/", ignore_errors=True); \
|
||||
shutil.rmtree("./dist/", ignore_errors=True)'
|
||||
commands =
|
||||
python -m build
|
||||
|
||||
[testenv:pypi-upload]
|
||||
description = Upload wheel to PyPi
|
||||
platform = Linux
|
||||
labels =
|
||||
release
|
||||
skip_install = true
|
||||
depends = wheel
|
||||
deps =
|
||||
twine
|
||||
passenv =
|
||||
TWINE_*
|
||||
setenv =
|
||||
TWINE_NON_INTERACTIVE=true
|
||||
commands =
|
||||
python -m twine upload dist/*.whl dist/*.tar.gz
|
||||
|
||||
[pep8]
|
||||
ignore = E265,E501
|
||||
max_line_length = 120
|
||||
|
||||
[flake8]
|
||||
extend-ignore = E501, A003
|
||||
max_line_length = 120
|
||||
|
||||
[coverage:run]
|
||||
plugins = covdefaults
|
||||
|
||||
|
@ -64,6 +64,45 @@ example: list[tuple[list[str], str, str]] = [
|
||||
),
|
||||
]
|
||||
success = [
|
||||
(
|
||||
(
|
||||
('--test-setting',),
|
||||
dict(
|
||||
group='tst',
|
||||
),
|
||||
), # Equivalent to Setting("--test-setting", group="tst")
|
||||
{
|
||||
'action': None,
|
||||
'choices': None,
|
||||
'cmdline': True,
|
||||
'const': None,
|
||||
'default': None,
|
||||
'dest': 'test_setting', # dest is calculated by Setting and is not used by argparse
|
||||
'display_name': 'test_setting', # defaults to dest
|
||||
'exclusive': False,
|
||||
'file': True,
|
||||
'group': 'tst',
|
||||
'help': None,
|
||||
'internal_name': 'tst_test_setting', # Should almost always be "{group}_{dest}"
|
||||
'metavar': 'TEST_SETTING', # Set manually so argparse doesn't use TST_TEST
|
||||
'nargs': None,
|
||||
'required': None,
|
||||
'type': None,
|
||||
'argparse_args': ('--test-setting',), # *args actually sent to argparse
|
||||
'argparse_kwargs': {
|
||||
'action': None,
|
||||
'choices': None,
|
||||
'const': None,
|
||||
'default': None,
|
||||
'dest': 'tst_test_setting',
|
||||
'help': None,
|
||||
'metavar': 'TEST_SETTING',
|
||||
'nargs': None,
|
||||
'required': None,
|
||||
'type': None,
|
||||
}, # Non-None **kwargs sent to argparse
|
||||
},
|
||||
),
|
||||
(
|
||||
(
|
||||
('--test',),
|
||||
@ -71,7 +110,7 @@ success = [
|
||||
group='tst',
|
||||
dest='testing',
|
||||
),
|
||||
), # Equivalent to Setting("--test", group="tst")
|
||||
), # Equivalent to Setting("--test", group="tst", dest="testing")
|
||||
{
|
||||
'action': None,
|
||||
'choices': None,
|
||||
@ -79,6 +118,7 @@ success = [
|
||||
'const': None,
|
||||
'default': None,
|
||||
'dest': 'testing', # dest is calculated by Setting and is not used by argparse
|
||||
'display_name': 'testing', # defaults to dest
|
||||
'exclusive': False,
|
||||
'file': True,
|
||||
'group': 'tst',
|
||||
@ -117,6 +157,7 @@ success = [
|
||||
'const': None,
|
||||
'default': None,
|
||||
'dest': 'test', # dest is calculated by Setting and is not used by argparse
|
||||
'display_name': 'test', # defaults to dest
|
||||
'exclusive': False,
|
||||
'file': True,
|
||||
'group': 'tst',
|
||||
@ -156,6 +197,7 @@ success = [
|
||||
'const': None,
|
||||
'default': None,
|
||||
'dest': 'test', # dest is calculated by Setting and is not used by argparse
|
||||
'display_name': 'test', # defaults to dest
|
||||
'exclusive': False,
|
||||
'file': True,
|
||||
'group': 'tst',
|
||||
@ -194,6 +236,7 @@ success = [
|
||||
'const': None,
|
||||
'default': None,
|
||||
'dest': 'test',
|
||||
'display_name': 'test', # defaults to dest
|
||||
'exclusive': False,
|
||||
'file': True,
|
||||
'group': 'tst',
|
||||
@ -232,6 +275,7 @@ success = [
|
||||
'const': None,
|
||||
'default': None,
|
||||
'dest': 'test',
|
||||
'display_name': 'test', # defaults to dest
|
||||
'exclusive': False,
|
||||
'file': True,
|
||||
'group': 'tst',
|
||||
@ -268,6 +312,7 @@ success = [
|
||||
'const': None,
|
||||
'default': None,
|
||||
'dest': 'test',
|
||||
'display_name': 'test', # defaults to dest
|
||||
'exclusive': False,
|
||||
'file': True,
|
||||
'group': '',
|
||||
|
@ -2,6 +2,7 @@ from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
from collections import defaultdict
|
||||
|
||||
import pytest
|
||||
|
||||
@ -58,7 +59,7 @@ def test_get_defaults(settngs_manager):
|
||||
assert defaults['']['test'] == 'hello'
|
||||
|
||||
|
||||
def test_get_namespace(settngs_manager):
|
||||
def test_get_defaults_namespace(settngs_manager):
|
||||
settngs_manager.add_setting('--test', default='hello')
|
||||
defaults, _ = settngs_manager.get_namespace(settngs_manager.defaults())
|
||||
assert defaults.test == 'hello'
|
||||
@ -66,8 +67,8 @@ def test_get_namespace(settngs_manager):
|
||||
|
||||
def test_get_namespace_with_namespace(settngs_manager):
|
||||
settngs_manager.add_setting('--test', default='hello')
|
||||
defaults, _ = settngs_manager.get_namespace(argparse.Namespace(test='hello'))
|
||||
assert defaults.test == 'hello'
|
||||
defaults, _ = settngs_manager.get_namespace(argparse.Namespace(test='success'))
|
||||
assert defaults.test == 'success'
|
||||
|
||||
|
||||
def test_get_defaults_group(settngs_manager):
|
||||
@ -96,6 +97,20 @@ def test_cmdline_only(settngs_manager):
|
||||
assert 'test2' in file_normalized['tst2']
|
||||
|
||||
|
||||
def test_cmdline_only_persistent_group(settngs_manager):
|
||||
settngs_manager.add_persistent_group('tst', lambda parser: parser.add_setting('--test', default='hello', file=False))
|
||||
settngs_manager.add_group('tst2', lambda parser: parser.add_setting('--test2', default='hello', cmdline=False))
|
||||
|
||||
file_normalized, _ = settngs_manager.normalize_config(settngs_manager.defaults(), file=True)
|
||||
cmdline_normalized, _ = settngs_manager.normalize_config(settngs_manager.defaults(), cmdline=True)
|
||||
|
||||
assert 'test' in cmdline_normalized['tst']
|
||||
assert 'test2' not in cmdline_normalized['tst2']
|
||||
|
||||
assert 'test' not in file_normalized['tst']
|
||||
assert 'test2' in file_normalized['tst2']
|
||||
|
||||
|
||||
def test_normalize(settngs_manager):
|
||||
settngs_manager.add_group('tst', lambda parser: parser.add_setting('--test', default='hello'))
|
||||
settngs_manager.add_persistent_group('persistent', lambda parser: parser.add_setting('--world', default='world'))
|
||||
@ -117,11 +132,13 @@ def test_normalize(settngs_manager):
|
||||
assert 'test' in normalized['tst']
|
||||
assert normalized['tst']['test'] == 'hello'
|
||||
assert normalized['persistent']['hello'] == 'success'
|
||||
assert normalized['persistent']['world'] == 'world'
|
||||
|
||||
assert not hasattr(normalized_namespace, 'test')
|
||||
assert hasattr(normalized_namespace, 'tst_test')
|
||||
assert normalized_namespace.tst_test == 'hello'
|
||||
assert normalized_namespace.persistent_hello == 'success'
|
||||
assert normalized_namespace.persistent_world == 'world'
|
||||
|
||||
|
||||
def test_clean_config(settngs_manager):
|
||||
@ -141,7 +158,7 @@ def test_clean_config(settngs_manager):
|
||||
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))
|
||||
|
||||
normalized, _ = settngs_manager.parse_cmdline(['--test', 'success'])
|
||||
@ -150,15 +167,25 @@ def test_parse_cmdline(settngs_manager, tmp_path):
|
||||
assert normalized['tst']['test'] == 'success'
|
||||
|
||||
|
||||
def test_parse_cmdline_with_namespace(settngs_manager, tmp_path):
|
||||
namespaces = (
|
||||
lambda definitions: settngs.Config({'tst': {'test': 'fail', 'test2': 'success'}}, definitions),
|
||||
lambda definitions: settngs.Config(argparse.Namespace(tst_test='fail', tst_test2='success'), definitions),
|
||||
lambda definitions: argparse.Namespace(tst_test='fail', tst_test2='success'),
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('ns', namespaces)
|
||||
def test_parse_cmdline_with_namespace(settngs_manager, ns):
|
||||
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('--test2', default='fail', cmdline=True))
|
||||
|
||||
normalized, _ = settngs_manager.parse_cmdline(
|
||||
['--test', 'success'], namespace=settngs.Config({'tst': {'test': 'fail'}}, settngs_manager.definitions),
|
||||
['--test', 'success'], namespace=ns(settngs_manager.definitions),
|
||||
)
|
||||
|
||||
assert 'test' in normalized['tst']
|
||||
assert normalized['tst']['test'] == 'success'
|
||||
assert normalized['tst']['test2'] == 'success'
|
||||
|
||||
|
||||
def test_parse_file(settngs_manager, tmp_path):
|
||||
@ -286,6 +313,42 @@ def test_cli_explicit_default(settngs_manager, tmp_path):
|
||||
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):
|
||||
monkeypatch.chdir(tmp_path)
|
||||
settings_file = tmp_path / 'settings.json'
|
||||
|
17
tox.ini
17
tox.ini
@ -1,17 +0,0 @@
|
||||
[tox]
|
||||
envlist = py3.8,py3.9,py3.10,py3.11,pypy3
|
||||
|
||||
[testenv]
|
||||
deps = -rrequirements-dev.txt
|
||||
commands =
|
||||
coverage erase
|
||||
coverage run -m pytest {posargs:tests}
|
||||
coverage report
|
||||
|
||||
[pep8]
|
||||
ignore = E265,E501
|
||||
max_line_length = 120
|
||||
|
||||
[flake8]
|
||||
extend-ignore = E501, A003
|
||||
max_line_length = 120
|
Reference in New Issue
Block a user