diff --git a/RELEASE.md b/RELEASE.md index 5e08f318d6..72cfee8cdb 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -5,6 +5,14 @@ Please follow the established format: - Use present tense (e.g. 'Add new feature') - Include the ID number for the related PR (or PRs) in parentheses --> + +# Release 10.1.0 + +## Major features and improvements + +- Update Kedro-Viz telemetry for opt-out model (#2022) + + # Release 10.0.0 ## Major features and improvements diff --git a/package/.pylintrc b/package/.pylintrc index e8ae443c08..bbf5e49a40 100644 --- a/package/.pylintrc +++ b/package/.pylintrc @@ -321,7 +321,7 @@ valid-metaclass-classmethod-first-arg=mcs [DESIGN] # Maximum number of arguments for function / method -max-args=5 +max-args=12 # Maximum number of attributes for a class (see R0902). max-attributes=7 diff --git a/package/kedro_viz/data_access/managers.py b/package/kedro_viz/data_access/managers.py index 9801c86cb7..40e00ebe55 100644 --- a/package/kedro_viz/data_access/managers.py +++ b/package/kedro_viz/data_access/managers.py @@ -230,6 +230,7 @@ def add_node( self.tags.add_tags(task_node.tags) return task_node + # pylint: disable=too-many-positional-arguments def add_node_input( self, registered_pipeline_id: str, diff --git a/package/kedro_viz/integrations/kedro/data_loader.py b/package/kedro_viz/integrations/kedro/data_loader.py index 2955d73b29..aabc5b73a5 100644 --- a/package/kedro_viz/integrations/kedro/data_loader.py +++ b/package/kedro_viz/integrations/kedro/data_loader.py @@ -108,6 +108,7 @@ def _load_data_helper( return catalog, pipelines_dict, session_store, stats_dict +# pylint: disable=too-many-positional-arguments def load_data( project_path: Path, env: Optional[str] = None, diff --git a/package/kedro_viz/integrations/kedro/telemetry.py b/package/kedro_viz/integrations/kedro/telemetry.py index 45bcefb5d8..2c57c41536 100644 --- a/package/kedro_viz/integrations/kedro/telemetry.py +++ b/package/kedro_viz/integrations/kedro/telemetry.py @@ -1,14 +1,15 @@ """`kedro_viz.integrations.kedro.telemetry` helps integrate Kedro-Viz with Kedro-Telemetry """ -import hashlib -import socket + from pathlib import Path from typing import Optional -import yaml - try: - from kedro_telemetry.plugin import _get_heap_app_id, _is_valid_syntax + from kedro_telemetry.plugin import ( + _check_for_telemetry_consent, + _get_heap_app_id, + _get_or_create_uuid, + ) _IS_TELEMETRY_INSTALLED = True except ImportError: # pragma: no cover @@ -19,23 +20,18 @@ def get_heap_app_id(project_path: Path) -> Optional[str]: """Return the Heap App ID used for Kedro telemetry if user has given consent.""" if not _IS_TELEMETRY_INSTALLED: # pragma: no cover return None - telemetry_file_path = project_path / ".telemetry" - if not telemetry_file_path.exists(): - return None - with open( - telemetry_file_path, encoding="utf8" - ) as telemetry_file: # pylint: disable: unspecified-encoding - telemetry = yaml.safe_load(telemetry_file) - if _is_valid_syntax(telemetry) and telemetry["consent"]: - return _get_heap_app_id() + + if _check_for_telemetry_consent(project_path): + return _get_heap_app_id() return None +# pylint: disable=broad-exception-caught def get_heap_identity() -> Optional[str]: # pragma: no cover - """Return the user ID in heap identical to the id used by kedro-telemetry plugin.""" + """Reads a UUID from a configuration file or generates and saves a new one if not present.""" if not _IS_TELEMETRY_INSTALLED: return None try: - return hashlib.sha512(bytes(socket.gethostname(), encoding="utf8")).hexdigest() - except socket.timeout: + return _get_or_create_uuid() + except Exception: # pragma: no cover return None diff --git a/package/kedro_viz/launchers/cli/run.py b/package/kedro_viz/launchers/cli/run.py index 9988214261..97c9ab3dbc 100644 --- a/package/kedro_viz/launchers/cli/run.py +++ b/package/kedro_viz/launchers/cli/run.py @@ -83,7 +83,7 @@ is_flag=True, help="An experimental flag to open Kedro-Viz without Kedro project dependencies", ) -# pylint: disable=import-outside-toplevel, too-many-locals +# pylint: disable=import-outside-toplevel, too-many-locals, too-many-positional-arguments def run( host, port, diff --git a/package/kedro_viz/launchers/cli/utils.py b/package/kedro_viz/launchers/cli/utils.py index eb4efdfbc9..290a0461c0 100644 --- a/package/kedro_viz/launchers/cli/utils.py +++ b/package/kedro_viz/launchers/cli/utils.py @@ -114,6 +114,7 @@ def display_cli_message(msg, msg_color=None): ) +# pylint: disable=too-many-positional-arguments def _load_and_deploy_viz( platform, is_all_previews_enabled, diff --git a/package/kedro_viz/models/flowchart.py b/package/kedro_viz/models/flowchart.py index e8e81cfb61..9e6cb087d4 100644 --- a/package/kedro_viz/models/flowchart.py +++ b/package/kedro_viz/models/flowchart.py @@ -164,6 +164,7 @@ def create_task_node( ) @classmethod + # pylint: disable=too-many-positional-arguments def create_data_node( cls, dataset_id: str, @@ -216,6 +217,7 @@ def create_data_node( ) @classmethod + # pylint: disable=too-many-positional-arguments def create_parameters_node( cls, dataset_id: str, diff --git a/package/kedro_viz/server.py b/package/kedro_viz/server.py index 76026ddbbf..37d31f2f19 100644 --- a/package/kedro_viz/server.py +++ b/package/kedro_viz/server.py @@ -44,6 +44,7 @@ def populate_data( data_access_manager.add_pipelines(pipelines) +# pylint: disable=too-many-positional-arguments def load_and_populate_data( path: Path, env: Optional[str] = None, @@ -70,7 +71,7 @@ def load_and_populate_data( populate_data(data_access_manager, catalog, pipelines, session_store, stats_dict) -# pylint: disable=too-many-locals +# pylint: disable=too-many-positional-arguments, too-many-locals def run_server( host: str = DEFAULT_HOST, port: int = DEFAULT_PORT, diff --git a/package/requirements.txt b/package/requirements.txt index 2b1dad563f..caf3fa63ea 100644 --- a/package/requirements.txt +++ b/package/requirements.txt @@ -4,6 +4,7 @@ fastapi>=0.100.0,<0.200.0 fsspec>=2021.4 ipython>=7.0.0, <9.0 kedro>=0.18.0 +kedro-telemetry>=0.6.0 networkx>=2.5 orjson>=3.9, <4.0 packaging>=23.0 diff --git a/package/tests/test_api/test_apps.py b/package/tests/test_api/test_apps.py index 310c2b679f..38e7b427ad 100644 --- a/package/tests/test_api/test_apps.py +++ b/package/tests/test_api/test_apps.py @@ -10,7 +10,7 @@ class TestIndexEndpoint: def test_index(self, client): response = client.get("/") assert response.status_code == 200 - assert "heap" not in response.text + assert "heap" in response.text assert "checkReloadStatus" not in response.text @mock.patch("kedro_viz.integrations.kedro.telemetry.get_heap_app_id") diff --git a/package/tests/test_integrations/test_telemetry.py b/package/tests/test_integrations/test_telemetry.py index f5bae4a613..f8fbfc8a26 100644 --- a/package/tests/test_integrations/test_telemetry.py +++ b/package/tests/test_integrations/test_telemetry.py @@ -5,13 +5,13 @@ def test_get_heap_app_id_no_telemetry_file(): - assert kedro_telemetry.get_heap_app_id(Path.cwd()) is None + assert kedro_telemetry.get_heap_app_id(Path.cwd()) is not None def test_get_heap_app_id_invalid_telemetry_file(tmpdir): telemetry_file = tmpdir / ".telemetry" telemetry_file.write_text("foo", encoding="utf-8") - assert kedro_telemetry.get_heap_app_id(tmpdir) is None + assert kedro_telemetry.get_heap_app_id(tmpdir) is not None def test_get_heap_app_id_no_consent(tmpdir): @@ -21,8 +21,22 @@ def test_get_heap_app_id_no_consent(tmpdir): @mock.patch("kedro_viz.integrations.kedro.telemetry._get_heap_app_id") -def test_get_heap_app_id_with_consent(original_get_heap_app_id, tmpdir): - original_get_heap_app_id.return_value = "my_heap_id" +@mock.patch("kedro_viz.integrations.kedro.telemetry._check_for_telemetry_consent") +def test_get_heap_app_id_with_consent( + mock_check_for_telemetry_consent, mock_get_heap_app_id, tmpdir +): + mock_check_for_telemetry_consent.return_value = True + mock_get_heap_app_id.return_value = "my_heap_id" telemetry_file = tmpdir / ".telemetry" telemetry_file.write_text("consent: true", encoding="utf-8") assert kedro_telemetry.get_heap_app_id(tmpdir) == "my_heap_id" + + +@mock.patch("kedro_viz.integrations.kedro.telemetry._check_for_telemetry_consent") +def test_get_heap_app_id_with_env_var(mock_check_for_telemetry_consent, tmpdir): + mock_check_for_telemetry_consent.return_value = False + with mock.patch.dict("os.environ", {"DO_NOT_TRACK": "1"}): + assert kedro_telemetry.get_heap_app_id(tmpdir) is None + + with mock.patch.dict("os.environ", {"KEDRO_DISABLE_TELEMETRY": "1"}): + assert kedro_telemetry.get_heap_app_id(tmpdir) is None