Skip to content

Commit 2f9ab2c

Browse files
authored
Merge branch 'main' into jit/gc
2 parents ae51767 + d716e3b commit 2f9ab2c

File tree

5 files changed

+129
-17
lines changed

5 files changed

+129
-17
lines changed

.github/workflows/build.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,7 @@ jobs:
392392
needs: build-context
393393
if: needs.build-context.outputs.run-ios == 'true'
394394
timeout-minutes: 60
395-
runs-on: macos-15
395+
runs-on: macos-14
396396
steps:
397397
- uses: actions/checkout@v4
398398
with:
@@ -405,10 +405,10 @@ jobs:
405405
# https://github.com/actions/runner-images/issues/12751.
406406
- name: Select Xcode version
407407
run: |
408-
sudo xcode-select --switch /Applications/Xcode_16.4.app
408+
sudo xcode-select --switch /Applications/Xcode_15.4.app
409409
410410
- name: Build and test
411-
run: python3 Apple ci iOS --fast-ci --simulator 'iPhone 16e,OS=18.5'
411+
run: python3 Apple ci iOS --fast-ci --simulator 'iPhone SE (3rd generation),OS=17.5'
412412

413413
build-wasi:
414414
name: 'WASI'

Doc/using/windows.rst

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -290,8 +290,12 @@ Passing ``--dry-run`` will generate output and logs, but will not modify any
290290
installs.
291291

292292
In addition to the above options, the ``--target`` option will extract the
293-
runtime to the specified directory instead of doing a normal install. This is
294-
useful for embedding runtimes into larger applications.
293+
runtime to the specified directory instead of doing a normal install.
294+
This is useful for embedding runtimes into larger applications.
295+
Unlike a normal install, ``py`` will not be aware of the extracted runtime,
296+
and no Start menu or other shortcuts will be created.
297+
To launch the runtime, directly execute the main executable (typically
298+
``python.exe``) in the target directory.
295299

296300
.. code::
297301
@@ -378,10 +382,13 @@ overridden installs may resolve settings differently.
378382

379383
A global configuration file may be configured by an administrator, and would be
380384
read first. The user configuration file is stored at
381-
:file:`%AppData%\\Python\\pymanager.json` (by default) and is read next,
385+
:file:`%AppData%\\Python\\pymanager.json`
386+
(note that this location is under ``Roaming``, not ``Local``) and is read next,
382387
overwriting any settings from earlier files. An additional configuration file
383388
may be specified as the ``PYTHON_MANAGER_CONFIG`` environment variable or the
384389
``--config`` command line option (but not both).
390+
These locations may be modified by administrative customization options listed
391+
later.
385392

386393
The following settings are those that are considered likely to be modified in
387394
normal use. Later sections list those that are intended for administrative
@@ -420,8 +427,8 @@ customization.
420427

421428
* - ``automatic_install``
422429
- ``PYTHON_MANAGER_AUTOMATIC_INSTALL``
423-
- True to allow automatic installs when specifying a particular runtime
424-
to launch.
430+
- True to allow automatic installs when using ``py exec`` to launch.
431+
Other commands will not automatically install.
425432
By default, true.
426433

427434
* - ``include_unmanaged``
@@ -799,6 +806,12 @@ default).
799806
* -
800807
- Check that the ``py`` and ``pymanager`` commands work.
801808

809+
* -
810+
- Ensure your :envvar:`PATH` variable contains the entry for
811+
``%UserProfile%\AppData\Local\Microsoft\WindowsApps``.
812+
The operating system includes this entry once by default, after other
813+
user paths. If removed, shortcuts will not be found.
814+
802815
* - ``py`` gives me a "command not found" error when I type it in my terminal.
803816
- Did you :ref:`install the Python install manager <pymanager>`?
804817

@@ -809,6 +822,12 @@ default).
809822
The "Python (default windowed)" and "Python install manager" commands
810823
may also need refreshing.
811824

825+
* -
826+
- Ensure your :envvar:`PATH` variable contains the entry for
827+
``%UserProfile%\AppData\Local\Microsoft\WindowsApps``.
828+
The operating system includes this entry once by default, after other
829+
user paths. If removed, shortcuts will not be found.
830+
812831
* - ``py`` gives me a "can't open file" error when I type commands in my
813832
terminal.
814833
- This usually means you have the legacy launcher installed and
@@ -839,7 +858,7 @@ default).
839858
- Prerelease and experimental installs that are not managed by the Python
840859
install manager may be chosen ahead of stable releases.
841860
Configure your default tag or uninstall the prerelease runtime
842-
and reinstall using ``py install``.
861+
and reinstall it using ``py install``.
843862

844863
* - ``pythonw`` or ``pyw`` don't launch the same runtime as ``python`` or ``py``
845864
- Click Start, open "Manage app execution aliases", and check that your
@@ -869,6 +888,20 @@ default).
869888
the `legacy launcher`_, or with the Python install manager when installed
870889
from the MSI.
871890

891+
* - I have installed the Python install manager multiple times.
892+
- It is possible to install from the Store or WinGet, from the MSIX on
893+
the Python website, and from the MSI, all at once.
894+
They are all compatible and will share configuration and runtimes.
895+
896+
* -
897+
- See the earlier :ref:`pymanager-advancedinstall` section for ways to
898+
uninstall the install manager other than the typical Installed Apps
899+
(Add and Remove Programs) settings page.
900+
901+
* - My old ``py.ini`` settings no longer work.
902+
- The new Python install manager no longer supports this configuration file
903+
or its settings, and so it will be ignored.
904+
See :ref:`pymanager-config` for information about configuration settings.
872905

