🐛 fix(py_info): discover Python 3.6 and 3.7 interpreters - #117
Conversation
2941653 to
5fb1dc2
Compare
|
I was playing with this (adding 3.7 only is a 10 line change), then saw you had a patch, so ran a Fable review, pasted below, in case it's helpful. 🤖 AI text below 🤖 The review is done: #117 is fundamentally sound — my Docker testing confirmed every headline claim — but the review surfaced 8 verified findings, four of them correctness issues worth fixing before it leaves draft. All 8 are in the findings panel; the short version: Correctness (the ones that matter):
Hardening/cleanup: the vermin test only asserts The agent also explicitly refuted one candidate (a suspected 3.6 |
The interrogation script runs inside the candidate interpreter, so its syntax floor decides which Pythons are discoverable, independent of requires-python. Sharing one file between the library and that script tied the floor to the library's style: the standalone rewrite pulled in typing.Final and a pre-commit autoupdate added walrus operators, both 3.8-only, so 3.6 and 3.7 candidates died with a SyntaxError logged at debug level after two identical attempts (#116). Split the target-side collection into _py_info_collect.py. Collection supports 3.6+, reaching RHEL 8's system Python, while the rest of the library keeps modern style. The file parses down to Python 2.7 and a version gate above every other import reports older interpreters with a dedicated exit code plus a stderr marker, all within the single interrogation call; the host classifies only when both agree, so an errno collision or a shim echoing the phrase cannot misfire. The verdict is permanent, so it is written to the disk cache and warned about once; the retry that cannot succeed is skipped, and an absolute-path spec raises the same message. A vermin check, a gate placement test, and CI jobs against real 2.7 through 3.7 containers keep lint modernizations from raising the floor again. The cache keys entries on the script hash, so entries written by earlier releases re-query instead of misreading the new payload. PythonInfo.from_dict builds via __new__ instead of running a throwaway collection, cutting the cost of every cache hit.
5fb1dc2 to
7097231
Compare
CI jobs that still target Python 3.7 stopped finding their interpreters once nox adopted python-discovery; closes #116. The script interrogating each candidate runs inside that interpreter, so its syntax floor decides which Pythons are discoverable, independent of
requires-python. Because it shared_py_info.pywith the library, style modernizations raised that floor to 3.8 without anyone noticing: the standalone rewrite pulled intyping.Final, and a pre-commit autoupdate later added walrus operators. 🐛 Candidates on 3.6 or 3.7 died with aSyntaxErrorburied at debug level, after two identical query attempts.The target-side collection now lives in its own module,
_py_info_collect.py. Collection supports Python 3.6+, reaching back to RHEL 8's system Python, while the rest of the library keeps its modern style. The file parses down to Python 2.7, and a version gate above every other import reports anything older through a dedicated exit code plus a stderr marker, within the single interrogation call; the host classifies a candidate as too old only when both signals agree, so neither an errno collision nor a shim echoing the phrase can misfire. A staticvermincheck plus CI jobs that exercise discovery against realpython:2.7throughpython:3.7containers pin the floor, closing the door on the lint-autoupdate regression path. The disk cache keys entries on the script hash, so caches written by earlier releases re-query instead of misreading the new payload, in both upgrade directions.A candidate below the floor logs one warning naming the executable and the version found, skips the retry, and the verdict lands in the disk cache so the interpreter is never spawned again; an absolute-path spec pointing at such an interpreter raises
RuntimeErrorwith the same message. ⚡PythonInfo.from_dictbuilds instances via__new__, so loading a cache entry no longer performs a throwaway collection of the host interpreter. The docs state both floors: the library runs on Python 3.8+ and discovers interpreters down to 3.6, with the floor moving only in a major release.