Merge branch 'master' of https://github.com/python/cpython into tupleify-ga
This commit is contained in:
commit
7a3cfa41a9
|
@ -112,14 +112,15 @@ The module :mod:`curses` defines the following functions:
|
|||
.. function:: color_content(color_number)
|
||||
|
||||
Return the intensity of the red, green, and blue (RGB) components in the color
|
||||
*color_number*, which must be between ``0`` and :const:`COLORS`. Return a 3-tuple,
|
||||
*color_number*, which must be between ``0`` and ``COLORS - 1``. Return a 3-tuple,
|
||||
containing the R,G,B values for the given color, which will be between
|
||||
``0`` (no component) and ``1000`` (maximum amount of component).
|
||||
|
||||
|
||||
.. function:: color_pair(color_number)
|
||||
.. function:: color_pair(pair_number)
|
||||
|
||||
Return the attribute value for displaying text in the specified color. This
|
||||
Return the attribute value for displaying text in the specified color pair.
|
||||
Only the first 256 color pairs are supported. This
|
||||
attribute value can be combined with :const:`A_STANDOUT`, :const:`A_REVERSE`,
|
||||
and the other :const:`A_\*` attributes. :func:`pair_number` is the counterpart
|
||||
to this function.
|
||||
|
@ -287,7 +288,7 @@ The module :mod:`curses` defines the following functions:
|
|||
Change the definition of a color, taking the number of the color to be changed
|
||||
followed by three RGB values (for the amounts of red, green, and blue
|
||||
components). The value of *color_number* must be between ``0`` and
|
||||
:const:`COLORS`. Each of *r*, *g*, *b*, must be a value between ``0`` and
|
||||
`COLORS - 1`. Each of *r*, *g*, *b*, must be a value between ``0`` and
|
||||
``1000``. When :func:`init_color` is used, all occurrences of that color on the
|
||||
screen immediately change to the new definition. This function is a no-op on
|
||||
most terminals; it is active only if :func:`can_change_color` returns ``True``.
|
||||
|
@ -300,7 +301,8 @@ The module :mod:`curses` defines the following functions:
|
|||
color number. The value of *pair_number* must be between ``1`` and
|
||||
``COLOR_PAIRS - 1`` (the ``0`` color pair is wired to white on black and cannot
|
||||
be changed). The value of *fg* and *bg* arguments must be between ``0`` and
|
||||
:const:`COLORS`. If the color-pair was previously initialized, the screen is
|
||||
``COLORS - 1``, or, after calling :func:`use_default_colors`, ``-1``.
|
||||
If the color-pair was previously initialized, the screen is
|
||||
refreshed and all occurrences of that color-pair are changed to the new
|
||||
definition.
|
||||
|
||||
|
@ -450,7 +452,7 @@ The module :mod:`curses` defines the following functions:
|
|||
.. function:: pair_content(pair_number)
|
||||
|
||||
Return a tuple ``(fg, bg)`` containing the colors for the requested color pair.
|
||||
The value of *pair_number* must be between ``1`` and ``COLOR_PAIRS - 1``.
|
||||
The value of *pair_number* must be between ``0`` and ``COLOR_PAIRS - 1``.
|
||||
|
||||
|
||||
.. function:: pair_number(attr)
|
||||
|
|
|
@ -198,7 +198,7 @@ However, for reading convenience, most of the examples show sorted sequences.
|
|||
|
||||
.. versionadded:: 3.6
|
||||
|
||||
.. versionchanged:: 3.8
|
||||
.. versionchanged:: 3.10
|
||||
Added support for *weights*.
|
||||
|
||||
.. function:: median(data)
|
||||
|
|
|
@ -426,9 +426,11 @@ Optimizations
|
|||
average.
|
||||
(Contributed by Victor Stinner in :issue:`41006`.)
|
||||
|
||||
* The ``LOAD_ATTR`` instruction now uses new "per opcode cache" mechanism.
|
||||
It is about 36% faster now. (Contributed by Pablo Galindo and Yury Selivanov
|
||||
in :issue:`42093`, based on ideas implemented originally in PyPy and MicroPython.)
|
||||
* The ``LOAD_ATTR`` instruction now uses new "per opcode cache" mechanism. It
|
||||
is about 36% faster now. This makes optimized ``LOAD_ATTR`` instructions the
|
||||
current most performance attribute access method (faster than slots).
|
||||
(Contributed by Pablo Galindo and Yury Selivanov in :issue:`42093`, based on
|
||||
ideas implemented originally in PyPy and MicroPython.)
|
||||
|
||||
* When building Python with ``--enable-optimizations`` now
|
||||
``-fno-semantic-interposition`` is added to both the compile and link line.
|
||||
|
|
|
@ -580,18 +580,23 @@ star_targets[expr_ty]:
|
|||
| a=star_target !',' { a }
|
||||
| a=star_target b=(',' c=star_target { c })* [','] {
|
||||
_Py_Tuple(CHECK(asdl_expr_seq*, _PyPegen_seq_insert_in_front(p, a, b)), Store, EXTRA) }
|
||||
star_targets_seq[asdl_expr_seq*]: a[asdl_expr_seq*]=','.star_target+ [','] { a }
|
||||
star_targets_list_seq[asdl_expr_seq*]: a[asdl_expr_seq*]=','.star_target+ [','] { a }
|
||||
star_targets_tuple_seq[asdl_expr_seq*]:
|
||||
| a=star_target b=(',' c=star_target { c })+ [','] { (asdl_expr_seq*) _PyPegen_seq_insert_in_front(p, a, b) }
|
||||
| a=star_target ',' { (asdl_expr_seq*) _PyPegen_singleton_seq(p, a) }
|
||||
star_target[expr_ty] (memo):
|
||||
| '*' a=(!'*' star_target) {
|
||||
_Py_Starred(CHECK(expr_ty, _PyPegen_set_expr_context(p, a, Store)), Store, EXTRA) }
|
||||
| target_with_star_atom
|
||||
target_with_star_atom[expr_ty] (memo):
|
||||
| a=t_primary '.' b=NAME !t_lookahead { _Py_Attribute(a, b->v.Name.id, Store, EXTRA) }
|
||||
| a=t_primary '[' b=slices ']' !t_lookahead { _Py_Subscript(a, b, Store, EXTRA) }
|
||||
| star_atom
|
||||
star_atom[expr_ty]:
|
||||
| a=NAME { _PyPegen_set_expr_context(p, a, Store) }
|
||||
| '(' a=star_target ')' { _PyPegen_set_expr_context(p, a, Store) }
|
||||
| '(' a=[star_targets_seq] ')' { _Py_Tuple(a, Store, EXTRA) }
|
||||
| '[' a=[star_targets_seq] ']' { _Py_List(a, Store, EXTRA) }
|
||||
| '(' a=target_with_star_atom ')' { _PyPegen_set_expr_context(p, a, Store) }
|
||||
| '(' a=[star_targets_tuple_seq] ')' { _Py_Tuple(a, Store, EXTRA) }
|
||||
| '[' a=[star_targets_list_seq] ']' { _Py_List(a, Store, EXTRA) }
|
||||
|
||||
single_target[expr_ty]:
|
||||
| single_subscript_attribute_target
|
||||
|
|
|
@ -174,7 +174,7 @@ def libc_ver(executable=None, lib='', version='', chunksize=16384):
|
|||
The file is read and scanned in chunks of chunksize bytes.
|
||||
|
||||
"""
|
||||
if executable is None:
|
||||
if not executable:
|
||||
try:
|
||||
ver = os.confstr('CS_GNU_LIBC_VERSION')
|
||||
# parse 'glibc 2.28' as ('glibc', '2.28')
|
||||
|
|
|
@ -96,6 +96,7 @@ LOG4 = _log(4.0)
|
|||
SG_MAGICCONST = 1.0 + _log(4.5)
|
||||
BPF = 53 # Number of bits in a float
|
||||
RECIP_BPF = 2 ** -BPF
|
||||
_ONE = 1
|
||||
|
||||
|
||||
class Random(_random.Random):
|
||||
|
@ -288,7 +289,7 @@ class Random(_random.Random):
|
|||
|
||||
## -------------------- integer methods -------------------
|
||||
|
||||
def randrange(self, start, stop=None, step=1):
|
||||
def randrange(self, start, stop=None, step=_ONE):
|
||||
"""Choose a random item from range(start, stop[, step]).
|
||||
|
||||
This fixes the problem with randint() which includes the
|
||||
|
@ -311,7 +312,12 @@ class Random(_random.Random):
|
|||
_warn('randrange() will raise TypeError in the future',
|
||||
DeprecationWarning, 2)
|
||||
raise ValueError("non-integer arg 1 for randrange()")
|
||||
|
||||
if stop is None:
|
||||
# We don't check for "step != 1" because it hasn't been
|
||||
# type checked and converted to an integer yet.
|
||||
if step is not _ONE:
|
||||
raise TypeError('Missing a non-None stop argument')
|
||||
if istart > 0:
|
||||
return self._randbelow(istart)
|
||||
raise ValueError("empty range for randrange()")
|
||||
|
@ -345,9 +351,9 @@ class Random(_random.Random):
|
|||
DeprecationWarning, 2)
|
||||
raise ValueError("non-integer step for randrange()")
|
||||
width = istop - istart
|
||||
if istep == 1 and width > 0:
|
||||
return istart + self._randbelow(width)
|
||||
if istep == 1:
|
||||
if width > 0:
|
||||
return istart + self._randbelow(width)
|
||||
raise ValueError("empty range for randrange() (%d, %d, %d)" % (istart, istop, width))
|
||||
|
||||
# Non-unit step argument supplied.
|
||||
|
@ -357,10 +363,8 @@ class Random(_random.Random):
|
|||
n = (width + istep + 1) // istep
|
||||
else:
|
||||
raise ValueError("zero step for randrange()")
|
||||
|
||||
if n <= 0:
|
||||
raise ValueError("empty range for randrange()")
|
||||
|
||||
return istart + istep * self._randbelow(n)
|
||||
|
||||
def randint(self, a, b):
|
||||
|
|
|
@ -69,6 +69,10 @@ def count_opcode(code, pickle):
|
|||
return n
|
||||
|
||||
|
||||
def identity(x):
|
||||
return x
|
||||
|
||||
|
||||
class UnseekableIO(io.BytesIO):
|
||||
def peek(self, *args):
|
||||
raise NotImplementedError
|
||||
|
@ -138,11 +142,12 @@ class E(C):
|
|||
def __getinitargs__(self):
|
||||
return ()
|
||||
|
||||
class H(object):
|
||||
# Simple mutable object.
|
||||
class Object:
|
||||
pass
|
||||
|
||||
# Hashable mutable key
|
||||
class K(object):
|
||||
# Hashable immutable key object containing unheshable mutable data.
|
||||
class K:
|
||||
def __init__(self, value):
|
||||
self.value = value
|
||||
|
||||
|
@ -157,10 +162,6 @@ __main__.D = D
|
|||
D.__module__ = "__main__"
|
||||
__main__.E = E
|
||||
E.__module__ = "__main__"
|
||||
__main__.H = H
|
||||
H.__module__ = "__main__"
|
||||
__main__.K = K
|
||||
K.__module__ = "__main__"
|
||||
|
||||
class myint(int):
|
||||
def __init__(self, x):
|
||||
|
@ -1496,54 +1497,182 @@ class AbstractPickleTests(unittest.TestCase):
|
|||
got = filelike.getvalue()
|
||||
self.assertEqual(expected, got)
|
||||
|
||||
def test_recursive_list(self):
|
||||
l = []
|
||||
def _test_recursive_list(self, cls, aslist=identity, minprotocol=0):
|
||||
# List containing itself.
|
||||
l = cls()
|
||||
l.append(l)
|
||||
for proto in protocols:
|
||||
for proto in range(minprotocol, pickle.HIGHEST_PROTOCOL + 1):
|
||||
s = self.dumps(l, proto)
|
||||
x = self.loads(s)
|
||||
self.assertIsInstance(x, list)
|
||||
self.assertEqual(len(x), 1)
|
||||
self.assertIs(x[0], x)
|
||||
self.assertIsInstance(x, cls)
|
||||
y = aslist(x)
|
||||
self.assertEqual(len(y), 1)
|
||||
self.assertIs(y[0], x)
|
||||
|
||||
def test_recursive_tuple_and_list(self):
|
||||
t = ([],)
|
||||
def test_recursive_list(self):
|
||||
self._test_recursive_list(list)
|
||||
|
||||
def test_recursive_list_subclass(self):
|
||||
self._test_recursive_list(MyList, minprotocol=2)
|
||||
|
||||
def test_recursive_list_like(self):
|
||||
self._test_recursive_list(REX_six, aslist=lambda x: x.items)
|
||||
|
||||
def _test_recursive_tuple_and_list(self, cls, aslist=identity, minprotocol=0):
|
||||
# Tuple containing a list containing the original tuple.
|
||||
t = (cls(),)
|
||||
t[0].append(t)
|
||||
for proto in protocols:
|
||||
for proto in range(minprotocol, pickle.HIGHEST_PROTOCOL + 1):
|
||||
s = self.dumps(t, proto)
|
||||
x = self.loads(s)
|
||||
self.assertIsInstance(x, tuple)
|
||||
self.assertEqual(len(x), 1)
|
||||
self.assertIsInstance(x[0], list)
|
||||
self.assertEqual(len(x[0]), 1)
|
||||
self.assertIs(x[0][0], x)
|
||||
self.assertIsInstance(x[0], cls)
|
||||
y = aslist(x[0])
|
||||
self.assertEqual(len(y), 1)
|
||||
self.assertIs(y[0], x)
|
||||
|
||||
# List containing a tuple containing the original list.
|
||||
t, = t
|
||||
for proto in range(minprotocol, pickle.HIGHEST_PROTOCOL + 1):
|
||||
s = self.dumps(t, proto)
|
||||
x = self.loads(s)
|
||||
self.assertIsInstance(x, cls)
|
||||
y = aslist(x)
|
||||
self.assertEqual(len(y), 1)
|
||||
self.assertIsInstance(y[0], tuple)
|
||||
self.assertEqual(len(y[0]), 1)
|
||||
self.assertIs(y[0][0], x)
|
||||
|
||||
def test_recursive_tuple_and_list(self):
|
||||
self._test_recursive_tuple_and_list(list)
|
||||
|
||||
def test_recursive_tuple_and_list_subclass(self):
|
||||
self._test_recursive_tuple_and_list(MyList, minprotocol=2)
|
||||
|
||||
def test_recursive_tuple_and_list_like(self):
|
||||
self._test_recursive_tuple_and_list(REX_six, aslist=lambda x: x.items)
|
||||
|
||||
def _test_recursive_dict(self, cls, asdict=identity, minprotocol=0):
|
||||
# Dict containing itself.
|
||||
d = cls()
|
||||
d[1] = d
|
||||
for proto in range(minprotocol, pickle.HIGHEST_PROTOCOL + 1):
|
||||
s = self.dumps(d, proto)
|
||||
x = self.loads(s)
|
||||
self.assertIsInstance(x, cls)
|
||||
y = asdict(x)
|
||||
self.assertEqual(list(y.keys()), [1])
|
||||
self.assertIs(y[1], x)
|
||||
|
||||
def test_recursive_dict(self):
|
||||
d = {}
|
||||
d[1] = d
|
||||
for proto in protocols:
|
||||
self._test_recursive_dict(dict)
|
||||
|
||||
def test_recursive_dict_subclass(self):
|
||||
self._test_recursive_dict(MyDict, minprotocol=2)
|
||||
|
||||
def test_recursive_dict_like(self):
|
||||
self._test_recursive_dict(REX_seven, asdict=lambda x: x.table)
|
||||
|
||||
def _test_recursive_tuple_and_dict(self, cls, asdict=identity, minprotocol=0):
|
||||
# Tuple containing a dict containing the original tuple.
|
||||
t = (cls(),)
|
||||
t[0][1] = t
|
||||
for proto in range(minprotocol, pickle.HIGHEST_PROTOCOL + 1):
|
||||
s = self.dumps(t, proto)
|
||||
x = self.loads(s)
|
||||
self.assertIsInstance(x, tuple)
|
||||
self.assertEqual(len(x), 1)
|
||||
self.assertIsInstance(x[0], cls)
|
||||
y = asdict(x[0])
|
||||
self.assertEqual(list(y), [1])
|
||||
self.assertIs(y[1], x)
|
||||
|
||||
# Dict containing a tuple containing the original dict.
|
||||
t, = t
|
||||
for proto in range(minprotocol, pickle.HIGHEST_PROTOCOL + 1):
|
||||
s = self.dumps(t, proto)
|
||||
x = self.loads(s)
|
||||
self.assertIsInstance(x, cls)
|
||||
y = asdict(x)
|
||||
self.assertEqual(list(y), [1])
|
||||
self.assertIsInstance(y[1], tuple)
|
||||
self.assertEqual(len(y[1]), 1)
|
||||
self.assertIs(y[1][0], x)
|
||||
|
||||
def test_recursive_tuple_and_dict(self):
|
||||
self._test_recursive_tuple_and_dict(dict)
|
||||
|
||||
def test_recursive_tuple_and_dict_subclass(self):
|
||||
self._test_recursive_tuple_and_dict(MyDict, minprotocol=2)
|
||||
|
||||
def test_recursive_tuple_and_dict_like(self):
|
||||
self._test_recursive_tuple_and_dict(REX_seven, asdict=lambda x: x.table)
|
||||
|
||||
def _test_recursive_dict_key(self, cls, asdict=identity, minprotocol=0):
|
||||
# Dict containing an immutable object (as key) containing the original
|
||||
# dict.
|
||||
d = cls()
|
||||
d[K(d)] = 1
|
||||
for proto in range(minprotocol, pickle.HIGHEST_PROTOCOL + 1):
|
||||
s = self.dumps(d, proto)
|
||||
x = self.loads(s)
|
||||
self.assertIsInstance(x, dict)
|
||||
self.assertEqual(list(x.keys()), [1])
|
||||
self.assertIs(x[1], x)
|
||||
self.assertIsInstance(x, cls)
|
||||
y = asdict(x)
|
||||
self.assertEqual(len(y.keys()), 1)
|
||||
self.assertIsInstance(list(y.keys())[0], K)
|
||||
self.assertIs(list(y.keys())[0].value, x)
|
||||
|
||||
def test_recursive_dict_key(self):
|
||||
d = {}
|
||||
k = K(d)
|
||||
d[k] = 1
|
||||
for proto in protocols:
|
||||
s = self.dumps(d, proto)
|
||||
self._test_recursive_dict_key(dict)
|
||||
|
||||
def test_recursive_dict_subclass_key(self):
|
||||
self._test_recursive_dict_key(MyDict, minprotocol=2)
|
||||
|
||||
def test_recursive_dict_like_key(self):
|
||||
self._test_recursive_dict_key(REX_seven, asdict=lambda x: x.table)
|
||||
|
||||
def _test_recursive_tuple_and_dict_key(self, cls, asdict=identity, minprotocol=0):
|
||||
# Tuple containing a dict containing an immutable object (as key)
|
||||
# containing the original tuple.
|
||||
t = (cls(),)
|
||||
t[0][K(t)] = 1
|
||||
for proto in range(minprotocol, pickle.HIGHEST_PROTOCOL + 1):
|
||||
s = self.dumps(t, proto)
|
||||
x = self.loads(s)
|
||||
self.assertIsInstance(x, dict)
|
||||
self.assertEqual(len(x.keys()), 1)
|
||||
self.assertIsInstance(list(x.keys())[0], K)
|
||||
self.assertIs(list(x.keys())[0].value, x)
|
||||
self.assertIsInstance(x, tuple)
|
||||
self.assertEqual(len(x), 1)
|
||||
self.assertIsInstance(x[0], cls)
|
||||
y = asdict(x[0])
|
||||
self.assertEqual(len(y), 1)
|
||||
self.assertIsInstance(list(y.keys())[0], K)
|
||||
self.assertIs(list(y.keys())[0].value, x)
|
||||
|
||||
# Dict containing an immutable object (as key) containing a tuple
|
||||
# containing the original dict.
|
||||
t, = t
|
||||
for proto in range(minprotocol, pickle.HIGHEST_PROTOCOL + 1):
|
||||
s = self.dumps(t, proto)
|
||||
x = self.loads(s)
|
||||
self.assertIsInstance(x, cls)
|
||||
y = asdict(x)
|
||||
self.assertEqual(len(y), 1)
|
||||
self.assertIsInstance(list(y.keys())[0], K)
|
||||
self.assertIs(list(y.keys())[0].value[0], x)
|
||||
|
||||
def test_recursive_tuple_and_dict_key(self):
|
||||
self._test_recursive_tuple_and_dict_key(dict)
|
||||
|
||||
def test_recursive_tuple_and_dict_subclass_key(self):
|
||||
self._test_recursive_tuple_and_dict_key(MyDict, minprotocol=2)
|
||||
|
||||
def test_recursive_tuple_and_dict_like_key(self):
|
||||
self._test_recursive_tuple_and_dict_key(REX_seven, asdict=lambda x: x.table)
|
||||
|
||||
def test_recursive_set(self):
|
||||
# Set containing an immutable object containing the original set.
|
||||
y = set()
|
||||
k = K(y)
|
||||
y.add(k)
|
||||
y.add(K(y))
|
||||
for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
|
||||
s = self.dumps(y, proto)
|
||||
x = self.loads(s)
|
||||
|
@ -1552,52 +1681,31 @@ class AbstractPickleTests(unittest.TestCase):
|
|||
self.assertIsInstance(list(x)[0], K)
|
||||
self.assertIs(list(x)[0].value, x)
|
||||
|
||||
def test_recursive_list_subclass(self):
|
||||
y = MyList()
|
||||
y.append(y)
|
||||
for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
|
||||
# Immutable object containing a set containing the original object.
|
||||
y, = y
|
||||
for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
|
||||
s = self.dumps(y, proto)
|
||||
x = self.loads(s)
|
||||
self.assertIsInstance(x, MyList)
|
||||
self.assertEqual(len(x), 1)
|
||||
self.assertIs(x[0], x)
|
||||
|
||||
def test_recursive_dict_subclass(self):
|
||||
d = MyDict()
|
||||
d[1] = d
|
||||
for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
|
||||
s = self.dumps(d, proto)
|
||||
x = self.loads(s)
|
||||
self.assertIsInstance(x, MyDict)
|
||||
self.assertEqual(list(x.keys()), [1])
|
||||
self.assertIs(x[1], x)
|
||||
|
||||
def test_recursive_dict_subclass_key(self):
|
||||
d = MyDict()
|
||||
k = K(d)
|
||||
d[k] = 1
|
||||
for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
|
||||
s = self.dumps(d, proto)
|
||||
x = self.loads(s)
|
||||
self.assertIsInstance(x, MyDict)
|
||||
self.assertEqual(len(list(x.keys())), 1)
|
||||
self.assertIsInstance(list(x.keys())[0], K)
|
||||
self.assertIs(list(x.keys())[0].value, x)
|
||||
self.assertIsInstance(x, K)
|
||||
self.assertIsInstance(x.value, set)
|
||||
self.assertEqual(len(x.value), 1)
|
||||
self.assertIs(list(x.value)[0], x)
|
||||
|
||||
def test_recursive_inst(self):
|
||||
i = C()
|
||||
# Mutable object containing itself.
|
||||
i = Object()
|
||||
i.attr = i
|
||||
for proto in protocols:
|
||||
s = self.dumps(i, proto)
|
||||
x = self.loads(s)
|
||||
self.assertIsInstance(x, C)
|
||||
self.assertIsInstance(x, Object)
|
||||
self.assertEqual(dir(x), dir(i))
|
||||
self.assertIs(x.attr, x)
|
||||
|
||||
def test_recursive_multi(self):
|
||||
l = []
|
||||
d = {1:l}
|
||||
i = C()
|
||||
i = Object()
|
||||
i.attr = d
|
||||
l.append(i)
|
||||
for proto in protocols:
|
||||
|
@ -1607,49 +1715,94 @@ class AbstractPickleTests(unittest.TestCase):
|
|||
self.assertEqual(len(x), 1)
|
||||
self.assertEqual(dir(x[0]), dir(i))
|
||||
self.assertEqual(list(x[0].attr.keys()), [1])
|
||||
self.assertTrue(x[0].attr[1] is x)
|
||||
self.assertIs(x[0].attr[1], x)
|
||||
|
||||
def check_recursive_collection_and_inst(self, factory):
|
||||
h = H()
|
||||
y = factory([h])
|
||||
h.attr = y
|
||||
def _test_recursive_collection_and_inst(self, factory):
|
||||
# Mutable object containing a collection containing the original
|
||||
# object.
|
||||
o = Object()
|
||||
o.attr = factory([o])
|
||||
t = type(o.attr)
|
||||
for proto in protocols:
|
||||
s = self.dumps(y, proto)
|
||||
s = self.dumps(o, proto)
|
||||
x = self.loads(s)
|
||||
self.assertIsInstance(x, type(y))
|
||||
self.assertIsInstance(x.attr, t)
|
||||
self.assertEqual(len(x.attr), 1)
|
||||
self.assertIsInstance(list(x.attr)[0], Object)
|
||||
self.assertIs(list(x.attr)[0], x)
|
||||
|
||||
# Collection containing a mutable object containing the original
|
||||
# collection.
|
||||
o = o.attr
|
||||
for proto in protocols:
|
||||
s = self.dumps(o, proto)
|
||||
x = self.loads(s)
|
||||
self.assertIsInstance(x, t)
|
||||
self.assertEqual(len(x), 1)
|
||||
self.assertIsInstance(list(x)[0], H)
|
||||
self.assertIsInstance(list(x)[0], Object)
|
||||
self.assertIs(list(x)[0].attr, x)
|
||||
|
||||
def test_recursive_list_and_inst(self):
|
||||
self.check_recursive_collection_and_inst(list)
|
||||
self._test_recursive_collection_and_inst(list)
|
||||
|
||||
def test_recursive_tuple_and_inst(self):
|
||||
self.check_recursive_collection_and_inst(tuple)
|
||||
self._test_recursive_collection_and_inst(tuple)
|
||||
|
||||
def test_recursive_dict_and_inst(self):
|
||||
self.check_recursive_collection_and_inst(dict.fromkeys)
|
||||
self._test_recursive_collection_and_inst(dict.fromkeys)
|
||||
|
||||
def test_recursive_set_and_inst(self):
|
||||
self.check_recursive_collection_and_inst(set)
|
||||
self._test_recursive_collection_and_inst(set)
|
||||
|
||||
def test_recursive_frozenset_and_inst(self):
|
||||
self.check_recursive_collection_and_inst(frozenset)
|
||||
self._test_recursive_collection_and_inst(frozenset)
|
||||
|
||||
def test_recursive_list_subclass_and_inst(self):
|
||||
self.check_recursive_collection_and_inst(MyList)
|
||||
self._test_recursive_collection_and_inst(MyList)
|
||||
|
||||
def test_recursive_tuple_subclass_and_inst(self):
|
||||
self.check_recursive_collection_and_inst(MyTuple)
|
||||
self._test_recursive_collection_and_inst(MyTuple)
|
||||
|
||||
def test_recursive_dict_subclass_and_inst(self):
|
||||
self.check_recursive_collection_and_inst(MyDict.fromkeys)
|
||||
self._test_recursive_collection_and_inst(MyDict.fromkeys)
|
||||
|
||||
def test_recursive_set_subclass_and_inst(self):
|
||||
self.check_recursive_collection_and_inst(MySet)
|
||||
self._test_recursive_collection_and_inst(MySet)
|
||||
|
||||
def test_recursive_frozenset_subclass_and_inst(self):
|
||||
self.check_recursive_collection_and_inst(MyFrozenSet)
|
||||
self._test_recursive_collection_and_inst(MyFrozenSet)
|
||||
|
||||
def test_recursive_inst_state(self):
|
||||
# Mutable object containing itself.
|
||||
y = REX_state()
|
||||
y.state = y
|
||||
for proto in protocols:
|
||||
s = self.dumps(y, proto)
|
||||
x = self.loads(s)
|
||||
self.assertIsInstance(x, REX_state)
|
||||
self.assertIs(x.state, x)
|
||||
|
||||
def test_recursive_tuple_and_inst_state(self):
|
||||
# Tuple containing a mutable object containing the original tuple.
|
||||
t = (REX_state(),)
|
||||
t[0].state = t
|
||||
for proto in protocols:
|
||||
s = self.dumps(t, proto)
|
||||
x = self.loads(s)
|
||||
self.assertIsInstance(x, tuple)
|
||||
self.assertEqual(len(x), 1)
|
||||
self.assertIsInstance(x[0], REX_state)
|
||||
self.assertIs(x[0].state, x)
|
||||
|
||||
# Mutable object containing a tuple containing the object.
|
||||
t, = t
|
||||
for proto in protocols:
|
||||
s = self.dumps(t, proto)
|
||||
x = self.loads(s)
|
||||
self.assertIsInstance(x, REX_state)
|
||||
self.assertIsInstance(x.state, tuple)
|
||||
self.assertEqual(len(x.state), 1)
|
||||
self.assertIs(x.state[0], x)
|
||||
|
||||
def test_unicode(self):
|
||||
endcases = ['', '<\\u>', '<\\\u1234>', '<\n>',
|
||||
|
@ -3062,6 +3215,19 @@ class REX_seven(object):
|
|||
def __reduce__(self):
|
||||
return type(self), (), None, None, iter(self.table.items())
|
||||
|
||||
class REX_state(object):
|
||||
"""This class is used to check the 3th argument (state) of
|
||||
the reduce protocol.
|
||||
"""
|
||||
def __init__(self, state=None):
|
||||
self.state = state
|
||||
def __eq__(self, other):
|
||||
return type(self) is type(other) and self.state == other.state
|
||||
def __setstate__(self, state):
|
||||
self.state = state
|
||||
def __reduce__(self):
|
||||
return type(self), (), self.state
|
||||
|
||||
|
||||
# Test classes for newobj
|
||||
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
# This script doesn't actually display anything very coherent. but it
|
||||
# does call (nearly) every method and function.
|
||||
#
|
||||
# Functions not tested: {def,reset}_{shell,prog}_mode, getch(), getstr(),
|
||||
# init_color()
|
||||
# Functions not tested: {def,reset}_{shell,prog}_mode, getch(), getstr()
|
||||
# Only called, not tested: getmouse(), ungetmouse()
|
||||
#
|
||||
|
||||
|
@ -13,6 +12,7 @@ import os
|
|||
import string
|
||||
import sys
|
||||
import tempfile
|
||||
import functools
|
||||
import unittest
|
||||
|
||||
from test.support import requires, verbose, SaveSignals
|
||||
|
@ -37,6 +37,15 @@ def requires_curses_func(name):
|
|||
return unittest.skipUnless(hasattr(curses, name),
|
||||
'requires curses.%s' % name)
|
||||
|
||||
def requires_colors(test):
|
||||
@functools.wraps(test)
|
||||
def wrapped(self, *args, **kwargs):
|
||||
if not curses.has_colors():
|
||||
self.skipTest('requires colors support')
|
||||
curses.start_color()
|
||||
test(self, *args, **kwargs)
|
||||
return wrapped
|
||||
|
||||
term = os.environ.get('TERM')
|
||||
|
||||
# If newterm was supported we could use it instead of initscr and not exit
|
||||
|
@ -48,37 +57,59 @@ class TestCurses(unittest.TestCase):
|
|||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
if not sys.__stdout__.isatty():
|
||||
# Temporary skip tests on non-tty
|
||||
raise unittest.SkipTest('sys.__stdout__ is not a tty')
|
||||
cls.tmp = tempfile.TemporaryFile()
|
||||
fd = cls.tmp.fileno()
|
||||
else:
|
||||
cls.tmp = None
|
||||
fd = sys.__stdout__.fileno()
|
||||
if verbose:
|
||||
print(f'TERM={term}', file=sys.stderr, flush=True)
|
||||
# testing setupterm() inside initscr/endwin
|
||||
# causes terminal breakage
|
||||
curses.setupterm(fd=fd)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
if cls.tmp:
|
||||
cls.tmp.close()
|
||||
del cls.tmp
|
||||
stdout_fd = sys.__stdout__.fileno()
|
||||
curses.setupterm(fd=stdout_fd)
|
||||
|
||||
def setUp(self):
|
||||
self.isatty = True
|
||||
self.output = sys.__stdout__
|
||||
stdout_fd = sys.__stdout__.fileno()
|
||||
if not sys.__stdout__.isatty():
|
||||
# initstr() unconditionally uses C stdout.
|
||||
# If it is redirected to file or pipe, try to attach it
|
||||
# to terminal.
|
||||
# First, save a copy of the file descriptor of stdout, so it
|
||||
# can be restored after finishing the test.
|
||||
dup_fd = os.dup(stdout_fd)
|
||||
self.addCleanup(os.close, dup_fd)
|
||||
self.addCleanup(os.dup2, dup_fd, stdout_fd)
|
||||
|
||||
if sys.__stderr__.isatty():
|
||||
# If stderr is connected to terminal, use it.
|
||||
tmp = sys.__stderr__
|
||||
self.output = sys.__stderr__
|
||||
else:
|
||||
try:
|
||||
# Try to open the terminal device.
|
||||
tmp = open('/dev/tty', 'wb', buffering=0)
|
||||
except OSError:
|
||||
# As a fallback, use regular file to write control codes.
|
||||
# Some functions (like savetty) will not work, but at
|
||||
# least the garbage control sequences will not be mixed
|
||||
# with the testing report.
|
||||
tmp = tempfile.TemporaryFile(mode='wb', buffering=0)
|
||||
self.isatty = False
|
||||
self.addCleanup(tmp.close)
|
||||
self.output = None
|
||||
os.dup2(tmp.fileno(), stdout_fd)
|
||||
|
||||
self.save_signals = SaveSignals()
|
||||
self.save_signals.save()
|
||||
if verbose:
|
||||
self.addCleanup(self.save_signals.restore)
|
||||
if verbose and self.output is not None:
|
||||
# just to make the test output a little more readable
|
||||
print()
|
||||
sys.stderr.flush()
|
||||
sys.stdout.flush()
|
||||
print(file=self.output, flush=True)
|
||||
self.stdscr = curses.initscr()
|
||||
curses.savetty()
|
||||
|
||||
def tearDown(self):
|
||||
curses.resetty()
|
||||
curses.endwin()
|
||||
self.save_signals.restore()
|
||||
if self.isatty:
|
||||
curses.savetty()
|
||||
self.addCleanup(curses.endwin)
|
||||
self.addCleanup(curses.resetty)
|
||||
|
||||
def test_window_funcs(self):
|
||||
"Test the methods of windows"
|
||||
|
@ -96,7 +127,7 @@ class TestCurses(unittest.TestCase):
|
|||
for meth in [stdscr.clear, stdscr.clrtobot,
|
||||
stdscr.clrtoeol, stdscr.cursyncup, stdscr.delch,
|
||||
stdscr.deleteln, stdscr.erase, stdscr.getbegyx,
|
||||
stdscr.getbkgd, stdscr.getkey, stdscr.getmaxyx,
|
||||
stdscr.getbkgd, stdscr.getmaxyx,
|
||||
stdscr.getparyx, stdscr.getyx, stdscr.inch,
|
||||
stdscr.insertln, stdscr.instr, stdscr.is_wintouched,
|
||||
win.noutrefresh, stdscr.redrawwin, stdscr.refresh,
|
||||
|
@ -207,6 +238,11 @@ class TestCurses(unittest.TestCase):
|
|||
if hasattr(stdscr, 'enclose'):
|
||||
stdscr.enclose(10, 10)
|
||||
|
||||
with tempfile.TemporaryFile() as f:
|
||||
self.stdscr.putwin(f)
|
||||
f.seek(0)
|
||||
curses.getwin(f)
|
||||
|
||||
self.assertRaises(ValueError, stdscr.getstr, -400)
|
||||
self.assertRaises(ValueError, stdscr.getstr, 2, 3, -400)
|
||||
self.assertRaises(ValueError, stdscr.instr, -2)
|
||||
|
@ -225,17 +261,20 @@ class TestCurses(unittest.TestCase):
|
|||
def test_module_funcs(self):
|
||||
"Test module-level functions"
|
||||
for func in [curses.baudrate, curses.beep, curses.can_change_color,
|
||||
curses.cbreak, curses.def_prog_mode, curses.doupdate,
|
||||
curses.flash, curses.flushinp,
|
||||
curses.doupdate, curses.flash, curses.flushinp,
|
||||
curses.has_colors, curses.has_ic, curses.has_il,
|
||||
curses.isendwin, curses.killchar, curses.longname,
|
||||
curses.nocbreak, curses.noecho, curses.nonl,
|
||||
curses.noqiflush, curses.noraw,
|
||||
curses.reset_prog_mode, curses.termattrs,
|
||||
curses.termname, curses.erasechar,
|
||||
curses.noecho, curses.nonl, curses.noqiflush,
|
||||
curses.termattrs, curses.termname, curses.erasechar,
|
||||
curses.has_extended_color_support]:
|
||||
with self.subTest(func=func.__qualname__):
|
||||
func()
|
||||
if self.isatty:
|
||||
for func in [curses.cbreak, curses.def_prog_mode,
|
||||
curses.nocbreak, curses.noraw,
|
||||
curses.reset_prog_mode]:
|
||||
with self.subTest(func=func.__qualname__):
|
||||
func()
|
||||
if hasattr(curses, 'filter'):
|
||||
curses.filter()
|
||||
if hasattr(curses, 'getsyx'):
|
||||
|
@ -247,13 +286,9 @@ class TestCurses(unittest.TestCase):
|
|||
curses.delay_output(1)
|
||||
curses.echo() ; curses.echo(1)
|
||||
|
||||
with tempfile.TemporaryFile() as f:
|
||||
self.stdscr.putwin(f)
|
||||
f.seek(0)
|
||||
curses.getwin(f)
|
||||
|
||||
curses.halfdelay(1)
|
||||
curses.intrflush(1)
|
||||
if self.isatty:
|
||||
curses.intrflush(1)
|
||||
curses.meta(1)
|
||||
curses.napms(100)
|
||||
curses.newpad(50,50)
|
||||
|
@ -262,7 +297,8 @@ class TestCurses(unittest.TestCase):
|
|||
curses.nl() ; curses.nl(1)
|
||||
curses.putp(b'abc')
|
||||
curses.qiflush()
|
||||
curses.raw() ; curses.raw(1)
|
||||
if self.isatty:
|
||||
curses.raw() ; curses.raw(1)
|
||||
curses.set_escdelay(25)
|
||||
self.assertEqual(curses.get_escdelay(), 25)
|
||||
curses.set_tabsize(4)
|
||||
|
@ -281,31 +317,101 @@ class TestCurses(unittest.TestCase):
|
|||
curses.use_env(1)
|
||||
|
||||
# Functions only available on a few platforms
|
||||
def test_colors_funcs(self):
|
||||
if not curses.has_colors():
|
||||
self.skipTest('requires colors support')
|
||||
curses.start_color()
|
||||
curses.init_pair(2, 1,1)
|
||||
curses.color_content(1)
|
||||
curses.color_pair(2)
|
||||
|
||||
def bad_colors(self):
|
||||
return (-1, curses.COLORS, -2**31 - 1, 2**31, -2**63 - 1, 2**63, 2**64)
|
||||
|
||||
def bad_colors2(self):
|
||||
return (curses.COLORS, 2**31, 2**63, 2**64)
|
||||
|
||||
def bad_pairs(self):
|
||||
return (-1, -2**31 - 1, 2**31, -2**63 - 1, 2**63, 2**64)
|
||||
|
||||
@requires_colors
|
||||
def test_color_content(self):
|
||||
self.assertEqual(curses.color_content(curses.COLOR_BLACK), (0, 0, 0))
|
||||
curses.color_content(0)
|
||||
curses.color_content(curses.COLORS - 1)
|
||||
|
||||
for color in self.bad_colors():
|
||||
self.assertRaises(ValueError, curses.color_content, color)
|
||||
|
||||
@requires_colors
|
||||
def test_init_color(self):
|
||||
if not curses.can_change_color:
|
||||
self.skipTest('cannot change color')
|
||||
|
||||
old = curses.color_content(0)
|
||||
try:
|
||||
curses.init_color(0, *old)
|
||||
except curses.error:
|
||||
self.skipTest('cannot change color (init_color() failed)')
|
||||
self.addCleanup(curses.init_color, 0, *old)
|
||||
curses.init_color(0, 0, 0, 0)
|
||||
self.assertEqual(curses.color_content(0), (0, 0, 0))
|
||||
curses.init_color(0, 1000, 1000, 1000)
|
||||
self.assertEqual(curses.color_content(0), (1000, 1000, 1000))
|
||||
|
||||
old = curses.color_content(curses.COLORS - 1)
|
||||
curses.init_color(curses.COLORS - 1, *old)
|
||||
self.addCleanup(curses.init_color, curses.COLORS - 1, *old)
|
||||
curses.init_color(curses.COLORS - 1, 0, 500, 1000)
|
||||
self.assertEqual(curses.color_content(curses.COLORS - 1), (0, 500, 1000))
|
||||
|
||||
for color in self.bad_colors():
|
||||
self.assertRaises(ValueError, curses.init_color, color, 0, 0, 0)
|
||||
for comp in (-1, 1001):
|
||||
self.assertRaises(ValueError, curses.init_color, 0, comp, 0, 0)
|
||||
self.assertRaises(ValueError, curses.init_color, 0, 0, comp, 0)
|
||||
self.assertRaises(ValueError, curses.init_color, 0, 0, 0, comp)
|
||||
|
||||
@requires_colors
|
||||
def test_pair_content(self):
|
||||
if not hasattr(curses, 'use_default_colors'):
|
||||
self.assertEqual(curses.pair_content(0),
|
||||
(curses.COLOR_WHITE, curses.COLOR_BLACK))
|
||||
curses.pair_content(0)
|
||||
curses.pair_content(curses.COLOR_PAIRS - 1)
|
||||
curses.pair_number(0)
|
||||
|
||||
if hasattr(curses, 'use_default_colors'):
|
||||
curses.use_default_colors()
|
||||
for pair in self.bad_pairs():
|
||||
self.assertRaises(ValueError, curses.pair_content, pair)
|
||||
|
||||
self.assertRaises(ValueError, curses.color_content, -1)
|
||||
self.assertRaises(ValueError, curses.color_content, curses.COLORS + 1)
|
||||
self.assertRaises(ValueError, curses.color_content, -2**31 - 1)
|
||||
self.assertRaises(ValueError, curses.color_content, 2**31)
|
||||
self.assertRaises(ValueError, curses.color_content, -2**63 - 1)
|
||||
self.assertRaises(ValueError, curses.color_content, 2**63 - 1)
|
||||
self.assertRaises(ValueError, curses.pair_content, -1)
|
||||
self.assertRaises(ValueError, curses.pair_content, curses.COLOR_PAIRS)
|
||||
self.assertRaises(ValueError, curses.pair_content, -2**31 - 1)
|
||||
self.assertRaises(ValueError, curses.pair_content, 2**31)
|
||||
self.assertRaises(ValueError, curses.pair_content, -2**63 - 1)
|
||||
self.assertRaises(ValueError, curses.pair_content, 2**63 - 1)
|
||||
@requires_colors
|
||||
def test_init_pair(self):
|
||||
old = curses.pair_content(1)
|
||||
curses.init_pair(1, *old)
|
||||
self.addCleanup(curses.init_pair, 1, *old)
|
||||
|
||||
curses.init_pair(1, 0, 0)
|
||||
self.assertEqual(curses.pair_content(1), (0, 0))
|
||||
curses.init_pair(1, curses.COLORS - 1, curses.COLORS - 1)
|
||||
self.assertEqual(curses.pair_content(1),
|
||||
(curses.COLORS - 1, curses.COLORS - 1))
|
||||
curses.init_pair(curses.COLOR_PAIRS - 1, 2, 3)
|
||||
self.assertEqual(curses.pair_content(curses.COLOR_PAIRS - 1), (2, 3))
|
||||
|
||||
for pair in self.bad_pairs():
|
||||
self.assertRaises(ValueError, curses.init_pair, pair, 0, 0)
|
||||
for color in self.bad_colors2():
|
||||
self.assertRaises(ValueError, curses.init_pair, 1, color, 0)
|
||||
self.assertRaises(ValueError, curses.init_pair, 1, 0, color)
|
||||
|
||||
@requires_colors
|
||||
def test_color_attrs(self):
|
||||
for pair in 0, 1, 255:
|
||||
attr = curses.color_pair(pair)
|
||||
self.assertEqual(curses.pair_number(attr), pair, attr)
|
||||
self.assertEqual(curses.pair_number(attr | curses.A_BOLD), pair)
|
||||
self.assertEqual(curses.color_pair(0), 0)
|
||||
self.assertEqual(curses.pair_number(0), 0)
|
||||
|
||||
@requires_curses_func('use_default_colors')
|
||||
@requires_colors
|
||||
def test_use_default_colors(self):
|
||||
self.assertIn(curses.pair_content(0),
|
||||
((curses.COLOR_WHITE, curses.COLOR_BLACK), (-1, -1)))
|
||||
curses.use_default_colors()
|
||||
self.assertEqual(curses.pair_content(0), (-1, -1))
|
||||
|
||||
@requires_curses_func('keyname')
|
||||
def test_keyname(self):
|
||||
|
@ -373,7 +479,6 @@ class TestCurses(unittest.TestCase):
|
|||
|
||||
@requires_curses_func('resizeterm')
|
||||
def test_resizeterm(self):
|
||||
stdscr = self.stdscr
|
||||
lines, cols = curses.LINES, curses.COLS
|
||||
new_lines = lines - 1
|
||||
new_cols = cols + 1
|
||||
|
|
|
@ -332,6 +332,59 @@ non-important content
|
|||
self.assertEqual(binop.left.col_offset, 4)
|
||||
self.assertEqual(binop.right.col_offset, 7)
|
||||
|
||||
def test_ast_line_numbers_with_parentheses(self):
|
||||
expr = """
|
||||
x = (
|
||||
f" {test(t)}"
|
||||
)"""
|
||||
t = ast.parse(expr)
|
||||
self.assertEqual(type(t), ast.Module)
|
||||
self.assertEqual(len(t.body), 1)
|
||||
# check the test(t) location
|
||||
call = t.body[0].value.values[1].value
|
||||
self.assertEqual(type(call), ast.Call)
|
||||
self.assertEqual(call.lineno, 3)
|
||||
self.assertEqual(call.end_lineno, 3)
|
||||
self.assertEqual(call.col_offset, 8)
|
||||
self.assertEqual(call.end_col_offset, 15)
|
||||
|
||||
expr = """
|
||||
x = (
|
||||
'PERL_MM_OPT', (
|
||||
f'wat'
|
||||
f'some_string={f(x)} '
|
||||
f'wat'
|
||||
),
|
||||
)
|
||||
"""
|
||||
t = ast.parse(expr)
|
||||
self.assertEqual(type(t), ast.Module)
|
||||
self.assertEqual(len(t.body), 1)
|
||||
# check the fstring
|
||||
fstring = t.body[0].value.elts[1]
|
||||
self.assertEqual(type(fstring), ast.JoinedStr)
|
||||
self.assertEqual(len(fstring.values), 3)
|
||||
wat1, middle, wat2 = fstring.values
|
||||
# check the first wat
|
||||
self.assertEqual(type(wat1), ast.Constant)
|
||||
self.assertEqual(wat1.lineno, 4)
|
||||
self.assertEqual(wat1.end_lineno, 6)
|
||||
self.assertEqual(wat1.col_offset, 12)
|
||||
self.assertEqual(wat1.end_col_offset, 18)
|
||||
# check the call
|
||||
call = middle.value
|
||||
self.assertEqual(type(call), ast.Call)
|
||||
self.assertEqual(call.lineno, 5)
|
||||
self.assertEqual(call.end_lineno, 5)
|
||||
self.assertEqual(call.col_offset, 27)
|
||||
self.assertEqual(call.end_col_offset, 31)
|
||||
# check the second wat
|
||||
self.assertEqual(type(wat2), ast.Constant)
|
||||
self.assertEqual(wat2.lineno, 4)
|
||||
self.assertEqual(wat2.end_lineno, 6)
|
||||
self.assertEqual(wat2.col_offset, 12)
|
||||
self.assertEqual(wat2.end_col_offset, 18)
|
||||
|
||||
def test_docstring(self):
|
||||
def f():
|
||||
f'''Not a docstring'''
|
||||
|
|
|
@ -562,6 +562,14 @@ class SystemRandom_TestBasicOps(TestBasicOps, unittest.TestCase):
|
|||
with self.assertRaises(ValueError):
|
||||
randrange(10, 20, 1.5)
|
||||
|
||||
def test_randrange_step(self):
|
||||
# bpo-42772: When stop is None, the step argument was being ignored.
|
||||
randrange = self.gen.randrange
|
||||
with self.assertRaises(TypeError):
|
||||
randrange(1000, step=100)
|
||||
with self.assertRaises(TypeError):
|
||||
randrange(1000, None, step=100)
|
||||
|
||||
def test_randbelow_logic(self, _log=log, int=int):
|
||||
# check bitcount transition points: 2**i and 2**(i+1)-1
|
||||
# show that: k = int(1.001 + _log(n, 2))
|
||||
|
|
|
@ -737,6 +737,16 @@ class TypesTests(unittest.TestCase):
|
|||
with self.assertRaises(ZeroDivisionError):
|
||||
list[int] | list[bt]
|
||||
|
||||
union_ga = (int | list[str], int | collections.abc.Callable[..., str],
|
||||
int | d)
|
||||
# Raise error when isinstance(type, type | genericalias)
|
||||
for type_ in union_ga:
|
||||
with self.subTest(f"check isinstance/issubclass is invalid for {type_}"):
|
||||
with self.assertRaises(TypeError):
|
||||
isinstance(list, type_)
|
||||
with self.assertRaises(TypeError):
|
||||
issubclass(list, type_)
|
||||
|
||||
def test_ellipsis_type(self):
|
||||
self.assertIsInstance(Ellipsis, types.EllipsisType)
|
||||
|
||||
|
|
|
@ -346,6 +346,31 @@ Now some general starred expressions (all fail).
|
|||
...
|
||||
SyntaxError: can't use starred expression here
|
||||
|
||||
>>> (*x),y = 1, 2 # doctest:+ELLIPSIS
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
SyntaxError: can't use starred expression here
|
||||
|
||||
>>> (((*x))),y = 1, 2 # doctest:+ELLIPSIS
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
SyntaxError: can't use starred expression here
|
||||
|
||||
>>> z,(*x),y = 1, 2, 4 # doctest:+ELLIPSIS
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
SyntaxError: can't use starred expression here
|
||||
|
||||
>>> z,(*x) = 1, 2 # doctest:+ELLIPSIS
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
SyntaxError: can't use starred expression here
|
||||
|
||||
>>> ((*x),y) = 1, 2 # doctest:+ELLIPSIS
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
SyntaxError: can't use starred expression here
|
||||
|
||||
Some size constraints (all fail.)
|
||||
|
||||
>>> s = ", ".join("a%d" % i for i in range(1<<8)) + ", *rest = range(1<<8 + 1)"
|
||||
|
|
|
@ -242,15 +242,12 @@ def library_recipes():
|
|||
|
||||
result.extend([
|
||||
dict(
|
||||
name="OpenSSL 1.1.1g",
|
||||
url="https://www.openssl.org/source/openssl-1.1.1g.tar.gz",
|
||||
checksum='76766e98997660138cdaf13a187bd234',
|
||||
name="OpenSSL 1.1.1i",
|
||||
url="https://www.openssl.org/source/openssl-1.1.1i.tar.gz",
|
||||
checksum='08987c3cf125202e2b0840035efb392c',
|
||||
buildrecipe=build_universal_openssl,
|
||||
configure=None,
|
||||
install=None,
|
||||
patches=[
|
||||
"openssl-mac-arm64.patch",
|
||||
],
|
||||
),
|
||||
])
|
||||
|
||||
|
@ -263,10 +260,10 @@ def library_recipes():
|
|||
tk_patches = ['tk868_on_10_8_10_9.patch']
|
||||
|
||||
else:
|
||||
tcl_tk_ver='8.6.10'
|
||||
tcl_checksum='97c55573f8520bcab74e21bfd8d0aadc'
|
||||
tcl_tk_ver='8.6.11'
|
||||
tcl_checksum='8a4c004f48984a03a7747e9ba06e4da4'
|
||||
|
||||
tk_checksum='602a47ad9ecac7bf655ada729d140a94'
|
||||
tk_checksum='c7ee71a2d05bba78dfffd76528dc17c6'
|
||||
tk_patches = [ ]
|
||||
|
||||
|
||||
|
@ -357,9 +354,9 @@ def library_recipes():
|
|||
),
|
||||
),
|
||||
dict(
|
||||
name="SQLite 3.33.0",
|
||||
url="https://sqlite.org/2020/sqlite-autoconf-3330000.tar.gz",
|
||||
checksum='842a8a100d7b01b09e543deb2b7951dd',
|
||||
name="SQLite 3.34.0",
|
||||
url="https://sqlite.org/2020/sqlite-autoconf-3340000.tar.gz",
|
||||
checksum='7f33c9db7b713957fcb9271fe9049fef',
|
||||
extra_cflags=('-Os '
|
||||
'-DSQLITE_ENABLE_FTS5 '
|
||||
'-DSQLITE_ENABLE_FTS4 '
|
||||
|
@ -1138,7 +1135,6 @@ def buildPythonDocs():
|
|||
if not os.path.exists(htmlDir):
|
||||
# Create virtual environment for docs builds with blurb and sphinx
|
||||
runCommand('make venv')
|
||||
runCommand('venv/bin/python3 -m pip install -U Sphinx==2.3.1')
|
||||
runCommand('make html PYTHON=venv/bin/python')
|
||||
os.rename(htmlDir, docdir)
|
||||
os.chdir(curDir)
|
||||
|
@ -1615,7 +1611,7 @@ def buildDMG():
|
|||
if os.path.exists(outdir):
|
||||
shutil.rmtree(outdir)
|
||||
|
||||
# We used to use the deployment target as the last characters of the
|
||||
# We used to use the deployment target as the last characters of the
|
||||
# installer file name. With the introduction of weaklinked installer
|
||||
# variants, we may have two variants with the same file name, i.e.
|
||||
# both ending in '10.9'. To avoid this, we now use the major/minor
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
diff -ur openssl-1.1.1g-orig/Configurations/10-main.conf openssl-1.1.1g/Configurations/10-main.conf
|
||||
--- openssl-1.1.1g-orig/Configurations/10-main.conf 2020-04-21 14:22:39.000000000 +0200
|
||||
+++ openssl-1.1.1g/Configurations/10-main.conf 2020-07-26 12:21:32.000000000 +0200
|
||||
@@ -1557,6 +1557,14 @@
|
||||
bn_ops => "SIXTY_FOUR_BIT_LONG",
|
||||
perlasm_scheme => "macosx",
|
||||
},
|
||||
+ "darwin64-arm64-cc" => {
|
||||
+ inherit_from => [ "darwin-common", asm("aarch64_asm") ],
|
||||
+ CFLAGS => add("-Wall"),
|
||||
+ cflags => add("-arch arm64"),
|
||||
+ lib_cppflags => add("-DL_ENDIAN"),
|
||||
+ bn_ops => "SIXTY_FOUR_BIT_LONG",
|
||||
+ perlasm_scheme => "ios64",
|
||||
+ },
|
||||
|
||||
##### GNU Hurd
|
||||
"hurd-x86" => {
|
||||
diff -ur openssl-1.1.1g-orig/config openssl-1.1.1g/config
|
||||
--- openssl-1.1.1g-orig/config 2020-04-21 14:22:39.000000000 +0200
|
||||
+++ openssl-1.1.1g/config 2020-07-26 12:21:59.000000000 +0200
|
||||
@@ -255,6 +255,9 @@
|
||||
;;
|
||||
x86_64)
|
||||
echo "x86_64-apple-darwin${VERSION}"
|
||||
+ ;;
|
||||
+ arm64)
|
||||
+ echo "arm64-apple-darwin${VERSION}"
|
||||
;;
|
||||
*)
|
||||
echo "i686-apple-darwin${VERSION}"
|
||||
@@ -497,6 +500,9 @@
|
||||
else
|
||||
OUT="darwin64-x86_64-cc"
|
||||
fi ;;
|
||||
+ x86_64-apple-darwin*)
|
||||
+ OUT="darwin64-arm64-cc"
|
||||
+ ;;
|
||||
armv6+7-*-iphoneos)
|
||||
__CNF_CFLAGS="$__CNF_CFLAGS -arch armv6 -arch armv7"
|
||||
__CNF_CXXFLAGS="$__CNF_CXXFLAGS -arch armv6 -arch armv7"
|
|
@ -0,0 +1 @@
|
|||
Fix __builtin_available check on older compilers. Patch by Joshua Root.
|
|
@ -0,0 +1 @@
|
|||
Convert :mod:`array` to use heap types, and establish module state for these.
|
|
@ -0,0 +1,2 @@
|
|||
Fix regression where a single parenthesized starred expression was a valid
|
||||
assignment target.
|
|
@ -0,0 +1,2 @@
|
|||
Fix the column offsets for f-strings :mod:`ast` nodes surrounded by
|
||||
parentheses and for nodes that spawn multiple lines. Patch by Pablo Galindo.
|
|
@ -0,0 +1 @@
|
|||
Fix undefined behavior in ``Objects/genericaliasobject.c``.
|
|
@ -0,0 +1 @@
|
|||
Fixed range checks for color and pair numbers in :mod:`curses`.
|
|
@ -0,0 +1,2 @@
|
|||
randrange() now raises a TypeError when step is specified without a stop
|
||||
argument. Formerly, it silently ignored the step argument.
|
|
@ -0,0 +1 @@
|
|||
Handle empty string in variable executable in platform.libc_ver()
|
|
@ -0,0 +1 @@
|
|||
Update macOS installer to use SQLite 3.34.0.
|
|
@ -0,0 +1 @@
|
|||
Update macOS installer build to use OpenSSL 1.1.1i.
|
|
@ -0,0 +1,2 @@
|
|||
Update macOS installer build to use Tcl/Tk 8.6.11 (rc2, expected to be final
|
||||
release).
|
|
@ -155,10 +155,8 @@ typedef chtype attr_t; /* No attr_t type is available */
|
|||
#define _CURSES_PAIR_NUMBER_FUNC pair_content
|
||||
#endif /* _NCURSES_EXTENDED_COLOR_FUNCS */
|
||||
|
||||
#define _CURSES_FUNC_NAME_STR(s) #s
|
||||
|
||||
#define _CURSES_INIT_COLOR_FUNC_NAME _CURSES_FUNC_NAME_STR(_CURSES_INIT_COLOR_FUNC)
|
||||
#define _CURSES_INIT_PAIR_FUNC_NAME _CURSES_FUNC_NAME_STR(_CURSES_INIT_PAIR_FUNC)
|
||||
#define _CURSES_INIT_COLOR_FUNC_NAME Py_STRINGIFY(_CURSES_INIT_COLOR_FUNC)
|
||||
#define _CURSES_INIT_PAIR_FUNC_NAME Py_STRINGIFY(_CURSES_INIT_PAIR_FUNC)
|
||||
|
||||
/*[clinic input]
|
||||
module _curses
|
||||
|
@ -202,18 +200,6 @@ static char *screen_encoding = NULL;
|
|||
|
||||
/* Utility Functions */
|
||||
|
||||
static inline int
|
||||
color_pair_to_attr(short color_number)
|
||||
{
|
||||
return ((int)color_number << 8);
|
||||
}
|
||||
|
||||
static inline short
|
||||
attr_to_color_pair(int attr)
|
||||
{
|
||||
return (short)((attr & A_COLOR) >> 8);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check the return code from a curses function and return None
|
||||
* or raise an exception as appropriate. These are exported using the
|
||||
|
@ -414,7 +400,7 @@ PyCurses_ConvertToString(PyCursesWindowObject *win, PyObject *obj,
|
|||
}
|
||||
|
||||
static int
|
||||
color_converter(PyObject *arg, void *ptr)
|
||||
color_allow_default_converter(PyObject *arg, void *ptr)
|
||||
{
|
||||
long color_number;
|
||||
int overflow;
|
||||
|
@ -423,19 +409,31 @@ color_converter(PyObject *arg, void *ptr)
|
|||
if (color_number == -1 && PyErr_Occurred())
|
||||
return 0;
|
||||
|
||||
if (overflow > 0 || color_number > COLORS) {
|
||||
if (overflow > 0 || color_number >= COLORS) {
|
||||
PyErr_Format(PyExc_ValueError,
|
||||
"Color number is greater than COLORS (%d).",
|
||||
COLORS);
|
||||
"Color number is greater than COLORS-1 (%d).",
|
||||
COLORS - 1);
|
||||
return 0;
|
||||
}
|
||||
else if (overflow < 0 || color_number < 0) {
|
||||
color_number = -1;
|
||||
}
|
||||
|
||||
*(int *)ptr = (int)color_number;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
color_converter(PyObject *arg, void *ptr)
|
||||
{
|
||||
if (!color_allow_default_converter(arg, ptr)) {
|
||||
return 0;
|
||||
}
|
||||
if (*(int *)ptr < 0) {
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"Color number is less than 0.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
*(int *)ptr = (int)color_number;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -446,6 +444,13 @@ class color_converter(CConverter):
|
|||
[python start generated code]*/
|
||||
/*[python end generated code: output=da39a3ee5e6b4b0d input=4260d2b6e66b3709]*/
|
||||
|
||||
/*[python input]
|
||||
class color_allow_default_converter(CConverter):
|
||||
type = 'int'
|
||||
converter = 'color_allow_default_converter'
|
||||
[python start generated code]*/
|
||||
/*[python end generated code: output=da39a3ee5e6b4b0d input=975602bc058a872d]*/
|
||||
|
||||
static int
|
||||
pair_converter(PyObject *arg, void *ptr)
|
||||
{
|
||||
|
@ -456,15 +461,24 @@ pair_converter(PyObject *arg, void *ptr)
|
|||
if (pair_number == -1 && PyErr_Occurred())
|
||||
return 0;
|
||||
|
||||
if (overflow > 0 || pair_number > COLOR_PAIRS - 1) {
|
||||
#if _NCURSES_EXTENDED_COLOR_FUNCS
|
||||
if (overflow > 0 || pair_number > INT_MAX) {
|
||||
PyErr_Format(PyExc_ValueError,
|
||||
"Color pair is greater than maximum (%d).",
|
||||
INT_MAX);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
if (overflow > 0 || pair_number >= COLOR_PAIRS) {
|
||||
PyErr_Format(PyExc_ValueError,
|
||||
"Color pair is greater than COLOR_PAIRS-1 (%d).",
|
||||
COLOR_PAIRS - 1);
|
||||
return 0;
|
||||
}
|
||||
else if (overflow < 0 || pair_number < 1) {
|
||||
#endif
|
||||
else if (overflow < 0 || pair_number < 0) {
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"Color pair is less than 1.");
|
||||
"Color pair is less than 0.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -742,7 +756,7 @@ _curses_window_addch_impl(PyCursesWindowObject *self, int group_left_1,
|
|||
if (type == 2) {
|
||||
funcname = "add_wch";
|
||||
wstr[1] = L'\0';
|
||||
setcchar(&wcval, wstr, attr, attr_to_color_pair(attr), NULL);
|
||||
setcchar(&wcval, wstr, attr, PAIR_NUMBER(attr), NULL);
|
||||
if (coordinates_group)
|
||||
rtn = mvwadd_wch(self->win,y,x, &wcval);
|
||||
else {
|
||||
|
@ -2710,7 +2724,7 @@ NoArgOrFlagNoReturnFunctionBody(cbreak, flag)
|
|||
_curses.color_content
|
||||
|
||||
color_number: color
|
||||
The number of the color (0 - COLORS).
|
||||
The number of the color (0 - (COLORS-1)).
|
||||
/
|
||||
|
||||
Return the red, green, and blue (RGB) components of the specified color.
|
||||
|
@ -2721,7 +2735,7 @@ which will be between 0 (no component) and 1000 (maximum amount of component).
|
|||
|
||||
static PyObject *
|
||||
_curses_color_content_impl(PyObject *module, int color_number)
|
||||
/*[clinic end generated code: output=17b466df7054e0de input=c10ef58f694b13ee]*/
|
||||
/*[clinic end generated code: output=17b466df7054e0de input=03b5ed0472662aea]*/
|
||||
{
|
||||
_NCURSES_COLOR_VAL_TYPE r,g,b;
|
||||
|
||||
|
@ -2740,8 +2754,8 @@ _curses_color_content_impl(PyObject *module, int color_number)
|
|||
/*[clinic input]
|
||||
_curses.color_pair
|
||||
|
||||
color_number: color
|
||||
The number of the color (0 - COLORS).
|
||||
pair_number: int
|
||||
The number of the color pair.
|
||||
/
|
||||
|
||||
Return the attribute value for displaying text in the specified color.
|
||||
|
@ -2751,13 +2765,13 @@ other A_* attributes. pair_number() is the counterpart to this function.
|
|||
[clinic start generated code]*/
|
||||
|
||||
static PyObject *
|
||||
_curses_color_pair_impl(PyObject *module, int color_number)
|
||||
/*[clinic end generated code: output=3fd752e8e24c93fb input=b049033819ab4ef5]*/
|
||||
_curses_color_pair_impl(PyObject *module, int pair_number)
|
||||
/*[clinic end generated code: output=60718abb10ce9feb input=6034e9146f343802]*/
|
||||
{
|
||||
PyCursesInitialised;
|
||||
PyCursesInitialisedColor;
|
||||
|
||||
return PyLong_FromLong(color_pair_to_attr(color_number));
|
||||
return PyLong_FromLong(COLOR_PAIR(pair_number));
|
||||
}
|
||||
|
||||
/*[clinic input]
|
||||
|
@ -3152,7 +3166,7 @@ _curses_has_key_impl(PyObject *module, int key)
|
|||
_curses.init_color
|
||||
|
||||
color_number: color
|
||||
The number of the color to be changed (0 - COLORS).
|
||||
The number of the color to be changed (0 - (COLORS-1)).
|
||||
r: component
|
||||
Red component (0 - 1000).
|
||||
g: component
|
||||
|
@ -3165,13 +3179,13 @@ Change the definition of a color.
|
|||
|
||||
When init_color() is used, all occurrences of that color on the screen
|
||||
immediately change to the new definition. This function is a no-op on
|
||||
most terminals; it is active only if can_change_color() returns 1.
|
||||
most terminals; it is active only if can_change_color() returns true.
|
||||
[clinic start generated code]*/
|
||||
|
||||
static PyObject *
|
||||
_curses_init_color_impl(PyObject *module, int color_number, short r, short g,
|
||||
short b)
|
||||
/*[clinic end generated code: output=d7ed71b2d818cdf2 input=8a2fe94ca9204aa5]*/
|
||||
/*[clinic end generated code: output=d7ed71b2d818cdf2 input=ae2b8bea0f152c80]*/
|
||||
{
|
||||
PyCursesInitialised;
|
||||
PyCursesInitialisedColor;
|
||||
|
@ -3184,10 +3198,10 @@ _curses.init_pair
|
|||
|
||||
pair_number: pair
|
||||
The number of the color-pair to be changed (1 - (COLOR_PAIRS-1)).
|
||||
fg: color
|
||||
Foreground color number (0 - COLORS).
|
||||
bg: color
|
||||
Background color number (0 - COLORS).
|
||||
fg: color_allow_default
|
||||
Foreground color number (-1 - (COLORS-1)).
|
||||
bg: color_allow_default
|
||||
Background color number (-1 - (COLORS-1)).
|
||||
/
|
||||
|
||||
Change the definition of a color-pair.
|
||||
|
@ -3198,7 +3212,7 @@ all occurrences of that color-pair are changed to the new definition.
|
|||
|
||||
static PyObject *
|
||||
_curses_init_pair_impl(PyObject *module, int pair_number, int fg, int bg)
|
||||
/*[clinic end generated code: output=a0bba03d2bbc3ee6 input=b865583a18061c1f]*/
|
||||
/*[clinic end generated code: output=a0bba03d2bbc3ee6 input=54b421b44c12c389]*/
|
||||
{
|
||||
PyCursesInitialised;
|
||||
PyCursesInitialisedColor;
|
||||
|
@ -3821,7 +3835,7 @@ NoArgNoReturnFunctionBody(noraw)
|
|||
_curses.pair_content
|
||||
|
||||
pair_number: pair
|
||||
The number of the color pair (1 - (COLOR_PAIRS-1)).
|
||||
The number of the color pair (0 - (COLOR_PAIRS-1)).
|
||||
/
|
||||
|
||||
Return a tuple (fg, bg) containing the colors for the requested color pair.
|
||||
|
@ -3829,7 +3843,7 @@ Return a tuple (fg, bg) containing the colors for the requested color pair.
|
|||
|
||||
static PyObject *
|
||||
_curses_pair_content_impl(PyObject *module, int pair_number)
|
||||
/*[clinic end generated code: output=4a726dd0e6885f3f input=b42eacf8a4103852]*/
|
||||
/*[clinic end generated code: output=4a726dd0e6885f3f input=03970f840fc7b739]*/
|
||||
{
|
||||
_NCURSES_COLOR_VAL_TYPE f, b;
|
||||
|
||||
|
@ -3838,7 +3852,7 @@ _curses_pair_content_impl(PyObject *module, int pair_number)
|
|||
|
||||
if (_CURSES_PAIR_NUMBER_FUNC(pair_number, &f, &b)==ERR) {
|
||||
PyErr_SetString(PyCursesError,
|
||||
"Argument 1 was out of range. (1..COLOR_PAIRS-1)");
|
||||
"Argument 1 was out of range. (0..COLOR_PAIRS-1)");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -3863,7 +3877,7 @@ _curses_pair_number_impl(PyObject *module, int attr)
|
|||
PyCursesInitialised;
|
||||
PyCursesInitialisedColor;
|
||||
|
||||
return PyLong_FromLong(attr_to_color_pair(attr));
|
||||
return PyLong_FromLong(PAIR_NUMBER(attr));
|
||||
}
|
||||
|
||||
/*[clinic input]
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#define PY_SSIZE_T_CLEAN
|
||||
#include "Python.h"
|
||||
#include "structmember.h" // PyMemberDef
|
||||
#include <stddef.h> // offsetof()
|
||||
|
||||
#ifdef STDC_HEADERS
|
||||
|
@ -21,6 +22,7 @@ module array
|
|||
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=7d1b8d7f5958fd83]*/
|
||||
|
||||
struct arrayobject; /* Forward */
|
||||
static struct PyModuleDef arraymodule;
|
||||
|
||||
/* All possible arraydescr values are defined in the vector "descriptors"
|
||||
* below. That's defined later because the appropriate get and set
|
||||
|
@ -46,8 +48,6 @@ typedef struct arrayobject {
|
|||
Py_ssize_t ob_exports; /* Number of exported buffers */
|
||||
} arrayobject;
|
||||
|
||||
static PyTypeObject Arraytype;
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
Py_ssize_t index;
|
||||
|
@ -55,9 +55,21 @@ typedef struct {
|
|||
PyObject* (*getitem)(struct arrayobject *, Py_ssize_t);
|
||||
} arrayiterobject;
|
||||
|
||||
static PyTypeObject PyArrayIter_Type;
|
||||
typedef struct {
|
||||
PyTypeObject *ArrayType;
|
||||
PyTypeObject *ArrayIterType;
|
||||
} array_state;
|
||||
|
||||
#define PyArrayIter_Check(op) PyObject_TypeCheck(op, &PyArrayIter_Type)
|
||||
static array_state *
|
||||
get_array_state(PyObject *module)
|
||||
{
|
||||
return (array_state *)PyModule_GetState(module);
|
||||
}
|
||||
|
||||
#define find_array_state_by_type(tp) \
|
||||
(get_array_state(_PyType_GetModuleByDef(tp, &arraymodule)))
|
||||
#define get_array_state_by_class(cls) \
|
||||
(get_array_state(PyType_GetModule(cls)))
|
||||
|
||||
enum machine_format_code {
|
||||
UNKNOWN_FORMAT = -1,
|
||||
|
@ -105,8 +117,7 @@ enum machine_format_code {
|
|||
*/
|
||||
#include "clinic/arraymodule.c.h"
|
||||
|
||||
#define array_Check(op) PyObject_TypeCheck(op, &Arraytype)
|
||||
#define array_CheckExact(op) Py_IS_TYPE(op, &Arraytype)
|
||||
#define array_Check(op, state) PyObject_TypeCheck(op, state->ArrayType)
|
||||
|
||||
static int
|
||||
array_resize(arrayobject *self, Py_ssize_t newsize)
|
||||
|
@ -562,9 +573,9 @@ static const struct arraydescr descriptors[] = {
|
|||
Implementations of array object methods.
|
||||
****************************************************************************/
|
||||
/*[clinic input]
|
||||
class array.array "arrayobject *" "&Arraytype"
|
||||
class array.array "arrayobject *" "ArrayType"
|
||||
[clinic start generated code]*/
|
||||
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=ad43d37e942a8854]*/
|
||||
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=a5c29edf59f176a3]*/
|
||||
|
||||
static PyObject *
|
||||
newarrayobject(PyTypeObject *type, Py_ssize_t size, const struct arraydescr *descr)
|
||||
|
@ -607,8 +618,11 @@ newarrayobject(PyTypeObject *type, Py_ssize_t size, const struct arraydescr *des
|
|||
static PyObject *
|
||||
getarrayitem(PyObject *op, Py_ssize_t i)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
array_state *state = find_array_state_by_type(Py_TYPE(op));
|
||||
assert(array_Check(op, state));
|
||||
#endif
|
||||
arrayobject *ap;
|
||||
assert(array_Check(op));
|
||||
ap = (arrayobject *)op;
|
||||
assert(i>=0 && i<Py_SIZE(ap));
|
||||
return (*ap->ob_descr->getitem)(ap, i);
|
||||
|
@ -649,23 +663,27 @@ ins1(arrayobject *self, Py_ssize_t where, PyObject *v)
|
|||
static void
|
||||
array_dealloc(arrayobject *op)
|
||||
{
|
||||
PyTypeObject *tp = Py_TYPE(op);
|
||||
|
||||
if (op->weakreflist != NULL)
|
||||
PyObject_ClearWeakRefs((PyObject *) op);
|
||||
if (op->ob_item != NULL)
|
||||
PyMem_Free(op->ob_item);
|
||||
Py_TYPE(op)->tp_free((PyObject *)op);
|
||||
tp->tp_free(op);
|
||||
Py_DECREF(tp);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
array_richcompare(PyObject *v, PyObject *w, int op)
|
||||
{
|
||||
array_state *state = find_array_state_by_type(Py_TYPE(v));
|
||||
arrayobject *va, *wa;
|
||||
PyObject *vi = NULL;
|
||||
PyObject *wi = NULL;
|
||||
Py_ssize_t i, k;
|
||||
PyObject *res;
|
||||
|
||||
if (!array_Check(v) || !array_Check(w))
|
||||
if (!array_Check(v, state) || !array_Check(w, state))
|
||||
Py_RETURN_NOTIMPLEMENTED;
|
||||
|
||||
va = (arrayobject *)v;
|
||||
|
@ -787,7 +805,9 @@ array_item(arrayobject *a, Py_ssize_t i)
|
|||
static PyObject *
|
||||
array_slice(arrayobject *a, Py_ssize_t ilow, Py_ssize_t ihigh)
|
||||
{
|
||||
array_state *state = find_array_state_by_type(Py_TYPE(a));
|
||||
arrayobject *np;
|
||||
|
||||
if (ilow < 0)
|
||||
ilow = 0;
|
||||
else if (ilow > Py_SIZE(a))
|
||||
|
@ -798,7 +818,7 @@ array_slice(arrayobject *a, Py_ssize_t ilow, Py_ssize_t ihigh)
|
|||
ihigh = ilow;
|
||||
else if (ihigh > Py_SIZE(a))
|
||||
ihigh = Py_SIZE(a);
|
||||
np = (arrayobject *) newarrayobject(&Arraytype, ihigh - ilow, a->ob_descr);
|
||||
np = (arrayobject *) newarrayobject(state->ArrayType, ihigh - ilow, a->ob_descr);
|
||||
if (np == NULL)
|
||||
return NULL;
|
||||
if (ihigh > ilow) {
|
||||
|
@ -841,9 +861,10 @@ array_array___deepcopy__(arrayobject *self, PyObject *unused)
|
|||
static PyObject *
|
||||
array_concat(arrayobject *a, PyObject *bb)
|
||||
{
|
||||
array_state *state = find_array_state_by_type(Py_TYPE(a));
|
||||
Py_ssize_t size;
|
||||
arrayobject *np;
|
||||
if (!array_Check(bb)) {
|
||||
if (!array_Check(bb, state)) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"can only append array (not \"%.200s\") to array",
|
||||
Py_TYPE(bb)->tp_name);
|
||||
|
@ -858,7 +879,7 @@ array_concat(arrayobject *a, PyObject *bb)
|
|||
return PyErr_NoMemory();
|
||||
}
|
||||
size = Py_SIZE(a) + Py_SIZE(b);
|
||||
np = (arrayobject *) newarrayobject(&Arraytype, size, a->ob_descr);
|
||||
np = (arrayobject *) newarrayobject(state->ArrayType, size, a->ob_descr);
|
||||
if (np == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -876,6 +897,7 @@ array_concat(arrayobject *a, PyObject *bb)
|
|||
static PyObject *
|
||||
array_repeat(arrayobject *a, Py_ssize_t n)
|
||||
{
|
||||
array_state *state = find_array_state_by_type(Py_TYPE(a));
|
||||
Py_ssize_t size;
|
||||
arrayobject *np;
|
||||
Py_ssize_t oldbytes, newbytes;
|
||||
|
@ -885,7 +907,7 @@ array_repeat(arrayobject *a, Py_ssize_t n)
|
|||
return PyErr_NoMemory();
|
||||
}
|
||||
size = Py_SIZE(a) * n;
|
||||
np = (arrayobject *) newarrayobject(&Arraytype, size, a->ob_descr);
|
||||
np = (arrayobject *) newarrayobject(state->ArrayType, size, a->ob_descr);
|
||||
if (np == NULL)
|
||||
return NULL;
|
||||
if (size == 0)
|
||||
|
@ -958,7 +980,10 @@ array_ass_item(arrayobject *a, Py_ssize_t i, PyObject *v)
|
|||
static int
|
||||
setarrayitem(PyObject *a, Py_ssize_t i, PyObject *v)
|
||||
{
|
||||
assert(array_Check(a));
|
||||
#ifndef NDEBUG
|
||||
array_state *state = find_array_state_by_type(Py_TYPE(a));
|
||||
assert(array_Check(a, state));
|
||||
#endif
|
||||
return array_ass_item((arrayobject *)a, i, v);
|
||||
}
|
||||
|
||||
|
@ -986,11 +1011,11 @@ array_iter_extend(arrayobject *self, PyObject *bb)
|
|||
}
|
||||
|
||||
static int
|
||||
array_do_extend(arrayobject *self, PyObject *bb)
|
||||
array_do_extend(array_state *state, arrayobject *self, PyObject *bb)
|
||||
{
|
||||
Py_ssize_t size, oldsize, bbsize;
|
||||
|
||||
if (!array_Check(bb))
|
||||
if (!array_Check(bb, state))
|
||||
return array_iter_extend(self, bb);
|
||||
#define b ((arrayobject *)bb)
|
||||
if (self->ob_descr != b->ob_descr) {
|
||||
|
@ -1021,13 +1046,15 @@ array_do_extend(arrayobject *self, PyObject *bb)
|
|||
static PyObject *
|
||||
array_inplace_concat(arrayobject *self, PyObject *bb)
|
||||
{
|
||||
if (!array_Check(bb)) {
|
||||
array_state *state = find_array_state_by_type(Py_TYPE(self));
|
||||
|
||||
if (!array_Check(bb, state)) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"can only extend array with array (not \"%.200s\")",
|
||||
Py_TYPE(bb)->tp_name);
|
||||
return NULL;
|
||||
}
|
||||
if (array_do_extend(self, bb) == -1)
|
||||
if (array_do_extend(state, self, bb) == -1)
|
||||
return NULL;
|
||||
Py_INCREF(self);
|
||||
return (PyObject *)self;
|
||||
|
@ -1232,6 +1259,7 @@ array_array_pop_impl(arrayobject *self, Py_ssize_t i)
|
|||
/*[clinic input]
|
||||
array.array.extend
|
||||
|
||||
cls: defining_class
|
||||
bb: object
|
||||
/
|
||||
|
||||
|
@ -1239,10 +1267,12 @@ Append items to the end of the array.
|
|||
[clinic start generated code]*/
|
||||
|
||||
static PyObject *
|
||||
array_array_extend(arrayobject *self, PyObject *bb)
|
||||
/*[clinic end generated code: output=bbddbc8e8bef871d input=43be86aba5c31e44]*/
|
||||
array_array_extend_impl(arrayobject *self, PyTypeObject *cls, PyObject *bb)
|
||||
/*[clinic end generated code: output=e65eb7588f0bc266 input=8eb6817ec4d2cb62]*/
|
||||
{
|
||||
if (array_do_extend(self, bb) == -1)
|
||||
array_state *state = get_array_state_by_class(cls);
|
||||
|
||||
if (array_do_extend(state, self, bb) == -1)
|
||||
return NULL;
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
@ -1928,6 +1958,7 @@ array__array_reconstructor_impl(PyObject *module, PyTypeObject *arraytype,
|
|||
PyObject *items)
|
||||
/*[clinic end generated code: output=e05263141ba28365 input=2464dc8f4c7736b5]*/
|
||||
{
|
||||
array_state *state = get_array_state(module);
|
||||
PyObject *converted_items;
|
||||
PyObject *result;
|
||||
const struct arraydescr *descr;
|
||||
|
@ -1938,10 +1969,10 @@ array__array_reconstructor_impl(PyObject *module, PyTypeObject *arraytype,
|
|||
Py_TYPE(arraytype)->tp_name);
|
||||
return NULL;
|
||||
}
|
||||
if (!PyType_IsSubtype(arraytype, &Arraytype)) {
|
||||
if (!PyType_IsSubtype(arraytype, state->ArrayType)) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"%.200s is not a subtype of %.200s",
|
||||
arraytype->tp_name, Arraytype.tp_name);
|
||||
arraytype->tp_name, state->ArrayType->tp_name);
|
||||
return NULL;
|
||||
}
|
||||
for (descr = descriptors; descr->typecode != '\0'; descr++) {
|
||||
|
@ -2287,6 +2318,8 @@ array_repr(arrayobject *a)
|
|||
static PyObject*
|
||||
array_subscr(arrayobject* self, PyObject* item)
|
||||
{
|
||||
array_state *state = find_array_state_by_type(Py_TYPE(self));
|
||||
|
||||
if (PyIndex_Check(item)) {
|
||||
Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
|
||||
if (i==-1 && PyErr_Occurred()) {
|
||||
|
@ -2310,10 +2343,10 @@ array_subscr(arrayobject* self, PyObject* item)
|
|||
step);
|
||||
|
||||
if (slicelength <= 0) {
|
||||
return newarrayobject(&Arraytype, 0, self->ob_descr);
|
||||
return newarrayobject(state->ArrayType, 0, self->ob_descr);
|
||||
}
|
||||
else if (step == 1) {
|
||||
PyObject *result = newarrayobject(&Arraytype,
|
||||
PyObject *result = newarrayobject(state->ArrayType,
|
||||
slicelength, self->ob_descr);
|
||||
if (result == NULL)
|
||||
return NULL;
|
||||
|
@ -2323,7 +2356,7 @@ array_subscr(arrayobject* self, PyObject* item)
|
|||
return result;
|
||||
}
|
||||
else {
|
||||
result = newarrayobject(&Arraytype, slicelength, self->ob_descr);
|
||||
result = newarrayobject(state->ArrayType, slicelength, self->ob_descr);
|
||||
if (!result) return NULL;
|
||||
|
||||
ar = (arrayobject*)result;
|
||||
|
@ -2349,6 +2382,7 @@ static int
|
|||
array_ass_subscr(arrayobject* self, PyObject* item, PyObject* value)
|
||||
{
|
||||
Py_ssize_t start, stop, step, slicelength, needed;
|
||||
array_state* state = find_array_state_by_type(Py_TYPE(self));
|
||||
arrayobject* other;
|
||||
int itemsize;
|
||||
|
||||
|
@ -2390,7 +2424,7 @@ array_ass_subscr(arrayobject* self, PyObject* item, PyObject* value)
|
|||
other = NULL;
|
||||
needed = 0;
|
||||
}
|
||||
else if (array_Check(value)) {
|
||||
else if (array_Check(value, state)) {
|
||||
other = (arrayobject *)value;
|
||||
needed = Py_SIZE(other);
|
||||
if (self == other) {
|
||||
|
@ -2502,12 +2536,6 @@ array_ass_subscr(arrayobject* self, PyObject* item, PyObject* value)
|
|||
}
|
||||
}
|
||||
|
||||
static PyMappingMethods array_as_mapping = {
|
||||
(lenfunc)array_length,
|
||||
(binaryfunc)array_subscr,
|
||||
(objobjargproc)array_ass_subscr
|
||||
};
|
||||
|
||||
static const void *emptybuf = "";
|
||||
|
||||
|
||||
|
@ -2558,32 +2586,15 @@ array_buffer_relbuf(arrayobject *self, Py_buffer *view)
|
|||
self->ob_exports--;
|
||||
}
|
||||
|
||||
static PySequenceMethods array_as_sequence = {
|
||||
(lenfunc)array_length, /*sq_length*/
|
||||
(binaryfunc)array_concat, /*sq_concat*/
|
||||
(ssizeargfunc)array_repeat, /*sq_repeat*/
|
||||
(ssizeargfunc)array_item, /*sq_item*/
|
||||
0, /*sq_slice*/
|
||||
(ssizeobjargproc)array_ass_item, /*sq_ass_item*/
|
||||
0, /*sq_ass_slice*/
|
||||
(objobjproc)array_contains, /*sq_contains*/
|
||||
(binaryfunc)array_inplace_concat, /*sq_inplace_concat*/
|
||||
(ssizeargfunc)array_inplace_repeat /*sq_inplace_repeat*/
|
||||
};
|
||||
|
||||
static PyBufferProcs array_as_buffer = {
|
||||
(getbufferproc)array_buffer_getbuf,
|
||||
(releasebufferproc)array_buffer_relbuf
|
||||
};
|
||||
|
||||
static PyObject *
|
||||
array_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
array_state *state = find_array_state_by_type(type);
|
||||
int c;
|
||||
PyObject *initial = NULL, *it = NULL;
|
||||
const struct arraydescr *descr;
|
||||
|
||||
if (type == &Arraytype && !_PyArg_NoKeywords("array.array", kwds))
|
||||
if (type == state->ArrayType && !_PyArg_NoKeywords("array.array", kwds))
|
||||
return NULL;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "C|O:array", &c, &initial))
|
||||
|
@ -2600,7 +2611,7 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|||
"an array with typecode '%c'", c);
|
||||
return NULL;
|
||||
}
|
||||
else if (array_Check(initial) &&
|
||||
else if (array_Check(initial, state) &&
|
||||
((arrayobject*)initial)->ob_descr->typecode == 'u') {
|
||||
PyErr_Format(PyExc_TypeError, "cannot use a unicode array to "
|
||||
"initialize an array with typecode '%c'", c);
|
||||
|
@ -2613,7 +2624,7 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|||
|| PyBytes_Check(initial)
|
||||
|| PyTuple_Check(initial)
|
||||
|| ((c=='u') && PyUnicode_Check(initial))
|
||||
|| (array_Check(initial)
|
||||
|| (array_Check(initial, state)
|
||||
&& c == ((arrayobject*)initial)->ob_descr->typecode))) {
|
||||
it = PyObject_GetIter(initial);
|
||||
if (it == NULL)
|
||||
|
@ -2634,7 +2645,7 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|||
len = 0;
|
||||
else if (PyList_Check(initial))
|
||||
len = PyList_GET_SIZE(initial);
|
||||
else if (PyTuple_Check(initial) || array_Check(initial))
|
||||
else if (PyTuple_Check(initial) || array_Check(initial, state))
|
||||
len = Py_SIZE(initial);
|
||||
else
|
||||
len = 0;
|
||||
|
@ -2643,7 +2654,7 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|||
if (a == NULL)
|
||||
return NULL;
|
||||
|
||||
if (len > 0 && !array_Check(initial)) {
|
||||
if (len > 0 && !array_Check(initial, state)) {
|
||||
Py_ssize_t i;
|
||||
for (i = 0; i < len; i++) {
|
||||
PyObject *v =
|
||||
|
@ -2688,7 +2699,7 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|||
self->allocated = n;
|
||||
}
|
||||
}
|
||||
else if (initial != NULL && array_Check(initial) && len > 0) {
|
||||
else if (initial != NULL && array_Check(initial, state) && len > 0) {
|
||||
arrayobject *self = (arrayobject *)a;
|
||||
arrayobject *other = (arrayobject *)initial;
|
||||
memcpy(self->ob_item, other->ob_item, len * other->ob_descr->itemsize);
|
||||
|
@ -2777,67 +2788,73 @@ itemsize -- the length in bytes of one array item\n\
|
|||
|
||||
static PyObject *array_iter(arrayobject *ao);
|
||||
|
||||
static PyTypeObject Arraytype = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"array.array",
|
||||
sizeof(arrayobject),
|
||||
0,
|
||||
(destructor)array_dealloc, /* tp_dealloc */
|
||||
0, /* tp_vectorcall_offset */
|
||||
0, /* tp_getattr */
|
||||
0, /* tp_setattr */
|
||||
0, /* tp_as_async */
|
||||
(reprfunc)array_repr, /* tp_repr */
|
||||
0, /* tp_as_number*/
|
||||
&array_as_sequence, /* tp_as_sequence*/
|
||||
&array_as_mapping, /* tp_as_mapping*/
|
||||
0, /* tp_hash */
|
||||
0, /* tp_call */
|
||||
0, /* tp_str */
|
||||
PyObject_GenericGetAttr, /* tp_getattro */
|
||||
0, /* tp_setattro */
|
||||
&array_as_buffer, /* tp_as_buffer*/
|
||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
|
||||
arraytype_doc, /* tp_doc */
|
||||
0, /* tp_traverse */
|
||||
0, /* tp_clear */
|
||||
array_richcompare, /* tp_richcompare */
|
||||
offsetof(arrayobject, weakreflist), /* tp_weaklistoffset */
|
||||
(getiterfunc)array_iter, /* tp_iter */
|
||||
0, /* tp_iternext */
|
||||
array_methods, /* tp_methods */
|
||||
0, /* tp_members */
|
||||
array_getsets, /* tp_getset */
|
||||
0, /* tp_base */
|
||||
0, /* tp_dict */
|
||||
0, /* tp_descr_get */
|
||||
0, /* tp_descr_set */
|
||||
0, /* tp_dictoffset */
|
||||
0, /* tp_init */
|
||||
PyType_GenericAlloc, /* tp_alloc */
|
||||
array_new, /* tp_new */
|
||||
PyObject_Del, /* tp_free */
|
||||
static struct PyMemberDef array_members[] = {
|
||||
{"__weaklistoffset__", T_PYSSIZET, offsetof(arrayobject, weakreflist), READONLY},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
static PyType_Slot array_slots[] = {
|
||||
{Py_tp_dealloc, array_dealloc},
|
||||
{Py_tp_repr, array_repr},
|
||||
{Py_tp_getattro, PyObject_GenericGetAttr},
|
||||
{Py_tp_doc, (void *)arraytype_doc},
|
||||
{Py_tp_richcompare, array_richcompare},
|
||||
{Py_tp_iter, array_iter},
|
||||
{Py_tp_methods, array_methods},
|
||||
{Py_tp_members, array_members},
|
||||
{Py_tp_getset, array_getsets},
|
||||
{Py_tp_alloc, PyType_GenericAlloc},
|
||||
{Py_tp_new, array_new},
|
||||
{Py_tp_free, PyObject_Del},
|
||||
|
||||
/* as sequence */
|
||||
{Py_sq_length, array_length},
|
||||
{Py_sq_concat, array_concat},
|
||||
{Py_sq_repeat, array_repeat},
|
||||
{Py_sq_item, array_item},
|
||||
{Py_sq_ass_item, array_ass_item},
|
||||
{Py_sq_contains, array_contains},
|
||||
{Py_sq_inplace_concat, array_inplace_concat},
|
||||
{Py_sq_inplace_repeat, array_inplace_repeat},
|
||||
|
||||
/* as mapping */
|
||||
{Py_mp_length, array_length},
|
||||
{Py_mp_subscript, array_subscr},
|
||||
{Py_mp_ass_subscript, array_ass_subscr},
|
||||
|
||||
/* as buffer */
|
||||
{Py_bf_getbuffer, array_buffer_getbuf},
|
||||
{Py_bf_releasebuffer, array_buffer_relbuf},
|
||||
|
||||
{0, NULL},
|
||||
};
|
||||
|
||||
static PyType_Spec array_spec = {
|
||||
.name = "array.array",
|
||||
.basicsize = sizeof(arrayobject),
|
||||
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
|
||||
.slots = array_slots,
|
||||
};
|
||||
|
||||
/*********************** Array Iterator **************************/
|
||||
|
||||
/*[clinic input]
|
||||
class array.arrayiterator "arrayiterobject *" "&PyArrayIter_Type"
|
||||
class array.arrayiterator "arrayiterobject *" "find_array_state_by_type(type)->ArrayIterType"
|
||||
[clinic start generated code]*/
|
||||
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=5aefd2d74d8c8e30]*/
|
||||
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=fb46d5ef98dd95ff]*/
|
||||
|
||||
static PyObject *
|
||||
array_iter(arrayobject *ao)
|
||||
{
|
||||
array_state *state = find_array_state_by_type(Py_TYPE(ao));
|
||||
arrayiterobject *it;
|
||||
|
||||
if (!array_Check(ao)) {
|
||||
if (!array_Check(ao, state)) {
|
||||
PyErr_BadInternalCall();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
it = PyObject_GC_New(arrayiterobject, &PyArrayIter_Type);
|
||||
it = PyObject_GC_New(arrayiterobject, state->ArrayIterType);
|
||||
if (it == NULL)
|
||||
return NULL;
|
||||
|
||||
|
@ -2855,12 +2872,17 @@ arrayiter_next(arrayiterobject *it)
|
|||
arrayobject *ao;
|
||||
|
||||
assert(it != NULL);
|
||||
assert(PyArrayIter_Check(it));
|
||||
#ifndef NDEBUG
|
||||
array_state *state = find_array_state_by_type(Py_TYPE(it));
|
||||
assert(PyObject_TypeCheck(it, state->ArrayIterType));
|
||||
#endif
|
||||
ao = it->ao;
|
||||
if (ao == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
assert(array_Check(ao));
|
||||
#ifndef NDEBUG
|
||||
assert(array_Check(ao, state));
|
||||
#endif
|
||||
if (it->index < Py_SIZE(ao)) {
|
||||
return (*it->getitem)(ao, it->index++);
|
||||
}
|
||||
|
@ -2872,9 +2894,12 @@ arrayiter_next(arrayiterobject *it)
|
|||
static void
|
||||
arrayiter_dealloc(arrayiterobject *it)
|
||||
{
|
||||
PyTypeObject *tp = Py_TYPE(it);
|
||||
|
||||
PyObject_GC_UnTrack(it);
|
||||
Py_XDECREF(it->ao);
|
||||
PyObject_GC_Del(it);
|
||||
Py_DECREF(tp);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -2932,86 +2957,103 @@ static PyMethodDef arrayiter_methods[] = {
|
|||
{NULL, NULL} /* sentinel */
|
||||
};
|
||||
|
||||
static PyTypeObject PyArrayIter_Type = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"arrayiterator", /* tp_name */
|
||||
sizeof(arrayiterobject), /* tp_basicsize */
|
||||
0, /* tp_itemsize */
|
||||
/* methods */
|
||||
(destructor)arrayiter_dealloc, /* tp_dealloc */
|
||||
0, /* tp_vectorcall_offset */
|
||||
0, /* tp_getattr */
|
||||
0, /* tp_setattr */
|
||||
0, /* tp_as_async */
|
||||
0, /* tp_repr */
|
||||
0, /* tp_as_number */
|
||||
0, /* tp_as_sequence */
|
||||
0, /* tp_as_mapping */
|
||||
0, /* tp_hash */
|
||||
0, /* tp_call */
|
||||
0, /* tp_str */
|
||||
PyObject_GenericGetAttr, /* tp_getattro */
|
||||
0, /* tp_setattro */
|
||||
0, /* tp_as_buffer */
|
||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
|
||||
0, /* tp_doc */
|
||||
(traverseproc)arrayiter_traverse, /* tp_traverse */
|
||||
0, /* tp_clear */
|
||||
0, /* tp_richcompare */
|
||||
0, /* tp_weaklistoffset */
|
||||
PyObject_SelfIter, /* tp_iter */
|
||||
(iternextfunc)arrayiter_next, /* tp_iternext */
|
||||
arrayiter_methods, /* tp_methods */
|
||||
static PyType_Slot arrayiter_slots[] = {
|
||||
{Py_tp_dealloc, arrayiter_dealloc},
|
||||
{Py_tp_getattro, PyObject_GenericGetAttr},
|
||||
{Py_tp_traverse, arrayiter_traverse},
|
||||
{Py_tp_iter, PyObject_SelfIter},
|
||||
{Py_tp_iternext, arrayiter_next},
|
||||
{Py_tp_methods, arrayiter_methods},
|
||||
{0, NULL},
|
||||
};
|
||||
|
||||
static PyType_Spec arrayiter_spec = {
|
||||
.name = "array.arrayiterator",
|
||||
.basicsize = sizeof(arrayiterobject),
|
||||
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
|
||||
.slots = arrayiter_slots,
|
||||
};
|
||||
|
||||
|
||||
/*********************** Install Module **************************/
|
||||
|
||||
static int
|
||||
array_traverse(PyObject *module, visitproc visit, void *arg)
|
||||
{
|
||||
array_state *state = get_array_state(module);
|
||||
Py_VISIT(state->ArrayType);
|
||||
Py_VISIT(state->ArrayIterType);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
array_clear(PyObject *module)
|
||||
{
|
||||
array_state *state = get_array_state(module);
|
||||
Py_CLEAR(state->ArrayType);
|
||||
Py_CLEAR(state->ArrayIterType);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
array_free(void *module)
|
||||
{
|
||||
array_clear((PyObject *)module);
|
||||
}
|
||||
|
||||
/* No functions in array module. */
|
||||
static PyMethodDef a_methods[] = {
|
||||
ARRAY__ARRAY_RECONSTRUCTOR_METHODDEF
|
||||
{NULL, NULL, 0, NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
#define CREATE_TYPE(module, type, spec) \
|
||||
do { \
|
||||
type = (PyTypeObject *)PyType_FromModuleAndSpec(module, spec, NULL); \
|
||||
if (type == NULL) { \
|
||||
return -1; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static int
|
||||
array_modexec(PyObject *m)
|
||||
{
|
||||
array_state *state = get_array_state(m);
|
||||
char buffer[Py_ARRAY_LENGTH(descriptors)], *p;
|
||||
PyObject *typecodes;
|
||||
const struct arraydescr *descr;
|
||||
|
||||
if (PyType_Ready(&Arraytype) < 0)
|
||||
return -1;
|
||||
Py_SET_TYPE(&PyArrayIter_Type, &PyType_Type);
|
||||
CREATE_TYPE(m, state->ArrayType, &array_spec);
|
||||
CREATE_TYPE(m, state->ArrayIterType, &arrayiter_spec);
|
||||
Py_SET_TYPE(state->ArrayIterType, &PyType_Type);
|
||||
|
||||
Py_INCREF((PyObject *)&Arraytype);
|
||||
if (PyModule_AddObject(m, "ArrayType", (PyObject *)&Arraytype) < 0) {
|
||||
Py_DECREF((PyObject *)&Arraytype);
|
||||
Py_INCREF((PyObject *)state->ArrayType);
|
||||
if (PyModule_AddObject(m, "ArrayType", (PyObject *)state->ArrayType) < 0) {
|
||||
Py_DECREF((PyObject *)state->ArrayType);
|
||||
return -1;
|
||||
}
|
||||
|
||||
PyObject *abc_mod = PyImport_ImportModule("collections.abc");
|
||||
if (!abc_mod) {
|
||||
Py_DECREF((PyObject *)&Arraytype);
|
||||
Py_DECREF((PyObject *)state->ArrayType);
|
||||
return -1;
|
||||
}
|
||||
PyObject *mutablesequence = PyObject_GetAttrString(abc_mod, "MutableSequence");
|
||||
Py_DECREF(abc_mod);
|
||||
if (!mutablesequence) {
|
||||
Py_DECREF((PyObject *)&Arraytype);
|
||||
Py_DECREF((PyObject *)state->ArrayType);
|
||||
return -1;
|
||||
}
|
||||
PyObject *res = PyObject_CallMethod(mutablesequence, "register", "O", (PyObject *)&Arraytype);
|
||||
PyObject *res = PyObject_CallMethod(mutablesequence, "register", "O",
|
||||
(PyObject *)state->ArrayType);
|
||||
Py_DECREF(mutablesequence);
|
||||
if (!res) {
|
||||
Py_DECREF((PyObject *)&Arraytype);
|
||||
Py_DECREF((PyObject *)state->ArrayType);
|
||||
return -1;
|
||||
}
|
||||
Py_DECREF(res);
|
||||
|
||||
Py_INCREF((PyObject *)&Arraytype);
|
||||
if (PyModule_AddObject(m, "array", (PyObject *)&Arraytype) < 0) {
|
||||
Py_DECREF((PyObject *)&Arraytype);
|
||||
if (PyModule_AddType(m, state->ArrayType) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -3035,15 +3077,15 @@ static PyModuleDef_Slot arrayslots[] = {
|
|||
|
||||
|
||||
static struct PyModuleDef arraymodule = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"array",
|
||||
module_doc,
|
||||
0,
|
||||
a_methods,
|
||||
arrayslots,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
.m_base = PyModuleDef_HEAD_INIT,
|
||||
.m_name = "array",
|
||||
.m_size = sizeof(array_state),
|
||||
.m_doc = module_doc,
|
||||
.m_methods = a_methods,
|
||||
.m_slots = arrayslots,
|
||||
.m_traverse = array_traverse,
|
||||
.m_clear = array_clear,
|
||||
.m_free = array_free,
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -1958,7 +1958,7 @@ PyDoc_STRVAR(_curses_color_content__doc__,
|
|||
"Return the red, green, and blue (RGB) components of the specified color.\n"
|
||||
"\n"
|
||||
" color_number\n"
|
||||
" The number of the color (0 - COLORS).\n"
|
||||
" The number of the color (0 - (COLORS-1)).\n"
|
||||
"\n"
|
||||
"A 3-tuple is returned, containing the R, G, B values for the given color,\n"
|
||||
"which will be between 0 (no component) and 1000 (maximum amount of component).");
|
||||
|
@ -1985,13 +1985,13 @@ exit:
|
|||
}
|
||||
|
||||
PyDoc_STRVAR(_curses_color_pair__doc__,
|
||||
"color_pair($module, color_number, /)\n"
|
||||
"color_pair($module, pair_number, /)\n"
|
||||
"--\n"
|
||||
"\n"
|
||||
"Return the attribute value for displaying text in the specified color.\n"
|
||||
"\n"
|
||||
" color_number\n"
|
||||
" The number of the color (0 - COLORS).\n"
|
||||
" pair_number\n"
|
||||
" The number of the color pair.\n"
|
||||
"\n"
|
||||
"This attribute value can be combined with A_STANDOUT, A_REVERSE, and the\n"
|
||||
"other A_* attributes. pair_number() is the counterpart to this function.");
|
||||
|
@ -2000,18 +2000,19 @@ PyDoc_STRVAR(_curses_color_pair__doc__,
|
|||
{"color_pair", (PyCFunction)_curses_color_pair, METH_O, _curses_color_pair__doc__},
|
||||
|
||||
static PyObject *
|
||||
_curses_color_pair_impl(PyObject *module, int color_number);
|
||||
_curses_color_pair_impl(PyObject *module, int pair_number);
|
||||
|
||||
static PyObject *
|
||||
_curses_color_pair(PyObject *module, PyObject *arg)
|
||||
{
|
||||
PyObject *return_value = NULL;
|
||||
int color_number;
|
||||
int pair_number;
|
||||
|
||||
if (!color_converter(arg, &color_number)) {
|
||||
pair_number = _PyLong_AsInt(arg);
|
||||
if (pair_number == -1 && PyErr_Occurred()) {
|
||||
goto exit;
|
||||
}
|
||||
return_value = _curses_color_pair_impl(module, color_number);
|
||||
return_value = _curses_color_pair_impl(module, pair_number);
|
||||
|
||||
exit:
|
||||
return return_value;
|
||||
|
@ -2542,7 +2543,7 @@ PyDoc_STRVAR(_curses_init_color__doc__,
|
|||
"Change the definition of a color.\n"
|
||||
"\n"
|
||||
" color_number\n"
|
||||
" The number of the color to be changed (0 - COLORS).\n"
|
||||
" The number of the color to be changed (0 - (COLORS-1)).\n"
|
||||
" r\n"
|
||||
" Red component (0 - 1000).\n"
|
||||
" g\n"
|
||||
|
@ -2552,7 +2553,7 @@ PyDoc_STRVAR(_curses_init_color__doc__,
|
|||
"\n"
|
||||
"When init_color() is used, all occurrences of that color on the screen\n"
|
||||
"immediately change to the new definition. This function is a no-op on\n"
|
||||
"most terminals; it is active only if can_change_color() returns 1.");
|
||||
"most terminals; it is active only if can_change_color() returns true.");
|
||||
|
||||
#define _CURSES_INIT_COLOR_METHODDEF \
|
||||
{"init_color", (PyCFunction)(void(*)(void))_curses_init_color, METH_FASTCALL, _curses_init_color__doc__},
|
||||
|
@ -2600,9 +2601,9 @@ PyDoc_STRVAR(_curses_init_pair__doc__,
|
|||
" pair_number\n"
|
||||
" The number of the color-pair to be changed (1 - (COLOR_PAIRS-1)).\n"
|
||||
" fg\n"
|
||||
" Foreground color number (0 - COLORS).\n"
|
||||
" Foreground color number (-1 - (COLORS-1)).\n"
|
||||
" bg\n"
|
||||
" Background color number (0 - COLORS).\n"
|
||||
" Background color number (-1 - (COLORS-1)).\n"
|
||||
"\n"
|
||||
"If the color-pair was previously initialized, the screen is refreshed and\n"
|
||||
"all occurrences of that color-pair are changed to the new definition.");
|
||||
|
@ -2627,10 +2628,10 @@ _curses_init_pair(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
|
|||
if (!pair_converter(args[0], &pair_number)) {
|
||||
goto exit;
|
||||
}
|
||||
if (!color_converter(args[1], &fg)) {
|
||||
if (!color_allow_default_converter(args[1], &fg)) {
|
||||
goto exit;
|
||||
}
|
||||
if (!color_converter(args[2], &bg)) {
|
||||
if (!color_allow_default_converter(args[2], &bg)) {
|
||||
goto exit;
|
||||
}
|
||||
return_value = _curses_init_pair_impl(module, pair_number, fg, bg);
|
||||
|
@ -3403,7 +3404,7 @@ PyDoc_STRVAR(_curses_pair_content__doc__,
|
|||
"Return a tuple (fg, bg) containing the colors for the requested color pair.\n"
|
||||
"\n"
|
||||
" pair_number\n"
|
||||
" The number of the color pair (1 - (COLOR_PAIRS-1)).");
|
||||
" The number of the color pair (0 - (COLOR_PAIRS-1)).");
|
||||
|
||||
#define _CURSES_PAIR_CONTENT_METHODDEF \
|
||||
{"pair_content", (PyCFunction)_curses_pair_content, METH_O, _curses_pair_content__doc__},
|
||||
|
@ -4288,4 +4289,4 @@ _curses_has_extended_color_support(PyObject *module, PyObject *Py_UNUSED(ignored
|
|||
#ifndef _CURSES_USE_DEFAULT_COLORS_METHODDEF
|
||||
#define _CURSES_USE_DEFAULT_COLORS_METHODDEF
|
||||
#endif /* !defined(_CURSES_USE_DEFAULT_COLORS_METHODDEF) */
|
||||
/*[clinic end generated code: output=92bad2172fef9747 input=a9049054013a1b77]*/
|
||||
/*[clinic end generated code: output=ae6559aa61200289 input=a9049054013a1b77]*/
|
||||
|
|
|
@ -108,7 +108,28 @@ PyDoc_STRVAR(array_array_extend__doc__,
|
|||
"Append items to the end of the array.");
|
||||
|
||||
#define ARRAY_ARRAY_EXTEND_METHODDEF \
|
||||
{"extend", (PyCFunction)array_array_extend, METH_O, array_array_extend__doc__},
|
||||
{"extend", (PyCFunction)(void(*)(void))array_array_extend, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, array_array_extend__doc__},
|
||||
|
||||
static PyObject *
|
||||
array_array_extend_impl(arrayobject *self, PyTypeObject *cls, PyObject *bb);
|
||||
|
||||
static PyObject *
|
||||
array_array_extend(arrayobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
|
||||
{
|
||||
PyObject *return_value = NULL;
|
||||
static const char * const _keywords[] = {"", NULL};
|
||||
static _PyArg_Parser _parser = {"O:extend", _keywords, 0};
|
||||
PyObject *bb;
|
||||
|
||||
if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
|
||||
&bb)) {
|
||||
goto exit;
|
||||
}
|
||||
return_value = array_array_extend_impl(self, cls, bb);
|
||||
|
||||
exit:
|
||||
return return_value;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(array_array_insert__doc__,
|
||||
"insert($self, i, v, /)\n"
|
||||
|
@ -514,4 +535,4 @@ PyDoc_STRVAR(array_arrayiterator___setstate____doc__,
|
|||
|
||||
#define ARRAY_ARRAYITERATOR___SETSTATE___METHODDEF \
|
||||
{"__setstate__", (PyCFunction)array_arrayiterator___setstate__, METH_O, array_arrayiterator___setstate____doc__},
|
||||
/*[clinic end generated code: output=91c1cded65a1285f input=a9049054013a1b77]*/
|
||||
/*[clinic end generated code: output=a7f71a18b994c88f input=a9049054013a1b77]*/
|
||||
|
|
|
@ -61,7 +61,13 @@
|
|||
*/
|
||||
#if defined(__APPLE__)
|
||||
|
||||
#if defined(__has_builtin) && __has_builtin(__builtin_available)
|
||||
#if defined(__has_builtin)
|
||||
#if __has_builtin(__builtin_available)
|
||||
#define HAVE_BUILTIN_AVAILABLE 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_BUILTIN_AVAILABLE
|
||||
# define HAVE_FSTATAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
|
||||
# define HAVE_FACCESSAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
|
||||
# define HAVE_FCHMODAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
|
||||
|
|
|
@ -1836,6 +1836,13 @@ error:
|
|||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
pyexpat_destructor(PyObject *op)
|
||||
{
|
||||
void *p = PyCapsule_GetPointer(op, PyExpat_CAPSULE_NAME);
|
||||
PyMem_Free(p);
|
||||
}
|
||||
|
||||
static int
|
||||
pyexpat_exec(PyObject *mod)
|
||||
{
|
||||
|
@ -1921,40 +1928,46 @@ pyexpat_exec(PyObject *mod)
|
|||
MYCONST(XML_PARAM_ENTITY_PARSING_ALWAYS);
|
||||
#undef MYCONST
|
||||
|
||||
static struct PyExpat_CAPI capi;
|
||||
struct PyExpat_CAPI *capi = PyMem_Calloc(1, sizeof(struct PyExpat_CAPI));
|
||||
if (capi == NULL) {
|
||||
PyErr_NoMemory();
|
||||
return -1;
|
||||
}
|
||||
/* initialize pyexpat dispatch table */
|
||||
capi.size = sizeof(capi);
|
||||
capi.magic = PyExpat_CAPI_MAGIC;
|
||||
capi.MAJOR_VERSION = XML_MAJOR_VERSION;
|
||||
capi.MINOR_VERSION = XML_MINOR_VERSION;
|
||||
capi.MICRO_VERSION = XML_MICRO_VERSION;
|
||||
capi.ErrorString = XML_ErrorString;
|
||||
capi.GetErrorCode = XML_GetErrorCode;
|
||||
capi.GetErrorColumnNumber = XML_GetErrorColumnNumber;
|
||||
capi.GetErrorLineNumber = XML_GetErrorLineNumber;
|
||||
capi.Parse = XML_Parse;
|
||||
capi.ParserCreate_MM = XML_ParserCreate_MM;
|
||||
capi.ParserFree = XML_ParserFree;
|
||||
capi.SetCharacterDataHandler = XML_SetCharacterDataHandler;
|
||||
capi.SetCommentHandler = XML_SetCommentHandler;
|
||||
capi.SetDefaultHandlerExpand = XML_SetDefaultHandlerExpand;
|
||||
capi.SetElementHandler = XML_SetElementHandler;
|
||||
capi.SetNamespaceDeclHandler = XML_SetNamespaceDeclHandler;
|
||||
capi.SetProcessingInstructionHandler = XML_SetProcessingInstructionHandler;
|
||||
capi.SetUnknownEncodingHandler = XML_SetUnknownEncodingHandler;
|
||||
capi.SetUserData = XML_SetUserData;
|
||||
capi.SetStartDoctypeDeclHandler = XML_SetStartDoctypeDeclHandler;
|
||||
capi.SetEncoding = XML_SetEncoding;
|
||||
capi.DefaultUnknownEncodingHandler = PyUnknownEncodingHandler;
|
||||
capi->size = sizeof(*capi);
|
||||
capi->magic = PyExpat_CAPI_MAGIC;
|
||||
capi->MAJOR_VERSION = XML_MAJOR_VERSION;
|
||||
capi->MINOR_VERSION = XML_MINOR_VERSION;
|
||||
capi->MICRO_VERSION = XML_MICRO_VERSION;
|
||||
capi->ErrorString = XML_ErrorString;
|
||||
capi->GetErrorCode = XML_GetErrorCode;
|
||||
capi->GetErrorColumnNumber = XML_GetErrorColumnNumber;
|
||||
capi->GetErrorLineNumber = XML_GetErrorLineNumber;
|
||||
capi->Parse = XML_Parse;
|
||||
capi->ParserCreate_MM = XML_ParserCreate_MM;
|
||||
capi->ParserFree = XML_ParserFree;
|
||||
capi->SetCharacterDataHandler = XML_SetCharacterDataHandler;
|
||||
capi->SetCommentHandler = XML_SetCommentHandler;
|
||||
capi->SetDefaultHandlerExpand = XML_SetDefaultHandlerExpand;
|
||||
capi->SetElementHandler = XML_SetElementHandler;
|
||||
capi->SetNamespaceDeclHandler = XML_SetNamespaceDeclHandler;
|
||||
capi->SetProcessingInstructionHandler = XML_SetProcessingInstructionHandler;
|
||||
capi->SetUnknownEncodingHandler = XML_SetUnknownEncodingHandler;
|
||||
capi->SetUserData = XML_SetUserData;
|
||||
capi->SetStartDoctypeDeclHandler = XML_SetStartDoctypeDeclHandler;
|
||||
capi->SetEncoding = XML_SetEncoding;
|
||||
capi->DefaultUnknownEncodingHandler = PyUnknownEncodingHandler;
|
||||
#if XML_COMBINED_VERSION >= 20100
|
||||
capi.SetHashSalt = XML_SetHashSalt;
|
||||
capi->SetHashSalt = XML_SetHashSalt;
|
||||
#else
|
||||
capi.SetHashSalt = NULL;
|
||||
capi->SetHashSalt = NULL;
|
||||
#endif
|
||||
|
||||
/* export using capsule */
|
||||
PyObject *capi_object = PyCapsule_New(&capi, PyExpat_CAPSULE_NAME, NULL);
|
||||
PyObject *capi_object = PyCapsule_New(capi, PyExpat_CAPSULE_NAME,
|
||||
pyexpat_destructor);
|
||||
if (capi_object == NULL) {
|
||||
PyMem_Free(capi);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -174,6 +174,7 @@ is_typing_name(PyObject *obj, int num, ...)
|
|||
break;
|
||||
}
|
||||
}
|
||||
va_end(names);
|
||||
if (!hit) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -185,7 +186,6 @@ is_typing_name(PyObject *obj, int num, ...)
|
|||
&& _PyUnicode_EqualToASCIIString(module, "typing");
|
||||
Py_DECREF(module);
|
||||
|
||||
va_end(names);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ is_generic_alias_in_args(PyObject *args) {
|
|||
Py_ssize_t nargs = PyTuple_GET_SIZE(args);
|
||||
for (Py_ssize_t iarg = 0; iarg < nargs; iarg++) {
|
||||
PyObject *arg = PyTuple_GET_ITEM(args, iarg);
|
||||
if (Py_TYPE(arg) == &Py_GenericAliasType) {
|
||||
if (PyObject_TypeCheck(arg, &Py_GenericAliasType)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
1639
Parser/parser.c
1639
Parser/parser.c
File diff suppressed because it is too large
Load Diff
|
@ -405,7 +405,7 @@ fstring_compile_expr(Parser *p, const char *expr_start, const char *expr_end,
|
|||
Parser *p2 = _PyPegen_Parser_New(tok, Py_fstring_input, p->flags, p->feature_version,
|
||||
NULL, p->arena);
|
||||
p2->starting_lineno = t->lineno + lines - 1;
|
||||
p2->starting_col_offset = p->tok->first_lineno == p->tok->lineno ? t->col_offset + cols : cols;
|
||||
p2->starting_col_offset = t->col_offset + cols;
|
||||
|
||||
expr = _PyPegen_run_parser(p2);
|
||||
|
||||
|
|
Loading…
Reference in New Issue