monkey_wrench.generic package
The package providing some generic utilities and types, used in other sub-packages of Monkey Wrench.
- class monkey_wrench.generic.Model[source]
Bases:
BaseModelA Pydantic model to be used as a base for all other models, e.g. specifications of a task.
Note
Models that inherit from this model have the following properties
1- They do not allow any extra keyword arguments to be passed to the constructor if the corresponding field is not explicitly defined.
2- The fields are faux-immutable (frozen).
3- They allow for arbitrary types to be validated, e.g. when using pydantic.validate_call decorator.
Example
class Dataset(Model): name: str # The following will lead to an exception. # `number` has not been explicitly defined as a model field. dataset = Dataset(name="dataset-name", number=1) dataset = Dataset(name="dataset-name") # The following will lead to an exception. # All fields (i.e. `name` in this case) are immutable. dataset.name = "dataset-name_changed"
- new_with(**kwargs: dict[str, Any]) Self[source]
Create an instance of the same model but with new values for the fields as determined by
kwargs.Warning
The new instance will be validated against all field and model validators before being returned. This is true even for the fields which have not been updated via
kwargs. As a result, if validators for fields have side effects, it is important to ensure that the side effects do not unintentionally get repeated!d! Look at the example below for such an unintentional side effect!Example
>>> from typing_extensions import Annotated >>> from pydantic import AfterValidator >>> >>> class Dataset(Model): ... set_number: int ... count: int ... name: Annotated[str, AfterValidator(lambda x: x + ".extension")] >>> >>> dataset = Dataset(name="dataset-original", count=10, set_number=1) >>> dataset Dataset(set_number=1, count=10, name='dataset-original.extension') >>> >>> dataset_new = dataset.new_with(set_number=2) >>> dataset_new Dataset(set_number=2, count=10, name='dataset-original.extension.extension') >>> # `.extension` gets duplicated as the validator for `name` runs twice. >>> # `name` has not been explicitly passed to the `with_new()` method! >>> # `count` has not been affected since its validator `int` is pure!
- class monkey_wrench.generic.StringTransformation(*, trim: bool = True, transform_function: Annotated[Callable[[...], TransformedType], BeforeValidator(func=validate_function_path, json_schema_input_type=PydanticUndefined)] | Callable[[...], TransformedType] | None = None)[source]
Bases:
Model,GenericPydantic model for transformations on strings, e.g. before writing to or after reading from a file.
- _transform_item(item: OriginalType) OriginalType | TransformedType[source]
Transform a single item.
- _trim_item(item: OriginalType) str[source]
Trim a single item. The item can be of any type and will be coerced into a string first.
- transform_items(items: list[OriginalType] | set[OriginalType] | tuple[OriginalType, ...] | OriginalType) list[TransformedType] | set[TransformedType] | tuple[TransformedType, ...] | list[OriginalType] | set[OriginalType] | tuple[OriginalType, ...] | OriginalType | TransformedType[source]
Transform a single or multiple items (of any type).
- trim_items(items: list[OriginalType] | set[OriginalType] | tuple[OriginalType, ...] | OriginalType) list[str] | set[str] | tuple[str, ...] | str[source]
Trim a single or multiple items. The items can be of any type and will be first coerced into strings.
- trim: bool
A boolean indicating whether to remove trailing/leading whitespaces, tabs, and newlines from string items.
Defaults to
True.
- transform_function: Annotated[Callable[[...], TransformedType], BeforeValidator(func=validate_function_path, json_schema_input_type=PydanticUndefined)] | Callable[[...], TransformedType] | None
If given, each item will be transformed according to the function.
Defaults to
None, which means no transformation is performed and items will be treated as they are.
- monkey_wrench.generic.apply_to_single_or_collection(function: Callable[[T], R], single_or_collection: dict[Any, T] | list[T] | set[T] | tuple[T, ...] | T) dict[Any, R] | list[R] | set[R] | tuple[R, ...] | R[source]
Apply the given function to a single item or all elements of a collection (dict/list/set/tuple).
Note
In the case of a dictionary,
functionwill be applied to the values.Warning
A string, although being a collection, is treated as a single item.
- Parameters:
function – The function to be applied.
single_or_collection – Either a single item or a collection (dict/list/set/tuple).
- Returns:
Either a single output, or a collection as output resulting from applying the given function.
Examples
>>> apply_to_single_or_collection(lambda x: x**2, [1, 2, 3]) [1, 4, 9]
>>> apply_to_single_or_collection(lambda x: x**2, (1, 2, 3)) (1, 4, 9)
>>> apply_to_single_or_collection(lambda x: x**2, {"a": 1, "b": 2, "c":3}) {'a': 1, 'b': 4, 'c': 9}
>>> apply_to_single_or_collection(lambda x: x**2, set()) set()
>>> apply_to_single_or_collection(lambda x: x**2, 3) 9
>>> apply_to_single_or_collection(lambda x: x*2, "book!") 'book!book!'
- monkey_wrench.generic.assert_(item: ~monkey_wrench.generic._common.T, message: str, exception: type[Exception] = <class 'ValueError'>, silent: bool = True) T[source]
Assert the truth value of the item, and return the item or raise
exception.- Parameters:
item – The item to assert. It does not have to be a boolean. For example, given an empty list,
assert []fails as an empty list evaluates toFalse.message – The exception message, which will be shown when the exception is raised.
exception – The exception to raise if both the
itemandsilentevaluate toFalse. Defaults toValueError.silent – A boolean indicating whether to return the item silently or raise an exception in the case of assertion failure. Defaults to
True, which means the item will be silently returned.
- Returns:
Return the item if it evaluates to
True. If the item evaluates toFalse, return it only ifsilentisTrue.- Raises:
exception – If the
itemevaluates toFalseandsilentisFalse.
- monkey_wrench.generic.collection_element_type(collection: dict[Any, T] | list[T] | set[T] | tuple[T, ...]) type[T] | None[source]
Return the type of collection elements, e.g. for
set[T]it returnsT.- Parameters:
collection – The collection to get the type of any element from.
- Returns:
The type of any element from the collection (dict/list/set/tuple). In the case of an empty collection,
Noneis returned.- Raises:
TypeError – If the collection elements are of different types.
Examples
>>> collection_element_type([3, 2, 1]) <class 'int'>
>>> collection_element_type(set()) is None True
>>> # The following will lead to an exception, since the collection elements are not of the same type. >>> # element_type_from_collection((3.0, 2.0, "1"))
- monkey_wrench.generic.type_(single_or_collection: dict[Any, T] | list[T] | set[T] | tuple[T, ...] | T) type[T] | None[source]
Return the type of the given item, or any element from the collection using
element_type_from_collection().Examples
>>> type_([3, 2, 1]) <class 'int'>
>>> type_(3) <class 'int'>