diff --git a/nisaba/scripts/natural_translit/utils/list_op.py b/nisaba/scripts/natural_translit/utils/list_op.py index dec88dd8..4bee8020 100644 --- a/nisaba/scripts/natural_translit/utils/list_op.py +++ b/nisaba/scripts/natural_translit/utils/list_op.py @@ -119,7 +119,7 @@ def attr_list( else: [t.attr for t in things] """ - l = [ty.get_attribute(t, attr, want=attr_type) for t in things] + l = [ty.get_attribute(t, attr, typeinfo=attr_type) for t in things] return list(filter(ty.is_found, l)) diff --git a/nisaba/scripts/natural_translit/utils/log_op.py b/nisaba/scripts/natural_translit/utils/log_op.py index fca222cb..0ebb0142 100644 --- a/nisaba/scripts/natural_translit/utils/log_op.py +++ b/nisaba/scripts/natural_translit/utils/log_op.py @@ -57,6 +57,12 @@ def _return_message(return_value: ..., message: str = '') -> str: return return_message +def _in_message(look_for: ..., look_in: ..., message: str = '') -> str: + in_message = '%s in %s' % (class_and_text(look_for), text_of(look_in)) + if message: in_message += ', ' + message + return in_message + + ## Public functions # Log functions @@ -94,6 +100,18 @@ def dbg_return_false( return dbg_return(False, message, callstack_index + 1) +def dbg_return_in( + look_for: ..., look_in: ..., + message: str = '', + callstack_index: int = 0 +) -> bool: + return dbg_return( + look_for in look_in, + _in_message(look_for, look_in, message), + callstack_index + 1 + ) + + # Functions that return simple and readable strings to identify the objects. @@ -113,14 +131,16 @@ def text_of(obj: ...) -> str: return text if text else '' -def texts_of(*args) -> str: - return ' ,'.join([text_of(arg) for arg in args]) - - def alias_of(obj: ...) -> str: return obj.alias if hasattr(obj, 'alias') else text_of(obj) +def name_of(obj: ...) -> str: + if hasattr(obj, 'name'): return obj.name + if hasattr(obj, '__name__'): return obj.__name__ + return alias_of(obj) + + def class_and_alias(obj: ...) -> str: return '%s_%s' % (class_of(obj), alias_of(obj)) @@ -129,5 +149,9 @@ def class_and_text(obj: ...) -> str: return '%s_%s' % (class_of(obj), text_of(obj)) +def class_text_comma(*args) -> str: + return ', '.join(class_and_text(arg) for arg in args) + + def from_class_and_text(obj: ...) -> str: return 'from:%s' % class_and_text(obj) diff --git a/nisaba/scripts/natural_translit/utils/log_op_test.py b/nisaba/scripts/natural_translit/utils/log_op_test.py index f341d983..60a6cd75 100644 --- a/nisaba/scripts/natural_translit/utils/log_op_test.py +++ b/nisaba/scripts/natural_translit/utils/log_op_test.py @@ -24,6 +24,8 @@ _T1 = t.Thing.with_alias('T1') _T3 = t.Thing.with_alias_and_value('', _T1) _T5 = t.Thing.with_alias_and_value('T5', t.pyn.accep('')) +Named = collections.namedtuple('Named', ['name']) +_NAMED = Named('Jane') class LoggingTest(absltest.TestCase): @@ -70,12 +72,33 @@ def test_alias_of_thing_empty(self): def test_alias_of_list(self): self.assertEqual(log.alias_of([0, 1]), '[0, 1]') + def test_name_of_named(self): + self.assertEqual(log.name_of(_NAMED), 'Jane') + + def test_name_of_type(self): + self.assertEqual(log.name_of(int), 'int') + + def test_name_of_obj_int(self): + self.assertEqual(log.name_of(3), '3') + + def test_name_of_thing(self): + self.assertEqual(log.name_of(_T1), 'T1') + + def test_class_text_comma(self): + self.assertEqual( + log.class_text_comma(1, t.MISSING, ''), + 'int_1, Nothing_Missing, str_' + ) + def test_frame(self): self.assertEqual(log._add_caller('msg', 3), 'case.py/run: msg') def test_return_message(self): self.assertEqual(log._return_message(5, 'msg'), 'returns 5, detail: msg') + def test_in_message(self): + self.assertEqual(log._in_message(3, [0, 1], 'msg'), 'int_3 in [0, 1], msg') + def test_dbg_return(self): self.assertEqual(log.dbg_return(5), 5) @@ -85,5 +108,8 @@ def test_dbg_return_true(self): def test_dbg_return_false(self): self.assertFalse(log.dbg_return_false('msg')) + def test_dbg_return_in(self): + self.assertFalse(log.dbg_return_in(3, [0, 1])) + if __name__ == '__main__': absltest.main() diff --git a/nisaba/scripts/natural_translit/utils/type_op.py b/nisaba/scripts/natural_translit/utils/type_op.py index 3bfbb51c..c7892df0 100644 --- a/nisaba/scripts/natural_translit/utils/type_op.py +++ b/nisaba/scripts/natural_translit/utils/type_op.py @@ -22,7 +22,7 @@ TODO(): Fix typing in natural_translit. """ -from typing import Any, Dict, Iterable, List, Tuple, Union, Type +from typing import Any, Iterable, Union, Type import pynini as pyn from nisaba.scripts.natural_translit.utils import log_op as log @@ -144,6 +144,8 @@ def set_alias(self, alias: str) -> None: # FstLike from pynini doesn't work in isinstance() FstLike = Union[str, pyn.Fst] # OrNothing unions for arguments. +DictOrNothing = Union[dict, Nothing] +IntOrNothing = Union[int, Nothing] ListOrNothing = Union[list, Nothing] SetOrNothing = Union[set, Nothing] ThingOrNothing = Union[Thing, Nothing] @@ -202,21 +204,24 @@ def not_nothing(obj: ...) -> bool: return not is_nothing(obj) -def exists(obj: ..., allow_none: bool = False) -> bool: +def exists(obj: ...) -> bool: """Combines checking for None and undefined Things.""" - return (not_none(obj) or allow_none) and not_nothing(obj) + return log.dbg_return( + obj is not None and not isinstance(obj, Nothing), + log.class_and_text(obj) + ) -def not_exists(obj: ..., allow_none: bool = False) -> bool: - return not exists(obj, allow_none) +def not_exists(obj: ...) -> bool: + return not exists(obj) -def is_instance_dbg(obj: ..., want: TypeOrNothing = UNSPECIFIED) -> bool: +def is_instance_dbg(obj: ..., typeinfo: TypeOrNothing = UNSPECIFIED) -> bool: """Checks instance for logging purposes. Args: obj: Object - want: Type. Default value is UNSPECIFIED to make type check optional in + typeinfo: Type. Default value is UNSPECIFIED to make type check optional in functions that call is_instance_dbg, while the case of optional argument and specifically checking for Null type as distinct cases. @@ -224,47 +229,40 @@ def is_instance_dbg(obj: ..., want: TypeOrNothing = UNSPECIFIED) -> bool: bool """ - if not_specified(want): - return log.dbg_return_true( - 'type check not requested for %s' % log.text_of(obj) - ) - try: - if isinstance(obj, want): return True - return log.dbg_return_false('%s not %s' % (log.text_of(obj), want.__name__)) - except TypeError: - return log.dbg_return_false('invalid type') - - -def not_instance(obj: ..., want: TypeOrNothing = UNSPECIFIED) -> bool: - return not is_instance_dbg(obj, want) + if isinstance(typeinfo, Nothing): return log.dbg_return_true( + 'typeinfo %s for %s' % (typeinfo.text, log.class_and_text(obj)) + ) + if isinstance(obj, typeinfo): return True + return log.dbg_return_false( + '%s not %s' % (log.class_and_text(obj), log.name_of(typeinfo)) + ) -def enforce_thing(t: ...) -> Thing: - """Enforces thing type. If t is not Thing, puts t in value of a new Thing.""" - if isinstance(t, Thing): return t - return log.dbg_return(Thing.from_value_of(t)) +def not_instance(obj: ..., typeinfo: TypeOrNothing = UNSPECIFIED) -> bool: + return not is_instance_dbg(obj, typeinfo) # Attribute functions with type check. def has_attribute( - obj: ..., attr: str, want: TypeOrNothing = UNSPECIFIED + obj: ..., attr: str, typeinfo: TypeOrNothing = UNSPECIFIED ) -> bool: """Adds log and optional type check to hasattr().""" - if not_exists(obj): return False - if not hasattr(obj, attr): - return log.dbg_return_false( - '%s not an attribute of %s' % (attr, log.text_of(obj)) - ) - return is_instance_dbg(getattr(obj, attr), want) + if not hasattr(obj, attr): return log.dbg_return_false( + '%s has no attribute %s' % (log.class_and_text(obj), attr) + ) + return log.dbg_return(is_instance_dbg(getattr(obj, attr), typeinfo)) def get_attribute( obj: ..., attr: str, default: ... = MISSING, - want: TypeOrNothing = UNSPECIFIED + typeinfo: TypeOrNothing = UNSPECIFIED ) -> ...: """Adds log and type check to getattr().""" - return getattr(obj, attr) if has_attribute(obj, attr, want) else default + return log.dbg_return( + getattr(obj, attr) if has_attribute(obj, attr, typeinfo) else default, + '%s of %s' % (attr, log.class_and_text(obj)) + ) # Equivalence functions. @@ -276,7 +274,7 @@ def is_equal( """Checks equivalence. Never equates None, logs other 'not a' conditions. - Never equates UNASSIGNED, UNSPECIFIED or MISSING. + Never equates Nothing. Thing instances are equal if their values are equal. Args: @@ -292,25 +290,25 @@ def is_equal( """ # Check Fst first, otherwise if Fst == Non-FstLike raises error. if isinstance(obj1, pyn.Fst) or isinstance(obj2, pyn.Fst): - if not_instance(obj1, FstLike) or not_instance(obj2, FstLike): - return log.dbg_return_false( - 'type mismatch between %s and %s' % - (log.class_and_text(obj1), log.class_and_text(obj2)) - ) - if obj1 != obj2: return False + if ( + not isinstance(obj1, FstLike) or + not isinstance(obj2, FstLike) or + obj1 != obj2 + ): + return log.dbg_return_false(log.class_text_comma(obj1, obj2)) if not epsilon and obj1 == pyn.accep(''): return log.dbg_return_false('epsilon fst') + return True obj1_val = value_of(obj1) obj2_val = value_of(obj2) if obj1_val != obj2_val: - if not_instance(obj1_val, type(obj2_val)): - log.dbg_message('type mismatch %s' % log.texts_of(obj1_val, obj2_val)) - return False + return log.dbg_return_false(log.class_text_comma(obj1_val, obj2_val)) if ( - not_exists(obj1_val) or + obj1_val is None or + isinstance(obj1_val, Nothing) or (not zero and obj1_val == 0) or (not empty and is_empty(obj1_val)) - ): return log.dbg_return_false(log.text_of(obj1_val)) + ): return log.dbg_return_false(log.class_and_text(obj1_val)) return True @@ -323,20 +321,28 @@ def not_equal( # Iterable functions -def is_empty(obj: ..., allow_none: bool = False) -> bool: - return not_exists(obj, allow_none) or (isinstance(obj, Iterable) and not obj) +def is_empty(obj: ...) -> bool: + try: + return log.dbg_return(len(obj) < 1, log.class_and_text(obj)) + except TypeError: + return log.dbg_return_false('no size for ' + log.class_and_text(obj)) -def not_empty(obj: ..., allow_none: bool = False) -> bool: - return not is_empty(obj, allow_none) +# CAVEAT: is_empty() and not_empty() both return False for obj with no size. +def not_empty(obj: ...) -> bool: + try: + return log.dbg_return(len(obj) >= 1, log.class_and_text(obj)) + except TypeError: + return log.dbg_return_false('no size for ' + log.class_and_text(obj)) def get_element( search_in: ..., index: int, default: ... = MISSING ) -> ...: """Returns a[index] if possible, default value if not.""" - if not_exists(search_in): return default - if not_instance(search_in, Iterable): return default + if not isinstance(search_in, Iterable): return log.dbg_return( + default, log.class_and_text(search_in) + ' not iterable' + ) try: return search_in[index] except IndexError: @@ -344,27 +350,28 @@ def get_element( def enforce_range( - arg1: ..., arg2: ... = UNSPECIFIED, arg3: ... = UNSPECIFIED, - def_start: ... = UNSPECIFIED, def_stop: ... = UNSPECIFIED, + start: IntOrNothing, stop: IntOrNothing, + def_start: IntOrNothing = UNSPECIFIED, def_stop: IntOrNothing = UNSPECIFIED, ) -> range: - """Ensures range type for tuple arguments. + """Enforces range type for int or Nothing arguments. Args: - arg1: If int, start or stop. If Tuple(int, int), provides range arguments. - arg2: If arg1 is int, stop. If arg1 is (int, int) step. - arg3: If arg1 and arg2 are int, step. - def_start: Optional start value if range starts at None. - def_stop: Optional stop value if range stops at None. + start: Start of range. + stop: Stop of range. + def_start: Optional start value if start is Nothing. + def_stop: Optional stop value if stop is Nothing. Fail value is range(0) to ensure type but in_range() always returns false. - Default values are UNSPECIFIED to differentiate NoneType from optional args. - Eg. `enforce_range(1, 5, 2)` returns `range(1, 5, 2)` - `enforce_range((1, 5), 2)` returns `range(1, 5, 2)` - `enforce_range(5)` returns `range(5)`. - `enforce_range(5, None)` returns `range(0)`. + Eg. + `enforce_range(1, 5)` returns `range(1, 5)` + `enforce_range(MISSING, 5)` returns `range(0)` + `enforce_range(1, 5, 0, 10)` returns `range(1, 5)` + `enforce_range(MISSING, 5, 0, 10)` returns `range(0, 5)` + `enforce_range(1, MISSING, 0, 10)` returns `range(1, 10)` + `enforce_range(1, MISSING, 0, MISSING)` returns `range(0)` - def_start and def_stop values for None start and stop args for cases like: + def_start and def_stop values for Nothing start and stop args for cases like: ``` enforce_range( previous_vowel_index, @@ -376,213 +383,56 @@ def enforce_range( Returns: range """ - - a3 = 1 if not_specified(arg3) else arg3 - if isinstance(arg1, Tuple): - if len(arg1) > 3 or (len(arg1) == 3 and is_specified(arg2)): - return log.dbg_return( - range(0), - 'too many arguments range(%s)' % log.texts_of(arg1, arg2, arg3) - ) - log.dbg_message(log.from_class_and_text(arg1)) - e1 = get_element(arg1, 0) - e2 = get_element(arg1, 1) - e3 = get_element(arg1, 2) - a1, a2 = (e1, e2) - a3 = arg2 if not_found(e3) and exists(arg2) else e3 - else: - if not_specified(arg2): - a1, a2 = (0, arg1) - else: - a1, a2 = (arg1, arg2) - if not_exists(a1) and exists(def_start): a1 = def_start - if not_exists(a2) and exists(def_stop): a2 = def_stop - if isinstance(a1, int) and isinstance(a2, int): - if isinstance(a3, int): return range(a1, a2, a3) - if is_nothing(a3): return range(a1, a2) - return log.dbg_return(range(0), log.texts_of(arg1, arg2, arg3)) + r_start = start if isinstance(start, int) else def_start + r_stop = stop if isinstance(stop, int) else def_stop + if isinstance(r_start, int) and isinstance(r_stop, int): + r = range(r_start, r_stop) + else: r = range(0) + return log.dbg_return( + r, log.class_text_comma(start, stop, def_start, def_stop) + ) def in_range( - look_for: ..., arg1: ..., - arg2: ... = UNSPECIFIED, arg3: ... = UNSPECIFIED, + look_for: IntOrNothing, start: IntOrNothing, stop: IntOrNothing, + def_start: IntOrNothing = UNSPECIFIED, def_stop: IntOrNothing = UNSPECIFIED ) -> bool: """Checks if look_for is in an enforced range.""" - if not_exists(look_for): return False - if not_instance(look_for, int): return False - return look_for in enforce_range(arg1, arg2, arg3) - - -def enforce_list( - l: ..., enf_dict: bool = True, allow_none: bool = False -) -> List[Any]: - """Enforces list type. - - When l is a list, returns l. If l is an iterable returns `list(l)`, except - for str and dict. For other types returns `[l]`. + return log.dbg_return_in( + look_for, enforce_range(start, stop, def_start, def_stop) + ) - Args: - l: ... variable. - enf_dict: When true, if l is a dict returns the list of values. - allow_none: When false, if l is None returns an empty list. When true, - returns `[None]`. - Returns: - List. - """ - if isinstance(l, list): return l - log.dbg_message(log.from_class_and_text(l)) - if enf_dict and isinstance(l, dict): return log.dbg_return(list(l.values())) - if ( - isinstance(l, Iterable) and - not_instance(l, str) and not_instance(l, dict) - ): return log.dbg_return(list(l)) - if not_exists(l, allow_none): return log.dbg_return([]) - return log.dbg_return([l]) +def enforce_list(obj: ListOrNothing) -> list[Any]: + """Enforces list type for list or Nothing arguments.""" + # TODO: catch dict iterables as list + if isinstance(obj, list): return obj + return log.dbg_return([], log.from_class_and_text(obj)) -def in_list( - look_for: ..., look_in: ..., - enf_dict: bool = True, allow_none: bool = False -) -> bool: +def in_list(look_for: ..., look_in: ListOrNothing) -> bool: """Checks if look_for is an element of a list enforced from look_in.""" - return look_for in enforce_list(look_in, enf_dict, allow_none) + return log.dbg_return_in(look_for, enforce_list(look_in)) -def enforce_dict( - d: ..., add_key: ... = 'default', allow_none: bool = False -) -> Dict[Any, Any]: - """Enforces dict type. +def enforce_dict(obj: DictOrNothing) -> dict[Any, Any]: + """Enforces dict type for dict or Nothing arguments.""" + if isinstance(obj, dict): return obj + return log.dbg_return({}, log.from_class_and_text(obj)) - Args: - d: ... variable. - When d is a dict, returns d. Otherwise returns `{add_key: d}`. - add_key: optional key for adding d as a value to a new list. - allow_none: When false, if d is a nonexistant type returns an empty dict. - When true, returns `{add_key: d}` - Returns: - Dict. - """ - if isinstance(d, dict): return d - log.dbg_message(log.from_class_and_text(d)) - if isinstance(d, Thing): return log.dbg_return(d.__dict__) - if isinstance(d, Tuple) and hasattr(d, '_fields'): - return log.dbg_return(d._asdict()) - if not_exists(d, allow_none): return log.dbg_return({}) - return log.dbg_return( - {add_key: d}, - '{%s: %s}' % (log.text_of(add_key), log.text_of(d)) - ) - - -def dict_get( - d: ..., key: ... = 'default', default: ... = MISSING, - add_key: ... = 'default', allow_none: bool = False -) -> ...: +def dict_get(obj: DictOrNothing, key: ..., default: ... = MISSING) -> ...: try: - return enforce_dict(d, add_key, allow_none).get(key, default) + return log.dbg_return(enforce_dict(obj).get(key, default)) except TypeError: return log.dbg_return(default, 'invalid key type') -def in_dict(look_for: ..., look_in: ..., keys: ... = UNSPECIFIED) -> bool: - """Checks if look_for is a value of a dict enforced from look_in. - - If the value of a key is a list, searches the elements of the list. - Example: `i in {key: i}` and `i in {key: [i, j, k]}` will both return True. - - Args: - look_for: Item to be checked. - look_in: Dictionary. If not dict type will be converted to dict. - keys: If unspecified, will look in the values of all keys of dict. - - Returns: - bool. - """ - enforced = enforce_dict(look_in) - key_list = enforce_list(keys) if is_specified(keys) else list(enforced.keys()) - for k in key_list: - if in_list(look_for, dict_get(enforced, k)): return True - return False - - -def enforce_set( - s: ..., enf_dict: bool = True, allow_none: bool = False -) -> set[Any]: - """Enforces set type. +def enforce_set(obj: SetOrNothing) -> set[Any]: + """Enforces set type for set or Nothing arguments.""" + if isinstance(obj, set): return obj + return log.dbg_return(set(), log.from_class_and_text(obj)) - If s is a set, returns s. If s is iterable returns set(s). Else returns {s}. - If an object is unhashable, converts it to a Thing whose value is the - unhashable object. - Args: - s: Object to be converted to set. - enf_dict: When true, returns a set of values of dict. When false, returns - a set of tuples where the first element is the key and the second is the - value. - allow_none: When false, if s is None returns an empty set. When true, - returns `{None}`. - - Returns: - Set. - """ - if isinstance(s, set): return s - log.dbg_message(log.from_class_and_text(s)) - if not_exists(s, allow_none): return log.dbg_return(set()) - if isinstance(s, str): return log.dbg_return({s}) - if isinstance(s, dict): - s = set(enforce_list(s)) if enf_dict else {(k, v) for k, v in s.items()} - return log.dbg_return(s) - result = set() - if isinstance(s, Iterable): - for element in s: - try: - result.add(element) - except TypeError: - result.add(Thing.from_value_of(element)) - else: - try: - result.add(s) - except TypeError: - result.add(Thing.from_value_of(s)) - return log.dbg_return(result) - - -def in_set( - look_for: ..., look_in: ..., - enf_dict: bool = True, allow_none: bool = False -) -> bool: - return look_for in enforce_set(look_in, enf_dict, allow_none) - - -def in_enforced( - look_for: ..., look_in: ..., keys: ... = UNSPECIFIED, - enf_list: bool = True, enf_dict: bool = True, enf_set: bool = True, - enf_range: bool = False, allow_none: bool = False -) -> bool: - """Checks if look_for is in enforced type look_in.""" - if not_exists(look_for, allow_none): return False - if is_specified(keys) and not enf_dict and not_instance(look_in, dict): - return log.dbg_return_false( - 'key for non-dict argument %s' % log.text_of(look_in) - ) - if ( - (enf_list and in_list(look_for, look_in)) or - (enf_dict and in_dict(look_for, look_in, keys)) or - (enf_range and in_range(look_for, look_in)) or - (enf_set and in_set(look_for, look_in)) - ): return True - return False - - -def in_attribute( - look_for: ..., thing: ..., attr: str, keys: ... = UNSPECIFIED, - enf_list: bool = True, enf_dict: bool = True, enf_range: bool = False, - allow_none: bool = False -) -> bool: - """Checks if look_for is in an enforced type attribute of thing.""" - return in_enforced( - look_for, get_attribute(thing, attr), - keys, enf_list, enf_dict, enf_range, allow_none - ) +def in_set(look_for: ..., look_in: ...) -> bool: + return log.dbg_return_in(look_for, enforce_set(look_in)) diff --git a/nisaba/scripts/natural_translit/utils/type_op_test.py b/nisaba/scripts/natural_translit/utils/type_op_test.py index 86392394..65398678 100644 --- a/nisaba/scripts/natural_translit/utils/type_op_test.py +++ b/nisaba/scripts/natural_translit/utils/type_op_test.py @@ -14,15 +14,11 @@ """Tests for type_op.""" -import collections - from absl.testing import absltest from nisaba.scripts.natural_translit.utils import type_op as t # Test objects -D = collections.namedtuple('D', ['k']) -_D1 = D('v') _T0 = t.Thing.with_alias_and_value('T0', 0) _T1 = t.Thing.with_alias('T1') _T2 = t.Thing.from_value_of(_T0) @@ -95,9 +91,6 @@ def test_is_instance_dbg(self): def test_not_instance(self): self.assertTrue(t.not_instance(1, str)) - def test_not_instance_invalid_type(self): - self.assertTrue(t.not_instance(1, t.MISSING)) - def test_make_thing(self): self.assertEqual(_T0.value, 0) @@ -107,12 +100,6 @@ def test_make_thing_default_value(self): def test_make_thing_inherit_value(self): self.assertEqual(_T2.value, 0) - def test_enforce_thing_thing(self): - self.assertEqual(t.enforce_thing(_T1), _T1) - - def test_enforce_thing_int(self): - self.assertEqual(t.enforce_thing(0).value, 0) - def test_has_attribute(self): self.assertTrue(t.has_attribute(complex(1, 2), 'real')) @@ -123,10 +110,10 @@ def test_has_attribute_none(self): self.assertFalse(t.has_attribute(None, 'real')) def test_has_attribute_type(self): - self.assertTrue(t.has_attribute(complex(1, 2), 'real', want=float)) + self.assertTrue(t.has_attribute(complex(1, 2), 'real', typeinfo=float)) def test_has_attribute_type_false(self): - self.assertFalse(t.has_attribute(complex(1, 2), 'real', want=str)) + self.assertFalse(t.has_attribute(complex(1, 2), 'real', typeinfo=str)) def test_get_attribute(self): self.assertEqual(t.get_attribute(complex(1, 2), 'real'), 1.0) @@ -136,7 +123,7 @@ def test_get_attribute_default(self): def test_get_attribute_type(self): self.assertEqual( - t.get_attribute(complex(1, 2), 'real', want=int, default=-1), -1 + t.get_attribute(complex(1, 2), 'real', typeinfo=int, default=-1), -1 ) def test_is_equal(self): @@ -216,29 +203,23 @@ def test_not_equal_nothing(self): def test_is_empty_list(self): self.assertTrue(t.is_empty([])) - def test_not_empty_list(self): - self.assertTrue(t.not_empty([1])) - def test_is_empty_range(self): self.assertTrue(t.is_empty(range(0))) def test_is_empty_set(self): self.assertTrue(t.is_empty(set())) - def test_not_empty_non_iterable(self): - self.assertTrue(t.not_empty(_T1)) - - def test_not_empty_zero(self): - self.assertTrue(t.not_empty(0)) + def test_not_empty_set(self): + self.assertTrue(t.not_empty({1})) - def test_is_empty_unassigned(self): - self.assertTrue(t.is_empty(t.UNASSIGNED)) + def test_is_empty_non_iterable(self): + self.assertFalse(t.is_empty(_T1)) def test_is_empty_none(self): - self.assertTrue(t.is_empty(None)) + self.assertFalse(t.is_empty(None)) - def test_not_empty_allow_none(self): - self.assertTrue(t.not_empty(None, allow_none=True)) + def test_not_empty_none(self): + self.assertFalse(t.not_empty(None)) def test_get_element(self): self.assertEqual(t.get_element([1, 2, 3], 1), 2) @@ -255,184 +236,71 @@ def test_get_element_out_of_index(self): def test_get_element_default(self): self.assertEqual(t.get_element([1, 2, 3], 4, default=0), 0) - def test_enforce_range_1(self): - self.assertEqual(t.enforce_range(3), range(3)) - - def test_enforce_range_2(self): - self.assertEqual(t.enforce_range(1, 3), range(1, 3)) + def test_enforce_range(self): + self.assertEqual(t.enforce_range(1, 3, 0, 10), range(1, 3)) - def test_enforce_range_3(self): - self.assertEqual(t.enforce_range(1, 3, 2), range(1, 3, 2)) - - def test_enforce_range_none(self): - self.assertEqual(t.enforce_range(1, None), range(0)) - - def test_enforce_range_none_def_stop(self): - self.assertEqual( - t.enforce_range(1, None, def_stop=len([0, 1, 2])), - range(1, 3) - ) - - def test_enforce_range_none_def_start(self): - self.assertEqual( - t.enforce_range(None, 3, def_start=1), - range(1, 3) - ) + def test_enforce_range_start_nothing(self): + self.assertEqual(t.enforce_range(t.MISSING, 3), range(0)) - def test_enforce_range_tuple(self): - self.assertEqual(t.enforce_range((1, 3)), range(1, 3)) + def test_enforce_range_stop_nothing(self): + self.assertEqual(t.enforce_range(1, t.MISSING), range(0)) - def test_enforce_range_tuple_none(self): - self.assertEqual(t.enforce_range((1, None)), range(0)) - - def test_enforce_range_tuple_none_def_stop(self): - self.assertEqual(t.enforce_range((1, None), def_stop=3), range(1, 3)) - - def test_enforce_range_tuple_step_in(self): - self.assertEqual(t.enforce_range((1, 3, 2)), range(1, 3, 2)) - - def test_enforce_range_tuple_step_out(self): - self.assertEqual(t.enforce_range((1, 3), 2), range(1, 3, 2)) - - def test_enforce_range_tuple_too_long(self): - self.assertEqual(t.enforce_range((1, 3, 2, 2)), range(0)) - - def test_enforce_range_tuple_step_in_and_out(self): - self.assertEqual(t.enforce_range((1, 3, 2), 2), range(0)) - - def test_enforce_range_bad_start(self): - self.assertEqual(t.enforce_range(_T1, 3), range(0)) - - def test_enforce_range_bad_stop(self): - self.assertEqual(t.enforce_range(1, '3'), range(0)) - - def test_enforce_range_bad_step(self): - self.assertEqual(t.enforce_range(1, 3, [1]), range(0)) + def test_enforce_range_default(self): + self.assertEqual(t.enforce_range(t.MISSING, t.MISSING, 0, 10), range(0, 10)) def test_in_range(self): self.assertTrue(t.in_range(1, 0, 5)) - def test_in_range_step_false(self): - self.assertFalse(t.in_range(1, 0, 5, 2)) + def test_in_range_nothing(self): + self.assertFalse(t.in_range(t.MISSING, 0, 5)) def test_in_range_tuple(self): - self.assertTrue(t.in_range(1, (0, 5))) + self.assertNotIn(t.MISSING, range(0, 5)) def test_enforce_list(self): self.assertEqual(t.enforce_list([0, 1]), [0, 1]) - def test_enforce_list_dict(self): - self.assertEqual(t.enforce_list({'k': 'v'}), ['v']) - - def test_enforce_list_enf_dict_false(self): - self.assertEqual( - t.enforce_list({'k': 'v'}, enf_dict=False), [{'k': 'v'}] - ) - - def test_enforce_list_iter(self): - self.assertEqual(t.enforce_list({'k': 'v'}.values()), ['v']) - - def test_enforce_list_range(self): - self.assertEqual(t.enforce_list(range(0, 5, 2)), [0, 2, 4]) - - def test_enforce_list_none(self): - self.assertEqual(t.enforce_list(None), []) - - def test_enforce_list_none_true(self): - self.assertEqual( - t.enforce_list(None, allow_none=True), [None] - ) + def test_enforce_list_nothing(self): + self.assertEqual(t.enforce_list(t.UNSPECIFIED), []) def test_in_list(self): - self.assertTrue(t.in_list(3, range(1, 5))) + self.assertTrue(t.in_list(1, [0, 1])) + + def test_in_list_nothing(self): + self.assertFalse(t.in_list(3, t.MISSING)) def test_enforce_dict(self): self.assertEqual(t.enforce_dict({'k': 'v'}), {'k': 'v'}) - def test_enforce_dict_namedtuple(self): - self.assertEqual(t.enforce_dict(_D1), {'k': 'v'}) - - def test_enforce_dict_thing(self): - self.assertEqual( - t.enforce_dict(_T1), {'alias': 'T1', 'text': 'Thing_T1', 'value': _T1} - ) - - def test_enforce_dict_no_key(self): - self.assertEqual(t.enforce_dict('v'), {'default': 'v'}) - - def test_enforce_dict_with_key(self): - self.assertEqual(t.enforce_dict('v', add_key='k'), {'k': 'v'}) - - def test_enforce_dict_none(self): - self.assertEqual(t.enforce_dict(None), {}) - - def test_enforce_dict_none_true(self): - self.assertEqual( - t.enforce_dict(None, allow_none=True), {'default': None} - ) + def test_enforce_dict_nothing(self): + self.assertEqual(t.enforce_dict(t.UNSPECIFIED), {}) - def test_dict_get(self): - self.assertEqual(t.dict_get('v'), 'v') + def test_dict_get_existing_key(self): + self.assertEqual(t.dict_get({'k': 'v'}, 'k'), 'v') - def test_dict_get_with_key(self): - self.assertTrue(t.not_found(t.dict_get('v', key='k'))) + def test_dict_get_missing_key(self): + self.assertEqual(t.dict_get({'k': 'v'}, 'k2'), t.MISSING) - def test_dict_get_with_key_unhashable(self): - self.assertTrue(t.not_found(t.dict_get('v', key=['a']))) + def test_dict_get_missing_key_with_default(self): + self.assertEqual(t.dict_get({'k': 'v'}, 'k2', 'def'), 'def') - def test_dict_get_with_default(self): - self.assertEqual(t.dict_get('v', key='k', default=[]), []) + def test_dict_get_unhashable_key(self): + self.assertEqual(t.dict_get({'k': 'v'}, ['k']), t.MISSING) - def test_in_dict(self): - self.assertTrue(t.in_dict('v', {'k': ['v', 'v2']})) - - def test_in_dict_with_keys(self): - self.assertTrue(t.in_dict('v', {'k': ['v', 'v2']}, keys='k')) + def test_dict_get_nothing(self): + self.assertEqual(t.dict_get(t.UNSPECIFIED, 'k'), t.MISSING) def test_enforce_set(self): self.assertEqual(t.enforce_set({1, 2, 3}), {1, 2, 3}) - def test_enforce_set_int(self): - self.assertEqual(t.enforce_set(1), {1}) - - def test_enforce_set_list(self): - self.assertEqual(t.enforce_set([1, 2, 3, 3]), {1, 2, 3}) - - def test_enforce_set_empty_list(self): - self.assertEqual(t.enforce_set([]), set()) - - def test_enforce_set_dict(self): - self.assertEqual(t.enforce_set({'k1': 'v1', 'k2': 'v2'}), {'v1', 'v2'}) - - def test_enforce_set_dict_false(self): - self.assertEqual( - t.enforce_set({'k1': 'v1', 'k2': 'v2'}, enf_dict=False), - {('k1', 'v1'), ('k2', 'v2')}, - ) - - def test_enforce_set_list_of_unhashable(self): - self.assertNotEmpty(t.enforce_set([[1], [2], [3]])) - - def test_enforce_set_str(self): - self.assertEqual(t.enforce_set({'abc'}), {('abc')}) - - def test_enforce_set_none(self): - self.assertEqual(t.enforce_set(None), set()) - - def test_enforce_set_allow_none(self): - self.assertEqual(t.enforce_set(None, allow_none=True), {None}) + def test_enforce_set_nothing(self): + self.assertEqual(t.enforce_set(t.MISSING), set()) def test_in_set(self): self.assertTrue(t.in_set(1, {1, 2, 3})) - def test_in_set_int(self): - self.assertTrue(t.in_set(1, 1)) - - def test_in_enforced_key_non_dict(self): - self.assertFalse(t.in_enforced('v', ['k', 'v'], keys='k', enf_dict=False)) - - def test_in_attribute(self): - self.assertTrue(t.in_attribute(1.0, complex(1, 2), 'real')) + def test_in_set_nothing(self): + self.assertFalse(t.in_set(1, t.UNSPECIFIED)) if __name__ == '__main__':