Skip to content

Commit 544f422

Browse files
authored
Fix bug with uploading evaluations with private link enabled (Azure#39760)
* Fix for bug 3868811 Deserialization class for PrivateEndpointConnection was missing. Since we don't actually need this information for current functionality, this field in the JSON is now ignored by commenting out the respective sections in the model * Merge test recordings * Remove unneeded changes, include tox black reformatting, work around test failures due to irrelevant header * Update test assets
1 parent 4b87d87 commit 544f422

File tree

4 files changed

+39
-30
lines changed

4 files changed

+39
-30
lines changed

sdk/evaluation/azure-ai-evaluation/assets.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
"AssetsRepo": "Azure/azure-sdk-assets",
33
"AssetsRepoPrefixPath": "python",
44
"TagPrefix": "python/evaluation/azure-ai-evaluation",
5-
"Tag": "python/evaluation/azure-ai-evaluation_266a01515b"
5+
"Tag": "python/evaluation/azure-ai-evaluation_2840d9d130"
66
}

sdk/evaluation/azure-ai-evaluation/azure/ai/evaluation/_azure/_models.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ class Workspace(Model):
5252
"agents_endpoint_uri": {"readonly": True},
5353
"ml_flow_tracking_uri": {"readonly": True},
5454
#'notebook_info': {'readonly': True},
55-
"private_endpoint_connections": {"readonly": True},
55+
#"private_endpoint_connections": {"readonly": True},
5656
#'private_link_count': {'readonly': True},
5757
"provisioning_state": {"readonly": True},
5858
"service_provisioned_resource_group": {"readonly": True},
@@ -99,10 +99,10 @@ class Workspace(Model):
9999
#'network_acls': {'key': 'properties.networkAcls', 'type': 'NetworkAcls'},
100100
#'notebook_info': {'key': 'properties.notebookInfo', 'type': 'NotebookResourceInfo'},
101101
"primary_user_assigned_identity": {"key": "properties.primaryUserAssignedIdentity", "type": "str"},
102-
"private_endpoint_connections": {
103-
"key": "properties.privateEndpointConnections",
104-
"type": "[PrivateEndpointConnection]",
105-
},
102+
#"private_endpoint_connections": {
103+
# "key": "properties.privateEndpointConnections",
104+
# "type": "[PrivateEndpointConnection]",
105+
#},
106106
"private_link_count": {"key": "properties.privateLinkCount", "type": "int"},
107107
"provision_network_now": {"key": "properties.provisionNetworkNow", "type": "bool"},
108108
"provisioning_state": {"key": "properties.provisioningState", "type": "str"},
@@ -207,7 +207,7 @@ def __init__(
207207
# self.network_acls = network_acls
208208
# self.notebook_info = None
209209
self.primary_user_assigned_identity = primary_user_assigned_identity
210-
self.private_endpoint_connections = None
210+
# self.private_endpoint_connections = None
211211
self.private_link_count = None
212212
self.provision_network_now = provision_network_now
213213
self.provisioning_state = None

sdk/evaluation/azure-ai-evaluation/tests/conftest.py

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from logging import Logger
1010
from enum import Enum
1111
from pathlib import Path
12-
from typing import Any, Dict, Final, Optional
12+
from typing import Any, Dict, Final, Literal, Optional
1313
from unittest.mock import patch
1414

1515
import pytest
@@ -20,7 +20,7 @@
2020
add_header_regex_sanitizer,
2121
is_live,
2222
remove_batch_sanitizers,
23-
add_batch_sanitizers,
23+
add_remove_header_sanitizer,
2424
Sanitizer,
2525
)
2626
from devtools_testutils.config import PROXY_URL
@@ -44,7 +44,7 @@
4444
ZERO_GUID: Final[str] = "00000000-0000-0000-0000-000000000000"
4545

4646

47-
def pytest_configure(config):
47+
def pytest_configure(config: pytest.Config) -> None:
4848
# register Azure test markers to reduce spurious warnings on test runs
4949
config.addinivalue_line("markers", "azuretest: mark test as an Azure test.")
5050
config.addinivalue_line("markers", "localtest: mark test as a local test.")
@@ -196,9 +196,9 @@ def evalutation_run_sanitizer() -> None:
196196
add_body_key_sanitizer(json_path="$..userTenantId", value=ZERO_GUID)
197197
add_body_key_sanitizer(json_path="$..upn", value="Sanitized")
198198

199-
# remove the stainless retry header and read timeout since it is causing some unnecessary mismatches in recordings
200-
add_batch_sanitizers({Sanitizer.REMOVE_HEADER: [{"headers": "x-stainless-retry-count"}]})
201-
add_batch_sanitizers({Sanitizer.REMOVE_HEADER: [{"headers": "x-stainless-read-timeout"}]})
199+
# removes some stainless headers since they are causing some unnecessary mismatches in recordings
200+
stainless_headers = ["x-stainless-retry-count", "x-stainless-read-timeout"]
201+
add_remove_header_sanitizer(headers=",".join(stainless_headers))
202202

