Skip to content

Commit

Permalink
add ability to compare values other than Choice
Browse files Browse the repository at this point in the history
  • Loading branch information
goktug97 committed Apr 15, 2021
1 parent 51c32b2 commit caa523e
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 47 deletions.
97 changes: 54 additions & 43 deletions pipcs/pipcs.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,53 @@ class required:
Required = Union[Type[required], T]


class Comparison():
def __init__(self, comp):
self.comp = comp

def __and__(self, other):
return Comparison(lambda config: self.comp(config) and other.comp(config))

def __or__(self, other):
return Comparison(lambda config: self.comp(config) or other.comp(config))

def __invert__(self):
return Comparison(lambda config: not self.comp(config))

def __call__(self, config):
return self.comp(config)


class Comparable():
def __init__(self, data):
self.data = data

def _get_value(self, config):
value = config.get_value(self._name)
if isinstance(value, Comparable):
return self.data
else:
return value

def __eq__(self, other):
return Comparison(lambda config: self._get_value(config) == other)

def __lt__(self, other):
return Comparison(lambda config: self._get_value(config) < other)

def __le__(self, other):
return Comparison(lambda config: self._get_value(config) <= other)

def __ne__(self, other):
return Comparison(lambda config: self._get_value(config) != other)

def __gt__(self, other):
return Comparison(lambda config: self._get_value(config) > other)

def __ge__(self, other):
return Comparison(lambda config: self._get_value(config) >= other)


class Condition(Generic[T]):
"""Mark a variable as valid, only if the condition is hold. It is used combined with :class:`pipcs.Choices`.
Expand Down Expand Up @@ -81,24 +128,12 @@ class UserExample():
print(user_config.example.to_dict())
# {'variable': 1}
"""
def __init__(self, value: T, comp):
def __init__(self, value: T, comp: Comparison):
self.value: T = value
self.comp = comp

def _compare(self, config):
return self.comp(config)

def __and__(self, other):
return Condition(self.value, lambda config: self.comp(config) and other.comp(config))

def __or__(self, other):
return Condition(self.value, lambda config: self.comp(config) or other.comp(config))

def __invert__(self):
return Condition(self.value, lambda config: not self.comp(config))


class Choices(Generic[T]):
class Choices(Comparable, Generic[T]):
"""Specify valid choices for a variable.
:class:`pipcs.InvalidChoiceError` error will be raised when the user
tries to set the variable to a non-valid choice in the inherited configuration.
Expand Down Expand Up @@ -139,31 +174,7 @@ def __init__(self, choices: List[T], default=required):
raise InvalidChoiceError('Default value is not in choices')
self.choices: List[T] = choices
self.default: Required[T] = default

def __get_value(self, config):
value = config.get_value(self._name)
if isinstance(value, Choices):
return self.default
else:
return value

def __eq__(self, other):
return lambda config: self.__get_value(config) == other

def __lt__(self, other):
return lambda config: self.__get_value(config) < other

def __le__(self, other):
return lambda config: self.__get_value(config) <= other

def __ne__(self, other):
return lambda config: self.__get_value(config) != other

def __gt__(self, other):
return lambda config: self.__get_value(config) > other

def __ge__(self, other):
return lambda config: self.__get_value(config) >= other
super().__init__(self.default)


class Config(dict):
Expand Down Expand Up @@ -210,7 +221,7 @@ def check_value(self, key, value):
if value.default is required:
raise RequiredError(f'{key} is required!')
elif isinstance(value, Condition):
if value._compare(self):
if value.comp(self):
if value.value is required:
raise RequiredError(f'{key} is required!')
elif value is required:
Expand Down Expand Up @@ -241,7 +252,7 @@ class Example():
"""
value = dict.__getitem__(self, key)
if isinstance(value, Condition):
if value._compare(self):
if value.comp(self):
return value.value
if check:
check_value = object.__getattribute__(self, 'check_value')
Expand Down Expand Up @@ -278,7 +289,7 @@ def to_dict(self, check=False):
elif isinstance(v, Choices):
config_dict[k] = v.default
elif isinstance(v, Condition):
if v._compare(self):
if v.comp(self):
config_dict[k] = v.value
else:
config_dict[k] = v
Expand Down Expand Up @@ -316,7 +327,7 @@ def add_config(self, cls, name, check=True):
datacls = Config(datacls)
self[name] = datacls
for k, v in self[name].items():
if isinstance(v, Choices):
if isinstance(v, Comparable):
v._name = k
return self[name]

Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
long_description = f.read()

setup(name='pipcs',
version=f'1.1.3',
version=f'1.2.0',
description='pipcs is python configuration system',
author='Göktuğ Karakaşlı',
author_email='karakasligk@gmail.com',
Expand Down
6 changes: 3 additions & 3 deletions tests/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,9 @@ class Test():
conditional_variable1: Condition[Required[int]] = Condition(required, variable1 == 1)
conditional_variable2: Condition[int] = Condition(1, variable1 == 2)
conditional_variable3: Condition[Required[int]] = Condition(required, variable1 == 3)
conditional_variable4: Condition[int] = Condition(1, variable1 == 3) & Condition(1, variable2 == 1)
conditional_variable5: Condition[int] = Condition(1, variable1 == 3) | Condition(1, variable2 == 1)
conditional_variable6: Condition[int] = ~Condition(1, variable1 == 3)
conditional_variable4: Condition[int] = Condition(1, (variable1 == 3) & (variable2 == 1))
conditional_variable5: Condition[int] = Condition(1, (variable1 == 3) | (variable2 == 1))
conditional_variable6: Condition[int] = Condition(1, ~(variable1 == 3))

self.user_config1 = Config(self.config)
@self.user_config1('test')
Expand Down

0 comments on commit caa523e

Please sign in to comment.