Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ repos:
name: Run Ruff (lint) on Argument Clinic
args: [--exit-non-zero-on-fix, --config=Tools/clinic/.ruff.toml]
files: ^Tools/clinic/|Lib/test/test_clinic.py
- id: ruff
name: Run Ruff (lint) on Tools/peg_generator/
args: [--exit-non-zero-on-fix, --config=Tools/peg_generator/.ruff.toml]
files: ^Tools/peg_generator/
- id: ruff-format
name: Run Ruff (format) on Doc/
args: [--check]
Expand Down
2 changes: 1 addition & 1 deletion Doc/library/venv.rst
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ It also creates a :file:`bin` (or :file:`Scripts` on Windows) subdirectory
containing a copy or symlink of the Python executable
(as appropriate for the platform or arguments used at environment creation time).
It also creates a :file:`lib/pythonX.Y/site-packages` subdirectory
(on Windows, this is :file:`Lib\site-packages`).
(on Windows, this is :file:`Lib\\site-packages`).
If an existing directory is specified, it will be re-used.

.. versionchanged:: 3.5
Expand Down
1 change: 0 additions & 1 deletion Doc/tools/.nitignore
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,3 @@ Doc/reference/datamodel.rst
Doc/whatsnew/2.4.rst
Doc/whatsnew/2.5.rst
Doc/whatsnew/2.6.rst
Doc/whatsnew/3.10.rst
6 changes: 3 additions & 3 deletions Doc/whatsnew/3.10.rst
Original file line number Diff line number Diff line change
Expand Up @@ -901,7 +901,7 @@ Improved Modules
asyncio
-------

Add missing :meth:`~asyncio.events.AbstractEventLoop.connect_accepted_socket`
Add missing :meth:`~asyncio.loop.connect_accepted_socket`
method.
(Contributed by Alex Grönholm in :issue:`41332`.)

Expand Down Expand Up @@ -933,7 +933,7 @@ Base32 Encoding with Extended Hex Alphabet.
bdb
---

Add :meth:`~bdb.Breakpoint.clearBreakpoints` to reset all set breakpoints.
Add :meth:`!clearBreakpoints` to reset all set breakpoints.
(Contributed by Irit Katriel in :issue:`24160`.)

bisect
Expand Down Expand Up @@ -1398,7 +1398,7 @@ A new verify flag :const:`~ssl.VERIFY_X509_PARTIAL_CHAIN` has been added.
sqlite3
-------

Add audit events for :func:`~sqlite3.connect/handle`,
Add audit events for :func:`~sqlite3.connect`,
:meth:`~sqlite3.Connection.enable_load_extension`, and
:meth:`~sqlite3.Connection.load_extension`.
(Contributed by Erlend E. Aasland in :issue:`43762`.)
Expand Down
6 changes: 6 additions & 0 deletions Include/internal/pycore_optimizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,12 @@ PyJitRef_Wrap(JitOptSymbol *sym)
return (JitOptRef){.bits=(uintptr_t)sym};
}

static inline JitOptRef
PyJitRef_StripReferenceInfo(JitOptRef ref)
{
return PyJitRef_Wrap(PyJitRef_Unwrap(ref));
}

