diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c7e51eea1028b8..dfffec486f357c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -392,7 +392,7 @@ jobs: needs: build-context if: needs.build-context.outputs.run-ios == 'true' timeout-minutes: 60 - runs-on: macos-15 + runs-on: macos-14 steps: - uses: actions/checkout@v4 with: @@ -405,10 +405,10 @@ jobs: # https://github.com/actions/runner-images/issues/12751. - name: Select Xcode version run: | - sudo xcode-select --switch /Applications/Xcode_16.4.app + sudo xcode-select --switch /Applications/Xcode_15.4.app - name: Build and test - run: python3 Apple ci iOS --fast-ci --simulator 'iPhone 16e,OS=18.5' + run: python3 Apple ci iOS --fast-ci --simulator 'iPhone SE (3rd generation),OS=17.5' build-wasi: name: 'WASI' diff --git a/Doc/using/windows.rst b/Doc/using/windows.rst index ee18251919959e..a4bc336cc92618 100644 --- a/Doc/using/windows.rst +++ b/Doc/using/windows.rst @@ -290,8 +290,12 @@ Passing ``--dry-run`` will generate output and logs, but will not modify any installs. In addition to the above options, the ``--target`` option will extract the -runtime to the specified directory instead of doing a normal install. This is -useful for embedding runtimes into larger applications. +runtime to the specified directory instead of doing a normal install. +This is useful for embedding runtimes into larger applications. +Unlike a normal install, ``py`` will not be aware of the extracted runtime, +and no Start menu or other shortcuts will be created. +To launch the runtime, directly execute the main executable (typically +``python.exe``) in the target directory. .. code:: @@ -378,10 +382,13 @@ overridden installs may resolve settings differently. A global configuration file may be configured by an administrator, and would be read first. The user configuration file is stored at -:file:`%AppData%\\Python\\pymanager.json` (by default) and is read next, +:file:`%AppData%\\Python\\pymanager.json` +(note that this location is under ``Roaming``, not ``Local``) and is read next, overwriting any settings from earlier files. An additional configuration file may be specified as the ``PYTHON_MANAGER_CONFIG`` environment variable or the ``--config`` command line option (but not both). +These locations may be modified by administrative customization options listed +later. The following settings are those that are considered likely to be modified in normal use. Later sections list those that are intended for administrative @@ -420,8 +427,8 @@ customization. * - ``automatic_install`` - ``PYTHON_MANAGER_AUTOMATIC_INSTALL`` - - True to allow automatic installs when specifying a particular runtime - to launch. + - True to allow automatic installs when using ``py exec`` to launch. + Other commands will not automatically install. By default, true. * - ``include_unmanaged`` @@ -799,6 +806,12 @@ default). * - - Check that the ``py`` and ``pymanager`` commands work. + * - + - Ensure your :envvar:`PATH` variable contains the entry for + ``%UserProfile%\AppData\Local\Microsoft\WindowsApps``. + The operating system includes this entry once by default, after other + user paths. If removed, shortcuts will not be found. + * - ``py`` gives me a "command not found" error when I type it in my terminal. - Did you :ref:`install the Python install manager `? @@ -809,6 +822,12 @@ default). The "Python (default windowed)" and "Python install manager" commands may also need refreshing. + * - + - Ensure your :envvar:`PATH` variable contains the entry for + ``%UserProfile%\AppData\Local\Microsoft\WindowsApps``. + The operating system includes this entry once by default, after other + user paths. If removed, shortcuts will not be found. + * - ``py`` gives me a "can't open file" error when I type commands in my terminal. - This usually means you have the legacy launcher installed and @@ -839,7 +858,7 @@ default). - Prerelease and experimental installs that are not managed by the Python install manager may be chosen ahead of stable releases. Configure your default tag or uninstall the prerelease runtime - and reinstall using ``py install``. + and reinstall it using ``py install``. * - ``pythonw`` or ``pyw`` don't launch the same runtime as ``python`` or ``py`` - Click Start, open "Manage app execution aliases", and check that your @@ -869,6 +888,20 @@ default). the `legacy launcher`_, or with the Python install manager when installed from the MSI. + * - I have installed the Python install manager multiple times. + - It is possible to install from the Store or WinGet, from the MSIX on + the Python website, and from the MSI, all at once. + They are all compatible and will share configuration and runtimes. + + * - + - See the earlier :ref:`pymanager-advancedinstall` section for ways to + uninstall the install manager other than the typical Installed Apps + (Add and Remove Programs) settings page. + + * - My old ``py.ini`` settings no longer work. + - The new Python install manager no longer supports this configuration file + or its settings, and so it will be ignored. + See :ref:`pymanager-config` for information about configuration settings. .. _windows-embeddable: @@ -886,7 +919,7 @@ To install an embedded distribution, we recommend using ``py install`` with the .. code:: - $> py install 3.14-embed --target=runtime + $> py install 3.14-embed --target= When extracted, the embedded distribution is (almost) fully isolated from the user's system, including environment variables, system registry settings, and diff --git a/Lib/profiling/sampling/_heatmap_assets/heatmap.css b/Lib/profiling/sampling/_heatmap_assets/heatmap.css index ada6d2f2ee1db6..b6f086f11cae5e 100644 --- a/Lib/profiling/sampling/_heatmap_assets/heatmap.css +++ b/Lib/profiling/sampling/_heatmap_assets/heatmap.css @@ -75,18 +75,6 @@ overflow: hidden; } -.stat-card::before { - content: ''; - position: absolute; - top: 0; - left: 0; - right: 0; - height: 3px; - background: linear-gradient(90deg, var(--python-blue), var(--python-gold)); - opacity: 0; - transition: opacity var(--transition-fast); -} - .stat-card:nth-child(1) { --i: 0; --card-color: 55, 118, 171; } .stat-card:nth-child(2) { --i: 1; --card-color: 40, 167, 69; } .stat-card:nth-child(3) { --i: 2; --card-color: 255, 193, 7; } @@ -101,10 +89,6 @@ box-shadow: 0 4px 16px rgba(var(--card-color), 0.15); } -.stat-card:hover::before { - opacity: 1; -} - .stat-icon { width: 40px; height: 40px; diff --git a/Lib/profiling/sampling/_heatmap_assets/heatmap_pyfile_template.html b/Lib/profiling/sampling/_heatmap_assets/heatmap_pyfile_template.html index fc85b570984b98..55f70f90c4211c 100644 --- a/Lib/profiling/sampling/_heatmap_assets/heatmap_pyfile_template.html +++ b/Lib/profiling/sampling/_heatmap_assets/heatmap_pyfile_template.html @@ -12,7 +12,7 @@
- Tachyon + Tachyon
diff --git a/Lib/profiling/sampling/_shared_assets/base.css b/Lib/profiling/sampling/_shared_assets/base.css index 4815dae3feae19..5da44249e2e5f9 100644 --- a/Lib/profiling/sampling/_shared_assets/base.css +++ b/Lib/profiling/sampling/_shared_assets/base.css @@ -213,10 +213,13 @@ body { } .brand-text { + font-family: var(--font-sans); font-weight: 700; font-size: 16px; letter-spacing: -0.3px; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.15); + color: inherit; + text-decoration: none; } .brand-subtitle { diff --git a/Lib/profiling/sampling/heatmap_collector.py b/Lib/profiling/sampling/heatmap_collector.py index e1454f0663a439..f705fbe3a32eb9 100644 --- a/Lib/profiling/sampling/heatmap_collector.py +++ b/Lib/profiling/sampling/heatmap_collector.py @@ -335,12 +335,14 @@ def render_hierarchical_html(self, trees: Dict[str, TreeNode]) -> str: icon = '▶' if is_collapsed else '▼' content_style = ' style="display: none;"' if is_collapsed else '' + file_word = "file" if tree.count == 1 else "files" + sample_word = "sample" if tree.samples == 1 else "samples" section_html = f'''
{icon} {type_names[module_type]} - ({tree.count} files, {tree.samples:,} samples) + ({tree.count} {file_word}, {tree.samples:,} {sample_word})
''' @@ -380,11 +382,14 @@ def _render_folder(self, node: TreeNode, name: str, level: int = 1) -> str: parts = [] # Render folder header (collapsed by default) + file_word = "file" if node.count == 1 else "files" + sample_word = "sample" if node.samples == 1 else "samples" parts.append(f'{indent}