Fix lxml and distutils compatibility for Python 3.13#388
Fix lxml and distutils compatibility for Python 3.13#388Aparup-Roy-24f3001874 wants to merge 10 commits into
Conversation
|
I've fixed the lxml/distutils compatibility issues for Python 3.13 and ensured the CI build passes by resolving the PEP 8 style requirements. Ready for review! |
📝 WalkthroughWalkthroughThe PR updates version handling and packaging metadata for newer Python releases. It changes the version import source, revises ChangesPython compatibility updates
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@evalai/utils/updates.py`:
- Line 3: Update get_latest_version() in updates.py so it returns a parsed
StrictVersion object instead of the raw release string, using the existing
StrictVersion alias imported from packaging.version. Then update the version
check in evalai/main.py to parse __version__ with StrictVersion before comparing
it to latest_version, so both sides use version objects and not lexicographic
string comparison.
In `@requirements.txt`:
- Around line 6-7: The Python 3.12+ lxml pin is still allowed to resolve to
vulnerable 5.x releases, so update the version marker in requirements.txt to
require lxml 6.1.0 or newer for python_version >= "3.12" while leaving the
Python <3.12 constraint unchanged; adjust the existing lxml dependency entries
only, using the lxml requirement lines as the reference point.
In `@setup.py`:
- Around line 41-43: Remove the outdated flake8 pin from the tests_require list
in setup.py and update it to a Python 3.13-compatible version, using the
existing dependency entry alongside coveralls. Locate the dependency declaration
near the flake8 package name and replace flake8==3.0.4 with flake8>=6.1.0 so the
test/lint environment works on newer Python versions.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: b66dbd31-6e7f-481f-99a5-e3f1d2afa23b
📒 Files selected for processing (3)
evalai/utils/updates.pyrequirements.txtsetup.py
| import requests | ||
|
|
||
| from distutils.version import StrictVersion | ||
| from packaging.version import Version as StrictVersion |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
rg -n -C2 '__version__\s*<\s*latest_version|get_latest_version\(' evalai/main.py evalai/utils/updates.pyRepository: Cloud-CV/evalai-cli
Length of output: 654
🏁 Script executed:
sed -n '6,30p' evalai/utils/updates.pyRepository: Cloud-CV/evalai-cli
Length of output: 395
Return a parsed Version object instead of a string from get_latest_version()
The helper sorts releases using StrictVersion but returns a raw string from the release list. Consequently, evalai/main.py compares __version__ and latest_version as strings, causing lexicographic errors (e.g., 0.9.0 fails to trigger an update against 0.10.0).
Modify get_latest_version() to return a StrictVersion instance (strict_version = StrictVersion(versions[-1]); return strict_version) and update evalai/main.py to parse __version__ before comparison:
- if __version__ < latest_version:
+ if StrictVersion(__version__) < latest_version:🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@evalai/utils/updates.py` at line 3, Update get_latest_version() in updates.py
so it returns a parsed StrictVersion object instead of the raw release string,
using the existing StrictVersion alias imported from packaging.version. Then
update the version check in evalai/main.py to parse __version__ with
StrictVersion before comparing it to latest_version, so both sides use version
objects and not lexicographic string comparison.
| lxml>=4.6.2,<5.0; python_version < "3.12" | ||
| lxml>=5.0.0; python_version >= "3.12" |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
rg -n -C2 --type=py '\bfrom lxml\b|\bimport lxml\b|\biterparse\s*\(|\bETCompatXMLParser\s*\(' .Repository: Cloud-CV/evalai-cli
Length of output: 157
🌐 Web query:
What is the first patched lxml 5.x release for GHSA-vfmq-68hx-4jfw / PYSEC-2026-87, and is lxml 5.0.0 affected?
💡 Result:
The vulnerability GHSA-vfmq-68hx-4jfw (also tracked as PYSEC-2026-87 and CVE-2026-41066) was fixed in lxml 6.1.0 [1][2][3]. Consequently, there is no patched lxml 5.x release for this issue, as it remained unpatched in the 5.x series [1][4]. Lxml 5.0.0 is affected by this vulnerability because the default configuration for iterparse and ETCompatXMLParser still allowed entity resolution (resolve_entities=True) at that time [1][2]. While lxml 5.0 introduced a change to default resolve_entities='internal' for normal XML and HTML parsers, this change was not applied to iterparse or ETCompatXMLParser until version 6.1.0 [1][2].
Citations:
- 1: GHSA-vfmq-68hx-4jfw
- 2: https://pypi.org/project/lxml/6.1.0/
- 3: https://github.com/pypa/advisory-database/blob/main/vulns/lxml/PYSEC-2026-87.yaml
- 4: https://osv.dev/vulnerability/GHSA-vfmq-68hx-4jfw
Bump lxml to >=6.1.0 for Python 3.12+ due to XXE (GHSA-vfmq-68hx-4jfw).
GHSA-vfmq-68hx-4jfw affects lxml 5.0.0–5.x; the first patched release is 6.1.0. Your current pin lxml>=5.0.0; python_version >= "3.12" can resolve to an affected version.
Update both markers to require 6.1.0 minimum:
required change
lxml>=4.6.2,<5.0; python_version < "3.12"
lxml>=6.1.0; python_version >= "3.12"
Even though no explicit lxml imports or iterparse/ETCompatXMLParser calls were found in Python sources, the dependency may be consumed transitively or via non-Python entrypoints. Since the advisory remains unpatched in the 5.x series, pinning to 6.1.0+ eliminates this risk.
[remove: and security flags once updated.]
🧰 Tools
🪛 OSV Scanner (2.4.0)
[HIGH] 6-6: lxml 5.0.0: undefined
(PYSEC-2026-87)
[HIGH] 6-6: lxml 5.0.0: lxml: Default configuration of iterparse() and ETCompatXMLParser() allows XXE to local files
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@requirements.txt` around lines 6 - 7, The Python 3.12+ lxml pin is still
allowed to resolve to vulnerable 5.x releases, so update the version marker in
requirements.txt to require lxml 6.1.0 or newer for python_version >= "3.12"
while leaving the Python <3.12 constraint unchanged; adjust the existing lxml
dependency entries only, using the lxml requirement lines as the reference
point.
Source: Linters/SAST tools
| "packaging", | ||
| "coveralls==1.3.0", | ||
| "flake8==3.0.4", |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major
🧩 Analysis chain
🌐 Web query:
Does flake8 3.0.4 support Python 3.12 or Python 3.13?
💡 Result:
No, Flake8 version 3.0.4 does not support Python 3.12 or Python 3.13. Flake8 3.0.4 was released on August 8, 2016 [1][2], long before the release of Python 3.12 or 3.13. Flake8 is tightly coupled to the version of Python on which it runs because it must be able to parse the syntax of the code it checks [3]. Support for Python 3.12 was only introduced much later, starting with Flake8 version 6.1.0, released in July 2023 [4]. Consequently, version 3.0.4 lacks the necessary infrastructure and language feature support to correctly parse or lint Python 3.12 or 3.13 code.
Citations:
- 1: https://flake8.pycqa.org/en/3.0.4/release-notes/3.0.4.html
- 2: https://flake8.pycqa.org/en/3.0.4/release-notes/index.html
- 3: https://flake8.pycqa.org/en/3.0.4/
- 4: https://flake8.pycqa.org/en/latest/release-notes/6.1.0.html
Remove the outdated flake8==3.0.4 pin to enable Python 3.13 support
flake8==3.0.4 (released Aug 2016) is incompatible with Python 3.12 and 3.13, as support for these versions was only introduced in flake8 6.1.0. Retaining this pin in tests_require will cause linting failures on target CI environments. Update to flake8>=6.1.0.
"packaging",
"coveralls==1.3.0",
"flake8==3.0.4",🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@setup.py` around lines 41 - 43, Remove the outdated flake8 pin from the
tests_require list in setup.py and update it to a Python 3.13-compatible
version, using the existing dependency entry alongside coveralls. Locate the
dependency declaration near the flake8 package name and replace flake8==3.0.4
with flake8>=6.1.0 so the test/lint environment works on newer Python versions.
Description
This PR fixes the installation and runtime errors on Python 3.13 (specifically for Windows users) as reported in #383.
Changes:
lxmlversion gating inrequirements.txt. It now useslxml>=5.0.0for Python 3.12+ to ensure pre-compiled wheels are available, avoiding the need for C++ Build Tools.packagingandsetuptoolstorequirements.txtto provide thedistutilsfunctionality that was removed in Python 3.12.evalai/utils/updates.pyto usepackaging.version.Versioninstead of the deprecateddistutils.version.StrictVersion.Fixes #383
Summary by CodeRabbit
Bug Fixes
lxmlinstalls correctly across older and newer Python versions.Chores