Skip to content

Commit ce35e4d

Browse files
committed
test: add an integration test for exporting and importing Python wheels
1 parent 7c44bf7 commit ce35e4d

File tree

2 files changed

+104
-2
lines changed

2 files changed

+104
-2
lines changed

src/cls/IPM/Lifecycle/Base.cls

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -714,7 +714,7 @@ Method InstallPythonRequirements(pRoot As %String = "", ByRef pParams)
714714
Quit tSC
715715
}
716716

717-
Method ResolvePipCaller(ByRef pParams) As %List
717+
ClassMethod ResolvePipCaller(ByRef pParams) As %List
718718
{
719719
Set tUseStandalonePip = ##class(%IPM.Repo.UniversalSettings).GetValue("UseStandalonePip")
720720
Set tPipCaller = ##class(%IPM.Repo.UniversalSettings).GetValue("PipCaller")
@@ -734,7 +734,7 @@ Method ResolvePipCaller(ByRef pParams) As %List
734734
Return ..DetectPipCaller(tUseStandalonePip, $Get(pParams("Verbose"), 0))
735735
}
736736

737-
Method DetectPipCaller(pUseStandalonePip As %Boolean, pVerbose As %Boolean = 0) As %List
737+
ClassMethod DetectPipCaller(pUseStandalonePip As %Boolean, pVerbose As %Boolean = 0) As %List
738738
{
739739
If pVerbose {
740740
Write !,"Detecting pip caller"
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
Class Test.PM.Integration.PythonWheel Extends Test.PM.Integration.Base
2+
{
3+
4+
/// A reference to Python's sys.path
5+
Property PythonPath As %SYS.Python;
6+
7+
/// A copy of python list containing the original sys.path
8+
Property PythonPathCopy As %SYS.Python;
9+
10+
/// Run by <B>RunTest</B> 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 <B>OnBeforeAllTests</B> See example in <b>OnBeforeAllTests</b>.
11+
Method OnAfterAllTests() As %Status
12+
{
13+
Set copy = ##class(%SYS.Python).Import("copy")
14+
Set PythonPath = copy.deepcopy(..PythonPathCopy)
15+
Quit $$$OK
16+
}
17+
18+
/// Run by <B>RunTest</B> once <a href="#OnBeforeAll">before any test methods</a> in the test class are run. Can be used to set up a
19+
/// test environment that will be later cleaned up by <B>OnAfterAllTests</B>.
20+
/// <br>NOTE: OnBeforeAllTests does not currently support skipping tests. Calls to $$$AssertSkipped in
21+
/// OnBeforeAllTests may result in tests appearing to pass rather than being skipped.
22+
/// <br><br>Example: Setup and Cleanup of an environment:
23+
/// <pre>
24+
/// Method OnBeforeAllTests() As %Status
25+
/// {
26+
/// //do setup stuff here
27+
/// set ^inputMessage = "input message"
28+
/// quit $$$OK
29+
/// }
30+
/// Method OnAfterAllTests() As %Status
31+
/// {
32+
/// //do clean up stuff here
33+
/// kill ^inputMessage
34+
/// quit $$$OK
35+
/// }</pre>
36+
///
37+
Method OnBeforeAllTests() As %Status
38+
{
39+
Set sys = ##class(%SYS.Python).Import("sys")
40+
Set ..PythonPath = sys.path
41+
42+
Set copy = ##class(%SYS.Python).Import("copy")
43+
Set ..PythonPathCopy = copy.deepcopy(sys.path)
44+
45+
Quit $$$OK
46+
}
47+
48+
Method TestPythonWheel()
49+
{
50+
Set package = "oras"
51+
Set outputDirectory = $$$FileTempDir
52+
Set bundleName = "my-oras-bundle"
53+
Set bundleVersion = "0.1.0"
54+
55+
// Export all dependencies of ORAS along with ORAS itself
56+
Set deps = ##class(%IPM.Utils.EmbeddedPython).ListDependencies(package, 1, 1)
57+
Do ##class(%IPM.Utils.EmbeddedPython).BundleWheel(deps, outputDirectory, bundleName, bundleVersion)
58+
59+
// There should be one and only one file - the wheel
60+
set rs = ##class(%File).FileSetFunc(outputDirectory)
61+
Do $$$AssertTrue(rs.%Next())
62+
Do $$$AssertEquals(rs.Type, "F")
63+
Set wheelPath = rs.Name
64+
Do $$$AssertNotTrue(rs.%Next())
65+
66+
// Try install the wheel to another directory
67+
Set pipCaller = ##class(%IPM.Lifecycle.Base).ResolvePipCaller()
68+
// Create a temporary directory for installing the wheel to
69+
Set targetInstallDir = $$$FileTempDir
70+
Set command = pipCaller _ $ListBuild("install", wheelPath, "-t", targetInstallDir)
71+
Set tSC = ##class(%IPM.Utils.Module).RunCommand(, command, .stdout)
72+
Do $$$AssertStatusOK(tSC, "Successfully installed the wheel")
73+
74+
// Exclude mgr/python from sys.path and include targetInstallDir to check if the installed wheel works
75+
Set mgrPython = ##class(%File).NormalizeDirectory("python", ##class(%File).ManagerDirectory())
76+
Set mgrPython = $Extract(mgrPython, 1, *-1) // Remove trailing slash
77+
Do ..PythonPath.remove(mgrPython)
78+
Do ..PythonPath.append(targetInstallDir)
79+
Try {
80+
// At this point, oras is probably already in sys.modules cache
81+
// because it was used in OrasTag test (which is alphabetically before this test)
82+
// but if it's not, we import it here so that we can use importlib.reload() with updated sys.path
83+
Set oras = ##class(%SYS.Python).Import("oras")
84+
Set importlib = ##class(%SYS.Python).Import("importlib")
85+
Set oras = importlib.reload(oras)
86+
87+
Do $$$AssertTrue(oras."__file__" [ targetInstallDir, "oras is imported from the installed wheel")
88+
89+
// revert oras back to the original one
90+
Do ..PythonPath.remove(targetInstallDir)
91+
Do ..PythonPath.append(mgrPython)
92+
Set oras = importlib.reload(oras)
93+
} Catch ex {
94+
Do $$$AssertFailure("Failed to import oras: "_ex.AsStatus())
95+
}
96+
97+
// Clean up temporary directories
98+
Do ##class(%File).RemoveDirectoryTree(outputDirectory)
99+
Do ##class(%File).RemoveDirectoryTree(targetInstallDir)
100+
}
101+
102+
}

0 commit comments

Comments
 (0)