mirror of https://github.com/python/cpython
merge heads
This commit is contained in:
commit
059226b8ec
|
@ -1669,6 +1669,24 @@ with the :class:`Pool` class.
|
|||
returned iterator should be considered arbitrary. (Only when there is
|
||||
only one worker process is the order guaranteed to be "correct".)
|
||||
|
||||
.. method:: starmap(func, iterable[, chunksize])
|
||||
|
||||
Like :meth:`map` except that the elements of the `iterable` are expected
|
||||
to be iterables that are unpacked as arguments.
|
||||
|
||||
Hence an `iterable` of `[(1,2), (3, 4)]` results in `[func(1,2),
|
||||
func(3,4)]`.
|
||||
|
||||
.. versionadded:: 3.3
|
||||
|
||||
.. method:: starmap_async(func, iterable[, chunksize[, callback[, error_back]]])
|
||||
|
||||
A combination of :meth:`starmap` and :meth:`map_async` that iterates over
|
||||
`iterable` of iterables and calls `func` with the iterables unpacked.
|
||||
Returns a result object.
|
||||
|
||||
.. versionadded:: 3.3
|
||||
|
||||
.. method:: close()
|
||||
|
||||
Prevents any more tasks from being submitted to the pool. Once all the
|
||||
|
|
|
@ -445,6 +445,14 @@ Constants
|
|||
|
||||
.. versionadded:: 3.3
|
||||
|
||||
.. data:: HAS_ECDH
|
||||
|
||||
Whether the OpenSSL library has built-in support for Elliptic Curve-based
|
||||
Diffie-Hellman key exchange. This should be true unless the feature was
|
||||
explicitly disabled by the distributor.
|
||||
|
||||
.. versionadded:: 3.3
|
||||
|
||||
.. data:: HAS_SNI
|
||||
|
||||
Whether the OpenSSL library has built-in support for the *Server Name
|
||||
|
@ -711,6 +719,8 @@ to speed up repeated connections from the same clients.
|
|||
This setting doesn't apply to client sockets. You can also use the
|
||||
:data:`OP_SINGLE_ECDH_USE` option to further improve security.
|
||||
|
||||
This method is not available if :data:`HAS_ECDH` is False.
|
||||
|
||||
.. versionadded:: 3.3
|
||||
|
||||
.. seealso::
|
||||
|
|
|
@ -96,47 +96,55 @@ A number of browser types are predefined. This table gives the type names that
|
|||
may be passed to the :func:`get` function and the corresponding instantiations
|
||||
for the controller classes, all defined in this module.
|
||||
|
||||
+-----------------------+-----------------------------------------+-------+
|
||||
| Type Name | Class Name | Notes |
|
||||
+=======================+=========================================+=======+
|
||||
| ``'mozilla'`` | :class:`Mozilla('mozilla')` | |
|
||||
+-----------------------+-----------------------------------------+-------+
|
||||
| ``'firefox'`` | :class:`Mozilla('mozilla')` | |
|
||||
+-----------------------+-----------------------------------------+-------+
|
||||
| ``'netscape'`` | :class:`Mozilla('netscape')` | |
|
||||
+-----------------------+-----------------------------------------+-------+
|
||||
| ``'galeon'`` | :class:`Galeon('galeon')` | |
|
||||
+-----------------------+-----------------------------------------+-------+
|
||||
| ``'epiphany'`` | :class:`Galeon('epiphany')` | |
|
||||
+-----------------------+-----------------------------------------+-------+
|
||||
| ``'skipstone'`` | :class:`BackgroundBrowser('skipstone')` | |
|
||||
+-----------------------+-----------------------------------------+-------+
|
||||
| ``'kfmclient'`` | :class:`Konqueror()` | \(1) |
|
||||
+-----------------------+-----------------------------------------+-------+
|
||||
| ``'konqueror'`` | :class:`Konqueror()` | \(1) |
|
||||
+-----------------------+-----------------------------------------+-------+
|
||||
| ``'kfm'`` | :class:`Konqueror()` | \(1) |
|
||||
+-----------------------+-----------------------------------------+-------+
|
||||
| ``'mosaic'`` | :class:`BackgroundBrowser('mosaic')` | |
|
||||
+-----------------------+-----------------------------------------+-------+
|
||||
| ``'opera'`` | :class:`Opera()` | |
|
||||
+-----------------------+-----------------------------------------+-------+
|
||||
| ``'grail'`` | :class:`Grail()` | |
|
||||
+-----------------------+-----------------------------------------+-------+
|
||||
| ``'links'`` | :class:`GenericBrowser('links')` | |
|
||||
+-----------------------+-----------------------------------------+-------+
|
||||
| ``'elinks'`` | :class:`Elinks('elinks')` | |
|
||||
+-----------------------+-----------------------------------------+-------+
|
||||
| ``'lynx'`` | :class:`GenericBrowser('lynx')` | |
|
||||
+-----------------------+-----------------------------------------+-------+
|
||||
| ``'w3m'`` | :class:`GenericBrowser('w3m')` | |
|
||||
+-----------------------+-----------------------------------------+-------+
|
||||
| ``'windows-default'`` | :class:`WindowsDefault` | \(2) |
|
||||
+-----------------------+-----------------------------------------+-------+
|
||||
| ``'internet-config'`` | :class:`InternetConfig` | \(3) |
|
||||
+-----------------------+-----------------------------------------+-------+
|
||||
| ``'macosx'`` | :class:`MacOSX('default')` | \(4) |
|
||||
+-----------------------+-----------------------------------------+-------+
|
||||
+------------------------+-----------------------------------------+-------+
|
||||
| Type Name | Class Name | Notes |
|
||||
+========================+=========================================+=======+
|
||||
| ``'mozilla'`` | :class:`Mozilla('mozilla')` | |
|
||||
+------------------------+-----------------------------------------+-------+
|
||||
| ``'firefox'`` | :class:`Mozilla('mozilla')` | |
|
||||
+------------------------+-----------------------------------------+-------+
|
||||
| ``'netscape'`` | :class:`Mozilla('netscape')` | |
|
||||
+------------------------+-----------------------------------------+-------+
|
||||
| ``'galeon'`` | :class:`Galeon('galeon')` | |
|
||||
+------------------------+-----------------------------------------+-------+
|
||||
| ``'epiphany'`` | :class:`Galeon('epiphany')` | |
|
||||
+------------------------+-----------------------------------------+-------+
|
||||
| ``'skipstone'`` | :class:`BackgroundBrowser('skipstone')` | |
|
||||
+------------------------+-----------------------------------------+-------+
|
||||
| ``'kfmclient'`` | :class:`Konqueror()` | \(1) |
|
||||
+------------------------+-----------------------------------------+-------+
|
||||
| ``'konqueror'`` | :class:`Konqueror()` | \(1) |
|
||||
+------------------------+-----------------------------------------+-------+
|
||||
| ``'kfm'`` | :class:`Konqueror()` | \(1) |
|
||||
+------------------------+-----------------------------------------+-------+
|
||||
| ``'mosaic'`` | :class:`BackgroundBrowser('mosaic')` | |
|
||||
+------------------------+-----------------------------------------+-------+
|
||||
| ``'opera'`` | :class:`Opera()` | |
|
||||
+------------------------+-----------------------------------------+-------+
|
||||
| ``'grail'`` | :class:`Grail()` | |
|
||||
+------------------------+-----------------------------------------+-------+
|
||||
| ``'links'`` | :class:`GenericBrowser('links')` | |
|
||||
+------------------------+-----------------------------------------+-------+
|
||||
| ``'elinks'`` | :class:`Elinks('elinks')` | |
|
||||
+------------------------+-----------------------------------------+-------+
|
||||
| ``'lynx'`` | :class:`GenericBrowser('lynx')` | |
|
||||
+------------------------+-----------------------------------------+-------+
|
||||
| ``'w3m'`` | :class:`GenericBrowser('w3m')` | |
|
||||
+------------------------+-----------------------------------------+-------+
|
||||
| ``'windows-default'`` | :class:`WindowsDefault` | \(2) |
|
||||
+------------------------+-----------------------------------------+-------+
|
||||
| ``'internet-config'`` | :class:`InternetConfig` | \(3) |
|
||||
+------------------------+-----------------------------------------+-------+
|
||||
| ``'macosx'`` | :class:`MacOSX('default')` | \(4) |
|
||||
+------------------------+-----------------------------------------+-------+
|
||||
| ``'google-chrome'`` | :class:`Chrome('google-chrome')` | |
|
||||
+------------------------+-----------------------------------------+-------+
|
||||
| ``'chrome'`` | :class:`Chrome('chrome')` | |
|
||||
+------------------------+-----------------------------------------+-------+
|
||||
| ``'chromium'`` | :class:`Chromium('chromium')` | |
|
||||
+------------------------+-----------------------------------------+-------+
|
||||
| ``'chromium-browser'`` | :class:`Chromium('chromium-browser')` | |
|
||||
+------------------------+-----------------------------------------+-------+
|
||||
|
||||
Notes:
|
||||
|
||||
|
|
|
@ -249,7 +249,8 @@ Miscellaneous options
|
|||
|
||||
Force the binary layer of the stdin, stdout and stderr streams (which is
|
||||
available as their ``buffer`` attribute) to be unbuffered. The text I/O
|
||||
layer will still be line-buffered.
|
||||
layer will still be line-buffered if writing to the console, or
|
||||
block-buffered if redirected to a non-interactive file.
|
||||
|
||||
See also :envvar:`PYTHONUNBUFFERED`.
|
||||
|
||||
|
|
|
@ -301,6 +301,12 @@ changed.
|
|||
There is no longer any need for using the encoding-aware streams
|
||||
in the :mod:`codecs` module.
|
||||
|
||||
* The initial values of :data:`sys.stdin`, :data:`sys.stdout` and
|
||||
:data:`sys.stderr` are now unicode-only text files (i.e., they are
|
||||
instances of :class:`io.TextIOBase`). To read and write bytes data
|
||||
with these streams, you need to use their :data:`io.TextIOBase.buffer`
|
||||
attribute.
|
||||
|
||||
* Filenames are passed to and returned from APIs as (Unicode) strings.
|
||||
This can present platform-specific problems because on some
|
||||
platforms filenames are arbitrary byte strings. (On the other hand,
|
||||
|
@ -511,9 +517,7 @@ consulted for longer descriptions.
|
|||
produces a literal of type :class:`bytes`.
|
||||
|
||||
* :ref:`pep-3116`. The :mod:`io` module is now the standard way of
|
||||
doing file I/O, and the initial values of :data:`sys.stdin`,
|
||||
:data:`sys.stdout` and :data:`sys.stderr` are now instances of
|
||||
:class:`io.TextIOBase`. The built-in :func:`open` function is now an
|
||||
doing file I/O. The built-in :func:`open` function is now an
|
||||
alias for :func:`io.open` and has additional keyword arguments
|
||||
*encoding*, *errors*, *newline* and *closefd*. Also note that an
|
||||
invalid *mode* argument now raises :exc:`ValueError`, not
|
||||
|
|
|
@ -99,11 +99,11 @@ def ismethoddescriptor(object):
|
|||
tests return false from the ismethoddescriptor() test, simply because
|
||||
the other tests promise more -- you can, e.g., count on having the
|
||||
__func__ attribute (etc) when an object passes ismethod()."""
|
||||
return (hasattr(object, "__get__")
|
||||
and not hasattr(object, "__set__") # else it's a data descriptor
|
||||
and not ismethod(object) # mutual exclusion
|
||||
and not isfunction(object)
|
||||
and not isclass(object))
|
||||
if isclass(object) or ismethod(object) or isfunction(object):
|
||||
# mutual exclusion
|
||||
return False
|
||||
tp = type(object)
|
||||
return hasattr(tp, "__get__") and not hasattr(tp, "__set__")
|
||||
|
||||
def isdatadescriptor(object):
|
||||
"""Return true if the object is a data descriptor.
|
||||
|
@ -113,7 +113,11 @@ def isdatadescriptor(object):
|
|||
Typically, data descriptors will also have __name__ and __doc__ attributes
|
||||
(properties, getsets, and members have both of these attributes), but this
|
||||
is not guaranteed."""
|
||||
return (hasattr(object, "__set__") and hasattr(object, "__get__"))
|
||||
if isclass(object) or ismethod(object) or isfunction(object):
|
||||
# mutual exclusion
|
||||
return False
|
||||
tp = type(object)
|
||||
return hasattr(tp, "__set__") and hasattr(tp, "__get__")
|
||||
|
||||
if hasattr(types, 'MemberDescriptorType'):
|
||||
# CPython and equivalent
|
||||
|
@ -253,12 +257,23 @@ def isabstract(object):
|
|||
def getmembers(object, predicate=None):
|
||||
"""Return all members of an object as (name, value) pairs sorted by name.
|
||||
Optionally, only return members that satisfy a given predicate."""
|
||||
if isclass(object):
|
||||
mro = (object,) + getmro(object)
|
||||
else:
|
||||
mro = ()
|
||||
results = []
|
||||
for key in dir(object):
|
||||
try:
|
||||
value = getattr(object, key)
|
||||
except AttributeError:
|
||||
continue
|
||||
# First try to get the value via __dict__. Some descriptors don't
|
||||
# like calling their __get__ (see bug #1785).
|
||||
for base in mro:
|
||||
if key in base.__dict__:
|
||||
value = base.__dict__[key]
|
||||
break
|
||||
else:
|
||||
try:
|
||||
value = getattr(object, key)
|
||||
except AttributeError:
|
||||
continue
|
||||
if not predicate or predicate(value):
|
||||
results.append((key, value))
|
||||
results.sort()
|
||||
|
@ -294,30 +309,21 @@ def classify_class_attrs(cls):
|
|||
names = dir(cls)
|
||||
result = []
|
||||
for name in names:
|
||||
# Get the object associated with the name.
|
||||
# Get the object associated with the name, and where it was defined.
|
||||
# Getting an obj from the __dict__ sometimes reveals more than
|
||||
# using getattr. Static and class methods are dramatic examples.
|
||||
if name in cls.__dict__:
|
||||
obj = cls.__dict__[name]
|
||||
# Furthermore, some objects may raise an Exception when fetched with
|
||||
# getattr(). This is the case with some descriptors (bug #1785).
|
||||
# Thus, we only use getattr() as a last resort.
|
||||
homecls = None
|
||||
for base in (cls,) + mro:
|
||||
if name in base.__dict__:
|
||||
obj = base.__dict__[name]
|
||||
homecls = base
|
||||
break
|
||||
else:
|
||||
obj = getattr(cls, name)
|
||||
|
||||
# Figure out where it was defined.
|
||||
homecls = getattr(obj, "__objclass__", None)
|
||||
if homecls is None:
|
||||
# search the dicts.
|
||||
for base in mro:
|
||||
if name in base.__dict__:
|
||||
homecls = base
|
||||
break
|
||||
|
||||
# Get the object again, in order to get it from the defining
|
||||
# __dict__ instead of via getattr (if possible).
|
||||
if homecls is not None and name in homecls.__dict__:
|
||||
obj = homecls.__dict__[name]
|
||||
|
||||
# Also get the object via getattr.
|
||||
obj_via_getattr = getattr(cls, name)
|
||||
homecls = getattr(obj, "__objclass__", homecls)
|
||||
|
||||
# Classify the object.
|
||||
if isinstance(obj, staticmethod):
|
||||
|
@ -326,11 +332,18 @@ def classify_class_attrs(cls):
|
|||
kind = "class method"
|
||||
elif isinstance(obj, property):
|
||||
kind = "property"
|
||||
elif (isfunction(obj_via_getattr) or
|
||||
ismethoddescriptor(obj_via_getattr)):
|
||||
elif ismethoddescriptor(obj):
|
||||
kind = "method"
|
||||
else:
|
||||
elif isdatadescriptor(obj):
|
||||
kind = "data"
|
||||
else:
|
||||
obj_via_getattr = getattr(cls, name)
|
||||
if (isfunction(obj_via_getattr) or
|
||||
ismethoddescriptor(obj_via_getattr)):
|
||||
kind = "method"
|
||||
else:
|
||||
kind = "data"
|
||||
obj = obj_via_getattr
|
||||
|
||||
result.append(Attribute(name, kind, homecls, obj))
|
||||
|
||||
|
|
|
@ -1066,11 +1066,12 @@ ArrayProxy = MakeProxyType('ArrayProxy', (
|
|||
|
||||
PoolProxy = MakeProxyType('PoolProxy', (
|
||||
'apply', 'apply_async', 'close', 'imap', 'imap_unordered', 'join',
|
||||
'map', 'map_async', 'terminate'
|
||||
'map', 'map_async', 'starmap', 'starmap_async', 'terminate'
|
||||
))
|
||||
PoolProxy._method_to_typeid_ = {
|
||||
'apply_async': 'AsyncResult',
|
||||
'map_async': 'AsyncResult',
|
||||
'starmap_async': 'AsyncResult',
|
||||
'imap': 'Iterator',
|
||||
'imap_unordered': 'Iterator'
|
||||
}
|
||||
|
|
|
@ -64,6 +64,9 @@ job_counter = itertools.count()
|
|||
def mapstar(args):
|
||||
return list(map(*args))
|
||||
|
||||
def starmapstar(args):
|
||||
return list(itertools.starmap(args[0], args[1]))
|
||||
|
||||
#
|
||||
# Code run by worker processes
|
||||
#
|
||||
|
@ -248,7 +251,25 @@ class Pool(object):
|
|||
in a list that is returned.
|
||||
'''
|
||||
assert self._state == RUN
|
||||
return self.map_async(func, iterable, chunksize).get()
|
||||
return self._map_async(func, iterable, mapstar, chunksize).get()
|
||||
|
||||
def starmap(self, func, iterable, chunksize=None):
|
||||
'''
|
||||
Like `map()` method but the elements of the `iterable` are expected to
|
||||
be iterables as well and will be unpacked as arguments. Hence
|
||||
`func` and (a, b) becomes func(a, b).
|
||||
'''
|
||||
assert self._state == RUN
|
||||
return self._map_async(func, iterable, starmapstar, chunksize).get()
|
||||
|
||||
def starmap_async(self, func, iterable, chunksize=None, callback=None,
|
||||
error_callback=None):
|
||||
'''
|
||||
Asynchronous version of `starmap()` method.
|
||||
'''
|
||||
assert self._state == RUN
|
||||
return self._map_async(func, iterable, starmapstar, chunksize,
|
||||
callback, error_callback)
|
||||
|
||||
def imap(self, func, iterable, chunksize=1):
|
||||
'''
|
||||
|
@ -302,6 +323,13 @@ class Pool(object):
|
|||
Asynchronous version of `map()` method.
|
||||
'''
|
||||
assert self._state == RUN
|
||||
return self._map_async(func, iterable, mapstar, chunksize)
|
||||
|
||||
def _map_async(self, func, iterable, mapper, chunksize=None, callback=None,
|
||||
error_callback=None):
|
||||
'''
|
||||
Helper function to implement map, starmap and their async counterparts.
|
||||
'''
|
||||
if not hasattr(iterable, '__len__'):
|
||||
iterable = list(iterable)
|
||||
|
||||
|
@ -315,7 +343,7 @@ class Pool(object):
|
|||
task_batches = Pool._get_tasks(func, iterable, chunksize)
|
||||
result = MapResult(self._cache, chunksize, len(iterable), callback,
|
||||
error_callback=error_callback)
|
||||
self._taskqueue.put((((result._job, i, mapstar, (x,), {})
|
||||
self._taskqueue.put((((result._job, i, mapper, (x,), {})
|
||||
for i, x in enumerate(task_batches)), None))
|
||||
return result
|
||||
|
||||
|
|
29
Lib/pydoc.py
29
Lib/pydoc.py
|
@ -748,8 +748,15 @@ class HTMLDoc(Doc):
|
|||
hr.maybe()
|
||||
push(msg)
|
||||
for name, kind, homecls, value in ok:
|
||||
push(self.document(getattr(object, name), name, mod,
|
||||
funcs, classes, mdict, object))
|
||||
try:
|
||||
value = getattr(object, name)
|
||||
except Exception:
|
||||
# Some descriptors may meet a failure in their __get__.
|
||||
# (bug #1785)
|
||||
push(self._docdescriptor(name, value, mod))
|
||||
else:
|
||||
push(self.document(value, name, mod,
|
||||
funcs, classes, mdict, object))
|
||||
push('\n')
|
||||
return attrs
|
||||
|
||||
|
@ -790,7 +797,12 @@ class HTMLDoc(Doc):
|
|||
mdict = {}
|
||||
for key, kind, homecls, value in attrs:
|
||||
mdict[key] = anchor = '#' + name + '-' + key
|
||||
value = getattr(object, key)
|
||||
try:
|
||||
value = getattr(object, name)
|
||||
except Exception:
|
||||
# Some descriptors may meet a failure in their __get__.
|
||||
# (bug #1785)
|
||||
pass
|
||||
try:
|
||||
# The value may not be hashable (e.g., a data attr with
|
||||
# a dict or list value).
|
||||
|
@ -1177,8 +1189,15 @@ location listed above.
|
|||
hr.maybe()
|
||||
push(msg)
|
||||
for name, kind, homecls, value in ok:
|
||||
push(self.document(getattr(object, name),
|
||||
name, mod, object))
|
||||
try:
|
||||
value = getattr(object, name)
|
||||
except Exception:
|
||||
# Some descriptors may meet a failure in their __get__.
|
||||
# (bug #1785)
|
||||
push(self._docdescriptor(name, value, mod))
|
||||
else:
|
||||
push(self.document(value,
|
||||
name, mod, object))
|
||||
return attrs
|
||||
|
||||
def spilldescriptors(msg, attrs, predicate):
|
||||
|
|
|
@ -86,7 +86,7 @@ from _ssl import (
|
|||
SSL_ERROR_EOF,
|
||||
SSL_ERROR_INVALID_ERROR_CODE,
|
||||
)
|
||||
from _ssl import HAS_SNI
|
||||
from _ssl import HAS_SNI, HAS_ECDH
|
||||
from _ssl import (PROTOCOL_SSLv3, PROTOCOL_SSLv23,
|
||||
PROTOCOL_TLSv1)
|
||||
from _ssl import _OPENSSL_API_VERSION
|
||||
|
|
|
@ -104,8 +104,9 @@ class ImportTests(unittest.TestCase):
|
|||
try:
|
||||
fname = TESTFN + os.extsep + "py"
|
||||
create_empty_file(fname)
|
||||
__import__(TESTFN)
|
||||
fn = imp.cache_from_source(fname)
|
||||
unlink(fn)
|
||||
__import__(TESTFN)
|
||||
if not os.path.exists(fn):
|
||||
self.fail("__import__ did not result in creation of "
|
||||
"either a .pyc or .pyo file")
|
||||
|
|
|
@ -425,10 +425,37 @@ class TestNoEOL(GetSourceBase):
|
|||
def test_class(self):
|
||||
self.assertSourceEqual(self.fodderModule.X, 1, 2)
|
||||
|
||||
|
||||
class _BrokenDataDescriptor(object):
|
||||
"""
|
||||
A broken data descriptor. See bug #1785.
|
||||
"""
|
||||
def __get__(*args):
|
||||
raise AssertionError("should not __get__ data descriptors")
|
||||
|
||||
def __set__(*args):
|
||||
raise RuntimeError
|
||||
|
||||
def __getattr__(*args):
|
||||
raise AssertionError("should not __getattr__ data descriptors")
|
||||
|
||||
|
||||
class _BrokenMethodDescriptor(object):
|
||||
"""
|
||||
A broken method descriptor. See bug #1785.
|
||||
"""
|
||||
def __get__(*args):
|
||||
raise AssertionError("should not __get__ method descriptors")
|
||||
|
||||
def __getattr__(*args):
|
||||
raise AssertionError("should not __getattr__ method descriptors")
|
||||
|
||||
|
||||
# Helper for testing classify_class_attrs.
|
||||
def attrs_wo_objs(cls):
|
||||
return [t[:3] for t in inspect.classify_class_attrs(cls)]
|
||||
|
||||
|
||||
class TestClassesAndFunctions(unittest.TestCase):
|
||||
def test_newstyle_mro(self):
|
||||
# The same w/ new-class MRO.
|
||||
|
@ -525,6 +552,9 @@ class TestClassesAndFunctions(unittest.TestCase):
|
|||
|
||||
datablob = '1'
|
||||
|
||||
dd = _BrokenDataDescriptor()
|
||||
md = _BrokenMethodDescriptor()
|
||||
|
||||
attrs = attrs_wo_objs(A)
|
||||
self.assertIn(('s', 'static method', A), attrs, 'missing static method')
|
||||
self.assertIn(('c', 'class method', A), attrs, 'missing class method')
|
||||
|
@ -533,6 +563,8 @@ class TestClassesAndFunctions(unittest.TestCase):
|
|||
'missing plain method: %r' % attrs)
|
||||
self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
|
||||
self.assertIn(('datablob', 'data', A), attrs, 'missing data')
|
||||
self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
|
||||
self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
|
||||
|
||||
class B(A):
|
||||
|
||||
|
@ -545,6 +577,8 @@ class TestClassesAndFunctions(unittest.TestCase):
|
|||
self.assertIn(('m', 'method', B), attrs, 'missing plain method')
|
||||
self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
|
||||
self.assertIn(('datablob', 'data', A), attrs, 'missing data')
|
||||
self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
|
||||
self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
|
||||
|
||||
|
||||
class C(A):
|
||||
|
@ -559,6 +593,8 @@ class TestClassesAndFunctions(unittest.TestCase):
|
|||
self.assertIn(('m', 'method', C), attrs, 'missing plain method')
|
||||
self.assertIn(('m1', 'method', A), attrs, 'missing plain method')
|
||||
self.assertIn(('datablob', 'data', A), attrs, 'missing data')
|
||||
self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
|
||||
self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
|
||||
|
||||
class D(B, C):
|
||||
|
||||
|
@ -571,6 +607,49 @@ class TestClassesAndFunctions(unittest.TestCase):
|
|||
self.assertIn(('m', 'method', B), attrs, 'missing plain method')
|
||||
self.assertIn(('m1', 'method', D), attrs, 'missing plain method')
|
||||
self.assertIn(('datablob', 'data', A), attrs, 'missing data')
|
||||
self.assertIn(('md', 'method', A), attrs, 'missing method descriptor')
|
||||
self.assertIn(('dd', 'data', A), attrs, 'missing data descriptor')
|
||||
|
||||
def test_classify_builtin_types(self):
|
||||
# Simple sanity check that all built-in types can have their
|
||||
# attributes classified.
|
||||
for name in dir(__builtins__):
|
||||
builtin = getattr(__builtins__, name)
|
||||
if isinstance(builtin, type):
|
||||
inspect.classify_class_attrs(builtin)
|
||||
|
||||
def test_getmembers_descriptors(self):
|
||||
class A(object):
|
||||
dd = _BrokenDataDescriptor()
|
||||
md = _BrokenMethodDescriptor()
|
||||
|
||||
def pred_wrapper(pred):
|
||||
# A quick'n'dirty way to discard standard attributes of new-style
|
||||
# classes.
|
||||
class Empty(object):
|
||||
pass
|
||||
def wrapped(x):
|
||||
if '__name__' in dir(x) and hasattr(Empty, x.__name__):
|
||||
return False
|
||||
return pred(x)
|
||||
return wrapped
|
||||
|
||||
ismethoddescriptor = pred_wrapper(inspect.ismethoddescriptor)
|
||||
isdatadescriptor = pred_wrapper(inspect.isdatadescriptor)
|
||||
|
||||
self.assertEqual(inspect.getmembers(A, ismethoddescriptor),
|
||||
[('md', A.__dict__['md'])])
|
||||
self.assertEqual(inspect.getmembers(A, isdatadescriptor),
|
||||
[('dd', A.__dict__['dd'])])
|
||||
|
||||
class B(A):
|
||||
pass
|
||||
|
||||
self.assertEqual(inspect.getmembers(B, ismethoddescriptor),
|
||||
[('md', A.__dict__['md'])])
|
||||
self.assertEqual(inspect.getmembers(B, isdatadescriptor),
|
||||
[('dd', A.__dict__['dd'])])
|
||||
|
||||
|
||||
class TestGetcallargsFunctions(unittest.TestCase):
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ import unittest
|
|||
import queue as pyqueue
|
||||
import time
|
||||
import io
|
||||
import itertools
|
||||
import sys
|
||||
import os
|
||||
import gc
|
||||
|
@ -1125,6 +1126,9 @@ def sqr(x, wait=0.0):
|
|||
time.sleep(wait)
|
||||
return x*x
|
||||
|
||||
def mul(x, y):
|
||||
return x*y
|
||||
|
||||
class _TestPool(BaseTestCase):
|
||||
|
||||
def test_apply(self):
|
||||
|
@ -1138,6 +1142,20 @@ class _TestPool(BaseTestCase):
|
|||
self.assertEqual(pmap(sqr, list(range(100)), chunksize=20),
|
||||
list(map(sqr, list(range(100)))))
|
||||
|
||||
def test_starmap(self):
|
||||
psmap = self.pool.starmap
|
||||
tuples = list(zip(range(10), range(9,-1, -1)))
|
||||
self.assertEqual(psmap(mul, tuples),
|
||||
list(itertools.starmap(mul, tuples)))
|
||||
tuples = list(zip(range(100), range(99,-1, -1)))
|
||||
self.assertEqual(psmap(mul, tuples, chunksize=20),
|
||||
list(itertools.starmap(mul, tuples)))
|
||||
|
||||
def test_starmap_async(self):
|
||||
tuples = list(zip(range(100), range(99,-1, -1)))
|
||||
self.assertEqual(self.pool.starmap_async(mul, tuples).get(),
|
||||
list(itertools.starmap(mul, tuples)))
|
||||
|
||||
def test_map_chunksize(self):
|
||||
try:
|
||||
self.pool.map_async(sqr, [], chunksize=1).get(timeout=TIMEOUT1)
|
||||
|
|
|
@ -103,6 +103,7 @@ class BasicSocketTests(unittest.TestCase):
|
|||
if ssl.OPENSSL_VERSION_INFO >= (1, 0):
|
||||
ssl.OP_NO_COMPRESSION
|
||||
self.assertIn(ssl.HAS_SNI, {True, False})
|
||||
self.assertIn(ssl.HAS_ECDH, {True, False})
|
||||
|
||||
def test_random(self):
|
||||
v = ssl.RAND_status()
|
||||
|
@ -561,6 +562,7 @@ class ContextTests(unittest.TestCase):
|
|||
ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
|
||||
ctx.set_default_verify_paths()
|
||||
|
||||
@unittest.skipUnless(ssl.HAS_ECDH, "ECDH disabled on this OpenSSL build")
|
||||
def test_set_ecdh_curve(self):
|
||||
ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
|
||||
ctx.set_ecdh_curve("prime256v1")
|
||||
|
@ -984,6 +986,14 @@ else:
|
|||
threading.Thread.__init__(self)
|
||||
self.daemon = True
|
||||
|
||||
def __enter__(self):
|
||||
self.start(threading.Event())
|
||||
self.flag.wait()
|
||||
|
||||
def __exit__(self, *args):
|
||||
self.stop()
|
||||
self.join()
|
||||
|
||||
def start(self, flag=None):
|
||||
self.flag = flag
|
||||
threading.Thread.start(self)
|
||||
|
@ -1095,6 +1105,20 @@ else:
|
|||
def __str__(self):
|
||||
return "<%s %s>" % (self.__class__.__name__, self.server)
|
||||
|
||||
def __enter__(self):
|
||||
self.start(threading.Event())
|
||||
self.flag.wait()
|
||||
|
||||
def __exit__(self, *args):
|
||||
if support.verbose:
|
||||
sys.stdout.write(" cleanup: stopping server.\n")
|
||||
self.stop()
|
||||
if support.verbose:
|
||||
sys.stdout.write(" cleanup: joining server thread.\n")
|
||||
self.join()
|
||||
if support.verbose:
|
||||
sys.stdout.write(" cleanup: successfully joined.\n")
|
||||
|
||||
def start (self, flag=None):
|
||||
self.flag = flag
|
||||
threading.Thread.start(self)
|
||||
|
@ -1122,12 +1146,7 @@ else:
|
|||
certreqs=ssl.CERT_REQUIRED,
|
||||
cacerts=CERTFILE, chatty=False,
|
||||
connectionchatty=False)
|
||||
flag = threading.Event()
|
||||
server.start(flag)
|
||||
# wait for it to start
|
||||
flag.wait()
|
||||
# try to connect
|
||||
try:
|
||||
with server:
|
||||
try:
|
||||
with socket.socket() as sock:
|
||||
s = ssl.wrap_socket(sock,
|
||||
|
@ -1147,9 +1166,6 @@ else:
|
|||
sys.stdout.write("\IOError is %s\n" % str(x))
|
||||
else:
|
||||
raise AssertionError("Use of invalid cert should have failed!")
|
||||
finally:
|
||||
server.stop()
|
||||
server.join()
|
||||
|
||||
def server_params_test(client_context, server_context, indata=b"FOO\n",
|
||||
chatty=True, connectionchatty=False):
|
||||
|
@ -1160,12 +1176,7 @@ else:
|
|||
server = ThreadedEchoServer(context=server_context,
|
||||
chatty=chatty,
|
||||
connectionchatty=False)
|
||||
flag = threading.Event()
|
||||
server.start(flag)
|
||||
# wait for it to start
|
||||
flag.wait()
|
||||
# try to connect
|
||||
try:
|
||||
with server:
|
||||
s = client_context.wrap_socket(socket.socket())
|
||||
s.connect((HOST, server.port))
|
||||
for arg in [indata, bytearray(indata), memoryview(indata)]:
|
||||
|
@ -1193,9 +1204,6 @@ else:
|
|||
}
|
||||
s.close()
|
||||
return stats
|
||||
finally:
|
||||
server.stop()
|
||||
server.join()
|
||||
|
||||
def try_protocol_combo(server_protocol, client_protocol, expect_success,
|
||||
certsreqs=None, server_options=0, client_options=0):
|
||||
|
@ -1264,12 +1272,7 @@ else:
|
|||
context.load_verify_locations(CERTFILE)
|
||||
context.load_cert_chain(CERTFILE)
|
||||
server = ThreadedEchoServer(context=context, chatty=False)
|
||||
flag = threading.Event()
|
||||
server.start(flag)
|
||||
# wait for it to start
|
||||
flag.wait()
|
||||
# try to connect
|
||||
try:
|
||||
with server:
|
||||
s = context.wrap_socket(socket.socket())
|
||||
s.connect((HOST, server.port))
|
||||
cert = s.getpeercert()
|
||||
|
@ -1292,9 +1295,6 @@ else:
|
|||
after = ssl.cert_time_to_seconds(cert['notAfter'])
|
||||
self.assertLess(before, after)
|
||||
s.close()
|
||||
finally:
|
||||
server.stop()
|
||||
server.join()
|
||||
|
||||
def test_empty_cert(self):
|
||||
"""Connecting with an empty cert file"""
|
||||
|
@ -1454,13 +1454,8 @@ else:
|
|||
starttls_server=True,
|
||||
chatty=True,
|
||||
connectionchatty=True)
|
||||
flag = threading.Event()
|
||||
server.start(flag)
|
||||
# wait for it to start
|
||||
flag.wait()
|
||||
# try to connect
|
||||
wrapped = False
|
||||
try:
|
||||
with server:
|
||||
s = socket.socket()
|
||||
s.setblocking(1)
|
||||
s.connect((HOST, server.port))
|
||||
|
@ -1507,9 +1502,6 @@ else:
|
|||
conn.close()
|
||||
else:
|
||||
s.close()
|
||||
finally:
|
||||
server.stop()
|
||||
server.join()
|
||||
|
||||
def test_socketserver(self):
|
||||
"""Using a SocketServer to create and manage SSL connections."""
|
||||
|
@ -1545,12 +1537,7 @@ else:
|
|||
|
||||
indata = b"FOO\n"
|
||||
server = AsyncoreEchoServer(CERTFILE)
|
||||
flag = threading.Event()
|
||||
server.start(flag)
|
||||
# wait for it to start
|
||||
flag.wait()
|
||||
# try to connect
|
||||
try:
|
||||
with server:
|
||||
s = ssl.wrap_socket(socket.socket())
|
||||
s.connect(('127.0.0.1', server.port))
|
||||
if support.verbose:
|
||||
|
@ -1571,15 +1558,6 @@ else:
|
|||
s.close()
|
||||
if support.verbose:
|
||||
sys.stdout.write(" client: connection closed.\n")
|
||||
finally:
|
||||
if support.verbose:
|
||||
sys.stdout.write(" cleanup: stopping server.\n")
|
||||
server.stop()
|
||||
if support.verbose:
|
||||
sys.stdout.write(" cleanup: joining server thread.\n")
|
||||
server.join()
|
||||
if support.verbose:
|
||||
sys.stdout.write(" cleanup: successfully joined.\n")
|
||||
|
||||
def test_recv_send(self):
|
||||
"""Test recv(), send() and friends."""
|
||||
|
@ -1592,19 +1570,14 @@ else:
|
|||
cacerts=CERTFILE,
|
||||
chatty=True,
|
||||
connectionchatty=False)
|
||||
flag = threading.Event()
|
||||
server.start(flag)
|
||||
# wait for it to start
|
||||
flag.wait()
|
||||
# try to connect
|
||||
s = ssl.wrap_socket(socket.socket(),
|
||||
server_side=False,
|
||||
certfile=CERTFILE,
|
||||
ca_certs=CERTFILE,
|
||||
cert_reqs=ssl.CERT_NONE,
|
||||
ssl_version=ssl.PROTOCOL_TLSv1)
|
||||
s.connect((HOST, server.port))
|
||||
try:
|
||||
with server:
|
||||
s = ssl.wrap_socket(socket.socket(),
|
||||
server_side=False,
|
||||
certfile=CERTFILE,
|
||||
ca_certs=CERTFILE,
|
||||
cert_reqs=ssl.CERT_NONE,
|
||||
ssl_version=ssl.PROTOCOL_TLSv1)
|
||||
s.connect((HOST, server.port))
|
||||
# helper methods for standardising recv* method signatures
|
||||
def _recv_into():
|
||||
b = bytearray(b"\0"*100)
|
||||
|
@ -1700,9 +1673,6 @@ else:
|
|||
|
||||
s.write(b"over\n")
|
||||
s.close()
|
||||
finally:
|
||||
server.stop()
|
||||
server.join()
|
||||
|
||||
def test_handshake_timeout(self):
|
||||
# Issue #5103: SSL handshake must respect the socket timeout
|
||||
|
@ -1766,19 +1736,14 @@ else:
|
|||
cacerts=CERTFILE,
|
||||
chatty=True,
|
||||
connectionchatty=False)
|
||||
flag = threading.Event()
|
||||
server.start(flag)
|
||||
# wait for it to start
|
||||
flag.wait()
|
||||
# try to connect
|
||||
s = ssl.wrap_socket(socket.socket(),
|
||||
server_side=False,
|
||||
certfile=CERTFILE,
|
||||
ca_certs=CERTFILE,
|
||||
cert_reqs=ssl.CERT_NONE,
|
||||
ssl_version=ssl.PROTOCOL_TLSv1)
|
||||
s.connect((HOST, server.port))
|
||||
try:
|
||||
with server:
|
||||
s = ssl.wrap_socket(socket.socket(),
|
||||
server_side=False,
|
||||
certfile=CERTFILE,
|
||||
ca_certs=CERTFILE,
|
||||
cert_reqs=ssl.CERT_NONE,
|
||||
ssl_version=ssl.PROTOCOL_TLSv1)
|
||||
s.connect((HOST, server.port))
|
||||
# get the data
|
||||
cb_data = s.get_channel_binding("tls-unique")
|
||||
if support.verbose:
|
||||
|
@ -1817,9 +1782,6 @@ else:
|
|||
self.assertEqual(peer_data_repr,
|
||||
repr(new_cb_data).encode("us-ascii"))
|
||||
s.close()
|
||||
finally:
|
||||
server.stop()
|
||||
server.join()
|
||||
|
||||
def test_compression(self):
|
||||
context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
|
||||
|
|
|
@ -299,6 +299,18 @@ class Galeon(UnixBrowser):
|
|||
background = True
|
||||
|
||||
|
||||
class Chrome(UnixBrowser):
|
||||
"Launcher class for Google Chrome browser."
|
||||
|
||||
remote_args = ['%action', '%s']
|
||||
remote_action = ""
|
||||
remote_action_newwin = "--new-window"
|
||||
remote_action_newtab = ""
|
||||
background = True
|
||||
|
||||
Chromium = Chrome
|
||||
|
||||
|
||||
class Opera(UnixBrowser):
|
||||
"Launcher class for Opera browser."
|
||||
|
||||
|
@ -466,6 +478,11 @@ def register_X_browsers():
|
|||
if _iscommand("skipstone"):
|
||||
register("skipstone", None, BackgroundBrowser("skipstone"))
|
||||
|
||||
# Google Chrome/Chromium browsers
|
||||
for browser in ("google-chrome", "chrome", "chromium", "chromium-browser"):
|
||||
if _iscommand(browser):
|
||||
register(browser, None, Chrome(browser))
|
||||
|
||||
# Opera, quite popular
|
||||
if _iscommand("opera"):
|
||||
register("opera", None, Opera("opera"))
|
||||
|
|
|
@ -878,6 +878,7 @@ Michael Scharf
|
|||
Andreas Schawo
|
||||
Neil Schemenauer
|
||||
David Scherer
|
||||
Hynek Schlawack
|
||||
Bob Schmertz
|
||||
Gregor Schmid
|
||||
Ralf Schmitt
|
||||
|
|
|
@ -419,6 +419,14 @@ Core and Builtins
|
|||
Library
|
||||
-------
|
||||
|
||||
- Issue #13620: Support for Chrome browser in webbrowser.py Patch contributed
|
||||
by Arnaud Calmettes.
|
||||
|
||||
- Issue #12708: Add starmap() and starmap_async() methods (similar to
|
||||
itertools.starmap()) to multiprocessing.Pool. Patch by Hynek Schlawack.
|
||||
|
||||
- Issue #1785: Fix inspect and pydoc with misbehaving descriptors.
|
||||
|
||||
- Issue #13637: "a2b" functions in the binascii module now accept ASCII-only
|
||||
unicode strings.
|
||||
|
||||
|
|
|
@ -2006,6 +2006,7 @@ set_default_verify_paths(PySSLContext *self, PyObject *unused)
|
|||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_ECDH
|
||||
static PyObject *
|
||||
set_ecdh_curve(PySSLContext *self, PyObject *name)
|
||||
{
|
||||
|
@ -2032,6 +2033,7 @@ set_ecdh_curve(PySSLContext *self, PyObject *name)
|
|||
EC_KEY_free(key);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static PyGetSetDef context_getsetlist[] = {
|
||||
{"options", (getter) get_options,
|
||||
|
@ -2054,8 +2056,10 @@ static struct PyMethodDef context_methods[] = {
|
|||
METH_NOARGS, NULL},
|
||||
{"set_default_verify_paths", (PyCFunction) set_default_verify_paths,
|
||||
METH_NOARGS, NULL},
|
||||
#ifndef OPENSSL_NO_ECDH
|
||||
{"set_ecdh_curve", (PyCFunction) set_ecdh_curve,
|
||||
METH_O, NULL},
|
||||
#endif
|
||||
{NULL, NULL} /* sentinel */
|
||||
};
|
||||
|
||||
|
@ -2523,6 +2527,14 @@ PyInit__ssl(void)
|
|||
Py_INCREF(r);
|
||||
PyModule_AddObject(m, "HAS_TLS_UNIQUE", r);
|
||||
|
||||
#ifdef OPENSSL_NO_ECDH
|
||||
r = Py_False;
|
||||
#else
|
||||
r = Py_True;
|
||||
#endif
|
||||
Py_INCREF(r);
|
||||
PyModule_AddObject(m, "HAS_ECDH", r);
|
||||
|
||||
/* OpenSSL version */
|
||||
/* SSLeay() gives us the version of the library linked against,
|
||||
which could be different from the headers version.
|
||||
|
|
Loading…
Reference in New Issue