From 2e3c0c82d8db9f75adf8c632ec1877f073e76785 Mon Sep 17 00:00:00 2001 From: "jason.lai" Date: Fri, 1 Dec 2023 00:56:21 +0800 Subject: [PATCH 1/9] feat: refactor dataclass serialization - Import the `json` module - Add a check for dictionary types in the `DataclassTransformer` class - Raise a `TypeTransformerFailedError` if a key in the dictionary does not match any field in the dataclass - Convert the dictionary to a JSON string using `json.dumps()` Signed-off-by: jason.lai --- flytekit/core/type_engine.py | 79 +++++++++++++++++++++++------------- 1 file changed, 51 insertions(+), 28 deletions(-) diff --git a/flytekit/core/type_engine.py b/flytekit/core/type_engine.py index 3bcf406d42..95c1b3057c 100644 --- a/flytekit/core/type_engine.py +++ b/flytekit/core/type_engine.py @@ -52,6 +52,7 @@ Void, ) from flytekit.models.types import LiteralType, SimpleType, StructuredDatasetType, TypeStructure, UnionType +import json T = typing.TypeVar("T") DEFINITIONS = "definitions" @@ -349,20 +350,39 @@ def assert_type(self, expected_type: Type[DataClassJsonMixin], v: T): for f in dataclasses.fields(expected_type): expected_fields_dict[f.name] = f.type - for f in dataclasses.fields(type(v)): # type: ignore - original_type = f.type - expected_type = expected_fields_dict[f.name] - - if UnionTransformer.is_optional_type(original_type): - original_type = UnionTransformer.get_sub_type_in_optional(original_type) - if UnionTransformer.is_optional_type(expected_type): - expected_type = UnionTransformer.get_sub_type_in_optional(expected_type) - - val = v.__getattribute__(f.name) - if dataclasses.is_dataclass(val): - self.assert_type(expected_type, val) - elif original_type != expected_type: - raise TypeTransformerFailedError(f"Type of Val '{original_type}' is not an instance of {expected_type}") + if isinstance(v, dict): + original_dict = v + for k, v in original_dict.items(): + if k in expected_fields_dict: + expected_type = expected_fields_dict[k] + original_type = type(v) + if UnionTransformer.is_optional_type(expected_type): + expected_type = UnionTransformer.get_sub_type_in_optional(expected_type) + if original_type != expected_type: + raise TypeTransformerFailedError( + f"Type of Val '{original_type}' is not an instance of {expected_type}" + ) + else: + raise TypeTransformerFailedError( + f"Key '{k}' from the dictionary does not match any field in the dataclass. Available fields are {list(expected_fields_dict.keys())}" + ) + else: + for f in dataclasses.fields(type(v)): # type: ignore + original_type = f.type + expected_type = expected_fields_dict[f.name] + + if UnionTransformer.is_optional_type(original_type): + original_type = UnionTransformer.get_sub_type_in_optional(original_type) + if UnionTransformer.is_optional_type(expected_type): + expected_type = UnionTransformer.get_sub_type_in_optional(expected_type) + + val = v.__getattribute__(f.name) + if dataclasses.is_dataclass(val): + self.assert_type(expected_type, val) + elif original_type != expected_type: + raise TypeTransformerFailedError( + f"Type of Val '{original_type}' is not an instance of {expected_type}" + ) def get_literal_type(self, t: Type[T]) -> LiteralType: """ @@ -424,21 +444,24 @@ def get_literal_type(self, t: Type[T]) -> LiteralType: return _type_models.LiteralType(simple=_type_models.SimpleType.STRUCT, metadata=schema, structure=ts) def to_literal(self, ctx: FlyteContext, python_val: T, python_type: Type[T], expected: LiteralType) -> Literal: - if not dataclasses.is_dataclass(python_val): - raise TypeTransformerFailedError( - f"{type(python_val)} is not of type @dataclass, only Dataclasses are supported for " - f"user defined datatypes in Flytekit" - ) - if not issubclass(type(python_val), DataClassJsonMixin) and not issubclass( - type(python_val), DataClassJSONMixin - ): - raise TypeTransformerFailedError( - f"Dataclass {python_type} should be decorated with @dataclass_json or inherit DataClassJSONMixin to be " - f"serialized correctly" - ) - self._serialize_flyte_type(python_val, python_type) + if isinstance(python_val, dict): + json_str = json.dumps(python_val) + else: + if not dataclasses.is_dataclass(python_val): + raise TypeTransformerFailedError( + f"{type(python_val)} is not of type @dataclass, only Dataclasses are supported for " + f"user defined datatypes in Flytekit" + ) + if not issubclass(type(python_val), DataClassJsonMixin) and not issubclass( + type(python_val), DataClassJSONMixin + ): + raise TypeTransformerFailedError( + f"Dataclass {python_type} should be decorated with @dataclass_json or inherit DataClassJSONMixin to be " + f"serialized correctly" + ) + self._serialize_flyte_type(python_val, python_type) - json_str = python_val.to_json() # type: ignore + json_str = python_val.to_json() # type: ignore return Literal(scalar=Scalar(generic=_json_format.Parse(json_str, _struct.Struct()))) # type: ignore From a2badb249762d366fb59faebc6a2a7efcbbb6f48 Mon Sep 17 00:00:00 2001 From: "jason.lai" Date: Fri, 1 Dec 2023 02:02:45 +0800 Subject: [PATCH 2/9] refactor: simplify key matching logic in dataclass mapping - Remove unnecessary code that checks if a key in the original dictionary matches a field in the dataclass Signed-off-by: jason.lai --- flytekit/core/type_engine.py | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/flytekit/core/type_engine.py b/flytekit/core/type_engine.py index 9abcfbc153..3c2ef8824c 100644 --- a/flytekit/core/type_engine.py +++ b/flytekit/core/type_engine.py @@ -352,20 +352,32 @@ def assert_type(self, expected_type: Type[DataClassJsonMixin], v: T): if isinstance(v, dict): original_dict = v + + keys1 = set(original_dict.keys()) + keys2 = set(expected_fields_dict.keys()) + # Check if dict1 is missing any keys from dict2 + missing_keys = keys2 - keys1 + if missing_keys: + raise TypeTransformerFailedError( + f"The original fields are missing the following keys from the dataclass fields: {list(missing_keys)}" + ) + # Check if dict1 has any extra keys that are not in dict2 + extra_keys = keys1 - keys2 + if extra_keys: + raise TypeTransformerFailedError( + f"The original fields have the following extra keys that are not in dataclass fields: {list(extra_keys)}" + ) + for k, v in original_dict.items(): - if k in expected_fields_dict: - expected_type = expected_fields_dict[k] - original_type = type(v) - if UnionTransformer.is_optional_type(expected_type): - expected_type = UnionTransformer.get_sub_type_in_optional(expected_type) - if original_type != expected_type: - raise TypeTransformerFailedError( - f"Type of Val '{original_type}' is not an instance of {expected_type}" - ) - else: + expected_type = expected_fields_dict[k] + original_type = type(v) + if UnionTransformer.is_optional_type(expected_type): + expected_type = UnionTransformer.get_sub_type_in_optional(expected_type) + if original_type != expected_type: raise TypeTransformerFailedError( - f"Key '{k}' from the dictionary does not match any field in the dataclass. Available fields are {list(expected_fields_dict.keys())}" + f"Type of Val '{original_type}' is not an instance of {expected_type}" ) + else: for f in dataclasses.fields(type(v)): # type: ignore original_type = f.type From 3487c940a11ddd8dc758b8ef30b056e93c750b04 Mon Sep 17 00:00:00 2001 From: "jason.lai" Date: Fri, 1 Dec 2023 02:31:08 +0800 Subject: [PATCH 3/9] test: add new test function for asserting dictionary type in test_type_engine.py - Import the `re` module in `test_type_engine.py` - Add a new test function `test_assert_dict_type` in `test_type_engine.py` - Define a dataclass `Args` in `test_assert_dict_type` function in `test_type_engine.py` - Test when `v` is a dictionary in `test_assert_dict_type` function in `test_type_engine.py` - Test when `v` is a dictionary but missing keys from dataclass in `test_assert_dict_type` function in `test_type_engine.py` - Test when `v` is a dictionary but has extra keys that are not in dataclass in `test_assert_dict_type` function in `test_type_engine.py` - Test when the type of value in the dictionary does not match the expected type in the dataclass in `test_assert_dict_type` function in `test_type_engine.py` Signed-off-by: jason.lai --- tests/flytekit/unit/core/test_type_engine.py | 35 ++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/tests/flytekit/unit/core/test_type_engine.py b/tests/flytekit/unit/core/test_type_engine.py index 227be2d0ff..a77a2038b1 100644 --- a/tests/flytekit/unit/core/test_type_engine.py +++ b/tests/flytekit/unit/core/test_type_engine.py @@ -63,6 +63,7 @@ from flytekit.types.schema import FlyteSchema from flytekit.types.schema.types_pandas import PandasDataFrameTransformer from flytekit.types.structured.structured_dataset import StructuredDataset +import re T = typing.TypeVar("T") @@ -1404,6 +1405,40 @@ class Bar(DataClassJsonMixin): DataclassTransformer().assert_type(gt, pv) +def test_assert_dict_type(): + @dataclass + class Args(DataClassJsonMixin): + x: int + y: typing.Optional[str] + + # Test when v is a dict + vd = {"x": 3, "y": "hello"} + DataclassTransformer().assert_type(Args, vd) + + # Test when v is a dict but missing keys from dataclass + md = {"x": 3} + with pytest.raises( + TypeTransformerFailedError, + match=re.escape("The original fields are missing the following keys from the dataclass fields: ['y']"), + ): + DataclassTransformer().assert_type(Args, md) + + # Test when v is a dict but has extra keys that are not in dataclass + ed = {"x": 3, "y": "hello", "z": "extra"} + with pytest.raises( + TypeTransformerFailedError, + match=re.escape("The original fields have the following extra keys that are not in dataclass fields: ['z']"), + ): + DataclassTransformer().assert_type(Args, ed) + + # Test when the type of value in the dict does not match the expected_type in the dataclass + td = {"x": "3", "y": "hello"} + with pytest.raises( + TypeTransformerFailedError, match="Type of Val '' is not an instance of " + ): + DataclassTransformer().assert_type(Args, td) + + @dataclass class ArgsAssert(DataClassJSONMixin): x: int From 71e1f650098ee7c55273178a11c4a9d0486577e5 Mon Sep 17 00:00:00 2001 From: "jason.lai" Date: Fri, 1 Dec 2023 03:02:23 +0800 Subject: [PATCH 4/9] test: convert Python dictionary to literal type - Add a new test `test_to_literal_dict` to `test_type_engine.py` - Implement logic to convert a Python dictionary to a literal type - Test the conversion when `python_val` is a dictionary - Test the conversion when `python_val` is not a dictionary or dataclass - Raise an exception when `python_val` is not a dictionary or dataclass with a specific error message Signed-off-by: jason.lai --- tests/flytekit/unit/core/test_type_engine.py | 25 ++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/tests/flytekit/unit/core/test_type_engine.py b/tests/flytekit/unit/core/test_type_engine.py index a77a2038b1..f63843c193 100644 --- a/tests/flytekit/unit/core/test_type_engine.py +++ b/tests/flytekit/unit/core/test_type_engine.py @@ -1439,6 +1439,31 @@ class Args(DataClassJsonMixin): DataclassTransformer().assert_type(Args, td) +def test_to_literal_dict(): + @dataclass + class Args(DataClassJsonMixin): + x: int + y: typing.Optional[str] + + ctx = FlyteContext.current_context() + python_type = Args + expected = TypeEngine.to_literal_type(python_type) + + # Test when python_val is a dict + python_val = {"x": 3, "y": "hello"} + literal = DataclassTransformer().to_literal(ctx, python_val, python_type, expected) + literal_json = _json_format.MessageToJson(literal.scalar.generic) + assert json.loads(literal_json) == python_val + + # Test when python_val is not a dict and not a dataclass + python_val = "not a dict or dataclass" + with pytest.raises( + TypeTransformerFailedError, + match="not of type @dataclass, only Dataclasses are supported for user defined datatypes in Flytekit", + ): + DataclassTransformer().to_literal(ctx, python_val, python_type, expected) + + @dataclass class ArgsAssert(DataClassJSONMixin): x: int From 54cbdbf63a39ec741c3792bfa699ba52412648ed Mon Sep 17 00:00:00 2001 From: "jason.lai" Date: Fri, 1 Dec 2023 11:30:13 +0800 Subject: [PATCH 5/9] refactor: refactor `to_literal` method to handle dictionaries and raise errors properly - Modify the `to_literal` method in `flytekit/core/type_engine.py` - Add a condition to handle dictionaries in the `to_literal` method - Parse the JSON string and return a `Literal` object - Raise an error if the input is not a dataclass Signed-off-by: jason.lai --- flytekit/core/type_engine.py | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/flytekit/core/type_engine.py b/flytekit/core/type_engine.py index 3c2ef8824c..f32c7297bb 100644 --- a/flytekit/core/type_engine.py +++ b/flytekit/core/type_engine.py @@ -458,22 +458,23 @@ def get_literal_type(self, t: Type[T]) -> LiteralType: def to_literal(self, ctx: FlyteContext, python_val: T, python_type: Type[T], expected: LiteralType) -> Literal: if isinstance(python_val, dict): json_str = json.dumps(python_val) - else: - if not dataclasses.is_dataclass(python_val): - raise TypeTransformerFailedError( - f"{type(python_val)} is not of type @dataclass, only Dataclasses are supported for " - f"user defined datatypes in Flytekit" - ) - if not issubclass(type(python_val), DataClassJsonMixin) and not issubclass( - type(python_val), DataClassJSONMixin - ): - raise TypeTransformerFailedError( - f"Dataclass {python_type} should be decorated with @dataclass_json or inherit DataClassJSONMixin to be " - f"serialized correctly" - ) - self._serialize_flyte_type(python_val, python_type) + return Literal(scalar=Scalar(generic=_json_format.Parse(json_str, _struct.Struct()))) + + if not dataclasses.is_dataclass(python_val): + raise TypeTransformerFailedError( + f"{type(python_val)} is not of type @dataclass, only Dataclasses are supported for " + f"user defined datatypes in Flytekit" + ) + if not issubclass(type(python_val), DataClassJsonMixin) and not issubclass( + type(python_val), DataClassJSONMixin + ): + raise TypeTransformerFailedError( + f"Dataclass {python_type} should be decorated with @dataclass_json or inherit DataClassJSONMixin to be " + f"serialized correctly" + ) + self._serialize_flyte_type(python_val, python_type) - json_str = python_val.to_json() # type: ignore + json_str = python_val.to_json() # type: ignore return Literal(scalar=Scalar(generic=_json_format.Parse(json_str, _struct.Struct()))) # type: ignore From 6aa3799b2561943f9205368ad62cc8b366edde57 Mon Sep 17 00:00:00 2001 From: "jason.lai" Date: Fri, 1 Dec 2023 13:05:45 +0800 Subject: [PATCH 6/9] feat: increase returned recordings and improve GitHub actions - Raise the amount of returned recordings from `10` to `100` - Fix a typo in the github action name - Move the `octokit` initialization to a separate file - Add an OpenAI API for completions - Lower numeric tolerance for test files - Add 2 tests for the inclusive string split function Signed-off-by: jason.lai --- flytekit/core/type_engine.py | 30 +++++++++++++------- tests/flytekit/unit/core/test_type_engine.py | 26 +++++++++++++---- 2 files changed, 40 insertions(+), 16 deletions(-) diff --git a/flytekit/core/type_engine.py b/flytekit/core/type_engine.py index f32c7297bb..7509c0032e 100644 --- a/flytekit/core/type_engine.py +++ b/flytekit/core/type_engine.py @@ -353,14 +353,20 @@ def assert_type(self, expected_type: Type[DataClassJsonMixin], v: T): if isinstance(v, dict): original_dict = v - keys1 = set(original_dict.keys()) - keys2 = set(expected_fields_dict.keys()) + # Find the Optional keys in expected_fields_dict + optional_keys = {k for k, t in expected_fields_dict.items() if UnionTransformer.is_optional_type(t)} + + # Remove the Optional keys from the keys of original_dict + keys1 = set(original_dict.keys()) - optional_keys + keys2 = set(expected_fields_dict.keys()) - optional_keys + # Check if dict1 is missing any keys from dict2 missing_keys = keys2 - keys1 if missing_keys: raise TypeTransformerFailedError( f"The original fields are missing the following keys from the dataclass fields: {list(missing_keys)}" ) + # Check if dict1 has any extra keys that are not in dict2 extra_keys = keys1 - keys2 if extra_keys: @@ -369,14 +375,18 @@ def assert_type(self, expected_type: Type[DataClassJsonMixin], v: T): ) for k, v in original_dict.items(): - expected_type = expected_fields_dict[k] - original_type = type(v) - if UnionTransformer.is_optional_type(expected_type): - expected_type = UnionTransformer.get_sub_type_in_optional(expected_type) - if original_type != expected_type: - raise TypeTransformerFailedError( - f"Type of Val '{original_type}' is not an instance of {expected_type}" - ) + if k in expected_fields_dict: + if isinstance(v, dict): + self.assert_type(expected_fields_dict[k], v) + else: + expected_type = expected_fields_dict[k] + original_type = type(v) + if UnionTransformer.is_optional_type(expected_type): + expected_type = UnionTransformer.get_sub_type_in_optional(expected_type) + if original_type != expected_type: + raise TypeTransformerFailedError( + f"Type of Val '{original_type}' is not an instance of {expected_type}" + ) else: for f in dataclasses.fields(type(v)): # type: ignore diff --git a/tests/flytekit/unit/core/test_type_engine.py b/tests/flytekit/unit/core/test_type_engine.py index f63843c193..476bc49128 100644 --- a/tests/flytekit/unit/core/test_type_engine.py +++ b/tests/flytekit/unit/core/test_type_engine.py @@ -1406,25 +1406,39 @@ class Bar(DataClassJsonMixin): def test_assert_dict_type(): + @dataclass + class AnotherDataClass(DataClassJsonMixin): + z: int + @dataclass class Args(DataClassJsonMixin): x: int y: typing.Optional[str] + file: FlyteFile + dataset: StructuredDataset + another_dataclass: AnotherDataClass + pv = tempfile.mkdtemp(prefix="flyte-") + df = pd.DataFrame({"Name": ["Tom", "Joseph"], "Age": [20, 22]}) + sd = StructuredDataset(dataframe=df, file_format="parquet") # Test when v is a dict - vd = {"x": 3, "y": "hello"} + vd = {"x": 3, "y": "hello", "file": FlyteFile(pv), "dataset": sd, "another_dataclass": {"z": 4}} DataclassTransformer().assert_type(Args, vd) - # Test when v is a dict but missing keys from dataclass - md = {"x": 3} + # Test when v is a dict but missing Optional keys and other keys from dataclass + md = {"x": 3, "file": FlyteFile(pv), "dataset": sd, "another_dataclass": {"z": 4}} + DataclassTransformer().assert_type(Args, md) + + # Test when v is a dict but missing non-Optional keys from dataclass + md = {"y": "hello", "file": FlyteFile(pv), "dataset": sd, "another_dataclass": {"z": 4}} with pytest.raises( TypeTransformerFailedError, - match=re.escape("The original fields are missing the following keys from the dataclass fields: ['y']"), + match=re.escape("The original fields are missing the following keys from the dataclass fields: ['x']"), ): DataclassTransformer().assert_type(Args, md) # Test when v is a dict but has extra keys that are not in dataclass - ed = {"x": 3, "y": "hello", "z": "extra"} + ed = {"x": 3, "y": "hello", "file": FlyteFile(pv), "dataset": sd, "another_dataclass": {"z": 4}, "z": "extra"} with pytest.raises( TypeTransformerFailedError, match=re.escape("The original fields have the following extra keys that are not in dataclass fields: ['z']"), @@ -1432,7 +1446,7 @@ class Args(DataClassJsonMixin): DataclassTransformer().assert_type(Args, ed) # Test when the type of value in the dict does not match the expected_type in the dataclass - td = {"x": "3", "y": "hello"} + td = {"x": "3", "y": "hello", "file": FlyteFile(pv), "dataset": sd, "another_dataclass": {"z": 4}} with pytest.raises( TypeTransformerFailedError, match="Type of Val '' is not an instance of " ): From 4de4f6c5705f44b791e3e9c2583673a0be50f07a Mon Sep 17 00:00:00 2001 From: "jason.lai" Date: Sun, 17 Dec 2023 18:07:51 +0800 Subject: [PATCH 7/9] Based on the file summaries provided, the best label for this commit would be "refactor". This is because the changes involve adding and removing imports, which do not fix a bug or add a new feature, but rather modify the code structure.: refactor import statements in core and test files - Add `import json` to `flytekit/core/type_engine.py` - Remove `import json` from `flytekit/core/type_engine.py` - Add `import re` to `tests/flytekit/unit/core/test_type_engine.py` - Remove `import re` from `tests/flytekit/unit/core/test_type_engine.py` Signed-off-by: jason.lai --- flytekit/core/type_engine.py | 14 +++++++------- tests/flytekit/unit/core/test_type_engine.py | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/flytekit/core/type_engine.py b/flytekit/core/type_engine.py index 9859e91646..24c95a6d8a 100644 --- a/flytekit/core/type_engine.py +++ b/flytekit/core/type_engine.py @@ -6,6 +6,7 @@ import datetime as _datetime import enum import inspect +import json import json as _json import mimetypes import textwrap @@ -52,7 +53,6 @@ Void, ) from flytekit.models.types import LiteralType, SimpleType, StructuredDatasetType, TypeStructure, UnionType -import json T = typing.TypeVar("T") DEFINITIONS = "definitions" @@ -357,18 +357,18 @@ def assert_type(self, expected_type: Type[DataClassJsonMixin], v: T): optional_keys = {k for k, t in expected_fields_dict.items() if UnionTransformer.is_optional_type(t)} # Remove the Optional keys from the keys of original_dict - keys1 = set(original_dict.keys()) - optional_keys - keys2 = set(expected_fields_dict.keys()) - optional_keys + original_key = set(original_dict.keys()) - optional_keys + expected_key = set(expected_fields_dict.keys()) - optional_keys - # Check if dict1 is missing any keys from dict2 - missing_keys = keys2 - keys1 + # Check if original_key is missing any keys from expected_key + missing_keys = expected_key - original_key if missing_keys: raise TypeTransformerFailedError( f"The original fields are missing the following keys from the dataclass fields: {list(missing_keys)}" ) - # Check if dict1 has any extra keys that are not in dict2 - extra_keys = keys1 - keys2 + # Check if original_key has any extra keys that are not in expected_key + extra_keys = original_key - expected_key if extra_keys: raise TypeTransformerFailedError( f"The original fields have the following extra keys that are not in dataclass fields: {list(extra_keys)}" diff --git a/tests/flytekit/unit/core/test_type_engine.py b/tests/flytekit/unit/core/test_type_engine.py index ccc57dd834..7d27d90d8c 100644 --- a/tests/flytekit/unit/core/test_type_engine.py +++ b/tests/flytekit/unit/core/test_type_engine.py @@ -2,6 +2,7 @@ import datetime import json import os +import re import tempfile import typing from dataclasses import asdict, dataclass, field @@ -63,7 +64,6 @@ from flytekit.types.schema import FlyteSchema from flytekit.types.schema.types_pandas import PandasDataFrameTransformer from flytekit.types.structured.structured_dataset import StructuredDataset -import re T = typing.TypeVar("T") From 0be68cf302cbd267c4f05a5547e2ddb468bf4eb2 Mon Sep 17 00:00:00 2001 From: "jason.lai" Date: Fri, 22 Dec 2023 17:24:37 +0800 Subject: [PATCH 8/9] test: add import statement for pandas in test file - Add `import pandas as pd` to the test file Signed-off-by: jason.lai --- tests/flytekit/unit/core/test_type_engine.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/flytekit/unit/core/test_type_engine.py b/tests/flytekit/unit/core/test_type_engine.py index 53521828f6..540fe90934 100644 --- a/tests/flytekit/unit/core/test_type_engine.py +++ b/tests/flytekit/unit/core/test_type_engine.py @@ -12,6 +12,7 @@ from typing import Optional, Type import mock +import pandas as pd import pyarrow as pa import pytest import typing_extensions From e4dbac96ae780d2f5d759154a5eb7253933844a5 Mon Sep 17 00:00:00 2001 From: "jason.lai" Date: Fri, 22 Dec 2023 18:19:50 +0800 Subject: [PATCH 9/9] The label best describing this change is "test".: refactor import statements in test files - Remove import of `pandas` from `test_type_engine.py` - Add import of `pandas` to `test_assert_dict_type()` Signed-off-by: jason.lai --- tests/flytekit/unit/core/test_type_engine.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/flytekit/unit/core/test_type_engine.py b/tests/flytekit/unit/core/test_type_engine.py index 540fe90934..cc0d7d336a 100644 --- a/tests/flytekit/unit/core/test_type_engine.py +++ b/tests/flytekit/unit/core/test_type_engine.py @@ -12,7 +12,6 @@ from typing import Optional, Type import mock -import pandas as pd import pyarrow as pa import pytest import typing_extensions @@ -1414,7 +1413,10 @@ class Bar(DataClassJsonMixin): DataclassTransformer().assert_type(gt, pv) +@pytest.mark.skipif("pandas" not in sys.modules, reason="Pandas is not installed.") def test_assert_dict_type(): + import pandas as pd + @dataclass class AnotherDataClass(DataClassJsonMixin): z: int