class ClassWithComparisonProcessedProperties: """A class with processed properties to be used as fixture instances. Attributes ---------- some_prop_min : :py:property:`processed_property` Numerical processed property with minimum and maximum numerical bounds, and comparison to :py:property:`some_prop_max`. some_prop_max : :py:property:`processed_property` Numerical processed property with minimum and maximum numerical bounds, and comparison to :py:property:`some_prop_min`. """ some_prop_min = processed_property(some_prop_min_keyword, **min_kwargs) some_prop_max = processed_property(some_prop_max_keyword, **max_kwargs) def __init__(self, some_prop_min, some_prop_max): """Initialise the numerical bounds on the processed properties. Parameters ---------- some_prop_min : :py:class:`Number <typing>` Numerical value to initialise the :py:attr:`some_prop_min` to. some_prop_max : :py:class:`Number <typing>` Numerical value to initialise the :py:attr:`some_prop_max` to. """ self.some_prop_min = some_prop_min self.some_prop_max = some_prop_max
class ClassWithPostMethodProperty: """Dummy class for testing processed properties with post methods.""" method_prop = processed_property("method_prop", type=int, method=square) np_method_prop = processed_property("np_method_prop", type=float, cast=True, method=np.cos)
class ClassWithOptionProperties: """A class with processed properties to be used as fixture instances. Attributes ---------- """ one_option_prop = processed_property( "one_option_prop", description="option property with a single option", type=str, options=single_option, ) mul_option_prop = processed_property( "mul_option_prop", description="option property with multiple options", type=str, options=multiple_options, ) one_unsupported_option_prop = processed_property( "one_unsupported_option_prop", description=( "option property with multiple options and a single unsupported option" ), type=str, options=multiple_options_single_unsupported, ) mul_unsupported_option_prop = processed_property( "mul_unsupported_option_prop", description=( "option property with multiple options and multiple unsupported options" ), type=str, options=multiple_options_multiple_unsupported, ) def __init__( self, one_option=OPTION_1_KEYWORD, mul_option=OPTION_1_KEYWORD, one_unsupported_option=OPTION_1_KEYWORD, mul_unsupported_option=OPTION_1_KEYWORD, ): """Initialise the numerical bounds on the processed properties. Parameters ---------- """ self.one_option_prop = one_option self.mul_option_prop = mul_option self.one_unsupported_option_prop = one_unsupported_option self.mul_unsupported_option_prop = mul_unsupported_option
class ClassWithOptionsProperty: """A class with processed properties to be used as fixture instances. Attributes ---------- options_prop : :py:property:`processed_property` Processed property that only takes an assortment of options. These options are random, contrived, of different types and are purely for testing purposes only. """ options_prop = processed_property("options_prop", options=OPTIONS, unsupported_options=UNSUPPORTED_OPTIONS) def __init__(self, option=None): """Initialise the numerical bounds on the processed properties. Parameters ---------- option : obj Value to initialise the :py:attr:`options_prop` to. """ self.options_prop = option
class ClassWithSingleOptionAllUnsupportedOptionProperties: one_all_unsupported_option_prop = processed_property( "one_all_unsupported_option_prop", type=str, unsupported_options=(OPTION_1_KEYWORD, ), )
class ClassWithOptimisableProperty: """Dummy class with optimisable processed property for tests. Attributes ---------- optimisable_prop : :py:property: Optimisable property that accepts either a single value or an iterable of length two (with first entry less than or equal to second entry if type is numeric). """ optimisable_prop = processed_property("optimisable_prop", optimisable=True)
class ClassWithMultipleOptionAllUnsupportedOptionProperties: option_from_dict_keys_prop = processed_property( "option_from_dict_keys_prop", type=str, options={ OPTION_1_KEYWORD: None, OPTION_2_KEYWORD: None, OPTION_3_KEYWORD: None, OPTION_4_KEYWORD: None, OPTION_5_KEYWORD: None, }.keys(), unsupported_options=(OPTION_5_KEYWORD, ), )
class ClassWithProcessedProperties: prop_a = processed_property("prop_a", type=str, options=("A", "B")) prop_b = processed_property( "prop_b", type=str, options=("A", "B"), unsupported_options=("B",) ) prop_c = processed_property( "prop_c", description="description", type=str, options=("A", "B"), unsupported_options=("B",), ) prop_d = processed_property("prop_d", description="a", type=int, min=0, max=1) prop_e = processed_property( "prop_e", description="a description", type=int, min=0, max=1 ) def __init__(self): self.prop_a = "A" self.prop_b = "A" self.prop_c = "A" self.prop_d = 1 self.prop_e = 1
class ClassWithCastableProperties: """Dummy class for fixtures with property that casts to np.ndarray Attributes ---------- cast_prop : processed_prop Processed property that enforces casting to a np.ndarray. """ cast_prop = processed_property( "cast_prop", type=np.ndarray, cast=True, )
class ClassWithReadOnlyProperty: """Dummy class with read-only processed property for tests. Attributes ---------- read_only_prop : :py:property: Read-only property that raises an AttributeError if tried to reset. Raises ------ AttributeError If :py:attr:`read_only_prop` is tried to be set more than once. """ read_only_prop = processed_property("read_only_prop", read_only=True)
class ClassWithMultipleOptionAllUnsupportedOptionProperties: mul_all_unsupported_option_prop = processed_property( "mul_all_unsupported_option_prop", type=str, options=( OPTION_1_KEYWORD, OPTION_2_KEYWORD, OPTION_3_KEYWORD, OPTION_4_KEYWORD, OPTION_5_KEYWORD, ), unsupported_options=( OPTION_1_KEYWORD, OPTION_2_KEYWORD, OPTION_3_KEYWORD, OPTION_4_KEYWORD, OPTION_5_KEYWORD, ), )
class TestProcessedProperties: """Base class for testing pyproprop functionality.""" _REQUIRED_LENGTH = 5 _MAX_VALUE = 5 _MIN_VALUE = 5 _BOUNDS = (1, 10) _DEFAULT_INT = 5 # TODO: expand to cover all use cases: # * Find suitable post method for use in test. # * Test description checked_type_int = processed_property( "checked_type_int", type=int, optional=True, ) checked_type_float = processed_property( "checked_type_float", type=float, optional=True, ) checked_type_str = processed_property( "checked_type_str", type=str, optional=True, ) checked_type_iterable = processed_property( "checked_type_iterable", type=Iterable, optional=True, ) checked_type_bool = processed_property( "checked_type_bool", type=bool, optional=True, ) checked_list_len = processed_property( "checked_list_len", len=_REQUIRED_LENGTH, optional=True, ) checked_max_value = processed_property( "checked_max_value", max=_MAX_VALUE, optional=True, ) checked_min_value = processed_property( "checked_min_value", min=_MIN_VALUE, optional=True, ) checked_max_value_excl = processed_property( "checked_max_value_excl", max=_MAX_VALUE, exclusive=True, optional=True, ) checked_min_value_excl = processed_property( "checked_min_value_excl", min=_MIN_VALUE, exclusive=True, optional=True, ) checked_bounds = processed_property( "checked_bounds", min=_BOUNDS[0], max=_BOUNDS[1], optional=True, ) checked_iterable_allowed = processed_property( "checked_iterable_allowed", iterable_allowed=True, optional=True, ) optional_prop = processed_property( "optional_prop", type=int, optional=True, ) optional_prop_with_default = processed_property( "optional_prop_with_default", type=int, default=_DEFAULT_INT, optional=True, ) cast_string = processed_property( "cast_string", type=str, cast=True, ) optimisable_property = processed_property( "optimisable_property", optimisable=True, ) int_from_options = processed_property( "int_from_options", description="integer from a set of options", type=int, cast=True, options=(1, 2), ) def __init__(self, *, checked_type_int=None, checked_type_float=None, checked_type_str=None, checked_type_iterable=None, checked_type_bool=None, checked_list_len=None, checked_max_value=None, checked_min_value=None, checked_max_value_excl=None, checked_min_value_excl=None, checked_bounds=None, checked_iterable_allowed=None, optional_prop=None, optional_prop_with_default=None, cast_string=None, optimisable_property=None): self.checked_type_int = checked_type_int self.checked_type_float = checked_type_float self.checked_type_str = checked_type_str self.checked_type_iterable = checked_type_iterable self.checked_type_bool = checked_type_bool if checked_list_len is not None: self.checked_list_len = checked_list_len if checked_max_value is not None: self.checked_max_value = checked_max_value if checked_min_value is not None: self.checked_min_value = checked_min_value if checked_max_value_excl is not None: self.checked_max_value_excl = checked_max_value_excl if checked_min_value_excl is not None: self.checked_min_value_excl = checked_min_value_excl if checked_bounds is not None: self.checked_bounds = checked_bounds self.checked_iterable_allowed = checked_iterable_allowed self.optional_prop = optional_prop self.optional_prop_with_default = optional_prop_with_default self.cast_string = cast_string if optimisable_property is not None: self.optimisable_property = optimisable_property
class ClassWithStringFormatProperties: """A class with processed properties to be used as fixture instances. Attributes ---------- lower_prop : :py:property:`processed_property` String processed property that automatically formats to lower case. upper_prop : :py:property:`processed_property` String processed property that automatically formats to upper case. title_prop : :py:property:`processed_property` String processed property that automatically formats to title case. start_prop : :py:property:`processed_property` String processed property that automatically formats to start case. snake_prop : :py:property:`processed_property` String processed property that automatically formats to snake case. pascal_prop : :py:property:`processed_property` String processed property that automatically formats to pascal case. """ lower_prop = processed_property("lower_prop", type=str, default="", str_format="lower") upper_prop = processed_property("upper_prop", type=str, default="", str_format="upper") title_prop = processed_property("title_prop", type=str, default="", str_format="title") start_prop = processed_property("start_prop", type=str, default="", str_format="start") snake_prop = processed_property("snake_prop", type=str, default="", str_format="snake") pascal_prop = processed_property("pascal_prop", type=str, default="", str_format="pascal") hyphen_prop = processed_property("hyphen_prop", type=str, default="", str_format="hyphen") def __init__( self, lower_prop="", upper_prop="", title_prop="", start_prop="", snake_prop="", pascal_prop="", hyphen_prop="", ): """Initialise the numerical bounds on the processed properties. Parameters ---------- lower : :py:obj:`str` Value to initialise the :py:attr:`lower_prop` to. upper : :py:obj:`str` Value to initialise the :py:attr:`upper_prop` to. title : :py:obj:`str` Value to initialise the :py:attr:`title_prop` to. start : :py:obj:`str` Value to initialise the :py:attr:`start_prop` to. snake : :py:obj:`str` Value to initialise the :py:attr:`snake_prop` to. pascal : :py:obj:`str` Value to initialise the :py:attr:`pascal_prop` to. hyphen : :py:obj:`str` Value to initialise the :py:attr:`hyphen_prop` to. """ self.lower_prop = lower_prop self.upper_prop = upper_prop self.title_prop = title_prop self.start_prop = start_prop self.snake_prop = snake_prop self.pascal_prop = pascal_prop self.hyphen_prop = hyphen_prop
class ClassWithDefaultProperties: """Dummy class for testing processed properties with default/optional values.""" prop_a = processed_property("prop_a", type=int, optional=True) prop_b = processed_property("prop_b", type=int, optional=True, default=1)