Papers
Topics
Authors
Recent
Search
2000 character limit reached

PCREQ: Automated Python Upgrade Repair

Updated 7 July 2026
  • PCREQ is an automated repair system that infers compatible requirements for Python library upgrades by combining dependency solving and code-level analysis.
  • It employs SMT-based version compatibility assessment alongside static API extraction to identify and resolve both dependency and API compatibility issues.
  • The system iteratively adjusts library versions and completes missing dependencies to ensure that pip installations succeed and projects run without runtime crashes.

PCREQ is an automated analysis and repair system for Python third-party library upgrades that infers a new requirements.txt for a given project and target library upgrade while jointly enforcing version compatibility and code compatibility. In the formulation introduced by “PCREQ: Automated Inference of Compatible Requirements for Python Third-party Library Upgrades” (Lei et al., 4 Aug 2025), the central objective is to produce an environment in which pip install -r requirements.txt succeeds and the project does not crash because of removed or changed APIs, including both direct project–library interactions and indirect library–library interactions.

1. Problem definition and compatibility model

PCREQ addresses upgrade failures in Python projects that depend on third-party libraries (TPLs). The paper separates these failures into two categories. Version Compatibility Issues (VCIs) arise at the dependency-graph level, typically as unsatisfiable version constraints among packages. Code Compatibility Issues (CCIs) arise at the code/API level and may persist even when installation succeeds. CCIs are further divided into four types: module, API name, API parameter, and API body (Lei et al., 4 Aug 2025).

