Created
October 28, 2019 11:46
-
-
Save dkgndianko/1387538d8286dc85d7fe0ca83fcec4ac to your computer and use it in GitHub Desktop.
Dynamically generate getter methods for a repository based on the name of fields
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from typing import List, Callable, Iterator, Tuple | |
LOGICAL_SEPARATORS = ["and", "or"] | |
OPERATORS = ["lt", "gt", "not", "in", "none"] | |
OPERATORS_MAPPING = {"=": "=", "lt": "<", "gt": ">", "lte": "<=", "gte": ">=", "not": "!=", "none": "is None", | |
"is": "is"} | |
def _generate_method(method_name: str) -> Callable: | |
zip_iterator = _process_getter(method_name.split("_")) | |
def the_method(*args): | |
res = [] | |
l = len(args) | |
it = iter(args) | |
for param, operation, logical in zip_iterator: | |
try: | |
value = next(it) | |
if isinstance(value, bool): # we must base on type of param | |
operation = "is" | |
res.append(f"{param} {OPERATORS_MAPPING[operation]} {value}") | |
except StopIteration: | |
raise TypeError(f"{method_name} is missing 1 required positional argument: '{param}'") | |
return ", ".join(res) | |
return the_method | |
def _process_getter(parts: List[str]) -> Iterator[Tuple[str, str, str]]: | |
current_name = None | |
operators = [] | |
logicals = [] | |
names = [] | |
last_logical = None | |
operation = None | |
for name in parts: | |
if not current_name: | |
current_name = name | |
continue | |
if name in OPERATORS: | |
operation = name | |
elif name in LOGICAL_SEPARATORS: | |
operators.append(operation or "=") | |
logicals.append(last_logical or "and") | |
names.append(current_name) | |
last_logical = name | |
current_name = None | |
else: | |
current_name = f"{current_name}_{name}" | |
operators.append(operation or "=") | |
logicals.append(last_logical or "and") | |
names.append(current_name) | |
return zip(names, operators, logicals) | |
def test(): | |
methods = {"username_and_password": ("mouhamad", "CTSM@@Ngui"), "value_gt_and_name_not_and_age_lt": (2, "Beep", 63), "last_change_or_password_expired": ("2019-05-21", False), "age_gt_and_is_enabled_and_locked": (18, False, False)} | |
# for m in methods: | |
# r = _process_getter(m.split("_")) | |
# r = [str(e) for e in r] | |
# print(f"{m} -> {r}") | |
for m, values in methods.items(): | |
f = _generate_method(m) | |
res = f(*values) | |
print(f"{m} -> {res}") | |
if __name__ == "__main__": | |
test() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment