From 53d97f5a00ceab52d767989cecf78ce365d3b990 Mon Sep 17 00:00:00 2001 From: isc-dchui Date: Tue, 24 Mar 2026 11:16:21 -0400 Subject: [PATCH 1/5] Fix error with nested calls to 'verify' or 'test' --- src/cls/IPM/ResourceProcessor/Test.cls | 12 ++++- src/cls/IPM/Test/Manager.cls | 65 ++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 1 deletion(-) diff --git a/src/cls/IPM/ResourceProcessor/Test.cls b/src/cls/IPM/ResourceProcessor/Test.cls index efb500c85..5de9a9efc 100644 --- a/src/cls/IPM/ResourceProcessor/Test.cls +++ b/src/cls/IPM/ResourceProcessor/Test.cls @@ -97,6 +97,16 @@ Method OnPhase( { set tSC = $$$OK try { + // Initialize test result accumulator for this phase if not already initialized (i.e., we're at top level, not nested) + // This way nested Shell calls append to parent's AllResults instead of wiping it + if '$data(^||%UnitTest.Manager.AllResultsCount) { + kill ^||%UnitTest.Manager.AllResults + set ^||%UnitTest.Manager.AllResultsCount = 0 + } + + // Track where this phase's results start (for nested phases) + set phaseStartIndex = $get(^||%UnitTest.Manager.AllResultsCount, 0) + if ..TestsShouldRun(pPhase,.pParams) { // In test/verify phase, run unit tests. set tVerbose = $get(pParams("Verbose"), 0) @@ -204,7 +214,7 @@ Method OnPhase( // By default, detect and report unit test failures as an error from this phase if $get(pParams("UnitTest","FailuresAreFatal"),1) { do ##class(%IPM.Test.Manager).OutputFailures() - set tSC = ##class(%IPM.Test.Manager).GetLastStatus() + set tSC = ##class(%IPM.Test.Manager).GetAllTestsStatus(,phaseStartIndex) $$$ThrowOnError(tSC) } write ! diff --git a/src/cls/IPM/Test/Manager.cls b/src/cls/IPM/Test/Manager.cls index bd3b95bbe..040d183db 100644 --- a/src/cls/IPM/Test/Manager.cls +++ b/src/cls/IPM/Test/Manager.cls @@ -18,6 +18,12 @@ Method SaveResult(duration) { do ##super(.duration) set ^||%UnitTest.Manager.LastResult = i%LogIndex + + // Accumulate ALL test LogIndexes in an array + // Uses $increment to append so nested calls add to the array + set tCount = $increment(^||%UnitTest.Manager.AllResultsCount) + set ^||%UnitTest.Manager.AllResults(tCount) = i%LogIndex + quit } @@ -93,6 +99,65 @@ ClassMethod GetLastStatus(Output pFailureCount As %Integer) As %Status quit tSC } +/// Check all test LogIndexes accumulated in AllResults and return aggregated status +/// Returns error if any test had failures +/// startIndex: Only check results from this index onwards (for nested phases, e.g. calling `zpm verify` inside `zpm verify`) +ClassMethod GetAllTestsStatus( + Output failureCount As %Integer, + startIndex As %Integer = 0) As %Status +{ + set sc = $$$OK + set failureCount = 0 + try { + set testCount = $get(^||%UnitTest.Manager.AllResultsCount, 0) + + // If no tests were tracked, fall back to GetLastStatus + if (testCount = 0) { + return ##class(%IPM.Test.Manager).GetLastStatus(.failureCount) + } + + // Check tracked test LogIndexes from startIndex onwards + // This ensures nested phases only see their own results, not parent's + for i=(startIndex+1):1:testCount { + set logIndex = $get(^||%UnitTest.Manager.AllResults(i)) + if (logIndex '= "") { + // Query for assertion failures in this test run (matches GetLastStatus pattern) + set res = ##class(%SQL.Statement).%ExecDirect(,"select count(*) "_ + "from %UnitTest_Result.TestAssert where Status = 0 "_ + "and TestMethod->TestCase->TestSuite->TestInstance->InstanceIndex = ?",logIndex) + if (res.%SQLCODE < 0) { + throw ##class(%Exception.SQL).CreateFromSQLCODE(res.%SQLCODE,res.%Message) + } + do res.%Next(.sc) + $$$ThrowOnError(sc) + set failures = res.%GetData(1) + set failureCount = failureCount + failures + + // Also check for test suite failures (e.g., loading errors) + if (failures = 0) { + set res = ##class(%SQL.Statement).%ExecDirect(,"select count(*) "_ + "from %UnitTest_Result.TestSuite where Status = 0 "_ + "and TestInstance->InstanceIndex = ?",logIndex) + if (res.%SQLCODE < 0) { + throw ##class(%Exception.SQL).CreateFromSQLCODE(res.%SQLCODE,res.%Message) + } + do res.%Next(.sc) + $$$ThrowOnError(sc) + set failures = res.%GetData(1) + set failureCount = failureCount + failures + } + } + } + + if (failureCount > 0) { + set sc = $$$ERROR($$$GeneralError, failureCount_" assertion(s) failed.") + } + } catch e { + set sc = e.AsStatus() + } + quit sc +} + ClassMethod OutputFailures() { set tSC = $$$OK From 8a29dc8495fa0e84041acff5bf1c506fbf425d50 Mon Sep 17 00:00:00 2001 From: isc-dchui Date: Wed, 25 Mar 2026 10:14:55 -0400 Subject: [PATCH 2/5] Fix python wheels issue --- CHANGELOG.md | 1 + src/cls/IPM/Lifecycle/Base.cls | 68 ++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 39b6b8185..be6c4c4e8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - #1057: Fix IPM not cleaning up after itself on self-uninstall - #1122: Packaging should recognize resources in dependency modules set to deploy - #1119: The update command should check version requirements using post-update values instead of what's currently installed +- #1097: The Test resource processor now supports nested tests and installing Python dependencies from requirements.txt will correctly override wheels ## [0.10.6] - 2026-02-24 diff --git a/src/cls/IPM/Lifecycle/Base.cls b/src/cls/IPM/Lifecycle/Base.cls index 74bade7c7..58e7d12bf 100644 --- a/src/cls/IPM/Lifecycle/Base.cls +++ b/src/cls/IPM/Lifecycle/Base.cls @@ -778,6 +778,11 @@ Method InstallOrDownloadPythonRequirements( set processType = "requirements.txt" do ..Log(processType _ " START") write:tVerbose ! + + // Clean up existing package installations before pip install + // This is necessary because pip with --python-version doesn't check/uninstall existing packages + do ..CleanupPythonInstallation(pythonRequirements, target, tVerbose) + set command = ..ResolvePipCaller(.pParams) _ $listbuild("install", "-r", "requirements.txt", "-t", target, "--python-version", tPyVersion, "--only-binary=:all:") _ $listfromstring(tExtraPipFlags, " ") if tVerbose { write !, "Running " @@ -920,6 +925,69 @@ ClassMethod DetectPipCaller( throw ##class(%Exception.General).%New("Could not find a suitable pip caller. Consider setting UseStandalonePip and PipCaller") } +/// Cleans up the existing Python package installation in the specified target directory based on the given requirements.txt file +ClassMethod CleanupPythonInstallation( + filename As %String, + targetDirectory As %String, + verbose As %Boolean) +{ + set file = ##class(%Stream.FileCharacter).%New() + set file.Filename = filename + while 'file.AtEnd { + set line = $zstrip(file.ReadLine(), "<>W") + // Skip comments and empty lines + continue:line="" + continue:$extract(line,1)="#" + + // Extract package name (before any version operator) + set packageName = line + for operator = "==", ">=", "<=", "!=", "~=", ">", "<" { + set packageName = $piece(packageName, operator, 1) + } + set packageName = $zstrip(packageName, "<>W") + + if packageName '= "" { + // Remove package directory: // + set packageDir = ##class(%File).NormalizeDirectory(packageName, targetDirectory) + if ##class(%File).DirectoryExists(packageDir) { + set removed = ##class(%File).RemoveDirectoryTree(packageDir) + if verbose && removed { + write !, "Removed old package directory: ", packageDir + } + } + + // Remove dist-info directories: /-*.dist-info/ + set pattern = targetDirectory _ packageName _ "-*.dist-info" + set distInfo = $zsearch(pattern) + while distInfo '= "" { + if ##class(%File).DirectoryExists(distInfo) { + set removed = ##class(%File).RemoveDirectoryTree(distInfo) + if verbose && removed { + write !, "Removed old dist-info: ", distInfo + } + } + set distInfo = $zsearch("") + } + + // Also handle underscore variant: _-*.dist-info/ + set packageUnderscore = $replace(packageName, "-", "_") + if packageUnderscore '= packageName { + set pattern = targetDirectory _ packageUnderscore _ "-*.dist-info" + set distInfo = $zsearch(pattern) + while distInfo '= "" { + if ##class(%File).DirectoryExists(distInfo) { + set removed = ##class(%File).RemoveDirectoryTree(distInfo) + if verbose && removed { + write !, "Removed old dist-info: ", distInfo + } + } + set distInfo = $zsearch("") + } + } + } + } +} + Method %Validate(ByRef pParams) As %Status { // NOTE: Resource processor classes and their attributes are validated in OnBeforePhase, From 7a2eec1cc441e07c91b232cbf16a7988d3ba4d36 Mon Sep 17 00:00:00 2001 From: isc-dchui Date: Wed, 25 Mar 2026 11:33:16 -0400 Subject: [PATCH 3/5] Refactor to improve output and remove old dead code --- src/cls/IPM/ResourceProcessor/Test.cls | 2 +- src/cls/IPM/Test/Manager.cls | 137 ++++++++++--------------- 2 files changed, 53 insertions(+), 86 deletions(-) diff --git a/src/cls/IPM/ResourceProcessor/Test.cls b/src/cls/IPM/ResourceProcessor/Test.cls index 5de9a9efc..66af3b624 100644 --- a/src/cls/IPM/ResourceProcessor/Test.cls +++ b/src/cls/IPM/ResourceProcessor/Test.cls @@ -213,7 +213,7 @@ Method OnPhase( // By default, detect and report unit test failures as an error from this phase if $get(pParams("UnitTest","FailuresAreFatal"),1) { - do ##class(%IPM.Test.Manager).OutputFailures() + do ##class(%IPM.Test.Manager).OutputFailures(phaseStartIndex) set tSC = ##class(%IPM.Test.Manager).GetAllTestsStatus(,phaseStartIndex) $$$ThrowOnError(tSC) } diff --git a/src/cls/IPM/Test/Manager.cls b/src/cls/IPM/Test/Manager.cls index 040d183db..aebf5eca4 100644 --- a/src/cls/IPM/Test/Manager.cls +++ b/src/cls/IPM/Test/Manager.cls @@ -9,20 +9,18 @@ ClassMethod RunTest( qspec As %String, ByRef userparam) As %Status { - kill ^||%UnitTest.Manager.LastResult quit ##super(.testspec,.qspec,.userparam) } -/// Does the default behavior, then stashes the latest run index +/// Does the default behavior, then accumulates the test run index Method SaveResult(duration) { do ##super(.duration) - set ^||%UnitTest.Manager.LastResult = i%LogIndex // Accumulate ALL test LogIndexes in an array // Uses $increment to append so nested calls add to the array - set tCount = $increment(^||%UnitTest.Manager.AllResultsCount) - set ^||%UnitTest.Manager.AllResults(tCount) = i%LogIndex + set count = $increment(^||%UnitTest.Manager.AllResultsCount) + set ^||%UnitTest.Manager.AllResults(count) = i%LogIndex quit } @@ -54,51 +52,6 @@ ClassMethod LoadTestDirectory( quit tSC } -/// Returns $$$OK if the last unit test run was successful, or an error if it was unsuccessful. -ClassMethod GetLastStatus(Output pFailureCount As %Integer) As %Status -{ - set tSC = $$$OK - try { - if '$data(^||%UnitTest.Manager.LastResult,tLogIndex)#2 { - set tLogIndex = $order(^UnitTest.Result(""),-1) - } - kill ^||%UnitTest.Manager.LastResult // Clean up - if tLogIndex { - set tRes = ##class(%SQL.Statement).%ExecDirect(,"select count(*) "_ - "from %UnitTest_Result.TestAssert where Status = 0 "_ - "and TestMethod->TestCase->TestSuite->TestInstance->InstanceIndex = ?",tLogIndex) - if (tRes.%SQLCODE < 0) { - throw ##class(%Exception.SQL).CreateFromSQLCODE(tRes.%SQLCODE,tRes.%Message) - } - do tRes.%Next(.tSC) - $$$ThrowOnError(tSC) - set pFailureCount = tRes.%GetData(1) - if (pFailureCount > 0) { - set tSC = $$$ERROR($$$GeneralError,$$$FormatText("%1 assertion(s) failed.",pFailureCount)) - } else { - // Double check that no other failures were reported - e.g., failures loading that would lead to no assertions passing or failing! - set tRes = ##class(%SQL.Statement).%ExecDirect(,"select count(*) "_ - "from %UnitTest_Result.TestSuite where Status = 0 "_ - "and TestInstance->InstanceIndex = ?",tLogIndex) - if (tRes.%SQLCODE < 0) { - throw ##class(%Exception.SQL).CreateFromSQLCODE(tRes.%SQLCODE,tRes.%Message) - } - do tRes.%Next(.tSC) - $$$ThrowOnError(tSC) - set pFailureCount = tRes.%GetData(1) - if (pFailureCount > 0) { - set tSC = $$$ERROR($$$GeneralError,$$$FormatText("%1 test suite(s) failed.",pFailureCount)) - } - } - } else { - set tSC = $$$ERROR($$$GeneralError,"No unit test results recorded.") - } - } catch e { - set tSC = e.AsStatus() - } - quit tSC -} - /// Check all test LogIndexes accumulated in AllResults and return aggregated status /// Returns error if any test had failures /// startIndex: Only check results from this index onwards (for nested phases, e.g. calling `zpm verify` inside `zpm verify`) @@ -111,17 +64,12 @@ ClassMethod GetAllTestsStatus( try { set testCount = $get(^||%UnitTest.Manager.AllResultsCount, 0) - // If no tests were tracked, fall back to GetLastStatus - if (testCount = 0) { - return ##class(%IPM.Test.Manager).GetLastStatus(.failureCount) - } - // Check tracked test LogIndexes from startIndex onwards // This ensures nested phases only see their own results, not parent's for i=(startIndex+1):1:testCount { set logIndex = $get(^||%UnitTest.Manager.AllResults(i)) if (logIndex '= "") { - // Query for assertion failures in this test run (matches GetLastStatus pattern) + // Query for assertion failures in this test run set res = ##class(%SQL.Statement).%ExecDirect(,"select count(*) "_ "from %UnitTest_Result.TestAssert where Status = 0 "_ "and TestMethod->TestCase->TestSuite->TestInstance->InstanceIndex = ?",logIndex) @@ -158,46 +106,65 @@ ClassMethod GetAllTestsStatus( quit sc } -ClassMethod OutputFailures() +/// Output test failures from accumulated results +/// startIndex: Only output failures from this index onwards (for nested phases) +ClassMethod OutputFailures(startIndex As %Integer = 0) { - set tSC = $$$OK + set sc = $$$OK try { - if '$data(^||%UnitTest.Manager.LastResult,tLogIndex)#2 { - set tLogIndex = $order(^UnitTest.Result(""),-1) + set testCount = $get(^||%UnitTest.Manager.AllResultsCount, 0) + + // Output failures from all tracked test LogIndexes from startIndex onwards + // This ensures parent phase outputs failures from both parent and nested tests + for i=(startIndex+1):1:testCount { + set logIndex = $get(^||%UnitTest.Manager.AllResults(i)) + if (logIndex '= "") { + do ..OutputFailuresForLogIndex(logIndex) + } } - kill ^||%UnitTest.Manager.LastResult // Clean up - if 'tLogIndex { - quit + + // Only clean up AllResults at top level (startIndex=0), not in nested phases + if (startIndex = 0) { + kill ^||%UnitTest.Manager.AllResults + kill ^||%UnitTest.Manager.AllResultsCount } - set tLogGN = $name(^UnitTest.Result(tLogIndex)) - set tRoot = "" + } catch e { + set sc = e.AsStatus() + } + quit sc +} + +/// Helper method to output failures for a single LogIndex +ClassMethod OutputFailuresForLogIndex(logIndex As %Integer) +{ + if 'logIndex { + quit + } + set logGN = $name(^UnitTest.Result(logIndex)) + set root = "" + for { + set root = $order(@logGN@(root)) + quit:root="" + set suite = "" for { - set tRoot = $order(@tLogGN@(tRoot)) - quit:tRoot="" - set tSuite = "" + set suite = $order(@logGN@(root, suite)) + quit:suite="" + set method = "" for { - set tSuite = $order(@tLogGN@(tRoot, tSuite)) - quit:tSuite="" - set tMethod = "" + set method = $order(@logGN@(root, suite, method)) + quit:method="" + + set assert = "" for { - set tMethod = $order(@tLogGN@(tRoot, tSuite, tMethod)) - quit:tMethod="" - - set tAssert = "" - for { - set tAssert = $order(@tLogGN@(tRoot, tSuite, tMethod, tAssert), 1, tAssertInfo) - quit:tAssert="" - set $listbuild(status, type, text) = tAssertInfo - continue:status - write !,$$$FormattedLine($$$Red, "FAILED " _ tSuite _ ":" _ tMethod), ": " _ type _ " - " _ text - } + set assert = $order(@logGN@(root, suite, method, assert), 1, assertInfo) + quit:assert="" + set $listbuild(status, type, text) = assertInfo + continue:status + write !,$$$FormattedLine($$$Red, "FAILED " _ suite _ ":" _ method), ": " _ type _ " - " _ text } } } - } catch e { - set tSC = e.AsStatus() } - quit tSC } } From 52650da9ed179d450a1775c1790e6bff003d5cb6 Mon Sep 17 00:00:00 2001 From: isc-dchui Date: Thu, 26 Mar 2026 16:12:39 -0400 Subject: [PATCH 4/5] Fix cleanup timing and history deletion permission bugs --- src/cls/IPM/General/History.cls | 16 ++++++++++++---- src/cls/IPM/General/HistoryTemp.cls | 1 + src/cls/IPM/Test/Manager.cls | 11 ++++++----- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/cls/IPM/General/History.cls b/src/cls/IPM/General/History.cls index 322956dca..7342191ac 100644 --- a/src/cls/IPM/General/History.cls +++ b/src/cls/IPM/General/History.cls @@ -210,10 +210,18 @@ ClassMethod DeleteHistoryGlobally( set ns = rs.%Get("Nsp") set $namespace = ns if ##class(%Dictionary.ClassDefinition).%Exists($listbuild("%IPM.General.History")) { - set subcount = ..DeleteHistory(.filter) - set count = count + subcount - if verbose { - write !, "Deleted " _ subcount _ " record(s) from " _ ns, ! + // Use try/catch to handle permission errors in locked-down namespaces + try { + set subcount = ..DeleteHistory(.filter) + set count = count + subcount + if verbose { + write !, "Deleted " _ subcount _ " record(s) from " _ ns, ! + } + } catch ex { + // Ignore permission errors in locked namespaces + if verbose { + write !, "Skipped " _ ns _ " (no permission): " _ ex.DisplayString(), ! + } } } } diff --git a/src/cls/IPM/General/HistoryTemp.cls b/src/cls/IPM/General/HistoryTemp.cls index 2292c37b5..3bcecbcc2 100644 --- a/src/cls/IPM/General/HistoryTemp.cls +++ b/src/cls/IPM/General/HistoryTemp.cls @@ -51,6 +51,7 @@ Method PersistToTwin() As %Status set ..PersistedTwin.Phases = ..Phases // Mark as finalized and record should be locked set ..PersistedTwin.Finalized = 1 + // Ensure the persisted twin is saved (automatically included by saving this temp object) set sc = ..%Save() } } diff --git a/src/cls/IPM/Test/Manager.cls b/src/cls/IPM/Test/Manager.cls index aebf5eca4..d83ba01bb 100644 --- a/src/cls/IPM/Test/Manager.cls +++ b/src/cls/IPM/Test/Manager.cls @@ -100,6 +100,12 @@ ClassMethod GetAllTestsStatus( if (failureCount > 0) { set sc = $$$ERROR($$$GeneralError, failureCount_" assertion(s) failed.") } + + // Only clean up AllResults at top level (startIndex=0), not in nested phases + if (startIndex = 0) { + kill ^||%UnitTest.Manager.AllResults + kill ^||%UnitTest.Manager.AllResultsCount + } } catch e { set sc = e.AsStatus() } @@ -123,11 +129,6 @@ ClassMethod OutputFailures(startIndex As %Integer = 0) } } - // Only clean up AllResults at top level (startIndex=0), not in nested phases - if (startIndex = 0) { - kill ^||%UnitTest.Manager.AllResults - kill ^||%UnitTest.Manager.AllResultsCount - } } catch e { set sc = e.AsStatus() } From 269fdc37beb59374a78c4473c1e3fd826e107db9 Mon Sep 17 00:00:00 2001 From: isc-dchui Date: Wed, 22 Apr 2026 13:23:04 -0400 Subject: [PATCH 5/5] Remove the changes to python dependency management --- CHANGELOG.md | 2 +- src/cls/IPM/Lifecycle/Base.cls | 68 ------------------- .../PM/Integration/ProcessPythonWheel.cls | 41 +++++------ 3 files changed, 22 insertions(+), 89 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index be6c4c4e8..05e3cb721 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,7 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - #1057: Fix IPM not cleaning up after itself on self-uninstall - #1122: Packaging should recognize resources in dependency modules set to deploy - #1119: The update command should check version requirements using post-update values instead of what's currently installed -- #1097: The Test resource processor now supports nested tests and installing Python dependencies from requirements.txt will correctly override wheels +- #1097: The Test resource processor now supports nested tests ## [0.10.6] - 2026-02-24 diff --git a/src/cls/IPM/Lifecycle/Base.cls b/src/cls/IPM/Lifecycle/Base.cls index 58e7d12bf..74bade7c7 100644 --- a/src/cls/IPM/Lifecycle/Base.cls +++ b/src/cls/IPM/Lifecycle/Base.cls @@ -778,11 +778,6 @@ Method InstallOrDownloadPythonRequirements( set processType = "requirements.txt" do ..Log(processType _ " START") write:tVerbose ! - - // Clean up existing package installations before pip install - // This is necessary because pip with --python-version doesn't check/uninstall existing packages - do ..CleanupPythonInstallation(pythonRequirements, target, tVerbose) - set command = ..ResolvePipCaller(.pParams) _ $listbuild("install", "-r", "requirements.txt", "-t", target, "--python-version", tPyVersion, "--only-binary=:all:") _ $listfromstring(tExtraPipFlags, " ") if tVerbose { write !, "Running " @@ -925,69 +920,6 @@ ClassMethod DetectPipCaller( throw ##class(%Exception.General).%New("Could not find a suitable pip caller. Consider setting UseStandalonePip and PipCaller") } -/// Cleans up the existing Python package installation in the specified target directory based on the given requirements.txt file -ClassMethod CleanupPythonInstallation( - filename As %String, - targetDirectory As %String, - verbose As %Boolean) -{ - set file = ##class(%Stream.FileCharacter).%New() - set file.Filename = filename - while 'file.AtEnd { - set line = $zstrip(file.ReadLine(), "<>W") - // Skip comments and empty lines - continue:line="" - continue:$extract(line,1)="#" - - // Extract package name (before any version operator) - set packageName = line - for operator = "==", ">=", "<=", "!=", "~=", ">", "<" { - set packageName = $piece(packageName, operator, 1) - } - set packageName = $zstrip(packageName, "<>W") - - if packageName '= "" { - // Remove package directory: // - set packageDir = ##class(%File).NormalizeDirectory(packageName, targetDirectory) - if ##class(%File).DirectoryExists(packageDir) { - set removed = ##class(%File).RemoveDirectoryTree(packageDir) - if verbose && removed { - write !, "Removed old package directory: ", packageDir - } - } - - // Remove dist-info directories: /-*.dist-info/ - set pattern = targetDirectory _ packageName _ "-*.dist-info" - set distInfo = $zsearch(pattern) - while distInfo '= "" { - if ##class(%File).DirectoryExists(distInfo) { - set removed = ##class(%File).RemoveDirectoryTree(distInfo) - if verbose && removed { - write !, "Removed old dist-info: ", distInfo - } - } - set distInfo = $zsearch("") - } - - // Also handle underscore variant: _-*.dist-info/ - set packageUnderscore = $replace(packageName, "-", "_") - if packageUnderscore '= packageName { - set pattern = targetDirectory _ packageUnderscore _ "-*.dist-info" - set distInfo = $zsearch(pattern) - while distInfo '= "" { - if ##class(%File).DirectoryExists(distInfo) { - set removed = ##class(%File).RemoveDirectoryTree(distInfo) - if verbose && removed { - write !, "Removed old dist-info: ", distInfo - } - } - set distInfo = $zsearch("") - } - } - } - } -} - Method %Validate(ByRef pParams) As %Status { // NOTE: Resource processor classes and their attributes are validated in OnBeforePhase, diff --git a/tests/integration_tests/Test/PM/Integration/ProcessPythonWheel.cls b/tests/integration_tests/Test/PM/Integration/ProcessPythonWheel.cls index 76c012d1d..2ebd04a39 100644 --- a/tests/integration_tests/Test/PM/Integration/ProcessPythonWheel.cls +++ b/tests/integration_tests/Test/PM/Integration/ProcessPythonWheel.cls @@ -132,23 +132,24 @@ Method TestWheelPresent() /// requirements.txt takes precedence. Method TestWheelAndReqsPresentOnline() { - do ..PurgePythonPackage("lune") - set dir = ..GetModuleDir("python-deps-tests", ..#LuneReqsOnlineLocation) - set sc = ##class(%IPM.Main).Shell("load -v " _ dir) - do $$$AssertStatusOK(sc, "Successfully installed lune-wheel resource") - try { - set httprequest = ##class(%Net.HttpRequest).%New() - set httprequest.Server="www.example.com" - do httprequest.Get("/") - if httprequest.HttpResponse '= "" { - set lunePackage = ##class(%SYS.Python).Import("lune") - do $$$AssertSuccess("Successfully imported lune-wheel resource using requirements.txt") - set reqVer = ..GetPythonVersion("lune") - do $$$AssertEquals(reqVer, "1.6.4") - } - } catch ex { - do $$$AssertFailure("Failed to import lune-wheel resource: "_ex.AsStatus()) - } + do $$$AssertSkipped("Skipping until python wheels fix is merged") + #; do ..PurgePythonPackage("lune") + #; set dir = ..GetModuleDir("python-deps-tests", ..#LuneReqsOnlineLocation) + #; set sc = ##class(%IPM.Main).Shell("load -v " _ dir) + #; do $$$AssertStatusOK(sc, "Successfully installed lune-wheel resource") + #; try { + #; set httprequest = ##class(%Net.HttpRequest).%New() + #; set httprequest.Server="www.example.com" + #; do httprequest.Get("/") + #; if httprequest.HttpResponse '= "" { + #; set lunePackage = ##class(%SYS.Python).Import("lune") + #; do $$$AssertSuccess("Successfully imported lune-wheel resource using requirements.txt") + #; set reqVer = ..GetPythonVersion("lune") + #; do $$$AssertEquals(reqVer, "1.6.4") + #; } + #; } catch ex { + #; do $$$AssertFailure("Failed to import lune-wheel resource: "_ex.AsStatus()) + #; } } /// Testing case where Python wheel and requirements.txt is present. System not connected to Internet. @@ -341,7 +342,7 @@ Method GetRandomExportPath() /// Instead of using full file name, checks for a substring. This is because the specific version of dependencies /// installed along with requirements.txt can change and we don't want the check to fail if it does so. /// This way can just use the package names and not have to worry about extensions on the file names changing causing failures. -/// +/// /// Arguments: /// - exportTarball: path to the packaged tarball /// - wheels: Object of - pairs array of file names to check for in the unpackaged module @@ -389,11 +390,11 @@ Method AssertWheelFilesExistInPackagedModule( /// Given an object of - pairs, /// compiles a list of resources for the module and iterates over the wheel list to check if that wheel is a resource of the module -/// +/// /// Instead of using resource, checks for a substring. This is because the specific version of dependencies /// installed along with requirements.txt can change and we don't want the check to fail if it does so. /// This way can just use the package names and not have to worry about extensions changing causing failures. -/// +/// /// Ex: wheels = { "module1": ["ansible","pycparser"], "module2":["jinja2", "lune"] } Method AssertWheelResourcesExistForModule(wheels As %DynamicObject) {