Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: GuillaumeLeclerc/fastargs
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v1.1.0
Choose a base ref
...
head repository: GuillaumeLeclerc/fastargs
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: main
Choose a head ref
  • 11 commits
  • 8 files changed
  • 2 contributors

Commits on Apr 7, 2021

  1. Fix bug

    - Content of --help sections were accumulating
    GuillaumeLeclerc committed Apr 7, 2021
    Copy the full SHA
    b68a317 View commit details
  2. Bump version

    GuillaumeLeclerc committed Apr 7, 2021
    Copy the full SHA
    cb6129c View commit details

Commits on Apr 8, 2021

  1. Copy the full SHA
    90f0e8f View commit details

Commits on May 14, 2021

  1. Copy the full SHA
    58af367 View commit details
  2. Copy the full SHA
    bf2e0ac View commit details

Commits on Nov 11, 2021

  1. Update README.md

    lengstrom authored Nov 11, 2021
    Copy the full SHA
    14e9074 View commit details

Commits on Jan 29, 2022

  1. Merge pull request #17 from lengstrom/patch-1

    Update README.md
    GuillaumeLeclerc authored Jan 29, 2022
    Copy the full SHA
    b39083a View commit details

Commits on May 31, 2022

  1. Copy the full SHA
    7165663 View commit details
  2. Copy the full SHA
    5668d69 View commit details
  3. Copy the full SHA
    a598697 View commit details

Commits on Jun 29, 2022

  1. Merge pull request #19 from lengstrom/main

    made ValidationError handling more verbose
    GuillaumeLeclerc authored Jun 29, 2022
    Copy the full SHA
    53dbda2 View commit details
Showing with 84 additions and 14 deletions.
  1. +1 −1 README.md
  2. +1 −1 fastargs/__init__.py
  3. +6 −2 fastargs/config.py
  4. +21 −7 fastargs/decorators.py
  5. +2 −2 fastargs/param.py
  6. +1 −1 setup.py
  7. +25 −0 tests/test_decorators.py
  8. +27 −0 tests/test_sources.py
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -244,7 +244,7 @@ Section('optim').params(
algorithm=Param(str)
)

Section('optim.alpha').enable_if(labmda cfg: cfg['optim.algorithm'] == 'Adam').params(
Section('optim.alpha').enable_if(lambda cfg: cfg['optim.algorithm'] == 'Adam').params(
'momentum': Param(float, required=True),
'alpha': Param(float, default=1.0),
'beta': Param(float, default=1.0)
2 changes: 1 addition & 1 deletion fastargs/__init__.py
Original file line number Diff line number Diff line change
@@ -13,4 +13,4 @@
from . import validation
from . import decorators

__version__ = "1.1.0"
__version__ = "1.1.1"
8 changes: 6 additions & 2 deletions fastargs/config.py
Original file line number Diff line number Diff line change
@@ -73,8 +73,8 @@ def augment_argparse(self, parser):
previous_epilog = ""
while True:
epilog = ""
table_content = [['Name', 'Default', 'Constraint', 'Description']]
for sec_path, entries in self.sections_to_entries.items():
table_content = [['Name', 'Default', 'Constraint', 'Description']]
for path in entries:
param = self.entries[path]
if not param.section.is_enabled(self):
@@ -180,7 +180,11 @@ def __getitem__(self, path):
if value is None and not param.required:
return value

return param.validate(value)
try:
return param.validate(value)
except ValidationError as e:
print(f'Issue when typechecking argument psyh `{".".join(path)}`:')
raise e


def get(self):
28 changes: 21 additions & 7 deletions fastargs/decorators.py
Original file line number Diff line number Diff line change
@@ -23,7 +23,11 @@ def __call__(self, *args, **kwargs):
for ns, path, alias in self.arg_paths:
if ns is not None:
path = ns + path
if alias in kwargs: # User overrode this argument
continue

value = config[path]

if value is not None:
filled_args[alias] = value

@@ -38,29 +42,39 @@ def __call__(self, *args, **kwargs):
else:
raise e


def extract_function(func):
if hasattr(func, '__fastarg_wrapper'):
return getattr(func, '__fastarg_wrapper')
else:
return WrappedFunction(func)

def param(parameter, alias=None):
if isinstance(parameter, str):
parameter = tuple(parameter.split('.'))

if alias==None:
if alias is None:
alias = parameter[-1]

def wrapper(func):
if not isinstance(func, WrappedFunction):
func = WrappedFunction(func)

func = extract_function(func)

func.add_arg(parameter, alias)
return func

def result(*args, **kwargs):
return func(*args, **kwargs)

setattr(result, '__fastarg_wrapper', func)
return result

return wrapper

def section(section):
if isinstance(section, str):
section = tuple(section.split('.'))

def wrapper(func):
if not isinstance(func, WrappedFunction):
func = WrappedFunction(func)
func = extract_function(func)
func.set_section(section)
return func
return wrapper
4 changes: 2 additions & 2 deletions fastargs/param.py
Original file line number Diff line number Diff line change
@@ -12,7 +12,6 @@ def __init__(self, checker, desc='', default=None, required=False,
self.section = None

def __str__(self):

result = ""

if self.required:
@@ -37,5 +36,6 @@ def validate(self, value):
try:
return self.checker.check(value)
except Exception:
raise ValidationError()
msg = f'value `{value}` does not fit checker for `{self.checker.help()}`'
raise ValidationError(msg)

2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
@@ -17,7 +17,7 @@
packages=find_packages('.'),
# Start with a small number and increase it with
# every change you make https://semver.org
version='1.1.0',
version='1.1.1',
# Chose a license from here: https: //
# help.github.com / articles / licensing - a -
# repository. For example: MIT
25 changes: 25 additions & 0 deletions tests/test_decorators.py
Original file line number Diff line number Diff line change
@@ -125,6 +125,31 @@ def compute(p1, p2):

self.assertEqual(compute(), 111)

def test_class_constructor(self):
Section('sec1').params(
p1=Param(int),
)

class TestClass:

@param('sec1.p1', 'value')
def __init__(self, value):
self.value = value

get_current_config().collect({
'sec1.p1': 42,
})

self.assertEqual(TestClass().value, 42)


def test_do_not_complain_not_missing_args(self):
@param('sec1.p1')
def compute(p1):
return p1

self.assertEqual(compute(p1=17), 17)


if __name__ == '__main__':
unittest.main()
27 changes: 27 additions & 0 deletions tests/test_sources.py
Original file line number Diff line number Diff line change
@@ -262,6 +262,33 @@ def test_flag(self):
self.assertTrue(cfg['a.a'])
self.assertFalse(cfg['a.b'])

def test_duplicate_sections(self):
Section('a').params(
a=Param(int)
)
Section('b').params(
b=Param(int)
)

cfg = get_current_config()
parser = argparse.ArgumentParser(description='Test lib')

def fake_exit(*args, **kwargs):
pass

fakeio = io.StringIO("")

with patch('sys.argv', ['pp', '--help']):
with patch('sys.exit', fake_exit):
with patch('sys.stdout', fakeio):
cfg.augment_argparse(parser)
cfg.collect_argparse_args(parser)

output = fakeio.getvalue()

self.assertEqual(output.count('a.a'), 1)
self.assertEqual(output.count('b.b'), 1)


if __name__ == '__main__':
unittest.main()