Skip to content

Conversation

@smillst
Copy link
Member

@smillst smillst commented Jan 7, 2026

This was changed in 54c3c50. shutil.copytree causes the script to fail with permission problems.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 7, 2026

📝 Walkthrough

Walkthrough

The pull request modifies the release build script to change how release website files are copied. The import statement is updated to replace shutil with copy_tree from distutils.dir_util. The corresponding copy operation is changed from using shutil.copytree() to using copy_tree(). The surrounding logic and functionality of the release build process remain unchanged.

🚥 Pre-merge checks | ✅ 1
✅ Passed checks (1 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @docs/developer/release/release_build.py:
- Line 11: Replace the removed distutils import and calls to copy_tree with
shutil.copytree(..., dirs_exist_ok=True): remove "from distutils.dir_util import
copy_tree", add "import shutil", and on the code path that currently calls
copy_tree(src, dst) (referenced around line 219 in release_build.py) call
shutil.copytree(src, dst, dirs_exist_ok=True) to preserve merge/overwrite
behavior on Python 3.10+.
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between aaf33ab and a673d33.

📒 Files selected for processing (1)
  • docs/developer/release/release_build.py
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: typetools.checker-framework (misc_jdk25)
  • GitHub Check: typetools.checker-framework (typecheck_part1_jdk25)
  • GitHub Check: typetools.checker-framework (inference_part2_jdk25)
  • GitHub Check: typetools.checker-framework (typecheck_part2_jdk25)
  • GitHub Check: typetools.checker-framework (junit_jdk25)
  • GitHub Check: typetools.checker-framework (inference_part1_jdk25)
  • GitHub Check: typetools.checker-framework (nonjunit_jdk25)
🔇 Additional comments (1)
docs/developer/release/release_build.py (1)

217-219: Add documentation for the file promotion behavior.

The operation copies from DEV_SITE_DIR/releases/{version} (freshly created per line 313) to the parent DEV_SITE_DIR. This merges release files using copy_tree, which overwrites files in the destination without error, unlike shutil.copytree which would fail on an existing destination.

While the merge behavior appears intentional here—promoting a versioned release directory's contents to the parent site directory—add a comment explaining this is a deliberate promotion to make the intent explicit and reduce confusion about why copy_tree is used rather than shutil.copytree. This clarifies that files in the version-specific directory are meant to overwrite corresponding files in the parent site directory.

import os
import shutil
import sys
from distutils.dir_util import copy_tree
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# Check the actual code in the file
cat -n docs/developer/release/release_build.py | head -30

Repository: typetools/checker-framework

Length of output: 989


🏁 Script executed:

# Check line 219 for the actual function call
sed -n '210,230p' docs/developer/release/release_build.py

Repository: typetools/checker-framework

Length of output: 964


🏁 Script executed:

# Find Python version requirements
fd -e toml -e txt -e cfg -e ini -e yml -e yaml . --max-one-result | head -20

Repository: typetools/checker-framework

Length of output: 304


🏁 Script executed:

# Check for setup.py, pyproject.toml, or similar files
fd -e toml -e py . -path "*/setup.py" -o -name "pyproject.toml" | head -10

Repository: typetools/checker-framework

Length of output: 239


🏁 Script executed:

# Search for Python version specifications
rg "python_requires|Programming Language :: Python" --type py --type txt

Repository: typetools/checker-framework

Length of output: 53


🏁 Script executed:

# Check for other distutils usage in the codebase
rg "distutils" --type py

Repository: typetools/checker-framework

Length of output: 151


🌐 Web query:

Python distutils deprecation removal timeline Python 3.10 3.12

💡 Result:

Short answer: distutils was deprecated in Python 3.10 (PEP 632), remained deprecated (warnings) through 3.11, and was removed from the standard library in Python 3.12 (so the last CPython that included it by default was 3.11). [1][2][3]

Sources

  • PEP 632 — Deprecate distutils module (deprecation in 3.10; removal planned in 3.12). [1]
  • Python "What’s New in 3.12" (notes removal of distutils). [2]
  • Python 3.12 stdlib distutils docs (states deprecated since 3.10, removed in 3.12). [3]

🏁 Script executed:

# Search more thoroughly for Python version constraints
find . -maxdepth 3 -type f \( -name "setup.py" -o -name "setup.cfg" -o -name "pyproject.toml" -o -name "tox.ini" -o -name "README*" \) | head -20

Repository: typetools/checker-framework

Length of output: 383


🏁 Script executed:

# Check the README or main config files
cat README.md 2>/dev/null | grep -i "python" | head -10

Repository: typetools/checker-framework

Length of output: 157


🏁 Script executed:

# Look for any CI configuration files
find . -maxdepth 2 -type f \( -name ".github" -o -name ".gitlab-ci.yml" -o -name ".travis.yml" \) 2>/dev/null

Repository: typetools/checker-framework

Length of output: 84


🏁 Script executed:

# Check if there's a .github directory
ls -la .github/workflows/ 2>/dev/null || echo "No workflows found"

Repository: typetools/checker-framework

Length of output: 266


🏁 Script executed:

# Check setup.py or similar for Python version requirements
find . -maxdepth 3 -name "setup.py" -o -name "setup.cfg" | xargs cat 2>/dev/null | grep -i "python_requires" -A 2 -B 2

Repository: typetools/checker-framework

Length of output: 53


🏁 Script executed:

# Check pyproject.toml for Python version requirements
cat pyproject.toml | head -50

Repository: typetools/checker-framework

Length of output: 342


🏁 Script executed:

# Check if there's a Python version specified anywhere in the file
grep -n "python" pyproject.toml -i

Repository: typetools/checker-framework

Length of output: 99


🏁 Script executed:

# Also check .travis.yml for Python version information
cat .travis.yml

Repository: typetools/checker-framework

Length of output: 4629


🏁 Script executed:

# Check the context of the release_build.py file - is it a development-only tool?
head -50 docs/developer/release/release_build.py

Repository: typetools/checker-framework

Length of output: 1212


Critical: distutils is removed in Python 3.12+, breaking the code on supported versions.

The project declares requires-python = ">=3.10" in pyproject.toml. The distutils module was deprecated in Python 3.10 and completely removed in Python 3.12. This code will fail on Python 3.12 and later.

Replace with shutil.copytree using the dirs_exist_ok=True parameter, which provides equivalent merge/overwrite behavior and is available in all supported Python versions (3.10+):

Proposed fix
-from distutils.dir_util import copy_tree
+import shutil

Then update line 219:

-    copy_tree(str(dev_website_relative_dir), str(DEV_SITE_DIR))
+    shutil.copytree(str(dev_website_relative_dir), str(DEV_SITE_DIR), dirs_exist_ok=True)

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In @docs/developer/release/release_build.py at line 11, Replace the removed
distutils import and calls to copy_tree with shutil.copytree(...,
dirs_exist_ok=True): remove "from distutils.dir_util import copy_tree", add
"import shutil", and on the code path that currently calls copy_tree(src, dst)
(referenced around line 219 in release_build.py) call shutil.copytree(src, dst,
dirs_exist_ok=True) to preserve merge/overwrite behavior on Python 3.10+.

@mernst
Copy link
Member

mernst commented Jan 7, 2026

@smillst distutils does not exist in Python 3.13 and later. Can you find a different solution? Thanks.

@mernst mernst assigned smillst and unassigned mernst Jan 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants