From 15c53d39b0167eaf624fb09fa4b423b4924b77fc Mon Sep 17 00:00:00 2001 From: Tom Gross Date: Wed, 19 Feb 2020 21:56:55 +0100 Subject: [PATCH] Add validator for all required parameters --- CHANGES.rst | 4 ++-- src/pcloud/tests/test_validate.py | 27 ++++++++++++++++++++++----- src/pcloud/validate.py | 23 ++++++++++++----------- test_requirements.txt | 1 + 4 files changed, 37 insertions(+), 18 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index e58ce24..b8f0e23 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -5,8 +5,8 @@ Changelog 1.0a7 (unreleased) ------------------ -- Nothing changed yet. - +- Consistently use MIT licences + [tomgross] 1.0a6 (2019-01-18) ------------------ diff --git a/src/pcloud/tests/test_validate.py b/src/pcloud/tests/test_validate.py index ccff5b9..ef08a16 100644 --- a/src/pcloud/tests/test_validate.py +++ b/src/pcloud/tests/test_validate.py @@ -1,20 +1,37 @@ import pytest from pcloud.validate import RequiredParameterCheck +from pcloud.validate import MODE_AND @RequiredParameterCheck(('path', 'folderid')) -def foo(self, path=None, folderid=None, bar=None): - return (path, folderid, bar) +def foo(path=None, folderid=None, bar=None): + return path, folderid, bar + + +@RequiredParameterCheck(('path', 'folderid'), mode=MODE_AND) +def foo_all(path=None, folderid=None, bar=None): + return path, folderid, bar class TestPathIdentifier(object): def test_validiate_path(self): - assert foo(None, path='/', bar='x') == ('/', None, 'x') + assert foo(path='/', bar='x') == ('/', None, 'x') def test_validiate_folderid(self): - assert foo(None, folderid='0') == (None, '0', None) + assert foo(folderid='0') == (None, '0', None) def test_validiate_nothing(self): with pytest.raises(ValueError): - foo(None, bar='something') + foo(bar='something') + + def test_validiate_all_path(self): + with pytest.raises(ValueError): + foo_all(path='/', bar='x') + + def test_validiate_all_folderid(self): + with pytest.raises(ValueError): + foo_all(folderid='0') == (None, '0', None) + + def test_validiate_all(self): + foo_all(folderid='0', path='/') == ('/', '0', None) diff --git a/src/pcloud/validate.py b/src/pcloud/validate.py index b192814..c09ad72 100644 --- a/src/pcloud/validate.py +++ b/src/pcloud/validate.py @@ -1,26 +1,27 @@ """ Validators and decorators """ +MODE_OR = 0 +MODE_AND = 1 + class RequiredParameterCheck(object): - """ A decorator that checks function parameter + """ A decorator that checks if at least on named parameter is present """ - def __init__(self, required): - self.required = required + def __init__(self, required, mode=MODE_OR): + self.required = sorted(required) + self.mode = mode def __call__(self, func): def wrapper(*args, **kwargs): - found_paramater = False - for req in self.required: - if req in kwargs: - found_paramater = True - break - if found_paramater: + found_paramater = sorted([req for req in self.required if req in kwargs]) + if self.mode == MODE_OR and found_paramater: + return func(*args, **kwargs) + elif self.mode == MODE_AND and found_paramater == self.required: return func(*args, **kwargs) else: - raise ValueError('One required parameter `%s` is missing', - ', '.join(self.required)) + raise ValueError(f"One required parameter `{ ', '.join(self.required)}` is missing: {found_paramater}") wrapper.__name__ = func.__name__ wrapper.__dict__.update(func.__dict__) wrapper.__doc__ = func.__doc__ diff --git a/test_requirements.txt b/test_requirements.txt index ca68ec5..95be7a6 100644 --- a/test_requirements.txt +++ b/test_requirements.txt @@ -2,3 +2,4 @@ pytest >= 2.8 tox wheel flake8 +fs