873906
.. _windows-embeddable:
874907

@@ -886,7 +919,7 @@ To install an embedded distribution, we recommend using ``py install`` with the
886919

887920
.. code::
888921
889-
$> py install 3.14-embed --target=runtime
922+
$> py install 3.14-embed --target=<directory>
890923
891924
When extracted, the embedded distribution is (almost) fully isolated from the
892925
user's system, including environment variables, system registry settings, and

Lib/pdb.py

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -183,19 +183,37 @@ class _ExecutableTarget:
183183

184184
class _ScriptTarget(_ExecutableTarget):
185185
def __init__(self, target):
186-
self._target = os.path.realpath(target)
186+
self._check(target)
187+
self._target = self._safe_realpath(target)
188+
189+
# If PYTHONSAFEPATH (-P) is not set, sys.path[0] is the directory
190+
# of pdb, and we should replace it with the directory of the script
191+
if not sys.flags.safe_path:
192+
sys.path[0] = os.path.dirname(self._target)
187193

188-
if not os.path.exists(self._target):
194+
@staticmethod
195+
def _check(target):
196+
"""
197+
Check that target is plausibly a script.
198+
"""
199+
if not os.path.exists(target):
189200
print(f'Error: {target} does not exist')
190201
sys.exit(1)
191-
if os.path.isdir(self._target):
202+
if os.path.isdir(target):
192203
print(f'Error: {target} is a directory')
193204
sys.exit(1)
194205

195-
# If safe_path(-P) is not set, sys.path[0] is the directory
196-
# of pdb, and we should replace it with the directory of the script
197-
if not sys.flags.safe_path:
198-
sys.path[0] = os.path.dirname(self._target)
206+
@staticmethod
207+
def _safe_realpath(path):
208+
"""
209+
Return the canonical path (realpath) if it is accessible from the userspace.
210+
Otherwise (for example, if the path is a symlink to an anonymous pipe),
211+
return the original path.
212+
213+
See GH-142315.
214+
"""
215+
realpath = os.path.realpath(path)
216+
return realpath if os.path.exists(realpath) else path
199217

200218
def __repr__(self):
201219
return self._target

Lib/test/test_pdb.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3561,6 +3561,24 @@ def _assert_find_function(self, file_content, func_name, expected):
35613561
self.assertEqual(
35623562
expected, pdb.find_function(func_name, os_helper.TESTFN))
35633563

3564+
def _fd_dir_for_pipe_targets(self):
3565+
"""Return a directory exposing live file descriptors, if any."""
3566+
proc_fd = "/proc/self/fd"
3567+
if os.path.isdir(proc_fd) and os.path.exists(os.path.join(proc_fd, '0')):
3568+
return proc_fd
3569+
3570+
dev_fd = "/dev/fd"
3571+
if os.path.isdir(dev_fd) and os.path.exists(os.path.join(dev_fd, '0')):
3572+
if sys.platform.startswith("freebsd"):
3573+
try:
3574+
if os.stat("/dev").st_dev == os.stat(dev_fd).st_dev:
3575+
return None
3576+
except FileNotFoundError:
3577+
return None
3578+
return dev_fd
3579+
3580+
return None
3581+
35643582
def test_find_function_empty_file(self):
35653583
self._assert_find_function(b'', 'foo', None)
35663584

@@ -3633,6 +3651,47 @@ def test_spec(self):
36333651
stdout, _ = self.run_pdb_script(script, commands)
36343652
self.assertIn('None', stdout)
36353653

3654+
def test_script_target_anonymous_pipe(self):
3655+
"""
3656+
_ScriptTarget doesn't fail on an anonymous pipe.
3657+
3658+
GH-142315
3659+
"""
3660+
fd_dir = self._fd_dir_for_pipe_targets()
3661+
if fd_dir is None:
3662+
self.skipTest('anonymous pipe targets require /proc/self/fd or /dev/fd')
3663+
3664+
read_fd, write_fd = os.pipe()
3665+
3666+
def safe_close(fd):
3667+
try:
3668+
os.close(fd)
3669+
except OSError:
3670+
pass
3671+
3672+
self.addCleanup(safe_close, read_fd)
3673+
self.addCleanup(safe_close, write_fd)
3674+
3675+
pipe_path = os.path.join(fd_dir, str(read_fd))
3676+
if not os.path.exists(pipe_path):
3677+
self.skipTest('fd directory does not expose anonymous pipes')
3678+
3679+
script_source = 'marker = "via_pipe"\n'
3680+
os.write(write_fd, script_source.encode('utf-8'))
3681+
os.close(write_fd)
3682+
3683+
original_path0 = sys.path[0]
3684+
self.addCleanup(sys.path.__setitem__, 0, original_path0)
3685+
3686+
target = pdb._ScriptTarget(pipe_path)
3687+
code_text = target.code
3688+
namespace = target.namespace
3689+
exec(code_text, namespace)
3690+
3691+
self.assertEqual(namespace['marker'], 'via_pipe')
3692+
self.assertEqual(namespace['__file__'], target.filename)
3693+
self.assertIsNone(namespace['__spec__'])
3694+
36363695
def test_find_function_first_executable_line(self):
36373696
code = textwrap.dedent("""\
36383697
def foo(): pass
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Pdb can now run scripts from anonymous pipes used in process substitution.
2+
Patch by Bartosz Sławecki.

0 commit comments

Comments
 (0)