Skip to content

Commit 39edf68

Browse files
committed
Merge from main
2 parents b1d6e2a + 9e87388 commit 39edf68

File tree

3 files changed

+46
-45
lines changed

3 files changed

+46
-45
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1414
- #996: Ensure COS commands execute in exec under a dedicated, isolated context
1515
- #1002: When listing configured repositories, only show the TokenAuthMethod when a token is defined.
1616
- #1024: Modules with PythonWheels have wheels packaged correctly under -export-python-deps
17+
- #1061: Fix issue when installing from OCI/ORAS registries
1718
- #1065: Fixed regression introduced in IPM 0.10.3 which removed support for resources with directories as names (e.g. /inc)
1819

1920
## [0.10.5] - 2026-01-15

src/cls/IPM/Repo/Oras/PackageService.cls

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -252,16 +252,17 @@ Method ListModules(pSearchCriteria As %IPM.Repo.SearchCriteria) As %ListOfObject
252252
// collect all versions for this package in tList
253253
do ..ListModulesFromTagString(tVersionExpression, client, pSearchCriteria, package, .tList)
254254
}
255-
} else {
256-
// Endpoint failed, but if the name is specified, still try to find it
255+
}
256+
// Endpoint failed, but if the name is specified, still try to find it
257+
if tList.Count()=0 {
257258
set name = pSearchCriteria.Name
258259
if (name '= "") {
259260
if ..Namespace '= "" {
260261
set name = ..AppendURIs(..Namespace, name)
261262
}
262263
do ..ListModulesFromTagString(tVersionExpression, client, pSearchCriteria, name, .tList)
263-
} else {
264-
// otherwise error out
264+
} elseif response.StatusCode '= 200 {
265+
// If no name is specified and the /v2/_catalog endpoint failed, error out
265266
set msg = "Error: Call to /v2/_catalog endpoint failed. This registry may not support it."
266267
set msg = msg _ $char(10,13) _ "Response Code: "_response.StatusCode _ " - " _ response.ReasonPhrase
267268
$$$ThrowStatus($$$ERROR($$$GeneralError, msg))

tests/integration_tests/Test/PM/Integration/ProcessPythonWheel.cls

Lines changed: 40 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -203,20 +203,8 @@ Method TestPackageWithPythonDeps() As %Status
203203
do $$$AssertStatusOK(sc, "Uninstalled module")
204204

205205

206-
set wheels = { "wheels": ["ansible_core-2.19.4-py3-none-any.whl",
207-
"ansible_core-2.19.5-py3-none-any.whl",
208-
"ansible-12.2.0-py3-none-any.whl",
209-
"cffi-2.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",
210-
"cryptography-46.0.3-cp311-abi3-manylinux_2_34_x86_64.whl",
211-
"jinja2-3.1.6-py3-none-any.whl",
212-
"lune-1.6.4-py3-none-any.whl",
213-
"markupsafe-3.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",
214-
"packaging-25.0-py3-none-any.whl",
215-
"packaging-26.0-py3-none-any.whl",
216-
"pycparser-2.23-py3-none-any.whl",
217-
"pycparser-3.0-py3-none-any.whl",
218-
"pyyaml-6.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",
219-
"resolvelib-1.2.1-py3-none-any.whl"] }
206+
set wheels = { "wheels": ["ansible", "cffi", "cryptography", "jinja2", "lune", "markupsafe",
207+
"packaging", "pycparser", "pyyaml", "resolvelib"] }
220208
do ..AssertWheelFilesExistInPackagedModule(exportTarball, wheels)
221209

222210
set sc = ##class(%IPM.Main).Shell("load -bypass-py-deps "_exportTarball)
@@ -230,7 +218,7 @@ Method TestPackageWithPythonDeps() As %Status
230218
do $$$AssertStatusOK(sc, "Deleted local filesystem repo")
231219
}
232220

