mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
* Preserve interpolation source text and canonical metadata Source-only checkpoint; candidate validation and the existing annotation expectation reconciliation remain pending. Assisted-by: OpenAI Codex:model version unavailable * Align existing annotation expectations with CPython metadata Update only the nine existing expected strings confirmed against pinned CPython 3.15, with explicit user approval. Assisted-by: OpenAI Codex:model version unavailable * Preserve template metadata through compilation and interactive input Escape literal debug prefixes, retain None AST expression metadata internally, and continue incomplete triple-quoted t-strings in the existing shell. Assisted-by: OpenAI Codex:model version unavailable * Classify normalized unclosed brackets as REPL line continuations Assisted-by: OpenAI Codex:model version unavailable * Nest equivalent REPL parse-error alternatives for Clippy Assisted-by: OpenAI Codex:model version unavailable * Remove fulfilled annotation migration lint workaround The canonical expected strings no longer trigger literal_string_with_formatting_args, so the previous lint expectation is obsolete. Assisted-by: OpenAI Codex:model version unavailable * Complete lazy-import exception and traceback library closure Copy canonical traceback and legacy exception mappings with preserved RustPython guards. Copy explicit non-Python library assets by exact path so exception hierarchy data does not expand into the entire test package. Assisted-by: OpenAI Codex:model version unavailable * Provide Python 3.15 traceback metadata for missing modules and attributes Preserve AttributeError context for missing class attribute deletion, matching type_update_dict. Expose canonical generated missing-stdlib messages through the native sysconfig modules without importing CPython build-specific disabled-module assumptions. Assisted-by: OpenAI Codex:model version unavailable
181 lines
7.1 KiB
Python
181 lines
7.1 KiB
Python
"""Tests for copy_lib.py - library copying with dependencies."""
|
|
|
|
import contextlib
|
|
import pathlib
|
|
import tempfile
|
|
import unittest
|
|
|
|
|
|
class TestCopySingle(unittest.TestCase):
|
|
"""Tests for _copy_single helper function."""
|
|
|
|
def test_copies_file(self):
|
|
"""Test copying a single file."""
|
|
from update_lib.cmd_copy_lib import _copy_single
|
|
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
tmpdir = pathlib.Path(tmpdir)
|
|
|
|
src = tmpdir / "source.py"
|
|
src.write_text("content")
|
|
dst = tmpdir / "dest.py"
|
|
|
|
_copy_single(src, dst, verbose=False)
|
|
|
|
self.assertTrue(dst.exists())
|
|
self.assertEqual(dst.read_text(), "content")
|
|
|
|
def test_copies_directory(self):
|
|
"""Test copying a directory."""
|
|
from update_lib.cmd_copy_lib import _copy_single
|
|
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
tmpdir = pathlib.Path(tmpdir)
|
|
|
|
src = tmpdir / "source_dir"
|
|
src.mkdir()
|
|
(src / "file.py").write_text("content")
|
|
dst = tmpdir / "dest_dir"
|
|
|
|
_copy_single(src, dst, verbose=False)
|
|
|
|
self.assertTrue(dst.exists())
|
|
self.assertTrue((dst / "file.py").exists())
|
|
|
|
def test_removes_existing_before_copy(self):
|
|
"""Test that existing destination is removed before copy."""
|
|
from update_lib.cmd_copy_lib import _copy_single
|
|
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
tmpdir = pathlib.Path(tmpdir)
|
|
|
|
src = tmpdir / "source.py"
|
|
src.write_text("new content")
|
|
dst = tmpdir / "dest.py"
|
|
dst.write_text("old content")
|
|
|
|
_copy_single(src, dst, verbose=False)
|
|
|
|
self.assertEqual(dst.read_text(), "new content")
|
|
|
|
def test_directory_copy_excludes_bytecode_cache_directories(self):
|
|
from update_lib.cmd_copy_lib import _copy_single
|
|
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
root = pathlib.Path(tmpdir)
|
|
src = root / "source"
|
|
dst = root / "destination"
|
|
for relative in ("__pycache__", "package/__pycache__", "assets"):
|
|
(src / relative).mkdir(parents=True)
|
|
files = {
|
|
"__init__.py": b"source\n",
|
|
"package/module.py": b"nested source\n",
|
|
"assets/data.bin": b"\x00\xffasset",
|
|
"assets/__pycache__": b"ordinary file, not a directory",
|
|
"assets/fixture.pyc": b"canonical bytecode fixture",
|
|
"__pycache__/module.cpython-315.pyc": b"stale cache",
|
|
"package/__pycache__/module.cpython-315.pyc": b"nested cache",
|
|
}
|
|
for relative, content in files.items():
|
|
(src / relative).write_bytes(content)
|
|
|
|
_copy_single(src, dst, verbose=False)
|
|
|
|
expected = {
|
|
relative: content
|
|
for relative, content in files.items()
|
|
if "__pycache__" not in pathlib.Path(relative).parts[:-1]
|
|
}
|
|
actual = {
|
|
path.relative_to(dst).as_posix(): path.read_bytes()
|
|
for path in dst.rglob("*")
|
|
if path.is_file()
|
|
}
|
|
self.assertEqual(actual, expected)
|
|
self.assertFalse((dst / "__pycache__").exists())
|
|
self.assertFalse((dst / "package/__pycache__").exists())
|
|
for relative, content in files.items():
|
|
self.assertEqual((src / relative).read_bytes(), content)
|
|
|
|
|
|
class TestCopyLib(unittest.TestCase):
|
|
"""Tests for copy_lib function."""
|
|
|
|
def test_nested_data_file_preserves_siblings(self):
|
|
from update_lib.cmd_copy_lib import copy_lib
|
|
|
|
for name in ("hierarchy.txt", "fixture.bin", "README"):
|
|
with self.subTest(name=name), tempfile.TemporaryDirectory() as tmpdir:
|
|
root = pathlib.Path(tmpdir)
|
|
source = root / "cpython/Lib/test/data" / name
|
|
source.parent.mkdir(parents=True)
|
|
source.write_bytes(b"canonical\x00\xff\n")
|
|
(source.parent / "other.txt").write_bytes(b"unselected source")
|
|
target = root / "Lib/test/data" / name
|
|
target.parent.mkdir(parents=True)
|
|
target.write_bytes(b"old")
|
|
sibling = root / "Lib/test/test_local.py"
|
|
sibling.write_bytes(b"local guards\n")
|
|
with contextlib.chdir(root):
|
|
copy_lib(source, verbose=False)
|
|
self.assertEqual(target.read_bytes(), source.read_bytes())
|
|
self.assertEqual(sibling.read_bytes(), b"local guards\n")
|
|
self.assertFalse((target.parent / "other.txt").exists())
|
|
|
|
def test_missing_data_file_does_not_copy_containing_package(self):
|
|
from update_lib.cmd_copy_lib import copy_lib
|
|
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
root = pathlib.Path(tmpdir)
|
|
source = root / "cpython/Lib/test/missing.txt"
|
|
source.parent.mkdir(parents=True)
|
|
(source.parent / "other.py").write_text("unselected source")
|
|
sibling = root / "Lib/test/test_local.py"
|
|
sibling.parent.mkdir(parents=True)
|
|
sibling.write_bytes(b"local guards\n")
|
|
with contextlib.chdir(root), self.assertRaises(FileNotFoundError):
|
|
copy_lib(source, verbose=False)
|
|
self.assertEqual(sibling.read_bytes(), b"local guards\n")
|
|
self.assertFalse((sibling.parent / "other.py").exists())
|
|
|
|
def test_python_module_still_copies_hard_dependencies(self):
|
|
from update_lib.cmd_copy_lib import copy_lib
|
|
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
root = pathlib.Path(tmpdir)
|
|
source = root / "cpython/Lib"
|
|
source.mkdir(parents=True)
|
|
for name in ("pickle.py", "_compat_pickle.py"):
|
|
(source / name).write_text(name)
|
|
with contextlib.chdir(root):
|
|
copy_lib(source / "pickle.py", verbose=False)
|
|
for name in ("pickle.py", "_compat_pickle.py"):
|
|
self.assertEqual((root / "Lib" / name).read_text(), name)
|
|
|
|
def test_package_still_copies_directory(self):
|
|
from update_lib.cmd_copy_lib import copy_lib
|
|
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
root = pathlib.Path(tmpdir)
|
|
source = root / "cpython/Lib/json"
|
|
source.mkdir(parents=True)
|
|
for name in ("__init__.py", "decoder.py"):
|
|
(source / name).write_text(name)
|
|
with contextlib.chdir(root):
|
|
copy_lib(source, verbose=False)
|
|
for name in ("__init__.py", "decoder.py"):
|
|
self.assertEqual((root / "Lib/json" / name).read_text(), name)
|
|
|
|
def test_raises_on_path_without_lib(self):
|
|
"""Test that copy_lib raises ValueError when path doesn't contain /Lib/."""
|
|
from update_lib.cmd_copy_lib import copy_lib
|
|
|
|
with self.assertRaises(ValueError) as ctx:
|
|
copy_lib(pathlib.Path("some/path/without/lib.py"))
|
|
|
|
self.assertIn("/Lib/", str(ctx.exception))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|