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
1 change: 1 addition & 0 deletions Doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,7 @@
# mapping unique short aliases to a base URL and a prefix.
# https://www.sphinx-doc.org/en/master/usage/extensions/extlinks.html
extlinks = {
"oss-fuzz": ("https://issues.oss-fuzz.com/issues/%s", "#%s"),
"pypi": ("https://pypi.org/project/%s/", "%s"),
"source": (SOURCE_URI, "%s"),
}
Expand Down
130 changes: 68 additions & 62 deletions Doc/faq/programming.rst

Large diffs are not rendered by default.

2 changes: 0 additions & 2 deletions Doc/installing/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
Installing Python Modules
*************************

:Email: distutils-sig@python.org

As a popular open source development project, Python has an active
supporting community of contributors and users that also make their software
available for other Python developers to use under open source license terms.
Expand Down
10 changes: 7 additions & 3 deletions Lib/_ast_unparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -738,9 +738,13 @@ def visit_SetComp(self, node):

def visit_DictComp(self, node):
with self.delimit("{", "}"):
self.traverse(node.key)
self.write(": ")
self.traverse(node.value)
if node.value:
self.traverse(node.key)
self.write(": ")
self.traverse(node.value)
else:
self.write("**")
self.traverse(node.key)
for gen in node.generators:
self.traverse(gen)

Expand Down
2 changes: 2 additions & 0 deletions Lib/test/test_future_stmt/test_future.py
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,8 @@ def test_annotations(self):
eq("(i ** 2 + j for i in (1, 2, 3) for j in (1, 2, 3))")
eq("{i: 0 for i in (1, 2, 3)}")
eq("{i: j for i, j in ((1, 'a'), (2, 'b'), (3, 'c'))}")
eq("{**x for x in ()}")
eq("[*x for x in ()]")
eq("[(x, y) for x, y in (a, b)]")
eq("[(x,) for x, in (a,)]")
eq("Python3 > Python2 > COBOL")
Expand Down
12 changes: 12 additions & 0 deletions Lib/test/test_listcomps.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,18 @@ def test_references___class___defined(self):
code, outputs={"res": [2]}, scopes=["module", "function"])
self._check_in_scopes(code, raises=NameError, scopes=["class"])

def test_references___classdict__(self):
code = """
class i: [__classdict__ for x in y]
"""
self._check_in_scopes(code, raises=NameError)

def test_references___conditional_annotations__(self):
code = """
class i: [__conditional_annotations__ for x in y]
"""
self._check_in_scopes(code, raises=NameError)

def test_references___class___enclosing(self):
code = """
__class__ = 2
Expand Down
5 changes: 5 additions & 0 deletions Lib/test/test_unparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,11 @@ def test_set_comprehension(self):
def test_dict_comprehension(self):
self.check_ast_roundtrip("{x: x*x for x in range(10)}")

def test_dict_comprehension_unpacking(self):
self.check_ast_roundtrip("{**x for x in ()}")
self.check_ast_roundtrip("{**x for x in range(10)}")
self.check_ast_roundtrip("[*x for x in ()]")

def test_class_decorators(self):
self.check_ast_roundtrip(class_decorator)

Expand Down
20 changes: 0 additions & 20 deletions Makefile.pre.in
Original file line number Diff line number Diff line change
Expand Up @@ -1729,9 +1729,6 @@ FROZEN_FILES_IN = \
Lib/zipimport.py \
Lib/abc.py \
Lib/codecs.py \
Lib/encodings/__init__.py \
Lib/encodings/aliases.py \
Lib/encodings/utf_8.py \
Lib/io.py \
Lib/_collections_abc.py \
Lib/_sitebuiltins.py \
Expand All @@ -1741,7 +1738,6 @@ FROZEN_FILES_IN = \
Lib/os.py \
Lib/site.py \
Lib/stat.py \
Lib/linecache.py \
Lib/importlib/util.py \
Lib/importlib/machinery.py \
Lib/runpy.py \
Expand All @@ -1758,9 +1754,6 @@ FROZEN_FILES_OUT = \
Python/frozen_modules/zipimport.h \
Python/frozen_modules/abc.h \
Python/frozen_modules/codecs.h \
Python/frozen_modules/encodings.h \
Python/frozen_modules/encodings.aliases.h \
Python/frozen_modules/encodings.utf_8.h \
Python/frozen_modules/io.h \
Python/frozen_modules/_collections_abc.h \
Python/frozen_modules/_sitebuiltins.h \
Expand All @@ -1770,7 +1763,6 @@ FROZEN_FILES_OUT = \
Python/frozen_modules/os.h \
Python/frozen_modules/site.h \
Python/frozen_modules/stat.h \
Python/frozen_modules/linecache.h \
Python/frozen_modules/importlib.util.h \
Python/frozen_modules/importlib.machinery.h \
Python/frozen_modules/runpy.h \
Expand Down Expand Up @@ -1810,15 +1802,6 @@ Python/frozen_modules/abc.h: Lib/abc.py $(FREEZE_MODULE_DEPS)
Python/frozen_modules/codecs.h: Lib/codecs.py $(FREEZE_MODULE_DEPS)
$(FREEZE_MODULE) codecs $(srcdir)/Lib/codecs.py Python/frozen_modules/codecs.h

Python/frozen_modules/encodings.h: Lib/encodings/__init__.py $(FREEZE_MODULE_DEPS)
$(FREEZE_MODULE) encodings $(srcdir)/Lib/encodings/__init__.py Python/frozen_modules/encodings.h

Python/frozen_modules/encodings.aliases.h: Lib/encodings/aliases.py $(FREEZE_MODULE_DEPS)
$(FREEZE_MODULE) encodings.aliases $(srcdir)/Lib/encodings/aliases.py Python/frozen_modules/encodings.aliases.h

Python/frozen_modules/encodings.utf_8.h: Lib/encodings/utf_8.py $(FREEZE_MODULE_DEPS)
$(FREEZE_MODULE) encodings.utf_8 $(srcdir)/Lib/encodings/utf_8.py Python/frozen_modules/encodings.utf_8.h

Python/frozen_modules/io.h: Lib/io.py $(FREEZE_MODULE_DEPS)
$(FREEZE_MODULE) io $(srcdir)/Lib/io.py Python/frozen_modules/io.h

Expand Down Expand Up @@ -1846,9 +1829,6 @@ Python/frozen_modules/site.h: Lib/site.py $(FREEZE_MODULE_DEPS)
Python/frozen_modules/stat.h: Lib/stat.py $(FREEZE_MODULE_DEPS)
$(FREEZE_MODULE) stat $(srcdir)/Lib/stat.py Python/frozen_modules/stat.h

Python/frozen_modules/linecache.h: Lib/linecache.py $(FREEZE_MODULE_DEPS)
$(FREEZE_MODULE) linecache $(srcdir)/Lib/linecache.py Python/frozen_modules/linecache.h

Python/frozen_modules/importlib.util.h: Lib/importlib/util.py $(FREEZE_MODULE_DEPS)
$(FREEZE_MODULE) importlib.util $(srcdir)/Lib/importlib/util.py Python/frozen_modules/importlib.util.h

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix crash in AST unparser when unparsing dict comprehension unpacking.
Found by OSS Fuzz in :oss-fuzz:`489790200`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Fix :exc:`SystemError` when ``__classdict__`` or
``__conditional_annotations__`` is in a class-scope inlined comprehension.
Found by OSS Fuzz in :oss-fuzz:`491105000`.
48 changes: 31 additions & 17 deletions Modules/_xxtestfuzz/fuzzer.c
Original file line number Diff line number Diff line change
Expand Up @@ -517,8 +517,8 @@ static int fuzz_pycompile(const char* data, size_t size) {
return 0;
}

// Need 2 bytes for parameter selection
if (size < 2) {
// Need 3 bytes for parameter selection
if (size < 3) {
return 0;
}

Expand All @@ -530,25 +530,39 @@ static int fuzz_pycompile(const char* data, size_t size) {
unsigned char optimize_idx = (unsigned char) data[1];
int optimize = optimize_vals[optimize_idx % NUM_OPTIMIZE_VALS];

// Use third byte to determine compiler flags to use.
unsigned char flags_byte = (unsigned char) data[2];
PyCompilerFlags flags = _PyCompilerFlags_INIT;
if (flags_byte & 0x01) {
flags.cf_flags |= PyCF_DONT_IMPLY_DEDENT;
}
if (flags_byte & 0x02) {
flags.cf_flags |= PyCF_ONLY_AST;
}
if (flags_byte & 0x04) {
flags.cf_flags |= PyCF_IGNORE_COOKIE;
}
if (flags_byte & 0x08) {
flags.cf_flags |= PyCF_TYPE_COMMENTS;
}
if (flags_byte & 0x10) {
flags.cf_flags |= PyCF_ALLOW_TOP_LEVEL_AWAIT;
}
if (flags_byte & 0x20) {
flags.cf_flags |= PyCF_ALLOW_INCOMPLETE_INPUT;
}
if (flags_byte & 0x40) {
flags.cf_flags |= PyCF_OPTIMIZED_AST;
}

char pycompile_scratch[MAX_PYCOMPILE_TEST_SIZE];

// Create a NUL-terminated C string from the remaining input
memcpy(pycompile_scratch, data + 2, size - 2);
memcpy(pycompile_scratch, data + 3, size - 3);
// Put a NUL terminator just after the copied data. (Space was reserved already.)
pycompile_scratch[size - 2] = '\0';

// XXX: instead of always using NULL for the `flags` value to
// `Py_CompileStringExFlags`, there are many flags that conditionally
// change parser behavior:
//
// #define PyCF_TYPE_COMMENTS 0x1000
// #define PyCF_ALLOW_TOP_LEVEL_AWAIT 0x2000
// #define PyCF_ONLY_AST 0x0400
//
// It would be good to test various combinations of these, too.
PyCompilerFlags *flags = NULL;

PyObject *result = Py_CompileStringExFlags(pycompile_scratch, "<fuzz input>", start, flags, optimize);
pycompile_scratch[size - 3] = '\0';

PyObject *result = Py_CompileStringExFlags(pycompile_scratch, "<fuzz input>", start, &flags, optimize);
if (result == NULL) {
/* Compilation failed, most likely from a syntax error. If it was a
SystemError we abort. There's no non-bug reason to raise a
Expand Down
4 changes: 2 additions & 2 deletions Modules/getpath.py
Original file line number Diff line number Diff line change
Expand Up @@ -776,9 +776,9 @@ def search_up(prefix, *landmarks, test=isfile):
# Warn if the standard library is missing, unless pythonpath_was_set was set, as
# that skips parts of the stdlib directories calculation — assume the provided
# pythonpath is correct. This is how subinterpreters initialize the path for eg.
if not py_setpath and not pythonpath_was_set and (not stdlib_zip or not isfile(stdlib_zip)):
if not py_setpath and not pythonpath_was_set:
home_hint = f"The Python 'home' directory was set to {home!r}, is this correct?"
if not stdlib_dir or not isdir(stdlib_dir):
if (not stdlib_zip or not isfile(stdlib_zip)) and (not stdlib_dir or not isdir(stdlib_dir)):
hint = home_hint if home else f'sys.prefix is set to {prefix}, is this correct?'
warn('WARN: Could not find the standard library directory! ' + hint)
elif not platstdlib_dir or not isdir(platstdlib_dir):
Expand Down
25 changes: 14 additions & 11 deletions Objects/typeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -647,7 +647,6 @@ clear_tp_bases(PyTypeObject *self, int final)
static inline PyObject *
lookup_tp_mro(PyTypeObject *self)
{
ASSERT_NEW_TYPE_OR_LOCKED(self);
return self->tp_mro;
}

Expand All @@ -664,8 +663,19 @@ set_tp_mro(PyTypeObject *self, PyObject *mro, int initial)
/* Other checks are done via set_tp_bases. */
_Py_SetImmortal(mro);
}
else {
PyUnstable_Object_EnableDeferredRefcount(mro);
}
}
if (!initial) {
type_lock_prevent_release();
types_stop_world();
}
self->tp_mro = mro;
if (!initial) {
types_start_world();
type_lock_allow_release();
}
}

static inline void
Expand Down Expand Up @@ -1728,18 +1738,11 @@ static PyObject *
type_get_mro(PyObject *tp, void *Py_UNUSED(closure))
{
PyTypeObject *type = PyTypeObject_CAST(tp);
PyObject *mro;

BEGIN_TYPE_LOCK();
mro = lookup_tp_mro(type);
PyObject *mro = lookup_tp_mro(type);
if (mro == NULL) {
mro = Py_None;
} else {
Py_INCREF(mro);
Py_RETURN_NONE;
}

END_TYPE_LOCK();
return mro;
return Py_NewRef(mro);
}

static PyTypeObject *find_best_base(PyObject *);
Expand Down
20 changes: 0 additions & 20 deletions PCbuild/_freeze_module.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -310,21 +310,6 @@
<IntFile>$(IntDir)codecs.g.h</IntFile>
<OutFile>$(GeneratedFrozenModulesDir)Python\frozen_modules\codecs.h</OutFile>
</None>
<None Include="..\Lib\encodings\__init__.py">
<ModName>encodings</ModName>
<IntFile>$(IntDir)encodings.g.h</IntFile>
<OutFile>$(GeneratedFrozenModulesDir)Python\frozen_modules\encodings.h</OutFile>
</None>
<None Include="..\Lib\encodings\aliases.py">
<ModName>encodings.aliases</ModName>
<IntFile>$(IntDir)encodings.aliases.g.h</IntFile>
<OutFile>$(GeneratedFrozenModulesDir)Python\frozen_modules\encodings.aliases.h</OutFile>
</None>
<None Include="..\Lib\encodings\utf_8.py">
<ModName>encodings.utf_8</ModName>
<IntFile>$(IntDir)encodings.utf_8.g.h</IntFile>
<OutFile>$(GeneratedFrozenModulesDir)Python\frozen_modules\encodings.utf_8.h</OutFile>
</None>
<None Include="..\Lib\io.py">
<ModName>io</ModName>
<IntFile>$(IntDir)io.g.h</IntFile>
Expand Down Expand Up @@ -370,11 +355,6 @@
<IntFile>$(IntDir)stat.g.h</IntFile>
<OutFile>$(GeneratedFrozenModulesDir)Python\frozen_modules\stat.h</OutFile>
</None>
<None Include="..\Lib\linecache.py">
<ModName>linecache</ModName>
<IntFile>$(IntDir)linecache.g.h</IntFile>
<OutFile>$(GeneratedFrozenModulesDir)Python\frozen_modules\linecache.h</OutFile>
</None>
<None Include="..\Lib\importlib\util.py">
<ModName>importlib.util</ModName>
<IntFile>$(IntDir)importlib.util.g.h</IntFile>
Expand Down
12 changes: 0 additions & 12 deletions PCbuild/_freeze_module.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -537,15 +537,6 @@
<None Include="..\Lib\codecs.py">
<Filter>Python Files</Filter>
</None>
<None Include="..\Lib\encodings\__init__.py">
<Filter>Python Files</Filter>
</None>
<None Include="..\Lib\encodings\aliases.py">
<Filter>Python Files</Filter>
</None>
<None Include="..\Lib\encodings\utf_8.py">
<Filter>Python Files</Filter>
</None>
<None Include="..\Lib\io.py">
<Filter>Python Files</Filter>
</None>
Expand Down Expand Up @@ -573,9 +564,6 @@
<None Include="..\Lib\stat.py">
<Filter>Python Files</Filter>
</None>
<None Include="..\Lib\linecache.py">
<Filter>Python Files</Filter>
</None>
<None Include="..\Lib\importlib\util.py">
<Filter>Python Files</Filter>
</None>
Expand Down
12 changes: 9 additions & 3 deletions Python/ast_unparse.c
Original file line number Diff line number Diff line change
Expand Up @@ -464,9 +464,15 @@ static int
append_ast_dictcomp(PyUnicodeWriter *writer, expr_ty e)
{
APPEND_CHAR('{');
APPEND_EXPR(e->v.DictComp.key, PR_TEST);
APPEND_STR(": ");
APPEND_EXPR(e->v.DictComp.value, PR_TEST);
if (e->v.DictComp.value) {
APPEND_EXPR(e->v.DictComp.key, PR_TEST);
APPEND_STR(": ");
APPEND_EXPR(e->v.DictComp.value, PR_TEST);
}
else {
APPEND_STR("**");
APPEND_EXPR(e->v.DictComp.key, PR_TEST);
}
APPEND(comprehensions, e->v.DictComp.generators);
APPEND_CHAR_FINISH('}');
}
Expand Down
10 changes: 0 additions & 10 deletions Python/frozen.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,6 @@
#include "frozen_modules/zipimport.h"
#include "frozen_modules/abc.h"
#include "frozen_modules/codecs.h"
#include "frozen_modules/encodings.h"
#include "frozen_modules/encodings.aliases.h"
#include "frozen_modules/encodings.utf_8.h"
#include "frozen_modules/io.h"
#include "frozen_modules/_collections_abc.h"
#include "frozen_modules/_sitebuiltins.h"
Expand All @@ -58,7 +55,6 @@
#include "frozen_modules/os.h"
#include "frozen_modules/site.h"
#include "frozen_modules/stat.h"
#include "frozen_modules/linecache.h"
#include "frozen_modules/importlib.util.h"
#include "frozen_modules/importlib.machinery.h"
#include "frozen_modules/runpy.h"
Expand All @@ -80,9 +76,6 @@ static const struct _frozen stdlib_modules[] = {
/* stdlib - startup, without site (python -S) */
{"abc", _Py_M__abc, (int)sizeof(_Py_M__abc), false},
{"codecs", _Py_M__codecs, (int)sizeof(_Py_M__codecs), false},
{"encodings", _Py_M__encodings, (int)sizeof(_Py_M__encodings), true},
{"encodings.aliases", _Py_M__encodings_aliases, (int)sizeof(_Py_M__encodings_aliases), false},
{"encodings.utf_8", _Py_M__encodings_utf_8, (int)sizeof(_Py_M__encodings_utf_8), false},
{"io", _Py_M__io, (int)sizeof(_Py_M__io), false},

/* stdlib - startup, with site */
Expand All @@ -95,9 +88,6 @@ static const struct _frozen stdlib_modules[] = {
{"site", _Py_M__site, (int)sizeof(_Py_M__site), false},
{"stat", _Py_M__stat, (int)sizeof(_Py_M__stat), false},

/* pythonrun - interactive */
{"linecache", _Py_M__linecache, (int)sizeof(_Py_M__linecache), false},

/* runpy - run module with -m */
{"importlib.util", _Py_M__importlib_util, (int)sizeof(_Py_M__importlib_util), false},
{"importlib.machinery", _Py_M__importlib_machinery, (int)sizeof(_Py_M__importlib_machinery), false},
Expand Down
Loading
Loading