static inline JitOptRef
PyJitRef_Borrow(JitOptRef ref)
{
Expand Down
40 changes: 2 additions & 38 deletions Lib/idlelib/editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
from idlelib.tree import wheel_event
from idlelib.util import py_extensions
from idlelib import window
from idlelib.help import _get_dochome

# The default tab setting for a Text widget, in average-width characters.
TK_TABWIDTH_DEFAULT = 8
Expand Down Expand Up @@ -76,44 +77,7 @@ def __init__(self, flist=None, filename=None, key=None, root=None):
from idlelib.runscript import ScriptBinding

if EditorWindow.help_url is None:
dochome = os.path.join(sys.base_prefix, 'Doc', 'index.html')
if sys.platform.count('linux'):
# look for html docs in a couple of standard places
pyver = 'python-docs-' + '%s.%s.%s' % sys.version_info[:3]
if os.path.isdir('/var/www/html/python/'): # "python2" rpm
dochome = '/var/www/html/python/index.html'
else:
basepath = '/usr/share/doc/' # standard location
dochome = os.path.join(basepath, pyver,
'Doc', 'index.html')
elif sys.platform[:3] == 'win':
import winreg # Windows only, block only executed once.
docfile = ''
KEY = (rf"Software\Python\PythonCore\{sys.winver}"
r"\Help\Main Python Documentation")
try:
docfile = winreg.QueryValue(winreg.HKEY_CURRENT_USER, KEY)
except FileNotFoundError:
try:
docfile = winreg.QueryValue(winreg.HKEY_LOCAL_MACHINE,
KEY)
except FileNotFoundError:
pass
if os.path.isfile(docfile):
dochome = docfile
elif sys.platform == 'darwin':
# documentation may be stored inside a python framework
dochome = os.path.join(sys.base_prefix,
'Resources/English.lproj/Documentation/index.html')
dochome = os.path.normpath(dochome)
if os.path.isfile(dochome):
EditorWindow.help_url = dochome
if sys.platform == 'darwin':
# Safari requires real file:-URLs
EditorWindow.help_url = 'file://' + EditorWindow.help_url
else:
EditorWindow.help_url = ("https://docs.python.org/%d.%d/"
% sys.version_info[:2])
EditorWindow.help_url = _get_dochome()
self.flist = flist
root = root or flist.root
self.root = root
Expand Down
46 changes: 46 additions & 0 deletions Lib/idlelib/help.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,12 @@
copy_strip - Copy the text part of idle.html to help.html while rstripping each line.

show_idlehelp - Create HelpWindow. Called in EditorWindow.help_dialog.

_get_dochome() - Return path to docs on user's system if present,
otherwise return link to docs.python.org.
"""
import os
import sys
from html.parser import HTMLParser
from os.path import abspath, dirname, isfile, join
from platform import python_version
Expand Down Expand Up @@ -289,6 +294,47 @@ def show_idlehelp(parent):
return HelpWindow(parent, filename, 'IDLE Doc (%s)' % python_version())


def _get_dochome():
"Return path to local docs if present, otherwise link to docs.python.org."

dochome = os.path.join(sys.base_prefix, 'Doc', 'index.html')
if sys.platform.count('linux'):
# look for html docs in a couple of standard places
pyver = 'python-docs-' + '%s.%s.%s' % sys.version_info[:3]
if os.path.isdir('/var/www/html/python/'): # rpm package manager
dochome = '/var/www/html/python/index.html'
else:
basepath = '/usr/share/doc/' # dnf/apt package managers
dochome = os.path.join(basepath, pyver, 'Doc', 'index.html')

elif sys.platform[:3] == 'win':
import winreg # Windows only, block only executed once.
docfile = ''
KEY = (rf"Software\Python\PythonCore\{sys.winver}"
r"\Help\Main Python Documentation")
try:
docfile = winreg.QueryValue(winreg.HKEY_CURRENT_USER, KEY)
except FileNotFoundError:
try:
docfile = winreg.QueryValue(winreg.HKEY_LOCAL_MACHINE, KEY)
except FileNotFoundError:
pass
if os.path.isfile(docfile):
dochome = docfile
elif sys.platform == 'darwin':
# documentation may be stored inside a python framework
dochome = os.path.join(sys.base_prefix,
'Resources/English.lproj/Documentation/index.html')
dochome = os.path.normpath(dochome)
if os.path.isfile(dochome):
if sys.platform == 'darwin':
# Safari requires real file:-URLs
return 'file://' + dochome
return dochome
else:
return "https://docs.python.org/%d.%d/" % sys.version_info[:2]


if __name__ == '__main__':
from unittest import main
main('idlelib.idle_test.test_help', verbosity=2, exit=False)
Expand Down
16 changes: 16 additions & 0 deletions Lib/test/test_capi/test_opt.py
Original file line number Diff line number Diff line change
Expand Up @@ -2501,6 +2501,22 @@ def testfunc(n):
# For now... until we constant propagate it away.
self.assertIn("_BINARY_OP", uops)

def test_reference_tracking_across_call_doesnt_crash(self):

def f1():
for _ in range(TIER2_THRESHOLD + 1):
# Choose a value that won't occur elsewhere to avoid sharing
str("value that won't occur elsewhere to avoid sharing")

f1()

def f2():
for _ in range(TIER2_THRESHOLD + 1):
# Choose a value that won't occur elsewhere to avoid sharing
tuple((31, -17, 25, "won't occur elsewhere"))

f2()


def global_identity(x):
return x
Expand Down
4 changes: 2 additions & 2 deletions Misc/NEWS.d/3.13.0a5.rst
Original file line number Diff line number Diff line change
Expand Up @@ -742,8 +742,8 @@ Add ``windows_31j`` to aliases for ``cp932`` codec
.. nonce: fv35wU
.. section: Library

:func:`functools.partial`s of :func:`repr` has been improved to include the
:term:`module` name. Patched by Furkan Onder and Anilyka Barry.
Always include the :term:`module` name in the :func:`repr` of
:func:`functools.partial` objects. Patch by Furkan Onder and Anilyka Barry.

..

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix a bug in the JIT optimizer when round-tripping strings and tuples.
13 changes: 8 additions & 5 deletions Python/optimizer_bytecodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -762,9 +762,8 @@ dummy_func(void) {
}

op(_RETURN_VALUE, (retval -- res)) {
// We wrap and unwrap the value to mimic PyStackRef_MakeHeapSafe
// in bytecodes.c
JitOptRef temp = PyJitRef_Wrap(PyJitRef_Unwrap(retval));
// Mimics PyStackRef_MakeHeapSafe in the interpreter.
JitOptRef temp = PyJitRef_StripReferenceInfo(retval);
DEAD(retval);
SAVE_STACK();
ctx->frame->stack_pointer = stack_pointer;
Expand Down Expand Up @@ -925,7 +924,9 @@ dummy_func(void) {
op(_CALL_STR_1, (unused, unused, arg -- res)) {
if (sym_matches_type(arg, &PyUnicode_Type)) {
// e.g. str('foo') or str(foo) where foo is known to be a string
res = arg;
// Note: we must strip the reference information because it goes
// through str() which strips the reference information from it.
res = PyJitRef_StripReferenceInfo(arg);
}
else {
res = sym_new_type(ctx, &PyUnicode_Type);
Expand Down Expand Up @@ -1065,7 +1066,9 @@ dummy_func(void) {
op(_CALL_TUPLE_1, (callable, null, arg -- res)) {
if (sym_matches_type(arg, &PyTuple_Type)) {
// e.g. tuple((1, 2)) or tuple(foo) where foo is known to be a tuple
res = arg;
// Note: we must strip the reference information because it goes
// through tuple() which strips the reference information from it.
res = PyJitRef_StripReferenceInfo(arg);
}
else {
res = sym_new_type(ctx, &PyTuple_Type);
Expand Down
6 changes: 3 additions & 3 deletions Python/optimizer_cases.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 27 additions & 0 deletions Tools/peg_generator/.ruff.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
extend = "../../.ruff.toml" # Inherit the project-wide settings

extend-exclude = [
# Generated files:
"Tools/peg_generator/pegen/grammar_parser.py",
]

[lint]
select = [
"F", # pyflakes
"I", # isort
"UP", # pyupgrade
"RUF100", # Ban unused `# noqa` comments
"PGH004", # Ban blanket `# noqa` comments (only ignore specific error codes)
]
ignore = [
# Use PEP-604 unions rather than tuples for isinstance() checks.
# Makes code slower and more verbose. https://github.com/astral-sh/ruff/issues/7871.
"UP038",
]
unfixable = [
# The autofixes sometimes do the wrong things for these;
# it's better to have to manually look at the code and see how it needs fixing
"F841", # Detects unused variables
"F601", # Detects dictionaries that have duplicate keys
"F602", # Also detects dictionaries that have duplicate keys
]
7 changes: 3 additions & 4 deletions Tools/peg_generator/pegen/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import time
import token
import traceback
from typing import Tuple

from pegen.grammar import Grammar
from pegen.parser import Parser
Expand All @@ -21,7 +20,7 @@

def generate_c_code(
args: argparse.Namespace,
) -> Tuple[Grammar, Parser, Tokenizer, ParserGenerator]:
) -> tuple[Grammar, Parser, Tokenizer, ParserGenerator]:
from pegen.build import build_c_parser_and_generator

verbose = args.verbose
Expand Down Expand Up @@ -50,7 +49,7 @@ def generate_c_code(

def generate_python_code(
args: argparse.Namespace,
) -> Tuple[Grammar, Parser, Tokenizer, ParserGenerator]:
) -> tuple[Grammar, Parser, Tokenizer, ParserGenerator]:
from pegen.build import build_python_parser_and_generator

verbose = args.verbose
Expand Down Expand Up @@ -188,7 +187,7 @@ def main() -> None:


if __name__ == "__main__":
if sys.version_info < (3, 8):
if sys.version_info < (3, 8): # noqa: UP036
print("ERROR: using pegen requires at least Python 3.8!", file=sys.stderr)
sys.exit(1)
main()
18 changes: 9 additions & 9 deletions Tools/peg_generator/pegen/ast_dump.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,17 @@
TODO: Remove the above-described hack.
"""

from typing import Any, Optional, Tuple
from typing import Any


def ast_dump(
node: Any,
annotate_fields: bool = True,
include_attributes: bool = False,
*,
indent: Optional[str] = None,
indent: str | None = None,
) -> str:
def _format(node: Any, level: int = 0) -> Tuple[str, bool]:
def _format(node: Any, level: int = 0) -> tuple[str, bool]:
if indent is not None:
level += 1
prefix = "\n" + indent * level
Expand All @@ -41,7 +41,7 @@ def _format(node: Any, level: int = 0) -> Tuple[str, bool]:
value, simple = _format(value, level)
allsimple = allsimple and simple
if keywords:
args.append("%s=%s" % (name, value))
args.append(f"{name}={value}")
else:
args.append(value)
if include_attributes and node._attributes:
Expand All @@ -54,16 +54,16 @@ def _format(node: Any, level: int = 0) -> Tuple[str, bool]:
continue
value, simple = _format(value, level)
allsimple = allsimple and simple
args.append("%s=%s" % (name, value))
args.append(f"{name}={value}")
if allsimple and len(args) <= 3:
return "%s(%s)" % (node.__class__.__name__, ", ".join(args)), not args
return "%s(%s%s)" % (node.__class__.__name__, prefix, sep.join(args)), False
return "{}({})".format(node.__class__.__name__, ", ".join(args)), not args
return f"{node.__class__.__name__}({prefix}{sep.join(args)})", False
elif isinstance(node, list):
if not node:
return "[]", True
return "[%s%s]" % (prefix, sep.join(_format(x, level)[0] for x in node)), False
return f"[{prefix}{sep.join(_format(x, level)[0] for x in node)}]", False
return repr(node), True

if all(cls.__name__ != "AST" for cls in node.__class__.__mro__):
raise TypeError("expected AST, got %r" % node.__class__.__name__)
raise TypeError(f"expected AST, got {node.__class__.__name__!r}")
return _format(node)[0]
Loading
Loading