mirror of
https://github.com/python/cpython.git
synced 2025-09-19 07:00:59 +00:00
Merged revisions 58211-58220 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk ........ r58211 | facundo.batista | 2007-09-19 19:53:25 +0200 (Wed, 19 Sep 2007) | 4 lines Issue #1772851. Optimization of __hash__ to behave better for big big numbers. ........ r58216 | raymond.hettinger | 2007-09-20 05:03:43 +0200 (Thu, 20 Sep 2007) | 1 line Fit nits ........ r58217 | georg.brandl | 2007-09-20 10:44:59 +0200 (Thu, 20 Sep 2007) | 2 lines alternate -> alternative. ........ r58218 | georg.brandl | 2007-09-20 18:06:07 +0200 (Thu, 20 Sep 2007) | 2 lines Patch #1541463: optimize performance of cgi.FieldStorage operations. ........ r58219 | georg.brandl | 2007-09-20 18:45:27 +0200 (Thu, 20 Sep 2007) | 2 lines #1176: document that string methods don't take keyword args. ........ r58220 | thomas.wouters | 2007-09-20 19:35:10 +0200 (Thu, 20 Sep 2007) | 4 lines Try harder to stay within the 79-column limit. There's still two places that go (way) over, but those are harder to fix without suffering in readability. ........
This commit is contained in:
parent
7ce29ca41c
commit
8ce81f767a
8 changed files with 117 additions and 61 deletions
|
@ -395,8 +395,8 @@ Setting the :attr:`default_factory` to :class:`set` makes the
|
||||||
|
|
||||||
.. _named-tuple-factory:
|
.. _named-tuple-factory:
|
||||||
|
|
||||||
:func:`NamedTuple` factory function
|
:func:`NamedTuple` Factory Function for Tuples with Named Fields
|
||||||
-----------------------------------
|
----------------------------------------------------------------
|
||||||
|
|
||||||
Named tuples assign meaning to each position in a tuple and allow for more readable,
|
Named tuples assign meaning to each position in a tuple and allow for more readable,
|
||||||
self-documenting code. They can be used wherever regular tuples are used, and
|
self-documenting code. They can be used wherever regular tuples are used, and
|
||||||
|
@ -413,10 +413,10 @@ they add the ability to access fields by name instead of position index.
|
||||||
The *fieldnames* are specified in a single string with each fieldname separated by
|
The *fieldnames* are specified in a single string with each fieldname separated by
|
||||||
a space and/or comma. Any valid Python identifier may be used for a fieldname.
|
a space and/or comma. Any valid Python identifier may be used for a fieldname.
|
||||||
|
|
||||||
If *verbose* is true, the *NamedTuple* call will print the class definition.
|
If *verbose* is true, will print the class definition.
|
||||||
|
|
||||||
*NamedTuple* instances do not have per-instance dictionaries, so they are
|
*NamedTuple* instances do not have per-instance dictionaries, so they are
|
||||||
lightweight, requiring no more memory than regular tuples.
|
lightweight and require no more memory than regular tuples.
|
||||||
|
|
||||||
Example::
|
Example::
|
||||||
|
|
||||||
|
@ -467,7 +467,9 @@ an additonal method and an informational read-only attribute.
|
||||||
|
|
||||||
.. method:: somenamedtuple.replace(field, value)
|
.. method:: somenamedtuple.replace(field, value)
|
||||||
|
|
||||||
Return a new instance of the named tuple replacing the named *field* with a new *value*::
|
Return a new instance of the named tuple replacing the named *field* with a new *value*:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
>>> p = Point(x=11, y=22)
|
>>> p = Point(x=11, y=22)
|
||||||
>>> p.__replace__('x', 33)
|
>>> p.__replace__('x', 33)
|
||||||
|
@ -480,7 +482,9 @@ an additonal method and an informational read-only attribute.
|
||||||
|
|
||||||
Return a tuple of strings listing the field names. This is useful for introspection,
|
Return a tuple of strings listing the field names. This is useful for introspection,
|
||||||
for converting a named tuple instance to a dictionary, and for combining named tuple
|
for converting a named tuple instance to a dictionary, and for combining named tuple
|
||||||
types to create new named tuple types::
|
types to create new named tuple types:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
>>> p.__fields__ # view the field names
|
>>> p.__fields__ # view the field names
|
||||||
('x', 'y')
|
('x', 'y')
|
||||||
|
|
|
@ -977,7 +977,7 @@ method. For example, ``C.exp(x)`` is equivalent to
|
||||||
|
|
||||||
The usual approach to working with decimals is to create :class:`Decimal`
|
The usual approach to working with decimals is to create :class:`Decimal`
|
||||||
instances and then apply arithmetic operations which take place within the
|
instances and then apply arithmetic operations which take place within the
|
||||||
current context for the active thread. An alternate approach is to use context
|
current context for the active thread. An alternative approach is to use context
|
||||||
methods for calculating within a specific context. The methods are similar to
|
methods for calculating within a specific context. The methods are similar to
|
||||||
those for the :class:`Decimal` class and are only briefly recounted here.
|
those for the :class:`Decimal` class and are only briefly recounted here.
|
||||||
|
|
||||||
|
|
|
@ -657,10 +657,13 @@ String Methods
|
||||||
|
|
||||||
.. index:: pair: string; methods
|
.. index:: pair: string; methods
|
||||||
|
|
||||||
String objects support the methods listed below. In addition, Python's strings
|
String objects support the methods listed below. Note that none of these
|
||||||
support the sequence type methods described in the :ref:`typesseq` section. To
|
methods take keyword arguments.
|
||||||
output formatted strings, see the :ref:`string-formatting` section. Also, see
|
|
||||||
the :mod:`re` module for string functions based on regular expressions.
|
In addition, Python's strings support the sequence type methods described in
|
||||||
|
the :ref:`typesseq` section. To output formatted strings, see the
|
||||||
|
:ref:`string-formatting` section. Also, see the :mod:`re` module for string
|
||||||
|
functions based on regular expressions.
|
||||||
|
|
||||||
.. method:: str.capitalize()
|
.. method:: str.capitalize()
|
||||||
|
|
||||||
|
|
|
@ -252,7 +252,7 @@ having to load the entire file in memory. Only complete lines will be returned.
|
||||||
>>> f.readlines()
|
>>> f.readlines()
|
||||||
['This is the first line of the file.\n', 'Second line of the file\n']
|
['This is the first line of the file.\n', 'Second line of the file\n']
|
||||||
|
|
||||||
An alternate approach to reading lines is to loop over the file object. This is
|
An alternative approach to reading lines is to loop over the file object. This is
|
||||||
memory efficient, fast, and leads to simpler code::
|
memory efficient, fast, and leads to simpler code::
|
||||||
|
|
||||||
>>> for line in f:
|
>>> for line in f:
|
||||||
|
|
12
Lib/cgi.py
12
Lib/cgi.py
|
@ -604,23 +604,21 @@ class FieldStorage:
|
||||||
"""Dictionary style keys() method."""
|
"""Dictionary style keys() method."""
|
||||||
if self.list is None:
|
if self.list is None:
|
||||||
raise TypeError("not indexable")
|
raise TypeError("not indexable")
|
||||||
keys = []
|
return list(set(item.name for item in self.list))
|
||||||
for item in self.list:
|
|
||||||
if item.name not in keys: keys.append(item.name)
|
|
||||||
return keys
|
|
||||||
|
|
||||||
def __contains__(self, key):
|
def __contains__(self, key):
|
||||||
"""Dictionary style __contains__ method."""
|
"""Dictionary style __contains__ method."""
|
||||||
if self.list is None:
|
if self.list is None:
|
||||||
raise TypeError("not indexable")
|
raise TypeError("not indexable")
|
||||||
for item in self.list:
|
return any(item.name == key for item in self.list)
|
||||||
if item.name == key: return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
def __len__(self):
|
def __len__(self):
|
||||||
"""Dictionary style len(x) support."""
|
"""Dictionary style len(x) support."""
|
||||||
return len(self.keys())
|
return len(self.keys())
|
||||||
|
|
||||||
|
def __nonzero__(self):
|
||||||
|
return bool(self.list)
|
||||||
|
|
||||||
def read_urlencoded(self):
|
def read_urlencoded(self):
|
||||||
"""Internal: read data in query string format."""
|
"""Internal: read data in query string format."""
|
||||||
qs = self.fp.read(self.length)
|
qs = self.fp.read(self.length)
|
||||||
|
|
|
@ -786,10 +786,17 @@ class Decimal(object):
|
||||||
if self._isnan():
|
if self._isnan():
|
||||||
raise TypeError('Cannot hash a NaN value.')
|
raise TypeError('Cannot hash a NaN value.')
|
||||||
return hash(str(self))
|
return hash(str(self))
|
||||||
i = int(self)
|
if not self:
|
||||||
if self == Decimal(i):
|
return 0
|
||||||
return hash(i)
|
if self._isinteger():
|
||||||
assert self.__bool__() # '-0' handled by integer case
|
op = _WorkRep(self.to_integral_value())
|
||||||
|
# to make computation feasible for Decimals with large
|
||||||
|
# exponent, we use the fact that hash(n) == hash(m) for
|
||||||
|
# any two nonzero integers n and m such that (i) n and m
|
||||||
|
# have the same sign, and (ii) n is congruent to m modulo
|
||||||
|
# 2**64-1. So we can replace hash((-1)**s*c*10**e) with
|
||||||
|
# hash((-1)**s*c*pow(10, e, 2**64-1).
|
||||||
|
return hash((-1)**op.sign*op.int*pow(10, op.exp, 2**64-1))
|
||||||
return hash(str(self.normalize()))
|
return hash(str(self.normalize()))
|
||||||
|
|
||||||
def as_tuple(self):
|
def as_tuple(self):
|
||||||
|
|
|
@ -901,6 +901,38 @@ class DecimalUsabilityTest(unittest.TestCase):
|
||||||
def test_hash_method(self):
|
def test_hash_method(self):
|
||||||
#just that it's hashable
|
#just that it's hashable
|
||||||
hash(Decimal(23))
|
hash(Decimal(23))
|
||||||
|
|
||||||
|
test_values = [Decimal(sign*(2**m + n))
|
||||||
|
for m in [0, 14, 15, 16, 17, 30, 31,
|
||||||
|
32, 33, 62, 63, 64, 65, 66]
|
||||||
|
for n in range(-10, 10)
|
||||||
|
for sign in [-1, 1]]
|
||||||
|
test_values.extend([
|
||||||
|
Decimal("-0"), # zeros
|
||||||
|
Decimal("0.00"),
|
||||||
|
Decimal("-0.000"),
|
||||||
|
Decimal("0E10"),
|
||||||
|
Decimal("-0E12"),
|
||||||
|
Decimal("10.0"), # negative exponent
|
||||||
|
Decimal("-23.00000"),
|
||||||
|
Decimal("1230E100"), # positive exponent
|
||||||
|
Decimal("-4.5678E50"),
|
||||||
|
# a value for which hash(n) != hash(n % (2**64-1))
|
||||||
|
# in Python pre-2.6
|
||||||
|
Decimal(2**64 + 2**32 - 1),
|
||||||
|
# selection of values which fail with the old (before
|
||||||
|
# version 2.6) long.__hash__
|
||||||
|
Decimal("1.634E100"),
|
||||||
|
Decimal("90.697E100"),
|
||||||
|
Decimal("188.83E100"),
|
||||||
|
Decimal("1652.9E100"),
|
||||||
|
Decimal("56531E100"),
|
||||||
|
])
|
||||||
|
|
||||||
|
# check that hash(d) == hash(int(d)) for integral values
|
||||||
|
for value in test_values:
|
||||||
|
self.assertEqual(hash(value), hash(int(value)))
|
||||||
|
|
||||||
#the same hash that to an int
|
#the same hash that to an int
|
||||||
self.assertEqual(hash(Decimal(23)), hash(23))
|
self.assertEqual(hash(Decimal(23)), hash(23))
|
||||||
self.assertRaises(TypeError, hash, Decimal('NaN'))
|
self.assertRaises(TypeError, hash, Decimal('NaN'))
|
||||||
|
|
|
@ -28,8 +28,9 @@
|
||||||
typedef unsigned long long uint64;
|
typedef unsigned long long uint64;
|
||||||
|
|
||||||
#if defined(__ppc__) /* <- Don't know if this is the correct symbol; this
|
#if defined(__ppc__) /* <- Don't know if this is the correct symbol; this
|
||||||
section should work for GCC on any PowerPC platform,
|
section should work for GCC on any PowerPC
|
||||||
irrespective of OS. POWER? Who knows :-) */
|
platform, irrespective of OS.
|
||||||
|
POWER? Who knows :-) */
|
||||||
|
|
||||||
#define READ_TIMESTAMP(var) ppc_getcounter(&var)
|
#define READ_TIMESTAMP(var) ppc_getcounter(&var)
|
||||||
|
|
||||||
|
@ -93,7 +94,8 @@ static PyObject * call_function(PyObject ***, int);
|
||||||
static PyObject * fast_function(PyObject *, PyObject ***, int, int, int);
|
static PyObject * fast_function(PyObject *, PyObject ***, int, int, int);
|
||||||
static PyObject * do_call(PyObject *, PyObject ***, int, int);
|
static PyObject * do_call(PyObject *, PyObject ***, int, int);
|
||||||
static PyObject * ext_do_call(PyObject *, PyObject ***, int, int, int);
|
static PyObject * ext_do_call(PyObject *, PyObject ***, int, int, int);
|
||||||
static PyObject * update_keyword_args(PyObject *, int, PyObject ***,PyObject *);
|
static PyObject * update_keyword_args(PyObject *, int, PyObject ***,
|
||||||
|
PyObject *);
|
||||||
static PyObject * update_star_args(int, int, PyObject *, PyObject ***);
|
static PyObject * update_star_args(int, int, PyObject *, PyObject ***);
|
||||||
static PyObject * load_args(PyObject ***, int);
|
static PyObject * load_args(PyObject ***, int);
|
||||||
#define CALL_FLAG_VAR 1
|
#define CALL_FLAG_VAR 1
|
||||||
|
@ -509,7 +511,8 @@ PyEval_EvalCode(PyCodeObject *co, PyObject *globals, PyObject *locals)
|
||||||
PyObject *
|
PyObject *
|
||||||
PyEval_EvalFrame(PyFrameObject *f) {
|
PyEval_EvalFrame(PyFrameObject *f) {
|
||||||
/* This is for backward compatibility with extension modules that
|
/* This is for backward compatibility with extension modules that
|
||||||
used this API; core interpreter code should call PyEval_EvalFrameEx() */
|
used this API; core interpreter code should call
|
||||||
|
PyEval_EvalFrameEx() */
|
||||||
return PyEval_EvalFrameEx(f, 0);
|
return PyEval_EvalFrameEx(f, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -610,10 +613,10 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
|
||||||
#define JUMPBY(x) (next_instr += (x))
|
#define JUMPBY(x) (next_instr += (x))
|
||||||
|
|
||||||
/* OpCode prediction macros
|
/* OpCode prediction macros
|
||||||
Some opcodes tend to come in pairs thus making it possible to predict
|
Some opcodes tend to come in pairs thus making it possible to
|
||||||
the second code when the first is run. For example, COMPARE_OP is often
|
predict the second code when the first is run. For example,
|
||||||
followed by JUMP_IF_FALSE or JUMP_IF_TRUE. And, those opcodes are often
|
COMPARE_OP is often followed by JUMP_IF_FALSE or JUMP_IF_TRUE. And,
|
||||||
followed by a POP_TOP.
|
those opcodes are often followed by a POP_TOP.
|
||||||
|
|
||||||
Verifying the prediction costs a single high-speed test of register
|
Verifying the prediction costs a single high-speed test of register
|
||||||
variable against a constant. If the pairing was good, then the
|
variable against a constant. If the pairing was good, then the
|
||||||
|
@ -660,11 +663,13 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
|
||||||
#define PUSH(v) { (void)(BASIC_PUSH(v), \
|
#define PUSH(v) { (void)(BASIC_PUSH(v), \
|
||||||
lltrace && prtrace(TOP(), "push")); \
|
lltrace && prtrace(TOP(), "push")); \
|
||||||
assert(STACK_LEVEL() <= co->co_stacksize); }
|
assert(STACK_LEVEL() <= co->co_stacksize); }
|
||||||
#define POP() ((void)(lltrace && prtrace(TOP(), "pop")), BASIC_POP())
|
#define POP() ((void)(lltrace && prtrace(TOP(), "pop")), \
|
||||||
|
BASIC_POP())
|
||||||
#define STACKADJ(n) { (void)(BASIC_STACKADJ(n), \
|
#define STACKADJ(n) { (void)(BASIC_STACKADJ(n), \
|
||||||
lltrace && prtrace(TOP(), "stackadj")); \
|
lltrace && prtrace(TOP(), "stackadj")); \
|
||||||
assert(STACK_LEVEL() <= co->co_stacksize); }
|
assert(STACK_LEVEL() <= co->co_stacksize); }
|
||||||
#define EXT_POP(STACK_POINTER) (lltrace && prtrace((STACK_POINTER)[-1], "ext_pop"), *--(STACK_POINTER))
|
#define EXT_POP(STACK_POINTER) (lltrace && prtrace((STACK_POINTER)[-1], \
|
||||||
|
"ext_pop"), *--(STACK_POINTER))
|
||||||
#else
|
#else
|
||||||
#define PUSH(v) BASIC_PUSH(v)
|
#define PUSH(v) BASIC_PUSH(v)
|
||||||
#define POP() BASIC_POP()
|
#define POP() BASIC_POP()
|
||||||
|
@ -1568,7 +1573,8 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
|
||||||
if ((x = f->f_locals) != NULL) {
|
if ((x = f->f_locals) != NULL) {
|
||||||
if ((err = PyObject_DelItem(x, w)) != 0)
|
if ((err = PyObject_DelItem(x, w)) != 0)
|
||||||
format_exc_check_arg(PyExc_NameError,
|
format_exc_check_arg(PyExc_NameError,
|
||||||
NAME_ERROR_MSG ,w);
|
NAME_ERROR_MSG,
|
||||||
|
w);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
PyErr_Format(PyExc_SystemError,
|
PyErr_Format(PyExc_SystemError,
|
||||||
|
@ -1579,8 +1585,10 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
|
||||||
PREDICTED_WITH_ARG(UNPACK_SEQUENCE);
|
PREDICTED_WITH_ARG(UNPACK_SEQUENCE);
|
||||||
case UNPACK_SEQUENCE:
|
case UNPACK_SEQUENCE:
|
||||||
v = POP();
|
v = POP();
|
||||||
if (PyTuple_CheckExact(v) && PyTuple_GET_SIZE(v) == oparg) {
|
if (PyTuple_CheckExact(v) &&
|
||||||
PyObject **items = ((PyTupleObject *)v)->ob_item;
|
PyTuple_GET_SIZE(v) == oparg) {
|
||||||
|
PyObject **items = \
|
||||||
|
((PyTupleObject *)v)->ob_item;
|
||||||
while (oparg--) {
|
while (oparg--) {
|
||||||
w = items[oparg];
|
w = items[oparg];
|
||||||
Py_INCREF(w);
|
Py_INCREF(w);
|
||||||
|
@ -1588,8 +1596,10 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
|
||||||
}
|
}
|
||||||
Py_DECREF(v);
|
Py_DECREF(v);
|
||||||
continue;
|
continue;
|
||||||
} else if (PyList_CheckExact(v) && PyList_GET_SIZE(v) == oparg) {
|
} else if (PyList_CheckExact(v) &&
|
||||||
PyObject **items = ((PyListObject *)v)->ob_item;
|
PyList_GET_SIZE(v) == oparg) {
|
||||||
|
PyObject **items = \
|
||||||
|
((PyListObject *)v)->ob_item;
|
||||||
while (oparg--) {
|
while (oparg--) {
|
||||||
w = items[oparg];
|
w = items[oparg];
|
||||||
Py_INCREF(w);
|
Py_INCREF(w);
|
||||||
|
@ -1669,7 +1679,8 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
|
||||||
else {
|
else {
|
||||||
x = PyObject_GetItem(v, w);
|
x = PyObject_GetItem(v, w);
|
||||||
if (x == NULL && PyErr_Occurred()) {
|
if (x == NULL && PyErr_Occurred()) {
|
||||||
if (!PyErr_ExceptionMatches(PyExc_KeyError))
|
if (!PyErr_ExceptionMatches(
|
||||||
|
PyExc_KeyError))
|
||||||
break;
|
break;
|
||||||
PyErr_Clear();
|
PyErr_Clear();
|
||||||
}
|
}
|
||||||
|
@ -1782,13 +1793,10 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
|
||||||
UNBOUNDLOCAL_ERROR_MSG,
|
UNBOUNDLOCAL_ERROR_MSG,
|
||||||
v);
|
v);
|
||||||
} else {
|
} else {
|
||||||
v = PyTuple_GET_ITEM(
|
v = PyTuple_GET_ITEM(co->co_freevars, oparg -
|
||||||
co->co_freevars,
|
PyTuple_GET_SIZE(co->co_cellvars));
|
||||||
oparg - PyTuple_GET_SIZE(co->co_cellvars));
|
format_exc_check_arg(PyExc_NameError,
|
||||||
format_exc_check_arg(
|
UNBOUNDFREE_ERROR_MSG, v);
|
||||||
PyExc_NameError,
|
|
||||||
UNBOUNDFREE_ERROR_MSG,
|
|
||||||
v);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -2046,7 +2054,8 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (PyErr_Occurred()) {
|
if (PyErr_Occurred()) {
|
||||||
if (!PyErr_ExceptionMatches(PyExc_StopIteration))
|
if (!PyErr_ExceptionMatches(
|
||||||
|
PyExc_StopIteration))
|
||||||
break;
|
break;
|
||||||
PyErr_Clear();
|
PyErr_Clear();
|
||||||
}
|
}
|
||||||
|
@ -2072,9 +2081,10 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
|
||||||
case SETUP_LOOP:
|
case SETUP_LOOP:
|
||||||
case SETUP_EXCEPT:
|
case SETUP_EXCEPT:
|
||||||
case SETUP_FINALLY:
|
case SETUP_FINALLY:
|
||||||
/* NOTE: If you add any new block-setup opcodes that are
|
/* NOTE: If you add any new block-setup opcodes that
|
||||||
not try/except/finally handlers, you may need to
|
are not try/except/finally handlers, you may need
|
||||||
update the PyGen_NeedsFinalizing() function. */
|
to update the PyGen_NeedsFinalizing() function.
|
||||||
|
*/
|
||||||
|
|
||||||
PyFrame_BlockSetup(f, opcode, INSTR_OFFSET() + oparg,
|
PyFrame_BlockSetup(f, opcode, INSTR_OFFSET() + oparg,
|
||||||
STACK_LEVEL());
|
STACK_LEVEL());
|
||||||
|
@ -3968,8 +3978,9 @@ string_concatenate(PyObject *v, PyObject *w,
|
||||||
if (v->ob_refcnt == 2) {
|
if (v->ob_refcnt == 2) {
|
||||||
/* In the common case, there are 2 references to the value
|
/* In the common case, there are 2 references to the value
|
||||||
* stored in 'variable' when the += is performed: one on the
|
* stored in 'variable' when the += is performed: one on the
|
||||||
* value stack (in 'v') and one still stored in the 'variable'.
|
* value stack (in 'v') and one still stored in the
|
||||||
* We try to delete the variable now to reduce the refcnt to 1.
|
* 'variable'. We try to delete the variable now to reduce
|
||||||
|
* the refcnt to 1.
|
||||||
*/
|
*/
|
||||||
switch (*next_instr) {
|
switch (*next_instr) {
|
||||||
case STORE_FAST:
|
case STORE_FAST:
|
||||||
|
@ -3982,7 +3993,8 @@ string_concatenate(PyObject *v, PyObject *w,
|
||||||
}
|
}
|
||||||
case STORE_DEREF:
|
case STORE_DEREF:
|
||||||
{
|
{
|
||||||
PyObject **freevars = f->f_localsplus + f->f_code->co_nlocals;
|
PyObject **freevars = (f->f_localsplus +
|
||||||
|
f->f_code->co_nlocals);
|
||||||
PyObject *c = freevars[PEEKARG()];
|
PyObject *c = freevars[PEEKARG()];
|
||||||
if (PyCell_GET(c) == v)
|
if (PyCell_GET(c) == v)
|
||||||
PyCell_Set(c, NULL);
|
PyCell_Set(c, NULL);
|
||||||
|
@ -4010,10 +4022,10 @@ string_concatenate(PyObject *v, PyObject *w,
|
||||||
*/
|
*/
|
||||||
if (_PyString_Resize(&v, new_len) != 0) {
|
if (_PyString_Resize(&v, new_len) != 0) {
|
||||||
/* XXX if _PyString_Resize() fails, 'v' has been
|
/* XXX if _PyString_Resize() fails, 'v' has been
|
||||||
* deallocated so it cannot be put back into 'variable'.
|
* deallocated so it cannot be put back into
|
||||||
* The MemoryError is raised when there is no value in
|
* 'variable'. The MemoryError is raised when there
|
||||||
* 'variable', which might (very remotely) be a cause
|
* is no value in 'variable', which might (very
|
||||||
* of incompatibilities.
|
* remotely) be a cause of incompatibilities.
|
||||||
*/
|
*/
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue