fix: replace distutils.version.LooseVersion for Python 3.12+ compatibility#616
Merged
btorresgil merged 1 commit intoMay 14, 2026
Merged
Conversation
…ility distutils was deprecated in Python 3.10 and removed entirely in Python 3.12, causing an immediate ModuleNotFoundError on any import of panos. Fixes PaloAltoNetworks#580. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
btorresgil
approved these changes
May 14, 2026
Member
btorresgil
left a comment
There was a problem hiding this comment.
@gh-ajinks Looks great! Thanks for fixing this!
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
distutilswas deprecated in Python 3.10 and removed entirely in Python 3.12, making the library completely unusable on any modern Python installation:Fixes #580.
Why not
pip install setuptools?The common workaround is adding
setuptoolsas a runtime dependency, because setuptools ships its owndistutilscopy. This has two problems:setuptoolsis a build-time dependency. Pulling it in at runtime just to recover 40 lines of version-parsing code couples every user's environment to a build tool they may not otherwise need.ModuleNotFoundErrorat import time with no clear signal thatsetuptoolsis required, since it isn't listed in the package's install dependencies.Why not the
packaginglibrary?packaging.version.Versionis the modern, maintained replacement fordistutils.version— but it enforces PEP 440. PAN-OS version strings like10.1.3-h3,9.0.0-b5, and11.0.0-c1are not PEP 440-compliant (his not a recognised pre-release identifier), sopackaging.version.VersionraisesInvalidVersionon them.packaging.version.LegacyVersion, which did handle arbitrary strings, was removed inpackaging22.0 (2022).What this PR does
Inlines a minimal
_LooseVersionclass using only stdlibre. It replicates the exact parsing behaviour thatPanOSVersiondepends on:10.1.3-h3→[10, 1, 3, '-', 'h', 3]9.0.0-b5→[9, 0, 0, '-', 'b', 5]11.0.0→[11, 0, 0]PanOSVersionalready overrides every comparison operator (__lt__,__gt__,__eq__,__le__,__ge__,__ne__), so the only things inherited fromLooseVersionwere the parser and__str__. Both are reproduced exactly. No new dependencies are introduced.Testing
All 244 existing tests in
test_init.py,test_PanOScomp.py, andtest_updater.pypass unchanged on Python 3.14.