From 5eff5befe5a470d3a8ed0f9dd4714b0156771b4a Mon Sep 17 00:00:00 2001 From: "Eric O. Korman" Date: Thu, 4 Jul 2024 23:15:56 -0500 Subject: [PATCH] have comparisons return bool when both objects are values (#611) --- client/unit-tests/coretypes/test_filtering.py | 14 +- client/unit-tests/schemas/test_label.py | 67 ++++++- .../symbolic/collections/test_structures.py | 27 +-- .../unit-tests/symbolic/types/test_schemas.py | 44 ++-- .../symbolic/types/test_symbolic_types.py | 189 +++++++++--------- client/valor/schemas/symbolic/types.py | 72 +++---- .../client/datasets/test_dataset.py | 5 + integration_tests/client/models/test_model.py | 4 + 8 files changed, 244 insertions(+), 178 deletions(-) diff --git a/client/unit-tests/coretypes/test_filtering.py b/client/unit-tests/coretypes/test_filtering.py index 9916e84c9..366935067 100644 --- a/client/unit-tests/coretypes/test_filtering.py +++ b/client/unit-tests/coretypes/test_filtering.py @@ -4,7 +4,7 @@ import pytest from valor import Annotation, Dataset, Filter, Label, Model -from valor.schemas import And, Polygon +from valor.schemas import And, Eq, Gt, Lt, Polygon @pytest.fixture @@ -36,14 +36,22 @@ def test_complex_filter( geojson: Dict[str, Union[str, List[List[Tuple[float, float]]]]], polygon: Polygon, ): + # check expression types (this also makes pyright pass) + model_name_eq_x = Model.name == "x" + assert isinstance(model_name_eq_x, Eq) + annotation_raster_area_gt = Annotation.raster.area > 100 + assert isinstance(annotation_raster_area_gt, Gt) + annotation_raster_area_lt = Annotation.raster.area < 500 + assert isinstance(annotation_raster_area_lt, Lt) + filter_from_constraints = Filter( annotations=And( Dataset.name.in_(["a", "b", "c"]), - (Model.name == "x") | Model.name.in_(["y", "z"]), + model_name_eq_x | Model.name.in_(["y", "z"]), Label.score > 0.75, Annotation.polygon.area > 1000, Annotation.polygon.area < 5000, - (Annotation.raster.area > 100) & (Annotation.raster.area < 500), + annotation_raster_area_gt & annotation_raster_area_lt, Dataset.metadata["some_str"] == "foobar", Dataset.metadata["some_float"] >= 0.123, Dataset.metadata["some_datetime"] > datetime.timedelta(days=1), diff --git a/client/unit-tests/schemas/test_label.py b/client/unit-tests/schemas/test_label.py index f58e86975..13fb61326 100644 --- a/client/unit-tests/schemas/test_label.py +++ b/client/unit-tests/schemas/test_label.py @@ -51,21 +51,21 @@ def test_scored_label(): assert l1.value == "value" # test member fn `__eq__` - assert (s1 == s2).get_value() # type: ignore - resolved to 'Bool' as both sides are values - assert (s1 == s6).get_value() # type: ignore - resolved to 'Bool' as both sides are values - assert not (s1 == s3).get_value() # type: ignore - resolved to 'Bool' as both sides are values - assert not (s1 == s4).get_value() # type: ignore - resolved to 'Bool' as both sides are values - assert not (s1 == s5).get_value() # type: ignore - resolved to 'Bool' as both sides are values + assert s1 == s2 + assert s1 == s6 + assert not (s1 == s3) + assert not (s1 == s4) + assert not (s1 == s5) with pytest.raises(TypeError): assert s1 == 123 with pytest.raises(TypeError): assert s1 == "123" # test member fn `__ne__` - assert not (s1 != s2).get_value() # type: ignore - resolved to 'Bool' as both sides are values - assert (s1 != s3).get_value() # type: ignore - resolved to 'Bool' as both sides are values - assert (s1 != s4).get_value() # type: ignore - resolved to 'Bool' as both sides are values - assert (s1 != s5).get_value() # type: ignore - resolved to 'Bool' as both sides are values + assert not (s1 != s2) + assert s1 != s3 + assert s1 != s4 + assert s1 != s5 with pytest.raises(TypeError): assert s1 != 123 with pytest.raises(TypeError): @@ -76,3 +76,52 @@ def test_scored_label(): assert s1.__hash__() != s3.__hash__() assert s1.__hash__() != s4.__hash__() assert s1.__hash__() != s5.__hash__() + + +def test_label_equality(): + label1 = Label(key="test", value="value") + label2 = Label(key="test", value="value") + label3 = Label(key="test", value="other") + label4 = Label(key="other", value="value") + + eq1 = label1 == label2 + assert type(eq1) == bool + assert eq1 + + eq2 = label1 == label3 + assert type(eq2) == bool + assert not eq2 + + eq3 = label1 == label4 + assert type(eq3) == bool + assert not eq3 + + +def test_label_score(): + label1 = Label(key="test", value="value", score=0.5) + label2 = Label(key="test", value="value", score=0.5) + label3 = Label(key="test", value="value", score=0.1) + + b1 = label1.score == label2.score + assert type(b1) == bool + assert b1 + + b2 = label1.score > label3.score + assert type(b2) == bool + assert b2 + + b3 = label1.score < label3.score + assert type(b3) == bool + assert not b3 + + b4 = label1.score >= label2.score + assert type(b4) == bool + assert b4 + + b5 = label1.score != label3.score + assert type(b5) == bool + assert b5 + + b6 = label1.score != label2.score + assert type(b6) == bool + assert not b6 diff --git a/client/unit-tests/symbolic/collections/test_structures.py b/client/unit-tests/symbolic/collections/test_structures.py index f1b2b554c..355d5d17d 100644 --- a/client/unit-tests/symbolic/collections/test_structures.py +++ b/client/unit-tests/symbolic/collections/test_structures.py @@ -207,7 +207,9 @@ def test_list(): assert variable[0].get_value() == 0.1 # test comparison symbol -> value - assert (symbol == [0.1, 0.2, 0.3]).to_dict() == { + eq = symbol == [0.1, 0.2, 0.3] + assert isinstance(eq, Eq) + assert eq.to_dict() == { "op": "eq", "lhs": { "name": "list[float]", @@ -217,7 +219,9 @@ def test_list(): } # test comparison symbol -> valued variable - assert (symbol == variable).to_dict() == { + eq = symbol == variable + assert isinstance(eq, Eq) + assert eq.to_dict() == { "op": "eq", "lhs": { "name": "list[float]", @@ -236,10 +240,7 @@ def test_list(): ] # test comparison between valued variable and value - assert (variable == [0.1, 0.2, 0.3]).to_dict() == { - "type": "boolean", - "value": True, - } + assert variable == [0.1, 0.2, 0.3] # test setting list to non-list type with pytest.raises(TypeError): @@ -303,9 +304,9 @@ def test_dictionary_value(): assert ( DictionaryValue.symbolic(name="a", key="b").is_not_none() ).to_dict()["op"] == "isnotnull" - assert (DictionaryValue.symbolic(name="a", key="b").area == 0).to_dict()[ - "op" - ] == "eq" + eq = DictionaryValue.symbolic(name="a", key="b") == 0 + assert isinstance(eq, Eq) + assert eq.to_dict()["op"] == "eq" # test router with Variable type assert (DictionaryValue.symbolic(name="a", key="b") == Float(0)).to_dict()[ @@ -368,12 +369,12 @@ def test_dictionary(): # test nullable v1 = objcls.nullable(None) assert v1.get_value() is None - assert v1.is_none().get_value() is True # type: ignore - issue #604 - assert v1.is_not_none().get_value() is False # type: ignore - issue #604 + assert v1.is_none() # type: ignore - issue #604 + assert not v1.is_not_none() # type: ignore - issue #604 v2 = objcls.nullable(permutations[0][0]) assert v2.get_value() is not None - assert v2.is_none().get_value() is False # type: ignore - issue #604 - assert v2.is_not_none().get_value() is True # type: ignore - issue #604 + assert not v2.is_none() # type: ignore - issue #604 + assert v2.is_not_none() # type: ignore - issue #604 # test encoding assert { diff --git a/client/unit-tests/symbolic/types/test_schemas.py b/client/unit-tests/symbolic/types/test_schemas.py index 0c8438717..cb0fc40d6 100644 --- a/client/unit-tests/symbolic/types/test_schemas.py +++ b/client/unit-tests/symbolic/types/test_schemas.py @@ -115,9 +115,9 @@ def _test_resolvable( truth = a.__getattribute__(op)(b) # test variable -> builtin against truth - assert A.__getattribute__(op)(b).get_value() is truth + assert A.__getattribute__(op)(b) is truth # test variable -> variable against truth - assert A.__getattribute__(op)(B).get_value() is truth + assert A.__getattribute__(op)(B) is truth # test dictionary generation dictA = A.to_dict() assert A.get_value() == a @@ -166,12 +166,12 @@ def test_score(): # test nullable v1 = objcls.nullable(None) assert v1.get_value() is None - assert v1.is_none().get_value() is True # type: ignore - issue #604 - assert v1.is_not_none().get_value() is False # type: ignore - issue #604 + assert v1.is_none() is True + assert v1.is_not_none() is False v2 = objcls.nullable(permutations[0][0]) assert v2.get_value() is not None - assert v2.is_none().get_value() is False # type: ignore - issue #604 - assert v2.is_not_none().get_value() is True # type: ignore - issue #604 + assert v2.is_none() is False + assert v2.is_not_none() is True # test unsupported methods for op in [ @@ -221,12 +221,12 @@ def test_tasktypeenum(): # test nullable v1 = objcls.nullable(None) assert v1.get_value() is None - assert v1.is_none().get_value() is True # type: ignore - issue #604 - assert v1.is_not_none().get_value() is False # type: ignore - issue #604 + assert v1.is_none() is True + assert v1.is_not_none() is False v2 = objcls.nullable(permutations[0][0]) assert v2.get_value() is not None - assert v2.is_none().get_value() is False # type: ignore - issue #604 - assert v2.is_not_none().get_value() is True # type: ignore - issue #604 + assert v2.is_none() is False + assert v2.is_not_none() is True # test encoding _test_encoding( @@ -273,12 +273,12 @@ def test_box(): # test nullable v1 = objcls.nullable(None) assert v1.get_value() is None - assert v1.is_none().get_value() is True # type: ignore - issue #604 - assert v1.is_not_none().get_value() is False # type: ignore - issue #604 + assert v1.is_none() is True + assert v1.is_not_none() is False v2 = objcls.nullable(permutations[0][0]) assert v2.get_value() is not None - assert v2.is_none().get_value() is False # type: ignore - issue #604 - assert v2.is_not_none().get_value() is True # type: ignore - issue #604 + assert v2.is_none() is False + assert v2.is_not_none() is True # test unsupported methods for op in [ @@ -338,12 +338,12 @@ def test_raster(): # test nullable v1 = objcls.nullable(None) assert v1.get_value() is None - assert v1.is_none().get_value() is True # type: ignore - issue #604 - assert v1.is_not_none().get_value() is False # type: ignore - issue #604 + assert v1.is_none() is True + assert v1.is_not_none() is False v2 = objcls.nullable(permutations[0][0]) assert v2.get_value() is not None - assert v2.is_none().get_value() is False # type: ignore - issue #604 - assert v2.is_not_none().get_value() is True # type: ignore - issue #604 + assert v2.is_none() is False + assert v2.is_not_none() is True # test 'from_numpy' classmethod assert Raster.from_numpy(bitmask1).to_dict() == Raster(value).to_dict() @@ -420,12 +420,12 @@ def test_embedding(): # test nullable v1 = objcls.nullable(None) assert v1.get_value() is None - assert v1.is_none().get_value() is True # type: ignore - issue #604 - assert v1.is_not_none().get_value() is False # type: ignore - issue #604 + assert v1.is_none() is True + assert v1.is_not_none() is False v2 = objcls.nullable(permutations[0][0]) assert v2.get_value() is not None - assert v2.is_none().get_value() is False # type: ignore - issue #604 - assert v2.is_not_none().get_value() is True # type: ignore - issue #604 + assert v2.is_none() is False + assert v2.is_not_none() is True # test unsupported methods for op in [ diff --git a/client/unit-tests/symbolic/types/test_symbolic_types.py b/client/unit-tests/symbolic/types/test_symbolic_types.py index 3320e9614..2e683cf6c 100644 --- a/client/unit-tests/symbolic/types/test_symbolic_types.py +++ b/client/unit-tests/symbolic/types/test_symbolic_types.py @@ -3,7 +3,14 @@ import pytest -from valor.schemas.symbolic.operators import Condition, Eq, Function, Ne +from valor.schemas.symbolic.operators import ( + Condition, + Eq, + Function, + IsNotNull, + IsNull, + Ne, +) from valor.schemas.symbolic.types import ( Boolean, Date, @@ -85,7 +92,9 @@ def test_variable(): _test_symbolic_outputs(var_method2) # test is_none - assert Variable.symbolic().is_none().to_dict() == { + is_none = Variable.symbolic().is_none() + assert isinstance(is_none, IsNull) + assert is_none.to_dict() == { "op": "isnull", "lhs": { "name": "variable", @@ -94,13 +103,15 @@ def test_variable(): "rhs": None, } assert Variable.symbolic().get_symbol() == Symbol(name="variable") - assert Variable(None).is_none().get_value() is True # type: ignore - issue #604 - assert Variable(1234).is_none().get_value() is False # type: ignore - issue #604 + assert Variable(None).is_none() is True + assert Variable(1234).is_none() is False with pytest.raises(TypeError): Variable(1234).get_symbol() # test is_not_none - assert Variable.symbolic().is_not_none().to_dict() == { + is_not_none = Variable.symbolic().is_not_none() + assert isinstance(is_not_none, IsNotNull) + assert is_not_none.to_dict() == { "op": "isnotnull", "lhs": { "name": "variable", @@ -108,8 +119,8 @@ def test_variable(): }, "rhs": None, } - assert Variable(None).is_not_none().get_value() is False # type: ignore - issue #604 - assert Variable(1234).is_not_none().get_value() is True # type: ignore - issue #604 + assert Variable(None).is_not_none() is False + assert Variable(1234).is_not_none() is True def _test_equatable(varA, varB, varC): @@ -441,13 +452,9 @@ def _test_resolvable( A = objcls(a) B = objcls(b) # test variable -> builtin against truth - assert A.__getattribute__(op)(b).get_value() is a.__getattribute__(op)( - b - ) + assert A.__getattribute__(op)(b) is a.__getattribute__(op)(b) # test variable -> variable against truth - assert A.__getattribute__(op)(B).get_value() is a.__getattribute__(op)( - b - ) + assert A.__getattribute__(op)(B) is a.__getattribute__(op)(b) # test dictionary generation dictA = A.to_dict() assert A.get_value() == a @@ -477,8 +484,8 @@ def test_bool(): # test supported methods for op in ["__eq__", "__ne__", "__and__", "__or__"]: _test_resolvable(objcls, permutations, op) - assert (~Boolean(True)).get_value() is False # type: ignore - this will always return a bool - assert (~Boolean(False)).get_value() is True # type: ignore - this will always return a bool + assert (~Boolean(True)) is False + assert (~Boolean(False)) is True # test unsupported methods for op in [ @@ -495,33 +502,33 @@ def test_bool(): # test nullable v1 = objcls.nullable(None) assert v1.get_value() is None - assert v1.is_none().get_value() is True # type: ignore - issue #604 - assert v1.is_not_none().get_value() is False # type: ignore - issue #604 + assert v1.is_none() is True + assert v1.is_not_none() is False v2 = objcls.nullable(permutations[0][0]) assert v2.get_value() is not None - assert v2.is_none().get_value() is False # type: ignore - issue #604 - assert v2.is_not_none().get_value() is True # type: ignore - issue #604 + assert v2.is_none() is False + assert v2.is_not_none() is True # test encoding _test_encoding(objcls, True, True) _test_encoding(objcls, False, False) # test and operation - assert (Boolean(True) & Boolean(True)).get_value() is True # type: ignore - issue #604 - assert (Boolean(True) & Boolean(False)).get_value() is False # type: ignore - issue #604 - assert (Boolean(False) & Boolean(True)).get_value() is False # type: ignore - issue #604 - assert (Boolean(False) & Boolean(False)).get_value() is False # type: ignore - issue #604 + assert (Boolean(True) & Boolean(True)) is True + assert (Boolean(True) & Boolean(False)) is False + assert (Boolean(False) & Boolean(True)) is False + assert (Boolean(False) & Boolean(False)) is False # test or operation - assert (Boolean(True) | Boolean(True)).get_value() is True # type: ignore - issue #604 - assert (Boolean(True) | Boolean(False)).get_value() is True # type: ignore - issue #604 - assert (Boolean(False) | Boolean(True)).get_value() is True # type: ignore - issue #604 - assert (Boolean(False) | Boolean(False)).get_value() is False # type: ignore - issue #604 + assert (Boolean(True) | Boolean(True)) is True + assert (Boolean(True) | Boolean(False)) is True + assert (Boolean(False) | Boolean(True)) is True + assert (Boolean(False) | Boolean(False)) is False # test negation operation - assert (~Boolean(True)).get_value() is False # type: ignore - issue #604 - assert (~Boolean(False)).get_value() is True # type: ignore - issue #604 - assert (~Boolean.symbolic()).to_dict() == { + assert (~Boolean(True)) is False + assert (~Boolean(False)) is True + assert (~Boolean.symbolic()).to_dict() == { # type: ignore "op": "not", "args": { "name": "boolean", @@ -555,28 +562,20 @@ def test_integer(): _test_unsupported(objcls, permutations, op) # test equatable - assert ( - Integer.nullable(None) == Integer(1) - ).get_value() is False # type: ignore - issue #604 - assert ( - Integer(1) == Integer.nullable(None) - ).get_value() is False # type: ignore - issue #604 - assert ( - Integer.nullable(None) != Integer(1) - ).get_value() is True # type: ignore - issue #604 - assert ( - Integer(1) != Integer.nullable(None) - ).get_value() is True # type: ignore - issue #604 + assert (Integer.nullable(None) == Integer(1)) is False + assert (Integer(1) == Integer.nullable(None)) is False + assert (Integer.nullable(None) != Integer(1)) is True + assert (Integer(1) != Integer.nullable(None)) is True # test nullable v1 = objcls.nullable(None) assert v1.get_value() is None - assert v1.is_none().get_value() is True # type: ignore - issue #604 - assert v1.is_not_none().get_value() is False # type: ignore - issue #604 + assert v1.is_none() is True + assert v1.is_not_none() is False v2 = objcls.nullable(permutations[0][0]) assert v2.get_value() is not None - assert v2.is_none().get_value() is False # type: ignore - issue #604 - assert v2.is_not_none().get_value() is True # type: ignore - issue #604 + assert v2.is_none() is False + assert v2.is_not_none() is True # test encoding _test_encoding(objcls, 10, 10) @@ -609,12 +608,12 @@ def test_float(): # test nullable v1 = objcls.nullable(None) assert v1.get_value() is None - assert v1.is_none().get_value() is True # type: ignore - issue #604 - assert v1.is_not_none().get_value() is False # type: ignore - issue #604 + assert v1.is_none() is True + assert v1.is_not_none() is False v2 = objcls.nullable(permutations[0][0]) assert v2.get_value() is not None - assert v2.is_none().get_value() is False # type: ignore - issue #604 - assert v2.is_not_none().get_value() is True # type: ignore - issue #604 + assert v2.is_none() is False + assert v2.is_not_none() is True # test encoding _test_encoding(objcls, 1.23, 1.23) @@ -651,12 +650,12 @@ def test_string(): # test nullable v1 = objcls.nullable(None) assert v1.get_value() is None - assert v1.is_none().get_value() is True # type: ignore - issue #604 - assert v1.is_not_none().get_value() is False # type: ignore - issue #604 + assert v1.is_none() is True + assert v1.is_not_none() is False v2 = objcls.nullable(permutations[0][0]) assert v2.get_value() is not None - assert v2.is_none().get_value() is False # type: ignore - issue #604 - assert v2.is_not_none().get_value() is True # type: ignore - issue #604 + assert v2.is_none() is False + assert v2.is_not_none() is True # test encoding _test_encoding(objcls, "hello", "hello") @@ -701,12 +700,12 @@ def test_datetime(): # test nullable v1 = objcls.nullable(None) assert v1.get_value() is None - assert v1.is_none().get_value() is True # type: ignore - issue #604 - assert v1.is_not_none().get_value() is False # type: ignore - issue #604 + assert v1.is_none() is True + assert v1.is_not_none() is False v2 = objcls.nullable(permutations[0][0]) assert v2.get_value() is not None - assert v2.is_none().get_value() is False # type: ignore - issue #604 - assert v2.is_not_none().get_value() is True # type: ignore - issue #604 + assert v2.is_none() is False + assert v2.is_not_none() is True # test encoding _test_encoding( @@ -755,12 +754,12 @@ def test_date(): # test nullable v1 = objcls.nullable(None) assert v1.get_value() is None - assert v1.is_none().get_value() is True # type: ignore - issue #604 - assert v1.is_not_none().get_value() is False # type: ignore - issue #604 + assert v1.is_none() is True + assert v1.is_not_none() is False v2 = objcls.nullable(permutations[0][0]) assert v2.get_value() is not None - assert v2.is_none().get_value() is False # type: ignore - issue #604 - assert v2.is_not_none().get_value() is True # type: ignore - issue #604 + assert v2.is_none() is False + assert v2.is_not_none() is True # test encoding _test_encoding( @@ -795,12 +794,12 @@ def test_time(): # test nullable v1 = objcls.nullable(None) assert v1.get_value() is None - assert v1.is_none().get_value() is True # type: ignore - issue #604 - assert v1.is_not_none().get_value() is False # type: ignore - issue #604 + assert v1.is_none() is True + assert v1.is_not_none() is False v2 = objcls.nullable(permutations[0][0]) assert v2.get_value() is not None - assert v2.is_none().get_value() is False # type: ignore - issue #604 - assert v2.is_not_none().get_value() is True # type: ignore - issue #604 + assert v2.is_none() is False + assert v2.is_not_none() is True # test encoding _test_encoding(objcls, datetime.time(hour=1), "01:00:00") @@ -833,12 +832,12 @@ def test_duration(): # test nullable v1 = objcls.nullable(None) assert v1.get_value() is None - assert v1.is_none().get_value() is True # type: ignore - issue #604 - assert v1.is_not_none().get_value() is False # type: ignore - issue #604 + assert v1.is_none() is True + assert v1.is_not_none() is False v2 = objcls.nullable(permutations[0][0]) - assert v2.get_value() is not None - assert v2.is_none().get_value() is False # type: ignore - issue #604 - assert v2.is_not_none().get_value() is True # type: ignore - issue #604 + assert v2 is not None + assert v2.is_none() is False + assert v2.is_not_none() is True # test encoding _test_encoding(objcls, datetime.timedelta(seconds=1), 1.0) @@ -867,12 +866,12 @@ def test_point(): # test nullable v1 = objcls.nullable(None) assert v1.get_value() is None - assert v1.is_none().get_value() is True # type: ignore - issue #604 - assert v1.is_not_none().get_value() is False # type: ignore - issue #604 + assert v1.is_none() is True + assert v1.is_not_none() is False v2 = objcls.nullable(permutations[0][0]) assert v2.get_value() is not None - assert v2.is_none().get_value() is False # type: ignore - issue #604 - assert v2.is_not_none().get_value() is True # type: ignore - issue #604 + assert v2.is_none() is False + assert v2.is_not_none() is True # test encoding _test_encoding(objcls, (1, -1), (1, -1)) @@ -903,12 +902,12 @@ def test_multipoint(): # test nullable v1 = objcls.nullable(None) assert v1.get_value() is None - assert v1.is_none().get_value() is True # type: ignore - issue #604 - assert v1.is_not_none().get_value() is False # type: ignore - issue #604 + assert v1.is_none() is True + assert v1.is_not_none() is False v2 = objcls.nullable(permutations[0][0]) assert v2.get_value() is not None - assert v2.is_none().get_value() is False # type: ignore - issue #604 - assert v2.is_not_none().get_value() is True # type: ignore - issue #604 + assert v2.is_none() is False + assert v2.is_not_none() is True # test encoding _test_encoding(objcls, [(0, 0), (1, 1)], [(0, 0), (1, 1)]) @@ -939,12 +938,12 @@ def test_linestring(): # test nullable v1 = objcls.nullable(None) assert v1.get_value() is None - assert v1.is_none().get_value() is True # type: ignore - issue #604 - assert v1.is_not_none().get_value() is False # type: ignore - issue #604 + assert v1.is_none() is True + assert v1.is_not_none() is False v2 = objcls.nullable(permutations[0][0]) assert v2.get_value() is not None - assert v2.is_none().get_value() is False # type: ignore - issue #604 - assert v2.is_not_none().get_value() is True # type: ignore - issue #604 + assert v2.is_none() is False + assert v2.is_not_none() is True # test encoding _test_encoding(objcls, [(0, 0), (1, 1)], [(0, 0), (1, 1)]) @@ -980,12 +979,12 @@ def test_multilinestring(): # test nullable v1 = objcls.nullable(None) assert v1.get_value() is None - assert v1.is_none().get_value() is True # type: ignore - issue #604 - assert v1.is_not_none().get_value() is False # type: ignore - issue #604 + assert v1.is_none() is True + assert v1.is_not_none() is False v2 = objcls.nullable(permutations[0][0]) assert v2.get_value() is not None - assert v2.is_none().get_value() is False # type: ignore - issue #604 - assert v2.is_not_none().get_value() is True # type: ignore - issue #604 + assert v2.is_none() is False + assert v2.is_not_none() is True # test encoding _test_encoding(objcls, [[(0, 0), (1, 1)]], [[(0, 0), (1, 1)]]) @@ -1024,12 +1023,12 @@ def test_polygon(): # test nullable v1 = objcls.nullable(None) assert v1.get_value() is None - assert v1.is_none().get_value() is True # type: ignore - issue #604 - assert v1.is_not_none().get_value() is False # type: ignore - issue #604 + assert v1.is_none() is True + assert v1.is_not_none() is False v2 = objcls.nullable(permutations[0][0]) assert v2.get_value() is not None - assert v2.is_none().get_value() is False # type: ignore - issue #604 - assert v2.is_not_none().get_value() is True # type: ignore - issue #604 + assert v2.is_none() is False + assert v2.is_not_none() is True # test encoding _test_encoding( @@ -1091,12 +1090,12 @@ def test_multipolygon(): # test nullable v1 = objcls.nullable(None) assert v1.get_value() is None - assert v1.is_none().get_value() is True # type: ignore - issue #604 - assert v1.is_not_none().get_value() is False # type: ignore - issue #604 + assert v1.is_none() is True + assert v1.is_not_none() is False v2 = objcls.nullable(permutations[0][0]) assert v2.get_value() is not None - assert v2.is_none().get_value() is False # type: ignore - issue #604 - assert v2.is_not_none().get_value() is True # type: ignore - issue #604 + assert v2.is_none() is False + assert v2.is_not_none() is True # test encoding _test_encoding( diff --git a/client/valor/schemas/symbolic/types.py b/client/valor/schemas/symbolic/types.py index da3d4f69e..48d9f60dc 100644 --- a/client/valor/schemas/symbolic/types.py +++ b/client/valor/schemas/symbolic/types.py @@ -311,44 +311,44 @@ def get_symbol(self) -> Symbol: raise TypeError(f"{type(self).__name__} is a valued object.") return self._value - def is_none(self) -> typing.Union["Boolean", IsNull]: + def is_none(self) -> typing.Union[bool, IsNull]: """Conditional whether variable is 'None'""" if self.is_value: - return Boolean(self.get_value() is None) + return self.get_value() is None return IsNull(self) - def is_not_none(self) -> typing.Union["Boolean", IsNotNull]: + def is_not_none(self) -> typing.Union[bool, IsNotNull]: """Conditional whether variable is not 'None'""" if self.is_value: - return Boolean(self.get_value() is not None) + return self.get_value() is not None return IsNotNull(self) - def __eq__(self, value: typing.Any) -> typing.Union["Boolean", Eq]: # type: ignore - overriding __eq__ + def __eq__(self, value: typing.Any) -> typing.Union[bool, Eq]: # type: ignore - overriding __eq__ raise AttributeError( f"'{type(self).__name__}' object has no attribute '__eq__'" ) - def __ne__(self, value: typing.Any) -> typing.Union["Boolean", Ne]: # type: ignore - overriding __ne__ + def __ne__(self, value: typing.Any) -> typing.Union[bool, Ne]: # type: ignore - overriding __ne__ raise AttributeError( f"'{type(self).__name__}' object has no attribute '__ne__'" ) - def __gt__(self, value: typing.Any) -> typing.Union["Boolean", Gt]: + def __gt__(self, value: typing.Any) -> typing.Union[bool, Gt]: raise AttributeError( f"'{type(self).__name__}' object has no attribute '__gt__'" ) - def __ge__(self, value: typing.Any) -> typing.Union["Boolean", Gte]: + def __ge__(self, value: typing.Any) -> typing.Union[bool, Gte]: raise AttributeError( f"'{type(self).__name__}' object has no attribute '__ge__'" ) - def __lt__(self, value: typing.Any) -> typing.Union["Boolean", Lt]: + def __lt__(self, value: typing.Any) -> typing.Union[bool, Lt]: raise AttributeError( f"'{type(self).__name__}' object has no attribute '__lt__'" ) - def __le__(self, value: typing.Any) -> typing.Union["Boolean", Lte]: + def __le__(self, value: typing.Any) -> typing.Union[bool, Lte]: raise AttributeError( f"'{type(self).__name__}' object has no attribute '__le__'" ) @@ -391,33 +391,33 @@ def __validate__(cls, value: typing.Any): f"Expected type '{bool}' received type '{type(value)}'" ) - def __eq__(self, value: typing.Any) -> typing.Union["Boolean", Eq]: + def __eq__(self, value: typing.Any) -> typing.Union[bool, Eq]: other = self.preprocess(value) if self.is_value and other.is_value: - return type(self)(self.get_value() is other.get_value()) + return self.get_value() is other.get_value() return Eq(self, other) - def __ne__(self, value: typing.Any) -> typing.Union["Boolean", Ne]: + def __ne__(self, value: typing.Any) -> typing.Union[bool, Ne]: other = self.preprocess(value) if self.is_value and other.is_value: - return type(self)(self.get_value() is not other.get_value()) + return self.get_value() is not other.get_value() return Ne(self, other) - def __and__(self, value: typing.Any) -> typing.Union["Boolean", And]: + def __and__(self, value: typing.Any) -> typing.Union[bool, And]: other = self.preprocess(value) if self.is_value and other.is_value: - return type(self)(self.get_value() and other.get_value()) + return self.get_value() and other.get_value() return And(self, other) - def __or__(self, value: typing.Any) -> typing.Union["Boolean", Or]: + def __or__(self, value: typing.Any) -> typing.Union[bool, Or]: other = self.preprocess(value) if self.is_value and other.is_value: - return type(self)(self.get_value() or other.get_value()) + return self.get_value() or other.get_value() return Or(self, other) - def __invert__(self) -> typing.Union["Boolean", Not]: + def __invert__(self) -> typing.Union[bool, Not]: if self.is_value: - return type(self)(not self.get_value()) + return not self.get_value() return Not(self) @@ -426,30 +426,30 @@ class Equatable(Variable): Variable modifier to handle equatable values. """ - def __eq__(self, value: typing.Any) -> typing.Union["Boolean", Eq]: + def __eq__(self, value: typing.Any) -> typing.Union[Eq, bool]: other = self.preprocess(value) if self.is_value and other.is_value: lhs = self.encode_value() rhs = other.encode_value() if lhs is None: - return Boolean(rhs is None) + return rhs is None elif rhs is None: - return Boolean(lhs is None) + return lhs is None else: - return Boolean(bool(lhs == rhs)) + return lhs == rhs return Eq(self, other) - def __ne__(self, value: typing.Any) -> typing.Union["Boolean", Ne]: + def __ne__(self, value: typing.Any) -> typing.Union[bool, Ne]: other = self.preprocess(value) if self.is_value and other.is_value: lhs = self.encode_value() rhs = other.encode_value() if lhs is None: - return Boolean(rhs is not None) + return rhs is not None elif rhs is None: - return Boolean(lhs is not None) + return lhs is not None else: - return Boolean(lhs != rhs) + return lhs != rhs return Ne(self, other) def in_(self, vlist: typing.List[typing.Any]) -> Or: @@ -467,28 +467,28 @@ class Quantifiable(Equatable): Variable modifier to handle quantifiable values. """ - def __gt__(self, value: typing.Any) -> typing.Union["Boolean", Gt]: + def __gt__(self, value: typing.Any) -> typing.Union[bool, Gt]: other = self.preprocess(value) if self.is_value and other.is_value: - return Boolean(self.get_value() > other.get_value()) + return self.get_value() > other.get_value() return Gt(self, other) - def __ge__(self, value: typing.Any) -> typing.Union["Boolean", Gte]: + def __ge__(self, value: typing.Any) -> typing.Union[bool, Gte]: other = self.preprocess(value) if self.is_value and other.is_value: - return Boolean(self.get_value() >= other.get_value()) + return self.get_value() >= other.get_value() return Gte(self, other) - def __lt__(self, value: typing.Any) -> typing.Union["Boolean", Lt]: + def __lt__(self, value: typing.Any) -> typing.Union[bool, Lt]: other = self.preprocess(value) if self.is_value and other.is_value: - return Boolean(self.get_value() < other.get_value()) + return self.get_value() < other.get_value() return Lt(self, other) - def __le__(self, value: typing.Any) -> typing.Union["Boolean", Lte]: + def __le__(self, value: typing.Any) -> typing.Union[bool, Lte]: other = self.preprocess(value) if self.is_value and other.is_value: - return Boolean(self.get_value() <= other.get_value()) + return self.get_value() <= other.get_value() return Lte(self, other) diff --git a/integration_tests/client/datasets/test_dataset.py b/integration_tests/client/datasets/test_dataset.py index 172c1b831..9839fbabc 100644 --- a/integration_tests/client/datasets/test_dataset.py +++ b/integration_tests/client/datasets/test_dataset.py @@ -139,6 +139,11 @@ def test_create_image_dataset_with_detections( elif gt.datum.uid == "uid2": gt_dets_uid2.extend(gt.annotations) assert dets1 and dets2 + + # set imnplied task type since these are federated by the backend + for ann in gt_dets_uid1 + gt_dets_uid2: + ann.implied_task_types = ["object-detection"] + assert dets1.annotations == gt_dets_uid1 assert dets2.annotations == gt_dets_uid2 diff --git a/integration_tests/client/models/test_model.py b/integration_tests/client/models/test_model.py index cd4424a22..28d1514e0 100644 --- a/integration_tests/client/models/test_model.py +++ b/integration_tests/client/models/test_model.py @@ -390,6 +390,10 @@ def test_add_prediction( # test get predictions pred = model.get_prediction(dataset, img1) assert pred + + # set imnplied task type since these are federated by the backend + for ann in pred_dets[0].annotations: + ann.implied_task_types = ["object-detection"] assert pred.annotations == pred_dets[0].annotations client.delete_dataset(dataset_name, timeout=30)