more docs!
This commit is contained in:
parent
720d4e97e4
commit
92961c8f58
8 changed files with 92 additions and 17 deletions
|
|
@ -68,6 +68,11 @@ class Functions(
|
|||
----------
|
||||
function
|
||||
A static function whose name will be used as the offered function name.
|
||||
|
||||
Raises
|
||||
------
|
||||
ValueError
|
||||
If the name already exists as a function.
|
||||
"""
|
||||
if cls.is_built_in(function.__name__):
|
||||
raise ValueError(
|
||||
|
|
|
|||
|
|
@ -405,6 +405,24 @@ class Script:
|
|||
resolved: Optional[Dict[str, Resolvable]] = None,
|
||||
unresolvable: Optional[Set[str]] = None,
|
||||
) -> Dict[str, Resolvable]:
|
||||
"""
|
||||
Given a new set of variable definitions, resolve them using the Script, but do not
|
||||
add them to the Script itself.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
variable_definitions
|
||||
Variables to resolve, but not store in the Script
|
||||
resolved
|
||||
Optional. Pre-resolved variables that should be used instead of what is in the script.
|
||||
unresolvable
|
||||
Optional. Unresolvable variables that will be ignored in resolution, including all
|
||||
variables with a dependency to them.
|
||||
|
||||
Returns
|
||||
-------
|
||||
Dict containing the variable names to their resolved values.
|
||||
"""
|
||||
try:
|
||||
self.add(variable_definitions)
|
||||
return self._resolve(
|
||||
|
|
|
|||
|
|
@ -93,6 +93,8 @@ class BuiltInFunction(Function, BuiltInFunctionType):
|
|||
|
||||
return self
|
||||
|
||||
# pylint: disable=missing-raises-doc
|
||||
|
||||
@property
|
||||
def callable(self) -> Callable[..., Resolvable]:
|
||||
"""
|
||||
|
|
@ -106,6 +108,8 @@ class BuiltInFunction(Function, BuiltInFunctionType):
|
|||
# Should be validated in the parser
|
||||
raise UNREACHABLE from exc
|
||||
|
||||
# pylint: enable=missing-raises-doc
|
||||
|
||||
@functools.cached_property
|
||||
def function_spec(self) -> FunctionSpec:
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -114,8 +114,6 @@ class Hashable(Resolvable, ABC):
|
|||
Resolvable type that can be used as hashes (i.e. in Maps)
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class NonHashable(NamedType, ABC):
|
||||
|
|
@ -123,8 +121,6 @@ class NonHashable(NamedType, ABC):
|
|||
Type that is known to never be hashable.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class ResolvableToJson(Resolvable, ABC):
|
||||
|
|
@ -151,32 +147,40 @@ class Numeric(ResolvableT[NumericT], ABC, Generic[NumericT]):
|
|||
Resolvable numeric types (int/float)
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Integer(Numeric[int], Argument):
|
||||
pass
|
||||
"""
|
||||
Resolved Integer type
|
||||
"""
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Float(Numeric[float], Argument):
|
||||
pass
|
||||
"""
|
||||
Resolved float type
|
||||
"""
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Boolean(ResolvableT[bool], Argument):
|
||||
pass
|
||||
"""
|
||||
Resolved bool type
|
||||
"""
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class String(ResolvableT[str], Argument):
|
||||
pass
|
||||
"""
|
||||
Resolved String type
|
||||
"""
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class NamedCustomFunction(NamedArgument, ABC):
|
||||
pass
|
||||
"""
|
||||
A custom function with a defined name (but unknown args)
|
||||
"""
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
|
|
@ -236,5 +240,3 @@ class LambdaReduce(LambdaTwo):
|
|||
"""
|
||||
Type-hinting for functions that apply a reduce-operation using a lambda (two arguments)
|
||||
"""
|
||||
|
||||
pass
|
||||
|
|
|
|||
|
|
@ -17,6 +17,12 @@ class FunctionArgument(Variable):
|
|||
|
||||
@classmethod
|
||||
def from_idx(cls, idx: int, custom_function_name: Optional[str]) -> "FunctionArgument":
|
||||
"""
|
||||
Returns
|
||||
-------
|
||||
FunctionArgument whose variable name is the index, and optionally contains the custom
|
||||
function name its defined in as a prefix.
|
||||
"""
|
||||
if custom_function_name:
|
||||
return FunctionArgument(name=f"${custom_function_name}___{idx}", index=idx)
|
||||
return FunctionArgument(name=f"${idx}", index=idx)
|
||||
|
|
|
|||
|
|
@ -39,7 +39,9 @@ class VariableDependency(ABC):
|
|||
output.append(arg)
|
||||
|
||||
if isinstance(arg, VariableDependency):
|
||||
# pylint: disable=protected-access
|
||||
output.extend(arg._recurse_get(ttype))
|
||||
# pylint: enable=protected-access
|
||||
|
||||
return output
|
||||
|
||||
|
|
@ -83,6 +85,8 @@ class VariableDependency(ABC):
|
|||
"""
|
||||
return set(self._recurse_get(Lambda, subclass=True))
|
||||
|
||||
# pylint: disable=missing-raises-doc
|
||||
|
||||
@final
|
||||
@property
|
||||
def custom_functions(self) -> Set[ParsedCustomFunction]:
|
||||
|
|
@ -105,6 +109,8 @@ class VariableDependency(ABC):
|
|||
|
||||
return output
|
||||
|
||||
# pylint: enable=missing-raises-doc
|
||||
|
||||
@abstractmethod
|
||||
def resolve(
|
||||
self,
|
||||
|
|
|
|||
|
|
@ -130,11 +130,10 @@ class FunctionArgumentsExceptionFormatter:
|
|||
for arg in self._input_args:
|
||||
if isinstance(arg, BuiltInFunctionType):
|
||||
if is_union(arg.output_type()):
|
||||
received_type_names.append(
|
||||
f"%{arg.name}(...)->Union["
|
||||
f"{', '.join(sorted(type_.type_name() for type_ in arg.output_type().__args__))}"
|
||||
f"]"
|
||||
readable_type_names = ", ".join(
|
||||
sorted(type_.type_name() for type_ in arg.output_type().__args__)
|
||||
)
|
||||
received_type_names.append(f"%{arg.name}(...)->Union[{readable_type_names}]")
|
||||
else:
|
||||
received_type_names.append(f"%{arg.name}(...)->{arg.output_type().type_name()}")
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -143,6 +143,11 @@ class FunctionSpec:
|
|||
return True
|
||||
|
||||
def _is_varargs_compatible(self, input_args: List[Argument]) -> bool:
|
||||
"""
|
||||
Returns
|
||||
-------
|
||||
True if the input args are compatible with the spec's varargs. False otherwise.
|
||||
"""
|
||||
assert self.varargs is not None
|
||||
|
||||
for input_arg in input_args:
|
||||
|
|
@ -165,22 +170,42 @@ class FunctionSpec:
|
|||
raise UNREACHABLE # TODO: functions with no args
|
||||
|
||||
def is_num_args_compatible(self, num_input_args: int) -> bool:
|
||||
"""
|
||||
Returns
|
||||
-------
|
||||
True if the number of input args is compatible with the function spec. False otherwise.
|
||||
"""
|
||||
if self.args is not None:
|
||||
return self.num_required_args <= num_input_args <= len(self.args)
|
||||
return True # varargs can take any number
|
||||
|
||||
@property
|
||||
def num_required_args(self) -> int:
|
||||
"""
|
||||
Returns
|
||||
-------
|
||||
The minimum number of args required to call the function.
|
||||
"""
|
||||
if self.args is not None:
|
||||
return sum(1 for arg in self.args if not is_optional(arg))
|
||||
return 0 # varargs can take any number
|
||||
|
||||
@property
|
||||
def is_lambda_reduce_function(self) -> Optional[Type[LambdaReduce]]:
|
||||
"""
|
||||
Returns
|
||||
-------
|
||||
True if the function is a Lambda-reduce function. False otherwise.
|
||||
"""
|
||||
return LambdaReduce if LambdaReduce in (self.args or []) else None
|
||||
|
||||
@property
|
||||
def is_lambda_function(self) -> Optional[Type[Lambda | LambdaTwo | LambdaThree]]:
|
||||
"""
|
||||
Returns
|
||||
-------
|
||||
True if the function is a Lambda function (excluding reduce). False otherwise.
|
||||
"""
|
||||
if LambdaThree in (self.args or []):
|
||||
return LambdaThree
|
||||
if LambdaTwo in (self.args or []):
|
||||
|
|
@ -191,6 +216,11 @@ class FunctionSpec:
|
|||
|
||||
@property
|
||||
def is_lambda_like(self) -> Optional[Type[TLambda]]:
|
||||
"""
|
||||
Returns
|
||||
-------
|
||||
True if the function is a Lambda type (including reduce).
|
||||
"""
|
||||
if l_type := self.is_lambda_reduce_function:
|
||||
return l_type
|
||||
if l_type := self.is_lambda_function:
|
||||
|
|
@ -199,6 +229,11 @@ class FunctionSpec:
|
|||
|
||||
@classmethod
|
||||
def from_callable(cls, callable_ref: Callable[..., Resolvable]) -> "FunctionSpec":
|
||||
"""
|
||||
Returns
|
||||
-------
|
||||
FunctionSpec from a built-in function.
|
||||
"""
|
||||
arg_spec: FullArgSpec = inspect.getfullargspec(callable_ref)
|
||||
if arg_spec.varargs:
|
||||
return FunctionSpec(
|
||||
|
|
|
|||
Loading…
Reference in a new issue