The distinction between VCIs and CCIs is operational rather than merely taxonomic. A VCI example is an upgrade that makes dependency constraints inconsistent, as in the reported case where torchvision == 0.7.0 requires torch == 1.6.0, causing a conflict when torch is upgraded to 1.9.0. A CCI example is a runtime failure caused by API removal despite a successful installation, such as tf.placeholder or tensorflow.Session disappearing in TensorFlow 2.0. The paper also emphasizes TPL–TPL incompatibilities, where the project does not directly call the breaking API but reaches it through another library, as in [scikit-learn](https://www.emergentmind.com/topics/scikit-learn) 0.18.1 importing from scipy.misc import comb, which breaks when scipy is upgraded to 1.3.0 and scipy.misc.comb is removed (Lei et al., 4 Aug 2025).

An empirical study over 34 projects, 20 TPLs, and 2,095 upgrade experiments motivates this formulation. In those experiments, 140 upgrades had pip installation errors, but 102 of those still ran successfully; conversely, among 1,955 upgrades that installed successfully, 368 crashed at runtime. This demonstrates that satisfying version constraints is neither necessary nor sufficient for runtime correctness, and it motivates a system that combines dependency solving with code-level compatibility analysis (Lei et al., 4 Aug 2025).

2. System architecture and end-to-end workflow

PCREQ integrates six modules and applies them in an iterative repair loop. The modules are knowledge acquisition, version compatibility assessment, invoked APIs and modules extraction, code compatibility assessment, version change, and missing TPL completion (Lei et al., 4 Aug 2025).

Module Function
Knowledge acquisition Collect candidate versions, metadata, source code, modules, and APIs
Version compatibility assessment Encode dependency constraints as SMT and solve them with Z3
Invoked APIs and modules extraction Extract direct and indirect API/module usage
Code compatibility assessment Detect module, API name, API parameter, and some body issues
Version change Adjust target or dependent TPL versions and re-run analysis
Missing TPL completion Add missing dependencies to the final requirements.txt

The workflow begins from the project path, the original requirements.txt, the Python version, a target TPL, and a target version. PCREQ first parses the original environment, sets the target library to the desired version, generates an SMT expression for dependency consistency, and solves it to obtain a version-compatible assignment. It then extracts code entities used by the project and relevant libraries, checks code compatibility between the starting environment and the candidate environment, and, if issues remain, iteratively adjusts versions and repeats the analysis. After compatibility checks succeed, it completes missing TPLs and outputs both a compatible requirements.txt and a repair report (Lei et al., 4 Aug 2025).

This architecture is explicitly designed to combine global environment inference with local code reasoning. A plausible implication is that PCREQ treats upgrade repair as a constrained search over the joint space of dependency assignments and code-level breakages rather than as a pure resolver problem or a pure API-migration problem.

3. Knowledge acquisition and SMT-based version compatibility analysis

The knowledge acquisition stage has two parts. For version-related knowledge, PCREQ parses each library==version entry in the initial requirements.txt, queries PyPI for all versions compatible with the specified Python version, and stores version candidates and dependency metadata, especially requires_dist, in local JSON files. For code-related knowledge, it downloads source distributions for candidate versions and extracts modules and APIs from source code and stub files such as *.pyi (Lei et al., 4 Aug 2025).

Module extraction walks the package directory and keeps *.py files as modules and directories containing __init__.py as packages while filtering irrelevant directories such as __pycache__, tests, and docs. API extraction parses each Python file into an AST and traverses FunctionDef, ClassDef, and Assign nodes to construct fully qualified names, including nested definitions. The system also analyzes __init__.py files to recover re-exported names and simplify fully qualified API paths to user-facing forms. The paper reports that this step reuses techniques from PCART for name simplification (Lei et al., 4 Aug 2025).

For VCI handling, PCREQ encodes dependency resolution as an SMT problem. Given Candidates[TPL] and Dependencies[TPL] [version], it builds a formula in which each TPL must be assigned one candidate version whose dependencies are themselves satisfiable. The solver is not asked for an arbitrary model. Instead, PCREQ defines an optimization objective that prefers preserving the original version from the starting requirements.txt, and otherwise prefers newer versions:

O=maxnN[1(n=Vx)(V+1)+index(n)].O = \max \sum_{n \in N} \left[ 1(n = V_x) \cdot (|V| + 1) + \text{index}(n) \right].

Here, V_x is the starting version and index(n) orders versions from oldest to newest. Z3 Optimize is then used to produce verCompatDeps, a version-compatible assignment with this preference structure (Lei et al., 4 Aug 2025).

This solver design distinguishes PCREQ from tools that only enumerate dependency solutions. It makes the original environment a first-class optimization target while still supporting target-library upgrades.

4. Code compatibility analysis for direct and indirect breakages

Once a version-compatible assignment is available, PCREQ analyzes which APIs and modules are actually used from libraries whose versions changed. It compares startDeps and verCompatDeps, constructs upgrade triples of the form <l, V_1, V_2>, and then identifies usage along TPL call chains such as project → numpy, project → scipy → numpy, or project → scikit-learn → scipy → numpy (Lei et al., 4 Aug 2025).

For Project–TPL compatibility, PCREQ parses project files into ASTs and supports several invocation forms: direct invocation, class object invocation, return value invocation, argument invocation, and inheritance invocation. It tracks imports and assignments, resolves aliases, reconstructs call paths, and maps simplified names back to fully qualified names using the knowledge base. If multiple candidates exist, it uses fuzzy matching based on Levenshtein distance (Lei et al., 4 Aug 2025).

For TPL–TPL compatibility, PCREQ first extracts the entry APIs through which the project reaches an intermediate library, then builds an on-demand call graph with code2flow to identify downstream APIs in another library that are used indirectly. It supplements this with recursive import traversal over related .py files so that imported modules and APIs not captured by the call graph are still considered. The result is a set of used APIs S_a and used modules S_m for each upgraded library (Lei et al., 4 Aug 2025).

Compatibility checking is then divided into four analyses. Module compatibility computes the set of modules present in V_1 but missing in V_2 and checks whether the used-module set intersects that difference. API name compatibility does the same for removed APIs. API parameter compatibility reuses PCART: it compares parameter lists between versions, distinguishes positional and keyword parameters, maps parameters across versions, analyzes how call sites pass arguments, and evaluates compatibility with a function f(P,E,M)f(P,E,M), where P is parameter type, E is change type, and M is passing mode. API body compatibility is acknowledged as difficult: the paper states that early attempts produced high false-positive rates, so the final system does not systematically detect behavior-breaking changes beyond limited cases (Lei et al., 4 Aug 2025).

Several case studies illustrate this design. In deep-belief-network, PCREQ traces the chain project → scikit-learn → scipy, extracts scipy.misc.comb, detects that the API is absent after upgrading SciPy, and searches for a compatible version. In PyTorch-ENet, it traces project → torchvision → pillow and identifies the removal of PIL.PILLOW_VERSION. In TensorFlow 1.x to 2.x upgrades, it detects the removal of tensorflow.placeholder and tensorflow.Session from direct project usage (Lei et al., 4 Aug 2025).

5. Version adjustment, missing TPL completion, and repair reporting

When CCIs are detected, PCREQ changes versions according to the role of the incompatible library. For Project–TPL issues involving the target library, it performs downgrade-only search over older candidate versions until both SMT-based version compatibility and code compatibility succeed. If the incompatible library is not the target TPL, PCREQ uses bidirectional search: it first tries upgrades, then downgrades (Lei et al., 4 Aug 2025).

For TPL–TPL issues, the policy depends on which library is the user-selected target. If the target TPL is one side of the incompatible pair, PCREQ keeps that library fixed and adjusts the other side with bidirectional search. If neither side is the target, PCREQ applies a cascading strategy: it first adjusts one incompatible TPL, and if that fails, adjusts the other, re-running SMT solving and CCI analysis after each attempt (Lei et al., 4 Aug 2025).

After a successful assignment is found, PCREQ performs missing TPL completion. It scans the chosen dependency set and, for any dependency referenced by version constraints but absent from requirements.txt, adds that TPL using the oldest version satisfying the constraints. The stated rationale is conservative backward compatibility, since code compatibility has not been analyzed for such a newly introduced library (Lei et al., 4 Aug 2025).

The system also emits a repair report. According to the paper, this report includes all version changes relative to the starting environment, the CCIs identified for each change, the TPLs and call chains involved, and the reasoning steps in the main loop, including SMT results, iterations required to resolve CCIs, and whether missing TPLs were added (Lei et al., 4 Aug 2025). This makes the output diagnostically useful rather than merely executable.

6. REQBench, empirical results, and limitations

PCREQ is evaluated on REQBench, a benchmark with 34 real-world Python projects, 20 TPLs, and 2,095 upgrade test cases. Each case corresponds to a project, a target TPL, and a start-version to target-version upgrade. The benchmark contains 1,689 Pip Solved cases and 406 Pip Unsolved cases. Among the 406 pip-unsolved cases, the paper reports 211 Project–TPL cases and 195 TPL–TPL cases; by type, the distribution is 55 module cases, 247 API name cases, 21 API parameter cases, and 83 API body cases (Lei et al., 4 Aug 2025).

On full REQBench, PCREQ achieves a 94.03% inference success rate, with 1,677 successes out of 1,689 Pip Solved cases and 293 successes out of 406 Pip Unsolved cases. The paper also reports fine-grained success over the 406 CCI cases: 54 of 55 module cases, 224 of 247 API name cases, 4 of 21 API parameter cases, and 11 of 83 API body cases. By level, it solves 169 of 211 Project–TPL cases and 124 of 195 TPL–TPL cases (Lei et al., 4 Aug 2025).

Against prior and alternative approaches, PCREQ substantially outperforms the reported baselines. On REQBench-PyEGo, PCREQ reaches 98.26% success versus 37.02% for PyEGo. On REQBench-ReadPyE, it reaches 95.18% versus 37.16% for ReadPyE. On full REQBench, it outperforms GPT-4o, DeepSeek V3, and DeepSeek R1 by 18.76, 20.00, and 18.61 percentage points, respectively (Lei et al., 4 Aug 2025).

The paper reports practical efficiency as well. PCREQ processes each case from REQBench in 60.79 seconds on average, and 90% of cases finish within 193 seconds. On REQBench-PyEGo, the average is approximately 69.93 seconds; on REQBench-ReadPyE, approximately 65.85 seconds (Lei et al., 4 Aug 2025).

The reported limitations are concentrated in forms of compatibility that are difficult to recover statically. PCREQ is weak on API body changes, where semantics change without signature changes, and on many API parameter changes that require deeper reasoning about constraints or types. It can also miss issues caused by implicit dependencies not declared in requires_dist, API redirection or re-export tricks, incomplete or inconsistent type annotations, and dynamic imports, reflection, or runtime code generation (Lei et al., 4 Aug 2025). This suggests that PCREQ is strongest when incompatibilities are structural, name-based, or statically recoverable, and weaker when they depend on latent semantics or dynamic behavior.

Within the broader landscape of Python environment inference and upgrade repair, PCREQ is presented as the first approach to jointly handle VCIs together with both Project–TPL and TPL–TPL CCIs while using live PyPI metadata and source code rather than a prebuilt static knowledge graph (Lei et al., 4 Aug 2025). Its central significance lies in converting library-upgrade repair from an ad hoc debugging exercise into a reproducible pipeline that combines SMT-based dependency reasoning, static API analysis, and iterative environment synthesis.

Definition Search Book Streamline Icon: https://streamlinehq.com
References (1)

Topic to Video (Beta)

No one has generated a video about this topic yet.

Whiteboard

No one has generated a whiteboard explanation for this topic yet.

Follow Topic

Get notified by email when new papers are published related to PCREQ.