-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #28 from 201st-Luka/structure-rework
Structure rework
- Loading branch information
Showing
73 changed files
with
1,011 additions
and
965 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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
This file contains 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
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
from abc import ABC | ||
from typing import Any | ||
|
||
from ...exceptions import RequestNotDone, MISSING | ||
|
||
|
||
class BaseModel(ABC): | ||
def __new__(cls, data=None): | ||
if data is MISSING: | ||
return MISSING | ||
return super().__new__(cls) | ||
|
||
def __init__(self, data=None): | ||
if data is not None: | ||
self._data = data | ||
return | ||
|
||
def to_dict(self): | ||
return self._data | ||
|
||
def _get_properties(self): | ||
if isinstance(self._data, dict): | ||
return {name: prop.__get__(self) for name, prop in vars(type(self)).items() if isinstance(prop, property)} | ||
return self._data | ||
|
||
def _get_data(self, item): | ||
if self._data is None: | ||
return None | ||
if self._data is MISSING: | ||
raise RequestNotDone | ||
if item in self._data: | ||
return self._data[item] | ||
else: | ||
return MISSING | ||
|
||
def __str__(self): | ||
if self._data is MISSING: | ||
return f"{self.__class__.__name__}(RequestNotDone)" | ||
return f"{self.__class__.__name__}()" | ||
|
||
def __repr__(self): | ||
return (f"{self.__class__.__name__}" | ||
f"({', '.join(('='.join((key, str(value))) for key, value in self._get_properties().items()))})") | ||
|
||
|
||
class IterBaseModel(ABC): | ||
_iter_rtype: Any | ||
|
||
def __new__(cls, data): | ||
if data is MISSING: | ||
return MISSING | ||
return super().__new__(cls) | ||
|
||
def __init__(self, data): | ||
self._data = data | ||
self._len = len(self._data) if self._data is not None else None | ||
return | ||
|
||
def to_dict_list(self): | ||
return self._data | ||
|
||
def __len__(self): | ||
if self._len is None and self._data is not None: | ||
self._len = len(self._data) | ||
return self._len | ||
|
||
def __getitem__(self, item): | ||
if self._data is MISSING: | ||
raise RequestNotDone | ||
if self._data is None: | ||
return None | ||
if isinstance(item, int): | ||
return self._iter_rtype(self._data[item]) | ||
if isinstance(item, slice): | ||
return (self._iter_rtype(self._data[i]) for i in range(*item.indices(len(self._data)))) | ||
raise NotImplementedError(f"there is no implementation for type {item.__class__.__name__} in " | ||
f"{self.__class__.__name__}.__getitem__()") | ||
|
||
def __iter__(self): | ||
self._iter = iter(self._data) | ||
return self | ||
|
||
def __next__(self): | ||
return self._iter_rtype(next(self._iter)) | ||
|
||
def __contains__(self, item): | ||
if isinstance(item, (self._iter_rtype, str)): | ||
for item_ in self: | ||
if item_ == item: | ||
return True | ||
return False | ||
return NotImplemented | ||
|
||
def __str__(self): | ||
return f"{self.__class__.__name__}()" | ||
|
||
def __repr__(self): | ||
return f"{self.__class__.__name__}(len={self._len}, type={self._iter_rtype.__name__}, {list(self)})" | ||
|
||
|
||
|
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
""" | ||
abstract base classes for the API models | ||
""" | ||
|
||
|
||
from typing import Any, Generator, Iterator | ||
|
||
from ...exceptions import MISSING, Missing | ||
|
||
|
||
class BaseModel: | ||
""" | ||
base model | ||
this model is a base for all other ClashOfClans API response models | ||
can be inherited from | ||
""" | ||
|
||
def __new__(cls, data: Missing | dict = None) -> BaseModel: | ||
... | ||
|
||
def __init__(self, data: Missing | dict = None) -> None: | ||
""" | ||
initialisation of the base model | ||
:param data: the data dictionary, None or MISSING | ||
:return: None | ||
:rtype: None | ||
""" | ||
self._data = data | ||
|
||
def to_dict(self) -> None | Missing | dict: | ||
""" | ||
method that returns the response as a dict | ||
:return: response as a dict | ||
:rtype: dict | None | Missing | ||
""" | ||
... | ||
|
||
def _get_properties(self) -> None | Missing | dict: | ||
""" | ||
protected method that returns a dict of the properties of a class (also works with inherited classes) | ||
or None or MISSING if the data is not defined | ||
key: name of the property | ||
value: value of the property | ||
:return: dict of properties | ||
:rtype: dict | ||
""" | ||
... | ||
|
||
def _get_data(self, item: str) -> None | Missing | dict | list | int | str | float | bool: | ||
""" | ||
getter for the data class attribute that handles errors if the data is not defined | ||
:param item: the key of the dict item | ||
:type item: str | ||
:return: the value of the key or MISSING | ||
:rtype: dict | list | int | str | float | bool | None | MISSING | ||
:raises RequestNotDone: if the data is not defined (MISSING) | ||
""" | ||
... | ||
|
||
def __str__(self) -> str: | ||
... | ||
|
||
def __repr__(self) -> str: | ||
... | ||
|
||
|
||
class IterBaseModel: | ||
""" | ||
iterative base model | ||
this model is an iterative base model for the ClashOfClans API response models | ||
can be inherited from | ||
:ivar _len: length of the iterative data | ||
:type _len: int | ||
:ivar _data: a list of dicts containing the data | ||
:type _data: list[dict] | None | ||
""" | ||
|
||
_iter_rtype: Any = Any | ||
|
||
def __init__(self, data: list[dict] | None) -> None: | ||
""" | ||
initialisation of the iterative base model | ||
:param data: a list of dicts containing the data | ||
:type data: list[dict] | None | ||
:return: None | ||
:rtype: None | ||
""" | ||
|
||
self._data = data | ||
if self._data is not None: | ||
self._len = len(self._data) | ||
|
||
def to_dict_list(self) -> list[dict] | None | MISSING: | ||
""" | ||
method that returns the response as a list of dicts | ||
:return: response as a list of dicts | ||
:rtype: list[dict] | None | Missing | ||
""" | ||
... | ||
|
||
def __len__(self) -> int: | ||
... | ||
|
||
def __getitem__(self, item: int | slice) -> MISSING | Generator | _iter_rtype: | ||
... | ||
|
||
def __iter__(self) -> Iterator[_iter_rtype]: | ||
self._iter = iter(self._data) | ||
... | ||
|
||
def __next__(self): | ||
... | ||
|
||
def __contains__(self, item) -> bool: | ||
... | ||
|
||
def __str__(self) -> str: | ||
... | ||
|
||
def __repr__(self) -> str: | ||
... | ||
|
Oops, something went wrong.