Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Cleanup type_op. Remove unused features and functions.
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 584888317
isingoo authored and copybara-github committed Nov 24, 2023
1 parent af0b07c commit b955b77
Showing 5 changed files with 202 additions and 434 deletions.
2 changes: 1 addition & 1 deletion nisaba/scripts/natural_translit/utils/list_op.py
Original file line number Diff line number Diff line change
@@ -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))


32 changes: 28 additions & 4 deletions nisaba/scripts/natural_translit/utils/log_op.py
Original file line number Diff line number Diff line change
@@ -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 '<no_text>'


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)
26 changes: 26 additions & 0 deletions nisaba/scripts/natural_translit/utils/log_op_test.py
Original file line number Diff line number Diff line change
@@ -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_<no_text>'
)

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()
358 changes: 104 additions & 254 deletions nisaba/scripts/natural_translit/utils/type_op.py
Original file line number Diff line number Diff line change
@@ -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]
# <class>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,69 +204,65 @@ 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.
Returns:
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,48 +321,57 @@ 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:
return log.dbg_return(default, 'index error')


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))
218 changes: 43 additions & 175 deletions nisaba/scripts/natural_translit/utils/type_op_test.py
Original file line number Diff line number Diff line change
@@ -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__':

0 comments on commit b955b77

Please sign in to comment.