Compare commits
6 Commits
Author | SHA1 | Date | |
---|---|---|---|
e2ff779c30 | |||
e9d0e874f3 | |||
c9f5d57ed1 | |||
ea5be60c63 | |||
391f65c71f | |||
ba645eb7c6 |
90
.gitignore
vendored
90
.gitignore
vendored
@ -1,7 +1,85 @@
|
|||||||
*.egg-info
|
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion
|
||||||
*.py[co]
|
|
||||||
/.coverage
|
*.iml
|
||||||
/.tox
|
|
||||||
/dist
|
## Directory-based project format:
|
||||||
.vscode/
|
.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/
|
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
|
- 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.1
|
rev: v2.0.2
|
||||||
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: v1.0.1
|
rev: v1.2.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: mypy
|
- id: mypy
|
||||||
|
@ -197,7 +197,7 @@ class Setting:
|
|||||||
if dest:
|
if dest:
|
||||||
dest_name = dest
|
dest_name = dest
|
||||||
if not dest_name.isidentifier():
|
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('_')
|
internal_name = f'{prefix}_{dest_name}'.lstrip('_')
|
||||||
return internal_name, dest_name, flag
|
return internal_name, dest_name, flag
|
||||||
@ -304,10 +304,15 @@ def normalize_config(
|
|||||||
if (setting.cmdline and cmdline) or (setting.file and file):
|
if (setting.cmdline and cmdline) or (setting.file and file):
|
||||||
# Ensures the option exists with the default if not already set
|
# Ensures the option exists with the default if not already set
|
||||||
value, default = get_option(options, setting)
|
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
|
group_options[setting_name] = value
|
||||||
elif setting_name in group_options:
|
elif setting_name in group_options:
|
||||||
|
# defaults have been requested to be removed
|
||||||
del group_options[setting_name]
|
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
|
normalized[group_name] = group_options
|
||||||
return Config(normalized, definitions)
|
return Config(normalized, definitions)
|
||||||
|
|
||||||
@ -374,7 +379,7 @@ def get_namespace(config: Config[T], defaults: bool = True, persistent: bool = T
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
if isinstance(config.values, Namespace):
|
if isinstance(config.values, Namespace):
|
||||||
options, definitions = normalize_config(config)
|
options, definitions = normalize_config(config, True, True, defaults=defaults, persistent=persistent)
|
||||||
else:
|
else:
|
||||||
options, definitions = config
|
options, definitions = config
|
||||||
namespace = Namespace()
|
namespace = Namespace()
|
||||||
@ -459,7 +464,7 @@ def parse_cmdline(
|
|||||||
description: str,
|
description: str,
|
||||||
epilog: str,
|
epilog: str,
|
||||||
args: list[str] | None = None,
|
args: list[str] | None = None,
|
||||||
config: Namespace | Config[T] | None = None,
|
config: ns[T] = None,
|
||||||
) -> Config[Values]:
|
) -> Config[Values]:
|
||||||
"""
|
"""
|
||||||
Creates an `argparse.ArgumentParser` from cmdline settings in `self.definitions`.
|
Creates an `argparse.ArgumentParser` from cmdline settings in `self.definitions`.
|
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
57
setup.cfg
57
setup.cfg
@ -1,6 +1,6 @@
|
|||||||
[metadata]
|
[metadata]
|
||||||
name = settngs
|
name = settngs
|
||||||
version = 0.6.0
|
version = 0.6.3
|
||||||
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
|
||||||
@ -17,16 +17,69 @@ classifiers =
|
|||||||
Programming Language :: Python :: Implementation :: PyPy
|
Programming Language :: Python :: Implementation :: PyPy
|
||||||
|
|
||||||
[options]
|
[options]
|
||||||
py_modules = settngs
|
packages = find:
|
||||||
install_requires =
|
install_requires =
|
||||||
typing-extensions;python_version < '3.11'
|
typing-extensions;python_version < '3.11'
|
||||||
python_requires = >=3.8
|
python_requires = >=3.8
|
||||||
|
include_package_data = True
|
||||||
|
|
||||||
[options.packages.find]
|
[options.packages.find]
|
||||||
exclude =
|
exclude =
|
||||||
tests*
|
tests*
|
||||||
testing*
|
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]
|
[coverage:run]
|
||||||
plugins = covdefaults
|
plugins = covdefaults
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ def test_get_defaults(settngs_manager):
|
|||||||
assert defaults['']['test'] == 'hello'
|
assert defaults['']['test'] == 'hello'
|
||||||
|
|
||||||
|
|
||||||
def test_get_namespace(settngs_manager):
|
def test_get_defaults_namespace(settngs_manager):
|
||||||
settngs_manager.add_setting('--test', default='hello')
|
settngs_manager.add_setting('--test', default='hello')
|
||||||
defaults, _ = settngs_manager.get_namespace(settngs_manager.defaults())
|
defaults, _ = settngs_manager.get_namespace(settngs_manager.defaults())
|
||||||
assert defaults.test == 'hello'
|
assert defaults.test == 'hello'
|
||||||
@ -67,8 +67,8 @@ def test_get_namespace(settngs_manager):
|
|||||||
|
|
||||||
def test_get_namespace_with_namespace(settngs_manager):
|
def test_get_namespace_with_namespace(settngs_manager):
|
||||||
settngs_manager.add_setting('--test', default='hello')
|
settngs_manager.add_setting('--test', default='hello')
|
||||||
defaults, _ = settngs_manager.get_namespace(argparse.Namespace(test='hello'))
|
defaults, _ = settngs_manager.get_namespace(argparse.Namespace(test='success'))
|
||||||
assert defaults.test == 'hello'
|
assert defaults.test == 'success'
|
||||||
|
|
||||||
|
|
||||||
def test_get_defaults_group(settngs_manager):
|
def test_get_defaults_group(settngs_manager):
|
||||||
@ -97,6 +97,20 @@ def test_cmdline_only(settngs_manager):
|
|||||||
assert 'test2' in file_normalized['tst2']
|
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):
|
def test_normalize(settngs_manager):
|
||||||
settngs_manager.add_group('tst', lambda parser: parser.add_setting('--test', default='hello'))
|
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'))
|
settngs_manager.add_persistent_group('persistent', lambda parser: parser.add_setting('--world', default='world'))
|
||||||
@ -118,11 +132,13 @@ def test_normalize(settngs_manager):
|
|||||||
assert 'test' in normalized['tst']
|
assert 'test' in normalized['tst']
|
||||||
assert normalized['tst']['test'] == 'hello'
|
assert normalized['tst']['test'] == 'hello'
|
||||||
assert normalized['persistent']['hello'] == 'success'
|
assert normalized['persistent']['hello'] == 'success'
|
||||||
|
assert normalized['persistent']['world'] == 'world'
|
||||||
|
|
||||||
assert not hasattr(normalized_namespace, 'test')
|
assert not hasattr(normalized_namespace, 'test')
|
||||||
assert hasattr(normalized_namespace, 'tst_test')
|
assert hasattr(normalized_namespace, 'tst_test')
|
||||||
assert normalized_namespace.tst_test == 'hello'
|
assert normalized_namespace.tst_test == 'hello'
|
||||||
assert normalized_namespace.persistent_hello == 'success'
|
assert normalized_namespace.persistent_hello == 'success'
|
||||||
|
assert normalized_namespace.persistent_world == 'world'
|
||||||
|
|
||||||
|
|
||||||
def test_clean_config(settngs_manager):
|
def test_clean_config(settngs_manager):
|
||||||
@ -151,15 +167,25 @@ def test_parse_cmdline(settngs_manager):
|
|||||||
assert normalized['tst']['test'] == 'success'
|
assert normalized['tst']['test'] == 'success'
|
||||||
|
|
||||||
|
|
||||||
def test_parse_cmdline_with_namespace(settngs_manager):
|
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('--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(
|
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 'test' in normalized['tst']
|
||||||
assert normalized['tst']['test'] == 'success'
|
assert normalized['tst']['test'] == 'success'
|
||||||
|
assert normalized['tst']['test2'] == 'success'
|
||||||
|
|
||||||
|
|
||||||
def test_parse_file(settngs_manager, tmp_path):
|
def test_parse_file(settngs_manager, tmp_path):
|
||||||
|
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