203203
azure_workspace_triad_sanitizer()
204204
azureopenai_connection_sanitizer()
@@ -210,7 +210,7 @@ def evalutation_run_sanitizer() -> None:
210210

211211

212212
@pytest.fixture
213-
def redirect_asyncio_requests_traffic() -> None:
213+
def redirect_asyncio_requests_traffic():
214214
"""Redirects requests sent through AsyncioRequestsTransport to the test proxy.
215215
216216
.. note::
@@ -394,20 +394,24 @@ def project_scope(request, dev_connections: Dict[str, Any]) -> dict:
394394

395395

396396
@pytest.fixture
397-
def datastore_project_scopes(connection_file, project_scope, mock_project_scope):
398-
conn_name = "azure_ai_entra_id_project_scope"
399-
if not is_live():
400-
entra_id = mock_project_scope
401-
else:
402-
entra_id = connection_file.get(conn_name)
403-
if not entra_id:
404-
raise ValueError(f"Connection '{conn_name}' not found in dev connections.")
397+
def datastore_project_scopes(connection_file, project_scope, mock_project_scope) -> Dict[str, Any]:
398+
keys = {"none": "azure_ai_entra_id_project_scope", "private": "azure_ai_private_connection_project_scope"}
405399

406-
return {
400+
scopes: Dict[str, Any] = {
407401
"sas": project_scope,
408-
"none": entra_id,
409402
}
410403

404+
if not is_live():
405+
for key in keys.keys():
406+
scopes[key] = mock_project_scope
407+
else:
408+
for key, value in keys.items():
409+
if value not in connection_file:
410+
raise ValueError(f"Connection '{value}' not found in dev connections.")
411+
scopes[key] = connection_file[value]["value"]
412+
413+
return scopes
414+
411415

412416
@pytest.fixture
413417
def mock_trace_destination_to_cloud(project_scope: dict):
@@ -470,14 +474,14 @@ def __init__(self, group=None, target=None, *args, **kwargs):
470474
@pytest.fixture
471475
def recording_injection(mocker: MockerFixture):
472476
original_process_class = multiprocessing.get_context("spawn").Process
473-
multiprocessing.get_context("spawn").Process = MockSpawnProcess
477+
multiprocessing.get_context("spawn").Process = MockSpawnProcess # type: ignore
474478
if "spawn" == multiprocessing.get_start_method():
475479
multiprocessing.Process = MockSpawnProcess
476480

477481
try:
478482
yield
479483
finally:
480-
multiprocessing.get_context("spawn").Process = original_process_class
484+
multiprocessing.get_context("spawn").Process = original_process_class # type: ignore
481485
if "spawn" == multiprocessing.get_start_method():
482486
multiprocessing.Process = original_process_class
483487

@@ -490,14 +494,12 @@ def _mock_create_spawned_fork_process_manager(*args, **kwargs):
490494
return create_spawned_fork_process_manager(*args, **kwargs)
491495

492496

493-
def package_scope_in_live_mode() -> str:
497+
def package_scope_in_live_mode() -> Literal["package", "function"]:
494498
"""Determine the scope of some expected sharing fixtures.
495-
496499
We have many tests against flows and runs, and it's very time consuming to create a new flow/run
497500
for each test. So we expect to leverage pytest fixture concept to share flows/runs across tests.
498501
However, we also have replay tests, which require function scope fixture as it will locate the
499502
recording YAML based on the test function info.
500-
501503
Use this function to determine the scope of the fixtures dynamically. For those fixtures that
502504
will request dynamic scope fixture(s), they also need to be dynamic scope.
503505
"""
@@ -601,6 +603,7 @@ def stop_promptflow_service() -> None:
601603

602604
stop_promptflow_service()
603605

606+
604607
@pytest.fixture
605608
def run_from_temp_dir(tmp_path):
606609
original_cwd = os.getcwd()

sdk/evaluation/azure-ai-evaluation/tests/e2etests/test_lite_management_client.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from typing import Any, Mapping
12
import pytest
23
import logging
34
from azure.core.credentials import AzureSasCredential, TokenCredential
@@ -66,7 +67,12 @@ def test_workspace_get_default_store(
6667
assert store.credential == None
6768

6869
@pytest.mark.azuretest
69-
def test_workspace_get_info(self, project_scope, azure_cred):
70+
@pytest.mark.parametrize("config_name", ["sas", "none", "private"])
71+
def test_workspace_get_info(
72+
self, datastore_project_scopes: Mapping[str, Any], azure_cred: TokenCredential, config_name: str
73+
):
74+
project_scope = datastore_project_scopes[config_name]
75+
7076
client = LiteMLClient(
7177
subscription_id=project_scope["subscription_id"],
7278
resource_group=project_scope["resource_group_name"],

0 commit comments

Comments
 (0)