Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ jobs:
- name: setup Python
uses: actions/setup-python@v7
with:
python-version: '3.9'
python-version: '3.13'
cache: 'pip'

- name: get Python location
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ target
.npmrc
src/providers/*.wasm
*.egg-info
*.m2
3 changes: 2 additions & 1 deletion src/providers/python_controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,8 @@ function bringAllDependencies(dependencies, dependencyName, cachedEnvironmentDep
function getDependencyTreeJsonFromPipDepTree(pipPath,pythonPath) {
let dependencyTree
try {
invokeCommand(pipPath, ['install', 'pipdeptree'])
// pipdeptree 4.x depends on nab-* packages that pull typing_extensions>=4.16, polluting the user's env and causing version-mismatch errors
invokeCommand(pipPath, ['install', 'pipdeptree<4'])
} catch (error) {
throw new Error(`Failed installing pipdeptree utility`, {cause: error})
}
Expand Down
28 changes: 24 additions & 4 deletions src/providers/python_poetry.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ export default class Python_poetry extends Base_pyproject {
* @param {Object} opts
* @returns {Promise<{directDeps: string[], graph: Map<string, {name: string, version: string, children: string[]}>}>}
*/
// eslint-disable-next-line no-unused-vars
async _getDependencyData(manifestDir, _workspaceDir, parsed, opts) {
let poetryBin = getCustomPath('poetry', opts)
let envBypass = environmentVariableIsPopulated('TRUSTIFY_DA_POETRY_SHOW_TREE')
Expand Down Expand Up @@ -136,11 +135,12 @@ export default class Python_poetry extends Base_pyproject {
* → transitiveMarkers['click']['colorama'] = "sys_platform == 'win32'"
* @param {string|null} lockDir
* @param {object} parsed - parsed pyproject.toml
* @returns {{directMarkers: Map<string, string>, transitiveMarkers: Map<string, Map<string, string>>, hashMap: Map<string, Array<{alg: string, content: string}>>}}
* @returns {{directMarkers: Map<string, string>, transitiveMarkers: Map<string, Map<string, string>>, packageMarkers: Map<string, string>, hashMap: Map<string, Array<{alg: string, content: string}>>}}
*/
_extractMarkerData(lockDir, parsed) {
let directMarkers = new Map()
let transitiveMarkers = new Map()
let packageMarkers = new Map()
let hashMap = new Map()

// Extract markers from PEP 621 dependency strings: "name[extras]>=ver ; marker"
Expand All @@ -160,6 +160,9 @@ export default class Python_poetry extends Base_pyproject {
let packages = lock.package || []
for (let pkg of packages) {
let pkgKey = this._canonicalize(pkg.name)
if (pkg.markers) {
packageMarkers.set(pkgKey, pkg.markers)
}
let pkgDeps = pkg.dependencies || {}
for (let [depName, depSpec] of Object.entries(pkgDeps)) {
let markers = typeof depSpec === 'object' && depSpec != null ? depSpec.markers : null
Expand All @@ -179,7 +182,7 @@ export default class Python_poetry extends Base_pyproject {
}
}

return { directMarkers, transitiveMarkers, hashMap }
return { directMarkers, transitiveMarkers, packageMarkers, hashMap }
}

/**
Expand All @@ -204,7 +207,7 @@ export default class Python_poetry extends Base_pyproject {
*
* @param {string} treeOutput
* @param {Map<string, string>} versionMap - canonical name -> resolved version
* @param {{directMarkers: Map<string, string>, transitiveMarkers: Map<string, Map<string, string>>, hashMap: Map<string, Array<{alg: string, content: string}>>}} markerData
* @param {{directMarkers: Map<string, string>, transitiveMarkers: Map<string, Map<string, string>>, packageMarkers: Map<string, string>, hashMap: Map<string, Array<{alg: string, content: string}>>}} markerData
* @returns {{directDeps: string[], graph: Map<string, {name: string, version: string, children: string[], hashes?: Array<{alg: string, content: string}>}>}}
*/
_parsePoetryTree(treeOutput, versionMap, markerData) {
Expand All @@ -214,6 +217,7 @@ export default class Python_poetry extends Base_pyproject {

let stack = [] // [{key, depth}]
let currentDirectDep = null
let skipDepth = null

for (let line of lines) {
if (!line.trim()) { continue }
Expand All @@ -229,8 +233,10 @@ export default class Python_poetry extends Base_pyproject {
if (marker && !evaluateMarker(marker)) {
currentDirectDep = null
stack = []
skipDepth = null
continue
}
skipDepth = null

directDeps.push(key)
if (!graph.has(key)) {
Expand Down Expand Up @@ -261,17 +267,31 @@ export default class Python_poetry extends Base_pyproject {
let prefix = line.substring(0, nameStart)
let depth = (prefix.match(/(?:[├└│ ][\s─]{2} ?)/g) || []).length

// skip entire subtree of a marker-excluded dep
if (skipDepth != null) {
if (depth > skipDepth) { continue }
skipDepth = null
}

// pop stack back to find the parent at depth-1
while (stack.length > 0 && stack[stack.length - 1].depth >= depth) {
stack.pop()
}

// check package-level markers from poetry.lock
let pkgMarker = markerData.packageMarkers.get(depKey)
if (pkgMarker && !evaluateMarker(pkgMarker)) {
skipDepth = depth
continue
}

let parentKey = stack.length > 0 ? stack[stack.length - 1].key : null
if (parentKey) {
let parentMarkers = markerData.transitiveMarkers.get(parentKey)
if (parentMarkers) {
let marker = parentMarkers.get(depKey)
if (marker && !evaluateMarker(marker)) {
skipDepth = depth
continue
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,6 @@
"type": "library",
"bom-ref": "pkg:pypi/asgiref@3.4.1"
},
{
"name": "async-timeout",
"version": "5.0.1",
"purl": "pkg:pypi/async-timeout@5.0.1",
"type": "library",
"bom-ref": "pkg:pypi/async-timeout@5.0.1"
},
{
"name": "beautifulsoup4",
"version": "4.12.2",
Expand Down Expand Up @@ -108,10 +101,10 @@
},
{
"name": "immutables",
"version": "0.20",
"purl": "pkg:pypi/immutables@0.20",
"version": "0.21",
"purl": "pkg:pypi/immutables@0.21",
"type": "library",
"bom-ref": "pkg:pypi/immutables@0.20"
"bom-ref": "pkg:pypi/immutables@0.21"
},
{
"name": "importlib-metadata",
Expand Down Expand Up @@ -219,7 +212,6 @@
"pkg:pypi/aiohappyeyeballs@2.6.1",
"pkg:pypi/anyio@3.6.2",
"pkg:pypi/asgiref@3.4.1",
"pkg:pypi/async-timeout@5.0.1",
"pkg:pypi/beautifulsoup4@4.12.2",
"pkg:pypi/certifi@2023.7.22",
"pkg:pypi/chardet@4.0.0",
Expand All @@ -228,7 +220,7 @@
"pkg:pypi/flask@2.0.3",
"pkg:pypi/h11@0.13.0",
"pkg:pypi/idna@2.10",
"pkg:pypi/immutables@0.20",
"pkg:pypi/immutables@0.21",
"pkg:pypi/importlib-metadata@4.8.3",
"pkg:pypi/itsdangerous@2.0.1",
"pkg:pypi/jinja2@3.0.3",
Expand Down Expand Up @@ -257,10 +249,6 @@
"ref": "pkg:pypi/asgiref@3.4.1",
"dependsOn": []
},
{
"ref": "pkg:pypi/async-timeout@5.0.1",
"dependsOn": []
},
{
"ref": "pkg:pypi/beautifulsoup4@4.12.2",
"dependsOn": []
Expand Down Expand Up @@ -294,7 +282,7 @@
"dependsOn": []
},
{
"ref": "pkg:pypi/immutables@0.20",
"ref": "pkg:pypi/immutables@0.21",
"dependsOn": []
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,6 @@
"type": "library",
"bom-ref": "pkg:pypi/asgiref@3.4.1"
},
{
"name": "async-timeout",
"version": "5.0.1",
"purl": "pkg:pypi/async-timeout@5.0.1",
"type": "library",
"bom-ref": "pkg:pypi/async-timeout@5.0.1"
},
{
"name": "beautifulsoup4",
"version": "4.12.2",
Expand Down Expand Up @@ -164,10 +157,10 @@
},
{
"name": "immutables",
"version": "0.20",
"purl": "pkg:pypi/immutables@0.20",
"version": "0.21",
"purl": "pkg:pypi/immutables@0.21",
"type": "library",
"bom-ref": "pkg:pypi/immutables@0.20"
"bom-ref": "pkg:pypi/immutables@0.21"
},
{
"name": "importlib-metadata",
Expand Down Expand Up @@ -219,7 +212,6 @@
"pkg:pypi/aiohappyeyeballs@2.6.1",
"pkg:pypi/anyio@3.6.2",
"pkg:pypi/asgiref@3.4.1",
"pkg:pypi/async-timeout@5.0.1",
"pkg:pypi/beautifulsoup4@4.12.2",
"pkg:pypi/certifi@2023.7.22",
"pkg:pypi/chardet@4.0.0",
Expand All @@ -228,7 +220,7 @@
"pkg:pypi/flask@2.0.3",
"pkg:pypi/h11@0.13.0",
"pkg:pypi/idna@2.10",
"pkg:pypi/immutables@0.20",
"pkg:pypi/immutables@0.21",
"pkg:pypi/importlib-metadata@4.8.3",
"pkg:pypi/itsdangerous@2.0.1",
"pkg:pypi/jinja2@3.0.3",
Expand Down Expand Up @@ -268,10 +260,6 @@
"ref": "pkg:pypi/asgiref@3.4.1",
"dependsOn": []
},
{
"ref": "pkg:pypi/async-timeout@5.0.1",
"dependsOn": []
},
{
"ref": "pkg:pypi/beautifulsoup4@4.12.2",
"dependsOn": [
Expand Down Expand Up @@ -341,7 +329,7 @@
"dependsOn": []
},
{
"ref": "pkg:pypi/immutables@0.20",
"ref": "pkg:pypi/immutables@0.21",
"dependsOn": []
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ fastapi==0.75.1
Flask==2.0.3
h11==0.13.0
idna==2.10
immutables==0.20
immutables==0.21
importlib-metadata==4.8.3
itsdangerous==2.0.1
Jinja2==3.0.3
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,10 @@
},
{
"name": "immutables",
"version": "0.20",
"purl": "pkg:pypi/immutables@0.20",
"version": "0.21",
"purl": "pkg:pypi/immutables@0.21",
"type": "library",
"bom-ref": "pkg:pypi/immutables@0.20"
"bom-ref": "pkg:pypi/immutables@0.21"
},
{
"name": "importlib-metadata",
Expand Down Expand Up @@ -227,7 +227,7 @@
"pkg:pypi/flask@2.0.3",
"pkg:pypi/h11@0.13.0",
"pkg:pypi/idna@2.10",
"pkg:pypi/immutables@0.20",
"pkg:pypi/immutables@0.21",
"pkg:pypi/importlib-metadata@4.8.3",
"pkg:pypi/itsdangerous@2.0.1",
"pkg:pypi/jinja2@3.0.3",
Expand Down Expand Up @@ -290,7 +290,7 @@
"dependsOn": []
},
{
"ref": "pkg:pypi/immutables@0.20",
"ref": "pkg:pypi/immutables@0.21",
"dependsOn": []
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,10 +164,10 @@
},
{
"name": "immutables",
"version": "0.20",
"purl": "pkg:pypi/immutables@0.20",
"version": "0.21",
"purl": "pkg:pypi/immutables@0.21",
"type": "library",
"bom-ref": "pkg:pypi/immutables@0.20"
"bom-ref": "pkg:pypi/immutables@0.21"
},
{
"name": "importlib-metadata",
Expand Down Expand Up @@ -227,7 +227,7 @@
"pkg:pypi/flask@2.0.3",
"pkg:pypi/h11@0.13.0",
"pkg:pypi/idna@2.10",
"pkg:pypi/immutables@0.20",
"pkg:pypi/immutables@0.21",
"pkg:pypi/importlib-metadata@4.8.3",
"pkg:pypi/itsdangerous@2.0.1",
"pkg:pypi/jinja2@3.0.3",
Expand Down Expand Up @@ -345,7 +345,7 @@
"dependsOn": []
},
{
"ref": "pkg:pypi/immutables@0.20",
"ref": "pkg:pypi/immutables@0.21",
"dependsOn": []
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ fastapi==0.75.1
Flask==2.0.3
h11==0.13.0
idna==2.10
immutables==0.20
immutables==0.21
importlib-metadata==4.8.3
itsdangerous==2.0.1
Jinja2==3.0.3
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,10 @@
},
{
"name" : "immutables",
"version" : "0.20",
"purl" : "pkg:pypi/immutables@0.20",
"version" : "0.21",
"purl" : "pkg:pypi/immutables@0.21",
"type" : "library",
"bom-ref" : "pkg:pypi/immutables@0.20"
"bom-ref" : "pkg:pypi/immutables@0.21"
},
{
"name" : "importlib-metadata",
Expand Down Expand Up @@ -242,7 +242,7 @@
"dependsOn" : [ ]
},
{
"ref" : "pkg:pypi/immutables@0.20",
"ref" : "pkg:pypi/immutables@0.21",
"dependsOn" : [ ]
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,10 +164,10 @@
},
{
"name": "immutables",
"version": "0.20",
"purl": "pkg:pypi/immutables@0.20",
"version": "0.21",
"purl": "pkg:pypi/immutables@0.21",
"type": "library",
"bom-ref": "pkg:pypi/immutables@0.20"
"bom-ref": "pkg:pypi/immutables@0.21"
},
{
"name": "importlib-metadata",
Expand Down Expand Up @@ -227,7 +227,7 @@
"pkg:pypi/flask@2.0.3",
"pkg:pypi/h11@0.13.0",
"pkg:pypi/idna@2.10",
"pkg:pypi/immutables@0.20",
"pkg:pypi/immutables@0.21",
"pkg:pypi/importlib-metadata@4.8.3",
"pkg:pypi/itsdangerous@2.0.1",
"pkg:pypi/jinja2@3.0.3",
Expand Down Expand Up @@ -345,7 +345,7 @@
"dependsOn": []
},
{
"ref": "pkg:pypi/immutables@0.20",
"ref": "pkg:pypi/immutables@0.21",
"dependsOn": []
},
{
Expand Down
Loading
Loading