Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Kedro Viz Lite User Warning UI #2092

Merged
merged 27 commits into from
Sep 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
8830cab
sync remote
ravi-kumar-pilla Jul 28, 2024
0a5d1ae
Merge branch 'main' of https://github.com/kedro-org/kedro-viz
ravi-kumar-pilla Jul 30, 2024
bf47b47
merge main
ravi-kumar-pilla Aug 8, 2024
13e905b
Merge branch 'main' of https://github.com/kedro-org/kedro-viz
ravi-kumar-pilla Aug 13, 2024
3d6326c
Merge branch 'main' of https://github.com/kedro-org/kedro-viz
ravi-kumar-pilla Aug 21, 2024
3d3bdda
Merge branch 'main' of https://github.com/kedro-org/kedro-viz
ravi-kumar-pilla Aug 22, 2024
1abfc43
Merge branch 'main' of https://github.com/kedro-org/kedro-viz
ravi-kumar-pilla Sep 4, 2024
1461a3c
Merge branch 'main' of https://github.com/kedro-org/kedro-viz
ravi-kumar-pilla Sep 5, 2024
c3f7cc6
Merge branch 'main' of https://github.com/kedro-org/kedro-viz
ravi-kumar-pilla Sep 9, 2024
61a871b
add lite viz banner
ravi-kumar-pilla Sep 10, 2024
3cc318e
banner design change
ravi-kumar-pilla Sep 10, 2024
39a5b45
Merge branch 'main' of https://github.com/kedro-org/kedro-viz into fe…
ravi-kumar-pilla Sep 10, 2024
54f18a1
add tests
ravi-kumar-pilla Sep 10, 2024
2191529
Merge branch 'main' of https://github.com/kedro-org/kedro-viz into fe…
ravi-kumar-pilla Sep 10, 2024
497d03c
refactor metadata api
ravi-kumar-pilla Sep 11, 2024
17c85a8
fix permissions
ravi-kumar-pilla Sep 11, 2024
d4bf0d2
working state
ravi-kumar-pilla Sep 12, 2024
3495f52
comment out banner condition for testing
ravi-kumar-pilla Sep 12, 2024
26d8cfb
Merge branch 'main' into feature/lite-user-warning-ui
ravi-kumar-pilla Sep 12, 2024
160f18f
address PR comments
ravi-kumar-pilla Sep 13, 2024
f8dbf95
Merge branch 'main' of https://github.com/kedro-org/kedro-viz into fe…
ravi-kumar-pilla Sep 13, 2024
a34b677
Merge branch 'feature/lite-user-warning-ui' of https://github.com/ked…
ravi-kumar-pilla Sep 13, 2024
f887a27
Merge branch 'main' into feature/lite-user-warning-ui
ravi-kumar-pilla Sep 16, 2024
405826e
fix tests
ravi-kumar-pilla Sep 16, 2024
8563187
update tests
ravi-kumar-pilla Sep 16, 2024
b38d19e
Merge branch 'main' of https://github.com/kedro-org/kedro-viz into fe…
ravi-kumar-pilla Sep 17, 2024
bb54b94
update release
ravi-kumar-pilla Sep 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions RELEASE.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Please follow the established format:
- Fixes design issues in metadata panel. (#2009)
- Fix missing run command in metadata panel for task nodes. (#2055)
- Add `UnavailableDataset` as a default dataset for `--lite` mode. (#2083)
- Add `kedro viz --lite` user warning banner UI. (#2092)

# Release 9.2.0

Expand Down
15 changes: 15 additions & 0 deletions cypress/fixtures/mock/compatibleMetadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"has_missing_dependencies": false,
"package_compatibilities": [
{
"package_name": "fsspec",
"package_version": "2023.9.1",
"is_compatible": true
},
{
"package_name": "kedro-datasets",
"package_version": "2.0.0",
"is_compatible": true
}
]
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
[
{
{
"has_missing_dependencies": true,
"package_compatibilities": [
{
"package_name": "fsspec",
"package_version": "2023.8.1",
"is_compatible": false
},
{
},
{
"package_name": "kedro-datasets",
"package_version": "1.8.0",
"is_compatible": false
}
]
}
]
}
12 changes: 0 additions & 12 deletions cypress/fixtures/mock/package-compatibilities-compatible.json

This file was deleted.

32 changes: 32 additions & 0 deletions cypress/tests/ui/flowchart/banners.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
describe('Banners in Kedro-Viz', () => {
beforeEach(() => {
// Clears localStorage before each test
cy.clearLocalStorage();
});

it("shows a missing dependencies banner in viz lite mode if the kedro project dependencies are not installed.", () => {
// Intercept the network request to mock with a fixture
cy.__interceptRest__(
'/api/metadata',
'GET',
'/mock/inCompatibleMetadata.json'
).as("appMetadata");

// Action
cy.reload();

// Assert after action
cy.get('[data-test="flowchart-wrapper--lite-banner"]').should('exist');
cy.get('.banner-message-body').should('contains.text', 'please install the missing Kedro project dependencies')
cy.get('.banner-message-title').should('contains.text', 'Missing dependencies')

// Test Learn more link
cy.get(".banner a")
.should("contains.attr", "href", "https://docs.kedro.org/projects/kedro-viz/en/latest/kedro-viz_visualisation.html#visualise-a-kedro-project-without-installing-project-dependencies");

// Close the banner
cy.get(".banner-close").click()
cy.get('[data-test="flowchart-wrapper--lite-banner"]').should('not.exist');

});
});
8 changes: 4 additions & 4 deletions cypress/tests/ui/flowchart/shareable-urls.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ describe('Shareable URLs with empty localStorage', () => {
it('verifies that users can open the Deploy Kedro-Viz modal if the localStorage is empty. #TC-52', () => {
// Intercept the network request to mock with a fixture
cy.__interceptRest__(
'/api/package-compatibilities',
'/api/metadata',
'GET',
'/mock/package-compatibilities-compatible.json'
'/mock/compatibleMetadata.json'
);

// Action
Expand All @@ -25,9 +25,9 @@ describe('Shareable URLs with empty localStorage', () => {
it("shows an incompatible message given the user's fsspec package version is outdated. #TC-53", () => {
// Intercept the network request to mock with a fixture
cy.__interceptRest__(
'/api/package-compatibilities',
'/api/metadata',
'GET',
'/mock/package-compatibilities-incompatible.json'
'/mock/inCompatibleMetadata.json'
);

// Action
Expand Down
62 changes: 23 additions & 39 deletions package/kedro_viz/api/rest/responses.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,14 @@
import abc
import json
import logging
from importlib.metadata import PackageNotFoundError
from typing import Any, Dict, List, Optional, Union

import orjson
import packaging
from fastapi.encoders import jsonable_encoder
from fastapi.responses import JSONResponse, ORJSONResponse
from pydantic import BaseModel, ConfigDict

from kedro_viz.api.rest.utils import get_package_version
from kedro_viz.api.rest.utils import get_package_compatibilities
from kedro_viz.data_access import data_access_manager
from kedro_viz.models.flowchart import (
DataNode,
Expand All @@ -24,6 +22,7 @@
TranscodedDataNode,
TranscodedDataNodeMetadata,
)
from kedro_viz.models.metadata import Metadata, PackageCompatibility

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -259,17 +258,24 @@ class GraphAPIResponse(BaseAPIResponse):
selected_pipeline: str


class PackageCompatibilityAPIResponse(BaseAPIResponse):
package_name: str
package_version: str
is_compatible: bool
class MetadataAPIResponse(BaseAPIResponse):
has_missing_dependencies: bool = False
package_compatibilities: List[PackageCompatibility] = []
model_config = ConfigDict(
json_schema_extra={
"example": {
"package_name": "fsspec",
"package_version": "2023.9.1",
"is_compatible": True,
}
"has_missing_dependencies": False,
"package_compatibilities": [
{
"package_name": "fsspec",
"package_version": "2024.6.1",
"is_compatible": True,
},
{
"package_name": "kedro-datasets",
"package_version": "4.0.0",
"is_compatible": True,
},
],
}
)

Expand Down Expand Up @@ -372,33 +378,11 @@ def get_selected_pipeline_response(registered_pipeline_id: str):
)


def get_package_compatibilities_response(
package_requirements: Dict[str, Dict[str, str]],
) -> List[PackageCompatibilityAPIResponse]:
"""API response for `/api/package_compatibility`."""
package_requirements_response = []

for package_name, package_info in package_requirements.items():
compatible_version = package_info["min_compatible_version"]
try:
package_version = get_package_version(package_name)
except PackageNotFoundError:
logger.warning(package_info["warning_message"])
package_version = "0.0.0"

is_compatible = packaging.version.parse(
package_version
) >= packaging.version.parse(compatible_version)

package_requirements_response.append(
PackageCompatibilityAPIResponse(
package_name=package_name,
package_version=package_version,
is_compatible=is_compatible,
)
)

return package_requirements_response
def get_metadata_response():
"""API response for `/api/metadata`."""
package_compatibilities = get_package_compatibilities()
Metadata.set_package_compatibilities(package_compatibilities)
return Metadata()


def get_encoded_response(response: Any) -> bytes:
Expand Down
20 changes: 8 additions & 12 deletions package/kedro_viz/api/rest/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,21 @@

# pylint: disable=missing-function-docstring, broad-exception-caught
import logging
from typing import List

from fastapi import APIRouter
from fastapi.responses import JSONResponse

from kedro_viz.api.rest.requests import DeployerConfiguration
from kedro_viz.constants import PACKAGE_REQUIREMENTS
from kedro_viz.integrations.deployment.deployer_factory import DeployerFactory

from .responses import (
APIErrorMessage,
GraphAPIResponse,
MetadataAPIResponse,
NodeMetadataAPIResponse,
PackageCompatibilityAPIResponse,
get_default_response,
get_metadata_response,
get_node_metadata_response,
get_package_compatibilities_response,
get_selected_pipeline_response,
)

Expand Down Expand Up @@ -91,17 +89,15 @@ async def deploy_kedro_viz(input_values: DeployerConfiguration):


@router.get(
"/package-compatibilities",
response_model=List[PackageCompatibilityAPIResponse],
"/metadata",
response_model=MetadataAPIResponse,
)
async def get_package_compatibilities():
async def get_metadata():
try:
return get_package_compatibilities_response(PACKAGE_REQUIREMENTS)
return get_metadata_response()
except Exception as exc:
logger.exception(
"An exception occurred while getting package compatibility info : %s", exc
)
logger.exception("An exception occurred while getting app metadata: %s", exc)
return JSONResponse(
status_code=500,
content={"message": "Failed to get package compatibility info"},
content={"message": "Failed to get app metadata"},
)
39 changes: 39 additions & 0 deletions package/kedro_viz/api/rest/utils.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,49 @@
"""`kedro_viz.api.rest.utils` contains utility functions used in the `kedro_viz.api.rest` package"""

import logging
from importlib.metadata import PackageNotFoundError
from typing import List

import packaging

from kedro_viz.constants import PACKAGE_REQUIREMENTS
from kedro_viz.models.metadata import PackageCompatibility

try:
from importlib.metadata import version
except ImportError: # pragma: no cover
from importlib_metadata import version

logger = logging.getLogger(__name__)


def get_package_version(package_name: str):
"""Returns the version of the given package."""
return version(package_name) # pragma: no cover


def get_package_compatibilities() -> List[PackageCompatibility]:
"""Returns the package compatibilities information
for the current python env."""
package_compatibilities: List[PackageCompatibility] = []

for package_name, package_info in PACKAGE_REQUIREMENTS.items():
compatible_version = package_info["min_compatible_version"]
try:
package_version = get_package_version(package_name)
except PackageNotFoundError:
logger.warning(package_info["warning_message"])
package_version = "0.0.0"

is_compatible = packaging.version.parse(
package_version
) >= packaging.version.parse(compatible_version)

package_compatibilities.append(
PackageCompatibility(
package_name=package_name,
package_version=package_version,
is_compatible=is_compatible,
)
)
return package_compatibilities
4 changes: 4 additions & 0 deletions package/kedro_viz/integrations/kedro/data_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
from kedro_viz.integrations.kedro.abstract_dataset_lite import AbstractDatasetLite
from kedro_viz.integrations.kedro.lite_parser import LiteParser
from kedro_viz.integrations.utils import _VizNullPluginManager
from kedro_viz.models.metadata import Metadata

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -145,6 +146,9 @@ def load_data(
if unresolved_imports and len(unresolved_imports) > 0:
modules_to_mock: Set[str] = set()

# for the viz lite banner
Metadata.set_has_missing_dependencies(True)

for unresolved_module_set in unresolved_imports.values():
modules_to_mock = modules_to_mock.union(unresolved_module_set)

Expand Down
47 changes: 47 additions & 0 deletions package/kedro_viz/models/metadata.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
"""`kedro_viz.models.metadata` defines metadata for Kedro-Viz application."""

# pylint: disable=missing-function-docstring
from typing import ClassVar, List

from pydantic import BaseModel, field_validator


class PackageCompatibility(BaseModel):
"""Represent package compatibility in app metadata"""

package_name: str
package_version: str
is_compatible: bool

@field_validator("package_name")
@classmethod
def set_package_name(cls, value):
assert isinstance(value, str)
return value

@field_validator("package_version")
@classmethod
def set_package_version(cls, value):
assert isinstance(value, str)
return value

@field_validator("is_compatible")
@classmethod
def set_is_compatible(cls, value):
assert isinstance(value, bool)
return value


class Metadata(BaseModel):
"""Represent Kedro-Viz application metadata"""

has_missing_dependencies: ClassVar[bool] = False
package_compatibilities: ClassVar[List[PackageCompatibility]] = []

@classmethod
def set_package_compatibilities(cls, value: List[PackageCompatibility]):
cls.package_compatibilities = value

@classmethod
def set_has_missing_dependencies(cls, value: bool):
cls.has_missing_dependencies = value
Loading
Loading