From 4ff9fad2a08c377f0db684043cfa466126e0ed81 Mon Sep 17 00:00:00 2001 From: Arnau Giralt Date: Wed, 11 Feb 2026 10:59:49 +0100 Subject: [PATCH 1/2] LITE-33618: Replace pkg_resources with importlib.resources for setuptools >= 82 compatibility --- connect/eaas/core/extension.py | 7 ++----- tests/connect/eaas/core/test_extension.py | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/connect/eaas/core/extension.py b/connect/eaas/core/extension.py index a6245f3..80c56f7 100644 --- a/connect/eaas/core/extension.py +++ b/connect/eaas/core/extension.py @@ -2,10 +2,10 @@ import inspect import json import os +from importlib.resources import files from typing import Dict, List, Union import anvil.server -import pkg_resources from fastapi import APIRouter from connect.client import AsyncConnectClient, ConnectClient @@ -50,10 +50,7 @@ def get_descriptor(cls) -> dict: # pragma: no cover ``` """ return json.load( - pkg_resources.resource_stream( - cls.__module__, - 'extension.json', - ), + files(cls.__module__).joinpath('extension.json').open('r'), ) @classmethod diff --git a/tests/connect/eaas/core/test_extension.py b/tests/connect/eaas/core/test_extension.py index a05b68c..4f574a5 100644 --- a/tests/connect/eaas/core/test_extension.py +++ b/tests/connect/eaas/core/test_extension.py @@ -1,8 +1,8 @@ import os +from importlib.metadata import EntryPoint import pytest from fastapi_utils.inferring_router import InferringRouter -from pkg_resources import EntryPoint from connect.client import AsyncConnectClient, ConnectClient from connect.eaas.core.constants import UNAUTHORIZED_ENDPOINT_ATTR_NAME From 9e28af3b5fadfcf382b686dffe5273677d6325e0 Mon Sep 17 00:00:00 2001 From: Arnau Giralt Date: Wed, 11 Feb 2026 11:00:44 +0100 Subject: [PATCH 2/2] test: Fix brittle test_helpers tests by replacing Faker-dependent assertions with deterministic data --- connect/eaas/core/extension.py | 2 +- tests/connect/eaas/core/test_extension.py | 56 ++++++++++++++++++ .../eaas/core/validation/test_helpers.py | 59 ++++++++++++++----- 3 files changed, 102 insertions(+), 15 deletions(-) diff --git a/connect/eaas/core/extension.py b/connect/eaas/core/extension.py index 80c56f7..b7b9153 100644 --- a/connect/eaas/core/extension.py +++ b/connect/eaas/core/extension.py @@ -31,7 +31,7 @@ class ApplicationBase: @classmethod - def get_descriptor(cls) -> dict: # pragma: no cover + def get_descriptor(cls) -> dict: """ Returns the **extension.json** extension descriptor. diff --git a/tests/connect/eaas/core/test_extension.py b/tests/connect/eaas/core/test_extension.py index 4f574a5..15b4df0 100644 --- a/tests/connect/eaas/core/test_extension.py +++ b/tests/connect/eaas/core/test_extension.py @@ -1,3 +1,4 @@ +import json import os from importlib.metadata import EntryPoint @@ -131,6 +132,61 @@ async def schedulable2(self, request): assert MyExtension(None, None, None).schedulable1.__doc__ == 'This is schedulable' +def test_get_descriptor(tmp_path, monkeypatch): + pkg_dir = tmp_path / 'fake_ext' + pkg_dir.mkdir() + (pkg_dir / '__init__.py').write_text('') + descriptor = { + 'name': 'Test Extension', + 'description': 'A test extension', + 'version': '1.0.0', + 'audience': ['vendor'], + } + (pkg_dir / 'extension.json').write_text(json.dumps(descriptor)) + + monkeypatch.syspath_prepend(str(tmp_path)) + + class MyExtension(EventsApplicationBase): + pass + + MyExtension.__module__ = 'fake_ext' + + assert MyExtension.get_descriptor() == descriptor + + +def test_get_descriptor_file_not_found(tmp_path, monkeypatch): + pkg_dir = tmp_path / 'fake_ext_no_json' + pkg_dir.mkdir() + (pkg_dir / '__init__.py').write_text('') + + monkeypatch.syspath_prepend(str(tmp_path)) + + class MyExtension(EventsApplicationBase): + pass + + MyExtension.__module__ = 'fake_ext_no_json' + + with pytest.raises(FileNotFoundError): + MyExtension.get_descriptor() + + +def test_get_descriptor_invalid_json(tmp_path, monkeypatch): + pkg_dir = tmp_path / 'fake_ext_bad_json' + pkg_dir.mkdir() + (pkg_dir / '__init__.py').write_text('') + (pkg_dir / 'extension.json').write_text('not valid json{') + + monkeypatch.syspath_prepend(str(tmp_path)) + + class MyExtension(EventsApplicationBase): + pass + + MyExtension.__module__ = 'fake_ext_bad_json' + + with pytest.raises(json.JSONDecodeError): + MyExtension.get_descriptor() + + def test_get_variables(): vars = [ diff --git a/tests/connect/eaas/core/validation/test_helpers.py b/tests/connect/eaas/core/validation/test_helpers.py index ac76e38..6bf142c 100644 --- a/tests/connect/eaas/core/validation/test_helpers.py +++ b/tests/connect/eaas/core/validation/test_helpers.py @@ -1,15 +1,16 @@ from connect.eaas.core.validation.helpers import get_code_context -def test_get_code_context_module(mocker, faker): +def test_get_code_context_module(mocker): mocker.patch( 'connect.eaas.core.validation.helpers.inspect.getsourcefile', return_value='path/file.py', ) - code_lines = [f'{line}\n' for line in faker.paragraphs(nb=10)] - - code = ''.join(code_lines) + pattern = 'target_pattern' + pattern_line = 6 + code_lines = [f'line {i}\n' for i in range(10)] + code_lines[pattern_line] = f'something {pattern} something\n' mocker.patch( 'connect.eaas.core.validation.helpers.inspect.getsourcelines', @@ -23,23 +24,25 @@ def test_get_code_context_module(mocker, faker): return_value=True, ) - result = get_code_context(mocker.MagicMock(), 'country store build before') + result = get_code_context(mocker.MagicMock(), pattern) + expected_lineno = 1 + pattern_line assert result['file'] == 'path/file.py' assert result['start_line'] == 1 - assert result['lineno'] == 7 - assert result['code'] == ''.join(code.splitlines(keepends=True)[0:7 + 3]) + assert result['lineno'] == expected_lineno + assert result['code'] == ''.join(code_lines[0:expected_lineno + 3]) -def test_get_code_context_function(mocker, faker): +def test_get_code_context_function(mocker): mocker.patch( 'connect.eaas.core.validation.helpers.inspect.getsourcefile', return_value='path/file.py', ) - code_lines = [f'{line}\n' for line in faker.paragraphs(nb=10)] - - code = ''.join(code_lines) + pattern = 'target_pattern' + pattern_line = 6 + code_lines = [f'line {i}\n' for i in range(10)] + code_lines[pattern_line] = f'something {pattern} something\n' mocker.patch( 'connect.eaas.core.validation.helpers.inspect.getsourcelines', @@ -53,9 +56,37 @@ def test_get_code_context_function(mocker, faker): return_value=False, ) - result = get_code_context(mocker.MagicMock(), 'country store build before') + result = get_code_context(mocker.MagicMock(), pattern) assert result['file'] == 'path/file.py' assert result['start_line'] == 1 - assert result['lineno'] == 7 - assert result['code'] == ''.join(code.splitlines(keepends=True)) + assert result['lineno'] == 1 + pattern_line + assert result['code'] == ''.join(code_lines) + + +def test_get_code_context_pattern_not_found(mocker): + mocker.patch( + 'connect.eaas.core.validation.helpers.inspect.getsourcefile', + return_value='path/file.py', + ) + + code_lines = [f'line {i}\n' for i in range(10)] + + mocker.patch( + 'connect.eaas.core.validation.helpers.inspect.getsourcelines', + return_value=( + code_lines, + 5, + ), + ) + mocker.patch( + 'connect.eaas.core.validation.helpers.inspect.ismodule', + return_value=False, + ) + + result = get_code_context(mocker.MagicMock(), 'nonexistent_pattern') + + assert result['file'] == 'path/file.py' + assert result['start_line'] == 5 + assert result['lineno'] == 5 + assert result['code'] == ''.join(code_lines)