KEMBAR78
GH-133789: Fix unpickling of pathlib objects pickled in Python 3.13 by barneygale · Pull Request #133831 · python/cpython · GitHub
Skip to content

Conversation

@barneygale
Copy link
Contributor

@barneygale barneygale commented May 10, 2025

In Python 3.13 (but not 3.12 or 3.14), pathlib classes are defined in pathlib._local rather than pathlib. In hindsight this was a mistake, but it was difficult to predict how the abstract/local split would pan out.

In this patch we re-introduce pathlib._local as a stub module that re-exports the classes from pathlib. This allows path objects pickled in 3.13 to be unpicked in 3.14+

…3.13

In Python 3.13 (but not 3.12 or 3.14), pathlib classes are defined in
`pathlib._local` rather than `pathlib`. In hindsight this was a mistake,
but it was difficult to predict how the abstract/local split would pan out.

In this patch we re-introduce `pathlib._local` as a stub module that
re-exports the classes from `pathlib`. This allows path objects pickled in
3.13 to be unpicked in 3.14+
@atravitz
Copy link

would this also add support for 3.12 to be able to unpickle path objects pickled in 3.13?

@barneygale
Copy link
Contributor Author

would this also add support for 3.12 to be able to unpickle path objects pickled in 3.13?

I'm afraid not. Generally we don't support that sort of forward-compatibility with pickling

@barneygale barneygale enabled auto-merge (squash) October 17, 2025 21:31
@barneygale barneygale merged commit f4e51f2 into python:main Oct 17, 2025
45 checks passed
@miss-islington-app
Copy link

Thanks @barneygale for the PR 🌮🎉.. I'm working now to backport this PR to: 3.14.
🐍🍒⛏🤖

miss-islington pushed a commit to miss-islington/cpython that referenced this pull request Oct 17, 2025
…3.13 (pythonGH-133831)

In Python 3.13 (but not 3.12 or 3.14), pathlib classes are defined in
`pathlib._local` rather than `pathlib`. In hindsight this was a mistake,
but it was difficult to predict how the abstract/local split would pan out.

In this patch we re-introduce `pathlib._local` as a stub module that
re-exports the classes from `pathlib`. This allows path objects pickled in
3.13 to be unpicked in 3.14+
(cherry picked from commit f4e51f2)

Co-authored-by: Barney Gale <barney.gale@gmail.com>
@bedevere-app
Copy link

bedevere-app bot commented Oct 17, 2025

GH-140276 is a backport of this pull request to the 3.14 branch.

