99from logging import Logger
1010from enum import Enum
1111from pathlib import Path
12- from typing import Any , Dict , Final , Optional
12+ from typing import Any , Dict , Final , Literal , Optional
1313from unittest .mock import patch
1414
1515import pytest
2020 add_header_regex_sanitizer ,
2121 is_live ,
2222 remove_batch_sanitizers ,
23- add_batch_sanitizers ,
23+ add_remove_header_sanitizer ,
2424 Sanitizer ,
2525)
2626from devtools_testutils .config import PROXY_URL
4444ZERO_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
413417def mock_trace_destination_to_cloud (project_scope : dict ):
@@ -470,14 +474,14 @@ def __init__(self, group=None, target=None, *args, **kwargs):
470474@pytest .fixture
471475def 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
605608def run_from_temp_dir (tmp_path ):
606609 original_cwd = os .getcwd ()
0 commit comments