@@ -22,8 +22,25 @@ function Get-PythonPath {
2222 [string ]$RepoRoot
2323 )
2424
25- # Use Validation module if available
26- $useValidation = Get-Command Test-ValidPath - ErrorAction SilentlyContinue
25+ # Use Validation module if available. Probe with the core-qualified Get-Command so unit
26+ # tests that Mock Get-Command (-ModuleName Python) cannot flip this to a false positive,
27+ # and invoke Test-ValidPath through a guarded helper that falls back to Test-Path when the
28+ # Validation module was unloaded by an earlier test in the same shard (prevents
29+ # "Test-ValidPath is not recognized").
30+ $useValidation = $null -ne (Microsoft.PowerShell.Core\Get-Command - Name ' Test-ValidPath' - ErrorAction SilentlyContinue)
31+ $testPathValidated = {
32+ param ([string ]$Path , [string ]$PathType = ' Any' )
33+ if (-not $Path -or [string ]::IsNullOrWhiteSpace($Path )) { return $false }
34+ if ($useValidation ) {
35+ try {
36+ return [bool ](Test-ValidPath - Path $Path - PathType $PathType )
37+ }
38+ catch {
39+ # Validation helper vanished mid-shard; fall through to Test-Path.
40+ }
41+ }
42+ return [bool ](Test-Path - LiteralPath $Path )
43+ }
2744
2845 # First, check common Python-related environment variables (highest priority)
2946 $pythonEnvVars = @ (' PYTHON_HOME' , ' PYTHON_ROOT' , ' PYTHON' , ' VIRTUAL_ENV' , ' CONDA_PREFIX' )
@@ -45,12 +62,7 @@ function Get-PythonPath {
4562 else {
4663 Join-Path $envValue ' bin' ' python'
4764 }
48- $pythonExists = if ($useValidation ) {
49- Test-ValidPath - Path $pythonExe - PathType File
50- }
51- else {
52- $pythonExe -and -not [string ]::IsNullOrWhiteSpace($pythonExe ) -and (Test-Path - LiteralPath $pythonExe )
53- }
65+ $pythonExists = & $testPathValidated - Path $pythonExe - PathType File
5466 if ($pythonExists ) {
5567 $debugLevel = 0
5668 if ($env: PS_PROFILE_DEBUG -and [int ]::TryParse($env: PS_PROFILE_DEBUG , [ref ]$debugLevel ) -and $debugLevel -ge 3 ) {
@@ -62,12 +74,7 @@ function Get-PythonPath {
6274 # For PYTHON_HOME, PYTHON_ROOT, PYTHON - these might point directly to Python or its directory
6375 elseif ($envVar -eq ' PYTHON' ) {
6476 # PYTHON might be a direct path to Python executable
65- $pythonExists = if ($useValidation ) {
66- Test-ValidPath - Path $envValue - PathType File
67- }
68- else {
69- $envValue -and -not [string ]::IsNullOrWhiteSpace($envValue ) -and (Test-Path - LiteralPath $envValue )
70- }
77+ $pythonExists = & $testPathValidated - Path $envValue - PathType File
7178 if ($pythonExists ) {
7279 $debugLevel = 0
7380 if ($env: PS_PROFILE_DEBUG -and [int ]::TryParse($env: PS_PROFILE_DEBUG , [ref ]$debugLevel ) -and $debugLevel -ge 3 ) {
@@ -84,12 +91,7 @@ function Get-PythonPath {
8491 else {
8592 Join-Path $envValue ' python'
8693 }
87- $pythonExists = if ($useValidation ) {
88- Test-ValidPath - Path $pythonExe - PathType File
89- }
90- else {
91- $pythonExe -and -not [string ]::IsNullOrWhiteSpace($pythonExe ) -and (Test-Path - LiteralPath $pythonExe )
92- }
94+ $pythonExists = & $testPathValidated - Path $pythonExe - PathType File
9395 if ($pythonExists ) {
9496 return $pythonExe
9597 }
@@ -100,12 +102,7 @@ function Get-PythonPath {
100102 else {
101103 Join-Path $envValue ' bin' ' python'
102104 }
103- $pythonExists = if ($useValidation ) {
104- Test-ValidPath - Path $pythonExe - PathType File
105- }
106- else {
107- $pythonExe -and -not [string ]::IsNullOrWhiteSpace($pythonExe ) -and (Test-Path - LiteralPath $pythonExe )
108- }
105+ $pythonExists = & $testPathValidated - Path $pythonExe - PathType File
109106 if ($pythonExists ) {
110107 $debugLevel = 0
111108 if ($env: PS_PROFILE_DEBUG -and [int ]::TryParse($env: PS_PROFILE_DEBUG , [ref ]$debugLevel ) -and $debugLevel -ge 3 ) {
@@ -147,22 +144,12 @@ function Get-PythonPath {
147144
148145 if ($RepoRoot ) {
149146 $venvPath = Join-Path $RepoRoot ' .venv'
150- $venvExists = if ($useValidation ) {
151- Test-ValidPath - Path $venvPath - PathType Directory
152- }
153- else {
154- $venvPath -and -not [string ]::IsNullOrWhiteSpace($venvPath ) -and (Test-Path - LiteralPath $venvPath )
155- }
147+ $venvExists = & $testPathValidated - Path $venvPath - PathType Directory
156148
157149 if ($venvExists ) {
158150 # Try Windows path first
159151 $venvPythonPath = Join-Path $venvPath ' Scripts' ' python.exe'
160- $pythonExists = if ($useValidation ) {
161- Test-ValidPath - Path $venvPythonPath - PathType File
162- }
163- else {
164- $venvPythonPath -and -not [string ]::IsNullOrWhiteSpace($venvPythonPath ) -and (Test-Path - LiteralPath $venvPythonPath )
165- }
152+ $pythonExists = & $testPathValidated - Path $venvPythonPath - PathType File
166153 if ($pythonExists ) {
167154 $debugLevel = 0
168155 if ($env: PS_PROFILE_DEBUG -and [int ]::TryParse($env: PS_PROFILE_DEBUG , [ref ]$debugLevel ) -and $debugLevel -ge 2 ) {
@@ -172,12 +159,7 @@ function Get-PythonPath {
172159 }
173160 # Try Unix-style path
174161 $venvPythonPath = Join-Path $venvPath ' bin' ' python'
175- $pythonExists = if ($useValidation ) {
176- Test-ValidPath - Path $venvPythonPath - PathType File
177- }
178- else {
179- $venvPythonPath -and -not [string ]::IsNullOrWhiteSpace($venvPythonPath ) -and (Test-Path - LiteralPath $venvPythonPath )
180- }
162+ $pythonExists = & $testPathValidated - Path $venvPythonPath - PathType File
181163 if ($pythonExists ) {
182164 $debugLevel = 0
183165 if ($env: PS_PROFILE_DEBUG -and [int ]::TryParse($env: PS_PROFILE_DEBUG , [ref ]$debugLevel ) -and $debugLevel -ge 2 ) {
@@ -295,18 +277,24 @@ function Invoke-PythonScript {
295277 [string ]$RepoRoot
296278 )
297279
298- # Validate script path exists
299- # Use Validation module if available
300- if (Get-Command Test-ValidPath - ErrorAction SilentlyContinue) {
301- if (-not (Test-ValidPath - Path $ScriptPath - PathType File)) {
302- throw " Python script not found: $ScriptPath "
280+ # Validate script path exists. Probe with the core-qualified Get-Command so a mocked
281+ # Get-Command cannot claim Test-ValidPath is present when the Validation module was
282+ # unloaded by an earlier test in the shard, and guard the call so it never throws
283+ # "Test-ValidPath is not recognized".
284+ $scriptPathValid = $false
285+ if ($null -ne (Microsoft.PowerShell.Core\Get-Command - Name ' Test-ValidPath' - ErrorAction SilentlyContinue)) {
286+ try {
287+ $scriptPathValid = [bool ](Test-ValidPath - Path $ScriptPath - PathType File)
288+ }
289+ catch {
290+ $scriptPathValid = ($ScriptPath -and -not [string ]::IsNullOrWhiteSpace($ScriptPath ) -and (Test-Path - LiteralPath $ScriptPath - ErrorAction SilentlyContinue))
303291 }
304292 }
305293 else {
306- # Fallback to manual validation
307- if ( -not ( $ScriptPath -and -not [ string ]::IsNullOrWhiteSpace( $ScriptPath ) -and ( Test-Path - LiteralPath $ScriptPath - ErrorAction SilentlyContinue))) {
308- throw " Python script not found: $ScriptPath "
309- }
294+ $scriptPathValid = ( $ScriptPath -and -not [ string ]::IsNullOrWhiteSpace( $ScriptPath ) -and ( Test-Path - LiteralPath $ScriptPath - ErrorAction SilentlyContinue))
295+ }
296+ if ( - not $scriptPathValid ) {
297+ throw " Python script not found: $ScriptPath "
310298 }
311299
312300 # Validate script is readable
0 commit comments