233-
/// Omitting -export-python-deps flag should package without the python
221+
/// Omitting -export-python-deps flag should package without the python wheels resource(s)
234222
Method TestPackageWithoutPythonDeps() As %Status
235223
{
236224
set dir = ..GetModuleDir("python-deps-tests", ..#PackageWithPythonDepsLocation)
@@ -253,20 +241,8 @@ Method TestPackageWithoutPythonDeps() As %Status
253241
do $$$AssertStatusOK(sc, "Uninstalled module")
254242

255243

256-
set wheels = { "wheels": ["ansible_core-2.19.4-py3-none-any.whl",
257-
"ansible_core-2.19.5-py3-none-any.whl",
258-
"ansible-12.2.0-py3-none-any.whl",
259-
"cffi-2.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",
260-
"cryptography-46.0.3-cp311-abi3-manylinux_2_34_x86_64.whl",
261-
"jinja2-3.1.6-py3-none-any.whl",
262-
"lune-1.6.4-py3-none-any.whl",
263-
"markupsafe-3.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",
264-
"packaging-25.0-py3-none-any.whl",
265-
"packaging-26.0-py3-none-any.whl",
266-
"pycparser-2.23-py3-none-any.whl",
267-
"pycparser-3.0-py3-none-any.whl",
268-
"pyyaml-6.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",
269-
"resolvelib-1.2.1-py3-none-any.whl"] }
244+
set wheels = { "wheels": ["ansible", "cffi", "cryptography", "jinja2", "lune", "markupsafe",
245+
"packaging", "pycparser", "pyyaml", "resolvelib"] }
270246
do ..AssertWheelFilesExistInPackagedModule(exportTarball, wheels, 0)
271247

272248
set sc = ##class(%IPM.Main).Shell("repo -delete -n localrepo")
@@ -279,24 +255,21 @@ Method TestPublishWithPythonDeps() As %Status
279255

280256
// 1. Test the case of python dependencies defined via requirements.txt
281257
set moduleNameReq = "publish-with-python-just-reqs"
282-
set wheelsReq = ["docx2md-1.0.5-py3-none-any.whl",
283-
"lxml-6.0.2-cp312-cp312-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl",
284-
"pillow-12.1.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl"]
258+
set wheelsReq = ["docx2md", "lxml", "pillow"]
285259
set wheels = {}
286260
do wheels.%Set(moduleNameReq, wheelsReq)
287261
do ..PublishTestHandler(moduleNameReq, wheels)
288262

289263
// 2. Test the case of python dependencies defined via wheel resources in module.xml
290264
set moduleNameWhl = "publish-with-python-just-wheels"
291-
set wheelsWhl = ["numpy-2.4.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl"]
265+
set wheelsWhl = ["numpy"]
292266
set wheels = {}
293267
do wheels.%Set(moduleNameWhl, wheelsWhl)
294268
do ..PublishTestHandler(moduleNameWhl, wheels)
295269

296270
// 3. Test the case of python dependencies both defined in module.xml and requirements.txt
297271
set moduleNameWhlReq = "publish-with-python-wheels-and-reqs"
298-
set wheelsWhlReq = ["colorama-0.4.6-py2.py3-none-any.whl",
299-
"six-1.17.0-py2.py3-none-any.whl"]
272+
set wheelsWhlReq = ["colorama", "six"]
300273
set wheels = {}
301274
do wheels.%Set(moduleNameWhlReq, wheelsWhlReq)
302275
do ..PublishTestHandler(moduleNameWhlReq, wheels)
@@ -365,11 +338,14 @@ Method GetRandomExportPath()
365338
}
366339

367340
/// Checks to see if the physical files exist in a packaged module
341+
/// Instead of using full file name, checks for a substring. This is because the specific version of dependencies
342+
/// installed along with requirements.txt can change and we don't want the check to fail if it does so.
343+
/// This way can just use the package names and not have to worry about extensions on the file names changing causing failures.
368344
///
369345
/// Arguments:
370346
/// - exportTarball: path to the packaged tarball
371-
/// - wheels: Object of <relative path>-<wheel name> pairs array of file names to check for in the unpackaged module
372-
/// Ex: { "/": ["wheel-1.whl","wheel-2.whl"], "wheels":["wheel-3.whl","wheel-4.whl"] }
347+
/// - wheels: Object of <relative path>-<wheel string> pairs array of file names to check for in the unpackaged module
348+
/// Ex: { "/": ["ansible","pycparser"], "wheels":["jinja2", "lune"] }
373349
/// - doesExist: set to 0 if we want to check that files explicitly do not exist (in the case -export-python-deps was not provided)
374350
Method AssertWheelFilesExistInPackagedModule(
375351
exportTarball As %String,
@@ -384,10 +360,23 @@ Method AssertWheelFilesExistInPackagedModule(
384360
set wheelsIter = wheels.%GetIterator()
385361
while wheelsIter.%GetNext(.relativePath, .wheelArr) {
386362
set directory = ##class(%File).NormalizeDirectory(relativePath, exportDir)
363+
// Compile a list of file names under the current directory
364+
set files = ""
365+
set file = $zsearch(directory_"*")
366+
while file '= "" {
367+
set files = files_$listbuild(##class(%File).GetFilename(file))
368+
set file = $zsearch("")
369+
}
370+
387371
set wheelArrIter = wheelArr.%GetIterator()
388372
while wheelArrIter.%GetNext(, .wheelName) {
389-
set fileName = ##class(%File).NormalizeFilename(wheelName, directory)
390-
set exists = ##class(%File).Exists(fileName)
373+
set exists = 0
374+
for i = 1:1:$listlength(files) {
375+
if $find($listget(files, i), wheelName) {
376+
set exists = 1
377+
quit
378+
}
379+
}
391380
if (doesExist) {
392381
do $$$AssertTrue(exists, wheelName_" exists in packaged contents")
393382
}
@@ -401,7 +390,11 @@ Method AssertWheelFilesExistInPackagedModule(
401390
/// Given an object of <module name>-<wheel list> pairs,
402391
/// 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
403392
///
404-
/// Ex: wheels = { "module1": ["wheel-1.whl","wheel-2.whl"], "module2":["wheel-3.whl","wheel-4.whl"] }
393+
/// Instead of using resource, checks for a substring. This is because the specific version of dependencies
394+
/// installed along with requirements.txt can change and we don't want the check to fail if it does so.
395+
/// This way can just use the package names and not have to worry about extensions changing causing failures.
396+
///
397+
/// Ex: wheels = { "module1": ["ansible","pycparser"], "module2":["jinja2", "lune"] }
405398
Method AssertWheelResourcesExistForModule(wheels As %DynamicObject)
406399
{
407400
set wheelsIter = wheels.%GetIterator()
@@ -417,7 +410,13 @@ Method AssertWheelResourcesExistForModule(wheels As %DynamicObject)
417410

418411
set moduleWheelsIter = moduleWheels.%GetIterator()
419412
while moduleWheelsIter.%GetNext(, .wheel) {
420-
set wheelIsResource = ($listfind(resourceList, wheel) > 0)
413+
for i = 1:1:$listlength(resourceList) {
414+
set wheelIsResource = 0
415+
if $find($listget(resourceList, i), wheel) {
416+
set wheelIsResource = 1
417+
quit
418+
}
419+
}
421420
do $$$AssertTrue(wheelIsResource, "Wheel resource "_wheel_" is a part of the installed module "_moduleName)
422421
}
423422
}

0 commit comments

Comments
 (0)