mirror of https://github.com/python/cpython.git
Merged revisions 60441-60474 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk ........ r60441 | christian.heimes | 2008-01-30 12:46:00 +0100 (Wed, 30 Jan 2008) | 1 line Removed unused var ........ r60448 | christian.heimes | 2008-01-30 18:21:22 +0100 (Wed, 30 Jan 2008) | 1 line Fixed some references leaks in sys. ........ r60450 | christian.heimes | 2008-01-30 19:58:29 +0100 (Wed, 30 Jan 2008) | 1 line The previous change was causing a segfault after multiple calls to Py_Initialize() and Py_Finalize(). ........ r60463 | raymond.hettinger | 2008-01-30 23:17:31 +0100 (Wed, 30 Jan 2008) | 1 line Update itertool recipes ........ r60464 | christian.heimes | 2008-01-30 23:54:18 +0100 (Wed, 30 Jan 2008) | 1 line Bug #1234: Fixed semaphore errors on AIX 5.2 ........ r60469 | raymond.hettinger | 2008-01-31 02:38:15 +0100 (Thu, 31 Jan 2008) | 6 lines Fix defect in __ixor__ which would get the wrong answer if the input iterable had a duplicate element (two calls to toggle() reverse each other). Borrow the correct code from sets.py. ........ r60470 | raymond.hettinger | 2008-01-31 02:42:11 +0100 (Thu, 31 Jan 2008) | 1 line Missing return ........ r60471 | jeffrey.yasskin | 2008-01-31 08:44:11 +0100 (Thu, 31 Jan 2008) | 4 lines Added more documentation on how mixed-mode arithmetic should be implemented. I also noticed and fixed a bug in Rational's forward operators (they were claiming all instances of numbers.Rational instead of just the concrete types). ........
This commit is contained in:
parent
4b8db419c2
commit
7b3ce6a17e
|
@ -511,5 +511,16 @@ which incur interpreter overhead. ::
|
||||||
"grouper(3, 'abcdefg', 'x') --> ('a','b','c'), ('d','e','f'), ('g','x','x')"
|
"grouper(3, 'abcdefg', 'x') --> ('a','b','c'), ('d','e','f'), ('g','x','x')"
|
||||||
return izip(*[chain(iterable, repeat(padvalue, n-1))]*n)
|
return izip(*[chain(iterable, repeat(padvalue, n-1))]*n)
|
||||||
|
|
||||||
|
def roundrobin(*iterables):
|
||||||
|
"roundrobin('abc', 'd', 'ef') --> 'a', 'd', 'e', 'b', 'f', 'c'"
|
||||||
|
# Recipe contributed by George Sakkis
|
||||||
|
pending = len(iterables)
|
||||||
|
nexts = cycle(iter(it).next for it in iterables)
|
||||||
|
while pending:
|
||||||
|
try:
|
||||||
|
for next in nexts:
|
||||||
|
yield next()
|
||||||
|
except StopIteration:
|
||||||
|
pending -= 1
|
||||||
|
nexts = cycle(islice(nexts, pending))
|
||||||
|
|
||||||
|
|
|
@ -97,3 +97,144 @@ The numeric tower
|
||||||
3-argument form of :func:`pow`, and the bit-string operations: ``<<``,
|
3-argument form of :func:`pow`, and the bit-string operations: ``<<``,
|
||||||
``>>``, ``&``, ``^``, ``|``, ``~``. Provides defaults for :func:`float`,
|
``>>``, ``&``, ``^``, ``|``, ``~``. Provides defaults for :func:`float`,
|
||||||
:attr:`Rational.numerator`, and :attr:`Rational.denominator`.
|
:attr:`Rational.numerator`, and :attr:`Rational.denominator`.
|
||||||
|
|
||||||
|
|
||||||
|
Notes for type implementors
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
Implementors should be careful to make equal numbers equal and hash
|
||||||
|
them to the same values. This may be subtle if there are two different
|
||||||
|
extensions of the real numbers. For example, :class:`rational.Rational`
|
||||||
|
implements :func:`hash` as follows::
|
||||||
|
|
||||||
|
def __hash__(self):
|
||||||
|
if self.denominator == 1:
|
||||||
|
# Get integers right.
|
||||||
|
return hash(self.numerator)
|
||||||
|
# Expensive check, but definitely correct.
|
||||||
|
if self == float(self):
|
||||||
|
return hash(float(self))
|
||||||
|
else:
|
||||||
|
# Use tuple's hash to avoid a high collision rate on
|
||||||
|
# simple fractions.
|
||||||
|
return hash((self.numerator, self.denominator))
|
||||||
|
|
||||||
|
|
||||||
|
Adding More Numeric ABCs
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
There are, of course, more possible ABCs for numbers, and this would
|
||||||
|
be a poor hierarchy if it precluded the possibility of adding
|
||||||
|
those. You can add ``MyFoo`` between :class:`Complex` and
|
||||||
|
:class:`Real` with::
|
||||||
|
|
||||||
|
class MyFoo(Complex): ...
|
||||||
|
MyFoo.register(Real)
|
||||||
|
|
||||||
|
|
||||||
|
Implementing the arithmetic operations
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
We want to implement the arithmetic operations so that mixed-mode
|
||||||
|
operations either call an implementation whose author knew about the
|
||||||
|
types of both arguments, or convert both to the nearest built in type
|
||||||
|
and do the operation there. For subtypes of :class:`Integral`, this
|
||||||
|
means that :meth:`__add__` and :meth:`__radd__` should be defined as::
|
||||||
|
|
||||||
|
class MyIntegral(Integral):
|
||||||
|
|
||||||
|
def __add__(self, other):
|
||||||
|
if isinstance(other, MyIntegral):
|
||||||
|
return do_my_adding_stuff(self, other)
|
||||||
|
elif isinstance(other, OtherTypeIKnowAbout):
|
||||||
|
return do_my_other_adding_stuff(self, other)
|
||||||
|
else:
|
||||||
|
return NotImplemented
|
||||||
|
|
||||||
|
def __radd__(self, other):
|
||||||
|
if isinstance(other, MyIntegral):
|
||||||
|
return do_my_adding_stuff(other, self)
|
||||||
|
elif isinstance(other, OtherTypeIKnowAbout):
|
||||||
|
return do_my_other_adding_stuff(other, self)
|
||||||
|
elif isinstance(other, Integral):
|
||||||
|
return int(other) + int(self)
|
||||||
|
elif isinstance(other, Real):
|
||||||
|
return float(other) + float(self)
|
||||||
|
elif isinstance(other, Complex):
|
||||||
|
return complex(other) + complex(self)
|
||||||
|
else:
|
||||||
|
return NotImplemented
|
||||||
|
|
||||||
|
|
||||||
|
There are 5 different cases for a mixed-type operation on subclasses
|
||||||
|
of :class:`Complex`. I'll refer to all of the above code that doesn't
|
||||||
|
refer to ``MyIntegral`` and ``OtherTypeIKnowAbout`` as
|
||||||
|
"boilerplate". ``a`` will be an instance of ``A``, which is a subtype
|
||||||
|
of :class:`Complex` (``a : A <: Complex``), and ``b : B <:
|
||||||
|
Complex``. I'll consider ``a + b``:
|
||||||
|
|
||||||
|
1. If ``A`` defines an :meth:`__add__` which accepts ``b``, all is
|
||||||
|
well.
|
||||||
|
2. If ``A`` falls back to the boilerplate code, and it were to
|
||||||
|
return a value from :meth:`__add__`, we'd miss the possibility
|
||||||
|
that ``B`` defines a more intelligent :meth:`__radd__`, so the
|
||||||
|
boilerplate should return :const:`NotImplemented` from
|
||||||
|
:meth:`__add__`. (Or ``A`` may not implement :meth:`__add__` at
|
||||||
|
all.)
|
||||||
|
3. Then ``B``'s :meth:`__radd__` gets a chance. If it accepts
|
||||||
|
``a``, all is well.
|
||||||
|
4. If it falls back to the boilerplate, there are no more possible
|
||||||
|
methods to try, so this is where the default implementation
|
||||||
|
should live.
|
||||||
|
5. If ``B <: A``, Python tries ``B.__radd__`` before
|
||||||
|
``A.__add__``. This is ok, because it was implemented with
|
||||||
|
knowledge of ``A``, so it can handle those instances before
|
||||||
|
delegating to :class:`Complex`.
|
||||||
|
|
||||||
|
If ``A<:Complex`` and ``B<:Real`` without sharing any other knowledge,
|
||||||
|
then the appropriate shared operation is the one involving the built
|
||||||
|
in :class:`complex`, and both :meth:`__radd__` s land there, so ``a+b
|
||||||
|
== b+a``.
|
||||||
|
|
||||||
|
Because most of the operations on any given type will be very similar,
|
||||||
|
it can be useful to define a helper function which generates the
|
||||||
|
forward and reverse instances of any given operator. For example,
|
||||||
|
:class:`rational.Rational` uses::
|
||||||
|
|
||||||
|
def _operator_fallbacks(monomorphic_operator, fallback_operator):
|
||||||
|
def forward(a, b):
|
||||||
|
if isinstance(b, (int, long, Rational)):
|
||||||
|
return monomorphic_operator(a, b)
|
||||||
|
elif isinstance(b, float):
|
||||||
|
return fallback_operator(float(a), b)
|
||||||
|
elif isinstance(b, complex):
|
||||||
|
return fallback_operator(complex(a), b)
|
||||||
|
else:
|
||||||
|
return NotImplemented
|
||||||
|
forward.__name__ = '__' + fallback_operator.__name__ + '__'
|
||||||
|
forward.__doc__ = monomorphic_operator.__doc__
|
||||||
|
|
||||||
|
def reverse(b, a):
|
||||||
|
if isinstance(a, RationalAbc):
|
||||||
|
# Includes ints.
|
||||||
|
return monomorphic_operator(a, b)
|
||||||
|
elif isinstance(a, numbers.Real):
|
||||||
|
return fallback_operator(float(a), float(b))
|
||||||
|
elif isinstance(a, numbers.Complex):
|
||||||
|
return fallback_operator(complex(a), complex(b))
|
||||||
|
else:
|
||||||
|
return NotImplemented
|
||||||
|
reverse.__name__ = '__r' + fallback_operator.__name__ + '__'
|
||||||
|
reverse.__doc__ = monomorphic_operator.__doc__
|
||||||
|
|
||||||
|
return forward, reverse
|
||||||
|
|
||||||
|
def _add(a, b):
|
||||||
|
"""a + b"""
|
||||||
|
return Rational(a.numerator * b.denominator +
|
||||||
|
b.numerator * a.denominator,
|
||||||
|
a.denominator * b.denominator)
|
||||||
|
|
||||||
|
__add__, __radd__ = _operator_fallbacks(_add, operator.add)
|
||||||
|
|
||||||
|
# ...
|
|
@ -300,16 +300,6 @@ def pop(self):
|
||||||
self.discard(value)
|
self.discard(value)
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def toggle(self, value):
|
|
||||||
"""Return True if it was added, False if deleted."""
|
|
||||||
# XXX This implementation is not thread-safe
|
|
||||||
if value in self:
|
|
||||||
self.discard(value)
|
|
||||||
return False
|
|
||||||
else:
|
|
||||||
self.add(value)
|
|
||||||
return True
|
|
||||||
|
|
||||||
def clear(self):
|
def clear(self):
|
||||||
"""This is slow (creates N new iterators!) but effective."""
|
"""This is slow (creates N new iterators!) but effective."""
|
||||||
try:
|
try:
|
||||||
|
@ -330,9 +320,13 @@ def __iand__(self, c: Container):
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def __ixor__(self, it: Iterable):
|
def __ixor__(self, it: Iterable):
|
||||||
# This calls toggle(), so if that is overridded, we call the override
|
if not isinstance(it, Set):
|
||||||
|
it = self._from_iterable(it)
|
||||||
for value in it:
|
for value in it:
|
||||||
self.toggle(it)
|
if value in self:
|
||||||
|
self.discard(value)
|
||||||
|
else:
|
||||||
|
self.add(value)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def __isub__(self, it: Iterable):
|
def __isub__(self, it: Iterable):
|
||||||
|
|
|
@ -291,7 +291,13 @@ def denominator(self):
|
||||||
|
|
||||||
# Concrete implementation of Real's conversion to float.
|
# Concrete implementation of Real's conversion to float.
|
||||||
def __float__(self):
|
def __float__(self):
|
||||||
"""float(self) = self.numerator / self.denominator"""
|
"""float(self) = self.numerator / self.denominator
|
||||||
|
|
||||||
|
It's important that this conversion use the integer's "true"
|
||||||
|
division rather than casting one side to float before dividing
|
||||||
|
so that ratios of huge integers convert without overflowing.
|
||||||
|
|
||||||
|
"""
|
||||||
return self.numerator / self.denominator
|
return self.numerator / self.denominator
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -178,16 +178,6 @@ def __str__(self):
|
||||||
else:
|
else:
|
||||||
return '%s/%s' % (self.numerator, self.denominator)
|
return '%s/%s' % (self.numerator, self.denominator)
|
||||||
|
|
||||||
""" XXX This section needs a lot more commentary
|
|
||||||
|
|
||||||
* Explain the typical sequence of checks, calls, and fallbacks.
|
|
||||||
* Explain the subtle reasons why this logic was needed.
|
|
||||||
* It is not clear how common cases are handled (for example, how
|
|
||||||
does the ratio of two huge integers get converted to a float
|
|
||||||
without overflowing the long-->float conversion.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
def _operator_fallbacks(monomorphic_operator, fallback_operator):
|
def _operator_fallbacks(monomorphic_operator, fallback_operator):
|
||||||
"""Generates forward and reverse operators given a purely-rational
|
"""Generates forward and reverse operators given a purely-rational
|
||||||
operator and a function from the operator module.
|
operator and a function from the operator module.
|
||||||
|
@ -195,10 +185,82 @@ def _operator_fallbacks(monomorphic_operator, fallback_operator):
|
||||||
Use this like:
|
Use this like:
|
||||||
__op__, __rop__ = _operator_fallbacks(just_rational_op, operator.op)
|
__op__, __rop__ = _operator_fallbacks(just_rational_op, operator.op)
|
||||||
|
|
||||||
|
In general, we want to implement the arithmetic operations so
|
||||||
|
that mixed-mode operations either call an implementation whose
|
||||||
|
author knew about the types of both arguments, or convert both
|
||||||
|
to the nearest built in type and do the operation there. In
|
||||||
|
Rational, that means that we define __add__ and __radd__ as:
|
||||||
|
|
||||||
|
def __add__(self, other):
|
||||||
|
if isinstance(other, (int, Rational)):
|
||||||
|
# Do the real operation.
|
||||||
|
return Rational(self.numerator * other.denominator +
|
||||||
|
other.numerator * self.denominator,
|
||||||
|
self.denominator * other.denominator)
|
||||||
|
# float and complex don't follow this protocol, and
|
||||||
|
# Rational knows about them, so special case them.
|
||||||
|
elif isinstance(other, float):
|
||||||
|
return float(self) + other
|
||||||
|
elif isinstance(other, complex):
|
||||||
|
return complex(self) + other
|
||||||
|
else:
|
||||||
|
# Let the other type take over.
|
||||||
|
return NotImplemented
|
||||||
|
|
||||||
|
def __radd__(self, other):
|
||||||
|
# radd handles more types than add because there's
|
||||||
|
# nothing left to fall back to.
|
||||||
|
if isinstance(other, RationalAbc):
|
||||||
|
return Rational(self.numerator * other.denominator +
|
||||||
|
other.numerator * self.denominator,
|
||||||
|
self.denominator * other.denominator)
|
||||||
|
elif isinstance(other, Real):
|
||||||
|
return float(other) + float(self)
|
||||||
|
elif isinstance(other, Complex):
|
||||||
|
return complex(other) + complex(self)
|
||||||
|
else:
|
||||||
|
return NotImplemented
|
||||||
|
|
||||||
|
|
||||||
|
There are 5 different cases for a mixed-type addition on
|
||||||
|
Rational. I'll refer to all of the above code that doesn't
|
||||||
|
refer to Rational, float, or complex as "boilerplate". 'r'
|
||||||
|
will be an instance of Rational, which is a subtype of
|
||||||
|
RationalAbc (r : Rational <: RationalAbc), and b : B <:
|
||||||
|
Complex. The first three involve 'r + b':
|
||||||
|
|
||||||
|
1. If B <: Rational, int, float, or complex, we handle
|
||||||
|
that specially, and all is well.
|
||||||
|
2. If Rational falls back to the boilerplate code, and it
|
||||||
|
were to return a value from __add__, we'd miss the
|
||||||
|
possibility that B defines a more intelligent __radd__,
|
||||||
|
so the boilerplate should return NotImplemented from
|
||||||
|
__add__. In particular, we don't handle RationalAbc
|
||||||
|
here, even though we could get an exact answer, in case
|
||||||
|
the other type wants to do something special.
|
||||||
|
3. If B <: Rational, Python tries B.__radd__ before
|
||||||
|
Rational.__add__. This is ok, because it was
|
||||||
|
implemented with knowledge of Rational, so it can
|
||||||
|
handle those instances before delegating to Real or
|
||||||
|
Complex.
|
||||||
|
|
||||||
|
The next two situations describe 'b + r'. We assume that b
|
||||||
|
didn't know about Rational in its implementation, and that it
|
||||||
|
uses similar boilerplate code:
|
||||||
|
|
||||||
|
4. If B <: RationalAbc, then __radd_ converts both to the
|
||||||
|
builtin rational type (hey look, that's us) and
|
||||||
|
proceeds.
|
||||||
|
5. Otherwise, __radd__ tries to find the nearest common
|
||||||
|
base ABC, and fall back to its builtin type. Since this
|
||||||
|
class doesn't subclass a concrete type, there's no
|
||||||
|
implementation to fall back to, so we need to try as
|
||||||
|
hard as possible to return an actual value, or the user
|
||||||
|
will get a TypeError.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
def forward(a, b):
|
def forward(a, b):
|
||||||
if isinstance(b, RationalAbc):
|
if isinstance(b, (int, Rational)):
|
||||||
# Includes ints.
|
|
||||||
return monomorphic_operator(a, b)
|
return monomorphic_operator(a, b)
|
||||||
elif isinstance(b, float):
|
elif isinstance(b, float):
|
||||||
return fallback_operator(float(a), b)
|
return fallback_operator(float(a), b)
|
||||||
|
|
|
@ -106,15 +106,9 @@ static PyStructSequence_Desc floatinfo_desc = {
|
||||||
PyObject *
|
PyObject *
|
||||||
PyFloat_GetInfo(void)
|
PyFloat_GetInfo(void)
|
||||||
{
|
{
|
||||||
static PyObject* floatinfo;
|
PyObject* floatinfo;
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
|
|
||||||
if (floatinfo != NULL) {
|
|
||||||
Py_INCREF(floatinfo);
|
|
||||||
return floatinfo;
|
|
||||||
}
|
|
||||||
PyStructSequence_InitType(&FloatInfoType, &floatinfo_desc);
|
|
||||||
|
|
||||||
floatinfo = PyStructSequence_New(&FloatInfoType);
|
floatinfo = PyStructSequence_New(&FloatInfoType);
|
||||||
if (floatinfo == NULL) {
|
if (floatinfo == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -143,8 +137,6 @@ PyFloat_GetInfo(void)
|
||||||
Py_CLEAR(floatinfo);
|
Py_CLEAR(floatinfo);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Py_INCREF(floatinfo);
|
|
||||||
return floatinfo;
|
return floatinfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1601,6 +1593,9 @@ _PyFloat_Init(void)
|
||||||
/* Initialize floating point repr */
|
/* Initialize floating point repr */
|
||||||
_PyFloat_DigitsInit();
|
_PyFloat_DigitsInit();
|
||||||
#endif
|
#endif
|
||||||
|
/* Init float info */
|
||||||
|
if (FloatInfoType.tp_name == 0)
|
||||||
|
PyStructSequence_InitType(&FloatInfoType, &floatinfo_desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -371,6 +371,8 @@ static char* sys_deletes[] = {
|
||||||
"path", "argv", "ps1", "ps2",
|
"path", "argv", "ps1", "ps2",
|
||||||
"last_type", "last_value", "last_traceback",
|
"last_type", "last_value", "last_traceback",
|
||||||
"path_hooks", "path_importer_cache", "meta_path",
|
"path_hooks", "path_importer_cache", "meta_path",
|
||||||
|
/* misc stuff */
|
||||||
|
"flags", "float_info",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -482,7 +482,7 @@ r_object(RFILE *p)
|
||||||
{
|
{
|
||||||
/* NULL is a valid return value, it does not necessarily means that
|
/* NULL is a valid return value, it does not necessarily means that
|
||||||
an exception is set. */
|
an exception is set. */
|
||||||
PyObject *v, *v2, *v3;
|
PyObject *v, *v2;
|
||||||
long i, n;
|
long i, n;
|
||||||
int type = r_byte(p);
|
int type = r_byte(p);
|
||||||
PyObject *retval;
|
PyObject *retval;
|
||||||
|
|
|
@ -1131,8 +1131,6 @@ make_flags(void)
|
||||||
if (PyErr_Occurred()) {
|
if (PyErr_Occurred()) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Py_INCREF(seq);
|
|
||||||
return seq;
|
return seq;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1146,6 +1144,11 @@ _PySys_Init(void)
|
||||||
if (m == NULL)
|
if (m == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
sysdict = PyModule_GetDict(m);
|
sysdict = PyModule_GetDict(m);
|
||||||
|
#define SET_SYS_FROM_STRING(key, value) \
|
||||||
|
v = value; \
|
||||||
|
if (v != NULL) \
|
||||||
|
PyDict_SetItemString(sysdict, key, v); \
|
||||||
|
Py_XDECREF(v)
|
||||||
|
|
||||||
{
|
{
|
||||||
/* XXX: does this work on Win/Win64? (see posix_fstat) */
|
/* XXX: does this work on Win/Win64? (see posix_fstat) */
|
||||||
|
@ -1165,19 +1168,16 @@ _PySys_Init(void)
|
||||||
PyDict_GetItemString(sysdict, "displayhook"));
|
PyDict_GetItemString(sysdict, "displayhook"));
|
||||||
PyDict_SetItemString(sysdict, "__excepthook__",
|
PyDict_SetItemString(sysdict, "__excepthook__",
|
||||||
PyDict_GetItemString(sysdict, "excepthook"));
|
PyDict_GetItemString(sysdict, "excepthook"));
|
||||||
PyDict_SetItemString(sysdict, "version",
|
SET_SYS_FROM_STRING("version",
|
||||||
v = PyUnicode_FromString(Py_GetVersion()));
|
PyUnicode_FromString(Py_GetVersion()));
|
||||||
Py_XDECREF(v);
|
SET_SYS_FROM_STRING("hexversion",
|
||||||
PyDict_SetItemString(sysdict, "hexversion",
|
PyLong_FromLong(PY_VERSION_HEX));
|
||||||
v = PyLong_FromLong(PY_VERSION_HEX));
|
|
||||||
Py_XDECREF(v);
|
|
||||||
svnversion_init();
|
svnversion_init();
|
||||||
v = Py_BuildValue("(UUU)", "CPython", branch, svn_revision);
|
SET_SYS_FROM_STRING("subversion",
|
||||||
PyDict_SetItemString(sysdict, "subversion", v);
|
Py_BuildValue("(UUU)", "CPython", branch,
|
||||||
Py_XDECREF(v);
|
svn_revision));
|
||||||
PyDict_SetItemString(sysdict, "dont_write_bytecode",
|
SET_SYS_FROM_STRING("dont_write_bytecode",
|
||||||
v = PyBool_FromLong(Py_DontWriteBytecodeFlag));
|
PyBool_FromLong(Py_DontWriteBytecodeFlag));
|
||||||
Py_XDECREF(v);
|
|
||||||
/*
|
/*
|
||||||
* These release level checks are mutually exclusive and cover
|
* These release level checks are mutually exclusive and cover
|
||||||
* the field, so don't get too fancy with the pre-processor!
|
* the field, so don't get too fancy with the pre-processor!
|
||||||
|
@ -1192,12 +1192,6 @@ _PySys_Init(void)
|
||||||
s = "final";
|
s = "final";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define SET_SYS_FROM_STRING(key, value) \
|
|
||||||
v = value; \
|
|
||||||
if (v != NULL) \
|
|
||||||
PyDict_SetItemString(sysdict, key, v); \
|
|
||||||
Py_XDECREF(v)
|
|
||||||
|
|
||||||
SET_SYS_FROM_STRING("version_info",
|
SET_SYS_FROM_STRING("version_info",
|
||||||
Py_BuildValue("iiiUi", PY_MAJOR_VERSION,
|
Py_BuildValue("iiiUi", PY_MAJOR_VERSION,
|
||||||
PY_MINOR_VERSION,
|
PY_MINOR_VERSION,
|
||||||
|
@ -1244,7 +1238,6 @@ _PySys_Init(void)
|
||||||
SET_SYS_FROM_STRING("winver",
|
SET_SYS_FROM_STRING("winver",
|
||||||
PyUnicode_FromString(PyWin_DLLVersionString));
|
PyUnicode_FromString(PyWin_DLLVersionString));
|
||||||
#endif
|
#endif
|
||||||
#undef SET_SYS_FROM_STRING
|
|
||||||
if (warnoptions == NULL) {
|
if (warnoptions == NULL) {
|
||||||
warnoptions = PyList_New(0);
|
warnoptions = PyList_New(0);
|
||||||
}
|
}
|
||||||
|
@ -1255,12 +1248,14 @@ _PySys_Init(void)
|
||||||
PyDict_SetItemString(sysdict, "warnoptions", warnoptions);
|
PyDict_SetItemString(sysdict, "warnoptions", warnoptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
PyStructSequence_InitType(&FlagsType, &flags_desc);
|
if (FlagsType.tp_name == 0)
|
||||||
PyDict_SetItemString(sysdict, "flags", make_flags());
|
PyStructSequence_InitType(&FlagsType, &flags_desc);
|
||||||
|
SET_SYS_FROM_STRING("flags", make_flags());
|
||||||
/* prevent user from creating new instances */
|
/* prevent user from creating new instances */
|
||||||
FlagsType.tp_init = NULL;
|
FlagsType.tp_init = NULL;
|
||||||
FlagsType.tp_new = NULL;
|
FlagsType.tp_new = NULL;
|
||||||
|
|
||||||
|
#undef SET_SYS_FROM_STRING
|
||||||
if (PyErr_Occurred())
|
if (PyErr_Occurred())
|
||||||
return NULL;
|
return NULL;
|
||||||
return m;
|
return m;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
# From configure.in Revision: 59829 .
|
# From configure.in Revision: 60144 .
|
||||||
# Guess values for system-dependent variables and create Makefiles.
|
# Guess values for system-dependent variables and create Makefiles.
|
||||||
# Generated by GNU Autoconf 2.61 for python 3.0.
|
# Generated by GNU Autoconf 2.61 for python 3.0.
|
||||||
#
|
#
|
||||||
|
@ -14600,6 +14600,12 @@ _ACEOF
|
||||||
SunOS/5.8)
|
SunOS/5.8)
|
||||||
cat >>confdefs.h <<\_ACEOF
|
cat >>confdefs.h <<\_ACEOF
|
||||||
#define HAVE_BROKEN_POSIX_SEMAPHORES 1
|
#define HAVE_BROKEN_POSIX_SEMAPHORES 1
|
||||||
|
_ACEOF
|
||||||
|
|
||||||
|
;;
|
||||||
|
AIX/5)
|
||||||
|
cat >>confdefs.h <<\_ACEOF
|
||||||
|
#define HAVE_BROKEN_POSIX_SEMAPHORES 1
|
||||||
_ACEOF
|
_ACEOF
|
||||||
|
|
||||||
;;
|
;;
|
||||||
|
|
|
@ -1965,6 +1965,9 @@ if test "$posix_threads" = "yes"; then
|
||||||
SunOS/5.8) AC_DEFINE(HAVE_BROKEN_POSIX_SEMAPHORES, 1,
|
SunOS/5.8) AC_DEFINE(HAVE_BROKEN_POSIX_SEMAPHORES, 1,
|
||||||
Define if the Posix semaphores do not work on your system)
|
Define if the Posix semaphores do not work on your system)
|
||||||
;;
|
;;
|
||||||
|
AIX/5) AC_DEFINE(HAVE_BROKEN_POSIX_SEMAPHORES, 1,
|
||||||
|
Define if the Posix semaphores do not work on your system)
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
AC_MSG_CHECKING(if PTHREAD_SCOPE_SYSTEM is supported)
|
AC_MSG_CHECKING(if PTHREAD_SCOPE_SYSTEM is supported)
|
||||||
|
|
Loading…
Reference in New Issue