From fcd15c8a80fdbe918fa0cde9fac6f1ccc18fe6f1 Mon Sep 17 00:00:00 2001 From: fdroessler Date: Tue, 12 Sep 2023 22:09:04 +0200 Subject: [PATCH 1/9] bump fastapi and add pydantic compatibility Signed-off-by: fdroessler --- package/kedro_viz/api/rest/responses.py | 71 +++++++++---------- .../kedro_viz/models/experiment_tracking.py | 9 +-- package/requirements.txt | 4 +- package/test_requirements.txt | 4 +- 4 files changed, 42 insertions(+), 46 deletions(-) diff --git a/package/kedro_viz/api/rest/responses.py b/package/kedro_viz/api/rest/responses.py index c7794516a3..ec6d62f8d2 100644 --- a/package/kedro_viz/api/rest/responses.py +++ b/package/kedro_viz/api/rest/responses.py @@ -5,7 +5,7 @@ import orjson from fastapi.responses import ORJSONResponse -from pydantic import BaseModel +from pydantic import BaseModel, ConfigDict from kedro_viz.data_access import data_access_manager @@ -15,8 +15,7 @@ class APIErrorMessage(BaseModel): class BaseAPIResponse(BaseModel, abc.ABC): - class Config: - orm_mode = True + model_config = ConfigDict(from_attributes=True) class BaseGraphNodeAPIResponse(BaseAPIResponse): @@ -27,14 +26,13 @@ class BaseGraphNodeAPIResponse(BaseAPIResponse): type: str # If a node is a ModularPipeline node, this value will be None, hence Optional. - modular_pipelines: Optional[List[str]] + modular_pipelines: Optional[List[str]] = None class TaskNodeAPIResponse(BaseGraphNodeAPIResponse): parameters: Dict - - class Config: - schema_extra = { + model_config = ConfigDict( + json_schema_extra={ "example": { "id": "6ab908b8", "name": "split_data_node", @@ -58,15 +56,15 @@ class Config: }, } } + ) class DataNodeAPIResponse(BaseGraphNodeAPIResponse): - layer: Optional[str] - dataset_type: Optional[str] - stats: Optional[Dict] - - class Config: - schema_extra = { + layer: Optional[str] = None + dataset_type: Optional[str] = None + stats: Optional[Dict] = None + model_config = ConfigDict( + json_schema_extra={ "example": { "id": "d7b83b05", "name": "master_table", @@ -79,6 +77,7 @@ class Config: "stats": {"rows": 10, "columns": 2, "file_size": 2300}, } } + ) NodeAPIResponse = Union[ @@ -88,15 +87,14 @@ class Config: class TaskNodeMetadataAPIResponse(BaseAPIResponse): - code: Optional[str] - filepath: Optional[str] - parameters: Optional[Dict] + code: Optional[str] = None + filepath: Optional[str] = None + parameters: Optional[Dict] = None inputs: List[str] outputs: List[str] - run_command: Optional[str] - - class Config: - schema_extra = { + run_command: Optional[str] = None + model_config = ConfigDict( + json_schema_extra={ "example": { "code": "def split_data(data: pd.DataFrame, parameters: Dict) -> Tuple:", "filepath": "proj/src/new_kedro_project/pipelines/data_science/nodes.py", @@ -106,41 +104,41 @@ class Config: "run_command": "kedro run --to-nodes=split_data", } } + ) class DataNodeMetadataAPIResponse(BaseAPIResponse): - filepath: Optional[str] + filepath: Optional[str] = None type: str - plot: Optional[Dict] - image: Optional[str] - tracking_data: Optional[Dict] - run_command: Optional[str] - preview: Optional[Dict] - stats: Optional[Dict] - - class Config: - schema_extra = { + plot: Optional[Dict] = None + image: Optional[str] = None + tracking_data: Optional[Dict] = None + run_command: Optional[str] = None + preview: Optional[Dict] = None + stats: Optional[Dict] = None + model_config = ConfigDict( + json_schema_extra={ "example": { "filepath": "/my-kedro-project/data/03_primary/master_table.csv", "type": "pandas.csv_dataset.CSVDataSet", "run_command": "kedro run --to-outputs=master_table", } } + ) class TranscodedDataNodeMetadataAPIReponse(BaseAPIResponse): filepath: str original_type: str transcoded_types: List[str] - run_command: Optional[str] - stats: Optional[Dict] + run_command: Optional[str] = None + stats: Optional[Dict] = None class ParametersNodeMetadataAPIResponse(BaseAPIResponse): parameters: Dict - - class Config: - schema_extra = { + model_config = ConfigDict( + json_schema_extra={ "example": { "parameters": { "test_size": 0.2, @@ -158,6 +156,7 @@ class Config: } } } + ) NodeMetadataAPIResponse = Union[ @@ -179,7 +178,7 @@ class NamedEntityAPIResponse(BaseAPIResponse): """ id: str - name: Optional[str] + name: Optional[str] = None class ModularPipelineChildAPIResponse(BaseAPIResponse): diff --git a/package/kedro_viz/models/experiment_tracking.py b/package/kedro_viz/models/experiment_tracking.py index ce8cf012c2..bb02587894 100644 --- a/package/kedro_viz/models/experiment_tracking.py +++ b/package/kedro_viz/models/experiment_tracking.py @@ -7,6 +7,7 @@ from typing import TYPE_CHECKING, Any, Dict from kedro.io import Version +from pydantic import ConfigDict from sqlalchemy import Column from sqlalchemy.orm import declarative_base # type: ignore from sqlalchemy.sql.schema import ForeignKey @@ -33,9 +34,7 @@ class RunModel(Base): # type: ignore id = Column(String, primary_key=True, index=True) blob = Column(JSON) - - class Config: - orm_mode = True + model_config = ConfigDict(from_attributes=True) class UserRunDetailsModel(Base): # type: ignore @@ -48,9 +47,7 @@ class UserRunDetailsModel(Base): # type: ignore bookmark = Column(Boolean, default=False) title = Column(String) notes = Column(String) - - class Config: - orm_mode = True + model_config = ConfigDict(from_attributes=True) class TrackingDatasetGroup(str, Enum): diff --git a/package/requirements.txt b/package/requirements.txt index 9329b4f890..1dd1f4e203 100644 --- a/package/requirements.txt +++ b/package/requirements.txt @@ -1,8 +1,8 @@ semver>=2.10 # Needs to be at least 2.10.0 to make use of `VersionInfo.match`. kedro>=0.17.5 ipython>=7.0.0, <9.0 -fastapi>=0.73.0, <0.96.0 -fsspec>=2021.4, <2024.1 +fastapi>=0.73.0, <0.104.0 +fsspec>=2021.4, <2024.1 aiofiles==22.1.0 uvicorn[standard]~=0.22.0 watchgod~=0.8.2 diff --git a/package/test_requirements.txt b/package/test_requirements.txt index 9c41b241a3..8a1fabc256 100644 --- a/package/test_requirements.txt +++ b/package/test_requirements.txt @@ -8,11 +8,11 @@ behave~=1.2 black~=23.3 boto3~=1.26 flake8~=5.0 -fastapi[all]>=0.73.0, <0.96.0 +fastapi[all]>=0.73.0, <0.104.0 isort~=5.11 matplotlib~=3.5 mypy~=1.0 -moto~=4.1.14 +moto~=4.1.14 psutil==5.9.5 # same as Kedro for now pylint~=2.17 pytest~=7.4 From 1f1ba1bf1c1e1c00e20b62af6c429a9f1145a4a1 Mon Sep 17 00:00:00 2001 From: fdroessler Date: Tue, 12 Sep 2023 22:36:00 +0200 Subject: [PATCH 2/9] bump lower requirements due to pydantic changes Signed-off-by: fdroessler --- package/features/steps/lower_requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/features/steps/lower_requirements.txt b/package/features/steps/lower_requirements.txt index 3466aa50ab..16acd36b43 100644 --- a/package/features/steps/lower_requirements.txt +++ b/package/features/steps/lower_requirements.txt @@ -1,6 +1,6 @@ semver==3.0 ipython==7.0.0 -fastapi==0.73.0 +fastapi==0.100.0 fsspec==2021.4 aiofiles==22.1.0 uvicorn[standard]==0.22.0 From a74e2ca305db3fa39a22f96063d7e857a1b49c8c Mon Sep 17 00:00:00 2001 From: fdroessler Date: Tue, 12 Sep 2023 22:53:24 +0200 Subject: [PATCH 3/9] Update Release notes Signed-off-by: fdroessler --- RELEASE.md | 1 + 1 file changed, 1 insertion(+) diff --git a/RELEASE.md b/RELEASE.md index 6af517974a..7f58d7ac07 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -10,6 +10,7 @@ Please follow the established format: ## Bug fixes and other changes - Fix for Kedro Viz Connection Error (#1507) +- Add support for pydantic v2 and fastapi >= 0.100.0 (#1529) # Release 6.5.0 From 1e7154e25653c9be3b45a04f595fe338bc6e84bc Mon Sep 17 00:00:00 2001 From: fdroessler Date: Mon, 25 Sep 2023 22:13:46 +0200 Subject: [PATCH 4/9] make lower requirements pydantic < v2 and code compatible Signed-off-by: fdroessler --- package/features/steps/lower_requirements.txt | 1 + package/kedro_viz/api/rest/responses.py | 204 +++++++++++------- .../kedro_viz/models/experiment_tracking.py | 15 +- 3 files changed, 135 insertions(+), 85 deletions(-) diff --git a/package/features/steps/lower_requirements.txt b/package/features/steps/lower_requirements.txt index 16acd36b43..19714bc525 100644 --- a/package/features/steps/lower_requirements.txt +++ b/package/features/steps/lower_requirements.txt @@ -13,3 +13,4 @@ strawberry-graphql==0.192.0 networkx==2.5 orjson==3.9 secure==0.3.0 +pydantic<2 diff --git a/package/kedro_viz/api/rest/responses.py b/package/kedro_viz/api/rest/responses.py index ec6d62f8d2..910fc24087 100644 --- a/package/kedro_viz/api/rest/responses.py +++ b/package/kedro_viz/api/rest/responses.py @@ -4,6 +4,7 @@ from typing import Any, Dict, List, Optional, Union import orjson +from fastapi._compat import PYDANTIC_V2 from fastapi.responses import ORJSONResponse from pydantic import BaseModel, ConfigDict @@ -15,7 +16,12 @@ class APIErrorMessage(BaseModel): class BaseAPIResponse(BaseModel, abc.ABC): - model_config = ConfigDict(from_attributes=True) + if PYDANTIC_V2: + model_config = ConfigDict(from_attributes=True) + else: + + class Config: + orm_mode = True class BaseGraphNodeAPIResponse(BaseAPIResponse): @@ -29,55 +35,67 @@ class BaseGraphNodeAPIResponse(BaseAPIResponse): modular_pipelines: Optional[List[str]] = None +task_node_api_response_example = { + "example": { + "id": "6ab908b8", + "name": "split_data_node", + "tags": [], + "pipelines": ["__default__", "ds"], + "modular_pipelines": [], + "type": "task", + "parameters": { + "test_size": 0.2, + "random_state": 3, + "features": [ + "engines", + "passenger_capacity", + "crew", + "d_check_complete", + "moon_clearance_complete", + "iata_approved", + "company_rating", + "review_scores_rating", + ], + }, + } +} + + class TaskNodeAPIResponse(BaseGraphNodeAPIResponse): parameters: Dict - model_config = ConfigDict( - json_schema_extra={ - "example": { - "id": "6ab908b8", - "name": "split_data_node", - "tags": [], - "pipelines": ["__default__", "ds"], - "modular_pipelines": [], - "type": "task", - "parameters": { - "test_size": 0.2, - "random_state": 3, - "features": [ - "engines", - "passenger_capacity", - "crew", - "d_check_complete", - "moon_clearance_complete", - "iata_approved", - "company_rating", - "review_scores_rating", - ], - }, - } - } - ) + if PYDANTIC_V2: + model_config = ConfigDict(json_schema_extra=task_node_api_response_example) + else: + + class Config: + schema_extra = task_node_api_response_example + + +data_node_api_response_example = { + "example": { + "id": "d7b83b05", + "name": "master_table", + "tags": [], + "pipelines": ["__default__", "dp", "ds"], + "modular_pipelines": [], + "type": "data", + "layer": "primary", + "dataset_type": "kedro.extras.datasets.pandas.csv_dataset.CSVDataSet", + "stats": {"rows": 10, "columns": 2, "file_size": 2300}, + } +} class DataNodeAPIResponse(BaseGraphNodeAPIResponse): layer: Optional[str] = None dataset_type: Optional[str] = None stats: Optional[Dict] = None - model_config = ConfigDict( - json_schema_extra={ - "example": { - "id": "d7b83b05", - "name": "master_table", - "tags": [], - "pipelines": ["__default__", "dp", "ds"], - "modular_pipelines": [], - "type": "data", - "layer": "primary", - "dataset_type": "kedro.extras.datasets.pandas.csv_dataset.CSVDataSet", - "stats": {"rows": 10, "columns": 2, "file_size": 2300}, - } - } - ) + if PYDANTIC_V2: + model_config = ConfigDict(json_schema_extra=data_node_api_response_example) + else: + + class Config: + schema_extra = data_node_api_response_example NodeAPIResponse = Union[ @@ -86,6 +104,18 @@ class DataNodeAPIResponse(BaseGraphNodeAPIResponse): ] +task_node_metadata_api_example = { + "example": { + "code": "def split_data(data: pd.DataFrame, parameters: Dict) -> Tuple:", + "filepath": "proj/src/new_kedro_project/pipelines/data_science/nodes.py", + "parameters": {"test_size": 0.2}, + "inputs": ["params:input1", "input2"], + "outputs": ["output1"], + "run_command": "kedro run --to-nodes=split_data", + } +} + + class TaskNodeMetadataAPIResponse(BaseAPIResponse): code: Optional[str] = None filepath: Optional[str] = None @@ -93,18 +123,21 @@ class TaskNodeMetadataAPIResponse(BaseAPIResponse): inputs: List[str] outputs: List[str] run_command: Optional[str] = None - model_config = ConfigDict( - json_schema_extra={ - "example": { - "code": "def split_data(data: pd.DataFrame, parameters: Dict) -> Tuple:", - "filepath": "proj/src/new_kedro_project/pipelines/data_science/nodes.py", - "parameters": {"test_size": 0.2}, - "inputs": ["params:input1", "input2"], - "outputs": ["output1"], - "run_command": "kedro run --to-nodes=split_data", - } - } - ) + if PYDANTIC_V2: + model_config = ConfigDict(json_schema_extra=task_node_metadata_api_example) + else: + + class Config: + schema_extra = task_node_metadata_api_example + + +data_node_metadata_api_example = { + "example": { + "filepath": "/my-kedro-project/data/03_primary/master_table.csv", + "type": "pandas.csv_dataset.CSVDataSet", + "run_command": "kedro run --to-outputs=master_table", + } +} class DataNodeMetadataAPIResponse(BaseAPIResponse): @@ -116,15 +149,12 @@ class DataNodeMetadataAPIResponse(BaseAPIResponse): run_command: Optional[str] = None preview: Optional[Dict] = None stats: Optional[Dict] = None - model_config = ConfigDict( - json_schema_extra={ - "example": { - "filepath": "/my-kedro-project/data/03_primary/master_table.csv", - "type": "pandas.csv_dataset.CSVDataSet", - "run_command": "kedro run --to-outputs=master_table", - } - } - ) + if PYDANTIC_V2: + model_config = ConfigDict(json_schema_extra=data_node_metadata_api_example) + else: + + class Config: + schema_extra = data_node_metadata_api_example class TranscodedDataNodeMetadataAPIReponse(BaseAPIResponse): @@ -135,28 +165,36 @@ class TranscodedDataNodeMetadataAPIReponse(BaseAPIResponse): stats: Optional[Dict] = None +parameters_node_metaxata_api_example = { + "example": { + "parameters": { + "test_size": 0.2, + "random_state": 3, + "features": [ + "engines", + "passenger_capacity", + "crew", + "d_check_complete", + "moon_clearance_complete", + "iata_approved", + "company_rating", + "review_scores_rating", + ], + } + } +} + + class ParametersNodeMetadataAPIResponse(BaseAPIResponse): parameters: Dict - model_config = ConfigDict( - json_schema_extra={ - "example": { - "parameters": { - "test_size": 0.2, - "random_state": 3, - "features": [ - "engines", - "passenger_capacity", - "crew", - "d_check_complete", - "moon_clearance_complete", - "iata_approved", - "company_rating", - "review_scores_rating", - ], - } - } - } - ) + if PYDANTIC_V2: + model_config = ConfigDict( + json_schema_extra=parameters_node_metaxata_api_example + ) + else: + + class Config: + schema_extra = parameters_node_metaxata_api_example NodeMetadataAPIResponse = Union[ diff --git a/package/kedro_viz/models/experiment_tracking.py b/package/kedro_viz/models/experiment_tracking.py index bb02587894..5dd85cfae3 100644 --- a/package/kedro_viz/models/experiment_tracking.py +++ b/package/kedro_viz/models/experiment_tracking.py @@ -6,6 +6,7 @@ from enum import Enum from typing import TYPE_CHECKING, Any, Dict +from fastapi._compat import PYDANTIC_V2 from kedro.io import Version from pydantic import ConfigDict from sqlalchemy import Column @@ -34,7 +35,12 @@ class RunModel(Base): # type: ignore id = Column(String, primary_key=True, index=True) blob = Column(JSON) - model_config = ConfigDict(from_attributes=True) + if PYDANTIC_V2: + model_config = ConfigDict(from_attributes=True) + else: + + class Config: + orm_mode = True class UserRunDetailsModel(Base): # type: ignore @@ -47,7 +53,12 @@ class UserRunDetailsModel(Base): # type: ignore bookmark = Column(Boolean, default=False) title = Column(String) notes = Column(String) - model_config = ConfigDict(from_attributes=True) + if PYDANTIC_V2: + model_config = ConfigDict(from_attributes=True) + else: + + class Config: + orm_mode = True class TrackingDatasetGroup(str, Enum): From 77378c40319d1cddb08342a48184d1b02f858d0e Mon Sep 17 00:00:00 2001 From: fdroessler Date: Mon, 25 Sep 2023 23:11:49 +0200 Subject: [PATCH 5/9] ignore mypy pydantic issues Signed-off-by: fdroessler --- package/kedro_viz/api/rest/responses.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/package/kedro_viz/api/rest/responses.py b/package/kedro_viz/api/rest/responses.py index 910fc24087..446a87ec45 100644 --- a/package/kedro_viz/api/rest/responses.py +++ b/package/kedro_viz/api/rest/responses.py @@ -64,7 +64,7 @@ class BaseGraphNodeAPIResponse(BaseAPIResponse): class TaskNodeAPIResponse(BaseGraphNodeAPIResponse): parameters: Dict if PYDANTIC_V2: - model_config = ConfigDict(json_schema_extra=task_node_api_response_example) + model_config = ConfigDict(json_schema_extra=task_node_api_response_example) # type: ignore else: class Config: @@ -91,7 +91,7 @@ class DataNodeAPIResponse(BaseGraphNodeAPIResponse): dataset_type: Optional[str] = None stats: Optional[Dict] = None if PYDANTIC_V2: - model_config = ConfigDict(json_schema_extra=data_node_api_response_example) + model_config = ConfigDict(json_schema_extra=data_node_api_response_example) # type: ignore else: class Config: @@ -124,7 +124,7 @@ class TaskNodeMetadataAPIResponse(BaseAPIResponse): outputs: List[str] run_command: Optional[str] = None if PYDANTIC_V2: - model_config = ConfigDict(json_schema_extra=task_node_metadata_api_example) + model_config = ConfigDict(json_schema_extra=task_node_metadata_api_example) # type: ignore else: class Config: @@ -150,7 +150,7 @@ class DataNodeMetadataAPIResponse(BaseAPIResponse): preview: Optional[Dict] = None stats: Optional[Dict] = None if PYDANTIC_V2: - model_config = ConfigDict(json_schema_extra=data_node_metadata_api_example) + model_config = ConfigDict(json_schema_extra=data_node_metadata_api_example) # type: ignore else: class Config: @@ -189,7 +189,7 @@ class ParametersNodeMetadataAPIResponse(BaseAPIResponse): parameters: Dict if PYDANTIC_V2: model_config = ConfigDict( - json_schema_extra=parameters_node_metaxata_api_example + json_schema_extra=parameters_node_metaxata_api_example # type: ignore ) else: From 446de3568401545088d234386a3bf7459b00522a Mon Sep 17 00:00:00 2001 From: Florian Roessler Date: Mon, 30 Oct 2023 17:47:46 +0100 Subject: [PATCH 6/9] revert pydantic v2 compat code Signed-off-by: Florian Roessler --- RELEASE.md | 2 +- package/features/steps/lower_requirements.txt | 1 - package/kedro_viz/api/rest/responses.py | 203 ++++++++---------- .../kedro_viz/models/experiment_tracking.py | 16 +- package/requirements.txt | 2 +- 5 files changed, 92 insertions(+), 132 deletions(-) diff --git a/RELEASE.md b/RELEASE.md index 60f23a9aca..33df74cf99 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -10,7 +10,7 @@ Please follow the established format: ## Bug fixes and other changes - Fix for Kedro Viz Connection Error (#1507) -- Add support for pydantic v2 and fastapi >= 0.100.0 (#1529) +- Add support for fastapi >= 0.100.0 (#1529) # Release 6.5.1 diff --git a/package/features/steps/lower_requirements.txt b/package/features/steps/lower_requirements.txt index 19714bc525..16acd36b43 100644 --- a/package/features/steps/lower_requirements.txt +++ b/package/features/steps/lower_requirements.txt @@ -13,4 +13,3 @@ strawberry-graphql==0.192.0 networkx==2.5 orjson==3.9 secure==0.3.0 -pydantic<2 diff --git a/package/kedro_viz/api/rest/responses.py b/package/kedro_viz/api/rest/responses.py index 446a87ec45..6ee605856b 100644 --- a/package/kedro_viz/api/rest/responses.py +++ b/package/kedro_viz/api/rest/responses.py @@ -4,9 +4,14 @@ from typing import Any, Dict, List, Optional, Union import orjson -from fastapi._compat import PYDANTIC_V2 from fastapi.responses import ORJSONResponse -from pydantic import BaseModel, ConfigDict + +try: + # Triggered if pydantic v2 is installed + from pydantic.v1 import BaseModel +except ImportError: + # Triggered if pydantic v1 is installed + from pydantic import BaseModel from kedro_viz.data_access import data_access_manager @@ -16,12 +21,8 @@ class APIErrorMessage(BaseModel): class BaseAPIResponse(BaseModel, abc.ABC): - if PYDANTIC_V2: - model_config = ConfigDict(from_attributes=True) - else: - - class Config: - orm_mode = True + class Config: + orm_mode = True class BaseGraphNodeAPIResponse(BaseAPIResponse): @@ -35,67 +36,55 @@ class BaseGraphNodeAPIResponse(BaseAPIResponse): modular_pipelines: Optional[List[str]] = None -task_node_api_response_example = { - "example": { - "id": "6ab908b8", - "name": "split_data_node", - "tags": [], - "pipelines": ["__default__", "ds"], - "modular_pipelines": [], - "type": "task", - "parameters": { - "test_size": 0.2, - "random_state": 3, - "features": [ - "engines", - "passenger_capacity", - "crew", - "d_check_complete", - "moon_clearance_complete", - "iata_approved", - "company_rating", - "review_scores_rating", - ], - }, - } -} - - class TaskNodeAPIResponse(BaseGraphNodeAPIResponse): parameters: Dict - if PYDANTIC_V2: - model_config = ConfigDict(json_schema_extra=task_node_api_response_example) # type: ignore - else: - - class Config: - schema_extra = task_node_api_response_example - -data_node_api_response_example = { - "example": { - "id": "d7b83b05", - "name": "master_table", - "tags": [], - "pipelines": ["__default__", "dp", "ds"], - "modular_pipelines": [], - "type": "data", - "layer": "primary", - "dataset_type": "kedro.extras.datasets.pandas.csv_dataset.CSVDataSet", - "stats": {"rows": 10, "columns": 2, "file_size": 2300}, - } -} + class Config: + schema_extra = { + "example": { + "id": "6ab908b8", + "name": "split_data_node", + "tags": [], + "pipelines": ["__default__", "ds"], + "modular_pipelines": [], + "type": "task", + "parameters": { + "test_size": 0.2, + "random_state": 3, + "features": [ + "engines", + "passenger_capacity", + "crew", + "d_check_complete", + "moon_clearance_complete", + "iata_approved", + "company_rating", + "review_scores_rating", + ], + }, + } + } class DataNodeAPIResponse(BaseGraphNodeAPIResponse): layer: Optional[str] = None dataset_type: Optional[str] = None stats: Optional[Dict] = None - if PYDANTIC_V2: - model_config = ConfigDict(json_schema_extra=data_node_api_response_example) # type: ignore - else: - class Config: - schema_extra = data_node_api_response_example + class Config: + schema_extra = { + "example": { + "id": "d7b83b05", + "name": "master_table", + "tags": [], + "pipelines": ["__default__", "dp", "ds"], + "modular_pipelines": [], + "type": "data", + "layer": "primary", + "dataset_type": "kedro.extras.datasets.pandas.csv_dataset.CSVDataSet", + "stats": {"rows": 10, "columns": 2, "file_size": 2300}, + } + } NodeAPIResponse = Union[ @@ -104,18 +93,6 @@ class Config: ] -task_node_metadata_api_example = { - "example": { - "code": "def split_data(data: pd.DataFrame, parameters: Dict) -> Tuple:", - "filepath": "proj/src/new_kedro_project/pipelines/data_science/nodes.py", - "parameters": {"test_size": 0.2}, - "inputs": ["params:input1", "input2"], - "outputs": ["output1"], - "run_command": "kedro run --to-nodes=split_data", - } -} - - class TaskNodeMetadataAPIResponse(BaseAPIResponse): code: Optional[str] = None filepath: Optional[str] = None @@ -123,21 +100,18 @@ class TaskNodeMetadataAPIResponse(BaseAPIResponse): inputs: List[str] outputs: List[str] run_command: Optional[str] = None - if PYDANTIC_V2: - model_config = ConfigDict(json_schema_extra=task_node_metadata_api_example) # type: ignore - else: - class Config: - schema_extra = task_node_metadata_api_example - - -data_node_metadata_api_example = { - "example": { - "filepath": "/my-kedro-project/data/03_primary/master_table.csv", - "type": "pandas.csv_dataset.CSVDataSet", - "run_command": "kedro run --to-outputs=master_table", - } -} + class Config: + schema_extra = { + "example": { + "code": "def split_data(data: pd.DataFrame, parameters: Dict) -> Tuple:", + "filepath": "proj/src/new_kedro_project/pipelines/data_science/nodes.py", + "parameters": {"test_size": 0.2}, + "inputs": ["params:input1", "input2"], + "outputs": ["output1"], + "run_command": "kedro run --to-nodes=split_data", + } + } class DataNodeMetadataAPIResponse(BaseAPIResponse): @@ -149,12 +123,15 @@ class DataNodeMetadataAPIResponse(BaseAPIResponse): run_command: Optional[str] = None preview: Optional[Dict] = None stats: Optional[Dict] = None - if PYDANTIC_V2: - model_config = ConfigDict(json_schema_extra=data_node_metadata_api_example) # type: ignore - else: - class Config: - schema_extra = data_node_metadata_api_example + class Config: + schema_extra = { + "example": { + "filepath": "/my-kedro-project/data/03_primary/master_table.csv", + "type": "pandas.csv_dataset.CSVDataSet", + "run_command": "kedro run --to-outputs=master_table", + } + } class TranscodedDataNodeMetadataAPIReponse(BaseAPIResponse): @@ -165,36 +142,28 @@ class TranscodedDataNodeMetadataAPIReponse(BaseAPIResponse): stats: Optional[Dict] = None -parameters_node_metaxata_api_example = { - "example": { - "parameters": { - "test_size": 0.2, - "random_state": 3, - "features": [ - "engines", - "passenger_capacity", - "crew", - "d_check_complete", - "moon_clearance_complete", - "iata_approved", - "company_rating", - "review_scores_rating", - ], - } - } -} - - class ParametersNodeMetadataAPIResponse(BaseAPIResponse): parameters: Dict - if PYDANTIC_V2: - model_config = ConfigDict( - json_schema_extra=parameters_node_metaxata_api_example # type: ignore - ) - else: - class Config: - schema_extra = parameters_node_metaxata_api_example + class Config: + schema_extra = { + "example": { + "parameters": { + "test_size": 0.2, + "random_state": 3, + "features": [ + "engines", + "passenger_capacity", + "crew", + "d_check_complete", + "moon_clearance_complete", + "iata_approved", + "company_rating", + "review_scores_rating", + ], + } + } + } NodeMetadataAPIResponse = Union[ diff --git a/package/kedro_viz/models/experiment_tracking.py b/package/kedro_viz/models/experiment_tracking.py index 5dd85cfae3..ce8cf012c2 100644 --- a/package/kedro_viz/models/experiment_tracking.py +++ b/package/kedro_viz/models/experiment_tracking.py @@ -6,9 +6,7 @@ from enum import Enum from typing import TYPE_CHECKING, Any, Dict -from fastapi._compat import PYDANTIC_V2 from kedro.io import Version -from pydantic import ConfigDict from sqlalchemy import Column from sqlalchemy.orm import declarative_base # type: ignore from sqlalchemy.sql.schema import ForeignKey @@ -35,12 +33,9 @@ class RunModel(Base): # type: ignore id = Column(String, primary_key=True, index=True) blob = Column(JSON) - if PYDANTIC_V2: - model_config = ConfigDict(from_attributes=True) - else: - class Config: - orm_mode = True + class Config: + orm_mode = True class UserRunDetailsModel(Base): # type: ignore @@ -53,12 +48,9 @@ class UserRunDetailsModel(Base): # type: ignore bookmark = Column(Boolean, default=False) title = Column(String) notes = Column(String) - if PYDANTIC_V2: - model_config = ConfigDict(from_attributes=True) - else: - class Config: - orm_mode = True + class Config: + orm_mode = True class TrackingDatasetGroup(str, Enum): diff --git a/package/requirements.txt b/package/requirements.txt index 1dd1f4e203..a682cb2e0b 100644 --- a/package/requirements.txt +++ b/package/requirements.txt @@ -1,7 +1,7 @@ semver>=2.10 # Needs to be at least 2.10.0 to make use of `VersionInfo.match`. kedro>=0.17.5 ipython>=7.0.0, <9.0 -fastapi>=0.73.0, <0.104.0 +fastapi>=0.100.0,<0.102.0 fsspec>=2021.4, <2024.1 aiofiles==22.1.0 uvicorn[standard]~=0.22.0 From a48608a5110e4ee7cce7fbdf734c0a7e2ffd261e Mon Sep 17 00:00:00 2001 From: Florian Roessler Date: Mon, 30 Oct 2023 18:12:09 +0100 Subject: [PATCH 7/9] fix release and ignore try except import in mypy Signed-off-by: Florian Roessler --- RELEASE.md | 1 - package/kedro_viz/api/rest/responses.py | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/RELEASE.md b/RELEASE.md index ce4e136a38..3908db36d8 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -9,7 +9,6 @@ Please follow the established format: ## Bug fixes and other changes -- Fix for Kedro Viz Connection Error (#1507) - Add support for fastapi >= 0.100.0 (#1529) - Fix dataset factory patterns in Experiment Tracking. (#1588) diff --git a/package/kedro_viz/api/rest/responses.py b/package/kedro_viz/api/rest/responses.py index c3008a5e06..6435e3713d 100644 --- a/package/kedro_viz/api/rest/responses.py +++ b/package/kedro_viz/api/rest/responses.py @@ -13,10 +13,10 @@ try: # Triggered if pydantic v2 is installed - from pydantic.v1 import BaseModel + from pydantic.v1 import BaseModel # type: ignore except ImportError: # Triggered if pydantic v1 is installed - from pydantic import BaseModel + from pydantic import BaseModel # type: ignore from kedro_viz.api.rest.utils import get_package_version from kedro_viz.data_access import data_access_manager From f7f3e716517be3a347bf9d2841e1e140b741fbd0 Mon Sep 17 00:00:00 2001 From: Florian Roessler Date: Mon, 30 Oct 2023 18:21:24 +0100 Subject: [PATCH 8/9] ignore try except import in mypy Signed-off-by: Florian Roessler --- package/kedro_viz/api/rest/responses.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/package/kedro_viz/api/rest/responses.py b/package/kedro_viz/api/rest/responses.py index 6435e3713d..6755777c76 100644 --- a/package/kedro_viz/api/rest/responses.py +++ b/package/kedro_viz/api/rest/responses.py @@ -2,7 +2,7 @@ # pylint: disable=missing-class-docstring,too-few-public-methods,invalid-name import abc import logging -from typing import Any, Dict, List, Optional, Union +from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union import fsspec import orjson @@ -11,12 +11,15 @@ from fastapi.responses import JSONResponse, ORJSONResponse from kedro.io.core import get_protocol_and_path -try: - # Triggered if pydantic v2 is installed - from pydantic.v1 import BaseModel # type: ignore -except ImportError: - # Triggered if pydantic v1 is installed - from pydantic import BaseModel # type: ignore +if TYPE_CHECKING: + from pydantic import BaseModel +else: + try: + # Triggered if pydantic v2 is installed + from pydantic.v1 import BaseModel + except ImportError: + # Triggered if pydantic v1 is installed + from pydantic import BaseModel from kedro_viz.api.rest.utils import get_package_version from kedro_viz.data_access import data_access_manager From a497d5db100376dd8be9d600113e437fd81ac581 Mon Sep 17 00:00:00 2001 From: Florian Roessler Date: Mon, 30 Oct 2023 18:30:05 +0100 Subject: [PATCH 9/9] ignore try except import in mypy Signed-off-by: Florian Roessler --- package/kedro_viz/api/rest/responses.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/package/kedro_viz/api/rest/responses.py b/package/kedro_viz/api/rest/responses.py index 6755777c76..e7c6993fdb 100644 --- a/package/kedro_viz/api/rest/responses.py +++ b/package/kedro_viz/api/rest/responses.py @@ -11,16 +11,6 @@ from fastapi.responses import JSONResponse, ORJSONResponse from kedro.io.core import get_protocol_and_path -if TYPE_CHECKING: - from pydantic import BaseModel -else: - try: - # Triggered if pydantic v2 is installed - from pydantic.v1 import BaseModel - except ImportError: - # Triggered if pydantic v1 is installed - from pydantic import BaseModel - from kedro_viz.api.rest.utils import get_package_version from kedro_viz.data_access import data_access_manager from kedro_viz.models.flowchart import ( @@ -33,6 +23,16 @@ TranscodedDataNodeMetadata, ) +if TYPE_CHECKING: + from pydantic import BaseModel +else: + try: + # Triggered if pydantic v2 is installed + from pydantic.v1 import BaseModel + except ImportError: + # Triggered if pydantic v1 is installed + from pydantic import BaseModel + logger = logging.getLogger(__name__) _FSSPEC_PACKAGE_NAME = "fsspec"