Move files
This commit is contained in:
parent
3cf28379e8
commit
00cc8225c5
159 changed files with 31 additions and 49 deletions
8
great_ai/helper/__init__.py
Normal file
8
great_ai/helper/__init__.py
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
from .freeze_arguments import freeze, freeze_arguments
|
||||
from .get_arguments import get_arguments
|
||||
from .get_function_metadata_store import get_function_metadata_store
|
||||
from .hashable_base_model import HashableBaseModel
|
||||
from .snake_case_to_text import snake_case_to_text
|
||||
from .strip_lines import strip_lines
|
||||
from .text_to_hex_color import text_to_hex_color
|
||||
from .use_http_exceptions import use_http_exceptions
|
||||
14
great_ai/helper/assert_function_is_not_finalised.py
Normal file
14
great_ai/helper/assert_function_is_not_finalised.py
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
from typing import Any, Callable
|
||||
|
||||
from ..exceptions import WrongDecoratorOrderError
|
||||
from .get_function_metadata_store import get_function_metadata_store
|
||||
|
||||
|
||||
def assert_function_is_not_finalised(func: Callable[..., Any]) -> None:
|
||||
error_message = (
|
||||
"The outer-most (first) decorator has to be `@GreatAI.deploy`. "
|
||||
+ f"In the case of `{func.__name__}`, it is not: fix this by moving `@GreatAI.deploy` to the top."
|
||||
)
|
||||
|
||||
if get_function_metadata_store(func).is_finalised:
|
||||
raise WrongDecoratorOrderError(error_message)
|
||||
56
great_ai/helper/freeze_arguments.py
Normal file
56
great_ai/helper/freeze_arguments.py
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
from functools import wraps
|
||||
from typing import Any, Callable, Dict, List, Set, Union
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class FrozenDict(dict):
|
||||
def __hash__(self) -> int:
|
||||
return hash(frozenset((k, freeze(v)) for k, v in self.items()))
|
||||
|
||||
|
||||
class FrozenList(list):
|
||||
def __hash__(self) -> int:
|
||||
return hash(tuple(freeze(i) for i in self))
|
||||
|
||||
|
||||
class FrozenSet(set):
|
||||
def __hash__(self) -> int:
|
||||
return hash(frozenset(freeze(i) for i in self))
|
||||
|
||||
|
||||
def freeze_arguments(func: Callable[..., Any]) -> Callable[..., Any]:
|
||||
"""Transform mutable dictionary
|
||||
Into immutable
|
||||
Useful to be compatible with cache
|
||||
source: https://stackoverflow.com/questions/6358481/using-functools-lru-cache-with-dictionary-arguments
|
||||
"""
|
||||
|
||||
@wraps(func)
|
||||
def wrapper(*args: List[Any], **kwargs: Dict[str, Any]) -> Any:
|
||||
args = tuple(freeze(arg) for arg in args)
|
||||
kwargs = {k: freeze(v) for k, v in kwargs.items()}
|
||||
return func(*args, **kwargs)
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
def freeze(value: Union[List[Any], Dict[str, Any], Set[Any]]) -> Any:
|
||||
if isinstance(value, dict):
|
||||
return FrozenDict(value)
|
||||
|
||||
if isinstance(value, list):
|
||||
return FrozenList(value)
|
||||
|
||||
if isinstance(value, set):
|
||||
return FrozenSet(value)
|
||||
|
||||
if isinstance(value, BaseModel):
|
||||
|
||||
class HashableValue(type(value)):
|
||||
def __hash__(self) -> int:
|
||||
return hash(frozenset((k, freeze(v)) for k, v in self.dict().items()))
|
||||
|
||||
return HashableValue(**value.dict())
|
||||
|
||||
return value
|
||||
24
great_ai/helper/get_arguments.py
Normal file
24
great_ai/helper/get_arguments.py
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
import inspect
|
||||
from typing import Any, Callable, Dict, Mapping, Sequence
|
||||
|
||||
|
||||
def get_arguments(
|
||||
func: Callable[..., Any], args: Sequence[Any], kwargs: Mapping[str, Any]
|
||||
) -> Dict[str, Any]:
|
||||
"""Return mapping from parameter names to actual argument values"""
|
||||
|
||||
signature = inspect.signature(func)
|
||||
|
||||
defaults = {
|
||||
p.name: p.default
|
||||
for p in signature.parameters.values()
|
||||
if p.default != inspect._empty
|
||||
}
|
||||
|
||||
filter_keys = [
|
||||
param.name
|
||||
for param in signature.parameters.values()
|
||||
if param.kind == param.POSITIONAL_OR_KEYWORD
|
||||
]
|
||||
|
||||
return {**defaults, **dict(zip(filter_keys, args)), **kwargs}
|
||||
12
great_ai/helper/get_function_metadata_store.py
Normal file
12
great_ai/helper/get_function_metadata_store.py
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
from typing import Any, Callable, cast
|
||||
|
||||
from ..views.function_metadata import FunctionMetadata
|
||||
|
||||
|
||||
def get_function_metadata_store(func: Callable[..., Any]) -> FunctionMetadata:
|
||||
any_func = cast(Any, func)
|
||||
|
||||
if not hasattr(any_func, "_great_ai_metadata"):
|
||||
any_func._great_ai_metadata = FunctionMetadata()
|
||||
|
||||
return any_func._great_ai_metadata
|
||||
6
great_ai/helper/hashable_base_model.py
Normal file
6
great_ai/helper/hashable_base_model.py
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class HashableBaseModel(BaseModel):
|
||||
def __hash__(self) -> int:
|
||||
return hash((type(self),) + tuple(self.__dict__.values()))
|
||||
2
great_ai/helper/snake_case_to_text.py
Normal file
2
great_ai/helper/snake_case_to_text.py
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
def snake_case_to_text(snake_case: str) -> str:
|
||||
return snake_case.capitalize().replace("_", " ")
|
||||
2
great_ai/helper/strip_lines.py
Normal file
2
great_ai/helper/strip_lines.py
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
def strip_lines(text: str) -> str:
|
||||
return "\n".join(line.strip() for line in text.split("\n"))
|
||||
13
great_ai/helper/text_to_hex_color.py
Normal file
13
great_ai/helper/text_to_hex_color.py
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
import colorsys
|
||||
from hashlib import md5
|
||||
|
||||
|
||||
def text_to_hex_color(text: str) -> str:
|
||||
ascii_bytes = text.encode("ascii")
|
||||
digest = md5(
|
||||
ascii_bytes
|
||||
).hexdigest() # the built-in hash function is salted differently in each process
|
||||
integer = int(digest, 16)
|
||||
hue = integer % 6311 / 6311.0
|
||||
rgb = colorsys.hsv_to_rgb(hue, 0.75, 0.6)
|
||||
return "#" + "".join("%02X" % round(i * 255) for i in rgb)
|
||||
20
great_ai/helper/use_http_exceptions.py
Normal file
20
great_ai/helper/use_http_exceptions.py
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
from functools import wraps
|
||||
from typing import Any, Callable, Dict, List, TypeVar, cast
|
||||
|
||||
from fastapi import HTTPException, status
|
||||
|
||||
F = TypeVar("F", bound=Callable[..., Any])
|
||||
|
||||
|
||||
def use_http_exceptions(func: F) -> F:
|
||||
@wraps(func)
|
||||
def wrapper(*args: List[Any], **kwargs: Dict[str, Any]) -> Any:
|
||||
try:
|
||||
return func(*args, **kwargs)
|
||||
except Exception as e:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail=f"The following exception has occurred: {type(e).__name__}: {e}",
|
||||
)
|
||||
|
||||
return cast(F, wrapper)
|
||||
Loading…
Add table
Add a link
Reference in a new issue