diff --git a/src/cls/IPM/Lifecycle/Base.cls b/src/cls/IPM/Lifecycle/Base.cls index 5b390b7c..f8e35b57 100644 --- a/src/cls/IPM/Lifecycle/Base.cls +++ b/src/cls/IPM/Lifecycle/Base.cls @@ -714,7 +714,7 @@ Method InstallPythonRequirements(pRoot As %String = "", ByRef pParams) Quit tSC } -Method ResolvePipCaller(ByRef pParams) As %List +ClassMethod ResolvePipCaller(ByRef pParams) As %List { Set tUseStandalonePip = ##class(%IPM.Repo.UniversalSettings).GetValue("UseStandalonePip") Set tPipCaller = ##class(%IPM.Repo.UniversalSettings).GetValue("PipCaller") @@ -734,7 +734,7 @@ Method ResolvePipCaller(ByRef pParams) As %List Return ..DetectPipCaller(tUseStandalonePip, $Get(pParams("Verbose"), 0)) } -Method DetectPipCaller(pUseStandalonePip As %Boolean, pVerbose As %Boolean = 0) As %List +ClassMethod DetectPipCaller(pUseStandalonePip As %Boolean, pVerbose As %Boolean = 0) As %List { If pVerbose { Write !,"Detecting pip caller" diff --git a/tests/integration_tests/Test/PM/Integration/PythonWheel.cls b/tests/integration_tests/Test/PM/Integration/PythonWheel.cls new file mode 100644 index 00000000..34a58dcb --- /dev/null +++ b/tests/integration_tests/Test/PM/Integration/PythonWheel.cls @@ -0,0 +1,102 @@ +Class Test.PM.Integration.PythonWheel Extends Test.PM.Integration.Base +{ + +/// A reference to Python's sys.path +Property PythonPath As %SYS.Python; + +/// A copy of python list containing the original sys.path +Property PythonPathCopy As %SYS.Python; + +/// Run by RunTest once after all test methods in the test class are run. Can be used to tear down a test environment that was set up by OnBeforeAllTests See example in OnBeforeAllTests. +Method OnAfterAllTests() As %Status +{ + Set copy = ##class(%SYS.Python).Import("copy") + Set PythonPath = copy.deepcopy(..PythonPathCopy) + Quit $$$OK +} + +/// Run by RunTest once before any test methods in the test class are run. Can be used to set up a +/// test environment that will be later cleaned up by OnAfterAllTests. +///
NOTE: OnBeforeAllTests does not currently support skipping tests. Calls to $$$AssertSkipped in +/// OnBeforeAllTests may result in tests appearing to pass rather than being skipped. +///

Example: Setup and Cleanup of an environment: +///
+/// Method OnBeforeAllTests() As %Status
+/// {
+/// 	//do setup stuff here
+///  	set ^inputMessage = "input message"
+/// 	quit $$$OK
+/// }
+/// Method OnAfterAllTests() As %Status
+/// {
+/// 	//do clean up stuff here
+/// 	kill ^inputMessage
+/// 	quit $$$OK
+/// }
+/// +Method OnBeforeAllTests() As %Status +{ + Set sys = ##class(%SYS.Python).Import("sys") + Set ..PythonPath = sys.path + + Set copy = ##class(%SYS.Python).Import("copy") + Set ..PythonPathCopy = copy.deepcopy(sys.path) + + Quit $$$OK +} + +Method TestPythonWheel() +{ + Set package = "oras" + Set outputDirectory = $$$FileTempDir + Set bundleName = "my-oras-bundle" + Set bundleVersion = "0.1.0" + + // Export all dependencies of ORAS along with ORAS itself + Set deps = ##class(%IPM.Utils.EmbeddedPython).ListDependencies(package, 1, 1) + Do ##class(%IPM.Utils.EmbeddedPython).BundleWheel(deps, outputDirectory, bundleName, bundleVersion) + + // There should be one and only one file - the wheel + set rs = ##class(%File).FileSetFunc(outputDirectory) + Do $$$AssertTrue(rs.%Next()) + Do $$$AssertEquals(rs.Type, "F") + Set wheelPath = rs.Name + Do $$$AssertNotTrue(rs.%Next()) + + // Try install the wheel to another directory + Set pipCaller = ##class(%IPM.Lifecycle.Base).ResolvePipCaller() + // Create a temporary directory for installing the wheel to + Set targetInstallDir = $$$FileTempDir + Set command = pipCaller _ $ListBuild("install", wheelPath, "-t", targetInstallDir) + Set tSC = ##class(%IPM.Utils.Module).RunCommand(, command, .stdout) + Do $$$AssertStatusOK(tSC, "Successfully installed the wheel") + + // Exclude mgr/python from sys.path and include targetInstallDir to check if the installed wheel works + Set mgrPython = ##class(%File).NormalizeDirectory("python", ##class(%File).ManagerDirectory()) + Set mgrPython = $Extract(mgrPython, 1, *-1) // Remove trailing slash + Do ..PythonPath.remove(mgrPython) + Do ..PythonPath.append(targetInstallDir) + Try { + // At this point, oras is probably already in sys.modules cache + // because it was used in OrasTag test (which is alphabetically before this test) + // but if it's not, we import it here so that we can use importlib.reload() with updated sys.path + Set oras = ##class(%SYS.Python).Import("oras") + Set importlib = ##class(%SYS.Python).Import("importlib") + Set oras = importlib.reload(oras) + + Do $$$AssertTrue(oras."__file__" [ targetInstallDir, "oras is imported from the installed wheel") + + // revert oras back to the original one + Do ..PythonPath.remove(targetInstallDir) + Do ..PythonPath.append(mgrPython) + Set oras = importlib.reload(oras) + } Catch ex { + Do $$$AssertFailure("Failed to import oras: "_ex.AsStatus()) + } + + // Clean up temporary directories + Do ##class(%File).RemoveDirectoryTree(outputDirectory) + Do ##class(%File).RemoveDirectoryTree(targetInstallDir) +} + +}