@bedevere-app bedevere-app bot removed the needs backport to 3.14 bugs and security fixes label Oct 17, 2025
barneygale added a commit that referenced this pull request Oct 17, 2025
… 3.13 (GH-133831) (#140276)

GH-133789: Fix unpickling of pathlib objects pickled in Python 3.13 (GH-133831)

In Python 3.13 (but not 3.12 or 3.14), pathlib classes are defined in
`pathlib._local` rather than `pathlib`. In hindsight this was a mistake,
but it was difficult to predict how the abstract/local split would pan out.

In this patch we re-introduce `pathlib._local` as a stub module that
re-exports the classes from `pathlib`. This allows path objects pickled in
3.13 to be unpicked in 3.14+
(cherry picked from commit f4e51f2)

Co-authored-by: Barney Gale <barney.gale@gmail.com>
@bedevere-bot
Copy link

⚠️⚠️⚠️ Buildbot failure ⚠️⚠️⚠️

Hi! The buildbot AMD64 Windows11 Non-Debug 3.14 (tier-1) has failed when building commit f59236b.

What do you need to do:

  1. Don't panic.
  2. Check the buildbot page in the devguide if you don't know what the buildbots are or how they work.
  3. Go to the page of the buildbot that failed (https://buildbot.python.org/#/builders/1684/builds/233) and take a look at the build logs.
  4. Check if the failure is related to this commit (f59236b) or if it is a false positive.
  5. If the failure is related to this commit, please, reflect that on the issue and make a new Pull Request with a fix.

You can take a look at the buildbot page here:

https://buildbot.python.org/#/builders/1684/builds/233

Failed tests:

  • test_external_inspection

Summary of the results of the build (if available):

==

Click to see traceback logs
Traceback (most recent call last):
  File "b:\uildarea\3.14.ware-win11.nondebug\build\Lib\test\support\os_helper.py", line 540, in temp_dir
    yield path
  File "b:\uildarea\3.14.ware-win11.nondebug\build\Lib\test\support\os_helper.py", line 599, in temp_cwd
    yield cwd_dir
  File "b:\uildarea\3.14.ware-win11.nondebug\build\Lib\test\libregrtest\worker.py", line 127, in main
    worker_process(worker_json)
    ~~~~~~~~~~~~~~^^^^^^^^^^^^^
  File "b:\uildarea\3.14.ware-win11.nondebug\build\Lib\test\libregrtest\worker.py", line 113, in worker_process
    sys.exit(0)
    ~~~~~~~~^^^
SystemExit: 0


Traceback (most recent call last):
  File "b:\uildarea\3.14.ware-win11.nondebug\build\Lib\test\support\__init__.py", line 208, in _force_run
    return func(*args)
PermissionError: [WinError 32] The process cannot access the file because it is being used by another process: 'B:\\uildarea\\3.14.ware-win11.nondebug\\build\\build\\test_python_17876�'


Traceback (most recent call last):
  File "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File "b:\uildarea\3.14.ware-win11.nondebug\build\Lib\test\libregrtest\worker.py", line 131, in <module>
    main()
    ~~~~^^
  File "b:\uildarea\3.14.ware-win11.nondebug\build\Lib\test\libregrtest\worker.py", line 126, in main
    with os_helper.temp_cwd(work_dir, quiet=True):
         ~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^
  File "b:\uildarea\3.14.ware-win11.nondebug\build\Lib\contextlib.py", line 162, in __exit__
    self.gen.throw(value)
    ~~~~~~~~~~~~~~^^^^^^^
  File "b:\uildarea\3.14.ware-win11.nondebug\build\Lib\test\support\os_helper.py", line 597, in temp_cwd
    with temp_dir(path=name, quiet=quiet) as temp_path:
         ~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^
  File "b:\uildarea\3.14.ware-win11.nondebug\build\Lib\contextlib.py", line 162, in __exit__
    self.gen.throw(value)
    ~~~~~~~~~~~~~~^^^^^^^
  File "b:\uildarea\3.14.ware-win11.nondebug\build\Lib\test\support\os_helper.py", line 545, in temp_dir
    rmtree(path)
    ~~~~~~^^^^^^
  File "b:\uildarea\3.14.ware-win11.nondebug\build\Lib\test\support\os_helper.py", line 497, in rmtree
    _rmtree(path)
    ~~~~~~~^^^^^^
  File "b:\uildarea\3.14.ware-win11.nondebug\build\Lib\test\support\os_helper.py", line 441, in _rmtree
    _waitfor(lambda p: _force_run(p, os.rmdir, p), path)
    ~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "b:\uildarea\3.14.ware-win11.nondebug\build\Lib\test\support\os_helper.py", line 381, in _waitfor
    func(pathname)
    ~~~~^^^^^^^^^^
  File "b:\uildarea\3.14.ware-win11.nondebug\build\Lib\test\support\os_helper.py", line 441, in <lambda>
    _waitfor(lambda p: _force_run(p, os.rmdir, p), path)
                       ~~~~~~~~~~^^^^^^^^^^^^^^^^
  File "b:\uildarea\3.14.ware-win11.nondebug\build\Lib\test\support\__init__.py", line 219, in _force_run
    return func(*args)
PermissionError: [WinError 32] The process cannot access the file because it is being used by another process: 'B:\\uildarea\\3.14.ware-win11.nondebug\\build\\build\\test_python_13700�'


Traceback (most recent call last):
  File "b:\uildarea\3.14.ware-win11.nondebug\build\Lib\test\support\__init__.py", line 208, in _force_run
    return func(*args)
PermissionError: [WinError 32] The process cannot access the file because it is being used by another process: 'B:\\uildarea\\3.14.ware-win11.nondebug\\build\\build\\test_python_13700�'


Traceback (most recent call last):
  File "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File "b:\uildarea\3.14.ware-win11.nondebug\build\Lib\test\libregrtest\worker.py", line 131, in <module>
    main()
    ~~~~^^
  File "b:\uildarea\3.14.ware-win11.nondebug\build\Lib\test\libregrtest\worker.py", line 126, in main
    with os_helper.temp_cwd(work_dir, quiet=True):
         ~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^
  File "b:\uildarea\3.14.ware-win11.nondebug\build\Lib\contextlib.py", line 162, in __exit__
    self.gen.throw(value)
    ~~~~~~~~~~~~~~^^^^^^^
  File "b:\uildarea\3.14.ware-win11.nondebug\build\Lib\test\support\os_helper.py", line 597, in temp_cwd
    with temp_dir(path=name, quiet=quiet) as temp_path:
         ~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^
  File "b:\uildarea\3.14.ware-win11.nondebug\build\Lib\contextlib.py", line 162, in __exit__
    self.gen.throw(value)
    ~~~~~~~~~~~~~~^^^^^^^
  File "b:\uildarea\3.14.ware-win11.nondebug\build\Lib\test\support\os_helper.py", line 545, in temp_dir
    rmtree(path)
    ~~~~~~^^^^^^
  File "b:\uildarea\3.14.ware-win11.nondebug\build\Lib\test\support\os_helper.py", line 497, in rmtree
    _rmtree(path)
    ~~~~~~~^^^^^^
  File "b:\uildarea\3.14.ware-win11.nondebug\build\Lib\test\support\os_helper.py", line 441, in _rmtree
    _waitfor(lambda p: _force_run(p, os.rmdir, p), path)
    ~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "b:\uildarea\3.14.ware-win11.nondebug\build\Lib\test\support\os_helper.py", line 381, in _waitfor
    func(pathname)
    ~~~~^^^^^^^^^^
  File "b:\uildarea\3.14.ware-win11.nondebug\build\Lib\test\support\os_helper.py", line 441, in <lambda>
    _waitfor(lambda p: _force_run(p, os.rmdir, p), path)
                       ~~~~~~~~~~^^^^^^^^^^^^^^^^
  File "b:\uildarea\3.14.ware-win11.nondebug\build\Lib\test\support\__init__.py", line 219, in _force_run
    return func(*args)
PermissionError: [WinError 32] The process cannot access the file because it is being used by another process: 'B:\\uildarea\\3.14.ware-win11.nondebug\\build\\build\\test_python_17876�'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants