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
7 changes: 7 additions & 0 deletions Doc/whatsnew/3.15.rst
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,13 @@ New modules
Improved modules
================

difflib
-------

* Improved the styling of HTML diff pages generated by the :class:`difflib.HtmlDiff`
class, and migrated the output to the HTML5 standard.
(Contributed by Jiahao Li in :gh:`134580`.)

ssl
---

Expand Down
3 changes: 3 additions & 0 deletions Include/internal/pycore_interp_structs.h
Original file line number Diff line number Diff line change
Expand Up @@ -677,8 +677,11 @@ struct _Py_interp_cached_objects {

/* object.__reduce__ */
PyObject *objreduce;
#ifndef Py_GIL_DISABLED
/* resolve_slotdups() */
PyObject *type_slots_pname;
pytype_slotdef *type_slots_ptrs[MAX_EQUIV];
#endif

/* TypeVar and related types */
PyTypeObject *generic_type;
Expand Down
2 changes: 1 addition & 1 deletion Include/internal/pycore_object.h
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ extern int _PyDict_CheckConsistency(PyObject *mp, int check_content);
// Fast inlined version of PyType_HasFeature()
static inline int
_PyType_HasFeature(PyTypeObject *type, unsigned long feature) {
return ((FT_ATOMIC_LOAD_ULONG_RELAXED(type->tp_flags) & feature) != 0);
return ((type->tp_flags) & feature) != 0;
}

extern void _PyType_InitCache(PyInterpreterState *interp);
Expand Down
1 change: 0 additions & 1 deletion Include/internal/pycore_typeobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,6 @@ extern int _PyType_AddMethod(PyTypeObject *, PyMethodDef *);
extern void _PyType_SetFlagsRecursive(PyTypeObject *self, unsigned long mask,
unsigned long flags);

extern unsigned int _PyType_GetVersionForCurrentState(PyTypeObject *tp);
PyAPI_FUNC(void) _PyType_SetVersion(PyTypeObject *tp, unsigned int version);
PyTypeObject *_PyType_LookupByVersion(unsigned int version);

Expand Down
12 changes: 7 additions & 5 deletions Include/object.h
Original file line number Diff line number Diff line change
Expand Up @@ -620,6 +620,12 @@ given type object has a specified feature.
#define Py_TPFLAGS_HAVE_FINALIZE (1UL << 0)
#define Py_TPFLAGS_HAVE_VERSION_TAG (1UL << 18)

// Flag values for ob_flags (16 bits available, if SIZEOF_VOID_P > 4).
#define _Py_IMMORTAL_FLAGS (1 << 0)
#define _Py_STATICALLY_ALLOCATED_FLAG (1 << 2)
#if defined(Py_GIL_DISABLED) && defined(Py_DEBUG)
#define _Py_TYPE_REVEALED_FLAG (1 << 3)
#endif

#define Py_CONSTANT_NONE 0
#define Py_CONSTANT_FALSE 1
Expand Down Expand Up @@ -776,11 +782,7 @@ PyType_HasFeature(PyTypeObject *type, unsigned long feature)
// PyTypeObject is opaque in the limited C API
flags = PyType_GetFlags(type);
#else
# ifdef Py_GIL_DISABLED
flags = _Py_atomic_load_ulong_relaxed(&type->tp_flags);
# else
flags = type->tp_flags;
# endif
flags = type->tp_flags;
#endif
return ((flags & feature) != 0);
}
Expand Down
3 changes: 0 additions & 3 deletions Include/refcount.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,6 @@ immortal. The latter should be the only instances that require
cleanup during runtime finalization.
*/

#define _Py_STATICALLY_ALLOCATED_FLAG 4
#define _Py_IMMORTAL_FLAGS 1

#if SIZEOF_VOID_P > 4
/*
In 64+ bit systems, any object whose 32 bit reference count is >= 2**31
Expand Down
50 changes: 36 additions & 14 deletions Lib/difflib.py
Original file line number Diff line number Diff line change
Expand Up @@ -1615,16 +1615,13 @@ def _line_pair_iterator():


_file_template = """
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html>

<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type"
content="text/html; charset=%(charset)s" />
<title></title>
<style type="text/css">%(styles)s
<meta charset="%(charset)s">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Diff comparison</title>
<style>%(styles)s
</style>
</head>

Expand All @@ -1636,20 +1633,45 @@ def _line_pair_iterator():

_styles = """
:root {color-scheme: light dark}
table.diff {font-family: Menlo, Consolas, Monaco, Liberation Mono, Lucida Console, monospace; border:medium}
.diff_header {background-color:#e0e0e0}
td.diff_header {text-align:right}
.diff_next {background-color:#c0c0c0}
table.diff {
font-family: Menlo, Consolas, Monaco, Liberation Mono, Lucida Console, monospace;
border: medium;
}
.diff_header {
background-color: #e0e0e0;
font-weight: bold;
}
td.diff_header {
text-align: right;
padding: 0 8px;
}
.diff_next {
background-color: #c0c0c0;
padding: 4px 0;
}
.diff_add {background-color:palegreen}
.diff_chg {background-color:#ffff77}
.diff_sub {background-color:#ffaaaa}
table.diff[summary="Legends"] {
margin-top: 20px;
border: 1px solid #ccc;
}
table.diff[summary="Legends"] th {
background-color: #e0e0e0;
padding: 4px 8px;
}
table.diff[summary="Legends"] td {
padding: 4px 8px;
}

@media (prefers-color-scheme: dark) {
.diff_header {background-color:#666}
.diff_next {background-color:#393939}
.diff_add {background-color:darkgreen}
.diff_chg {background-color:#847415}
.diff_sub {background-color:darkred}
table.diff[summary="Legends"] {border-color:#555}
table.diff[summary="Legends"] th{background-color:#666}
}"""

_table_template = """
Expand Down Expand Up @@ -1692,7 +1714,7 @@ class HtmlDiff(object):
make_table -- generates HTML for a single side by side table
make_file -- generates complete HTML file with a single side by side table

See tools/scripts/diff.py for an example usage of this class.
See Doc/includes/diff.py for an example usage of this class.
"""

_file_template = _file_template
Expand Down
28 changes: 28 additions & 0 deletions Lib/test/test_descr.py
Original file line number Diff line number Diff line change
Expand Up @@ -4114,6 +4114,34 @@ class E(D):
else:
self.fail("shouldn't be able to create inheritance cycles")

def test_assign_bases_many_subclasses(self):
# This is intended to check that typeobject.c:queue_slot_update() can
# handle updating many subclasses when a slot method is re-assigned.
class A:
x = 'hello'
def __call__(self):
return 123
def __getitem__(self, index):
return None

class X:
x = 'bye'

class B(A):
pass

subclasses = []
for i in range(1000):
sc = type(f'Sub{i}', (B,), {})
subclasses.append(sc)

self.assertEqual(subclasses[0]()(), 123)
self.assertEqual(subclasses[0]().x, 'hello')
B.__bases__ = (X,)
with self.assertRaises(TypeError):
subclasses[0]()()
self.assertEqual(subclasses[0]().x, 'bye')

def test_builtin_bases(self):
# Make sure all the builtin types can have their base queried without
# segfaulting. See issue #5787.
Expand Down
6 changes: 3 additions & 3 deletions Lib/test/test_difflib.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,21 +255,21 @@ def test_make_file_default_charset(self):
html_diff = difflib.HtmlDiff()
output = html_diff.make_file(patch914575_from1.splitlines(),
patch914575_to1.splitlines())
self.assertIn('content="text/html; charset=utf-8"', output)
self.assertIn('charset="utf-8"', output)

def test_make_file_iso88591_charset(self):
html_diff = difflib.HtmlDiff()
output = html_diff.make_file(patch914575_from1.splitlines(),
patch914575_to1.splitlines(),
charset='iso-8859-1')
self.assertIn('content="text/html; charset=iso-8859-1"', output)
self.assertIn('charset="iso-8859-1"', output)

def test_make_file_usascii_charset_with_nonascii_input(self):
html_diff = difflib.HtmlDiff()
output = html_diff.make_file(patch914575_nonascii_from1.splitlines(),
patch914575_nonascii_to1.splitlines(),
charset='us-ascii')
self.assertIn('content="text/html; charset=us-ascii"', output)
self.assertIn('charset="us-ascii"', output)
self.assertIn('&#305;mpl&#305;c&#305;t', output)

class TestDiffer(unittest.TestCase):
Expand Down
48 changes: 35 additions & 13 deletions Lib/test/test_difflib_expect.html
Original file line number Diff line number Diff line change
@@ -1,29 +1,51 @@

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html>

<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type"
content="text/html; charset=utf-8" />
<title></title>
<style type="text/css">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Diff comparison</title>
<style>
:root {color-scheme: light dark}
table.diff {font-family: Menlo, Consolas, Monaco, Liberation Mono, Lucida Console, monospace; border:medium}
.diff_header {background-color:#e0e0e0}
td.diff_header {text-align:right}
.diff_next {background-color:#c0c0c0}
table.diff {
font-family: Menlo, Consolas, Monaco, Liberation Mono, Lucida Console, monospace;
border: medium;
}
.diff_header {
background-color: #e0e0e0;
font-weight: bold;
}
td.diff_header {
text-align: right;
padding: 0 8px;
}
.diff_next {
background-color: #c0c0c0;
padding: 4px 0;
}
.diff_add {background-color:palegreen}
.diff_chg {background-color:#ffff77}
.diff_sub {background-color:#ffaaaa}
table.diff[summary="Legends"] {
margin-top: 20px;
border: 1px solid #ccc;
}
table.diff[summary="Legends"] th {
background-color: #e0e0e0;
padding: 4px 8px;
}
table.diff[summary="Legends"] td {
padding: 4px 8px;
}

@media (prefers-color-scheme: dark) {
.diff_header {background-color:#666}
.diff_next {background-color:#393939}
.diff_add {background-color:darkgreen}
.diff_chg {background-color:#847415}
.diff_sub {background-color:darkred}
table.diff[summary="Legends"] {border-color:#555}
table.diff[summary="Legends"] th{background-color:#666}
}
</style>
</head>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
In the free-threaded build, avoid data races caused by updating type slots
or type flags after the type was initially created. For those (typically
rare) cases, use the stop-the-world mechanism. Remove the use of atomics
when reading or writing type flags. The use of atomics is not sufficient to
avoid races (since flags are sometimes read without a lock and without
atomics) and are no longer required.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Improved the styling of HTML diff pages generated by the
:class:`difflib.HtmlDiff` class, and migrated the output to the HTML5
standard.
Loading
Loading