If you want to help the Documentation Team, you are always welcome. Just send
a mail to docs@python.org.
-
-
-Copyright notice
-================
-
-The Python source is copyrighted, but you can freely use and copy it
-as long as you don't change or remove the copyright notice:
-
-----------------------------------------------------------------------
-Copyright (c) 2000-2015 Python Software Foundation.
-All rights reserved.
-
-Copyright (c) 2000 BeOpen.com.
-All rights reserved.
-
-Copyright (c) 1995-2000 Corporation for National Research Initiatives.
-All rights reserved.
-
-Copyright (c) 1991-1995 Stichting Mathematisch Centrum.
-All rights reserved.
-
-See the file "license.rst" for information on usage and redistribution
-of this file, and for a DISCLAIMER OF ALL WARRANTIES.
-----------------------------------------------------------------------
.. _reporting-bugs:
-**************
-Reporting Bugs
-**************
+*****************
+Dealing with Bugs
+*****************
Python is a mature programming language which has established a reputation for
stability. In order to maintain this reputation, the developers would like to
know of any deficiencies you find in Python.
+It can be sometimes faster to fix bugs yourself and contribute patches to
+Python as it streamlines the process and involves less people. Learn how to
+:ref:`contribute <contributing-to-python>`.
Documentation bugs
==================
please submit a bug report on the :ref:`tracker <using-the-tracker>`. If you
have a suggestion how to fix it, include that as well.
-If you're short on time, you can also email your bug report to docs@python.org.
+If you're short on time, you can also email documentation bug reports to
+docs@python.org (behavioral bugs can be sent to python-list@python.org).
'docs@' is a mailing list run by volunteers; your request will be noticed,
though it may take a while to be processed.
Information about writing a good bug report. Some of this is specific to the
Mozilla project, but describes general good practices.
+.. _contributing-to-python:
Getting started contributing to Python yourself
===============================================
Strings and buffers
-------------------
-These formats allow to access an object as a contiguous chunk of memory.
+These formats allow accessing an object as a contiguous chunk of memory.
You don't have to provide raw storage for the returned unicode or bytes
area. Also, you won't have to release any memory yourself, except with the
``es``, ``es#``, ``et`` and ``et#`` formats.
:c:func:`PyArg_ParseTuple` will use this location as the buffer and interpret the
initial value of *\*buffer_length* as the buffer size. It will then copy the
encoded data into the buffer and NUL-terminate it. If the buffer is not large
- enough, a :exc:`ValueError` will be set.
+ enough, a :exc:`TypeError` will be set.
+ Note: starting from Python 3.6 a :exc:`ValueError` will be set.
In both cases, *\*buffer_length* is set to the length of the encoded data
without the trailing NUL byte.
``Py_CLEANUP_SUPPORTED`` was added.
``p`` (:class:`bool`) [int]
- Tests the value passed in for truth (a boolean **p**\redicate) and converts
+ Tests the value passed in for truth (a boolean **p**\ redicate) and converts
the result to its equivalent C true/false integer value.
Sets the int to 1 if the expression was true and 0 if it was false.
This accepts any valid Python value. See :ref:`truth` for more
.. _codeobjects:
+.. index:: object; code, code object
+
Code Objects
------------
.. sectionauthor:: Jeffrey Yasskin <jyasskin@gmail.com>
-
-.. index::
- object: code
-
Code objects are a low-level detail of the CPython implementation.
Each one represents a chunk of executable code that hasn't yet been
bound into a function.
:meth:`__del__` method.
The function is called with a single argument *obj* that identifies the context
- in which the unraisable exception occurred. The repr of *obj* will be printed in
- the warning message.
+ in which the unraisable exception occurred. If possible,
+ the repr of *obj* will be printed in the warning message.
Raising exceptions
.. c:function:: int PyErr_WarnEx(PyObject *category, const char *message, Py_ssize_t stack_level)
Issue a warning message. The *category* argument is a warning category (see
- below) or *NULL*; the *message* argument is an UTF-8 encoded string. *stack_level* is a
+ below) or *NULL*; the *message* argument is a UTF-8 encoded string. *stack_level* is a
positive number giving a number of stack frames; the warning will be issued from
the currently executing line of code in that stack frame. A *stack_level* of 1
is the function calling :c:func:`PyErr_WarnEx`, 2 is the function above that,
.. c:function:: PyObject* PyUnicodeTranslateError_Create(const Py_UNICODE *object, Py_ssize_t length, Py_ssize_t start, Py_ssize_t end, const char *reason)
Create a :class:`UnicodeTranslateError` object with the attributes *object*,
- *length*, *start*, *end* and *reason*. *reason* is an UTF-8 encoded string.
+ *length*, *start*, *end* and *reason*. *reason* is a UTF-8 encoded string.
.. c:function:: PyObject* PyUnicodeDecodeError_GetEncoding(PyObject *exc)
PyObject* PyUnicodeEncodeError_GetEncoding(PyObject *exc)
Return a new function object associated with the code object *code*. *globals*
must be a dictionary with the global variables accessible to the function.
- The function's docstring, name and *__module__* are retrieved from the code
- object, the argument defaults and closure are set to *NULL*.
+ The function's docstring and name are retrieved from the code object. *__module__*
+ is retrieved from *globals*. The argument defaults, annotations and closure are
+ set to *NULL*. *__qualname__* is set to the same value as the function's name.
.. c:function:: PyObject* PyFunction_NewWithQualName(PyObject *code, PyObject *globals, PyObject *qualname)
- As :c:func:`PyFunction_New`, but also allows to set the function object's
+ As :c:func:`PyFunction_New`, but also allows setting the function object's
``__qualname__`` attribute. *qualname* should be a unicode object or NULL;
if NULL, the ``__qualname__`` attribute is set to the same value as its
``__name__`` attribute.
.. c:function:: void Py_VISIT(PyObject *o)
- Call the *visit* callback, with arguments *o* and *arg*. If *visit* returns
- a non-zero value, then return it. Using this macro, :c:member:`~PyTypeObject.tp_traverse`
- handlers look like::
+ If *o* is not *NULL*, call the *visit* callback, with arguments *o*
+ and *arg*. If *visit* returns a non-zero value, then return it.
+ Using this macro, :c:member:`~PyTypeObject.tp_traverse` handlers
+ look like::
static int
my_traverse(Noddy *self, visitproc visit, void *arg)
.. c:function:: PyObject* PyImport_ImportModuleLevel(const char *name, PyObject *globals, PyObject *locals, PyObject *fromlist, int level)
- Similar to :c:func:`PyImport_ImportModuleLevelObject`, but the name is an
+ Similar to :c:func:`PyImport_ImportModuleLevelObject`, but the name is a
UTF-8 encoded string instead of a Unicode object.
.. versionchanged:: 3.3
For internal use only.
-.. c:function:: PyObject* _PyImport_FixupExtension(char *, char *)
-
- For internal use only.
-
-
.. c:function:: int PyImport_ImportFrozenModuleObject(PyObject *name)
Load a frozen module named *name*. Return ``1`` for success, ``0`` if the
};
-.. c:var:: struct _frozen* PyImport_FrozenModules
+.. c:var:: const struct _frozen* PyImport_FrozenModules
This pointer is initialized to point to an array of :c:type:`struct _frozen`
records, terminated by one whose members are all *NULL* or zero. When a frozen
It is recommended that applications embedding the Python interpreter
for purposes other than executing a single script pass 0 as *updatepath*,
and update :data:`sys.path` themselves if desired.
- See `CVE-2008-5983 <http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2008-5983>`_.
+ See `CVE-2008-5983 <https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2008-5983>`_.
On versions before 3.1.3, you can achieve the same effect by manually
popping the first :data:`sys.path` element after having called
.. c:function:: PyObject* PyMapping_Keys(PyObject *o)
- On success, return a list of the keys in object *o*. On failure, return *NULL*.
- This is equivalent to the Python expression ``list(o.keys())``.
+ On success, return a list, a tuple or a dictionary view in case of a dict,
+ of the keys in object *o*. On failure, return *NULL*.
.. c:function:: PyObject* PyMapping_Values(PyObject *o)
- On success, return a list of the values in object *o*. On failure, return
- *NULL*. This is equivalent to the Python expression ``list(o.values())``.
+ On success, return a list, a tuple or a dictionary view in case of a dict, of
+ the values in object *o*. On failure, return *NULL*.
.. c:function:: PyObject* PyMapping_Items(PyObject *o)
- On success, return a list of the items in object *o*, where each item is a tuple
- containing a key-value pair. On failure, return *NULL*. This is equivalent to
- the Python expression ``list(o.items())``.
+ On success, return a list, a tuple or a dictionary view in case of a dict, of
+ the items in object *o*, where each item is a tuple containing a key-value
+ pair. On failure, return *NULL*.
.. c:function:: PyObject* PyMapping_GetItemString(PyObject *o, const char *key)
the C library allocator as shown in the previous example, the allocated memory
for the I/O buffer escapes completely the Python memory manager.
+.. seealso::
+
+ The :envvar:`PYTHONMALLOCSTATS` environment variable can be used to print
+ memory allocation statistics every time a new object arena is created, and
+ on shutdown.
+
Raw Memory Interface
====================
.. c:function:: void* PyMem_RawMalloc(size_t n)
Allocates *n* bytes and returns a pointer of type :c:type:`void\*` to the
- allocated memory, or *NULL* if the request fails. Requesting zero bytes
- returns a distinct non-*NULL* pointer if possible, as if
- ``PyMem_RawMalloc(1)`` had been called instead. The memory will not have
+ allocated memory, or *NULL* if the request fails.
+
+ Requesting zero bytes returns a distinct non-*NULL* pointer if possible, as
+ if ``PyMem_RawMalloc(1)`` had been called instead. The memory will not have
been initialized in any way.
Allocates *nelem* elements each whose size in bytes is *elsize* and returns
a pointer of type :c:type:`void\*` to the allocated memory, or *NULL* if the
- request fails. The memory is initialized to zeros. Requesting zero elements
- or elements of size zero bytes returns a distinct non-*NULL* pointer if
- possible, as if ``PyMem_RawCalloc(1, 1)`` had been called instead.
+ request fails. The memory is initialized to zeros.
+
+ Requesting zero elements or elements of size zero bytes returns a distinct
+ non-*NULL* pointer if possible, as if ``PyMem_RawCalloc(1, 1)`` had been
+ called instead.
.. versionadded:: 3.5
.. c:function:: void* PyMem_RawRealloc(void *p, size_t n)
Resizes the memory block pointed to by *p* to *n* bytes. The contents will
- be unchanged to the minimum of the old and the new sizes. If *p* is *NULL*,
- the call is equivalent to ``PyMem_RawMalloc(n)``; else if *n* is equal to
- zero, the memory block is resized but is not freed, and the returned pointer
- is non-*NULL*. Unless *p* is *NULL*, it must have been returned by a
- previous call to :c:func:`PyMem_RawMalloc` or :c:func:`PyMem_RawRealloc`. If
- the request fails, :c:func:`PyMem_RawRealloc` returns *NULL* and *p* remains
- a valid pointer to the previous memory area.
+ be unchanged to the minimum of the old and the new sizes.
+
+ If *p* is *NULL*, the call is equivalent to ``PyMem_RawMalloc(n)``; else if
+ *n* is equal to zero, the memory block is resized but is not freed, and the
+ returned pointer is non-*NULL*.
+
+ Unless *p* is *NULL*, it must have been returned by a previous call to
+ :c:func:`PyMem_RawMalloc`, :c:func:`PyMem_RawRealloc` or
+ :c:func:`PyMem_RawCalloc`.
+
+ If the request fails, :c:func:`PyMem_RawRealloc` returns *NULL* and *p*
+ remains a valid pointer to the previous memory area.
.. c:function:: void PyMem_RawFree(void *p)
Frees the memory block pointed to by *p*, which must have been returned by a
- previous call to :c:func:`PyMem_RawMalloc` or :c:func:`PyMem_RawRealloc`.
- Otherwise, or if ``PyMem_Free(p)`` has been called before, undefined
- behavior occurs. If *p* is *NULL*, no operation is performed.
+ previous call to :c:func:`PyMem_RawMalloc`, :c:func:`PyMem_RawRealloc` or
+ :c:func:`PyMem_RawCalloc`. Otherwise, or if ``PyMem_Free(p)`` has been
+ called before, undefined behavior occurs.
+
+ If *p* is *NULL*, no operation is performed.
.. _memoryinterface:
.. c:function:: void* PyMem_Malloc(size_t n)
Allocates *n* bytes and returns a pointer of type :c:type:`void\*` to the
- allocated memory, or *NULL* if the request fails. Requesting zero bytes returns
- a distinct non-*NULL* pointer if possible, as if ``PyMem_Malloc(1)`` had
- been called instead. The memory will not have been initialized in any way.
+ allocated memory, or *NULL* if the request fails.
+
+ Requesting zero bytes returns a distinct non-*NULL* pointer if possible, as
+ if ``PyMem_Malloc(1)`` had been called instead. The memory will not have
+ been initialized in any way.
.. c:function:: void* PyMem_Calloc(size_t nelem, size_t elsize)
Allocates *nelem* elements each whose size in bytes is *elsize* and returns
a pointer of type :c:type:`void\*` to the allocated memory, or *NULL* if the
- request fails. The memory is initialized to zeros. Requesting zero elements
- or elements of size zero bytes returns a distinct non-*NULL* pointer if
- possible, as if ``PyMem_Calloc(1, 1)`` had been called instead.
+ request fails. The memory is initialized to zeros.
+
+ Requesting zero elements or elements of size zero bytes returns a distinct
+ non-*NULL* pointer if possible, as if ``PyMem_Calloc(1, 1)`` had been called
+ instead.
.. versionadded:: 3.5
.. c:function:: void* PyMem_Realloc(void *p, size_t n)
Resizes the memory block pointed to by *p* to *n* bytes. The contents will be
- unchanged to the minimum of the old and the new sizes. If *p* is *NULL*, the
- call is equivalent to ``PyMem_Malloc(n)``; else if *n* is equal to zero,
- the memory block is resized but is not freed, and the returned pointer is
- non-*NULL*. Unless *p* is *NULL*, it must have been returned by a previous call
- to :c:func:`PyMem_Malloc` or :c:func:`PyMem_Realloc`. If the request fails,
- :c:func:`PyMem_Realloc` returns *NULL* and *p* remains a valid pointer to the
- previous memory area.
+ unchanged to the minimum of the old and the new sizes.
+
+ If *p* is *NULL*, the call is equivalent to ``PyMem_Malloc(n)``; else if *n*
+ is equal to zero, the memory block is resized but is not freed, and the
+ returned pointer is non-*NULL*.
+
+ Unless *p* is *NULL*, it must have been returned by a previous call to
+ :c:func:`PyMem_Malloc`, :c:func:`PyMem_Realloc` or :c:func:`PyMem_Calloc`.
+
+ If the request fails, :c:func:`PyMem_Realloc` returns *NULL* and *p* remains
+ a valid pointer to the previous memory area.
.. c:function:: void PyMem_Free(void *p)
Frees the memory block pointed to by *p*, which must have been returned by a
- previous call to :c:func:`PyMem_Malloc` or :c:func:`PyMem_Realloc`. Otherwise, or
- if ``PyMem_Free(p)`` has been called before, undefined behavior occurs. If
- *p* is *NULL*, no operation is performed.
+ previous call to :c:func:`PyMem_Malloc`, :c:func:`PyMem_Realloc` or
+ :c:func:`PyMem_Calloc`. Otherwise, or if ``PyMem_Free(p)`` has been called
+ before, undefined behavior occurs.
+
+ If *p* is *NULL*, no operation is performed.
The following type-oriented macros are provided for convenience. Note that
*TYPE* refers to any C type.
Same as :c:func:`PyMem_Realloc`, but the memory block is resized to ``(n *
sizeof(TYPE))`` bytes. Returns a pointer cast to :c:type:`TYPE\*`. On return,
*p* will be a pointer to the new memory area, or *NULL* in the event of
- failure. This is a C preprocessor macro; p is always reassigned. Save
- the original value of p to avoid losing memory when handling errors.
+ failure.
+
+ This is a C preprocessor macro; *p* is always reassigned. Save the original
+ value of *p* to avoid losing memory when handling errors.
.. c:function:: void PyMem_Del(void *p)
note that their use does not preserve binary compatibility across Python
versions and is therefore deprecated in extension modules.
-:c:func:`PyMem_MALLOC`, :c:func:`PyMem_REALLOC`, :c:func:`PyMem_FREE`.
-
-:c:func:`PyMem_NEW`, :c:func:`PyMem_RESIZE`, :c:func:`PyMem_DEL`.
+* ``PyMem_MALLOC(size)``
+* ``PyMem_NEW(type, size)``
+* ``PyMem_REALLOC(ptr, size)``
+* ``PyMem_RESIZE(ptr, type, size)``
+* ``PyMem_FREE(ptr)``
+* ``PyMem_DEL(ptr)``
Customize Memory Allocators
Enum used to identify an allocator domain. Domains:
* :c:data:`PYMEM_DOMAIN_RAW`: functions :c:func:`PyMem_RawMalloc`,
- :c:func:`PyMem_RawRealloc` and :c:func:`PyMem_RawFree`
+ :c:func:`PyMem_RawRealloc`, :c:func:`PyMem_RawCalloc` and
+ :c:func:`PyMem_RawFree`
* :c:data:`PYMEM_DOMAIN_MEM`: functions :c:func:`PyMem_Malloc`,
- :c:func:`PyMem_Realloc` and :c:func:`PyMem_Free`
+ :c:func:`PyMem_Realloc`, :c:func:`PyMem_Calloc` and :c:func:`PyMem_Free`
* :c:data:`PYMEM_DOMAIN_OBJ`: functions :c:func:`PyObject_Malloc`,
- :c:func:`PyObject_Realloc` and :c:func:`PyObject_Free`
+ :c:func:`PyObject_Realloc`, :c:func:`PyObject_Calloc` and
+ :c:func:`PyObject_Free`
.. c:function:: void PyMem_GetAllocator(PyMemAllocatorDomain domain, PyMemAllocatorEx *allocator)
functions:
- :c:func:`PyMem_RawMalloc`, :c:func:`PyMem_RawRealloc`,
- :c:func:`PyMem_RawFree`
- - :c:func:`PyMem_Malloc`, :c:func:`PyMem_Realloc`, :c:func:`PyMem_Free`
+ :c:func:`PyMem_RawCalloc`, :c:func:`PyMem_RawFree`
+ - :c:func:`PyMem_Malloc`, :c:func:`PyMem_Realloc`, :c:func:`PyMem_Calloc`,
+ :c:func:`PyMem_Free`
- :c:func:`PyObject_Malloc`, :c:func:`PyObject_Realloc`,
- :c:func:`PyObject_Free`
+ :c:func:`PyObject_Calloc`, :c:func:`PyObject_Free`
Newly allocated memory is filled with the byte ``0xCB``, freed memory is
filled with the byte ``0xDB``. Additional checks:
.. index:: object: method
Methods are bound function objects. Methods are always bound to an instance of
-an user-defined class. Unbound methods (methods bound to a class object) are
+a user-defined class. Unbound methods (methods bound to a class object) are
no longer available.
.. c:function:: PyObject* PyModule_New(const char *name)
- Similar to :c:func:`PyImport_NewObject`, but the name is an UTF-8 encoded
+ Similar to :c:func:`PyImport_NewObject`, but the name is a UTF-8 encoded
string instead of a Unicode object.
(where the initialization function is added using :c:func:`PyImport_AppendInittab`).
See :ref:`building` or :ref:`extending-with-embedding` for details.
-The initialization function can either pass pass a module definition instance
+The initialization function can either pass a module definition instance
to :c:func:`PyModule_Create`, and return the resulting module object,
or request "multi-phase initialization" by returning the definition struct itself.
.. c:function:: int PyObject_SetAttr(PyObject *o, PyObject *attr_name, PyObject *v)
Set the value of the attribute named *attr_name*, for object *o*, to the value
- *v*. Returns ``-1`` on failure. This is the equivalent of the Python statement
+ *v*. Raise an exception and return ``-1`` on failure;
+ return ``0`` on success. This is the equivalent of the Python statement
``o.attr_name = v``.
+ If *v* is *NULL*, the attribute is deleted, however this feature is
+ deprecated in favour of using :c:func:`PyObject_DelAttr`.
+
.. c:function:: int PyObject_SetAttrString(PyObject *o, const char *attr_name, PyObject *v)
Set the value of the attribute named *attr_name*, for object *o*, to the value
- *v*. Returns ``-1`` on failure. This is the equivalent of the Python statement
+ *v*. Raise an exception and return ``-1`` on failure;
+ return ``0`` on success. This is the equivalent of the Python statement
``o.attr_name = v``.
+ If *v* is *NULL*, the attribute is deleted, however this feature is
+ deprecated in favour of using :c:func:`PyObject_DelAttrString`.
+
.. c:function:: int PyObject_GenericSetAttr(PyObject *o, PyObject *name, PyObject *value)
- Generic attribute setter function that is meant to be put into a type
- object's ``tp_setattro`` slot. It looks for a data descriptor in the
+ Generic attribute setter and deleter function that is meant
+ to be put into a type object's :c:member:`~PyTypeObject.tp_setattro`
+ slot. It looks for a data descriptor in the
dictionary of classes in the object's MRO, and if found it takes preference
- over setting the attribute in the instance dictionary. Otherwise, the
- attribute is set in the object's :attr:`~object.__dict__` (if present).
- Otherwise, an :exc:`AttributeError` is raised and ``-1`` is returned.
+ over setting or deleting the attribute in the instance dictionary. Otherwise, the
+ attribute is set or deleted in the object's :attr:`~object.__dict__` (if present).
+ On success, ``0`` is returned, otherwise an :exc:`AttributeError`
+ is raised and ``-1`` is returned.
.. c:function:: int PyObject_DelAttr(PyObject *o, PyObject *attr_name)
.. c:function:: int PyObject_SetItem(PyObject *o, PyObject *key, PyObject *v)
- Map the object *key* to the value *v*. Returns ``-1`` on failure. This is the
+ Map the object *key* to the value *v*. Raise an exception and
+ return ``-1`` on failure; return ``0`` on success. This is the
equivalent of the Python statement ``o[key] = v``.
.. c:function:: int PySequence_SetItem(PyObject *o, Py_ssize_t i, PyObject *v)
- Assign object *v* to the *i*\ th element of *o*. Returns ``-1`` on failure. This
+ Assign object *v* to the *i*\ th element of *o*. Raise an exception
+ and return ``-1`` on failure; return ``0`` on success. This
is the equivalent of the Python statement ``o[i] = v``. This function *does
not* steal a reference to *v*.
+ If *v* is *NULL*, the element is deleted, however this feature is
+ deprecated in favour of using :c:func:`PySequence_DelItem`.
+
.. c:function:: int PySequence_DelItem(PyObject *o, Py_ssize_t i)
of brand new frozensets before they are exposed to other code). Return 0 on
success or -1 on failure. Raise a :exc:`TypeError` if the *key* is
unhashable. Raise a :exc:`MemoryError` if there is no room to grow. Raise a
- :exc:`SystemError` if *set* is an not an instance of :class:`set` or its
+ :exc:`SystemError` if *set* is not an instance of :class:`set` or its
subtype.
error is encountered. Does not raise :exc:`KeyError` for missing keys. Raise a
:exc:`TypeError` if the *key* is unhashable. Unlike the Python :meth:`~set.discard`
method, this function does not automatically convert unhashable sets into
- temporary frozensets. Raise :exc:`PyExc_SystemError` if *set* is an not an
+ temporary frozensets. Raise :exc:`PyExc_SystemError` if *set* is not an
instance of :class:`set` or its subtype.
Return a new reference to an arbitrary object in the *set*, and removes the
object from the *set*. Return *NULL* on failure. Raise :exc:`KeyError` if the
- set is empty. Raise a :exc:`SystemError` if *set* is an not an instance of
+ set is empty. Raise a :exc:`SystemError` if *set* is not an instance of
:class:`set` or its subtype.
missing symbols) on the older releases.
As of Python 3.2, the set of functions available to the limited API is
-documented in PEP 384. In the C API documentation, API elements that are not
+documented in :pep:`384`. In the C API documentation, API elements that are not
part of the limited API are marked as "Not part of the limited API."
.. c:member:: setattrfunc PyTypeObject.tp_setattr
- An optional pointer to the set-attribute-string function.
+ An optional pointer to the function for setting and deleting attributes.
This field is deprecated. When it is defined, it should point to a function
that acts the same as the :c:member:`~PyTypeObject.tp_setattro` function, but taking a C string
instead of a Python string object to give the attribute name. The signature is
- the same as for :c:func:`PyObject_SetAttrString`.
+ the same as for :c:func:`PyObject_SetAttrString`, but setting
+ *v* to *NULL* to delete an attribute must be supported.
This field is inherited by subtypes together with :c:member:`~PyTypeObject.tp_setattro`: a subtype
inherits both :c:member:`~PyTypeObject.tp_setattr` and :c:member:`~PyTypeObject.tp_setattro` from its base type when
.. c:member:: setattrofunc PyTypeObject.tp_setattro
- An optional pointer to the set-attribute function.
+ An optional pointer to the function for setting and deleting attributes.
- The signature is the same as for :c:func:`PyObject_SetAttr`. It is usually
+ The signature is the same as for :c:func:`PyObject_SetAttr`, but setting
+ *v* to *NULL* to delete an attribute must be supported. It is usually
convenient to set this field to :c:func:`PyObject_GenericSetAttr`, which
implements the normal way of setting object attributes.
typedef struct PyGetSetDef {
char *name; /* attribute name */
getter get; /* C function to get the attribute */
- setter set; /* C function to set the attribute */
+ setter set; /* C function to set or delete the attribute */
char *doc; /* optional doc string */
void *closure; /* optional additional data for getter and setter */
} PyGetSetDef;
.. c:member:: descrsetfunc PyTypeObject.tp_descr_set
- An optional pointer to a "descriptor set" function.
+ An optional pointer to a function for setting and deleting
+ a descriptor's value.
The function signature is ::
int tp_descr_set(PyObject *self, PyObject *obj, PyObject *value);
+ The *value* argument is set to *NULL* to delete the value.
This field is inherited by subtypes.
.. XXX explain.
.. c:member:: objobjargproc PyMappingMethods.mp_ass_subscript
- This function is used by :c:func:`PyObject_SetItem` and has the same
- signature. If this slot is *NULL*, the object does not support item
- assignment.
+ This function is used by :c:func:`PyObject_SetItem` and
+ :c:func:`PyObject_DelItem`. It has the same signature as
+ :c:func:`PyObject_SetItem`, but *v* can also be set to *NULL* to delete
+ an item. If this slot is *NULL*, the object does not support item
+ assignment and deletion.
.. _sequence-structs:
This function is used by :c:func:`PySequence_SetItem` and has the same
signature. This slot may be left to *NULL* if the object does not support
- item assignment.
+ item assignment and deletion.
.. c:member:: objobjproc PySequenceMethods.sq_contains
.. c:macro:: Py_UNICODE_IS_HIGH_SURROGATE(ch)
- Check if *ch* is an high surrogate (``0xD800 <= ch <= 0xDBFF``).
+ Check if *ch* is a high surrogate (``0xD800 <= ch <= 0xDBFF``).
.. c:macro:: Py_UNICODE_IS_LOW_SURROGATE(ch)
.. c:function:: PyObject *PyUnicode_FromString(const char *u)
- Create a Unicode object from an UTF-8 encoded null-terminated char buffer
+ Create a Unicode object from a UTF-8 encoded null-terminated char buffer
*u*.
| :attr:`%%` | *n/a* | The literal % character. |
+-------------------+---------------------+--------------------------------+
| :attr:`%c` | int | A single character, |
- | | | represented as an C int. |
+ | | | represented as a C int. |
+-------------------+---------------------+--------------------------------+
| :attr:`%d` | int | Exactly equivalent to |
| | | ``printf("%d")``. |
.. c:function:: PyObject* PyUnicode_FromEncodedObject(PyObject *obj, \
const char *encoding, const char *errors)
- Coerce an encoded object *obj* to an Unicode object and return a reference with
- incremented refcount.
+ Decode an encoded object *obj* to a Unicode object.
:class:`bytes`, :class:`bytearray` and other
:term:`bytes-like objects <bytes-like object>`
are decoded according to the given *encoding* and using the error handling
defined by *errors*. Both can be *NULL* to have the interface use the default
- values (see the next section for details).
+ values (see :ref:`builtincodecs` for details).
All other objects, including Unicode objects, cause a :exc:`TypeError` to be
set.
This function checks that *unicode* is a Unicode object, that the index is
not out of bounds, and that the object can be modified safely (i.e. that it
- its reference count is one), in contrast to the macro version
- :c:func:`PyUnicode_WRITE_CHAR`.
+ its reference count is one).
.. versionadded:: 3.3
.. c:function:: PyObject* PyUnicode_FromObject(PyObject *obj)
- Shortcut for ``PyUnicode_FromEncodedObject(obj, NULL, "strict")`` which is used
- throughout the interpreter whenever coercion to Unicode is needed.
+ Copy an instance of a Unicode subtype to a new true Unicode object if
+ necessary. If *obj* is already a true Unicode object (not a subtype),
+ return the reference with incremented refcount.
+
+ Objects other than Unicode or its subtypes will cause a :exc:`TypeError`.
Locale Encoding
If *Py_UNICODE_WIDE* is defined, a single :c:type:`Py_UNICODE` value may get
represented as a surrogate pair. If it is not defined, each :c:type:`Py_UNICODE`
- values is interpreted as an UCS-2 character.
+ values is interpreted as a UCS-2 character.
Return *NULL* if an exception was raised by the codec.
cells.
+.. c:type:: PyFrameObject
+
+ The C structure of the objects used to describe frame objects. The
+ fields of this type are subject to change at any time.
+
+
.. c:function:: PyObject* PyEval_EvalFrame(PyFrameObject *f)
Evaluate an execution frame. This is a simplified interface to
- PyEval_EvalFrameEx, for backward compatibility.
+ :c:func:`PyEval_EvalFrameEx`, for backward compatibility.
.. c:function:: PyObject* PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
# General substitutions.
project = 'Python'
-copyright = '1990-%s, Python Software Foundation' % time.strftime('%Y')
+copyright = '2001-%s, Python Software Foundation' % time.strftime('%Y')
# We look for the Include/patchlevel.h file in the current Python source tree
# and replace the values accordingly.
# Get LaTeX to handle Unicode correctly
latex_elements = {'inputenc': r'\usepackage[utf8x]{inputenc}', 'utf8extra': ''}
+# Options for Epub output
+# -----------------------
+
+epub_author = 'Python Documentation Authors'
+epub_publisher = 'Python Software Foundation'
# Options for the coverage checker
# --------------------------------
Python and this documentation is:
-Copyright © 2001-2015 Python Software Foundation. All rights reserved.
+Copyright © 2001-2016 Python Software Foundation. All rights reserved.
Copyright © 2000 BeOpen.com. All rights reserved.
repository of open source licensed packages made available for use by
other Python users
* the `Python Packaging Authority
- <https://packaging.python.org/en/latest/future.html>`__ are the group of
+ <https://www.pypa.io/>`__ are the group of
developers and documentation authors responsible for the maintenance and
evolution of the standard packaging tools and the associated metadata and
file format standards. They maintain a variety of tools, documentation
extensions, to be installed on a system without needing to be built
locally.
-.. _setuptools: https://setuptools.pypa.io/en/latest/setuptools.html
-.. _wheel: http://wheel.readthedocs.org
+.. _setuptools: https://setuptools.readthedocs.io/en/latest/
+.. _wheel: https://wheel.readthedocs.org
Open source licensing and collaboration
=======================================
The Python Packaging User Guide includes more details on the `currently
recommended tools`_.
-.. _currently recommended tools: https://packaging.python.org/en/latest/current.html#packaging-tool-recommendations
+.. _currently recommended tools: https://packaging.python.org/en/latest/current/#packaging-tool-recommendations
Reading the guide
=================
* `Uploading the project to the Python Packaging Index`_
.. _Project structure: \
- https://packaging.python.org/en/latest/distributing.html#creating-your-own-project
+ https://packaging.python.org/en/latest/distributing/
.. _Building and packaging the project: \
- https://packaging.python.org/en/latest/distributing.html#packaging-your-project
+ https://packaging.python.org/en/latest/distributing/#packaging-your-project
.. _Uploading the project to the Python Packaging Index: \
- https://packaging.python.org/en/latest/distributing.html#uploading-your-project-to-pypi
+ https://packaging.python.org/en/latest/distributing/#uploading-your-project-to-pypi
How do I...?
.. seealso::
`Python Packaging User Guide: Binary Extensions
- <https://packaging.python.org/en/latest/extensions.html>`__
+ <https://packaging.python.org/en/latest/extensions>`__
.. other topics:
Once the Development & Deployment part of PPUG is fleshed out, some of
those sections should be linked from new questions here (most notably,
we should have a question about avoiding depending on PyPI that links to
- https://packaging.python.org/en/latest/deployment.html#pypi-mirrors-and-caches)
+ https://packaging.python.org/en/latest/mirrors/)
.. function:: gen_preprocess_options(macros, include_dirs)
- Generate C pre-processor options (:option:`-D`, :option:`-U`, :option:`-I`) as
+ Generate C pre-processor options (:option:`-D`, :option:`!-U`, :option:`!-I`) as
used by at least two types of compilers: the typical Unix compiler and Visual
C++. *macros* is the usual thing, a list of 1- or 2-tuples, where ``(name,)``
- means undefine (:option:`-U`) macro *name*, and ``(name, value)`` means define
+ means undefine (:option:`!-U`) macro *name*, and ``(name, value)`` means define
(:option:`-D`) macro *name* to *value*. *include_dirs* is just a list of
- directory names to be added to the header file search path (:option:`-I`).
+ directory names to be added to the header file search path (:option:`!-I`).
Returns a list of command-line options suitable for either Unix compilers or
Visual C++.
* library search directories specified with :option:`-Ldir`
-* compile handled by :program:`cc` (or similar) executable with :option:`-c`
+* compile handled by :program:`cc` (or similar) executable with :option:`!-c`
option: compiles :file:`.c` to :file:`.o`
* link static library handled by :program:`ar` command (possibly with
.. module:: distutils.bcppcompiler
-This module provides :class:`BorlandCCompiler`, an subclass of the abstract
+This module provides :class:`BorlandCCompiler`, a subclass of the abstract
:class:`CCompiler` class for the Borland C++ compiler.
archive. *root_dir* and *base_dir* both default to the current directory.
Returns the name of the archive file.
- .. versionchanged: 3.5
+ .. versionchanged:: 3.5
Added support for the ``xztar`` format.
compression extension (``.gz``, ``.bz2``, ``.xz`` or ``.Z``). Return the
output filename.
- .. versionchanged: 3.5
+ .. versionchanged:: 3.5
Added support for the ``xz`` compression.
<imp.get_tag>` in their name, in a :file:`__pycache__` subdirectory
instead of files without tag in the current directory.
- .. versionchanged: 3.5
+ .. versionchanged:: 3.5
Create ``.pyc`` files according to :pep:`488`.
Builds a `Windows Installer`_ (.msi) binary package.
- .. _Windows Installer: http://msdn.microsoft.com/en-us/library/cc185688(VS.85).aspx
+ .. _Windows Installer: https://msdn.microsoft.com/en-us/library/cc185688(VS.85).aspx
In most cases, the ``bdist_msi`` installer is a better choice than the
``bdist_wininst`` installer, because it provides better support for
that is designed to run with both Python 2.x and 3.x, add::
try:
- from distutils.command.build_py import build_py_2to3 as build_py
+ from distutils.command.build_py import build_py_2to3 as build_py
except ImportError:
- from distutils.command.build_py import build_py
+ from distutils.command.build_py import build_py
to your setup.py, and later::
continuation lines.
You can find out the list of options supported by a particular command with the
-universal :option:`--help` option, e.g. ::
+universal :option:`!--help` option, e.g. ::
> python setup.py --help build_ext
[...]
:Authors: Greg Ward, Anthony Baxter
:Email: distutils-sig@python.org
+.. seealso::
+
+ :ref:`distributing-index`
+ The up to date module distribution documentations
+
This document describes the Python Distribution Utilities ("Distutils") from
the module developer's point of view, describing how to use the Distutils to
make Python modules and extensions easily available to a wider audience with
recommendations section <https://packaging.python.org/en/latest/current/>`__
in the Python Packaging User Guide for more information.
-
.. toctree::
:maxdepth: 2
:numbered:
defining multiple initialization functions. However, importing them requires
using symbolic links or a custom importer, because by default only the
function corresponding to the filename is found.
-See :PEP:`489#multiple-modules-in-one-library` for details.
+See the *"Multiple modules in one library"* section in :pep:`489` for details.
.. highlightlang:: c
function. This takes a variable number of keyword arguments, of which the
example above uses only a subset. Specifically, the example specifies
meta-information to build packages, and it specifies the contents of the
-package. Normally, a package will contain of addition modules, like Python
+package. Normally, a package will contain additional modules, like Python
source modules, documentation, subpackages, etc. Please refer to the distutils
documentation in :ref:`distutils-index` to learn more about the features of
distutils; this section explains building extension modules only.
It is common to pre-compute arguments to :func:`setup`, to better structure the
driver script. In the example above, the ``ext_modules`` argument to
-:func:`setup` is a list of extension modules, each of which is an instance of
+:func:`~distutils.core.setup` is a list of extension modules, each of which is
+an instance of
the :class:`~distutils.extension.Extension`. In the example, the instance
defines an extension named ``demo`` which is build by compiling a single source
file, :file:`demo.c`.
ext_modules = [module1])
-In this example, :func:`setup` is called with additional meta-information, which
+In this example, :func:`~distutils.core.setup` is called with additional
+meta-information, which
is recommended when distribution packages have to be built. For the extension
itself, it specifies preprocessor defines, include directories, library
directories, and libraries. Depending on the compiler, distutils passes this
python setup.py sdist
In some cases, additional files need to be included in a source distribution;
-this is done through a :file:`MANIFEST.in` file; see the distutils documentation
-for details.
+this is done through a :file:`MANIFEST.in` file; see :ref:`manifest` for details.
If the source distribution has been build successfully, maintainers can also
create binary distributions. Depending on the platform, one of the following
avoid writing C extensions and preserve portability to other implementations.
For example, if your use case is calling C library functions or system calls,
you should consider using the :mod:`ctypes` module or the `cffi
- <http://cffi.readthedocs.org>`_ library rather than writing custom C code.
+ <https://cffi.readthedocs.org>`_ library rather than writing custom C code.
These modules let you write Python code to interface with C code and are more
portable between implementations of Python than writing and compiling a C
extension module.
.. seealso::
- `Python Packaging User Guide: Binary Extensions <https://packaging.python.org/en/latest/extensions.html>`_
+ `Python Packaging User Guide: Binary Extensions <https://packaging.python.org/en/latest/extensions/>`_
The Python Packaging User Guide not only covers several available
tools that simplify the creation of binary extensions, but also
discusses the various reasons why creating an extension module may be
line = f.readline()
if not line:
break
- ... # do something with line
+ ... # do something with line
The reason for not allowing assignment in Python expressions is a common,
hard-to-find bug in those other languages, caused by this construct:
line = f.readline()
while line:
- ... # do something with line...
+ ... # do something with line...
line = f.readline()
The problem with this is that if you change your mind about exactly how you get
<file object>` support the iterator protocol, so you can write simply::
for line in f:
- ... # do something with line...
+ ... # do something with line...
Practical answer:
-`Cython <http://cython.org/>`_ and `Pyrex <http://www.cosc.canterbury.ac.nz/greg.ewing/python/Pyrex/>`_
+`Cython <http://cython.org/>`_ and `Pyrex <https://www.cosc.canterbury.ac.nz/greg.ewing/python/Pyrex/>`_
compile a modified version of Python with optional annotations into C
-extensions. `Weave <http://docs.scipy.org/doc/scipy-dev/reference/tutorial/weave.html>`_ makes it easy to
+extensions. `Weave <https://scipy.github.io/devdocs/tutorial/weave.html>`_ makes it easy to
intermingle Python and C code in various ways to increase performance.
`Nuitka <http://www.nuitka.net/>`_ is an up-and-coming compiler of Python
into C++ code, aiming to support the full Python language.
class ListWrapper:
def __init__(self, the_list):
self.the_list = the_list
+
def __eq__(self, other):
return self.the_list == other.the_list
+
def __hash__(self):
l = self.the_list
result = 98767 - len(l)*555
dictionary in sorted order::
for key in sorted(mydict):
- ... # do whatever with mydict[key]...
+ ... # do whatever with mydict[key]...
How do you specify and enforce an interface spec in Python?
class label(Exception): pass # declare a label
try:
- ...
- if condition: raise label() # goto label
- ...
+ ...
+ if condition: raise label() # goto label
+ ...
except label: # where to goto
- pass
+ pass
...
This doesn't allow you to jump into the middle of a loop, but that's usually
.. XXX make sure these all work
`Cython <http://cython.org>`_ and its relative `Pyrex
-<http://www.cosc.canterbury.ac.nz/greg.ewing/python/Pyrex/>`_ are compilers
+<https://www.cosc.canterbury.ac.nz/greg.ewing/python/Pyrex/>`_ are compilers
that accept a slightly modified form of Python and generate the corresponding
C code. Cython and Pyrex make it possible to write an extension without having
to learn Python's C API.
If you need to interface to some C or C++ library for which no Python extension
currently exists, you can try wrapping the library's data types and functions
with a tool such as `SWIG <http://www.swig.org>`_. `SIP
-<http://www.riverbankcomputing.co.uk/software/sip/intro>`__, `CXX
+<https://riverbankcomputing.com/software/sip/intro>`__, `CXX
<http://cxx.sourceforge.net/>`_ `Boost
<http://www.boost.org/libs/python/doc/index.html>`_, or `Weave
-<http://docs.scipy.org/doc/scipy-dev/reference/tutorial/weave.html>`_ are also
+<https://scipy.github.io/devdocs/tutorial/weave.html>`_ are also
alternatives for wrapping C++ libraries.
For Debian, run ``apt-get install python-dev``.
-What does "SystemError: _PyImport_FixupExtension: module yourmodule not loaded" mean?
--------------------------------------------------------------------------------------
-
-This means that you have created an extension module named "yourmodule", but
-your module init function does not initialize with that name.
-
-Every module init function will have a line similar to::
-
- module = Py_InitModule("yourmodule", yourmodule_functions);
-
-If the string passed to this function is not the same name as your extension
-module, the :exc:`SystemError` exception will be raised.
-
-
How do I tell "incomplete input" from "invalid input"?
------------------------------------------------------
2.0cN, and *those* precede 2.0.
You may also find version numbers with a "+" suffix, e.g. "2.2+". These are
-unreleased versions, built directly from the Subversion trunk. In practice,
-after a final minor release is made, the Subversion trunk is incremented to the
-next minor version, which becomes the "a0" version,
-e.g. "2.4a0".
+unreleased versions, built directly from the CPython development repository. In
+practice, after a final minor release is made, the version is incremented to the
+next minor version, which becomes the "a0" version, e.g. "2.4a0".
See also the documentation for :data:`sys.version`, :data:`sys.hexversion`, and
:data:`sys.version_info`.
--------------------------------------------
The latest Python source distribution is always available from python.org, at
-https://www.python.org/download/. The latest development sources can be obtained
+https://www.python.org/downloads/. The latest development sources can be obtained
via anonymous Mercurial access at https://hg.python.org/cpython.
The source distribution is a gzipped tar file containing the complete C source,
How do I get a beta test version of Python?
-------------------------------------------
-Alpha and beta releases are available from https://www.python.org/download/. All
+Alpha and beta releases are available from https://www.python.org/downloads/. All
releases are announced on the comp.lang.python and comp.lang.python.announce
newsgroups and on the Python home page at https://www.python.org/; an RSS feed of
news is available.
The Python project's infrastructure is located all over the world.
`www.python.org <https://www.python.org>`_ is graciously hosted by `Rackspace
-<http://www.rackspace.com>`_, with CDN caching provided by `Fastly
+<https://www.rackspace.com>`_, with CDN caching provided by `Fastly
<https://www.fastly.com>`_. `Upfront Systems
-<http://www.upfrontsystems.co.za>`_ hosts `bugs.python.org
+<http://www.upfrontsystems.co.za/>`_ hosts `bugs.python.org
<https://bugs.python.org>`_. Many other Python services like `the Wiki
<https://wiki.python.org>`_ are hosted by `Oregon State
University Open Source Lab <https://osuosl.org>`_.
When he began implementing Python, Guido van Rossum was also reading the
published scripts from `"Monty Python's Flying Circus"
-<http://en.wikipedia.org/wiki/Monty_Python>`__, a BBC comedy series from the 1970s. Van Rossum
+<https://en.wikipedia.org/wiki/Monty_Python>`__, a BBC comedy series from the 1970s. Van Rossum
thought he needed a name that was short, unique, and slightly mysterious, so he
decided to call the language Python.
releases.
The latest stable releases can always be found on the `Python download page
-<https://www.python.org/download/>`_. There are two recommended production-ready
+<https://www.python.org/downloads/>`_. There are two recommended production-ready
versions at this point in time, because at the moment there are two branches of
stable releases: 2.x and 3.x. Python 3.x may be less useful than 2.x, since
currently there is more third party software available for Python 2 than for
High-profile Python projects include `the Mailman mailing list manager
<http://www.list.org>`_ and `the Zope application server
<http://www.zope.org>`_. Several Linux distributions, most notably `Red Hat
-<http://www.redhat.com>`_, have written part or all of their installer and
+<https://www.redhat.com>`_, have written part or all of their installer and
system administration software in Python. Companies that use Python internally
include Google, Yahoo, and Lucasfilm Ltd.
Standard builds of Python include an object-oriented interface to the Tcl/Tk
widget set, called :ref:`tkinter <Tkinter>`. This is probably the easiest to
install (since it comes included with most
-`binary distributions <https://www.python.org/download/>`_ of Python) and use.
+`binary distributions <https://www.python.org/downloads/>`_ of Python) and use.
For more info about Tk, including pointers to the source, see the
-`Tcl/Tk home page <http://www.tcl.tk>`_. Tcl/Tk is fully portable to the
+`Tcl/Tk home page <https://www.tcl.tk>`_. Tcl/Tk is fully portable to the
Mac OS X, Windows, and Unix platforms.
wxWidgets
---------
-wxWidgets (http://www.wxwidgets.org) is a free, portable GUI class
+wxWidgets (https://www.wxwidgets.org) is a free, portable GUI class
library written in C++ that provides a native look and feel on a
number of platforms, with Windows, Mac OS X, GTK, X11, all listed as
current stable targets. Language bindings are available for a number
---
There are bindings available for the Qt toolkit (using either `PyQt
-<http://www.riverbankcomputing.co.uk/software/pyqt/intro>`_ or `PySide
-<http://www.pyside.org/>`_) and for KDE (`PyKDE <https://techbase.kde.org/Development/Languages/Python>`__).
+<https://riverbankcomputing.com/software/pyqt/intro>`_ or `PySide
+<https://wiki.qt.io/PySide>`_) and for KDE (`PyKDE4 <https://techbase.kde.org/Languages/Python/Using_PyKDE_4>`__).
PyQt is currently more mature than PySide, but you must buy a PyQt license from
-`Riverbank Computing <http://www.riverbankcomputing.co.uk/software/pyqt/license>`_
+`Riverbank Computing <https://www.riverbankcomputing.com/commercial/license-faq>`_
if you want to write proprietary applications. PySide is free for all applications.
Qt 4.5 upwards is licensed under the LGPL license; also, commercial licenses
-are available from `The Qt Company <http://www.qt.io/licensing/>`_.
+are available from `The Qt Company <https://www.qt.io/licensing/>`_.
Gtk+
----
-The `GObject introspection bindings <https://live.gnome.org/PyGObject>`_
+The `GObject introspection bindings <https://wiki.gnome.org/Projects/PyGObject>`_
for Python allow you to write GTK+ 3 applications. There is also a
-`Python GTK+ 3 Tutorial <http://python-gtk-3-tutorial.readthedocs.org/en/latest/>`_.
+`Python GTK+ 3 Tutorial <https://python-gtk-3-tutorial.readthedocs.org/en/latest/>`_.
The older PyGtk bindings for the `Gtk+ 2 toolkit <http://www.gtk.org>`_ have
been implemented by James Henstridge; see <http://www.pygtk.org>.
import threading, time
def thread_task(name, n):
- for i in range(n): print(name, i)
+ for i in range(n):
+ print(name, i)
for i in range(10):
T = threading.Thread(target=thread_task, args=(str(i), i))
def thread_task(name, n):
time.sleep(0.001) # <--------------------!
- for i in range(n): print(name, i)
+ for i in range(n):
+ print(name, i)
for i in range(10):
T = threading.Thread(target=thread_task, args=(str(i), i))
import struct
with open(filename, "rb") as f:
- s = f.read(8)
- x, y, z = struct.unpack(">hhl", s)
+ s = f.read(8)
+ x, y, z = struct.unpack(">hhl", s)
The '>' in the format string forces big-endian data; the letter 'h' reads one
"short integer" (2 bytes), and 'l' reads one "long integer" (4 bytes) from the
For Unix, see a Usenet post by Mitch Chapman:
- http://groups.google.com/groups?selm=34A04430.CF9@ohioee.com
+ https://groups.google.com/groups?selm=34A04430.CF9@ohioee.com
Why doesn't closing sys.stdout (stdin, stderr) really close it?
import urllib.request
- ### build the query string
+ # build the query string
qs = "First=Josephine&MI=Q&Last=Public"
- ### connect and send the server a path
+ # connect and send the server a path
req = urllib.request.urlopen('http://www.some-server.out-there'
'/cgi-bin/some-cgi-script', data=qs)
with req:
``/usr/sbin/sendmail``. The sendmail manual page will help you out. Here's
some sample code::
- SENDMAIL = "/usr/sbin/sendmail" # sendmail location
import os
+
+ SENDMAIL = "/usr/sbin/sendmail" # sendmail location
p = os.popen("%s -t -i" % SENDMAIL, "w")
p.write("To: receiver@example.com\n")
p.write("Subject: test\n")
PythonWin is a Python IDE that includes a GUI debugger based on pdb. The
Pythonwin debugger colors breakpoints and has quite a few cool features such as
debugging non-Pythonwin programs. Pythonwin is available as part of the `Python
-for Windows Extensions <http://sourceforge.net/projects/pywin32/>`__ project and
+for Windows Extensions <https://sourceforge.net/projects/pywin32/>`__ project and
as a part of the ActivePython distribution (see
-http://www.activestate.com/activepython\ ).
+https://www.activestate.com/activepython\ ).
`Boa Constructor <http://boa-constructor.sourceforge.net/>`_ is an IDE and GUI
builder that uses wxWidgets. It offers visual frame creation and manipulation,
Pydb is a version of the standard Python debugger pdb, modified for use with DDD
(Data Display Debugger), a popular graphical debugger front end. Pydb can be
found at http://bashdb.sourceforge.net/pydb/ and DDD can be found at
-http://www.gnu.org/software/ddd.
+https://www.gnu.org/software/ddd.
There are a number of commercial Python IDEs that include graphical debuggers.
They include:
-* Wing IDE (http://wingware.com/)
-* Komodo IDE (http://komodoide.com/)
+* Wing IDE (https://wingware.com/)
+* Komodo IDE (https://komodoide.com/)
* PyCharm (https://www.jetbrains.com/pycharm/)
warns about code complexity and style. You can get PyChecker from
http://pychecker.sourceforge.net/.
-`Pylint <http://www.logilab.org/projects/pylint>`_ is another tool that checks
+`Pylint <https://www.pylint.org/>`_ is another tool that checks
if a module satisfies a coding standard, and also makes it possible to write
plug-ins to add a custom feature. In addition to the bug checking that
PyChecker performs, Pylint offers some additional features such as checking line
length, whether variable names are well-formed according to your coding
standard, whether declared interfaces are fully implemented, and more.
-http://docs.pylint.org/ provides a full list of Pylint's features.
+https://docs.pylint.org/ provides a full list of Pylint's features.
How can I create a stand-alone binary from a Python script?
>>> squares = []
>>> for x in range(5):
- ... squares.append(lambda: x**2)
+ ... squares.append(lambda: x**2)
This gives you a list that contains 5 lambdas that calculate ``x**2``. You
might expect that, when called, they would return, respectively, ``0``, ``1``,
>>> squares = []
>>> for x in range(5):
- ... squares.append(lambda n=x: n**2)
+ ... squares.append(lambda n=x: n**2)
Here, ``n=x`` creates a new variable ``n`` local to the lambda and computed
when the lambda is defined so that it has the same value that ``x`` had at
args['a'] = 'new-value' # args is a mutable dictionary
args['b'] = args['b'] + 1 # change it in-place
- args = {'a':' old-value', 'b': 99}
+ args = {'a': 'old-value', 'b': 99}
func3(args)
print(args['a'], args['b'])
``def`` and ``class`` statements, but in that case the value is a
callable. Consider the following code::
- class A:
- pass
-
- B = A
-
- a = B()
- b = a
- print(b)
+ >>> class A:
+ ... pass
+ ...
+ >>> B = A
+ >>> a = B()
+ >>> b = a
+ >>> print(b)
<__main__.A object at 0x16D07CC>
- print(a)
+ >>> print(a)
<__main__.A object at 0x16D07CC>
Arguably the class has a name: even though it is bound to two names and invoked
To convert, e.g., the number 144 to the string '144', use the built-in type
constructor :func:`str`. If you want a hexadecimal or octal representation, use
the built-in functions :func:`hex` or :func:`oct`. For fancy formatting, see
-the :ref:`string-formatting` section, e.g. ``"{:04d}".format(144)`` yields
+the :ref:`formatstrings` section, e.g. ``"{:04d}".format(144)`` yields
``'0144'`` and ``"{:.3f}".format(1.0/3.0)`` yields ``'0.333'``.
may come up with. This is doubly true for primitives written in C, such
as builtins and some extension types. For example, be sure to use
either the :meth:`list.sort` built-in method or the related :func:`sorted`
- function to do sorting (and see the
- `sorting mini-HOWTO <https://wiki.python.org/moin/HowTo/Sorting>`_ for examples
+ function to do sorting (and see the :ref:`sortinghowto` for examples
of moderately advanced usage).
* Abstractions tend to create indirections and force the interpreter to work
Use the :func:`reversed` built-in function, which is new in Python 2.4::
for x in reversed(sequence):
- ... # do something with x...
+ ... # do something with x ...
This won't touch your original sequence, but build a new copy with reversed
order to iterate over.
With Python 2.3, you can use an extended slice syntax::
for x in sequence[::-1]:
- ... # do something with x...
+ ... # do something with x ...
How do you remove duplicates from a list?
See the Python Cookbook for a long discussion of many ways to do this:
- http://code.activestate.com/recipes/52560/
+ https://code.activestate.com/recipes/52560/
If you don't mind reordering the list, sort it and then scan from the end of the
list, deleting duplicates as you go::
>>> A = [[None] * 2] * 3
-This looks correct if you print it::
+This looks correct if you print it:
+
+.. testsetup::
+
+ A = [[None] * 2] * 3
+
+.. doctest::
>>> A
[[None, None], [None, None], [None, None]]
But when you assign a value, it shows up in multiple places:
- >>> A[0][0] = 5
- >>> A
- [[5, None], [5, None], [5, None]]
+.. testsetup::
+
+ A = [[None] * 2] * 3
+
+.. doctest::
+
+ >>> A[0][0] = 5
+ >>> A
+ [[5, None], [5, None], [5, None]]
The reason is that replicating a list with ``*`` doesn't create copies, it only
creates references to the existing objects. The ``*3`` creates a list
w, h = 2, 3
A = [[None] * w for i in range(h)]
-Or, you can use an extension that provides a matrix datatype; `Numeric Python
+Or, you can use an extension that provides a matrix datatype; `NumPy
<http://www.numpy.org/>`_ is the best known.
The technique, attributed to Randal Schwartz of the Perl community, sorts the
elements of a list by a metric which maps each element to its "sort value". In
-Python, just use the ``key`` argument for the ``sort()`` method::
+Python, use the ``key`` argument for the :meth:`list.sort` method::
Isorted = L[:]
Isorted.sort(key=lambda s: int(s[10:15]))
-The ``key`` argument is new in Python 2.4, for older versions this kind of
-sorting is quite simple to do with list comprehensions. To sort a list of
-strings by their uppercase values::
-
- tmp1 = [(x.upper(), x) for x in L] # Schwartzian transform
- tmp1.sort()
- Usorted = [x[1] for x in tmp1]
-
-To sort by the integer value of a subfield extending from positions 10-15 in
-each string::
-
- tmp2 = [(int(s[10:15]), s) for s in L] # Schwartzian transform
- tmp2.sort()
- Isorted = [x[1] for x in tmp2]
-
-For versions prior to 3.0, Isorted may also be computed by ::
-
- def intfield(s):
- return int(s[10:15])
-
- def Icmp(s1, s2):
- return cmp(intfield(s1), intfield(s2))
-
- Isorted = L[:]
- Isorted.sort(Icmp)
-
-but since this method calls ``intfield()`` many times for each element of L, it
-is slower than the Schwartzian Transform.
-
How can I sort one list by values from another list?
----------------------------------------------------
definition::
class C:
- def meth (self, arg):
+ def meth(self, arg):
return arg * 2 + self.attribute
def search(obj):
if isinstance(obj, Mailbox):
- # ... code to search a mailbox
+ ... # code to search a mailbox
elif isinstance(obj, Document):
- # ... code to search a document
+ ... # code to search a document
elif ...
A better approach is to define a ``search()`` method on all the classes and just
class Mailbox:
def search(self):
- # ... code to search a mailbox
+ ... # code to search a mailbox
class Document:
def search(self):
- # ... code to search a document
+ ... # code to search a document
obj.search()
Use the built-in :func:`super` function::
class Derived(Base):
- def meth (self):
+ def meth(self):
super(Derived, self).meth()
For version prior to 3.0, you may be using classic classes: For a class
next freshly created object is allocated at the same position in memory. This
is illustrated by this example:
->>> id(1000)
+>>> id(1000) # doctest: +SKIP
13901272
->>> id(2000)
+>>> id(2000) # doctest: +SKIP
13901272
The two ids belong to different integer objects that are created before, and
to the object:
>>> a = 1000; b = 2000
->>> id(a)
+>>> id(a) # doctest: +SKIP
13901272
->>> id(b)
+>>> id(b) # doctest: +SKIP
13891296
Simply rename the downloaded file to have the .TGZ extension, and WinZip will be
able to handle it. (If your copy of WinZip doesn't, get a newer one from
-http://www.winzip.com.)
+https://www.winzip.com.)
asynchronous iterable
An object, that can be used in an :keyword:`async for` statement.
- Must return an :term:`awaitable` from its :meth:`__aiter__` method,
- which should in turn be resolved in an :term:`asynchronous iterator`
- object. Introduced by :pep:`492`.
+ Must return an :term:`asynchronous iterator` from its
+ :meth:`__aiter__` method. Introduced by :pep:`492`.
asynchronous iterator
An object that implements :meth:`__aiter__` and :meth:`__anext__`
- methods, that must return :term:`awaitable` objects.
+ methods. ``__anext__`` must return an :term:`awaitable` object.
:keyword:`async for` resolves awaitable returned from asynchronous
iterator's :meth:`__anext__` method until it raises
:exc:`StopAsyncIteration` exception. Introduced by :pep:`492`.
A buffer is considered contiguous exactly if it is either
*C-contiguous* or *Fortran contiguous*. Zero-dimensional buffers are
C and Fortran contiguous. In one-dimensional arrays, the items
- must be layed out in memory next to each other, in order of
+ must be laid out in memory next to each other, in order of
increasing indexes starting from zero. In multidimensional
C-contiguous arrays, the last index varies the fastest when
visiting items in order of memory address. However, in
A synonym for :term:`file object`.
finder
- An object that tries to find the :term:`loader` for a module. It must
- implement either a method named :meth:`find_loader` or a method named
- :meth:`find_module`. See :pep:`302` and :pep:`420` for details and
- :class:`importlib.abc.Finder` for an :term:`abstract base class`.
+ An object that tries to find the :term:`loader` for a module that is
+ being imported.
+
+ Since Python 3.3, there are two types of finder: :term:`meta path finders
+ <meta path finder>` for use with :data:`sys.meta_path`, and :term:`path
+ entry finders <path entry finder>` for use with :data:`sys.path_hooks`.
+
+ See :pep:`302`, :pep:`420` and :pep:`451` for much more detail.
floor division
Mathematical division that rounds down to nearest integer. The floor
:class:`collections.OrderedDict` and :class:`collections.Counter`.
meta path finder
- A finder returned by a search of :data:`sys.meta_path`. Meta path
+ A :term:`finder` returned by a search of :data:`sys.meta_path`. Meta path
finders are related to, but different from :term:`path entry finders
<path entry finder>`.
+ See :class:`importlib.abc.MetaPathFinder` for the methods that meta path
+ finders implement.
+
metaclass
The class of a class. Class definitions create a class name, a class
dictionary, and a list of base classes. The metaclass is responsible for
method resolution order
Method Resolution Order is the order in which base classes are searched
for a member during lookup. See `The Python 2.3 Method Resolution Order
- <https://www.python.org/download/releases/2.3/mro/>`_.
+ <https://www.python.org/download/releases/2.3/mro/>`_ for details of the
+ algorithm used by the Python interpreter since the 2.3 release.
module
An object that serves as an organizational unit of Python code. Modules
module spec
A namespace containing the import-related information used to load a
- module.
+ module. An instance of :class:`importlib.machinery.ModuleSpec`.
MRO
See :term:`method resolution order`.
(i.e. a :term:`path entry hook`) which knows how to locate modules given
a :term:`path entry`.
+ See :class:`importlib.abc.PathEntryFinder` for the methods that path entry
+ finders implement.
+
path entry hook
A callable on the :data:`sys.path_hook` list which returns a :term:`path
entry finder` if it knows how to find modules on a specific :term:`path
* Sadly, our help output isn't very informative on the new ability our script
has acquired, but that can always be fixed by improving the documentation for
- out script (e.g. via the ``help`` keyword argument).
+ our script (e.g. via the ``help`` keyword argument).
* That last output exposes a bug in our program.
#define INITERROR return NULL
- PyObject *
+ PyMODINIT_FUNC
PyInit_myextension(void)
#else
a lengthy tutorial for C programmers.
* `The ncurses man page <http://linux.die.net/man/3/ncurses>`_
* `The ncurses FAQ <http://invisible-island.net/ncurses/ncurses.faq.html>`_
-* `"Use curses... don't swear" <http://www.youtube.com/watch?v=eN1eZtjLEnU>`_:
+* `"Use curses... don't swear" <https://www.youtube.com/watch?v=eN1eZtjLEnU>`_:
video of a PyCon 2013 talk on controlling terminals using curses or Urwid.
* `"Console Applications with Urwid" <http://www.pyvideo.org/video/1568/console-applications-with-urwid>`_:
video of a PyCon CA 2012 talk demonstrating some applications written using
"Emulate type_getattro() in Objects/typeobject.c"
v = object.__getattribute__(self, key)
if hasattr(v, '__get__'):
- return v.__get__(None, self)
+ return v.__get__(None, self)
return v
The important points to remember are:
self.val = val
>>> class MyClass(object):
- x = RevealAccess(10, 'var "x"')
- y = 5
-
+ ... x = RevealAccess(10, 'var "x"')
+ ... y = 5
+ ...
>>> m = MyClass()
>>> m.x
Retrieving var "x"
Running the interpreter shows how the function descriptor works in practice::
>>> class D(object):
- def f(self, x):
- return x
-
+ ... def f(self, x):
+ ... return x
+ ...
>>> d = D()
- >>> D.__dict__['f'] # Stored internally as a function
+ >>> D.__dict__['f'] # Stored internally as a function
<function f at 0x00C45070>
- >>> D.f # Get from a class becomes an unbound method
+ >>> D.f # Get from a class becomes an unbound method
<unbound method D.f>
- >>> d.f # Get from an instance becomes a bound method
+ >>> d.f # Get from an instance becomes a bound method
<bound method D.f of <__main__.D object at 0x00B18C90>>
The output suggests that bound and unbound methods are two different types.
calls are unexciting::
>>> class E(object):
- def f(x):
- print(x)
- f = staticmethod(f)
-
+ ... def f(x):
+ ... print(x)
+ ... f = staticmethod(f)
+ ...
>>> print(E.f(3))
3
>>> print(E().f(3))
:func:`staticmethod` would look like this::
class StaticMethod(object):
- "Emulate PyStaticMethod_Type() in Objects/funcobject.c"
+ "Emulate PyStaticMethod_Type() in Objects/funcobject.c"
- def __init__(self, f):
- self.f = f
+ def __init__(self, f):
+ self.f = f
- def __get__(self, obj, objtype=None):
- return self.f
+ def __get__(self, obj, objtype=None):
+ return self.f
Unlike static methods, class methods prepend the class reference to the
argument list before calling the function. This format is the same
for whether the caller is an object or a class::
>>> class E(object):
- def f(klass, x):
- return klass.__name__, x
- f = classmethod(f)
-
+ ... def f(klass, x):
+ ... return klass.__name__, x
+ ... f = classmethod(f)
+ ...
>>> print(E.f(3))
('E', 3)
>>> print(E().f(3))
:func:`classmethod` would look like this::
class ClassMethod(object):
- "Emulate PyClassMethod_Type() in Objects/funcobject.c"
+ "Emulate PyClassMethod_Type() in Objects/funcobject.c"
- def __init__(self, f):
- self.f = f
+ def __init__(self, f):
+ self.f = f
- def __get__(self, obj, klass=None):
- if klass is None:
- klass = type(obj)
- def newfunc(*args):
- return self.f(klass, *args)
- return newfunc
+ def __get__(self, obj, klass=None):
+ if klass is None:
+ klass = type(obj)
+ def newfunc(*args):
+ return self.f(klass, *args)
+ return newfunc
List comprehensions and generator expressions (short form: "listcomps" and
"genexps") are a concise notation for such operations, borrowed from the
-functional programming language Haskell (http://www.haskell.org/). You can strip
+functional programming language Haskell (https://www.haskell.org/). You can strip
all the whitespace from a stream of strings with the following code::
line_list = [' line 1\n', 'line 2 \n', ...]
continue # Skip this element
for expr2 in sequence2:
if not (condition2):
- continue # Skip this element
+ continue # Skip this element
...
for exprN in sequenceN:
- if not (conditionN):
- continue # Skip this element
+ if not (conditionN):
+ continue # Skip this element
- # Output the value of
- # the expression.
+ # Output the value of
+ # the expression.
This means that when there are multiple ``for...in`` clauses but no ``if``
clauses, the length of the resulting output will be equal to the product of the
It doesn't construct an in-memory list and exhaust all the input iterators
before returning; instead tuples are constructed and returned only if they're
requested. (The technical term for this behaviour is `lazy evaluation
-<http://en.wikipedia.org/wiki/Lazy_evaluation>`__.)
+<https://en.wikipedia.org/wiki/Lazy_evaluation>`__.)
This iterator is intended to be used with iterables that are all of the same
length. If the iterables are of different lengths, the resulting stream will be
**Structure and Interpretation of Computer Programs**, by Harold Abelson and
Gerald Jay Sussman with Julie Sussman. Full text at
-http://mitpress.mit.edu/sicp/. In this classic textbook of computer science,
+https://mitpress.mit.edu/sicp/. In this classic textbook of computer science,
chapters 2 and 3 discuss the use of sequences and streams to organize the data
flow inside a program. The book uses Scheme for its examples, but many of the
design approaches described in these chapters are applicable to functional-style
http://www.defmacro.org/ramblings/fp.html: A general introduction to functional
programming that uses Java examples and has a lengthy historical introduction.
-http://en.wikipedia.org/wiki/Functional_programming: General Wikipedia entry
+https://en.wikipedia.org/wiki/Functional_programming: General Wikipedia entry
describing functional programming.
-http://en.wikipedia.org/wiki/Coroutine: Entry for coroutines.
+https://en.wikipedia.org/wiki/Coroutine: Entry for coroutines.
-http://en.wikipedia.org/wiki/Currying: Entry for the concept of currying.
+https://en.wikipedia.org/wiki/Currying: Entry for the concept of currying.
Python-specific
---------------
Mertz also wrote a 3-part series of articles on functional programming
for IBM's DeveloperWorks site; see
-`part 1 <http://www.ibm.com/developerworks/linux/library/l-prog/index.html>`__,
-`part 2 <http://www.ibm.com/developerworks/linux/library/l-prog2/index.html>`__, and
-`part 3 <http://www.ibm.com/developerworks/linux/library/l-prog3/index.html>`__,
+`part 1 <https://www.ibm.com/developerworks/linux/library/l-prog/index.html>`__,
+`part 2 <https://www.ibm.com/developerworks/linux/library/l-prog2/index.html>`__, and
+`part 3 <https://www.ibm.com/developerworks/linux/library/l-prog3/index.html>`__,
Python documentation
sorting.rst
unicode.rst
urllib2.rst
- webservers.rst
argparse.rst
ipaddress.rst
clinic.rst
def __init__(self):
self.logger = logging.getLogger('spam_application.auxiliary.Auxiliary')
self.logger.info('creating an instance of Auxiliary')
+
def do_something(self):
self.logger.info('doing something')
a = 1 + 1
2005-03-23 23:47:11,673 - spam_application - INFO -
done with auxiliary_module.some_function()
+Logging from multiple threads
+-----------------------------
+
+Logging from multiple threads requires no special effort. The following example
+shows logging from the main (initial) thread and another thread::
+
+ import logging
+ import threading
+ import time
+
+ def worker(arg):
+ while not arg['stop']:
+ logging.debug('Hi from myfunc')
+ time.sleep(0.5)
+
+ def main():
+ logging.basicConfig(level=logging.DEBUG, format='%(relativeCreated)6d %(threadName)s %(message)s')
+ info = {'stop': False}
+ thread = threading.Thread(target=worker, args=(info,))
+ thread.start()
+ while True:
+ try:
+ logging.debug('Hello from main')
+ time.sleep(0.75)
+ except KeyboardInterrupt:
+ info['stop'] = True
+ break
+ thread.join()
+
+ if __name__ == '__main__':
+ main()
+
+When run, the script should print something like the following::
+
+ 0 Thread-1 Hi from myfunc
+ 3 MainThread Hello from main
+ 505 Thread-1 Hi from myfunc
+ 755 MainThread Hello from main
+ 1007 Thread-1 Hi from myfunc
+ 1507 MainThread Hello from main
+ 1508 Thread-1 Hi from myfunc
+ 2010 Thread-1 Hi from myfunc
+ 2258 MainThread Hello from main
+ 2512 Thread-1 Hi from myfunc
+ 3009 MainThread Hello from main
+ 3013 Thread-1 Hi from myfunc
+ 3515 Thread-1 Hi from myfunc
+ 3761 MainThread Hello from main
+ 4017 Thread-1 Hi from myfunc
+ 4513 MainThread Hello from main
+ 4518 Thread-1 Hi from myfunc
+
+This shows the logging output interspersed as one might expect. This approach
+works for more threads than shown here, of course.
+
Multiple handlers and formatters
--------------------------------
An example of using these two classes follows (imports omitted)::
- que = queue.Queue(-1) # no limit on size
+ que = queue.Queue(-1) # no limit on size
queue_handler = QueueHandler(que)
handler = logging.StreamHandler()
listener = QueueListener(que, handler)
return True
if __name__ == '__main__':
- levels = (logging.DEBUG, logging.INFO, logging.WARNING, logging.ERROR, logging.CRITICAL)
- logging.basicConfig(level=logging.DEBUG,
- format='%(asctime)-15s %(name)-5s %(levelname)-8s IP: %(ip)-15s User: %(user)-8s %(message)s')
- a1 = logging.getLogger('a.b.c')
- a2 = logging.getLogger('d.e.f')
-
- f = ContextFilter()
- a1.addFilter(f)
- a2.addFilter(f)
- a1.debug('A debug message')
- a1.info('An info message with %s', 'some parameters')
- for x in range(10):
- lvl = choice(levels)
- lvlname = logging.getLevelName(lvl)
- a2.log(lvl, 'A message at %s level with %d %s', lvlname, 2, 'parameters')
+ levels = (logging.DEBUG, logging.INFO, logging.WARNING, logging.ERROR, logging.CRITICAL)
+ logging.basicConfig(level=logging.DEBUG,
+ format='%(asctime)-15s %(name)-5s %(levelname)-8s IP: %(ip)-15s User: %(user)-8s %(message)s')
+ a1 = logging.getLogger('a.b.c')
+ a2 = logging.getLogger('d.e.f')
+
+ f = ContextFilter()
+ a1.addFilter(f)
+ a2.addFilter(f)
+ a1.debug('A debug message')
+ a1.info('An info message with %s', 'some parameters')
+ for x in range(10):
+ lvl = choice(levels)
+ lvlname = logging.getLevelName(lvl)
+ a2.log(lvl, 'A message at %s level with %d %s', lvlname, 2, 'parameters')
which, when run, produces something like::
while True:
try:
record = queue.get()
- if record is None: # We send this as a sentinel to tell the listener to quit.
+ if record is None: # We send this as a sentinel to tell the listener to quit.
break
logger = logging.getLogger(record.name)
- logger.handle(record) # No level or filter logic applied - just do it!
+ logger.handle(record) # No level or filter logic applied - just do it!
except Exception:
import sys, traceback
print('Whoops! Problem:', file=sys.stderr)
# Note that on Windows you can't rely on fork semantics, so each process
# will run the logging configuration code when it starts.
def worker_configurer(queue):
- h = logging.handlers.QueueHandler(queue) # Just the one handler needed
+ h = logging.handlers.QueueHandler(queue) # Just the one handler needed
root = logging.getLogger()
root.addHandler(h)
- root.setLevel(logging.DEBUG) # send all messages, for demo; no other level or filter logic applied.
+ # send all messages, for demo; no other level or filter logic applied.
+ root.setLevel(logging.DEBUG)
# This is the worker process top-level loop, which just logs ten events with
# random intervening delays before terminating.
workers = []
for i in range(10):
worker = multiprocessing.Process(target=worker_process,
- args=(queue, worker_configurer))
+ args=(queue, worker_configurer))
workers.append(worker)
worker.start()
for w in workers:
of queues, for example a ZeroMQ 'publish' socket. In the example below,the
socket is created separately and passed to the handler (as its 'queue')::
- import zmq # using pyzmq, the Python binding for ZeroMQ
- import json # for serializing records portably
+ import zmq # using pyzmq, the Python binding for ZeroMQ
+ import json # for serializing records portably
ctx = zmq.Context()
- sock = zmq.Socket(ctx, zmq.PUB) # or zmq.PUSH, or other suitable value
- sock.bind('tcp://*:5556') # or wherever
+ sock = zmq.Socket(ctx, zmq.PUB) # or zmq.PUSH, or other suitable value
+ sock.bind('tcp://*:5556') # or wherever
class ZeroMQSocketHandler(QueueHandler):
def enqueue(self, record):
def __init__(self, uri, *handlers, **kwargs):
self.ctx = kwargs.get('ctx') or zmq.Context()
socket = zmq.Socket(self.ctx, zmq.SUB)
- socket.setsockopt(zmq.SUBSCRIBE, '') # subscribe to everything
+ socket.setsockopt(zmq.SUBSCRIBE, '') # subscribe to everything
socket.connect(uri)
def dequeue(self):
-----------------------------------------
Below is an example of a logging configuration dictionary - it's taken from
-the `documentation on the Django project <https://docs.djangoproject.com/en/1.3/topics/logging/#configuring-logging>`_.
+the `documentation on the Django project <https://docs.djangoproject.com/en/1.9/topics/logging/#configuring-logging>`_.
This dictionary is passed to :func:`~config.dictConfig` to put the configuration into effect::
LOGGING = {
}
For more information about this configuration, you can see the `relevant
-section <https://docs.djangoproject.com/en/1.6/topics/logging/#configuring-logging>`_
+section <https://docs.djangoproject.com/en/1.9/topics/logging/#configuring-logging>`_
of the Django documentation.
.. _cookbook-rotator-namer:
Inserting a BOM into messages sent to a SysLogHandler
-----------------------------------------------------
-`RFC 5424 <http://tools.ietf.org/html/rfc5424>`_ requires that a
+`RFC 5424 <https://tools.ietf.org/html/rfc5424>`_ requires that a
Unicode message be sent to a syslog daemon as a set of bytes which have the
following structure: an optional pure-ASCII component, followed by a UTF-8 Byte
Order Mark (BOM), followed by Unicode encoded using UTF-8. (See the `relevant
-section of the specification <http://tools.ietf.org/html/rfc5424#section-6>`_.)
+section of the specification <https://tools.ietf.org/html/rfc5424#section-6>`_.)
In Python 3.1, code was added to
:class:`~logging.handlers.SysLogHandler` to insert a BOM into the message, but
Format an exception so that it prints on a single line.
"""
result = super(OneLineExceptionFormatter, self).formatException(exc_info)
- return repr(result) # or format into one line however you want to
+ return repr(result) # or format into one line however you want to
def format(self, record):
s = super(OneLineExceptionFormatter, self).format(record)
The example script has a simple function, ``foo``, which just cycles through
all the logging levels, writing to ``sys.stderr`` to say what level it's about
-to log at, and then actually logging a message that that level. You can pass a
+to log at, and then actually logging a message at that level. You can pass a
parameter to ``foo`` which, if true, will log at ERROR and CRITICAL levels -
otherwise, it only logs at DEBUG, INFO and WARNING levels.
showing how the time is formatted both as local time and UTC, one for each
handler.
+
+
+.. _context-manager:
+
+Using a context manager for selective logging
+---------------------------------------------
+
+There are times when it would be useful to temporarily change the logging
+configuration and revert it back after doing something. For this, a context
+manager is the most obvious way of saving and restoring the logging context.
+Here is a simple example of such a context manager, which allows you to
+optionally change the logging level and add a logging handler purely in the
+scope of the context manager::
+
+ import logging
+ import sys
+
+ class LoggingContext(object):
+ def __init__(self, logger, level=None, handler=None, close=True):
+ self.logger = logger
+ self.level = level
+ self.handler = handler
+ self.close = close
+
+ def __enter__(self):
+ if self.level is not None:
+ self.old_level = self.logger.level
+ self.logger.setLevel(self.level)
+ if self.handler:
+ self.logger.addHandler(self.handler)
+
+ def __exit__(self, et, ev, tb):
+ if self.level is not None:
+ self.logger.setLevel(self.old_level)
+ if self.handler:
+ self.logger.removeHandler(self.handler)
+ if self.handler and self.close:
+ self.handler.close()
+ # implicit return of None => don't swallow exceptions
+
+If you specify a level value, the logger's level is set to that value in the
+scope of the with block covered by the context manager. If you specify a
+handler, it is added to the logger on entry to the block and removed on exit
+from the block. You can also ask the manager to close the handler for you on
+block exit - you could do this if you don't need the handler any more.
+
+To illustrate how it works, we can add the following block of code to the
+above::
+
+ if __name__ == '__main__':
+ logger = logging.getLogger('foo')
+ logger.addHandler(logging.StreamHandler())
+ logger.setLevel(logging.INFO)
+ logger.info('1. This should appear just once on stderr.')
+ logger.debug('2. This should not appear.')
+ with LoggingContext(logger, level=logging.DEBUG):
+ logger.debug('3. This should appear once on stderr.')
+ logger.debug('4. This should not appear.')
+ h = logging.StreamHandler(sys.stdout)
+ with LoggingContext(logger, level=logging.DEBUG, handler=h, close=True):
+ logger.debug('5. This should appear twice - once on stderr and once on stdout.')
+ logger.info('6. This should appear just once on stderr.')
+ logger.debug('7. This should not appear.')
+
+We initially set the logger's level to ``INFO``, so message #1 appears and
+message #2 doesn't. We then change the level to ``DEBUG`` temporarily in the
+following ``with`` block, and so message #3 appears. After the block exits, the
+logger's level is restored to ``INFO`` and so message #4 doesn't appear. In the
+next ``with`` block, we set the level to ``DEBUG`` again but also add a handler
+writing to ``sys.stdout``. Thus, message #5 appears twice on the console (once
+via ``stderr`` and once via ``stdout``). After the ``with`` statement's
+completion, the status is as it was before so message #6 appears (like message
+#1) whereas message #7 doesn't (just like message #2).
+
+If we run the resulting script, the result is as follows::
+
+ $ python logctx.py
+ 1. This should appear just once on stderr.
+ 3. This should appear once on stderr.
+ 5. This should appear twice - once on stderr and once on stdout.
+ 5. This should appear twice - once on stderr and once on stdout.
+ 6. This should appear just once on stderr.
+
+If we run it again, but pipe ``stderr`` to ``/dev/null``, we see the following,
+which is the only message written to ``stdout``::
+
+ $ python logctx.py 2>/dev/null
+ 5. This should appear twice - once on stderr and once on stdout.
+
+Once again, but piping ``stdout`` to ``/dev/null``, we get::
+
+ $ python logctx.py >/dev/null
+ 1. This should appear just once on stderr.
+ 3. This should appear once on stderr.
+ 5. This should appear twice - once on stderr and once on stdout.
+ 6. This should appear just once on stderr.
+
+In this case, the message #5 printed to ``stdout`` doesn't appear, as expected.
+
+Of course, the approach described here can be generalised, for example to attach
+logging filters temporarily. Note that the above code works in Python 2 as well
+as Python 3.
A very simple example is::
import logging
- logging.warning('Watch out!') # will print a message to the console
- logging.info('I told you so') # will not print anything
+ logging.warning('Watch out!') # will print a message to the console
+ logging.info('I told you so') # will not print anything
If you type these lines into a script and run it, you'll see::
If your logging needs are simple, then use the above examples to incorporate
logging into your own scripts, and if you run into problems or don't
understand something, please post a question on the comp.lang.python Usenet
-group (available at http://groups.google.com/group/comp.lang.python) and you
+group (available at https://groups.google.com/group/comp.lang.python) and you
should receive help before too long.
Still here? You can carry on reading the next few sections, which provide a
binary reading). Under Python 3, binary files and text files are clearly
distinct and mutually incompatible; see the :mod:`io` module for details.
Therefore, you **must** make a decision of whether a file will be used for
-binary access (allowing to read and/or write binary data) or text access
-(allowing to read and/or write text data). You should also use :func:`io.open`
+binary access (allowing binary data to be read and/or written) or text access
+(allowing text data to be read and/or written). You should also use :func:`io.open`
for opening files instead of the built-in :func:`open` function as the :mod:`io`
module is consistent from Python 2 to 3 while the built-in :func:`open` function
is not (in Python 3 it's actually :func:`io.open`).
appropriate
#. Be careful when indexing binary data
+
+Use feature detection instead of version detection
+++++++++++++++++++++++++++++++++++++++++++++++++++
+Inevitably you will have code that has to choose what to do based on what
+version of Python is running. The best way to do this is with feature detection
+of whether the version of Python you're running under supports what you need.
+If for some reason that doesn't work then you should make the version check is
+against Python 2 and not Python 3. To help explain this, let's look at an
+example.
+
+Let's pretend that you need access to a feature of importlib_ that
+is available in Python's standard library since Python 3.3 and available for
+Python 2 through importlib2_ on PyPI. You might be tempted to write code to
+access e.g. the ``importlib.abc`` module by doing the following::
+
+ import sys
+
+ if sys.version[0] == 3:
+ from importlib import abc
+ else:
+ from importlib2 import abc
+
+The problem with this code is what happens when Python 4 comes out? It would
+be better to treat Python 2 as the exceptional case instead of Python 3 and
+assume that future Python versions will be more compatible with Python 3 than
+Python 2::
+
+ import sys
+
+ if sys.version[0] > 2:
+ from importlib import abc
+ else:
+ from importlib2 import abc
+
+The best solution, though, is to do no version detection at all and instead rely
+on feature detection. That avoids any potential issues of getting the version
+detection wrong and helps keep you future-compatible::
+
+ try:
+ from importlib import abc
+ except ImportError:
+ from importlib2 import abc
+
+
Prevent compatibility regressions
---------------------------------
tox with your continuous integration system so that you never accidentally break
Python 2 or 3 support.
-You may also want to use use the ``-bb`` flag with the Python 3 interpreter to
+You may also want to use the ``-bb`` flag with the Python 3 interpreter to
trigger an exception when you are comparing bytes to strings or bytes to an int
(the latter is available starting in Python 3.5). By default type-differing
comparisons simply return ``False``, but if you made a mistake in your
.. _cheat sheet: http://python-future.org/compatible_idioms.html
.. _coverage.py: https://pypi.python.org/pypi/coverage
.. _Futurize: http://python-future.org/automatic_conversion.html
-.. _Modernize: http://python-modernize.readthedocs.org/en/latest/
+.. _importlib: https://docs.python.org/3/library/importlib.html#module-importlib
+.. _importlib2: https://pypi.python.org/pypi/importlib2
+.. _Modernize: https://python-modernize.readthedocs.org/en/latest/
.. _Porting to Python 3: http://python3porting.com/
.. _Pylint: https://pypi.python.org/pypi/pylint
-.. _Python 3 Q & A: http://ncoghlan-devs-python-notes.readthedocs.org/en/latest/python3/questions_and_answers.html
+.. _Python 3 Q & A: https://ncoghlan-devs-python-notes.readthedocs.org/en/latest/python3/questions_and_answers.html
.. _python-future: http://python-future.org/
.. _python-porting: https://mail.python.org/mailman/listinfo/python-porting
Repetitions such as ``*`` are :dfn:`greedy`; when repeating a RE, the matching
engine will try to repeat it as many times as possible. If later portions of the
pattern don't match, the matching engine will then back up and try again with
-few repetitions.
+fewer repetitions.
A step-by-step example will make this more obvious. Let's consider the
expression ``a[bcd]*b``. This matches the letter ``'a'``, zero or more letters
A negative lookahead cuts through all this confusion:
-``.*[.](?!bat$).*$`` The negative lookahead means: if the expression ``bat``
+``.*[.](?!bat$)[^.]*$`` The negative lookahead means: if the expression ``bat``
doesn't match at this point, try the rest of the pattern; if ``bat$`` does
match, the whole pattern will fail. The trailing ``$`` is required to ensure
that something like ``sample.batch``, where the extension only starts with
-``bat``, will be allowed.
+``bat``, will be allowed. The ``[^.]*`` makes sure that the pattern works
+when there are multiple dots in the filename.
Excluding another filename extension is now easy; simply add it as an
alternative inside the assertion. The following pattern excludes filenames that
end in either ``bat`` or ``exe``:
-``.*[.](?!bat$|exe$).*$``
+``.*[.](?!bat$|exe$)[^.]*$``
Modifying Strings
Here's a simple example of using the :meth:`sub` method. It replaces colour
names with the word ``colour``::
- >>> p = re.compile( '(blue|white|red)')
- >>> p.sub( 'colour', 'blue socks and red shoes')
+ >>> p = re.compile('(blue|white|red)')
+ >>> p.sub('colour', 'blue socks and red shoes')
'colour socks and colour shoes'
- >>> p.sub( 'colour', 'blue socks and red shoes', count=1)
+ >>> p.sub('colour', 'blue socks and red shoes', count=1)
'colour socks and red shoes'
The :meth:`subn` method does the same work, but returns a 2-tuple containing the
new string value and the number of replacements that were performed::
- >>> p = re.compile( '(blue|white|red)')
- >>> p.subn( 'colour', 'blue socks and red shoes')
+ >>> p = re.compile('(blue|white|red)')
+ >>> p.subn('colour', 'blue socks and red shoes')
('colour socks and colour shoes', 2)
- >>> p.subn( 'colour', 'no colours at all')
+ >>> p.subn('colour', 'no colours at all')
('no colours at all', 0)
Empty matches are replaced only when they're not adjacent to a previous match.
================================
Sorts are guaranteed to be `stable
-<http://en.wikipedia.org/wiki/Sorting_algorithm#Stability>`_\. That means that
+<https://en.wikipedia.org/wiki/Sorting_algorithm#Stability>`_\. That means that
when multiple records have the same key, their original order is preserved.
>>> data = [('red', 1), ('blue', 1), ('red', 2), ('blue', 2)]
>>> sorted(s, key=attrgetter('grade'), reverse=True) # now sort on primary key, descending
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
-The `Timsort <http://en.wikipedia.org/wiki/Timsort>`_ algorithm used in Python
+The `Timsort <https://en.wikipedia.org/wiki/Timsort>`_ algorithm used in Python
does multiple sorts efficiently because it can take advantage of any ordering
already present in a dataset.
directly.
Another name for this idiom is
-`Schwartzian transform <http://en.wikipedia.org/wiki/Schwartzian_transform>`_\,
+`Schwartzian transform <https://en.wikipedia.org/wiki/Schwartzian_transform>`_\,
after Randal L. Schwartz, who popularized it among Perl programmers.
Now that Python sorting provides key-functions, this technique is not often needed.
twice:
>>> data = [('red', 1), ('blue', 1), ('red', 2), ('blue', 2)]
- >>> assert sorted(data, reverse=True) == list(reversed(sorted(reversed(data))))
+ >>> standard_way = sorted(data, key=itemgetter(0), reverse=True)
+ >>> double_reversed = list(reversed(sorted(reversed(data), key=itemgetter(0))))
+ >>> assert standard_way == double_reversed
+ >>> standard_way
+ [('red', 1), ('red', 2), ('blue', 1), ('blue', 2)]
* The sort routines are guaranteed to use :meth:`__lt__` when making comparisons
between two objects. So, it is easy to add a standard sort order to a class by
precise historical details aren't necessary for understanding how to
use Unicode effectively, but if you're curious, consult the Unicode
consortium site listed in the References or
-the `Wikipedia entry for Unicode <http://en.wikipedia.org/wiki/Unicode#History>`_
+the `Wikipedia entry for Unicode <https://en.wikipedia.org/wiki/Unicode#History>`_
for more information.)
origin and development of Unicode is also available on the site.
To help understand the standard, Jukka Korpela has written `an introductory
-guide <http://www.cs.tut.fi/~jkorpela/unicode/guide.html>`_ to reading the
+guide <https://www.cs.tut.fi/~jkorpela/unicode/guide.html>`_ to reading the
Unicode character tables.
Another `good introductory article <http://www.joelonsoftware.com/articles/Unicode.html>`_
reading this alternate article before continuing.
Wikipedia entries are often helpful; see the entries for "`character encoding
-<http://en.wikipedia.org/wiki/Character_encoding>`_" and `UTF-8
-<http://en.wikipedia.org/wiki/UTF-8>`_, for example.
+<https://en.wikipedia.org/wiki/Character_encoding>`_" and `UTF-8
+<https://en.wikipedia.org/wiki/UTF-8>`_, for example.
Python's Unicode Support
>>> b'\x80abc'.decode("utf-8", "ignore")
'abc'
-(In this code example, the Unicode replacement character has been replaced by
-a question mark because it may not be displayed on some systems.)
-
Encodings are specified as strings containing the encoding's name. Python 3.2
comes with roughly 100 different encodings; see the Python Library Reference at
:ref:`standard-encodings` for a list. Some encodings have multiple names; for
# make changes to the string 'data'
with open(fname + '.new', 'w',
- encoding="ascii", errors="surrogateescape") as f:
+ encoding="ascii", errors="surrogateescape") as f:
f.write(data)
The ``surrogateescape`` error handler will decode any non-ASCII bytes
html = open(local_filename)
Many uses of urllib will be that simple (note that instead of an 'http:' URL we
-could have used an URL starting with 'ftp:', 'file:', etc.). However, it's the
+could have used a URL starting with 'ftp:', 'file:', etc.). However, it's the
purpose of this tutorial to explain the more complicated cases, concentrating on
HTTP.
'language' : 'Python' }
data = urllib.parse.urlencode(values)
- data = data.encode('utf-8') # data should be bytes
+ data = data.encode('ascii') # data should be bytes
req = urllib.request.Request(url, data)
with urllib.request.urlopen(req) as response:
the_page = response.read()
Note that other encodings are sometimes required (e.g. for file upload from HTML
forms - see `HTML Specification, Form Submission
-<http://www.w3.org/TR/REC-html40/interact/forms.html#h-17.13>`_ for more
+<https://www.w3.org/TR/REC-html40/interact/forms.html#h-17.13>`_ for more
details).
If you do not pass the ``data`` argument, urllib uses a **GET** request. One
url = 'http://www.someserver.com/cgi-bin/register.cgi'
user_agent = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64)'
- values = {'name' : 'Michael Foord',
- 'location' : 'Northampton',
- 'language' : 'Python' }
- headers = { 'User-Agent' : user_agent }
+ values = {'name': 'Michael Foord',
+ 'location': 'Northampton',
+ 'language': 'Python' }
+ headers = {'User-Agent': user_agent}
- data = urllib.parse.urlencode(values)
- data = data.encode('utf-8')
+ data = urllib.parse.urlencode(values)
+ data = data.encode('ascii')
req = urllib.request.Request(url, data, headers)
with urllib.request.urlopen(req) as response:
the_page = response.read()
>>> req = urllib.request.Request('http://www.pretend_server.org')
>>> try: urllib.request.urlopen(req)
... except urllib.error.URLError as e:
- ... print(e.reason) #doctest: +SKIP
+ ... print(e.reason) #doctest: +SKIP
...
(4, 'getaddrinfo failed')
::
from urllib.request import Request, urlopen
- from urllib.error import URLError
+ from urllib.error import URLError
req = Request(someurl)
try:
response = urlopen(req)
:class:`http.client.HTTPMessage` instance.
Typical headers include 'Content-length', 'Content-type', and so on. See the
-`Quick Reference to HTTP Headers <http://www.cs.tut.fi/~jkorpela/http.html>`_
+`Quick Reference to HTTP Headers <https://www.cs.tut.fi/~jkorpela/http.html>`_
for a useful listing of HTTP headers with brief explanations of their meaning
and use.
e.g. "http://example.com/" *or* an "authority" (i.e. the hostname,
optionally including the port number) e.g. "example.com" or "example.com:8080"
(the latter example includes a port number). The authority, if present, must
-NOT contain the "userinfo" component - for example "joe@password:example.com" is
+NOT contain the "userinfo" component - for example "joe:password@example.com" is
not correct.
scripts with a localhost server, I have to prevent urllib from using
the proxy.
.. [#] urllib opener for SSL proxy (CONNECT method): `ASPN Cookbook Recipe
- <http://code.activestate.com/recipes/456195/>`_.
+ <https://code.activestate.com/recipes/456195/>`_.
+++ /dev/null
-*******************************
- HOWTO Use Python in the web
-*******************************
-
-:Author: Marek Kubica
-
-.. topic:: Abstract
-
- This document shows how Python fits into the web. It presents some ways
- to integrate Python with a web server, and general practices useful for
- developing web sites.
-
-
-Programming for the Web has become a hot topic since the rise of "Web 2.0",
-which focuses on user-generated content on web sites. It has always been
-possible to use Python for creating web sites, but it was a rather tedious task.
-Therefore, many frameworks and helper tools have been created to assist
-developers in creating faster and more robust sites. This HOWTO describes
-some of the methods used to combine Python with a web server to create
-dynamic content. It is not meant as a complete introduction, as this topic is
-far too broad to be covered in one single document. However, a short overview
-of the most popular libraries is provided.
-
-.. seealso::
-
- While this HOWTO tries to give an overview of Python in the web, it cannot
- always be as up to date as desired. Web development in Python is rapidly
- moving forward, so the wiki page on `Web Programming
- <https://wiki.python.org/moin/WebProgramming>`_ may be more in sync with
- recent development.
-
-
-The Low-Level View
-==================
-
-When a user enters a web site, their browser makes a connection to the site's
-web server (this is called the *request*). The server looks up the file in the
-file system and sends it back to the user's browser, which displays it (this is
-the *response*). This is roughly how the underlying protocol, HTTP, works.
-
-Dynamic web sites are not based on files in the file system, but rather on
-programs which are run by the web server when a request comes in, and which
-*generate* the content that is returned to the user. They can do all sorts of
-useful things, like display the postings of a bulletin board, show your email,
-configure software, or just display the current time. These programs can be
-written in any programming language the server supports. Since most servers
-support Python, it is easy to use Python to create dynamic web sites.
-
-Most HTTP servers are written in C or C++, so they cannot execute Python code
-directly -- a bridge is needed between the server and the program. These
-bridges, or rather interfaces, define how programs interact with the server.
-There have been numerous attempts to create the best possible interface, but
-there are only a few worth mentioning.
-
-Not every web server supports every interface. Many web servers only support
-old, now-obsolete interfaces; however, they can often be extended using
-third-party modules to support newer ones.
-
-
-Common Gateway Interface
-------------------------
-
-This interface, most commonly referred to as "CGI", is the oldest, and is
-supported by nearly every web server out of the box. Programs using CGI to
-communicate with their web server need to be started by the server for every
-request. So, every request starts a new Python interpreter -- which takes some
-time to start up -- thus making the whole interface only usable for low load
-situations.
-
-The upside of CGI is that it is simple -- writing a Python program which uses
-CGI is a matter of about three lines of code. This simplicity comes at a
-price: it does very few things to help the developer.
-
-Writing CGI programs, while still possible, is no longer recommended. With
-:ref:`WSGI <WSGI>`, a topic covered later in this document, it is possible to write
-programs that emulate CGI, so they can be run as CGI if no better option is
-available.
-
-.. seealso::
-
- The Python standard library includes some modules that are helpful for
- creating plain CGI programs:
-
- * :mod:`cgi` -- Handling of user input in CGI scripts
- * :mod:`cgitb` -- Displays nice tracebacks when errors happen in CGI
- applications, instead of presenting a "500 Internal Server Error" message
-
- The Python wiki features a page on `CGI scripts
- <https://wiki.python.org/moin/CgiScripts>`_ with some additional information
- about CGI in Python.
-
-
-Simple script for testing CGI
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-To test whether your web server works with CGI, you can use this short and
-simple CGI program::
-
- #!/usr/bin/env python
- # -*- coding: UTF-8 -*-
-
- # enable debugging
- import cgitb
- cgitb.enable()
-
- print("Content-Type: text/plain;charset=utf-8")
- print()
-
- print("Hello World!")
-
-Depending on your web server configuration, you may need to save this code with
-a ``.py`` or ``.cgi`` extension. Additionally, this file may also need to be
-in a ``cgi-bin`` folder, for security reasons.
-
-You might wonder what the ``cgitb`` line is about. This line makes it possible
-to display a nice traceback instead of just crashing and displaying an "Internal
-Server Error" in the user's browser. This is useful for debugging, but it might
-risk exposing some confidential data to the user. You should not use ``cgitb``
-in production code for this reason. You should *always* catch exceptions, and
-display proper error pages -- end-users don't like to see nondescript "Internal
-Server Errors" in their browsers.
-
-
-Setting up CGI on your own server
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-If you don't have your own web server, this does not apply to you. You can
-check whether it works as-is, and if not you will need to talk to the
-administrator of your web server. If it is a big host, you can try filing a
-ticket asking for Python support.
-
-If you are your own administrator or want to set up CGI for testing purposes on
-your own computers, you have to configure it by yourself. There is no single
-way to configure CGI, as there are many web servers with different
-configuration options. Currently the most widely used free web server is
-`Apache HTTPd <http://httpd.apache.org/>`_, or Apache for short. Apache can be
-easily installed on nearly every system using the system's package management
-tool. `lighttpd <http://www.lighttpd.net>`_ is another alternative and is
-said to have better performance. On many systems this server can also be
-installed using the package management tool, so manually compiling the web
-server may not be needed.
-
-* On Apache you can take a look at the `Dynamic Content with CGI
- <http://httpd.apache.org/docs/2.2/howto/cgi.html>`_ tutorial, where everything
- is described. Most of the time it is enough just to set ``+ExecCGI``. The
- tutorial also describes the most common gotchas that might arise.
-
-* On lighttpd you need to use the `CGI module
- <http://redmine.lighttpd.net/projects/lighttpd/wiki/Docs_ModCGI>`_\ , which can be configured
- in a straightforward way. It boils down to setting ``cgi.assign`` properly.
-
-
-Common problems with CGI scripts
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Using CGI sometimes leads to small annoyances while trying to get these
-scripts to run. Sometimes a seemingly correct script does not work as
-expected, the cause being some small hidden problem that's difficult to spot.
-
-Some of these potential problems are:
-
-* The Python script is not marked as executable. When CGI scripts are not
- executable most web servers will let the user download it, instead of
- running it and sending the output to the user. For CGI scripts to run
- properly on Unix-like operating systems, the ``+x`` bit needs to be set.
- Using ``chmod a+x your_script.py`` may solve this problem.
-
-* On a Unix-like system, The line endings in the program file must be Unix
- style line endings. This is important because the web server checks the
- first line of the script (called shebang) and tries to run the program
- specified there. It gets easily confused by Windows line endings (Carriage
- Return & Line Feed, also called CRLF), so you have to convert the file to
- Unix line endings (only Line Feed, LF). This can be done automatically by
- uploading the file via FTP in text mode instead of binary mode, but the
- preferred way is just telling your editor to save the files with Unix line
- endings. Most editors support this.
-
-* Your web server must be able to read the file, and you need to make sure the
- permissions are correct. On unix-like systems, the server often runs as user
- and group ``www-data``, so it might be worth a try to change the file
- ownership, or making the file world readable by using ``chmod a+r
- your_script.py``.
-
-* The web server must know that the file you're trying to access is a CGI script.
- Check the configuration of your web server, as it may be configured
- to expect a specific file extension for CGI scripts.
-
-* On Unix-like systems, the path to the interpreter in the shebang
- (``#!/usr/bin/env python``) must be correct. This line calls
- ``/usr/bin/env`` to find Python, but it will fail if there is no
- ``/usr/bin/env``, or if Python is not in the web server's path. If you know
- where your Python is installed, you can also use that full path. The
- commands ``whereis python`` and ``type -p python`` could help you find
- where it is installed. Once you know the path, you can change the shebang
- accordingly: ``#!/usr/bin/python``.
-
-* The file must not contain a BOM (Byte Order Mark). The BOM is meant for
- determining the byte order of UTF-16 and UTF-32 encodings, but some editors
- write this also into UTF-8 files. The BOM interferes with the shebang line,
- so be sure to tell your editor not to write the BOM.
-
-* If the web server is using :ref:`mod-python`, ``mod_python`` may be having
- problems. ``mod_python`` is able to handle CGI scripts by itself, but it can
- also be a source of issues.
-
-
-.. _mod-python:
-
-mod_python
-----------
-
-People coming from PHP often find it hard to grasp how to use Python in the web.
-Their first thought is mostly `mod_python <http://modpython.org/>`_\ ,
-because they think that this is the equivalent to ``mod_php``. Actually, there
-are many differences. What ``mod_python`` does is embed the interpreter into
-the Apache process, thus speeding up requests by not having to start a Python
-interpreter for each request. On the other hand, it is not "Python intermixed
-with HTML" in the way that PHP is often intermixed with HTML. The Python
-equivalent of that is a template engine. ``mod_python`` itself is much more
-powerful and provides more access to Apache internals. It can emulate CGI,
-work in a "Python Server Pages" mode (similar to JSP) which is "HTML
-intermingled with Python", and it has a "Publisher" which designates one file
-to accept all requests and decide what to do with them.
-
-``mod_python`` does have some problems. Unlike the PHP interpreter, the Python
-interpreter uses caching when executing files, so changes to a file will
-require the web server to be restarted. Another problem is the basic concept
--- Apache starts child processes to handle the requests, and unfortunately
-every child process needs to load the whole Python interpreter even if it does
-not use it. This makes the whole web server slower. Another problem is that,
-because ``mod_python`` is linked against a specific version of ``libpython``,
-it is not possible to switch from an older version to a newer (e.g. 2.4 to 2.5)
-without recompiling ``mod_python``. ``mod_python`` is also bound to the Apache
-web server, so programs written for ``mod_python`` cannot easily run on other
-web servers.
-
-These are the reasons why ``mod_python`` should be avoided when writing new
-programs. In some circumstances it still might be a good idea to use
-``mod_python`` for deployment, but WSGI makes it possible to run WSGI programs
-under ``mod_python`` as well.
-
-
-FastCGI and SCGI
-----------------
-
-FastCGI and SCGI try to solve the performance problem of CGI in another way.
-Instead of embedding the interpreter into the web server, they create
-long-running background processes. There is still a module in the web server
-which makes it possible for the web server to "speak" with the background
-process. As the background process is independent of the server, it can be
-written in any language, including Python. The language just needs to have a
-library which handles the communication with the webserver.
-
-The difference between FastCGI and SCGI is very small, as SCGI is essentially
-just a "simpler FastCGI". As the web server support for SCGI is limited,
-most people use FastCGI instead, which works the same way. Almost everything
-that applies to SCGI also applies to FastCGI as well, so we'll only cover
-the latter.
-
-These days, FastCGI is never used directly. Just like ``mod_python``, it is only
-used for the deployment of WSGI applications.
-
-
-Setting up FastCGI
-^^^^^^^^^^^^^^^^^^
-
-Each web server requires a specific module.
-
-* Apache has both `mod_fastcgi <http://www.fastcgi.com/drupal/>`_ and `mod_fcgid
- <http://httpd.apache.org/mod_fcgid/>`_. ``mod_fastcgi`` is the original one, but it
- has some licensing issues, which is why it is sometimes considered non-free.
- ``mod_fcgid`` is a smaller, compatible alternative. One of these modules needs
- to be loaded by Apache.
-
-* lighttpd ships its own `FastCGI module
- <http://redmine.lighttpd.net/projects/lighttpd/wiki/Docs_ModFastCGI>`_ as well as an
- `SCGI module <http://redmine.lighttpd.net/projects/lighttpd/wiki/Docs_ModSCGI>`_.
-
-* `nginx <http://nginx.org/>`_ also supports `FastCGI
- <http://wiki.nginx.org/NginxSimplePythonFCGI>`_.
-
-Once you have installed and configured the module, you can test it with the
-following WSGI-application::
-
- #!/usr/bin/env python
- # -*- coding: UTF-8 -*-
-
- import sys, os
- from html import escape
- from flup.server.fcgi import WSGIServer
-
- def app(environ, start_response):
- start_response('200 OK', [('Content-Type', 'text/html')])
-
- yield '<h1>FastCGI Environment</h1>'
- yield '<table>'
- for k, v in sorted(environ.items()):
- yield '<tr><th>{0}</th><td>{1}</td></tr>'.format(
- escape(k), escape(v))
- yield '</table>'
-
- WSGIServer(app).run()
-
-This is a simple WSGI application, but you need to install `flup
-<https://pypi.python.org/pypi/flup/1.0>`_ first, as flup handles the low level
-FastCGI access.
-
-.. seealso::
-
- There is some documentation on `setting up Django with FastCGI
- <https://docs.djangoproject.com/en/dev/howto/deployment/fastcgi/>`_, most of
- which can be reused for other WSGI-compliant frameworks and libraries.
- Only the ``manage.py`` part has to be changed, the example used here can be
- used instead. Django does more or less the exact same thing.
-
-
-mod_wsgi
---------
-
-`mod_wsgi <http://code.google.com/p/modwsgi/>`_ is an attempt to get rid of the
-low level gateways. Given that FastCGI, SCGI, and mod_python are mostly used to
-deploy WSGI applications, mod_wsgi was started to directly embed WSGI applications
-into the Apache web server. mod_wsgi is specifically designed to host WSGI
-applications. It makes the deployment of WSGI applications much easier than
-deployment using other low level methods, which need glue code. The downside
-is that mod_wsgi is limited to the Apache web server; other servers would need
-their own implementations of mod_wsgi.
-
-mod_wsgi supports two modes: embedded mode, in which it integrates with the
-Apache process, and daemon mode, which is more FastCGI-like. Unlike FastCGI,
-mod_wsgi handles the worker-processes by itself, which makes administration
-easier.
-
-
-.. _WSGI:
-
-Step back: WSGI
-===============
-
-WSGI has already been mentioned several times, so it has to be something
-important. In fact it really is, and now it is time to explain it.
-
-The *Web Server Gateway Interface*, or WSGI for short, is defined in
-:pep:`333` and is currently the best way to do Python web programming. While
-it is great for programmers writing frameworks, a normal web developer does not
-need to get in direct contact with it. When choosing a framework for web
-development it is a good idea to choose one which supports WSGI.
-
-The big benefit of WSGI is the unification of the application programming
-interface. When your program is compatible with WSGI -- which at the outer
-level means that the framework you are using has support for WSGI -- your
-program can be deployed via any web server interface for which there are WSGI
-wrappers. You do not need to care about whether the application user uses
-mod_python or FastCGI or mod_wsgi -- with WSGI your application will work on
-any gateway interface. The Python standard library contains its own WSGI
-server, :mod:`wsgiref`, which is a small web server that can be used for
-testing.
-
-A really great WSGI feature is middleware. Middleware is a layer around your
-program which can add various functionality to it. There is quite a bit of
-`middleware <http://www.wsgi.org/en/latest/libraries.html>`_ already
-available. For example, instead of writing your own session management (HTTP
-is a stateless protocol, so to associate multiple HTTP requests with a single
-user your application must create and manage such state via a session), you can
-just download middleware which does that, plug it in, and get on with coding
-the unique parts of your application. The same thing with compression -- there
-is existing middleware which handles compressing your HTML using gzip to save
-on your server's bandwidth. Authentication is another a problem easily solved
-using existing middleware.
-
-Although WSGI may seem complex, the initial phase of learning can be very
-rewarding because WSGI and the associated middleware already have solutions to
-many problems that might arise while developing web sites.
-
-
-WSGI Servers
-------------
-
-The code that is used to connect to various low level gateways like CGI or
-mod_python is called a *WSGI server*. One of these servers is ``flup``, which
-supports FastCGI and SCGI, as well as `AJP
-<http://en.wikipedia.org/wiki/Apache_JServ_Protocol>`_. Some of these servers
-are written in Python, as ``flup`` is, but there also exist others which are
-written in C and can be used as drop-in replacements.
-
-There are many servers already available, so a Python web application
-can be deployed nearly anywhere. This is one big advantage that Python has
-compared with other web technologies.
-
-.. seealso::
-
- A good overview of WSGI-related code can be found in the `WSGI homepage
- <http://www.wsgi.org/en/latest/index.html>`_, which contains an extensive list of `WSGI servers
- <http://www.wsgi.org/en/latest/servers.html>`_ which can be used by *any* application
- supporting WSGI.
-
- You might be interested in some WSGI-supporting modules already contained in
- the standard library, namely:
-
- * :mod:`wsgiref` -- some tiny utilities and servers for WSGI
-
-
-Case study: MoinMoin
---------------------
-
-What does WSGI give the web application developer? Let's take a look at
-an application that's been around for a while, which was written in
-Python without using WSGI.
-
-One of the most widely used wiki software packages is `MoinMoin
-<http://moinmo.in/>`_. It was created in 2000, so it predates WSGI by about
-three years. Older versions needed separate code to run on CGI, mod_python,
-FastCGI and standalone.
-
-It now includes support for WSGI. Using WSGI, it is possible to deploy
-MoinMoin on any WSGI compliant server, with no additional glue code.
-Unlike the pre-WSGI versions, this could include WSGI servers that the
-authors of MoinMoin know nothing about.
-
-
-Model-View-Controller
-=====================
-
-The term *MVC* is often encountered in statements such as "framework *foo*
-supports MVC". MVC is more about the overall organization of code, rather than
-any particular API. Many web frameworks use this model to help the developer
-bring structure to their program. Bigger web applications can have lots of
-code, so it is a good idea to have an effective structure right from the beginning.
-That way, even users of other frameworks (or even other languages, since MVC is
-not Python-specific) can easily understand the code, given that they are
-already familiar with the MVC structure.
-
-MVC stands for three components:
-
-* The *model*. This is the data that will be displayed and modified. In
- Python frameworks, this component is often represented by the classes used by
- an object-relational mapper.
-
-* The *view*. This component's job is to display the data of the model to the
- user. Typically this component is implemented via templates.
-
-* The *controller*. This is the layer between the user and the model. The
- controller reacts to user actions (like opening some specific URL), tells
- the model to modify the data if necessary, and tells the view code what to
- display,
-
-While one might think that MVC is a complex design pattern, in fact it is not.
-It is used in Python because it has turned out to be useful for creating clean,
-maintainable web sites.
-
-.. note::
-
- While not all Python frameworks explicitly support MVC, it is often trivial
- to create a web site which uses the MVC pattern by separating the data logic
- (the model) from the user interaction logic (the controller) and the
- templates (the view). That's why it is important not to write unnecessary
- Python code in the templates -- it works against the MVC model and creates
- chaos in the code base, making it harder to understand and modify.
-
-.. seealso::
-
- The English Wikipedia has an article about the `Model-View-Controller pattern
- <http://en.wikipedia.org/wiki/Model-view-controller>`_. It includes a long
- list of web frameworks for various programming languages.
-
-
-Ingredients for Websites
-========================
-
-Websites are complex constructs, so tools have been created to help web
-developers make their code easier to write and more maintainable. Tools like
-these exist for all web frameworks in all languages. Developers are not forced
-to use these tools, and often there is no "best" tool. It is worth learning
-about the available tools because they can greatly simplify the process of
-developing a web site.
-
-
-.. seealso::
-
- There are far more components than can be presented here. The Python wiki
- has a page about these components, called
- `Web Components <https://wiki.python.org/moin/WebComponents>`_.
-
-
-Templates
----------
-
-Mixing of HTML and Python code is made possible by a few libraries. While
-convenient at first, it leads to horribly unmaintainable code. That's why
-templates exist. Templates are, in the simplest case, just HTML files with
-placeholders. The HTML is sent to the user's browser after filling in the
-placeholders.
-
-Python already includes a way to build simple templates::
-
- # a simple template
- template = "<html><body><h1>Hello {who}!</h1></body></html>"
- print(template.format(who="Reader"))
-
-To generate complex HTML based on non-trivial model data, conditional
-and looping constructs like Python's *for* and *if* are generally needed.
-*Template engines* support templates of this complexity.
-
-There are a lot of template engines available for Python which can be used with
-or without a `framework`_. Some of these define a plain-text programming
-language which is easy to learn, partly because it is limited in scope.
-Others use XML, and the template output is guaranteed to be always be valid
-XML. There are many other variations.
-
-Some `frameworks`_ ship their own template engine or recommend one in
-particular. In the absence of a reason to use a different template engine,
-using the one provided by or recommended by the framework is a good idea.
-
-Popular template engines include:
-
- * `Mako <http://www.makotemplates.org/>`_
- * `Genshi <http://genshi.edgewall.org/>`_
- * `Jinja <http://jinja.pocoo.org/>`_
-
-.. seealso::
-
- There are many template engines competing for attention, because it is
- pretty easy to create them in Python. The page `Templating
- <https://wiki.python.org/moin/Templating>`_ in the wiki lists a big,
- ever-growing number of these. The three listed above are considered "second
- generation" template engines and are a good place to start.
-
-
-Data persistence
-----------------
-
-*Data persistence*, while sounding very complicated, is just about storing data.
-This data might be the text of blog entries, the postings on a bulletin board or
-the text of a wiki page. There are, of course, a number of different ways to store
-information on a web server.
-
-Often, relational database engines like `MySQL <http://www.mysql.com/>`_ or
-`PostgreSQL <http://www.postgresql.org/>`_ are used because of their good
-performance when handling very large databases consisting of millions of
-entries. There is also a small database engine called `SQLite
-<http://www.sqlite.org/>`_, which is bundled with Python in the :mod:`sqlite3`
-module, and which uses only one file. It has no other dependencies. For
-smaller sites SQLite is just enough.
-
-Relational databases are *queried* using a language called `SQL
-<http://en.wikipedia.org/wiki/SQL>`_. Python programmers in general do not
-like SQL too much, as they prefer to work with objects. It is possible to save
-Python objects into a database using a technology called `ORM
-<http://en.wikipedia.org/wiki/Object-relational_mapping>`_ (Object Relational
-Mapping). ORM translates all object-oriented access into SQL code under the
-hood, so the developer does not need to think about it. Most `frameworks`_ use
-ORMs, and it works quite well.
-
-A second possibility is storing data in normal, plain text files (some
-times called "flat files"). This is very easy for simple sites,
-but can be difficult to get right if the web site is performing many
-updates to the stored data.
-
-A third possibility are object oriented databases (also called "object
-databases"). These databases store the object data in a form that closely
-parallels the way the objects are structured in memory during program
-execution. (By contrast, ORMs store the object data as rows of data in tables
-and relations between those rows.) Storing the objects directly has the
-advantage that nearly all objects can be saved in a straightforward way, unlike
-in relational databases where some objects are very hard to represent.
-
-`Frameworks`_ often give hints on which data storage method to choose. It is
-usually a good idea to stick to the data store recommended by the framework
-unless the application has special requirements better satisfied by an
-alternate storage mechanism.
-
-.. seealso::
-
- * `Persistence Tools <https://wiki.python.org/moin/PersistenceTools>`_ lists
- possibilities on how to save data in the file system. Some of these
- modules are part of the standard library
-
- * `Database Programming <https://wiki.python.org/moin/DatabaseProgramming>`_
- helps with choosing a method for saving data
-
- * `SQLAlchemy <http://www.sqlalchemy.org/>`_, the most powerful OR-Mapper
- for Python, and `Elixir <http://elixir.ematia.de/>`_, which makes
- SQLAlchemy easier to use
-
- * `SQLObject <http://www.sqlobject.org/>`_, another popular OR-Mapper
-
- * `ZODB <https://launchpad.net/zodb>`_ and `Durus
- <http://www.mems-exchange.org/software/durus/>`_, two object oriented
- databases
-
-
-.. _framework:
-
-Frameworks
-==========
-
-The process of creating code to run web sites involves writing code to provide
-various services. The code to provide a particular service often works the
-same way regardless of the complexity or purpose of the web site in question.
-Abstracting these common solutions into reusable code produces what are called
-"frameworks" for web development. Perhaps the most well-known framework for
-web development is Ruby on Rails, but Python has its own frameworks. Some of
-these were partly inspired by Rails, or borrowed ideas from Rails, but many
-existed a long time before Rails.
-
-Originally Python web frameworks tended to incorporate all of the services
-needed to develop web sites as a giant, integrated set of tools. No two web
-frameworks were interoperable: a program developed for one could not be
-deployed on a different one without considerable re-engineering work. This led
-to the development of "minimalist" web frameworks that provided just the tools
-to communicate between the Python code and the http protocol, with all other
-services to be added on top via separate components. Some ad hoc standards
-were developed that allowed for limited interoperability between frameworks,
-such as a standard that allowed different template engines to be used
-interchangeably.
-
-Since the advent of WSGI, the Python web framework world has been evolving
-toward interoperability based on the WSGI standard. Now many web frameworks,
-whether "full stack" (providing all the tools one needs to deploy the most
-complex web sites) or minimalist, or anything in between, are built from
-collections of reusable components that can be used with more than one
-framework.
-
-The majority of users will probably want to select a "full stack" framework
-that has an active community. These frameworks tend to be well documented,
-and provide the easiest path to producing a fully functional web site in
-minimal time.
-
-
-Some notable frameworks
------------------------
-
-There are an incredible number of frameworks, so they cannot all be covered
-here. Instead we will briefly touch on some of the most popular.
-
-
-Django
-^^^^^^
-
-`Django <https://www.djangoproject.com/>`_ is a framework consisting of several
-tightly coupled elements which were written from scratch and work together very
-well. It includes an ORM which is quite powerful while being simple to use,
-and has a great online administration interface which makes it possible to edit
-the data in the database with a browser. The template engine is text-based and
-is designed to be usable for page designers who cannot write Python. It
-supports template inheritance and filters (which work like Unix pipes). Django
-has many handy features bundled, such as creation of RSS feeds or generic views,
-which make it possible to create web sites almost without writing any Python code.
-
-It has a big, international community, the members of which have created many
-web sites. There are also a lot of add-on projects which extend Django's normal
-functionality. This is partly due to Django's well written `online
-documentation <https://docs.djangoproject.com/>`_ and the `Django book
-<http://www.djangobook.com/>`_.
-
-
-.. note::
-
- Although Django is an MVC-style framework, it names the elements
- differently, which is described in the `Django FAQ
- <https://docs.djangoproject.com/en/dev/faq/general/#django-appears-to-be-a-mvc-framework-but-you-call-the-controller-the-view-and-the-view-the-template-how-come-you-don-t-use-the-standard-names>`_.
-
-
-TurboGears
-^^^^^^^^^^
-
-Another popular web framework for Python is `TurboGears
-<http://www.turbogears.org/>`_. TurboGears takes the approach of using already
-existing components and combining them with glue code to create a seamless
-experience. TurboGears gives the user flexibility in choosing components. For
-example the ORM and template engine can be changed to use packages different
-from those used by default.
-
-The documentation can be found in the `TurboGears wiki
-<http://docs.turbogears.org/>`_, where links to screencasts can be found.
-TurboGears has also an active user community which can respond to most related
-questions. There is also a `TurboGears book <http://turbogearsbook.com/>`_
-published, which is a good starting point.
-
-The newest version of TurboGears, version 2.0, moves even further in direction
-of WSGI support and a component-based architecture. TurboGears 2 is based on
-the WSGI stack of another popular component-based web framework, `Pylons
-<http://www.pylonsproject.org/>`_.
-
-
-Zope
-^^^^
-
-The Zope framework is one of the "old original" frameworks. Its current
-incarnation in Zope2 is a tightly integrated full-stack framework. One of its
-most interesting feature is its tight integration with a powerful object
-database called the `ZODB <https://launchpad.net/zodb>`_ (Zope Object Database).
-Because of its highly integrated nature, Zope wound up in a somewhat isolated
-ecosystem: code written for Zope wasn't very usable outside of Zope, and
-vice-versa. To solve this problem the Zope 3 effort was started. Zope 3
-re-engineers Zope as a set of more cleanly isolated components. This effort
-was started before the advent of the WSGI standard, but there is WSGI support
-for Zope 3 from the `Repoze <http://repoze.org/>`_ project. Zope components
-have many years of production use behind them, and the Zope 3 project gives
-access to these components to the wider Python community. There is even a
-separate framework based on the Zope components: `Grok
-<http://grok.zope.org/>`_.
-
-Zope is also the infrastructure used by the `Plone <https://plone.org/>`_ content
-management system, one of the most powerful and popular content management
-systems available.
-
-
-Other notable frameworks
-^^^^^^^^^^^^^^^^^^^^^^^^
-
-Of course these are not the only frameworks that are available. There are
-many other frameworks worth mentioning.
-
-Another framework that's already been mentioned is `Pylons`_. Pylons is much
-like TurboGears, but with an even stronger emphasis on flexibility, which comes
-at the cost of being more difficult to use. Nearly every component can be
-exchanged, which makes it necessary to use the documentation of every single
-component, of which there are many. Pylons builds upon `Paste
-<http://pythonpaste.org/>`_, an extensive set of tools which are handy for WSGI.
-
-And that's still not everything. The most up-to-date information can always be
-found in the Python wiki.
-
-.. seealso::
-
- The Python wiki contains an extensive list of `web frameworks
- <https://wiki.python.org/moin/WebFrameworks>`_.
-
- Most frameworks also have their own mailing lists and IRC channels, look out
- for these on the projects' web sites.
.. TODO: Fill in XXX comments
+.. seealso::
+
+ :ref:`installing-index`
+ The up to date module installation documentations
+
.. The audience for this document includes people who don't know anything
about Python and aren't about to learn the language just in order to
install and maintain it for their users, i.e. system administrators.
run, they will use the values in the config file.)
You can find out the complete list of options for any command using the
-:option:`--help` option, e.g.::
+:option:`!--help` option, e.g.::
python setup.py build --help
and you can find out the complete list of global options by using
-:option:`--help` without a command::
+:option:`!--help` without a command::
python setup.py --help
to be in Objective C.
* *cpparg* is an argument for the C preprocessor, and is anything starting with
- :option:`-I`, :option:`-D`, :option:`-U` or :option:`-C`.
+ :option:`!-I`, :option:`-D`, :option:`!-U` or :option:`-C`.
* *library* is anything ending in :file:`.a` or beginning with :option:`-l` or
:option:`-L`.
.. seealso::
- `C++Builder Compiler <http://www.embarcadero.com/downloads>`_
+ `C++Builder Compiler <https://www.embarcadero.com/products>`_
Information about the free C++ compiler from Borland, including links to the
download pages.
for Borland's C++, because there is no program to convert the library. First
you have to create a list of symbols which the Python DLL exports. (You can find
a good program for this task at
-http://sourceforge.net/projects/mingw/files/MinGW/Extension/pexports/).
+https://sourceforge.net/projects/mingw/files/MinGW/Extension/pexports/).
.. I don't understand what the next line means. --amk
.. (inclusive the references on data structures.)
.. [#] This also means you could replace all existing COFF-libraries with OMF-libraries
of the same name.
-.. [#] Check http://www.sourceware.org/cygwin/ and http://www.mingw.org/ for more
+.. [#] Check https://www.sourceware.org/cygwin/ and http://www.mingw.org/ for more
information
.. [#] Then you have no POSIX emulation available, but you also don't need
repository of open source licensed packages made available for use by
other Python users
* the `Python Packaging Authority
- <https://packaging.python.org/en/latest/future.html>`__ are the group of
+ <https://www.pypa.io/en/latest/>`__ are the group of
developers and documentation authors responsible for the maintenance and
evolution of the standard packaging tools and the associated metadata and
file format standards. They maintain a variety of tools, documentation
Python.
It's also possible to specify an exact or minimum version directly on the
-command line::
+command line. When using comparator operators such as ``>``, ``<`` or some other
+special character which get interpreted by shell, the package name and the
+version should be enclosed within double quotes::
python -m pip install SomePackage==1.0.4 # specific version
- python -m pip install 'SomePackage>=1.0.4' # minimum version
+ python -m pip install "SomePackage>=1.0.4" # minimum version
Normally, if a suitable module is already installed, attempting to install
it again will have no effect. Upgrading existing modules must be requested
.. seealso::
`Python Packaging User Guide: Installing Python Distribution Packages
- <https://packaging.python.org/en/latest/installing.html#installing-python-distribution-packages>`__
+ <https://packaging.python.org/en/latest/installing/>`__
How do I ...?
.. seealso::
- `Python Packaging User Guide: Setup for Installing Distribution Packages
- <https://packaging.python.org/en/latest/installing.html#setup-for-installing-distribution-packages>`__
+ `Python Packaging User Guide: Requirements for Installing Packages
+ <https://packaging.python.org/en/latest/installing/#requirements-for-installing-packages>`__
.. installing-per-user-installation:
aren't currently easy to install using ``pip`` directly. At this point in
time, it will often be easier for users to install these packages by
`other means
-<https://packaging.python.org/en/latest/science.html>`__
+<https://packaging.python.org/en/latest/science/>`__
rather than attempting to install them with ``pip``.
.. seealso::
`Python Packaging User Guide: Installing Scientific Packages
- <https://packaging.python.org/en/latest/science.html>`__
+ <https://packaging.python.org/en/latest/science/>`__
... work with multiple versions of Python installed in parallel?
Once the Development & Deployment part of PPUG is fleshed out, some of
those sections should be linked from new questions here (most notably,
we should have a question about avoiding depending on PyPI that links to
- https://packaging.python.org/en/latest/deployment.html#pypi-mirrors-and-caches)
+ https://packaging.python.org/en/latest/mirrors/)
Common installation issues
than needing to build them themselves.
Some of the solutions for installing `scientific software
-<https://packaging.python.org/en/latest/science.html>`__
+<https://packaging.python.org/en/latest/science/>`__
that is not yet available as pre-built ``wheel`` files may also help with
obtaining other binary extensions without needing to build them locally.
.. seealso::
`Python Packaging User Guide: Binary Extensions
- <https://packaging.python.org/en/latest/extensions.html>`__
+ <https://packaging.python.org/en/latest/extensions/>`__
By default, 2to3 runs a set of :ref:`predefined fixers <2to3-fixers>`. The
:option:`-l` flag lists all available fixers. An explicit set of fixers to run
-can be given with :option:`-f`. Likewise the :option:`-x` explicitly disables a
+can be given with :option:`-f`. Likewise the :option:`!-x` explicitly disables a
fixer. The following example runs only the ``imports`` and ``has_key`` fixers::
$ 2to3 -f imports -f has_key example.py
beneath the diff for a file. You should address the warning in order to have
compliant 3.x code.
-2to3 can also refactor doctests. To enable this mode, use the :option:`-d`
+2to3 can also refactor doctests. To enable this mode, use the :option:`!-d`
flag. Note that *only* doctests will be refactored. This also doesn't require
the module to be valid Python. For example, doctest like examples in a reST
document could also be refactored with this option.
-The :option:`-v` option enables output of more information on the translation
+The :option:`!-v` option enables output of more information on the translation
process.
Since some print statements can be parsed as function calls or statements, 2to3
.. versionadded:: 3.2.3
The :option:`-o` option was added.
-The :option:`-W` or :option:`--write-unchanged-files` flag tells 2to3 to always
+The :option:`!-W` or :option:`--write-unchanged-files` flag tells 2to3 to always
write output files even if no changes were required to the file. This is most
useful with :option:`-o` so that an entire Python source tree is copied with
translation from one directory to another.
This option implies the :option:`-w` flag as it would not make sense otherwise.
.. versionadded:: 3.2.3
- The :option:`-W` flag was added.
+ The :option:`!-W` flag was added.
The :option:`--add-suffix` option specifies a string to append to all output
filenames. The :option:`-n` flag is required when specifying this as backups
.. module:: lib2to3
:synopsis: the 2to3 library
+
.. moduleauthor:: Guido van Rossum
.. moduleauthor:: Collin Winter
.. moduleauthor:: Benjamin Peterson <benjamin@python.org>
+**Source code:** :source:`Lib/lib2to3/`
+
+--------------
.. note::
.. module:: __main__
:synopsis: The environment where the top-level script is run.
+--------------
+
``'__main__'`` is the name of the scope in which top-level code executes.
A module's __name__ is set equal to ``'__main__'`` when read from
standard input, a script, or from an interactive prompt.
.. module:: _thread
:synopsis: Low-level threading API.
-
.. index::
single: light-weight processes
single: processes, light-weight
single: binary semaphores
single: semaphores, binary
+--------------
+
This module provides low-level primitives for working with multiple threads
(also called :dfn:`light-weight processes` or :dfn:`tasks`) --- multiple threads of
control sharing their global data space. For synchronization, simple locks
.. module:: abc
:synopsis: Abstract base classes according to PEP 3119.
+
.. moduleauthor:: Guido van Rossum
.. sectionauthor:: Georg Brandl
.. much of the content adapted from docstrings
.. module:: aifc
:synopsis: Read and write audio files in AIFF or AIFC format.
+**Source code:** :source:`Lib/aifc.py`
.. index::
single: Audio Interchange File Format
single: AIFF
single: AIFF-C
-**Source code:** :source:`Lib/aifc.py`
-
--------------
This module provides support for reading and writing AIFF and AIFF-C files.
.. module:: argparse
:synopsis: Command-line option and argument parsing library.
+
.. moduleauthor:: Steven Bethard <steven.bethard@gmail.com>
.. sectionauthor:: Steven Bethard <steven.bethard@gmail.com>
parser = argparse.ArgumentParser(description='Process some integers.')
parser.add_argument('integers', metavar='N', type=int, nargs='+',
- help='an integer for the accumulator')
+ help='an integer for the accumulator')
parser.add_argument('--sum', dest='accumulate', action='store_const',
- const=sum, default=max,
- help='sum the integers (default: find the max)')
+ const=sum, default=max,
+ help='sum the integers (default: find the max)')
args = parser.parse_args()
print(args.accumulate(args.integers))
arguments they contain. For example::
>>> with open('args.txt', 'w') as fp:
- ... fp.write('-f\nbar')
+ ... fp.write('-f\nbar')
>>> parser = argparse.ArgumentParser(fromfile_prefix_chars='@')
>>> parser.add_argument('-f')
>>> parser.parse_args(['-f', 'foo', '@args.txt'])
Namespace(foo='1')
* ``'store_const'`` - This stores the value specified by the const_ keyword
- argument. (Note that the const_ keyword argument defaults to the rather
- unhelpful ``None``.) The ``'store_const'`` action is most commonly used with
+ argument. The ``'store_const'`` action is most commonly used with
optional arguments that specify some sort of flag. For example::
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo', action='store_const', const=42)
- >>> parser.parse_args('--foo'.split())
+ >>> parser.parse_args(['--foo'])
Namespace(foo=42)
-* ``'store_true'`` and ``'store_false'`` - These store the values ``True`` and
- ``False`` respectively. These are special cases of ``'store_const'``. For
- example::
+* ``'store_true'`` and ``'store_false'`` - These are special cases of
+ ``'store_const'`` used for storing the values ``True`` and ``False``
+ respectively. In addition, they create default values of ``False`` and
+ ``True`` respectively. For example::
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo', action='store_true')
>>> parser.add_argument('--bar', action='store_false')
+ >>> parser.add_argument('--baz', action='store_false')
>>> parser.parse_args('--foo --bar'.split())
- Namespace(bar=False, foo=True)
+ Namespace(foo=True, bar=False, baz=True)
* ``'append'`` - This stores a list, and appends each argument value to the
list. This is useful to allow an option to be specified multiple times.
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--verbose', '-v', action='count')
- >>> parser.parse_args('-vvv'.split())
+ >>> parser.parse_args(['-vvv'])
Namespace(verbose=3)
* ``'help'`` - This prints a complete help message for all the options in the
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo', nargs='?', const='c', default='d')
>>> parser.add_argument('bar', nargs='?', default='d')
- >>> parser.parse_args('XX --foo YY'.split())
+ >>> parser.parse_args(['XX', '--foo', 'YY'])
Namespace(bar='XX', foo='YY')
- >>> parser.parse_args('XX --foo'.split())
+ >>> parser.parse_args(['XX', '--foo'])
Namespace(bar='XX', foo='c')
- >>> parser.parse_args(''.split())
+ >>> parser.parse_args([])
Namespace(bar='d', foo='d')
One of the more common uses of ``nargs='?'`` is to allow optional input and
>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('foo', nargs='+')
- >>> parser.parse_args('a b'.split())
+ >>> parser.parse_args(['a', 'b'])
Namespace(foo=['a', 'b'])
- >>> parser.parse_args(''.split())
+ >>> parser.parse_args([])
usage: PROG [-h] foo [foo ...]
PROG: error: too few arguments
command-line argument following it, the value of ``const`` will be assumed instead.
See the nargs_ description for examples.
-The ``const`` keyword argument defaults to ``None``.
+With the ``'store_const'`` and ``'append_const'`` actions, the ``const``
+keyword argument must be given. For other actions, it defaults to ``None``.
default
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo', default=42)
- >>> parser.parse_args('--foo 2'.split())
+ >>> parser.parse_args(['--foo', '2'])
Namespace(foo='2')
- >>> parser.parse_args(''.split())
+ >>> parser.parse_args([])
Namespace(foo=42)
If the ``default`` value is a string, the parser parses the value as if it
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('foo', nargs='?', default=42)
- >>> parser.parse_args('a'.split())
+ >>> parser.parse_args(['a'])
Namespace(foo='a')
- >>> parser.parse_args(''.split())
+ >>> parser.parse_args([])
Namespace(foo=42)
...
>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('foo', type=perfect_square)
- >>> parser.parse_args('9'.split())
+ >>> parser.parse_args(['9'])
Namespace(foo=9)
- >>> parser.parse_args('7'.split())
+ >>> parser.parse_args(['7'])
usage: PROG [-h] foo
PROG: error: argument foo: '7' is not a perfect square
>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('foo', type=int, choices=range(5, 10))
- >>> parser.parse_args('7'.split())
+ >>> parser.parse_args(['7'])
Namespace(foo=7)
- >>> parser.parse_args('11'.split())
+ >>> parser.parse_args(['11'])
usage: PROG [-h] {5,6,7,8,9}
PROG: error: argument foo: invalid choice: 11 (choose from 5, 6, 7, 8, 9)
>>> parser = argparse.ArgumentParser(prog='frobble')
>>> parser.add_argument('--foo', action='store_true',
- ... help='foo the bars before frobbling')
+ ... help='foo the bars before frobbling')
>>> parser.add_argument('bar', nargs='+',
- ... help='one of the bars to be frobbled')
- >>> parser.parse_args('-h'.split())
+ ... help='one of the bars to be frobbled')
+ >>> parser.parse_args(['-h'])
usage: frobble [-h] [--foo] bar [bar ...]
positional arguments:
>>> parser = argparse.ArgumentParser(prog='frobble')
>>> parser.add_argument('bar', nargs='?', type=int, default=42,
- ... help='the bar to %(prog)s (default: %(default)s)')
+ ... help='the bar to %(prog)s (default: %(default)s)')
>>> parser.print_help()
usage: frobble [-h] [bar]
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('bar')
- >>> parser.parse_args('XXX'.split())
+ >>> parser.parse_args(['XXX'])
Namespace(bar='XXX')
For optional argument actions, the value of ``dest`` is normally inferred from
>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('-x')
>>> parser.add_argument('--foo')
- >>> parser.parse_args('-x X'.split())
+ >>> parser.parse_args(['-x', 'X'])
Namespace(foo=None, x='X')
- >>> parser.parse_args('--foo FOO'.split())
+ >>> parser.parse_args(['--foo', 'FOO'])
Namespace(foo='FOO', x=None)
For long options (options with names longer than a single character), the option
and value can also be passed as a single command-line argument, using ``=`` to
separate them::
- >>> parser.parse_args('--foo=FOO'.split())
+ >>> parser.parse_args(['--foo=FOO'])
Namespace(foo='FOO', x=None)
For short options (options only one character long), the option and its value
can be concatenated::
- >>> parser.parse_args('-xX'.split())
+ >>> parser.parse_args(['-xX'])
Namespace(foo=None, x='X')
Several short options can be joined together, using only a single ``-`` prefix,
>>> parser.add_argument('-x', action='store_true')
>>> parser.add_argument('-y', action='store_true')
>>> parser.add_argument('-z')
- >>> parser.parse_args('-xyzZ'.split())
+ >>> parser.parse_args(['-xyzZ'])
Namespace(x=True, y=True, z='Z')
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument(
... 'integers', metavar='int', type=int, choices=range(10),
- ... nargs='+', help='an integer in the range 0..9')
+ ... nargs='+', help='an integer in the range 0..9')
>>> parser.add_argument(
... '--sum', dest='accumulate', action='store_const', const=sum,
- ... default=max, help='sum the integers (default: find the max)')
+ ... default=max, help='sum the integers (default: find the max)')
>>> parser.parse_args(['1', '2', '3', '4'])
Namespace(accumulate=<built-in function max>, integers=[1, 2, 3, 4])
- >>> parser.parse_args('1 2 3 4 --sum'.split())
+ >>> parser.parse_args(['1', '2', '3', '4', '--sum'])
Namespace(accumulate=<built-in function sum>, integers=[1, 2, 3, 4])
.. module:: array
:synopsis: Space efficient arrays of uniformly typed numeric values.
-
.. index:: single: arrays
+--------------
+
This module defines an object type which can compactly represent an array of
basic values: characters, integers, floating point numbers. Arrays are sequence
types and behave very much like lists, except that the type of objects stored in
concatenation, and multiplication. When using slice assignment, the assigned
value must be an array object with the same type code; in all other cases,
:exc:`TypeError` is raised. Array objects also implement the buffer interface,
-and may be used wherever :term:`bytes-like object`\ s are supported.
+and may be used wherever :term:`bytes-like objects <bytes-like object>` are supported.
The following data items and methods are also supported:
Packing and unpacking of External Data Representation (XDR) data as used in some
remote procedure call systems.
- `The Numerical Python Documentation <http://docs.scipy.org/doc/>`_
+ `The Numerical Python Documentation <https://docs.scipy.org/doc/>`_
The Numeric Python extension (NumPy) defines another array type; see
http://www.numpy.org/ for further information about Numerical Python.
wanted *annotate_fields* must be set to ``False``. Attributes such as line
numbers and column offsets are not dumped by default. If this is wanted,
*include_attributes* can be set to ``True``.
+
+.. seealso::
+
+ `Green Tree Snakes <https://greentreesnakes.readthedocs.org/>`_, an external documentation resource, has good
+ details on working with Python ASTs.
.. module:: asynchat
:synopsis: Support for asynchronous command/response protocols.
+
.. moduleauthor:: Sam Rushing <rushing@nightmare.com>
.. sectionauthor:: Steve Holden <sholden@holdenweb.com>
self.set_terminator(None)
self.handle_request()
elif not self.handling:
- self.set_terminator(None) # browsers sometimes over-send
+ self.set_terminator(None) # browsers sometimes over-send
self.cgi_data = parse(self.headers, b"".join(self.ibuffer))
self.handling = True
self.ibuffer = []
The :func:`asyncio.sleep` function.
+Futures
+-------
+
+.. method:: BaseEventLoop.create_future()
+
+ Create an :class:`asyncio.Future` object attached to the loop.
+
+ This is a preferred way to create futures in asyncio, as event
+ loop implementations can provide alternative implementations
+ of the Future class (with better performance or instrumentation).
+
+ .. versionadded:: 3.5.2
+
+
Tasks
-----
a class. For example, if you want to use a pre-created
protocol instance, you can pass ``lambda: my_protocol``.
- Options allowing to change how the connection is created:
+ Options that change how the connection is created:
* *ssl*: if given and not false, a SSL/TLS transport is created
(by default a plain TCP transport is created). If *ssl* is
.. coroutinemethod:: BaseEventLoop.sock_recv(sock, nbytes)
- Receive data from the socket. The return value is a bytes object
+ Receive data from the socket. Modeled after blocking
+ :meth:`socket.socket.recv` method.
+
+ The return value is a bytes object
representing the data received. The maximum amount of data to be received
at once is specified by *nbytes*.
This method is a :ref:`coroutine <coroutine>`.
- .. seealso::
-
- The :meth:`socket.socket.recv` method.
-
.. coroutinemethod:: BaseEventLoop.sock_sendall(sock, data)
- Send data to the socket. The socket must be connected to a remote socket.
+ Send data to the socket. Modeled after blocking
+ :meth:`socket.socket.sendall` method.
+
+ The socket must be connected to a remote socket.
This method continues to send data from *data* until either all data has
been sent or an error occurs. ``None`` is returned on success. On error,
an exception is raised, and there is no way to determine how much data, if
This method is a :ref:`coroutine <coroutine>`.
- .. seealso::
-
- The :meth:`socket.socket.sendall` method.
-
.. coroutinemethod:: BaseEventLoop.sock_connect(sock, address)
- Connect to a remote socket at *address*.
-
- The *address* must be already resolved to avoid the trap of hanging the
- entire event loop when the address requires doing a DNS lookup. For
- example, it must be an IP address, not an hostname, for
- :py:data:`~socket.AF_INET` and :py:data:`~socket.AF_INET6` address families.
- Use :meth:`getaddrinfo` to resolve the hostname asynchronously.
+ Connect to a remote socket at *address*. Modeled after
+ blocking :meth:`socket.socket.connect` method.
With :class:`SelectorEventLoop` event loop, the socket *sock* must be
non-blocking.
This method is a :ref:`coroutine <coroutine>`.
+ .. versionchanged:: 3.5.2
+ ``address`` no longer needs to be resolved. ``sock_connect``
+ will try to check if the *address* is already resolved by calling
+ :func:`socket.inet_pton`. If not,
+ :meth:`BaseEventLoop.getaddrinfo` will be used to resolve the
+ *address*.
+
.. seealso::
- The :meth:`BaseEventLoop.create_connection` method, the
- :func:`open_connection` function and the :meth:`socket.socket.connect`
- method.
+ :meth:`BaseEventLoop.create_connection`
+ and :func:`asyncio.open_connection() <open_connection>`.
.. coroutinemethod:: BaseEventLoop.sock_accept(sock)
- Accept a connection. The socket must be bound to an address and listening
+ Accept a connection. Modeled after blocking
+ :meth:`socket.socket.accept`.
+
+ The socket must be bound to an address and listening
for connections. The return value is a pair ``(conn, address)`` where *conn*
is a *new* socket object usable to send and receive data on the connection,
and *address* is the address bound to the socket on the other end of the
.. seealso::
- The :meth:`BaseEventLoop.create_server` method, the :func:`start_server`
- function and the :meth:`socket.socket.accept` method.
+ :meth:`BaseEventLoop.create_server` and :func:`start_server`.
Resolve host name
Error Handling API
------------------
-Allows to customize how exceptions are handled in the event loop.
+Allows customizing how exceptions are handled in the event loop.
.. method:: BaseEventLoop.set_exception_handler(handler)
will be a ``dict`` object (see :meth:`call_exception_handler`
documentation for details about context).
+.. method:: BaseEventLoop.get_exception_handler()
+
+ Return the exception handler, or ``None`` if the default one
+ is in use.
+
+ .. versionadded:: 3.5.2
+
.. method:: BaseEventLoop.default_exception_handler(context)
Default exception handler.
Stop serving: close listening sockets and set the :attr:`sockets`
attribute to ``None``.
- The sockets that represent existing incoming client connections are
- leaved open.
+ The sockets that represent existing incoming client connections are left
+ open.
- The server is closed asynchonously, use the :meth:`wait_closed` coroutine
- to wait until the server is closed.
+ The server is closed asynchronously, use the :meth:`wait_closed`
+ coroutine to wait until the server is closed.
.. coroutinemethod:: wait_closed()
On Windows, only sockets are supported (ex: pipes are not supported):
see the `MSDN documentation of select
- <http://msdn.microsoft.com/en-us/library/windows/desktop/ms740141%28v=vs.85%29.aspx>`_.
+ <https://msdn.microsoft.com/en-us/library/windows/desktop/ms740141%28v=vs.85%29.aspx>`_.
.. class:: ProactorEventLoop
.. seealso::
`MSDN documentation on I/O Completion Ports
- <http://msdn.microsoft.com/en-us/library/windows/desktop/aa365198%28v=vs.85%29.aspx>`_.
+ <https://msdn.microsoft.com/en-us/library/windows/desktop/aa365198%28v=vs.85%29.aspx>`_.
Example to use a :class:`ProactorEventLoop` on Windows::
The resolution of the monotonic clock on Windows is usually around 15.6 msec.
The best resolution is 0.5 msec. The resolution depends on the hardware
(availability of `HPET
-<http://fr.wikipedia.org/wiki/High_Precision_Event_Timer>`_) and on the Windows
+<https://en.wikipedia.org/wiki/High_Precision_Event_Timer>`_) and on the Windows
configuration. See :ref:`asyncio delayed calls <asyncio-delayed-calls>`.
.. versionchanged:: 3.5
.. currentmodule:: asyncio
-+++++++++++++++++++++++++++++++++++++++++
-Transports and protocols (low-level API)
-+++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++
+Transports and protocols (callback based API)
+++++++++++++++++++++++++++++++++++++++++++++++
.. _asyncio-transport:
.. _asyncio-streams:
-++++++++++++++++++++++++
-Streams (high-level API)
-++++++++++++++++++++++++
++++++++++++++++++++++++++++++
+Streams (coroutine based API)
++++++++++++++++++++++++++++++
Stream functions
================
.. note::
- The top-level functions in this module are meant convenience wrappers
+ The top-level functions in this module are meant as convenience wrappers
only; there's really nothing special there, and if they don't do
exactly what you want, feel free to copy their code.
This method is a :ref:`coroutine <coroutine>`.
+ .. coroutinemethod:: readuntil(separator=b'\n')
+
+ Read data from the stream until ``separator`` is found.
+
+ On success, the data and separator will be removed from the
+ internal buffer (consumed). Returned data will include the
+ separator at the end.
+
+ Configured stream limit is used to check result. Limit sets the
+ maximal length of data that can be returned, not counting the
+ separator.
+
+ If an EOF occurs and the complete separator is still not found,
+ an :exc:`IncompleteReadError` exception will be
+ raised, and the internal buffer will be reset. The
+ :attr:`IncompleteReadError.partial` attribute may contain the
+ separator partially.
+
+ If the data cannot be read because of over limit, a
+ :exc:`LimitOverrunError` exception will be raised, and the data
+ will be left in the internal buffer, so it can be read again.
+
+ .. versionadded:: 3.5.2
+
.. method:: at_eof()
Return ``True`` if the buffer is empty and :meth:`feed_eof` was called.
.. class:: StreamReaderProtocol(stream_reader, client_connected_cb=None, loop=None)
Trivial helper class to adapt between :class:`Protocol` and
- :class:`StreamReader`. Sublclass of :class:`Protocol`.
+ :class:`StreamReader`. Subclass of :class:`Protocol`.
*stream_reader* is a :class:`StreamReader` instance, *client_connected_cb*
is an optional function called with (stream_reader, stream_writer) when a
Read bytes string before the end of stream was reached (:class:`bytes`).
+LimitOverrunError
+=================
+
+.. exception:: LimitOverrunError
+
+ Reached the buffer limit while looking for a separator.
+
+ .. attribute:: consumed
+
+ Total number of to be consumed bytes.
+
+
Stream examples
===============
It is the application's responsibility to ensure that all whitespace and
metacharacters are quoted appropriately to avoid `shell injection
- <http://en.wikipedia.org/wiki/Shell_injection#Shell_injection>`_
+ <https://en.wikipedia.org/wiki/Shell_injection#Shell_injection>`_
vulnerabilities. The :func:`shlex.quote` function can be used to properly
escape whitespace and shell metacharacters in strings that are going to be
used to construct shell commands.
It is the application's responsibility to ensure that all whitespace and
metacharacters are quoted appropriately to avoid `shell injection
- <http://en.wikipedia.org/wiki/Shell_injection#Shell_injection>`_
+ <https://en.wikipedia.org/wiki/Shell_injection#Shell_injection>`_
vulnerabilities. The :func:`shlex.quote` function can be used to properly
escape whitespace and shell metacharacters in strings that are going to be
used to construct shell commands.
:meth:`acquire` is a coroutine and should be called with ``yield from``.
Locks also support the context management protocol. ``(yield from lock)``
- should be used as context manager expression.
+ should be used as the context manager expression.
This class is :ref:`not thread safe <asyncio-multithreading>`.
lock = Lock()
...
with (yield from lock):
- ...
+ ...
Lock objects can be tested for locking state::
if not lock.locked():
- yield from lock
+ yield from lock
else:
- # lock is acquired
+ # lock is acquired
...
.. method:: locked()
running in different threads. While a task waits for the completion of a
future, the event loop executes a new task.
- The cancellation of a task is different from the cancelation of a future. Calling
- :meth:`cancel` will throw a :exc:`~concurrent.futures.CancelledError` to the
- wrapped coroutine. :meth:`~Future.cancelled` only returns ``True`` if the
+ The cancellation of a task is different from the cancelation of a
+ future. Calling :meth:`cancel` will throw a
+ :exc:`~concurrent.futures.CancelledError` to the wrapped
+ coroutine. :meth:`~Future.cancelled` only returns ``True`` if the
wrapped coroutine did not catch the
:exc:`~concurrent.futures.CancelledError` exception, or raised a
:exc:`~concurrent.futures.CancelledError` exception.
Return the list of stack frames for this task's coroutine.
- If the coroutine is not done, this returns the stack where it is suspended.
- If the coroutine has completed successfully or was cancelled, this
- returns an empty list. If the coroutine was terminated by an exception,
- this returns the list of traceback frames.
+ If the coroutine is not done, this returns the stack where it is
+ suspended. If the coroutine has completed successfully or was
+ cancelled, this returns an empty list. If the coroutine was
+ terminated by an exception, this returns the list of traceback
+ frames.
The frames are always ordered from oldest to newest.
.. note::
- In the functions below, the optional *loop* argument allows to explicitly set
+ In the functions below, the optional *loop* argument allows explicitly setting
the event loop object used by the underlying task or coroutine. If it's
not provided, the default event loop is used.
.. versionadded:: 3.4.4
+ .. versionchanged:: 3.5.1
+ The function accepts any :term:`awaitable` object.
+
.. seealso::
The :meth:`BaseEventLoop.create_task` method.
<coroutine>`, which may be a decorated generator function or an
:keyword:`async def` function.
+.. function:: run_coroutine_threadsafe(coro, loop)
+
+ Submit a :ref:`coroutine object <coroutine>` to a given event loop.
+
+ Return a :class:`concurrent.futures.Future` to access the result.
+
+ This function is meant to be called from a different thread than the one
+ where the event loop is running. Usage::
+
+ # Create a coroutine
+ coro = asyncio.sleep(1, result=3)
+ # Submit the coroutine to a given loop
+ future = asyncio.run_coroutine_threadsafe(coro, loop)
+ # Wait for the result with an optional timeout argument
+ assert future.result(timeout) == 3
+
+ If an exception is raised in the coroutine, the returned future will be
+ notified. It can also be used to cancel the task in the event loop::
+
+ try:
+ result = future.result(timeout)
+ except asyncio.TimeoutError:
+ print('The coroutine took too long, cancelling the task...')
+ future.cancel()
+ except Exception as exc:
+ print('The coroutine raised an exception: {!r}'.format(exc))
+ else:
+ print('The coroutine returned: {!r}'.format(result))
+
+ See the :ref:`concurrency and multithreading <asyncio-multithreading>`
+ section of the documentation.
+
+ .. note::
+
+ Unlike other functions from the module,
+ :func:`run_coroutine_threadsafe` requires the *loop* argument to
+ be passed explicitly.
+
+ .. versionadded:: 3.5.1
+
.. coroutinefunction:: sleep(delay, result=None, \*, loop=None)
Create a :ref:`coroutine <coroutine>` that completes after a given
except CancelledError:
res = None
-.. coroutinefunction:: wait(futures, \*, loop=None, timeout=None, return_when=ALL_COMPLETED)
+
+.. coroutinefunction:: wait(futures, \*, loop=None, timeout=None,\
+ return_when=ALL_COMPLETED)
Wait for the Futures and coroutine objects given by the sequence *futures*
to complete. Coroutines will be wrapped in Tasks. Returns two sets of
.. versionchanged:: 3.4.3
If the wait is cancelled, the future *fut* is now also cancelled.
-
-
-.. function:: run_coroutine_threadsafe(coro, loop)
-
- Submit a :ref:`coroutine object <coroutine>` to a given event loop.
-
- Return a :class:`concurrent.futures.Future` to access the result.
-
- This function is meant to be called from a different thread than the one
- where the event loop is running. Usage::
-
- # Create a coroutine
- coro = asyncio.sleep(1, result=3)
- # Submit the coroutine to a given loop
- future = asyncio.run_coroutine_threadsafe(coro, loop)
- # Wait for the result with an optional timeout argument
- assert future.result(timeout) == 3
-
- If an exception is raised in the coroutine, the returned future will be
- notified. It can also be used to cancel the task in the event loop::
-
- try:
- result = future.result(timeout)
- except asyncio.TimeoutError:
- print('The coroutine took too long, cancelling the task...')
- future.cancel()
- except Exception as exc:
- print('The coroutine raised an exception: {!r}'.format(exc))
- else:
- print('The coroutine returned: {!r}'.format(result))
-
- See the :ref:`concurrency and multithreading <asyncio-multithreading>`
- section of the documentation.
-
- .. note::
-
- Unlike the functions above, :func:`run_coroutine_threadsafe` requires the
- *loop* argument to be passed explicitely.
-
- .. versionadded:: 3.4.4, 3.5.1
.. module:: asyncio
:synopsis: Asynchronous I/O, event loop, coroutines and tasks.
+.. versionadded:: 3.4
+
+**Source code:** :source:`Lib/asyncio/`
+
.. note::
The asyncio package has been included in the standard library on a
changes (up to and including removal of the module) may occur if deemed
necessary by the core developers.
-.. versionadded:: 3.4
-
-**Source code:** :source:`Lib/asyncio/`
-
--------------
This module provides infrastructure for writing single-threaded concurrent
.. module:: asyncore
:synopsis: A base class for developing asynchronous socket handling
services.
+
.. moduleauthor:: Sam Rushing <rushing@nightmare.com>
.. sectionauthor:: Christopher Petrilli <petrilli@amber.org>
.. sectionauthor:: Steve Holden <sholden@holdenweb.com>
self.buffer = self.buffer[sent:]
- client = HTTPClient('www.python.org', '/')
- asyncore.loop()
+ client = HTTPClient('www.python.org', '/')
+ asyncore.loop()
.. _asyncore-example-2:
.. module:: atexit
:synopsis: Register and execute cleanup functions.
+
.. moduleauthor:: Skip Montanaro <skip@pobox.com>
.. sectionauthor:: Skip Montanaro <skip@pobox.com>
+--------------
The :mod:`atexit` module defines functions to register and unregister cleanup
functions. Functions thus registered are automatically executed upon normal
.. module:: audioop
:synopsis: Manipulate raw audio data.
+--------------
The :mod:`audioop` module contains some useful operations on sound fragments.
It operates on sound fragments consisting of signed integer samples 8, 16, 24
-or 32 bits wide, stored in :term:`bytes-like object`\ s. All scalar items are
+or 32 bits wide, stored in :term:`bytes-like objects <bytes-like object>`. All scalar items are
integers, unless specified otherwise.
.. versionchanged:: 3.4
# out_test)
prefill = '\0'*(pos+ipos)*2
postfill = '\0'*(len(inputdata)-len(prefill)-len(outputdata))
- outputdata = prefill + audioop.mul(outputdata,2,-factor) + postfill
+ outputdata = prefill + audioop.mul(outputdata, 2, -factor) + postfill
return audioop.add(inputdata, outputdata, 2)
:synopsis: RFC 3548: Base16, Base32, Base64 Data Encodings;
Base85 and Ascii85
+**Source code:** :source:`Lib/base64.py`
.. index::
pair: base64; encoding
single: MIME; base64 encoding
+--------------
+
This module provides functions for encoding binary data to printable
ASCII characters and decoding such encodings back to binary data.
It provides encoding and decoding functions for the encodings specified in
POST request. The encoding algorithm is not the same as the
:program:`uuencode` program.
-There are two :rfc:`3548` interfaces provided by this module. The modern
-interface supports encoding and decoding ASCII byte string objects using all
-three :rfc:`3548` defined alphabets (normal, URL-safe, and filesystem-safe).
-Additionally, the decoding functions of the modern interface also accept
-Unicode strings containing only ASCII characters. The legacy interface provides
-for encoding and decoding to and from file-like objects as well as byte
-strings, but only using the Base64 standard alphabet.
+There are two interfaces provided by this module. The modern interface
+supports encoding :term:`bytes-like objects <bytes-like object>` to ASCII
+:class:`bytes`, and decoding :term:`bytes-like objects <bytes-like object>` or
+strings containing ASCII to :class:`bytes`. Both base-64 alphabets
+defined in :rfc:`3548` (normal, and URL- and filesystem-safe) are supported.
+
+The legacy interface does not support decoding from strings, but it does
+provide functions for encoding and decoding to and from :term:`file objects
+<file object>`. It only supports the Base64 standard alphabet, and it adds
+newlines every 76 characters as per :rfc:`2045`. Note that if you are looking
+for :rfc:`2045` support you probably want to be looking at the :mod:`email`
+package instead.
+
.. versionchanged:: 3.3
ASCII-only Unicode strings are now accepted by the decoding functions of
the modern interface.
.. versionchanged:: 3.4
- Any :term:`bytes-like object`\ s are now accepted by all
+ Any :term:`bytes-like objects <bytes-like object>` are now accepted by all
encoding and decoding functions in this module. Ascii85/Base85 support added.
The modern interface provides:
.. function:: b64encode(s, altchars=None)
- Encode a byte string using Base64.
+ Encode the :term:`bytes-like object` *s* using Base64 and return the encoded
+ :class:`bytes`.
- *s* is the string to encode. Optional *altchars* must be a string of at least
+ Optional *altchars* must be a :term:`bytes-like object` of at least
length 2 (additional characters are ignored) which specifies an alternative
alphabet for the ``+`` and ``/`` characters. This allows an application to e.g.
generate URL or filesystem safe Base64 strings. The default is ``None``, for
which the standard Base64 alphabet is used.
- The encoded byte string is returned.
-
.. function:: b64decode(s, altchars=None, validate=False)
- Decode a Base64 encoded byte string.
+ Decode the Base64 encoded :term:`bytes-like object` or ASCII string
+ *s* and return the decoded :class:`bytes`.
- *s* is the byte string to decode. Optional *altchars* must be a string of
+ Optional *altchars* must be a :term:`bytes-like object` or ASCII string of
at least length 2 (additional characters are ignored) which specifies the
alternative alphabet used instead of the ``+`` and ``/`` characters.
- The decoded string is returned. A :exc:`binascii.Error` exception is raised
+ A :exc:`binascii.Error` exception is raised
if *s* is incorrectly padded.
- If *validate* is ``False`` (the default), non-base64-alphabet characters are
+ If *validate* is ``False`` (the default), characters that are neither
+ in the normal base-64 alphabet nor the alternative alphabet are
discarded prior to the padding check. If *validate* is ``True``,
- non-base64-alphabet characters in the input result in a
+ these non-alphabet characters in the input result in a
:exc:`binascii.Error`.
.. function:: standard_b64encode(s)
- Encode byte string *s* using the standard Base64 alphabet.
+ Encode :term:`bytes-like object` *s* using the standard Base64 alphabet
+ and return the encoded :class:`bytes`.
.. function:: standard_b64decode(s)
- Decode byte string *s* using the standard Base64 alphabet.
+ Decode :term:`bytes-like object` or ASCII string *s* using the standard
+ Base64 alphabet and return the decoded :class:`bytes`.
.. function:: urlsafe_b64encode(s)
- Encode byte string *s* using a URL-safe alphabet, which substitutes ``-`` instead of
- ``+`` and ``_`` instead of ``/`` in the standard Base64 alphabet. The result
+ Encode :term:`bytes-like object` *s* using the
+ URL- and filesystem-safe alphabet, which
+ substitutes ``-`` instead of ``+`` and ``_`` instead of ``/`` in the
+ standard Base64 alphabet, and return the encoded :class:`bytes`. The result
can still contain ``=``.
.. function:: urlsafe_b64decode(s)
- Decode byte string *s* using a URL-safe alphabet, which substitutes ``-`` instead of
- ``+`` and ``_`` instead of ``/`` in the standard Base64 alphabet.
+ Decode :term:`bytes-like object` or ASCII string *s*
+ using the URL- and filesystem-safe
+ alphabet, which substitutes ``-`` instead of ``+`` and ``_`` instead of
+ ``/`` in the standard Base64 alphabet, and return the decoded
+ :class:`bytes`.
.. function:: b32encode(s)
- Encode a byte string using Base32. *s* is the string to encode. The encoded string
- is returned.
+ Encode the :term:`bytes-like object` *s* using Base32 and return the
+ encoded :class:`bytes`.
.. function:: b32decode(s, casefold=False, map01=None)
- Decode a Base32 encoded byte string.
+ Decode the Base32 encoded :term:`bytes-like object` or ASCII string *s* and
+ return the decoded :class:`bytes`.
- *s* is the byte string to decode. Optional *casefold* is a flag specifying
+ Optional *casefold* is a flag specifying
whether a lowercase alphabet is acceptable as input. For security purposes,
the default is ``False``.
digit 0 is always mapped to the letter O). For security purposes the default is
``None``, so that 0 and 1 are not allowed in the input.
- The decoded byte string is returned. A :exc:`binascii.Error` is raised if *s* is
+ A :exc:`binascii.Error` is raised if *s* is
incorrectly padded or if there are non-alphabet characters present in the
- string.
+ input.
.. function:: b16encode(s)
- Encode a byte string using Base16.
-
- *s* is the string to encode. The encoded byte string is returned.
+ Encode the :term:`bytes-like object` *s* using Base16 and return the
+ encoded :class:`bytes`.
.. function:: b16decode(s, casefold=False)
- Decode a Base16 encoded byte string.
+ Decode the Base16 encoded :term:`bytes-like object` or ASCII string *s* and
+ return the decoded :class:`bytes`.
- *s* is the string to decode. Optional *casefold* is a flag specifying whether a
+ Optional *casefold* is a flag specifying whether a
lowercase alphabet is acceptable as input. For security purposes, the default
is ``False``.
- The decoded byte string is returned. A :exc:`TypeError` is raised if *s* were
+ A :exc:`binascii.Error` is raised if *s* is
incorrectly padded or if there are non-alphabet characters present in the
- string.
-
+ input.
-.. function:: a85encode(s, *, foldspaces=False, wrapcol=0, pad=False, adobe=False)
- Encode a byte string using Ascii85.
+.. function:: a85encode(b, *, foldspaces=False, wrapcol=0, pad=False, adobe=False)
- *s* is the string to encode. The encoded byte string is returned.
+ Encode the :term:`bytes-like object` *b* using Ascii85 and return the
+ encoded :class:`bytes`.
*foldspaces* is an optional flag that uses the special short sequence 'y'
instead of 4 consecutive spaces (ASCII 0x20) as supported by 'btoa'. This
feature is not supported by the "standard" Ascii85 encoding.
- *wrapcol* controls whether the output should have newline ('\n')
+ *wrapcol* controls whether the output should have newline (``b'\n'``)
characters added to it. If this is non-zero, each output line will be
at most this many characters long.
- *pad* controls whether the input string is padded to a multiple of 4
+ *pad* controls whether the input is padded to a multiple of 4
before encoding. Note that the ``btoa`` implementation always pads.
*adobe* controls whether the encoded byte sequence is framed with ``<~``
.. versionadded:: 3.4
-.. function:: a85decode(s, *, foldspaces=False, adobe=False, ignorechars=b' \t\n\r\v')
+.. function:: a85decode(b, *, foldspaces=False, adobe=False, ignorechars=b' \\t\\n\\r\\v')
- Decode an Ascii85 encoded byte string.
-
- *s* is the byte string to decode.
+ Decode the Ascii85 encoded :term:`bytes-like object` or ASCII string *b* and
+ return the decoded :class:`bytes`.
*foldspaces* is a flag that specifies whether the 'y' short sequence
should be accepted as shorthand for 4 consecutive spaces (ASCII 0x20).
*adobe* controls whether the input sequence is in Adobe Ascii85 format
(i.e. is framed with <~ and ~>).
- *ignorechars* should be a byte string containing characters to ignore
+ *ignorechars* should be a :term:`bytes-like object` or ASCII string
+ containing characters to ignore
from the input. This should only contain whitespace characters, and by
default contains all whitespace characters in ASCII.
.. versionadded:: 3.4
-.. function:: b85encode(s, pad=False)
+.. function:: b85encode(b, pad=False)
- Encode a byte string using base85, as used in e.g. git-style binary
- diffs.
+ Encode the :term:`bytes-like object` *b* using base85 (as used in e.g.
+ git-style binary diffs) and return the encoded :class:`bytes`.
- If *pad* is true, the input is padded with "\\0" so its length is a
- multiple of 4 characters before encoding.
+ If *pad* is true, the input is padded with ``b'\0'`` so its length is a
+ multiple of 4 bytes before encoding.
.. versionadded:: 3.4
.. function:: b85decode(b)
- Decode base85-encoded byte string. Padding is implicitly removed, if
+ Decode the base85-encoded :term:`bytes-like object` or ASCII string *b* and
+ return the decoded :class:`bytes`. Padding is implicitly removed, if
necessary.
.. versionadded:: 3.4
Decode the contents of the binary *input* file and write the resulting binary
data to the *output* file. *input* and *output* must be :term:`file objects
- <file object>`. *input* will be read until ``input.read()`` returns an empty
- bytes object.
+ <file object>`. *input* will be read until ``input.readline()`` returns an
+ empty bytes object.
.. function:: decodebytes(s)
decodestring(s)
- Decode the byte string *s*, which must contain one or more lines of base64
- encoded data, and return a byte string containing the resulting binary data.
+ Decode the :term:`bytes-like object` *s*, which must contain one or more
+ lines of base64 encoded data, and return the decoded :class:`bytes`.
``decodestring`` is a deprecated alias.
.. versionadded:: 3.1
Encode the contents of the binary *input* file and write the resulting base64
encoded data to the *output* file. *input* and *output* must be :term:`file
objects <file object>`. *input* will be read until ``input.read()`` returns
- an empty bytes object. :func:`encode` returns the encoded data plus a trailing
- newline character (``b'\n'``).
+ an empty bytes object. :func:`encode` inserts a newline character (``b'\n'``)
+ after every 76 bytes of the output, as well as ensuring that the output
+ always ends with a newline, as per :rfc:`2045` (MIME).
.. function:: encodebytes(s)
encodestring(s)
- Encode the byte string *s*, which can contain arbitrary binary data, and
- return a byte string containing one or more lines of base64-encoded data.
- :func:`encodebytes` returns a string containing one or more lines of
- base64-encoded data always including an extra trailing newline (``b'\n'``).
+ Encode the :term:`bytes-like object` *s*, which can contain arbitrary binary
+ data, and return :class:`bytes` containing the base64-encoded data, with newlines
+ (``b'\n'``) inserted after every 76 bytes of output, and ensuring that
+ there is a trailing newline, as per :rfc:`2045` (MIME).
+
``encodestring`` is a deprecated alias.
:synopsis: Tools for converting between binary and various ASCII-encoded binary
representations.
-
.. index::
module: uu
module: base64
module: binhex
+--------------
+
The :mod:`binascii` module contains a number of methods to convert between
binary and various ASCII-encoded binary representations. Normally, you will not
use these functions directly but use wrapper modules like :mod:`uu`,
.. note::
``a2b_*`` functions accept Unicode strings containing only ASCII characters.
- Other functions only accept :term:`bytes-like object`\ s (such as
+ Other functions only accept :term:`bytes-like objects <bytes-like object>` (such as
:class:`bytes`, :class:`bytearray` and other objects that support the buffer
protocol).
.. function:: b2a_base64(data)
Convert binary data to a line of ASCII characters in base64 coding. The return
- value is the converted line, including a newline char. The length of *data*
- should be at most 57 to adhere to the base64 standard.
+ value is the converted line, including a newline char. The newline is
+ added because the original use case for this function was to feed it a
+ series of 57 byte input lines to get output lines that conform to the
+ MIME-base64 standard. Otherwise the output conforms to :rfc:`3548`.
.. function:: a2b_qp(data, header=False)
possibly the last fragment).
-.. function:: crc_hqx(data, crc)
+.. function:: crc_hqx(data, value)
- Compute the binhex4 crc value of *data*, starting with an initial *crc* and
- returning the result.
+ Compute the binhex4 crc value of *data*, starting with *value* as the
+ initial crc, and return the result.
-.. function:: crc32(data[, crc])
+.. function:: crc32(data[, value])
- Compute CRC-32, the 32-bit checksum of data, starting with an initial crc. This
+ Compute CRC-32, the 32-bit checksum of *data*, starting with an
+ initial CRC of *value*. The default initial CRC is zero. The algorithm
is consistent with the ZIP file checksum. Since the algorithm is designed for
use as a checksum algorithm, it is not suitable for use as a general hash
algorithm. Use as follows::
print(binascii.crc32(b"hello world"))
# Or, in two pieces:
crc = binascii.crc32(b"hello")
- crc = binascii.crc32(b" world", crc) & 0xffffffff
+ crc = binascii.crc32(b" world", crc)
print('crc32 = {:#010x}'.format(crc))
-.. note::
- To generate the same numeric value across all Python versions and
- platforms use crc32(data) & 0xffffffff. If you are only using
- the checksum in packed binary format this is not necessary as the
- return value is the correct 32bit binary representation
- regardless of sign.
+ .. versionchanged:: 3.0
+ The result is always unsigned.
+ To generate the same numeric value across all Python versions and
+ platforms, use ``crc32(data) & 0xffffffff``.
.. function:: b2a_hex(data)
Return the binary data represented by the hexadecimal string *hexstr*. This
function is the inverse of :func:`b2a_hex`. *hexstr* must contain an even number
- of hexadecimal digits (which can be upper or lower case), otherwise a
- :exc:`TypeError` is raised.
+ of hexadecimal digits (which can be upper or lower case), otherwise an
+ :exc:`Error` exception is raised.
.. exception:: Error
.. seealso::
Module :mod:`base64`
- Support for base64 encoding used in MIME email messages.
+ Support for RFC compliant base64-style encoding in base 16, 32, 64,
+ and 85.
Module :mod:`binhex`
Support for the binhex format used on the Macintosh.
.. module:: binhex
:synopsis: Encode and decode files in binhex4 format.
+**Source code:** :source:`Lib/binhex.py`
+
+--------------
This module encodes and decodes files in binhex4 format, a format allowing
representation of Macintosh files in ASCII. Only the data fork is handled.
.. seealso::
`SortedCollection recipe
- <http://code.activestate.com/recipes/577197-sortedcollection/>`_ that uses
+ <https://code.activestate.com/recipes/577197-sortedcollection/>`_ that uses
bisect to build a full-featured collection class with straight-forward search
methods and support for a key-function. The keys are precomputed to save
unnecessary calls to the key function during searches.
.. module:: builtins
:synopsis: The module that provides the built-in namespace.
+--------------
This module provides direct access to all 'built-in' identifiers of Python; for
example, ``builtins.open`` is the full name for the built-in function
.. module:: bz2
:synopsis: Interfaces for bzip2 compression and decompression.
+
.. moduleauthor:: Gustavo Niemeyer <niemeyer@conectiva.com>
.. moduleauthor:: Nadeem Vawda <nadeem.vawda@gmail.com>
.. sectionauthor:: Gustavo Niemeyer <niemeyer@conectiva.com>
.. sectionauthor:: Nadeem Vawda <nadeem.vawda@gmail.com>
+**Source code:** :source:`Lib/bz2.py`
+
+--------------
This module provides a comprehensive interface for compressing and
decompressing data using the bzip2 compression algorithm.
.. module:: calendar
:synopsis: Functions for working with calendars, including some emulation
of the Unix cal program.
+
.. sectionauthor:: Drew Csillag <drew_csillag@geocities.com>
**Source code:** :source:`Lib/calendar.py`
.. module:: cgi
:synopsis: Helpers for running Python scripts via the Common Gateway Interface.
+**Source code:** :source:`Lib/cgi.py`
.. index::
pair: WWW; server
single: URL
single: Common Gateway Interface
-**Source code:** :source:`Lib/cgi.py`
-
--------------
Support module for Common Gateway Interface (CGI) scripts.
.. module:: cgitb
:synopsis: Configurable traceback handler for CGI scripts.
+
.. moduleauthor:: Ka-Ping Yee <ping@lfw.org>
.. sectionauthor:: Fred L. Drake, Jr. <fdrake@acm.org>
+**Source code:** :source:`Lib/cgitb.py`
.. index::
single: CGI; exceptions
single: exceptions; in CGI scripts
single: tracebacks; in CGI scripts
+--------------
+
The :mod:`cgitb` module provides a special exception handler for Python scripts.
(Its name is a bit misleading. It was originally designed to display extensive
traceback information in HTML for CGI scripts. It was later generalized to also
.. module:: chunk
:synopsis: Module to read IFF chunks.
+
.. moduleauthor:: Sjoerd Mullender <sjoerd@acm.org>
.. sectionauthor:: Sjoerd Mullender <sjoerd@acm.org>
+**Source code:** :source:`Lib/chunk.py`
.. index::
single: Audio Interchange File Format
single: Real Media File Format
single: RMFF
+--------------
+
This module provides an interface for reading files that use EA IFF 85 chunks.
[#]_ This format is used in at least the Audio Interchange File Format
(AIFF/AIFF-C) and the Real Media File Format (RMFF). The WAVE audio file format
.. module:: cmath
:synopsis: Mathematical functions for complex numbers.
+--------------
This module is always available. It provides access to mathematical functions
for complex numbers. The functions in this module accept integers,
.. module:: cmd
:synopsis: Build line-oriented command interpreters.
+
.. sectionauthor:: Eric S. Raymond <esr@snark.thyrsus.com>
**Source code:** :source:`Lib/cmd.py`
**Source code:** :source:`Lib/code.py`
+--------------
+
The ``code`` module provides facilities to implement read-eval-print loops in
Python. Two classes and convenience functions are included which can be used to
build applications which provide an interactive interpreter prompt.
.. module:: codecs
:synopsis: Encode and decode data and streams.
+
.. moduleauthor:: Marc-André Lemburg <mal@lemburg.com>
.. sectionauthor:: Marc-André Lemburg <mal@lemburg.com>
.. sectionauthor:: Martin v. Löwis <martin@v.loewis.de>
single: streams
pair: stackable; streams
+--------------
+
This module defines base classes for standard Python codecs (encoders and
decoders) and provides access to the internal Python codec registry, which
manages the codec and error handling lookup process. Most standard codecs
.. function:: getreader(encoding)
- Look up the codec for the given encoding and return its StreamReader class or
- factory function.
+ Look up the codec for the given encoding and return its :class:`StreamReader`
+ class or factory function.
Raises a :exc:`LookupError` in case the encoding cannot be found.
.. function:: getwriter(encoding)
- Look up the codec for the given encoding and return its StreamWriter class or
- factory function.
+ Look up the codec for the given encoding and return its :class:`StreamWriter`
+ class or factory function.
Raises a :exc:`LookupError` in case the encoding cannot be found.
* an ISO 8859 codeset
-* a Microsoft Windows code page, which is typically derived from a 8859 codeset,
+* a Microsoft Windows code page, which is typically derived from an 8859 codeset,
but replaces control characters with additional graphic characters
* an IBM EBCDIC code page
names (:mod:`http.client` then also transparently sends an IDNA hostname in the
:mailheader:`Host` field if it sends that field at all).
-.. _section 3.1: http://tools.ietf.org/html/rfc3490#section-3.1
+.. _section 3.1: https://tools.ietf.org/html/rfc3490#section-3.1
When receiving host names from the wire (such as in reverse name lookup), no
automatic conversion to Unicode is performed: Applications wishing to present
.. module:: codeop
:synopsis: Compile (possibly incomplete) Python code.
+
.. sectionauthor:: Moshe Zadka <moshez@zadka.site.co.il>
.. sectionauthor:: Michael Hudson <mwh@python.net>
+**Source code:** :source:`Lib/codeop.py`
+
+--------------
+
The :mod:`codeop` module provides utilities upon which the Python
read-eval-print loop can be emulated, as is done in the :mod:`code` module. As
a result, you probably don't want to use the module directly; if you want to
.. module:: collections.abc
:synopsis: Abstract base classes for containers
+
.. moduleauthor:: Raymond Hettinger <python at rcn.com>
.. sectionauthor:: Raymond Hettinger <python at rcn.com>
.. versionadded:: 3.3
Formerly, this module was part of the :mod:`collections` module.
+**Source code:** :source:`Lib/_collections_abc.py`
+
.. testsetup:: *
from collections import *
import itertools
__name__ = '<doctest>'
-**Source code:** :source:`Lib/_collections_abc.py`
-
--------------
This module provides :term:`abstract base classes <abstract base class>` that
:meth:`isdisjoint`::
class ListBasedSet(collections.abc.Set):
- ''' Alternate set implementation favoring space over speed
- and not requiring the set elements to be hashable. '''
- def __init__(self, iterable):
- self.elements = lst = []
- for value in iterable:
- if value not in lst:
- lst.append(value)
- def __iter__(self):
- return iter(self.elements)
- def __contains__(self, value):
- return value in self.elements
- def __len__(self):
- return len(self.elements)
+ ''' Alternate set implementation favoring space over speed
+ and not requiring the set elements to be hashable. '''
+ def __init__(self, iterable):
+ self.elements = lst = []
+ for value in iterable:
+ if value not in lst:
+ lst.append(value)
+
+ def __iter__(self):
+ return iter(self.elements)
+
+ def __contains__(self, value):
+ return value in self.elements
+
+ def __len__(self):
+ return len(self.elements)
s1 = ListBasedSet('abcdef')
s2 = ListBasedSet('defghi')
.. seealso::
- * `OrderedSet recipe <http://code.activestate.com/recipes/576694/>`_ for an
+ * `OrderedSet recipe <https://code.activestate.com/recipes/576694/>`_ for an
example built on :class:`MutableSet`.
* For more about ABCs, see the :mod:`abc` module and :pep:`3119`.
.. module:: collections
:synopsis: Container datatypes
+
.. moduleauthor:: Raymond Hettinger <python@rcn.com>
.. sectionauthor:: Raymond Hettinger <python@rcn.com>
+**Source code:** :source:`Lib/collections/__init__.py`
+
.. testsetup:: *
from collections import *
import itertools
__name__ = '<doctest>'
-**Source code:** :source:`Lib/collections/__init__.py`
-
--------------
This module implements specialized container datatypes providing alternatives to
dictionary is provided so that a new chain always has at least one mapping.
The underlying mappings are stored in a list. That list is public and can
- accessed or updated using the *maps* attribute. There is no other state.
+ be accessed or updated using the *maps* attribute. There is no other state.
Lookups search the underlying mappings successively until a key is found. In
contrast, writes, updates, and deletions only operate on the first mapping.
:meth:`~collections.ChainMap.parents` property.
* The `Nested Contexts recipe
- <http://code.activestate.com/recipes/577434/>`_ has options to control
+ <https://code.activestate.com/recipes/577434/>`_ has options to control
whether writes and other mutations apply only to the first mapping or to
any mapping in the chain.
* A `greatly simplified read-only version of Chainmap
- <http://code.activestate.com/recipes/305268/>`_.
+ <https://code.activestate.com/recipes/305268/>`_.
:class:`ChainMap` Examples and Recipes
.. seealso::
- * `Bag class <http://www.gnu.org/software/smalltalk/manual-base/html_node/Bag.html>`_
+ * `Bag class <https://www.gnu.org/software/smalltalk/manual-base/html_node/Bag.html>`_
in Smalltalk.
- * Wikipedia entry for `Multisets <http://en.wikipedia.org/wiki/Multiset>`_.
+ * Wikipedia entry for `Multisets <https://en.wikipedia.org/wiki/Multiset>`_.
- * `C++ multisets <http://www.demo2s.com/Tutorial/Cpp/0380__set-multiset/Catalog0380__set-multiset.htm>`_
+ * `C++ multisets <http://www.java2s.com/Tutorial/Cpp/0380__set-multiset/Catalog0380__set-multiset.htm>`_
tutorial with examples.
* For mathematical operations on multisets and their use cases, see
Insert *x* into the deque at position *i*.
+ If the insertion would cause a bounded deque to grow beyond *maxlen*,
+ an :exc:`IndexError` is raised.
+
.. versionadded:: 3.5
Named tuple instances do not have per-instance dictionaries, so they are
lightweight and require no more memory than regular tuples.
+ For simple uses, where the only requirement is to be able to refer to a set
+ of values by name using attribute-style access, the
+ :class:`types.SimpleNamespace` type can be a suitable alternative to using
+ a namedtuple.
+
.. versionchanged:: 3.1
Added support for *rename*.
>>> Book.title.__doc__ = 'Title of first printing'
>>> Book.authors.__doc__ = 'List of authors sorted by last name'
+.. versionchanged:: 3.5
+ Property docstrings became writeable.
+
Default values can be implemented by using :meth:`_replace` to
customize a prototype instance:
.. seealso::
* `Recipe for named tuple abstract base class with a metaclass mix-in
- <http://code.activestate.com/recipes/577629-namedtupleabc-abstract-base-class-mix-in-for-named/>`_
+ <https://code.activestate.com/recipes/577629-namedtupleabc-abstract-base-class-mix-in-for-named/>`_
by Jan Kaliszewski. Besides providing an :term:`abstract base class` for
named tuples, it also supports an alternate :term:`metaclass`-based
constructor that is convenient for use cases where named tuples are being
in conjunction with sorting to make a sorted dictionary::
>>> # regular unsorted dictionary
- >>> d = {'banana': 3, 'apple':4, 'pear': 1, 'orange': 2}
+ >>> d = {'banana': 3, 'apple': 4, 'pear': 1, 'orange': 2}
>>> # dictionary sorted by key
>>> OrderedDict(sorted(d.items(), key=lambda t: t[0]))
.. module:: colorsys
:synopsis: Conversion functions between RGB and other color systems.
+
.. sectionauthor:: David Ascher <da@python.net>
**Source code:** :source:`Lib/colorsys.py`
More information about color spaces can be found at
http://www.poynton.com/ColorFAQ.html and
- http://www.cambridgeincolour.com/tutorials/color-spaces.htm.
+ https://www.cambridgeincolour.com/tutorials/color-spaces.htm.
The :mod:`colorsys` module defines the following functions:
--------------
-
This module provides some utility functions to support installing Python
libraries. These functions compile Python source files in a directory tree.
This module can be used to create the cached byte-code files at library
Equivalent to :func:`map(func, *iterables) <map>` except *func* is executed
asynchronously and several calls to *func* may be made concurrently. The
- returned iterator raises a :exc:`TimeoutError` if
+ returned iterator raises a :exc:`concurrent.futures.TimeoutError` if
:meth:`~iterator.__next__` is called and the result isn't available
after *timeout* seconds from the original call to :meth:`Executor.map`.
*timeout* can be an int or a float. If *timeout* is not specified or
import time
def wait_on_b():
time.sleep(5)
- print(b.result()) # b will never complete because it is waiting on a.
+ print(b.result()) # b will never complete because it is waiting on a.
return 5
def wait_on_a():
time.sleep(5)
- print(a.result()) # a will never complete because it is waiting on b.
+ print(a.result()) # a will never complete because it is waiting on b.
return 6
'http://www.bbc.co.uk/',
'http://some-made-up-domain.com/']
- # Retrieve a single page and report the url and contents
+ # Retrieve a single page and report the URL and contents
def load_url(url, timeout):
with urllib.request.urlopen(url, timeout=timeout) as conn:
return conn.read()
Return the value returned by the call. If the call hasn't yet completed
then this method will wait up to *timeout* seconds. If the call hasn't
- completed in *timeout* seconds, then a :exc:`TimeoutError` will be
- raised. *timeout* can be an int or float. If *timeout* is not specified
- or ``None``, there is no limit to the wait time.
+ completed in *timeout* seconds, then a
+ :exc:`concurrent.futures.TimeoutError` will be raised. *timeout* can be
+ an int or float. If *timeout* is not specified or ``None``, there is no
+ limit to the wait time.
- If the future is cancelled before completing then :exc:`CancelledError`
+ If the future is cancelled before completing then :exc:`.CancelledError`
will be raised.
If the call raised, this method will raise the same exception.
Return the exception raised by the call. If the call hasn't yet
completed then this method will wait up to *timeout* seconds. If the
- call hasn't completed in *timeout* seconds, then a :exc:`TimeoutError`
- will be raised. *timeout* can be an int or float. If *timeout* is not
- specified or ``None``, there is no limit to the wait time.
+ call hasn't completed in *timeout* seconds, then a
+ :exc:`concurrent.futures.TimeoutError` will be raised. *timeout* can be
+ an int or float. If *timeout* is not specified or ``None``, there is no
+ limit to the wait time.
- If the future is cancelled before completing then :exc:`CancelledError`
+ If the future is cancelled before completing then :exc:`.CancelledError`
will be raised.
If the call completed without raising, ``None`` is returned.
Returns an iterator over the :class:`Future` instances (possibly created by
different :class:`Executor` instances) given by *fs* that yields futures as
they complete (finished or were cancelled). Any futures given by *fs* that
- are duplicated will be returned once. Any futures that completed
- before :func:`as_completed` is called will be yielded first. The returned
- iterator raises a :exc:`TimeoutError` if :meth:`~iterator.__next__` is
- called and the result isn't available after *timeout* seconds from the
- original call to :func:`as_completed`. *timeout* can be an int or float.
- If *timeout* is not specified or ``None``, there is no limit to the wait
- time.
+ are duplicated will be returned once. Any futures that completed before
+ :func:`as_completed` is called will be yielded first. The returned iterator
+ raises a :exc:`concurrent.futures.TimeoutError` if :meth:`~iterator.__next__`
+ is called and the result isn't available after *timeout* seconds from the
+ original call to :func:`as_completed`. *timeout* can be an int or float. If
+ *timeout* is not specified or ``None``, there is no limit to the wait time.
.. seealso::
Exception classes
-----------------
+.. currentmodule:: concurrent.futures
+
+.. exception:: CancelledError
+
+ Raised when a future is cancelled.
+
+.. exception:: TimeoutError
+
+ Raised when a future operation exceeds the given timeout.
+
.. currentmodule:: concurrent.futures.process
.. exception:: BrokenProcessPool
single: ini file
single: Windows ini file
+--------------
+
This module provides the :class:`ConfigParser` class which implements a basic
configuration language which provides a structure similar to what's found in
Microsoft Windows INI files. You can use this to write Python programs which
# Set the optional *raw* argument of get() to True if you wish to disable
# interpolation in a single get operation.
- print(cfg.get('Section1', 'foo', raw=False)) # -> "Python is fun!"
- print(cfg.get('Section1', 'foo', raw=True)) # -> "%(bar)s is %(baz)s!"
+ print(cfg.get('Section1', 'foo', raw=False)) # -> "Python is fun!"
+ print(cfg.get('Section1', 'foo', raw=True)) # -> "%(bar)s is %(baz)s!"
# The optional *vars* argument is a dict with members that will take
# precedence in interpolation.
print(cfg.get('Section1', 'foo', vars={'bar': 'Documentation',
- 'baz': 'evil'}))
+ 'baz': 'evil'}))
# The optional *fallback* argument can be used to provide a fallback value
print(cfg.get('Section1', 'foo'))
config = configparser.ConfigParser({'bar': 'Life', 'baz': 'hard'})
config.read('example.cfg')
- print(config.get('Section1', 'foo')) # -> "Python is fun!"
+ print(config.get('Section1', 'foo')) # -> "Python is fun!"
config.remove_option('Section1', 'bar')
config.remove_option('Section1', 'baz')
- print(config.get('Section1', 'foo')) # -> "Life is hard!"
+ print(config.get('Section1', 'foo')) # -> "Life is hard!"
.. _configparser-objects:
.. seealso::
- :pep:`0343` - The "with" statement
+ :pep:`343` - The "with" statement
The specification, background, and examples for the Python :keyword:`with`
statement.
Before
After
>>> with cm:
- ... pass
+ ... pass
...
Traceback (most recent call last):
...
.. module:: copy
:synopsis: Shallow and deep copy operations.
+**Source code:** :source:`Lib/copy.py`
+
+--------------
+
Assignment statements in Python do not copy objects, they create bindings
between a target and an object. For collections that are mutable or contain
mutable items, a copy is sometimes needed so one can change one copy without
.. module:: copyreg
:synopsis: Register pickle support functions.
+**Source code:** :source:`Lib/copyreg.py`
.. index::
module: pickle
module: copy
+--------------
+
The :mod:`copyreg` module offers a way to define functions used while pickling
specific objects. The :mod:`pickle` and :mod:`copy` modules use those functions
when pickling/copying those objects. The module provides configuration
.. module:: crypt
:platform: Unix
:synopsis: The crypt() function used to check Unix passwords.
+
.. moduleauthor:: Steven D. Majewski <sdm7g@virginia.edu>
.. sectionauthor:: Steven D. Majewski <sdm7g@virginia.edu>
.. sectionauthor:: Peter Funk <pf@artcom-gmbh.de>
+**Source code:** :source:`Lib/crypt.py`
.. index::
single: crypt(3)
pair: cipher; DES
+--------------
+
This module implements an interface to the :manpage:`crypt(3)` routine, which is
a one-way hash function based upon a modified DES algorithm; see the Unix man
page for further details. Possible uses include storing hashed passwords
hashed = crypt.crypt(plaintext)
if not compare_hash(hashed, crypt.crypt(plaintext, hashed)):
- raise ValueError("hashed version doesn't validate against original")
+ raise ValueError("hashed version doesn't validate against original")
hashlib.rst
hmac.rst
-
-.. index::
- pair: AES; algorithm
- single: cryptography
- single: Kuchling, Andrew
-
-Hardcore cypherpunks will probably find the cryptographic modules written by
-A.M. Kuchling of further interest; the package contains modules for various
-encryption algorithms, most notably AES. These modules are not distributed with
-Python but available separately. See the URL http://www.pycrypto.org/ for more
-information.
.. module:: csv
:synopsis: Write and read tabular data to and from delimited files.
+
.. sectionauthor:: Skip Montanaro <skip@pobox.com>
**Source code:** :source:`Lib/csv.py`
single: csv
pair: data; tabular
+--------------
+
The so-called CSV (Comma Separated Values) format is the most common import and
export format for spreadsheets and databases. CSV format was used for many
years prior to attempts to describe the format in a standardized way in
.. module:: ctypes
:synopsis: A foreign function library for Python.
+
.. moduleauthor:: Thomas Heller <theller@python.net>
+--------------
:mod:`ctypes` is a foreign function library for Python. It provides C compatible
data types, and allows calling functions in DLLs or shared libraries. It can be
they actually work. Since some code samples behave differently under Linux,
Windows, or Mac OS X, they contain doctest directives in comments.
-Note: Some code samples reference the ctypes :class:`c_int` type. This type is
-an alias for the :class:`c_long` type on 32-bit systems. So, you should not be
-confused if :class:`c_long` is printed if you would expect :class:`c_int` ---
-they are actually the same type.
-
+Note: Some code samples reference the ctypes :class:`c_int` type. On platforms
+where ``sizeof(long) == sizeof(int)`` it is an alias to :class:`c_long`.
+So, you should not be confused if :class:`c_long` is printed if you would expect
+:class:`c_int` --- they are actually the same type.
.. _ctypes-loading-dynamic-link-libraries:
convention::
>>> from ctypes import *
- >>> print(windll.kernel32) # doctest: +WINDOWS
+ >>> print(windll.kernel32) # doctest: +WINDOWS
<WinDLL 'kernel32', handle ... at ...>
- >>> print(cdll.msvcrt) # doctest: +WINDOWS
+ >>> print(cdll.msvcrt) # doctest: +WINDOWS
<CDLL 'msvcrt', handle ... at ...>
- >>> libc = cdll.msvcrt # doctest: +WINDOWS
+ >>> libc = cdll.msvcrt # doctest: +WINDOWS
>>>
Windows appends the usual ``.dll`` file suffix automatically.
+.. note::
+ Accessing the standard C library through ``cdll.msvcrt`` will use an
+ outdated version of the library that may be incompatible with the one
+ being used by Python. Where possible, use native Python functionality,
+ or else import and use the ``msvcrt`` module.
+
On Linux, it is required to specify the filename *including* the extension to
load a library, so attribute access can not be used to load libraries. Either the
:meth:`LoadLibrary` method of the dll loaders should be used, or you should load
the library by creating an instance of CDLL by calling the constructor::
- >>> cdll.LoadLibrary("libc.so.6") # doctest: +LINUX
+ >>> cdll.LoadLibrary("libc.so.6") # doctest: +LINUX
<CDLL 'libc.so.6', handle ... at ...>
- >>> libc = CDLL("libc.so.6") # doctest: +LINUX
- >>> libc # doctest: +LINUX
+ >>> libc = CDLL("libc.so.6") # doctest: +LINUX
+ >>> libc # doctest: +LINUX
<CDLL 'libc.so.6', handle ... at ...>
>>>
>>> from ctypes import *
>>> libc.printf
<_FuncPtr object at 0x...>
- >>> print(windll.kernel32.GetModuleHandleA) # doctest: +WINDOWS
+ >>> print(windll.kernel32.GetModuleHandleA) # doctest: +WINDOWS
<_FuncPtr object at 0x...>
- >>> print(windll.kernel32.MyOwnFunction) # doctest: +WINDOWS
+ >>> print(windll.kernel32.MyOwnFunction) # doctest: +WINDOWS
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "ctypes.py", line 239, in __getattr__
identifiers, like ``"??2@YAPAXI@Z"``. In this case you have to use
:func:`getattr` to retrieve the function::
- >>> getattr(cdll.msvcrt, "??2@YAPAXI@Z") # doctest: +WINDOWS
+ >>> getattr(cdll.msvcrt, "??2@YAPAXI@Z") # doctest: +WINDOWS
<_FuncPtr object at 0x...>
>>>
On Windows, some dlls export functions not by name but by ordinal. These
functions can be accessed by indexing the dll object with the ordinal number::
- >>> cdll.kernel32[1] # doctest: +WINDOWS
+ >>> cdll.kernel32[1] # doctest: +WINDOWS
<_FuncPtr object at 0x...>
- >>> cdll.kernel32[0] # doctest: +WINDOWS
+ >>> cdll.kernel32[0] # doctest: +WINDOWS
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "ctypes.py", line 310, in __getitem__
This example calls both functions with a NULL pointer (``None`` should be used
as the NULL pointer)::
- >>> print(libc.time(None)) # doctest: +SKIP
+ >>> print(libc.time(None)) # doctest: +SKIP
1150640792
- >>> print(hex(windll.kernel32.GetModuleHandleA(None))) # doctest: +WINDOWS
+ >>> print(hex(windll.kernel32.GetModuleHandleA(None))) # doctest: +WINDOWS
0x1d000000
>>>
Windows. It does this by examining the stack after the function returns, so
although an error is raised the function *has* been called::
- >>> windll.kernel32.GetModuleHandleA() # doctest: +WINDOWS
+ >>> windll.kernel32.GetModuleHandleA() # doctest: +WINDOWS
Traceback (most recent call last):
File "<stdin>", line 1, in ?
ValueError: Procedure probably called with not enough arguments (4 bytes missing)
- >>> windll.kernel32.GetModuleHandleA(0, 0) # doctest: +WINDOWS
+ >>> windll.kernel32.GetModuleHandleA(0, 0) # doctest: +WINDOWS
Traceback (most recent call last):
File "<stdin>", line 1, in ?
ValueError: Procedure probably called with too many arguments (4 bytes in excess)
The same exception is raised when you call an ``stdcall`` function with the
``cdecl`` calling convention, or vice versa::
- >>> cdll.kernel32.GetModuleHandleA(None) # doctest: +WINDOWS
+ >>> cdll.kernel32.GetModuleHandleA(None) # doctest: +WINDOWS
Traceback (most recent call last):
File "<stdin>", line 1, in ?
ValueError: Procedure probably called with not enough arguments (4 bytes missing)
>>>
- >>> windll.msvcrt.printf(b"spam") # doctest: +WINDOWS
+ >>> windll.msvcrt.printf(b"spam") # doctest: +WINDOWS
Traceback (most recent call last):
File "<stdin>", line 1, in ?
ValueError: Procedure probably called with too many arguments (4 bytes in excess)
crashes from general protection faults when functions are called with invalid
argument values::
- >>> windll.kernel32.GetModuleHandleA(32) # doctest: +WINDOWS
+ >>> windll.kernel32.GetModuleHandleA(32) # doctest: +WINDOWS
Traceback (most recent call last):
File "<stdin>", line 1, in ?
OSError: exception: access violation reading 0x00000020
a string pointer and a char, and returns a pointer to a string::
>>> strchr = libc.strchr
- >>> strchr(b"abcdef", ord("d")) # doctest: +SKIP
+ >>> strchr(b"abcdef", ord("d")) # doctest: +SKIP
8059983
- >>> strchr.restype = c_char_p # c_char_p is a pointer to a string
+ >>> strchr.restype = c_char_p # c_char_p is a pointer to a string
>>> strchr(b"abcdef", ord("d"))
b'def'
>>> print(strchr(b"abcdef", ord("x")))
result of this call will be used as the result of your function call. This is
useful to check for error return values and automatically raise an exception::
- >>> GetModuleHandle = windll.kernel32.GetModuleHandleA # doctest: +WINDOWS
+ >>> GetModuleHandle = windll.kernel32.GetModuleHandleA # doctest: +WINDOWS
>>> def ValidHandle(value):
... if value == 0:
... raise WinError()
... return value
...
>>>
- >>> GetModuleHandle.restype = ValidHandle # doctest: +WINDOWS
- >>> GetModuleHandle(None) # doctest: +WINDOWS
+ >>> GetModuleHandle.restype = ValidHandle # doctest: +WINDOWS
+ >>> GetModuleHandle(None) # doctest: +WINDOWS
486539264
- >>> GetModuleHandle("something silly") # doctest: +WINDOWS
+ >>> GetModuleHandle("something silly") # doctest: +WINDOWS
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 3, in ValidHandle
TenPointsArrayType = POINT * 10
-Here is an example of an somewhat artificial data type, a structure containing 4
+Here is an example of a somewhat artificial data type, a structure containing 4
POINTs among other stuff::
>>> from ctypes import *
>>> class POINT(Structure):
- ... _fields_ = ("x", c_int), ("y", c_int)
+ ... _fields_ = ("x", c_int), ("y", c_int)
...
>>> class MyStruct(Structure):
- ... _fields_ = [("a", c_int),
- ... ("b", c_float),
- ... ("point_array", POINT * 4)]
+ ... _fields_ = [("a", c_int),
+ ... ("b", c_float),
+ ... ("point_array", POINT * 4)]
>>>
>>> print(len(MyStruct().point_array))
4
>>> pi = pointer(i)
>>>
-Pointer instances have a :attr:`contents` attribute which returns the object to
-which the pointer points, the ``i`` object above::
+Pointer instances have a :attr:`~_Pointer.contents` attribute which
+returns the object to which the pointer points, the ``i`` object above::
>>> pi.contents
c_long(42)
Callback functions
^^^^^^^^^^^^^^^^^^
-:mod:`ctypes` allows to create C callable function pointers from Python callables.
+:mod:`ctypes` allows creating C callable function pointers from Python callables.
These are sometimes called *callback functions*.
First, you must create a class for the callback function. The class knows the
The result::
- >>> qsort(ia, len(ia), sizeof(c_int), cmp_func) # doctest: +LINUX
+ >>> qsort(ia, len(ia), sizeof(c_int), cmp_func) # doctest: +LINUX
py_cmp_func 5 1
py_cmp_func 33 99
py_cmp_func 7 33
hit the NULL entry::
>>> for item in table:
- ... print(item.name, item.size)
- ... if item.name is None:
- ... break
+ ... if item.name is None:
+ ... break
+ ... print(item.name.decode("ascii"), item.size)
...
- __hello__ 104
- __phello__ -104
- __phello__.spam 104
- None 0
+ _frozen_importlib 31764
+ _frozen_importlib_external 41499
+ __hello__ 161
+ __phello__ -161
+ __phello__.spam 161
>>>
The fact that standard Python has a frozen module and a frozen package
Loading shared libraries
^^^^^^^^^^^^^^^^^^^^^^^^
-There are several ways to loaded shared libraries into the Python process. One
+There are several ways to load shared libraries into the Python process. One
way is to instantiate one of the following classes:
ignored.
The *use_errno* parameter, when set to True, enables a ctypes mechanism that
-allows to access the system :data:`errno` error number in a safe way.
+allows accessing the system :data:`errno` error number in a safe way.
:mod:`ctypes` maintains a thread-local copy of the systems :data:`errno`
variable; if you call foreign functions created with ``use_errno=True`` then the
:data:`errno` value before the function call is swapped with the ctypes private
Class which loads shared libraries. *dlltype* should be one of the
:class:`CDLL`, :class:`PyDLL`, :class:`WinDLL`, or :class:`OleDLL` types.
- :meth:`__getattr__` has special behavior: It allows to load a shared library by
+ :meth:`__getattr__` has special behavior: It allows loading a shared library by
accessing it as attribute of a library loader instance. The result is cached,
so repeated attribute accesses return the same library each time.
It is possible to assign a callable Python object that is not a ctypes
type, in this case the function is assumed to return a C :c:type:`int`, and
- the callable will be called with this integer, allowing to do further
+ the callable will be called with this integer, allowing further
processing or error checking. Using this is deprecated, for more flexible
post processing or error checking use a ctypes data type as
:attr:`restype` and assign a callable to the :attr:`errcheck` attribute.
When a foreign function is called, each actual argument is passed to the
:meth:`from_param` class method of the items in the :attr:`argtypes`
- tuple, this method allows to adapt the actual argument to an object that
+ tuple, this method allows adapting the actual argument to an object that
the foreign function accepts. For example, a :class:`c_char_p` item in
the :attr:`argtypes` tuple will convert a string passed as argument into
a bytes object using ctypes conversion rules.
New: It is now possible to put items in argtypes which are not ctypes
types, but each item must have a :meth:`from_param` method which returns a
value usable as argument (integer, string, ctypes instance). This allows
- to define adapters that can adapt custom objects as function parameters.
+ defining adapters that can adapt custom objects as function parameters.
.. attribute:: errcheck
*result* is what the foreign function returns, as specified by the
:attr:`restype` attribute.
- *func* is the foreign function object itself, this allows to reuse the
+ *func* is the foreign function object itself, this allows reusing the
same callable object to check or post process the results of several
functions.
*arguments* is a tuple containing the parameters originally passed to
- the function call, this allows to specialize the behavior on the
+ the function call, this allows specializing the behavior on the
arguments used.
The object that this function returns will be returned from the
If a bytes object is specified as first argument, the buffer is made one item
larger than its length so that the last element in the array is a NUL
termination character. An integer can be passed as second argument which allows
- to specify the size of the array if the length of the bytes should not be used.
+ specifying the size of the array if the length of the bytes should not be used.
If a string is specified as first argument, the buffer is made one item
larger than the length of the string so that the last element in the array is a
NUL termination character. An integer can be passed as second argument which
- allows to specify the size of the array if the length of the string should not
+ allows specifying the size of the array if the length of the string should not
be used.
.. function:: DllCanUnloadNow()
- Windows only: This function is a hook which allows to implement in-process
+ Windows only: This function is a hook which allows implementing in-process
COM servers with ctypes. It is called from the DllCanUnloadNow function that
the _ctypes extension dll exports.
.. function:: DllGetClassObject()
- Windows only: This function is a hook which allows to implement in-process
+ Windows only: This function is a hook which allows implementing in-process
COM servers with ctypes. It is called from the DllGetClassObject function
that the ``_ctypes`` extension dll exports.
.. function:: POINTER(type)
This factory function creates and returns a new ctypes pointer type. Pointer
- types are cached an reused internally, so calling this function repeatedly is
+ types are cached and reused internally, so calling this function repeatedly is
cheap. *type* must be a ctypes type.
checked, only one field can be accessed when names are repeated.
It is possible to define the :attr:`_fields_` class variable *after* the
- class statement that defines the Structure subclass, this allows to create
+ class statement that defines the Structure subclass, this allows creating
data types that directly or indirectly reference themselves::
class List(Structure):
.. attribute:: _pack_
- An optional small integer that allows to override the alignment of
+ An optional small integer that allows overriding the alignment of
structure fields in the instance. :attr:`_pack_` must already be defined
when :attr:`_fields_` is assigned, otherwise it will have no effect.
assigned, otherwise it will have no effect.
The fields listed in this variable must be structure or union type fields.
- :mod:`ctypes` will create descriptors in the structure type that allows to
- access the nested fields directly, without the need to create the
+ :mod:`ctypes` will create descriptors in the structure type that allows
+ accessing the nested fields directly, without the need to create the
structure or union field.
Here is an example type (Windows)::
Arrays and pointers
^^^^^^^^^^^^^^^^^^^
-Not yet written - please see the sections :ref:`ctypes-pointers` and section
-:ref:`ctypes-arrays` in the tutorial.
+.. class:: Array(\*args)
+
+ Abstract base class for arrays.
+
+ The recommended way to create concrete array types is by multiplying any
+ :mod:`ctypes` data type with a positive integer. Alternatively, you can subclass
+ this type and define :attr:`_length_` and :attr:`_type_` class variables.
+ Array elements can be read and written using standard
+ subscript and slice accesses; for slice reads, the resulting object is
+ *not* itself an :class:`Array`.
+
+
+ .. attribute:: _length_
+
+ A positive integer specifying the number of elements in the array.
+ Out-of-range subscripts result in an :exc:`IndexError`. Will be
+ returned by :func:`len`.
+
+
+ .. attribute:: _type_
+
+ Specifies the type of each element in the array.
+
+
+ Array subclass constructors accept positional arguments, used to
+ initialize the elements in order.
+
+
+.. class:: _Pointer
+
+ Private, abstract base class for pointers.
+
+ Concrete pointer types are created by calling :func:`POINTER` with the
+ type that will be pointed to; this is done automatically by
+ :func:`pointer`.
+
+ If a pointer points to an array, its elements can be read and
+ written using standard subscript and slice accesses. Pointer objects
+ have no size, so :func:`len` will raise :exc:`TypeError`. Negative
+ subscripts will read from the memory *before* the pointer (as in C), and
+ out-of-range subscripts will probably crash with an access violation (if
+ you're lucky).
+
+
+ .. attribute:: _type_
+
+ Specifies the type pointed to.
+
+ .. attribute:: contents
+
+ Returns the object to which to pointer points. Assigning to this
+ attribute changes the pointer to point to the assigned object.
.. module:: curses.ascii
:synopsis: Constants and set-membership functions for ASCII characters.
+
.. moduleauthor:: Eric S. Raymond <esr@thyrsus.com>
.. sectionauthor:: Eric S. Raymond <esr@thyrsus.com>
+--------------
The :mod:`curses.ascii` module supplies name constants for ASCII characters and
functions to test membership in various ASCII character classes. The constants
.. module:: curses.panel
:synopsis: A panel stack extension that adds depth to curses windows.
+
.. sectionauthor:: A.M. Kuchling <amk@amk.ca>
+--------------
Panels are windows with the added feature of depth, so they can be stacked on
top of each other, and only the visible portions of each window will be
:synopsis: An interface to the curses library, providing portable
terminal handling.
:platform: Unix
+
.. sectionauthor:: Moshe Zadka <moshez@zadka.site.co.il>
.. sectionauthor:: Eric Raymond <esr@thyrsus.com>
+--------------
+
The :mod:`curses` module provides an interface to the curses library, the
de-facto standard for portable advanced terminal handling.
+------------------+-----------+
| :kbd:`End` | KEY_END |
+------------------+-----------+
-| :kbd:`Page Up` | KEY_NPAGE |
+| :kbd:`Page Up` | KEY_PPAGE |
+------------------+-----------+
-| :kbd:`Page Down` | KEY_PPAGE |
+| :kbd:`Page Down` | KEY_NPAGE |
+------------------+-----------+
The following table lists characters from the alternate character set. These are
.. module:: datetime
:synopsis: Basic date and time types.
+
.. moduleauthor:: Tim Peters <tim@zope.com>
.. sectionauthor:: Tim Peters <tim@zope.com>
.. sectionauthor:: A.M. Kuchling <amk@amk.ca>
**Source code:** :source:`Lib/datetime.py`
+--------------
+
.. XXX what order should the types be discussed in?
The :mod:`datetime` module supplies classes for manipulating dates and times in
understand and to work with, at the cost of ignoring some aspects of reality.
For applications requiring aware objects, :class:`.datetime` and :class:`.time`
-objects have an optional time zone information attribute, :attr:`tzinfo`, that
+objects have an optional time zone information attribute, :attr:`!tzinfo`, that
can be set to an instance of a subclass of the abstract :class:`tzinfo` class.
These :class:`tzinfo` objects capture information about the offset from UTC
time, the time zone name, and whether Daylight Saving Time is in effect. Note
An idealized time, independent of any particular day, assuming that every day
has exactly 24\*60\*60 seconds (there is no notion of "leap seconds" here).
Attributes: :attr:`hour`, :attr:`minute`, :attr:`second`, :attr:`microsecond`,
- and :attr:`tzinfo`.
+ and :attr:`.tzinfo`.
.. class:: datetime
A combination of a date and a time. Attributes: :attr:`year`, :attr:`month`,
:attr:`day`, :attr:`hour`, :attr:`minute`, :attr:`second`, :attr:`microsecond`,
- and :attr:`tzinfo`.
+ and :attr:`.tzinfo`.
.. class:: timedelta
.. class:: tzinfo
+ :noindex:
An abstract base class for time zone information objects. These are used by the
:class:`.datetime` and :class:`.time` classes to provide a customizable notion of
time).
.. class:: timezone
+ :noindex:
A class that implements the :class:`tzinfo` abstract base class as a
fixed offset from the UTC.
Return a 3-tuple, (ISO year, ISO week number, ISO weekday).
The ISO calendar is a widely used variant of the Gregorian calendar. See
- http://www.staff.science.uu.nl/~gent0113/calendar/isocalendar.htm for a good
+ https://www.staff.science.uu.nl/~gent0113/calendar/isocalendar.htm for a good
explanation.
The ISO year consists of 52 or 53 full weeks, and where a week starts on a
.. method:: date.__format__(format)
- Same as :meth:`.date.strftime`. This makes it possible to specify format
+ Same as :meth:`.date.strftime`. This makes it possible to specify a format
string for a :class:`.date` object when using :meth:`str.format`. For a
complete list of formatting directives, see
:ref:`strftime-strptime-behavior`.
.. classmethod:: datetime.today()
- Return the current local datetime, with :attr:`tzinfo` ``None``. This is
+ Return the current local datetime, with :attr:`.tzinfo` ``None``. This is
equivalent to ``datetime.fromtimestamp(time.time())``. See also :meth:`now`,
:meth:`fromtimestamp`.
(for example, this may be possible on platforms supplying the C
:c:func:`gettimeofday` function).
- Else *tz* must be an instance of a class :class:`tzinfo` subclass, and the
- current date and time are converted to *tz*'s time zone. In this case the
+ If *tz* is not ``None``, it must be an instance of a :class:`tzinfo` subclass, and the
+ current date and time are converted to *tz*’s time zone. In this case the
result is equivalent to ``tz.fromutc(datetime.utcnow().replace(tzinfo=tz))``.
See also :meth:`today`, :meth:`utcnow`.
.. classmethod:: datetime.utcnow()
- Return the current UTC date and time, with :attr:`tzinfo` ``None``. This is like
+ Return the current UTC date and time, with :attr:`.tzinfo` ``None``. This is like
:meth:`now`, but returns the current UTC date and time, as a naive
:class:`.datetime` object. An aware current UTC datetime can be obtained by
calling ``datetime.now(timezone.utc)``. See also :meth:`now`.
specified, the timestamp is converted to the platform's local date and time, and
the returned :class:`.datetime` object is naive.
- Else *tz* must be an instance of a class :class:`tzinfo` subclass, and the
- timestamp is converted to *tz*'s time zone. In this case the result is
+ If *tz* is not ``None``, it must be an instance of a :class:`tzinfo` subclass, and the
+ timestamp is converted to *tz*’s time zone. In this case the result is
equivalent to
``tz.fromutc(datetime.utcfromtimestamp(timestamp).replace(tzinfo=tz))``.
.. classmethod:: datetime.utcfromtimestamp(timestamp)
Return the UTC :class:`.datetime` corresponding to the POSIX timestamp, with
- :attr:`tzinfo` ``None``. This may raise :exc:`OverflowError`, if the timestamp is
+ :attr:`.tzinfo` ``None``. This may raise :exc:`OverflowError`, if the timestamp is
out of the range of values supported by the platform C :c:func:`gmtime` function,
and :exc:`OSError` on :c:func:`gmtime` failure.
It's common for this to be restricted to years in 1970 through 2038.
Return the :class:`.datetime` corresponding to the proleptic Gregorian ordinal,
where January 1 of year 1 has ordinal 1. :exc:`ValueError` is raised unless ``1
<= ordinal <= datetime.max.toordinal()``. The hour, minute, second and
- microsecond of the result are all 0, and :attr:`tzinfo` is ``None``.
+ microsecond of the result are all 0, and :attr:`.tzinfo` is ``None``.
.. classmethod:: datetime.combine(date, time)
Return a new :class:`.datetime` object whose date components are equal to the
- given :class:`date` object's, and whose time components and :attr:`tzinfo`
+ given :class:`date` object's, and whose time components and :attr:`.tzinfo`
attributes are equal to the given :class:`.time` object's. For any
:class:`.datetime` object *d*,
``d == datetime.combine(d.date(), d.timetz())``. If date is a
- :class:`.datetime` object, its time components and :attr:`tzinfo` attributes
+ :class:`.datetime` object, its time components and :attr:`.tzinfo` attributes
are ignored.
(1)
datetime2 is a duration of timedelta removed from datetime1, moving forward in
time if ``timedelta.days`` > 0, or backward if ``timedelta.days`` < 0. The
- result has the same :attr:`tzinfo` attribute as the input datetime, and
+ result has the same :attr:`~.datetime.tzinfo` attribute as the input datetime, and
datetime2 - datetime1 == timedelta after. :exc:`OverflowError` is raised if
datetime2.year would be smaller than :const:`MINYEAR` or larger than
:const:`MAXYEAR`. Note that no time zone adjustments are done even if the
(2)
Computes the datetime2 such that datetime2 + timedelta == datetime1. As for
- addition, the result has the same :attr:`tzinfo` attribute as the input
+ addition, the result has the same :attr:`~.datetime.tzinfo` attribute as the input
datetime, and no time zone adjustments are done even if the input is aware.
This isn't quite equivalent to datetime1 + (-timedelta), because -timedelta
in isolation can overflow in cases where datetime1 - timedelta does not.
both operands are naive, or if both are aware. If one is aware and the other is
naive, :exc:`TypeError` is raised.
- If both are naive, or both are aware and have the same :attr:`tzinfo` attribute,
- the :attr:`tzinfo` attributes are ignored, and the result is a :class:`timedelta`
+ If both are naive, or both are aware and have the same :attr:`~.datetime.tzinfo` attribute,
+ the :attr:`~.datetime.tzinfo` attributes are ignored, and the result is a :class:`timedelta`
object *t* such that ``datetime2 + t == datetime1``. No time zone adjustments
are done in this case.
- If both are aware and have different :attr:`tzinfo` attributes, ``a-b`` acts
+ If both are aware and have different :attr:`~.datetime.tzinfo` attributes, ``a-b`` acts
as if *a* and *b* were first converted to naive UTC datetimes first. The
result is ``(a.replace(tzinfo=None) - a.utcoffset()) - (b.replace(tzinfo=None)
- b.utcoffset())`` except that the implementation never overflows.
is raised if an order comparison is attempted. For equality
comparisons, naive instances are never equal to aware instances.
- If both comparands are aware, and have the same :attr:`tzinfo` attribute, the
- common :attr:`tzinfo` attribute is ignored and the base datetimes are
- compared. If both comparands are aware and have different :attr:`tzinfo`
+ If both comparands are aware, and have the same :attr:`~.datetime.tzinfo` attribute, the
+ common :attr:`~.datetime.tzinfo` attribute is ignored and the base datetimes are
+ compared. If both comparands are aware and have different :attr:`~.datetime.tzinfo`
attributes, the comparands are first adjusted by subtracting their UTC
offsets (obtained from ``self.utcoffset()``).
.. versionchanged:: 3.3
- Equality comparisons between naive and aware :class:`datetime`
+ Equality comparisons between naive and aware :class:`.datetime`
instances don't raise :exc:`TypeError`.
.. note::
.. method:: datetime.time()
Return :class:`.time` object with same hour, minute, second and microsecond.
- :attr:`tzinfo` is ``None``. See also method :meth:`timetz`.
+ :attr:`.tzinfo` is ``None``. See also method :meth:`timetz`.
.. method:: datetime.timetz()
.. method:: datetime.astimezone(tz=None)
- Return a :class:`datetime` object with new :attr:`tzinfo` attribute *tz*,
+ Return a :class:`.datetime` object with new :attr:`.tzinfo` attribute *tz*,
adjusting the date and time data so the result is the same UTC time as
*self*, but in *tz*'s local time.
not return ``None``).
If called without arguments (or with ``tz=None``) the system local
- timezone is assumed. The ``tzinfo`` attribute of the converted
+ timezone is assumed. The ``.tzinfo`` attribute of the converted
datetime instance will be set to an instance of :class:`timezone`
with the zone name and offset obtained from the OS.
.. method:: datetime.utcoffset()
- If :attr:`tzinfo` is ``None``, returns ``None``, else returns
+ If :attr:`.tzinfo` is ``None``, returns ``None``, else returns
``self.tzinfo.utcoffset(self)``, and raises an exception if the latter doesn't
return ``None``, or a :class:`timedelta` object representing a whole number of
minutes with magnitude less than one day.
.. method:: datetime.dst()
- If :attr:`tzinfo` is ``None``, returns ``None``, else returns
+ If :attr:`.tzinfo` is ``None``, returns ``None``, else returns
``self.tzinfo.dst(self)``, and raises an exception if the latter doesn't return
``None``, or a :class:`timedelta` object representing a whole number of minutes
with magnitude less than one day.
.. method:: datetime.tzname()
- If :attr:`tzinfo` is ``None``, returns ``None``, else returns
+ If :attr:`.tzinfo` is ``None``, returns ``None``, else returns
``self.tzinfo.tzname(self)``, raises an exception if the latter doesn't return
``None`` or a string object,
d.hour, d.minute, d.second, d.weekday(), yday, dst))``, where ``yday =
d.toordinal() - date(d.year, 1, 1).toordinal() + 1`` is the day number within
the current year starting with ``1`` for January 1st. The :attr:`tm_isdst` flag
- of the result is set according to the :meth:`dst` method: :attr:`tzinfo` is
+ of the result is set according to the :meth:`dst` method: :attr:`.tzinfo` is
``None`` or :meth:`dst` returns ``None``, :attr:`tm_isdst` is set to ``-1``;
else if :meth:`dst` returns a non-zero value, :attr:`tm_isdst` is set to ``1``;
else :attr:`tm_isdst` is set to ``0``.
.. method:: datetime.timestamp()
- Return POSIX timestamp corresponding to the :class:`datetime`
+ Return POSIX timestamp corresponding to the :class:`.datetime`
instance. The return value is a :class:`float` similar to that
returned by :func:`time.time`.
- Naive :class:`datetime` instances are assumed to represent local
+ Naive :class:`.datetime` instances are assumed to represent local
time and this method relies on the platform C :c:func:`mktime`
- function to perform the conversion. Since :class:`datetime`
+ function to perform the conversion. Since :class:`.datetime`
supports wider range of values than :c:func:`mktime` on many
platforms, this method may raise :exc:`OverflowError` for times far
in the past or far in the future.
- For aware :class:`datetime` instances, the return value is computed
+ For aware :class:`.datetime` instances, the return value is computed
as::
(dt - datetime(1970, 1, 1, tzinfo=timezone.utc)).total_seconds()
.. note::
There is no method to obtain the POSIX timestamp directly from a
- naive :class:`datetime` instance representing UTC time. If your
+ naive :class:`.datetime` instance representing UTC time. If your
application uses this convention and your system timezone is not
set to UTC, you can obtain the POSIX timestamp by supplying
``tzinfo=timezone.utc``::
.. method:: datetime.__format__(format)
- Same as :meth:`.datetime.strftime`. This makes it possible to specify format
+ Same as :meth:`.datetime.strftime`. This makes it possible to specify a format
string for a :class:`.datetime` object when using :meth:`str.format`. For a
complete list of formatting directives, see
:ref:`strftime-strptime-behavior`.
comparisons, naive instances are never equal to aware instances.
If both comparands are aware, and have
- the same :attr:`tzinfo` attribute, the common :attr:`tzinfo` attribute is
+ the same :attr:`~time.tzinfo` attribute, the common :attr:`~time.tzinfo` attribute is
ignored and the base times are compared. If both comparands are aware and
- have different :attr:`tzinfo` attributes, the comparands are first adjusted by
+ have different :attr:`~time.tzinfo` attributes, the comparands are first adjusted by
subtracting their UTC offsets (obtained from ``self.utcoffset()``). In order
to stop mixed-type comparisons from falling back to the default comparison by
object address, when a :class:`.time` object is compared to an object of a
.. method:: time.__format__(format)
- Same as :meth:`.time.strftime`. This makes it possible to specify format string
+ Same as :meth:`.time.strftime`. This makes it possible to specify a format string
for a :class:`.time` object when using :meth:`str.format`. For a
complete list of formatting directives, see
:ref:`strftime-strptime-behavior`.
.. method:: time.utcoffset()
- If :attr:`tzinfo` is ``None``, returns ``None``, else returns
+ If :attr:`.tzinfo` is ``None``, returns ``None``, else returns
``self.tzinfo.utcoffset(None)``, and raises an exception if the latter doesn't
return ``None`` or a :class:`timedelta` object representing a whole number of
minutes with magnitude less than one day.
.. method:: time.dst()
- If :attr:`tzinfo` is ``None``, returns ``None``, else returns
+ If :attr:`.tzinfo` is ``None``, returns ``None``, else returns
``self.tzinfo.dst(None)``, and raises an exception if the latter doesn't return
``None``, or a :class:`timedelta` object representing a whole number of minutes
with magnitude less than one day.
.. method:: time.tzname()
- If :attr:`tzinfo` is ``None``, returns ``None``, else returns
+ If :attr:`.tzinfo` is ``None``, returns ``None``, else returns
``self.tzinfo.tzname(None)``, or raises an exception if the latter doesn't
return ``None`` or a string object.
:class:`tzinfo` Objects
-----------------------
-:class:`tzinfo` is an abstract base class, meaning that this class should not be
-instantiated directly. You need to derive a concrete subclass, and (at least)
-supply implementations of the standard :class:`tzinfo` methods needed by the
-:class:`.datetime` methods you use. The :mod:`datetime` module supplies
-a simple concrete subclass of :class:`tzinfo` :class:`timezone` which can represent
-timezones with fixed offset from UTC such as UTC itself or North American EST and
-EDT.
+.. class:: tzinfo()
+
+ This is an abstract base class, meaning that this class should not be
+ instantiated directly. You need to derive a concrete subclass, and (at least)
+ supply implementations of the standard :class:`tzinfo` methods needed by the
+ :class:`.datetime` methods you use. The :mod:`datetime` module supplies
+ a simple concrete subclass of :class:`tzinfo`, :class:`timezone`, which can represent
+ timezones with fixed offset from UTC such as UTC itself or North American EST and
+ EDT.
-An instance of (a concrete subclass of) :class:`tzinfo` can be passed to the
-constructors for :class:`.datetime` and :class:`.time` objects. The latter objects
-view their attributes as being in local time, and the :class:`tzinfo` object
-supports methods revealing offset of local time from UTC, the name of the time
-zone, and DST offset, all relative to a date or time object passed to them.
+ An instance of (a concrete subclass of) :class:`tzinfo` can be passed to the
+ constructors for :class:`.datetime` and :class:`.time` objects. The latter objects
+ view their attributes as being in local time, and the :class:`tzinfo` object
+ supports methods revealing offset of local time from UTC, the name of the time
+ zone, and DST offset, all relative to a date or time object passed to them.
-Special requirement for pickling: A :class:`tzinfo` subclass must have an
-:meth:`__init__` method that can be called with no arguments, else it can be
-pickled but possibly not unpickled again. This is a technical requirement that
-may be relaxed in the future.
+ Special requirement for pickling: A :class:`tzinfo` subclass must have an
+ :meth:`__init__` method that can be called with no arguments, else it can be
+ pickled but possibly not unpickled again. This is a technical requirement that
+ may be relaxed in the future.
-A concrete subclass of :class:`tzinfo` may need to implement the following
-methods. Exactly which methods are needed depends on the uses made of aware
-:mod:`datetime` objects. If in doubt, simply implement all of them.
+ A concrete subclass of :class:`tzinfo` may need to implement the following
+ methods. Exactly which methods are needed depends on the uses made of aware
+ :mod:`datetime` objects. If in doubt, simply implement all of them.
.. method:: tzinfo.utcoffset(dt)
(see :meth:`utcoffset` for details). Note that DST offset, if applicable, has
already been added to the UTC offset returned by :meth:`utcoffset`, so there's
no need to consult :meth:`dst` unless you're interested in obtaining DST info
- separately. For example, :meth:`datetime.timetuple` calls its :attr:`tzinfo`
+ separately. For example, :meth:`datetime.timetuple` calls its :attr:`~.datetime.tzinfo`
attribute's :meth:`dst` method to determine how the :attr:`tm_isdst` flag
should be set, and :meth:`tzinfo.fromutc` calls :meth:`dst` to account for
DST changes when crossing time zones.
*pytz* library brings the *IANA timezone database* (also known as the
Olson database) to Python and its usage is recommended.
- `IANA timezone database <http://www.iana.org/time-zones>`_
+ `IANA timezone database <https://www.iana.org/time-zones>`_
The Time Zone Database (often called tz or zoneinfo) contains code and
data that represent the history of local time for many representative
locations around the globe. It is updated periodically to reflect changes
+-----------+--------------------------------+------------------------+-------+
| ``%z`` | UTC offset in the form +HHMM | (empty), +0000, -0400, | \(6) |
| | or -HHMM (empty string if the | +1030 | |
-| | the object is naive). | | |
+| | object is naive). | | |
+-----------+--------------------------------+------------------------+-------+
| ``%Z`` | Time zone name (empty string | (empty), UTC, EST, CST | |
| | if the object is naive). | | |
.. module:: dbm
:synopsis: Interfaces to various Unix "database" formats.
+**Source code:** :source:`Lib/dbm/__init__.py`
+
+--------------
+
:mod:`dbm` is a generic interface to variants of the DBM database ---
:mod:`dbm.gnu` or :mod:`dbm.ndbm`. If none of these modules is installed, the
slow-but-simple implementation in module :mod:`dbm.dumb` will be used. There
-is a `third party interface <http://www.jcea.es/programacion/pybsddb.htm>`_ to
+is a `third party interface <https://www.jcea.es/programacion/pybsddb.htm>`_ to
the Oracle Berkeley DB.
# make sure each group gets a fresh context
setcontext(Context())
+--------------
+
The :mod:`decimal` module provides support for fast correctly-rounded
decimal floating point arithmetic. It offers several advantages over the
:class:`float` datatype:
* IBM's General Decimal Arithmetic Specification, `The General Decimal Arithmetic
Specification <http://speleotrove.com/decimal/decarith.html>`_.
- * IEEE standard 854-1987, `Unofficial IEEE 854 Text
- <http://754r.ucbtest.org/standards/854.pdf>`_.
-
.. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
.. module:: difflib
:synopsis: Helpers for computing differences between objects.
+
.. moduleauthor:: Tim Peters <tim_one@users.sourceforge.net>
.. sectionauthor:: Tim Peters <tim_one@users.sourceforge.net>
.. Markup by Fred L. Drake, Jr. <fdrake@acm.org>
import sys
from difflib import *
+--------------
+
This module provides classes and functions for comparing sequences. It
can be used for example, for comparing files, and can produce difference
information in various formats, including HTML and context and unified
| | are equal). |
+---------------+---------------------------------------------+
- For example:
+ For example::
>>> a = "qabxcd"
>>> b = "abycdf"
>>> s = SequenceMatcher(None, a, b)
>>> for tag, i1, i2, j1, j2 in s.get_opcodes():
- print('{:7} a[{}:{}] --> b[{}:{}] {!r:>8} --> {!r}'.format(
- tag, i1, i2, j1, j2, a[i1:i2], b[j1:j2]))
-
-
+ ... print('{:7} a[{}:{}] --> b[{}:{}] {!r:>8} --> {!r}'.format(
+ ... tag, i1, i2, j1, j2, a[i1:i2], b[j1:j2]))
delete a[0:1] --> b[0:0] 'q' --> ''
equal a[1:3] --> b[0:2] 'ab' --> 'ab'
replace a[3:4] --> b[2:3] 'x' --> 'y'
work.
* `Simple version control recipe
- <http://code.activestate.com/recipes/576729/>`_ for a small application
+ <https://code.activestate.com/recipes/576729/>`_ for a small application
built with :class:`SequenceMatcher`.
Disassemble the *x* object. *x* can denote either a module, a class, a
method, a function, a generator, a code object, a string of source code or
a byte sequence of raw bytecode. For a module, it disassembles all functions.
- For a class, it disassembles all methods. For a code object or sequence of
- raw bytecode, it prints one line per bytecode instruction. Strings are first
- compiled to code objects with the :func:`compile` built-in function before being
- disassembled. If no object is provided, this function disassembles the last
- traceback.
+ For a class, it disassembles all methods (including class and static methods).
+ For a code object or sequence of raw bytecode, it prints one line per bytecode
+ instruction. Strings are first compiled to code objects with the :func:`compile`
+ built-in function before being disassembled. If no object is provided, this
+ function disassembles the last traceback.
The disassembly is written as text to the supplied *file* argument if
provided and to ``sys.stdout`` otherwise.
Implements assignment with a starred target: Unpacks an iterable in TOS into
individual values, where the total number of values can be smaller than the
- number of items in the iterable: one the new values will be a list of all
+ number of items in the iterable: one of the new values will be a list of all
leftover items.
The low byte of *counts* is the number of values before the list value, the
.. module:: distutils
:synopsis: Support for building and installing Python modules into an
existing Python installation.
+
.. sectionauthor:: Fred L. Drake, Jr. <fdrake@acm.org>
+--------------
The :mod:`distutils` package provides support for building and installing
additional modules into a Python installation. The new modules may be either
Most Python users will *not* want to use this module directly, but instead
use the cross-version tools maintained by the Python Packaging Authority. In
particular,
-`setuptools <https://setuptools.pypa.io/en/latest/setuptools.html>`__ is an
+`setuptools <https://setuptools.readthedocs.io/en/latest/>`__ is an
enhanced alternative to :mod:`distutils` that provides:
* support for declaring project dependencies
.. module:: doctest
:synopsis: Test pieces of code within docstrings.
+
.. moduleauthor:: Tim Peters <tim@python.org>
.. sectionauthor:: Tim Peters <tim@python.org>
.. sectionauthor:: Moshe Zadka <moshez@debian.org>
.. sectionauthor:: Edward Loper <edloper@users.sourceforge.net>
+**Source code:** :source:`Lib/doctest.py`
+
+--------------
The :mod:`doctest` module searches for pieces of text that look like interactive
Python sessions, and then executes those sessions to verify that they work
.. module:: email.charset
:synopsis: Character Sets
+**Source code:** :source:`Lib/email/charset.py`
+
+--------------
This module provides a class :class:`Charset` for representing character sets
and character set conversions in email messages, as well as a character set
returns the string ``base64`` if *body_encoding* is ``BASE64``, and
returns the string ``7bit`` otherwise.
+
.. XXX to_splittable and from_splittable are not there anymore!
- .. method to_splittable(s)
+ .. to_splittable(s)
Convert a possibly multibyte string to a safely splittable format. *s* is
the string to split.
the Unicode replacement character ``'U+FFFD'``.
- .. method from_splittable(ustr[, to_output])
+ .. from_splittable(ustr[, to_output])
Convert a splittable string back into an encoded string. *ustr* is a
Unicode string to "unsplit".
.. moduleauthor:: R. David Murray <rdmurray@bitdance.com>
.. sectionauthor:: R. David Murray <rdmurray@bitdance.com>
+.. versionadded:: 3.4
+ as a :term:`provisional module <provisional package>`.
+
+**Source code:** :source:`Lib/email/contentmanager.py`
.. note::
changes (up to and including removal of the module) may occur if deemed
necessary by the core developers.
-.. versionadded:: 3.4
- as a :term:`provisional module <provisional package>`.
+--------------
The :mod:`~email.message` module provides a class that can represent an
arbitrary email message. That basic message model has a useful and flexible
.. module:: email.encoders
:synopsis: Encoders for email message payloads.
+**Source code:** :source:`Lib/email/encoders.py`
+
+--------------
When creating :class:`~email.message.Message` objects from scratch, you often
need to encode the payloads for transport through compliant mail servers. This
.. module:: email.errors
:synopsis: The exception classes used by the email package.
+**Source code:** :source:`Lib/email/errors.py`
+
+--------------
The following exception classes are defined in the :mod:`email.errors` module:
.. module:: email.generator
:synopsis: Generate flat text email messages from a message structure.
+**Source code:** :source:`Lib/email/generator.py`
+
+--------------
One of the most common tasks is to generate the flat text of the email message
represented by a message object structure. You will need to do this if you want
followed by a space at the beginning of the line. This is the only guaranteed
portable way to avoid having such lines be mistaken for a Unix mailbox format
envelope header separator (see `WHY THE CONTENT-LENGTH FORMAT IS BAD
- <http://www.jwz.org/doc/content-length.html>`_ for details). *mangle_from_*
+ <https://www.jwz.org/doc/content-length.html>`_ for details). *mangle_from_*
defaults to ``True``, but you might want to set this to ``False`` if you are not
writing Unix mailbox format files.
i.e. ``From`` followed by a space at the beginning of the line. This is the
only guaranteed portable way to avoid having such lines be mistaken for a
Unix mailbox format envelope header separator (see `WHY THE CONTENT-LENGTH
- FORMAT IS BAD <http://www.jwz.org/doc/content-length.html>`_ for details).
+ FORMAT IS BAD <https://www.jwz.org/doc/content-length.html>`_ for details).
*mangle_from_* defaults to ``True``, but you might want to set this to
``False`` if you are not writing Unix mailbox format files.
.. module:: email.header
:synopsis: Representing non-ASCII headers
+**Source code:** :source:`Lib/email/header.py`
+
+--------------
:rfc:`2822` is the base standard that describes the format of email messages.
It derives from the older :rfc:`822` standard which came into widespread use at
.. moduleauthor:: R. David Murray <rdmurray@bitdance.com>
.. sectionauthor:: R. David Murray <rdmurray@bitdance.com>
+.. versionadded:: 3.3
+ as a :term:`provisional module <provisional package>`.
+
+**Source code:** :source:`Lib/email/headerregistry.py`
.. note::
changes (up to and including removal of the module) may occur if deemed
necessary by the core developers.
-.. versionadded:: 3.3
- as a :term:`provisional module <provisional package>`.
+--------------
Headers are represented by customized subclasses of :class:`str`. The
particular class used to represent a given header is determined by the
:class:`~datetime.datetime` instance. This means, for example, that
the following code is valid and does what one would expect::
- msg['Date'] = datetime(2011, 7, 15, 21)
+ msg['Date'] = datetime(2011, 7, 15, 21)
Because this is a naive ``datetime`` it will be interpreted as a UTC
timestamp, and the resulting value will have a timezone of ``-0000``. Much
.. module:: email.iterators
:synopsis: Iterate over a message object tree.
+**Source code:** :source:`Lib/email/iterators.py`
+
+--------------
Iterating over a message object tree is fairly easy with the
:meth:`Message.walk <email.message.Message.walk>` method. The
.. module:: email.message
:synopsis: The base class representing email messages.
+**Source code:** :source:`Lib/email/message.py`
+
+--------------
The central class in the :mod:`email` package is the :class:`Message` class,
imported from the :mod:`email.message` module. It is the base class for the
.. module:: email.mime
:synopsis: Build MIME messages.
+**Source code:** :source:`Lib/email/mime/`
+
+--------------
Ordinarily, you get a message object structure by passing a file or some text to
a parser, which parses the text and returns the root message object. However
.. module:: email.parser
:synopsis: Parse flat text email messages to produce a message object structure.
+**Source code:** :source:`Lib/email/parser.py`
+
+--------------
Message object structures can be created in one of two ways: they can be created
from whole cloth by instantiating :class:`~email.message.Message` objects and
.. versionadded:: 3.3
+**Source code:** :source:`Lib/email/policy.py`
+
+--------------
The :mod:`email` package's prime focus is the handling of email messages as
described by the various email and MIME RFCs. However, the general format of
.. module:: email
:synopsis: Package supporting the parsing, manipulating, and generating
email messages, including MIME documents.
+
.. moduleauthor:: Barry A. Warsaw <barry@python.org>
.. sectionauthor:: Barry A. Warsaw <barry@python.org>
.. Copyright (C) 2001-2010 Python Software Foundation
+**Source code:** :source:`Lib/email/__init__.py`
+
+--------------
The :mod:`email` package is a library for managing email messages, including
MIME and other :rfc:`2822`\ -based message documents. It is specifically *not*
.. module:: email.utils
:synopsis: Miscellaneous email package utilities.
+**Source code:** :source:`Lib/email/utils.py`
+
+--------------
There are several useful utilities provided in the :mod:`email.utils` module:
.. versionadded:: 3.4
+--------------
+
The :mod:`ensurepip` package provides support for bootstrapping the ``pip``
installer into an existing Python installation or virtual environment. This
bootstrapping approach reflects the fact that ``pip`` is an independent
>>> str(Mood.funky)
'my custom str! 1'
-The rules for what is allowed are as follows: names that start and end with a
-with a single underscore are reserved by enum and cannot be used; all other
+The rules for what is allowed are as follows: names that start and end with
+a single underscore are reserved by enum and cannot be used; all other
attributes defined within an enumeration will become members of this
enumeration, with the exception of special methods (:meth:`__str__`,
:meth:`__add__`, etc.) and descriptors (methods are also descriptors).
3. When another data type is mixed in, the :attr:`value` attribute is *not the
same* as the enum member itself, although it is equivalent and will compare
equal.
-4. %-style formatting: `%s` and `%r` call :class:`Enum`'s :meth:`__str__` and
- :meth:`__repr__` respectively; other codes (such as `%i` or `%h` for
- IntEnum) treat the enum member as its mixed-in type.
-5. :meth:`str.__format__` (or :func:`format`) will use the mixed-in
- type's :meth:`__format__`. If the :class:`Enum`'s :func:`str` or
- :func:`repr` is desired use the `!s` or `!r` :class:`str` format codes.
+4. %-style formatting: `%s` and `%r` call the :class:`Enum` class's
+ :meth:`__str__` and :meth:`__repr__` respectively; other codes (such as
+ `%i` or `%h` for IntEnum) treat the enum member as its mixed-in type.
+5. :meth:`str.format` (or :func:`format`) will use the mixed-in
+ type's :meth:`__format__`. If the :class:`Enum` class's :func:`str` or
+ :func:`repr` is desired, use the `!s` or `!r` format codes.
Interesting examples
.. module:: errno
:synopsis: Standard errno system symbols.
+----------------
This module makes available standard ``errno`` system symbols. The value of each
symbol is the corresponding integer value. The names and descriptions are
.. versionchanged:: 3.3
:exc:`EnvironmentError`, :exc:`IOError`, :exc:`WindowsError`,
- :exc:`VMSError`, :exc:`socket.error`, :exc:`select.error` and
+ :exc:`socket.error`, :exc:`select.error` and
:exc:`mmap.error` have been merged into :exc:`OSError`, and the
constructor may return a subclass.
.. versionadded:: 3.3
+----------------
+
This module contains functions to dump Python tracebacks explicitly, on a fault,
after a timeout, or on a user signal. Call :func:`faulthandler.enable` to
install fault handlers for the :const:`SIGSEGV`, :const:`SIGFPE`,
.. module:: fcntl
:platform: Unix
:synopsis: The fcntl() and ioctl() system calls.
-.. sectionauthor:: Jaap Vermeulen
+.. sectionauthor:: Jaap Vermeulen
.. index::
pair: UNIX; file control
pair: UNIX; I/O control
+----------------
+
This module performs file control and I/O control on file descriptors. It is an
-interface to the :c:func:`fcntl` and :c:func:`ioctl` Unix routines.
+interface to the :c:func:`fcntl` and :c:func:`ioctl` Unix routines. For a
+complete description of these calls, see :manpage:`fcntl(2)` and
+:manpage:`ioctl(2)` Unix manual pages.
All functions in this module take a file descriptor *fd* as their first
argument. This can be an integer file descriptor, such as returned by
buffer 1024 bytes long which is then passed to :func:`ioctl` and copied back
into the supplied buffer.
- If the :c:func:`ioctl` fails, an :exc:`IOError` exception is raised.
+ If the :c:func:`ioctl` fails, an :exc:`OSError` exception is raised.
An example::
:manpage:`flock(2)` for details. (On some systems, this function is emulated
using :c:func:`fcntl`.)
- If the :c:func:`flock` fails, an :exc:`IOError` exception is raised.
+ If the :c:func:`flock` fails, an :exc:`OSError` exception is raised.
.. function:: lockf(fd, cmd, len=0, start=0, whence=0)
.. module:: filecmp
:synopsis: Compare files efficiently.
+
.. sectionauthor:: Moshe Zadka <moshez@zadka.site.co.il>
**Source code:** :source:`Lib/filecmp.py`
.. module:: fileinput
:synopsis: Loop over standard input or a list of files.
+
.. moduleauthor:: Guido van Rossum <guido@python.org>
.. sectionauthor:: Fred L. Drake, Jr. <fdrake@acm.org>
.. versionchanged:: 3.2
Can be used as a context manager.
+ .. versionchanged:: 3.5.2
+ The *bufsize* parameter is no longer used.
+
The following functions use the global state created by :func:`fileinput.input`;
if there is no active state, :exc:`RuntimeError` is raised.
Can be used as a context manager.
.. deprecated:: 3.4
- The ``'rU'`` and ``'U'`` modes.
+ The ``'rU'`` and ``'U'`` modes.
+
+ .. versionchanged:: 3.5.2
+ The *bufsize* parameter is no longer used.
**Optional in-place filtering:** if the keyword argument ``inplace=True`` is
.. function:: hook_encoded(encoding)
- Returns a hook which opens each file with :func:`codecs.open`, using the given
+ Returns a hook which opens each file with :func:`open`, using the given
*encoding* to read the file.
Usage example: ``fi =
.. module:: fnmatch
:synopsis: Unix shell style filename pattern matching.
+**Source code:** :source:`Lib/fnmatch.py`
.. index:: single: filenames; wildcard expansion
.. index:: module: re
-**Source code:** :source:`Lib/fnmatch.py`
-
--------------
This module provides support for Unix shell-style wildcards, which are *not* the
.. deprecated:: 3.4
Due to lack of usage, the formatter module has been deprecated.
+--------------
This module supports two interface definitions, each with multiple
implementations: The *formatter* interface, and the *writer* interface which is
.. module:: fpectl
:platform: Unix
:synopsis: Provide control for floating point exception handling.
+
.. moduleauthor:: Lee Busby <busby1@llnl.gov>
.. sectionauthor:: Lee Busby <busby1@llnl.gov>
-
.. note::
The :mod:`fpectl` module is not built by default, and its usage is discouraged
.. index:: single: IEEE-754
+--------------
+
Most computers carry out floating point operations in conformance with the
so-called IEEE-754 standard. On any real computer, some floating point
operations produce results that cannot be expressed as a normal floating point
.. module:: fractions
:synopsis: Rational numbers.
+
.. moduleauthor:: Jeffrey Yasskin <jyasskin at gmail.com>
.. sectionauthor:: Jeffrey Yasskin <jyasskin at gmail.com>
.. module:: ftplib
:synopsis: FTP protocol client (requires sockets).
+**Source code:** :source:`Lib/ftplib.py`
.. index::
pair: FTP; protocol
single: FTP; ftplib (standard module)
-**Source code:** :source:`Lib/ftplib.py`
-
--------------
This module defines the class :class:`FTP` and a few related items. The
:class:`FTP` class implements the client side of the FTP protocol. You can use
this to write Python programs that perform a variety of automated FTP jobs, such
-as mirroring other ftp servers. It is also used by the module
+as mirroring other FTP servers. It is also used by the module
:mod:`urllib.request` to handle URLs that use FTP. For more information on FTP
(File Transfer Protocol), see Internet :rfc:`959`.
typically used by FTP clients to load user authentication information
before prompting the user.
- .. index:: single: ftpmirror.py
-
- The file :file:`Tools/scripts/ftpmirror.py` in the Python source distribution is
- a script that can mirror FTP sites, or portions thereof, using the :mod:`ftplib`
- module. It can be used as an extended example that applies this module.
-
.. _ftp-objects:
.. method:: FTP.mlsd(path="", facts=[])
- List a directory in a standardized format by using MLSD command
+ List a directory in a standardized format by using ``MLSD`` command
(:rfc:`3659`). If *path* is omitted the current directory is assumed.
*facts* is a list of strings representing the type of information desired
(e.g. ``["type", "size", "perm"]``). Return a generator object yielding a
directory). Multiple arguments can be used to pass non-standard options to
the ``NLST`` command.
- .. deprecated:: 3.3 use :meth:`mlsd` instead.
+ .. note:: If your server supports the command, :meth:`mlsd` offers a better API.
.. method:: FTP.dir(argument[, ...])
as a *callback* function as for :meth:`retrlines`; the default prints to
``sys.stdout``. This method returns ``None``.
- .. deprecated:: 3.3 use :meth:`mlsd` instead.
+ .. note:: If your server supports the command, :meth:`mlsd` offers a better API.
.. method:: FTP.rename(fromname, toname)
Return the string representing a character whose Unicode code point is the
integer *i*. For example, ``chr(97)`` returns the string ``'a'``, while
- ``chr(957)`` returns the string ``'ν'``. This is the inverse of :func:`ord`.
+ ``chr(8364)`` returns the string ``'€'``. This is the inverse of :func:`ord`.
The valid range for the argument is from 0 through 1,114,111 (0x10FFFF in
base 16). :exc:`ValueError` will be raised if *i* is outside that range.
or ``2`` (docstrings are removed too).
This function raises :exc:`SyntaxError` if the compiled source is invalid,
- and :exc:`TypeError` if the source contains null bytes.
+ and :exc:`ValueError` if the source contains null bytes.
If you want to parse Python code into its AST representation, see
:func:`ast.parse`.
Allowed use of Windows and Mac newlines. Also input in ``'exec'`` mode
does not have to end in a newline anymore. Added the *optimize* parameter.
+ .. versionchanged:: 3.5
+ Previously, :exc:`TypeError` was raised when null bytes were encountered
+ in *source*.
+
.. class:: complex([real[, imag]])
exception, the function now retries the system call instead of raising an
:exc:`InterruptedError` exception (see :pep:`475` for the rationale).
+ .. versionchanged:: 3.5
+ The ``'namereplace'`` error handler was added.
.. function:: ord(c)
Given a string representing one Unicode character, return an integer
representing the Unicode code point of that character. For example,
- ``ord('a')`` returns the integer ``97`` and ``ord('ν')`` returns ``957``.
- This is the inverse of :func:`chr`.
+ ``ord('a')`` returns the integer ``97`` and ``ord('€')`` (Euro sign)
+ returns ``8364``. This is the inverse of :func:`chr`.
.. function:: pow(x, y[, z])
compare equal --- this is helpful for sorting in multiple passes (for
example, sort by department, then by salary grade).
- For sorting examples and a brief sorting tutorial, see `Sorting HowTo
- <https://wiki.python.org/moin/HowTo/Sorting/>`_\.
+ For sorting examples and a brief sorting tutorial, see :ref:`sortinghowto`.
.. function:: staticmethod(function)
For practical suggestions on how to design cooperative classes using
:func:`super`, see `guide to using super()
- <http://rhettinger.wordpress.com/2011/05/26/super-considered-super/>`_.
+ <https://rhettinger.wordpress.com/2011/05/26/super-considered-super/>`_.
.. _func-tuple:
class name and becomes the :attr:`~class.__name__` attribute; the *bases*
tuple itemizes the base classes and becomes the :attr:`~class.__bases__`
attribute; and the *dict* dictionary is the namespace containing definitions
- for class body and becomes the :attr:`~object.__dict__` attribute. For
- example, the following two statements create identical :class:`type` objects:
+ for class body and is copied to a standard dictionary to become the
+ :attr:`~object.__dict__` attribute. For example, the following two
+ statements create identical :class:`type` objects:
>>> class X:
... a = 1
.. module:: functools
:synopsis: Higher-order functions and operations on callable objects.
+
.. moduleauthor:: Peter Harris <scav@blueyonder.co.uk>
.. moduleauthor:: Raymond Hettinger <python@rcn.com>
.. moduleauthor:: Nick Coghlan <ncoghlan@gmail.com>
bypassing the cache, or for rewrapping the function with a different cache.
An `LRU (least recently used) cache
- <http://en.wikipedia.org/wiki/Cache_algorithms#Examples>`_ works
+ <https://en.wikipedia.org/wiki/Cache_algorithms#Examples>`_ works
best when the most recent calls are the best predictors of upcoming calls (for
example, the most popular articles on a news server tend to change each day).
The cache's size limit assures that the cache does not grow without bound on
CacheInfo(hits=3, misses=8, maxsize=32, currsize=8)
Example of efficiently computing
- `Fibonacci numbers <http://en.wikipedia.org/wiki/Fibonacci_number>`_
+ `Fibonacci numbers <https://en.wikipedia.org/wiki/Fibonacci_number>`_
using a cache to implement a
- `dynamic programming <http://en.wikipedia.org/wiki/Dynamic_programming>`_
+ `dynamic programming <https://en.wikipedia.org/wiki/Dynamic_programming>`_
technique::
@lru_cache(maxsize=None)
def newfunc(*fargs, **fkeywords):
newkeywords = keywords.copy()
newkeywords.update(fkeywords)
- return func(*(args + fargs), **newkeywords)
+ return func(*args, *fargs, **newkeywords)
newfunc.func = func
newfunc.args = args
newfunc.keywords = keywords
assigned directly to the matching attributes on the wrapper function and which
attributes of the wrapper function are updated with the corresponding attributes
from the original function. The default values for these arguments are the
- module level constants *WRAPPER_ASSIGNMENTS* (which assigns to the wrapper
- function's *__name__*, *__module__*, *__annotations__* and *__doc__*, the
- documentation string) and *WRAPPER_UPDATES* (which updates the wrapper
- function's *__dict__*, i.e. the instance dictionary).
+ module level constants ``WRAPPER_ASSIGNMENTS`` (which assigns to the wrapper
+ function's ``__module__``, ``__name__``, ``__qualname__``, ``__annotations__``
+ and ``__doc__``, the documentation string) and ``WRAPPER_UPDATES`` (which
+ updates the wrapper function's ``__dict__``, i.e. the instance dictionary).
To allow access to the original function for introspection and other purposes
(e.g. bypassing a caching decorator such as :func:`lru_cache`), this function
.. module:: gc
:synopsis: Interface to the cycle-detecting garbage collector.
+
.. moduleauthor:: Neil Schemenauer <nas@arctrix.com>
.. sectionauthor:: Neil Schemenauer <nas@arctrix.com>
+--------------
This module provides an interface to the optional garbage collector. It
provides the ability to disable the collector, tune the collection frequency,
**Source code:** :source:`Lib/getopt.py`
---------------
-
.. note::
The :mod:`getopt` module is a parser for command line options whose API is
less code and get better help and error messages should consider using the
:mod:`argparse` module instead.
+--------------
+
This module helps scripts to parse the command line arguments in ``sys.argv``.
It supports the same conventions as the Unix :c:func:`getopt` function (including
the special meanings of arguments of the form '``-``' and '``--``'). Long
opts, args = getopt.getopt(sys.argv[1:], "ho:v", ["help", "output="])
except getopt.GetoptError as err:
# print help information and exit:
- print(err) # will print something like "option -a not recognized"
+ print(err) # will print something like "option -a not recognized"
usage()
sys.exit(2)
output = None
.. module:: getpass
:synopsis: Portable reading of passwords and retrieval of the userid.
+
.. moduleauthor:: Piers Lauder <piers@cs.su.oz.au>
.. sectionauthor:: Fred L. Drake, Jr. <fdrake@acm.org>
.. Windows (& Mac?) support by Guido van Rossum.
+**Source code:** :source:`Lib/getpass.py`
+
+--------------
+
The :mod:`getpass` module provides two functions:
a warning message to *stream* and reading from ``sys.stdin`` and
issuing a :exc:`GetPassWarning`.
- Availability: Macintosh, Unix, Windows.
-
.. note::
If you call getpass from within IDLE, the input may be done in the
terminal you launched IDLE from rather than the idle window itself.
.. function:: getuser()
- Return the "login name" of the user. Availability: Unix, Windows.
+ Return the "login name" of the user.
This function checks the environment variables :envvar:`LOGNAME`,
:envvar:`USER`, :envvar:`LNAME` and :envvar:`USERNAME`, in order, and returns
.. module:: gettext
:synopsis: Multilingual internationalization services.
+
.. moduleauthor:: Barry A. Warsaw <barry@python.org>
.. sectionauthor:: Barry A. Warsaw <barry@python.org>
.. module:: glob
:synopsis: Unix shell style pathname pattern expansion.
+**Source code:** :source:`Lib/glob.py`
.. index:: single: filenames; pathname expansion
-**Source code:** :source:`Lib/glob.py`
-
--------------
The :mod:`glob` module finds all the pathnames matching a specified pattern
:platform: Unix
:synopsis: The group database (getgrnam() and friends).
+--------------
This module provides access to the Unix group database. It is available on all
Unix versions.
.. module:: hashlib
:synopsis: Secure hash and message digest algorithms.
+
.. moduleauthor:: Gregory P. Smith <greg@krypto.org>
.. sectionauthor:: Gregory P. Smith <greg@krypto.org>
+**Source code:** :source:`Lib/hashlib.py`
.. index::
single: message digest, MD5
single: secure hash algorithm, SHA1, SHA224, SHA256, SHA384, SHA512
-**Source code:** :source:`Lib/hashlib.py`
-
--------------
This module implements a common interface to many different secure hash and
There is one constructor method named for each type of :dfn:`hash`. All return
a hash object with the same simple interface. For example: use :func:`sha1` to
create a SHA1 hash object. You can now feed this object with :term:`bytes-like
-object`\ s (normally :class:`bytes`) using the :meth:`update` method.
+objects <bytes-like object>` (normally :class:`bytes`) using the :meth:`update` method.
At any point you can ask it for the :dfn:`digest` of the
concatenation of the data fed to it so far using the :meth:`digest` or
:meth:`hexdigest` methods.
include a `salt <https://en.wikipedia.org/wiki/Salt_%28cryptography%29>`_.
-.. function:: pbkdf2_hmac(name, password, salt, rounds, dklen=None)
+.. function:: pbkdf2_hmac(hash_name, password, salt, iterations, dklen=None)
The function provides PKCS#5 password-based key derivation function 2. It
uses HMAC as pseudorandom function.
- The string *name* is the desired name of the hash digest algorithm for
+ The string *hash_name* is the desired name of the hash digest algorithm for
HMAC, e.g. 'sha1' or 'sha256'. *password* and *salt* are interpreted as
buffers of bytes. Applications and libraries should limit *password* to
- a sensible value (e.g. 1024). *salt* should be about 16 or more bytes from
+ a sensible length (e.g. 1024). *salt* should be about 16 or more bytes from
a proper source, e.g. :func:`os.urandom`.
- The number of *rounds* should be chosen based on the hash algorithm and
- computing power. As of 2013, at least 100,000 rounds of SHA-256 is suggested.
+ The number of *iterations* should be chosen based on the hash algorithm and
+ computing power. As of 2013, at least 100,000 iterations of SHA-256 are
+ suggested.
*dklen* is the length of the derived key. If *dklen* is ``None`` then the
- digest size of the hash algorithm *name* is used, e.g. 64 for SHA-512.
+ digest size of the hash algorithm *hash_name* is used, e.g. 64 for SHA-512.
>>> import hashlib, binascii
>>> dk = hashlib.pbkdf2_hmac('sha256', b'password', b'salt', 100000)
Wikipedia article with information on which algorithms have known issues and
what that means regarding their use.
- http://www.ietf.org/rfc/rfc2898.txt
+ https://www.ietf.org/rfc/rfc2898.txt
PKCS #5: Password-Based Cryptography Specification Version 2.0
.. module:: heapq
:synopsis: Heap queue algorithm (a.k.a. priority queue).
+
.. moduleauthor:: Kevin O'Connor
.. sectionauthor:: Guido van Rossum <guido@python.org>
.. sectionauthor:: François Pinard
Basic Examples
--------------
-A `heapsort <http://en.wikipedia.org/wiki/Heapsort>`_ can be implemented by
+A `heapsort <https://en.wikipedia.org/wiki/Heapsort>`_ can be implemented by
pushing all values onto a heap and then popping off the smallest values one at a
time::
Priority Queue Implementation Notes
-----------------------------------
-A `priority queue <http://en.wikipedia.org/wiki/Priority_queue>`_ is common use
+A `priority queue <https://en.wikipedia.org/wiki/Priority_queue>`_ is common use
for a heap, and it presents several implementation challenges:
* Sort stability: how do you get two tasks with equal priorities to be returned
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
-In the tree above, each cell *k* is topping ``2*k+1`` and ``2*k+2``. In an usual
+In the tree above, each cell *k* is topping ``2*k+1`` and ``2*k+2``. In a usual
binary tournament we see in sports, each cell is the winner over the two cells
it tops, and we can trace the winner down the tree to see all opponents s/he
had. However, in many computer applications of such tournaments, we do not need
.. module:: hmac
:synopsis: Keyed-Hashing for Message Authentication (HMAC) implementation
+
.. moduleauthor:: Gerhard Häring <ghaering@users.sourceforge.net>
.. sectionauthor:: Gerhard Häring <ghaering@users.sourceforge.net>
.. module:: html.entities
:synopsis: Definitions of HTML general entities.
+
.. sectionauthor:: Fred L. Drake, Jr. <fdrake@acm.org>
**Source code:** :source:`Lib/html/entities.py`
.. rubric:: Footnotes
-.. [#] See http://www.w3.org/TR/html5/syntax.html#named-character-references
+.. [#] See https://www.w3.org/TR/html5/syntax.html#named-character-references
.. module:: html.parser
:synopsis: A simple parser that can handle HTML and XHTML.
+**Source code:** :source:`Lib/html/parser.py`
.. index::
single: HTML
single: XHTML
-**Source code:** :source:`Lib/html/parser.py`
-
--------------
This module defines a class :class:`HTMLParser` which serves as the basis for
class MyHTMLParser(HTMLParser):
def handle_starttag(self, tag, attrs):
print("Encountered a start tag:", tag)
+
def handle_endtag(self, tag):
print("Encountered an end tag :", tag)
+
def handle_data(self, data):
print("Encountered some data :", data)
and quotes in the *value* have been removed, and character and entity references
have been replaced.
- For instance, for the tag ``<A HREF="http://www.cwi.nl/">``, this method
- would be called as ``handle_starttag('a', [('href', 'http://www.cwi.nl/')])``.
+ For instance, for the tag ``<A HREF="https://www.cwi.nl/">``, this method
+ would be called as ``handle_starttag('a', [('href', 'https://www.cwi.nl/')])``.
All entity references from :mod:`html.entities` are replaced in the attribute
values.
print("Start tag:", tag)
for attr in attrs:
print(" attr:", attr)
+
def handle_endtag(self, tag):
print("End tag :", tag)
+
def handle_data(self, data):
print("Data :", data)
+
def handle_comment(self, data):
print("Comment :", data)
+
def handle_entityref(self, name):
c = chr(name2codepoint[name])
print("Named ent:", c)
+
def handle_charref(self, name):
if name.startswith('x'):
c = chr(int(name[1:], 16))
else:
c = chr(int(name))
print("Num ent :", c)
+
def handle_decl(self, data):
print("Decl :", data)
attr: ('type', 'text/css')
Data : #python { color: green }
End tag : style
- >>>
+
>>> parser.feed('<script type="text/javascript">'
... 'alert("<strong>hello!</strong>");</script>')
Start tag: script
.. module:: http.client
:synopsis: HTTP and HTTPS protocol client (requires sockets).
+**Source code:** :source:`Lib/http/client.py`
.. index::
pair: HTTP; protocol
.. index:: module: urllib.request
-**Source code:** :source:`Lib/http/client.py`
-
--------------
This module defines classes which implement the client side of the HTTP and
.. seealso::
- The `Requests package <http://requests.readthedocs.org/>`_
- is recommended for a higher-level http client interface.
+ The `Requests package <https://requests.readthedocs.org/>`_
+ is recommended for a higher-level HTTP client interface.
.. note::
body. The response is an iterable object and can be used in a with
statement.
+.. versionchanged:: 3.5
+ The :class:`io.BufferedIOBase` interface is now implemented and
+ all of its reader operations are supported.
+
.. method:: HTTPResponse.read([amt])
>>> conn.request("GET", "/")
>>> r1 = conn.getresponse()
>>> while not r1.closed:
- ... print(r1.read(200)) # 200 bytes
+ ... print(r1.read(200)) # 200 bytes
b'<!doctype html>\n<!--[if"...
...
>>> # Example of an invalid request
.. module:: http.cookiejar
:synopsis: Classes for automatic handling of HTTP cookies.
+
.. moduleauthor:: John J. Lee <jjl@pobox.com>
.. sectionauthor:: John J. Lee <jjl@pobox.com>
:mod:`http.cookiejar` and :mod:`http.cookies` modules do not depend on each
other.
- http://curl.haxx.se/rfc/cookie_spec.html
+ https://curl.haxx.se/rfc/cookie_spec.html
The specification of the original Netscape cookie protocol. Though this is
still the dominant protocol, the 'Netscape cookie protocol' implemented by all
the major browsers (and :mod:`http.cookiejar`) only bears a passing resemblance to
.. module:: http.cookies
:synopsis: Support for HTTP state management (cookies).
+
.. moduleauthor:: Timothy O'Malley <timo@alum.mit.edu>
.. sectionauthor:: Moshe Zadka <moshez@zadka.site.co.il>
in HTTP requests, and is not accessible through JavaScript. This is intended
to mitigate some forms of cross-site scripting.
- The keys are case-insensitive.
+ The keys are case-insensitive and their default value is ``''``.
.. versionchanged:: 3.5
:meth:`~Morsel.__eq__` now takes :attr:`~Morsel.key` and :attr:`~Morsel.value`
.. module:: http
:synopsis: HTTP status codes and messages
+**Source code:** :source:`Lib/http/__init__.py`
+
.. index::
pair: HTTP; protocol
single: HTTP; http (standard module)
-**Source code:** :source:`Lib/http/__init__.py`
+--------------
:mod:`http` is a package that collects several modules for working with the
HyperText Transfer Protocol:
-----------------
Supported,
-`IANA-registered <http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml>`_
+`IANA-registered <https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml>`_
status codes available in :class:`http.HTTPStatus` are:
======= =================================== ==================================================================
.. module:: http.server
:synopsis: HTTP server and request handlers.
+**Source code:** :source:`Lib/http/server.py`
.. index::
pair: WWW; server
single: URL
single: httpd
-**Source code:** :source:`Lib/http/server.py`
-
--------------
This module defines classes for implementing HTTP servers (Web servers).
:mod:`http.client` is used to parse the headers and it requires that the
HTTP request provide a valid :rfc:`2822` style header.
-
.. attribute:: rfile
Contains an input stream, positioned at the start of the optional input
client. Proper adherence to the HTTP protocol must be used when writing to
this stream.
- :class:`BaseHTTPRequestHandler` has the following class variables:
+ :class:`BaseHTTPRequestHandler` has the following attributes:
.. attribute:: server_version
.. attribute:: error_message_format
- Specifies a format string for building an error response to the client. It
- uses parenthesized, keyed format specifiers, so the format operand must be
- a dictionary. The *code* key should be an integer, specifying the numeric
- HTTP error code value. *message* should be a string containing a
- (detailed) error message of what occurred, and *explain* should be an
- explanation of the error code number. Default *message* and *explain*
- values can found in the :attr:`responses` class variable.
+ Specifies a format string that should be used by :meth:`send_error` method
+ for building an error response to the client. The string is filled by
+ default with variables from :attr:`responses` based on the status code
+ that passed to :meth:`send_error`.
.. attribute:: error_content_type
.. attribute:: responses
- This variable contains a mapping of error code integers to two-element tuples
+ This attribute contains a mapping of error code integers to two-element tuples
containing a short and long message. For example, ``{code: (shortmessage,
longmessage)}``. The *shortmessage* is usually used as the *message* key in an
- error response, and *longmessage* as the *explain* key (see the
- :attr:`error_message_format` class variable).
+ error response, and *longmessage* as the *explain* key. It is used by
+ :meth:`send_response_only` and :meth:`send_error` methods.
A :class:`BaseHTTPRequestHandler` instance has the following methods:
specifies the HTTP error code, with *message* as an optional, short, human
readable description of the error. The *explain* argument can be used to
provide more detailed information about the error; it will be formatted
- using the :attr:`error_message_format` class variable and emitted, after
+ using the :attr:`error_message_format` attribute and emitted, after
a complete set of headers, as the response body. The :attr:`responses`
- class variable holds the default values for *message* and *explain* that
+ attribute holds the default values for *message* and *explain* that
will be used if no value is provided; for unknown codes the default value
- for both is the string ``???``.
+ for both is the string ``???``. The body will be empty if the method is
+ HEAD or the response code is one of the following: ``1xx``,
+ ``204 No Content``, ``205 Reset Content``, ``304 Not Modified``.
.. versionchanged:: 3.4
The error response includes a Content-Length header.
Added the *explain* argument.
-
.. method:: send_response(code, message=None)
Adds a response header to the headers buffer and logs the accepted
Headers are stored to an internal buffer and :meth:`end_headers`
needs to be called explicitly.
-
.. method:: send_header(keyword, value)
Adds the HTTP header to an internal buffer which will be written to the
.. versionchanged:: 3.2
Headers are stored in an internal buffer.
-
.. method:: send_response_only(code, message=None)
Sends the response header only, used for the purposes when ``100
.. method:: version_string()
Returns the server software's version string. This is a combination of the
- :attr:`server_version` and :attr:`sys_version` class variables.
+ :attr:`server_version` and :attr:`sys_version` attributes.
.. method:: date_time_string(timestamp=None)
IDLE
====
+.. moduleauthor:: Guido van Rossum <guido@python.org>
+
+**Source code:** :source:`Lib/idlelib/`
+
.. index::
single: IDLE
single: Python Editor
single: Integrated Development Environment
-.. moduleauthor:: Guido van Rossum <guido@python.org>
+--------------
IDLE is Python's Integrated Development and Learning Environment.
Search for the currently selected string, if there is one.
Find in Files...
- Open a file search dialog. Put results in an new output window.
+ Open a file search dialog. Put results in a new output window.
Replace...
Open a search-and-replace dialog.
As much as possible, the result of executing Python code with IDLE is the
same as executing the same code in a console window. However, the different
-interface and operation occasionally affects results.
-
-For instance, IDLE normally executes user code in a separate process from
-the IDLE GUI itself. The IDLE versions of sys.stdin, .stdout, and .stderr in the
-execution process get input from and send output to the GUI process,
-which keeps control of the keyboard and screen. This is normally transparent,
-but code that access these object will see different attribute values.
-Also, functions that directly access the keyboard and screen will not work.
+interface and operation occasionally affects visible results. For instance,
+``sys.modules`` starts with more entries.
+
+IDLE also replaces ``sys.stdin``, ``sys.stdout``, and ``sys.stderr`` with
+objects that get input from and send output to the Shell window.
+When this window has the focus, it controls the keyboard and screen.
+This is normally transparent, but functions that directly access the keyboard
+and screen will not work. If ``sys`` is reset with ``importlib.reload(sys)``,
+IDLE's changes are lost and things li ke ``input``, ``raw_input``, and
+``print`` will not work correctly.
With IDLE's Shell, one enters, edits, and recalls complete statements.
Some consoles only work with a single physical line at a time.
.. module:: imaplib
:synopsis: IMAP4 protocol client (requires sockets).
+
.. moduleauthor:: Piers Lauder <piers@communitysolutions.com.au>
.. sectionauthor:: Piers Lauder <piers@communitysolutions.com.au>
.. revised by ESR, January 2000
.. changes for IMAP4_stream by Piers Lauder <piers@communitysolutions.com.au>,
November 2002
+**Source code:** :source:`Lib/imaplib.py`
.. index::
pair: IMAP4; protocol
pair: IMAP4_SSL; protocol
pair: IMAP4_stream; protocol
-**Source code:** :source:`Lib/imaplib.py`
-
--------------
This module defines three classes, :class:`IMAP4`, :class:`IMAP4_SSL` and
Documents describing the protocol, and sources and binaries for servers
implementing it, can all be found at the University of Washington's *IMAP
- Information Center* (http://www.washington.edu/imap/).
+ Information Center* (https://www.washington.edu/imap/).
.. _imap4-objects:
:synopsis: Access the implementation of the import statement.
:deprecated:
+**Source code:** :source:`Lib/imp.py`
+
.. deprecated:: 3.4
The :mod:`imp` package is pending deprecation in favor of :mod:`importlib`.
.. index:: statement: import
+--------------
+
This module provides an interface to the mechanisms used to implement the
:keyword:`import` statement. It defines the following constants and functions:
.. versionadded:: 3.1
+**Source code:** :source:`Lib/importlib/__init__.py`
+
+--------------
Introduction
------------
:pep:`366`
Main module explicit relative imports
+ :pep:`420`
+ Implicit namespace packages
+
:pep:`451`
A ModuleSpec Type for the Import System
.. deprecated:: 3.3
Use :class:`MetaPathFinder` or :class:`PathEntryFinder` instead.
- .. method:: find_module(fullname, path=None)
+ .. abstractmethod:: find_module(fullname, path=None)
An abstact method for finding a :term:`loader` for the specified
module. Originally specified in :pep:`302`, this method was meant
:pep:`302` protocol for loading arbitrary resources from the storage
back-end.
- .. method:: get_data(path)
+ .. abstractmethod:: get_data(path)
An abstract method to return the bytes for the data located at *path*.
Loaders that have a file-like storage back-end
.. versionchanged:: 3.4
No longer abstract and a concrete implementation is provided.
- .. method:: get_source(fullname)
+ .. abstractmethod:: get_source(fullname)
An abstract method to return the source of a module. It is returned as
a text string using :term:`universal newlines`, translating all
when implemented, helps a module to be executed as a script. The ABC
represents an optional :pep:`302` protocol.
- .. method:: get_filename(fullname)
+ .. abstractmethod:: get_filename(fullname)
An abstract method that is to return the value of :attr:`__file__` for
the specified module. If no path is available, :exc:`ImportError` is
.. deprecated:: 3.4
Use :meth:`Loader.exec_module` instead.
- .. method:: get_filename(fullname)
+ .. abstractmethod:: get_filename(fullname)
Returns :attr:`path`.
- .. method:: get_data(path)
+ .. abstractmethod:: get_data(path)
Reads *path* as a binary file and returns the bytes from it.
.. versionadded:: 3.4
- .. versionchanged ::3.5
+ .. versionchanged:: 3.5
The *optimization* parameter was added and the *debug_override* parameter
was deprecated.
:meth:`~importlib.abc.Loader.exec_module` as control over what module type
is used for the module is required. For those same reasons, the loader's
:meth:`~importlib.abc.Loader.create_module` method will be ignored (i.e., the
- loader's method should only return ``None``). Finally,
+ loader's method should only return ``None``; this excludes
+ :class:`BuiltinImporter` and :class:`ExtensionFileLoader`). Finally,
modules which substitute the object placed into :attr:`sys.modules` will
not work as there is no way to properly replace the module references
throughout the interpreter safely; :exc:`ValueError` is raised if such a
suffixes = importlib.machinery.SOURCE_SUFFIXES
loader = importlib.machinery.SourceFileLoader
lazy_loader = importlib.util.LazyLoader.factory(loader)
- finder = importlib.machinery.FileFinder(path, [(lazy_loader, suffixes)])
+ finder = importlib.machinery.FileFinder(path, (lazy_loader, suffixes))
.. module:: inspect
:synopsis: Extract information and source code from live objects.
+
.. moduleauthor:: Ka-Ping Yee <ping@lfw.org>
.. sectionauthor:: Ka-Ping Yee <ping@lfw.org>
.. function:: cleandoc(doc)
Clean up indentation from docstrings that are indented to line up with blocks
- of code. Any whitespace that can be uniformly removed from the second line
- onwards is removed. Also, all tabs are expanded to spaces.
+ of code.
+
+ All leading whitespace is removed from the first line. Any leading whitespace
+ that can be uniformly removed from the second line onwards is removed. Empty
+ lines at the beginning and end are subsequently removed. Also, all tabs are
+ expanded to spaces.
.. _inspect-signature-object:
functions::
def test(a, *, b):
- ...
+ ...
sig = signature(test)
ba = sig.bind(10, b=20)
.. deprecated:: 3.0
Use :func:`signature` and
:ref:`Signature Object <inspect-signature-object>`, which provide a
- better introspecting API for callables. This function will be removed
- in Python 3.6.
+ better introspecting API for callables.
.. function:: getfullargspec(func)
.. module:: io
:synopsis: Core tools for working with streams.
+
.. moduleauthor:: Guido van Rossum <guido@python.org>
.. moduleauthor:: Mike Verdone <mike.verdone@gmail.com>
.. moduleauthor:: Mark Russell <mark.russell@zen.co.uk>
.. moduleauthor:: Benjamin Peterson <benjamin@python.org>
.. sectionauthor:: Benjamin Peterson <benjamin@python.org>
+**Source code:** :source:`Lib/io.py`
+
+--------------
+
.. _io-overview:
Overview
Binary I/O
^^^^^^^^^^
-Binary I/O (also called *buffered I/O*) expects and produces :class:`bytes`
+Binary I/O (also called *buffered I/O*) expects
+:term:`bytes-like objects <bytes-like object>` and produces :class:`bytes`
objects. No encoding, decoding, or newline translation is performed. This
category of streams can be used for all kinds of non-text data, and also when
manual control over the handling of text data is desired.
In-memory streams
^^^^^^^^^^^^^^^^^
-It is also possible to use a :class:`str` or :class:`bytes`-like object as a
+It is also possible to use a :class:`str` or :term:`bytes-like object` as a
file for both reading and writing. For strings :class:`StringIO` can be used
like a file opened in text mode. :class:`BytesIO` can be used like a file
opened in binary mode. Both provide full read-write capabilities with random
when operations they do not support are called.
The basic type used for binary data read from or written to a file is
- :class:`bytes`. :class:`bytearray`\s are accepted too, and in some cases
- (such as :meth:`readinto`) required. Text I/O classes work with
- :class:`str` data.
+ :class:`bytes`. Other :term:`bytes-like objects <bytes-like object>` are
+ accepted as method arguments too. In some cases, such as
+ :meth:`~RawIOBase.readinto`, a writable object such as :class:`bytearray`
+ is required. Text I/O classes work with :class:`str` data.
Note that calling any method (even inquiries) on a closed stream is
undefined. Implementations may raise :exc:`ValueError` in this case.
.. method:: readinto(b)
- Read up to ``len(b)`` bytes into :class:`bytearray` *b* and return the
+ Read bytes into a pre-allocated, writable
+ :term:`bytes-like object` *b*, and return the
number of bytes read. If the object is in non-blocking mode and no bytes
are available, ``None`` is returned.
.. method:: write(b)
- Write the given :class:`bytes` or :class:`bytearray` object, *b*, to the
- underlying raw stream and return the number of bytes written. This can
- be less than ``len(b)``, depending on specifics of the underlying raw
+ Write the given :term:`bytes-like object`, *b*, to the
+ underlying raw stream, and return the number of
+ bytes written. This can be less than the length of *b* in
+ bytes, depending on specifics of the underlying raw
stream, and especially if it is in non-blocking mode. ``None`` is
returned if the raw stream is set not to block and no single byte could
- be readily written to it.
+ be readily written to it. The caller may release or mutate *b* after
+ this method returns, so the implementation should only access *b*
+ during the method call.
.. class:: BufferedIOBase
.. method:: readinto(b)
- Read up to ``len(b)`` bytes into bytearray *b* and return the number of
- bytes read.
+ Read bytes into a pre-allocated, writable
+ :term:`bytes-like object` *b* and return the number of bytes read.
Like :meth:`read`, multiple reads may be issued to the underlying raw
stream, unless the latter is interactive.
.. method:: readinto1(b)
- Read up to ``len(b)`` bytes into bytearray *b*, using at most one call to
+ Read bytes into a pre-allocated, writable
+ :term:`bytes-like object` *b*, using at most one call to
the underlying raw stream's :meth:`~RawIOBase.read` (or
:meth:`~RawIOBase.readinto`) method. Return the number of bytes read.
.. method:: write(b)
- Write the given :class:`bytes` or :class:`bytearray` object, *b* and
- return the number of bytes written (never less than ``len(b)``, since if
+ Write the given :term:`bytes-like object`, *b*, and return the number
+ of bytes written (always equal to the length of *b* in bytes, since if
the write fails an :exc:`OSError` will be raised). Depending on the
actual implementation, these bytes may be readily written to the
underlying stream, or held in a buffer for performance and latency
data needed to be written to the raw stream but it couldn't accept
all the data without blocking.
+ The caller may release or mutate *b* after this method returns,
+ so the implementation should only access *b* during the method call.
+
Raw File I/O
^^^^^^^^^^^^
:class:`BufferedIOBase`. The buffer is discarded when the
:meth:`~IOBase.close` method is called.
- The argument *initial_bytes* contains optional initial :class:`bytes` data.
+ The optional argument *initial_bytes* is a :term:`bytes-like object` that
+ contains initial data.
:class:`BytesIO` provides or overrides these methods in addition to those
from :class:`BufferedIOBase` and :class:`IOBase`:
.. method:: write(b)
- Write the :class:`bytes` or :class:`bytearray` object, *b* and return the
+ Write the :term:`bytes-like object`, *b*, and return the
number of bytes written. When in non-blocking mode, a
:exc:`BlockingIOError` is raised if the buffer needs to be written out but
the raw stream blocks.
.. module:: ipaddress
:synopsis: IPv4/IPv6 manipulation library.
+
.. moduleauthor:: Peter Moody
**Source code:** :source:`Lib/ipaddress.py`
``True`` if the address is reserved for link-local usage. See
:RFC:`3927`.
-.. _iana-ipv4-special-registry: http://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
-.. _iana-ipv6-special-registry: http://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml
+.. _iana-ipv4-special-registry: https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
+.. _iana-ipv6-special-registry: https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml
.. class:: IPv6Address(address)
4. A two-tuple of an address description and a netmask, where the address
description is either a string, a 128-bits integer, a 16-bytes packed
- integer, or an existing IPv4Address object; and the netmask is an
+ integer, or an existing IPv6Address object; and the netmask is an
integer representing the prefix length.
An :exc:`AddressValueError` is raised if *address* is not a valid IPv6
example::
>>> for addr in IPv4Network('192.0.2.0/28'):
- ... addr
+ ... addr
...
IPv4Address('192.0.2.0')
IPv4Address('192.0.2.1')
.. module:: itertools
:synopsis: Functions creating iterators for efficient looping.
+
.. moduleauthor:: Raymond Hettinger <python@rcn.com>
.. sectionauthor:: Raymond Hettinger <python@rcn.com>
-
.. testsetup::
from itertools import *
+--------------
This module implements a number of :term:`iterator` building blocks inspired
by constructs from APL, Haskell, and SML. Each has been recast in a form
:class:`~fractions.Fraction`.) If the input iterable is empty, the
output iterable will also be empty.
- Equivalent to::
+ Roughly equivalent to::
def accumulate(iterable, func=operator.add):
'Return running totals'
:func:`min` for a running minimum, :func:`max` for a running maximum, or
:func:`operator.mul` for a running product. Amortization tables can be
built by accumulating interest and applying payments. First-order
- `recurrence relations <http://en.wikipedia.org/wiki/Recurrence_relation>`_
+ `recurrence relations <https://en.wikipedia.org/wiki/Recurrence_relation>`_
can be modeled by supplying the initial value in the iterable and using only
the accumulated total in *func* argument::
>>> list(accumulate(cashflows, lambda bal, pmt: bal*1.05 + pmt))
[1000, 960.0, 918.0, 873.9000000000001, 827.5950000000001]
- # Chaotic recurrence relation http://en.wikipedia.org/wiki/Logistic_map
+ # Chaotic recurrence relation https://en.wikipedia.org/wiki/Logistic_map
>>> logistic_map = lambda x, _: r * x * (1 - x)
>>> r = 3.8
>>> x0 = 0.4
Make an iterator that returns elements from the first iterable until it is
exhausted, then proceeds to the next iterable, until all of the iterables are
exhausted. Used for treating consecutive sequences as a single sequence.
- Equivalent to::
+ Roughly equivalent to::
def chain(*iterables):
# chain('ABC', 'DEF') --> A B C D E F
value. So if the input elements are unique, there will be no repeat
values in each combination.
- Equivalent to::
+ Roughly equivalent to::
def combinations(iterable, r):
# combinations('ABCD', 2) --> AB AC AD BC BD CD
value. So if the input elements are unique, the generated combinations
will also be unique.
- Equivalent to::
+ Roughly equivalent to::
def combinations_with_replacement(iterable, r):
# combinations_with_replacement('ABC', 2) --> AA AB AC BB BC CC
Make an iterator that filters elements from *data* returning only those that
have a corresponding element in *selectors* that evaluates to ``True``.
Stops when either the *data* or *selectors* iterables has been exhausted.
- Equivalent to::
+ Roughly equivalent to::
def compress(data, selectors):
# compress('ABCDEF', [1,0,1,0,1,1]) --> A C E F
Make an iterator that returns evenly spaced values starting with number *start*. Often
used as an argument to :func:`map` to generate consecutive data points.
- Also, used with :func:`zip` to add sequence numbers. Equivalent to::
+ Also, used with :func:`zip` to add sequence numbers. Roughly equivalent to::
def count(start=0, step=1):
# count(10) --> 10 11 12 13 14 ...
Make an iterator returning elements from the iterable and saving a copy of each.
When the iterable is exhausted, return elements from the saved copy. Repeats
- indefinitely. Equivalent to::
+ indefinitely. Roughly equivalent to::
def cycle(iterable):
# cycle('ABCD') --> A B C D A B C D A B C D ...
Make an iterator that drops elements from the iterable as long as the predicate
is true; afterwards, returns every element. Note, the iterator does not produce
*any* output until the predicate first becomes false, so it may have a lengthy
- start-up time. Equivalent to::
+ start-up time. Roughly equivalent to::
def dropwhile(predicate, iterable):
# dropwhile(lambda x: x<5, [1,4,6,4,1]) --> 6 4 1
Make an iterator that filters elements from iterable returning only those for
which the predicate is ``False``. If *predicate* is ``None``, return the items
- that are false. Equivalent to::
+ that are false. Roughly equivalent to::
def filterfalse(predicate, iterable):
# filterfalse(lambda x: x%2, range(10)) --> 0 2 4 6 8
groups.append(list(g)) # Store group iterator as a list
uniquekeys.append(k)
- :func:`groupby` is equivalent to::
+ :func:`groupby` is roughly equivalent to::
class groupby:
# [k for k, g in groupby('AAAABBBCCDAABBB')] --> A B C D A B
specified position. Unlike regular slicing, :func:`islice` does not support
negative values for *start*, *stop*, or *step*. Can be used to extract related
fields from data where the internal structure has been flattened (for example, a
- multi-line report may list a name field on every third line). Equivalent to::
+ multi-line report may list a name field on every third line). Roughly equivalent to::
def islice(iterable, *args):
# islice('ABCDEFG', 2) --> A B
value. So if the input elements are unique, there will be no repeat
values in each permutation.
- Equivalent to::
+ Roughly equivalent to::
def permutations(iterable, r=None):
# permutations('ABCD', 2) --> AB AC AD BA BC BD CA CB CD DA DB DC
Cartesian product of input iterables.
- Equivalent to nested for-loops in a generator expression. For example,
+ Roughly equivalent to nested for-loops in a generator expression. For example,
``product(A, B)`` returns the same as ``((x,y) for x in A for y in B)``.
The nested loops cycle like an odometer with the rightmost element advancing
repetitions with the optional *repeat* keyword argument. For example,
``product(A, repeat=4)`` means the same as ``product(A, A, A, A)``.
- This function is equivalent to the following code, except that the
+ This function is roughly equivalent to the following code, except that the
actual implementation does not build up intermediate results in memory::
def product(*args, repeat=1):
Make an iterator that returns *object* over and over again. Runs indefinitely
unless the *times* argument is specified. Used as argument to :func:`map` for
invariant parameters to the called function. Also used with :func:`zip` to
- create an invariant part of a tuple record. Equivalent to::
+ create an invariant part of a tuple record.
+
+ Roughly equivalent to::
def repeat(object, times=None):
# repeat(10, 3) --> 10 10 10
the iterable. Used instead of :func:`map` when argument parameters are already
grouped in tuples from a single iterable (the data has been "pre-zipped"). The
difference between :func:`map` and :func:`starmap` parallels the distinction
- between ``function(a,b)`` and ``function(*c)``. Equivalent to::
+ between ``function(a,b)`` and ``function(*c)``. Roughly equivalent to::
def starmap(function, iterable):
# starmap(pow, [(2,5), (3,2), (10,3)]) --> 32 9 1000
.. function:: takewhile(predicate, iterable)
Make an iterator that returns elements from the iterable as long as the
- predicate is true. Equivalent to::
+ predicate is true. Roughly equivalent to::
def takewhile(predicate, iterable):
# takewhile(lambda x: x<5, [1,4,6,4,1]) --> 1 4
.. function:: tee(iterable, n=2)
- Return *n* independent iterators from a single iterable. Equivalent to::
+ Return *n* independent iterators from a single iterable. Roughly equivalent to::
def tee(iterable, n=2):
it = iter(iterable)
Make an iterator that aggregates elements from each of the iterables. If the
iterables are of uneven length, missing values are filled-in with *fillvalue*.
- Iteration continues until the longest iterable is exhausted. Equivalent to::
+ Iteration continues until the longest iterable is exhausted. Roughly equivalent to::
class ZipExhausted(Exception):
pass
"Returns the nth item or a default value"
return next(islice(iterable, n, None), default)
+ def all_equal(iterable):
+ "Returns True if all the elements are equal to each other"
+ g = groupby(iterable)
+ return next(g, True) and not next(g, False)
+
def quantify(iterable, pred=bool):
"Count how many times the predicate is true"
return sum(map(pred, iterable))
try:
if first is not None:
yield first() # For database APIs needing an initial cast to db.first()
- while 1:
+ while True:
yield func()
except exception:
pass
.. module:: json
:synopsis: Encode and decode the JSON format.
+
.. moduleauthor:: Bob Ippolito <bob@redivi.com>
.. sectionauthor:: Bob Ippolito <bob@redivi.com>
+**Source code:** :source:`Lib/json/__init__.py`
+
+--------------
+
`JSON (JavaScript Object Notation) <http://json.org>`_, specified by
:rfc:`7159` (which obsoletes :rfc:`4627`) and by
`ECMA-404 <http://www.ecma-international.org/publications/standards/Ecma-404.htm>`_,
is a lightweight data interchange format inspired by
-`JavaScript <http://en.wikipedia.org/wiki/JavaScript>`_ object literal syntax
+`JavaScript <https://en.wikipedia.org/wiki/JavaScript>`_ object literal syntax
(although it is not a strict subset of JavaScript [#rfc-errata]_ ).
:mod:`json` exposes an API familiar to users of the standard library
.. rubric:: Footnotes
.. [#rfc-errata] As noted in `the errata for RFC 7159
- <http://www.rfc-editor.org/errata_search.php?rfc=7159>`_,
+ <https://www.rfc-editor.org/errata_search.php?rfc=7159>`_,
JSON permits literal U+2028 (LINE SEPARATOR) and
U+2029 (PARAGRAPH SEPARATOR) characters in strings, whereas JavaScript
(as of ECMAScript Edition 5.1) does not.
.. module:: linecache
:synopsis: This module provides random access to individual lines from text files.
+
.. sectionauthor:: Moshe Zadka <moshez@zadka.site.co.il>
**Source code:** :source:`Lib/linecache.py`
.. module:: locale
:synopsis: Internationalization services.
+
.. moduleauthor:: Martin von Löwis <martin@v.loewis.de>
.. sectionauthor:: Martin von Löwis <martin@v.loewis.de>
+**Source code:** :source:`Lib/locale.py`
+
+--------------
The :mod:`locale` module opens access to the POSIX locale database and
functionality. The POSIX locale mechanism allows programmers to deal with
Example::
>>> import locale
- >>> loc = locale.getlocale() # get current locale
+ >>> loc = locale.getlocale() # get current locale
# use German locale; name might vary with platform
>>> locale.setlocale(locale.LC_ALL, 'de_DE')
- >>> locale.strcoll('f\xe4n', 'foo') # compare a string containing an umlaut
- >>> locale.setlocale(locale.LC_ALL, '') # use user's preferred locale
- >>> locale.setlocale(locale.LC_ALL, 'C') # use default (C) locale
- >>> locale.setlocale(locale.LC_ALL, loc) # restore saved locale
+ >>> locale.strcoll('f\xe4n', 'foo') # compare a string containing an umlaut
+ >>> locale.setlocale(locale.LC_ALL, '') # use user's preferred locale
+ >>> locale.setlocale(locale.LC_ALL, 'C') # use default (C) locale
+ >>> locale.setlocale(locale.LC_ALL, loc) # restore saved locale
Background, details, hints, tips and caveats
.. module:: logging.config
:synopsis: Configuration of the logging module.
-
.. moduleauthor:: Vinay Sajip <vinay_sajip@red-dove.com>
.. sectionauthor:: Vinay Sajip <vinay_sajip@red-dove.com>
+**Source code:** :source:`Lib/logging/config.py`
+
.. sidebar:: Important
This page contains only reference information. For tutorials,
* :ref:`Advanced Tutorial <logging-advanced-tutorial>`
* :ref:`Logging Cookbook <logging-cookbook>`
-**Source code:** :source:`Lib/logging/config.py`
-
--------------
This section describes the API for configuring the logging module.
.. module:: logging.handlers
:synopsis: Handlers for the logging module.
-
.. moduleauthor:: Vinay Sajip <vinay_sajip@red-dove.com>
.. sectionauthor:: Vinay Sajip <vinay_sajip@red-dove.com>
+**Source code:** :source:`Lib/logging/handlers.py`
+
.. sidebar:: Important
This page contains only reference information. For tutorials,
* :ref:`Advanced Tutorial <logging-advanced-tutorial>`
* :ref:`Logging Cookbook <logging-cookbook>`
-**Source code:** :source:`Lib/logging/handlers.py`
-
--------------
.. currentmodule:: logging
(See: :issue:`12168`.) In earlier versions, the message sent to the
syslog daemons was always terminated with a NUL byte, because early
versions of these daemons expected a NUL terminated message - even
- though it's not in the relevant specification (RF 5424). More recent
+ though it's not in the relevant specification (RFC 5424). More recent
versions of these daemons don't expect the NUL byte but strip it off
if it's there, and even more recent daemons (which adhere more closely
to RFC 5424) pass the NUL byte on as part of the message.
.. method:: emit(record)
- Sends the record to the Web server as an URL-encoded dictionary. The
+ Sends the record to the Web server as a URL-encoded dictionary. The
:meth:`mapLogRecord` method is used to convert the record to the
dictionary to be sent.
.. module:: logging
:synopsis: Flexible event logging system for applications.
-
.. moduleauthor:: Vinay Sajip <vinay_sajip@red-dove.com>
.. sectionauthor:: Vinay Sajip <vinay_sajip@red-dove.com>
+**Source code:** :source:`Lib/logging/__init__.py`
.. index:: pair: Errors; logging
* :ref:`Advanced Tutorial <logging-advanced-tutorial>`
* :ref:`Logging Cookbook <logging-cookbook>`
-
-**Source code:** :source:`Lib/logging/__init__.py`
-
--------------
This module defines functions and classes which implement a flexible event
| Attribute name | Format | Description |
+================+=========================+===============================================+
| args | You shouldn't need to | The tuple of arguments merged into ``msg`` to |
-| | format this yourself. | produce ``message``. |
+| | format this yourself. | produce ``message``, or a dict whose values |
+| | | are used for the merge (when there is only one|
+| | | argument, and it is a dictionary). |
+----------------+-------------------------+-----------------------------------------------+
| asctime | ``%(asctime)s`` | Human-readable time when the |
| | | :class:`LogRecord` was created. By default |
The proposal which described this feature for inclusion in the Python standard
library.
- `Original Python logging package <http://www.red-dove.com/python_logging.html>`_
+ `Original Python logging package <https://www.red-dove.com/python_logging.html>`_
This is the original source for the :mod:`logging` package. The version of the
package available from this site is suitable for use with Python 1.5.2, 2.1.x
and 2.2.x, which do not include the :mod:`logging` package in the standard
.. module:: lzma
:synopsis: A Python wrapper for the liblzma compression library.
+
.. moduleauthor:: Nadeem Vawda <nadeem.vawda@gmail.com>
.. sectionauthor:: Nadeem Vawda <nadeem.vawda@gmail.com>
.. versionadded:: 3.3
+**Source code:** :source:`Lib/lzma.py`
+
+--------------
This module provides classes and convenience functions for compressing and
decompressing data using the LZMA compression algorithm. Also included is a file
.. module:: macpath
:synopsis: Mac OS 9 path manipulation functions.
+**Source code:** :source:`Lib/macpath.py`
+
+--------------
This module is the Mac OS 9 (and earlier) implementation of the :mod:`os.path`
module. It can be used to manipulate old-style Macintosh pathnames on Mac OS X
.. module:: mailbox
:synopsis: Manipulate mailboxes in various formats
+
.. moduleauthor:: Gregory K. Johnson <gkj@gregorykjohnson.com>
.. sectionauthor:: Gregory K. Johnson <gkj@gregorykjohnson.com>
+**Source code:** :source:`Lib/mailbox.py`
+
+--------------
This module defines two classes, :class:`Mailbox` and :class:`Message`, for
accessing and manipulating on-disk mailboxes and the messages they contain.
`maildir man page from qmail <http://www.qmail.org/man/man5/maildir.html>`_
The original specification of the format.
- `Using maildir format <http://cr.yp.to/proto/maildir.html>`_
+ `Using maildir format <https://cr.yp.to/proto/maildir.html>`_
Notes on Maildir by its inventor. Includes an updated name-creation scheme and
details on "info" semantics.
`mbox man page from tin <http://www.tin.org/bin/man.cgi?section=5&topic=mbox>`_
Another specification of the format, with details on locking.
- `Configuring Netscape Mail on Unix: Why The Content-Length Format is Bad <http://www.jwz.org/doc/content-length.html>`_
+ `Configuring Netscape Mail on Unix: Why The Content-Length Format is Bad <https://www.jwz.org/doc/content-length.html>`_
An argument for using the original mbox format rather than a variation.
`"mbox" is a family of several mutually incompatible mailbox formats <http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/mail-mbox-formats.html>`_
.. seealso::
- `Format of Version 5 Babyl Files <http://quimby.gnus.org/notes/BABYL>`_
+ `Format of Version 5 Babyl Files <https://quimby.gnus.org/notes/BABYL>`_
A specification of the Babyl format.
- `Reading Mail with Rmail <http://www.gnu.org/software/emacs/manual/html_node/emacs/Rmail.html>`_
+ `Reading Mail with Rmail <https://www.gnu.org/software/emacs/manual/html_node/emacs/Rmail.html>`_
The Rmail manual, with some information on Babyl semantics.
`mmdf man page from tin <http://www.tin.org/bin/man.cgi?section=5&topic=mmdf>`_
A specification of MMDF format from the documentation of tin, a newsreader.
- `MMDF <http://en.wikipedia.org/wiki/MMDF>`_
+ `MMDF <https://en.wikipedia.org/wiki/MMDF>`_
A Wikipedia article describing the Multichannel Memorandum Distribution
Facility.
An example usage::
>>> import mailcap
- >>> d=mailcap.getcaps()
+ >>> d = mailcap.getcaps()
>>> mailcap.findmatch(d, 'video/mpeg', filename='tmp1223')
('xmpeg tmp1223', {'view': 'xmpeg %s'})
:synopsis: Convert Python objects to streams of bytes and back (with different
constraints).
+--------------
This module contains functions that can read and write Python values in a binary
format. The format is specific to Python, but independent of machine
.. index::
module: pickle
module: shelve
- object: code
This is not a general "persistence" module. For general persistence and
transfer of Python objects through RPC calls, see the modules :mod:`pickle` and
maliciously constructed data. Never unmarshal data received from an
untrusted or unauthenticated source.
+.. index:: object; code, code object
+
Not all Python object types are supported; in general, only objects whose value
is independent from a particular invocation of Python can be written and read by
this module. The following types are supported: booleans, integers, floating
point numbers, complex numbers, strings, bytes, bytearrays, tuples, lists, sets,
frozensets, dictionaries, and code objects, where it should be understood that
tuples, lists, sets, frozensets and dictionaries are only supported as long as
-the values contained therein are themselves supported.
+the values contained therein are themselves supported. The
singletons :const:`None`, :const:`Ellipsis` and :exc:`StopIteration` can also be
marshalled and unmarshalled.
For format *version* lower than 3, recursive lists, sets and dictionaries cannot
from math import fsum
+--------------
+
This module is always available. It provides access to the mathematical
functions defined by the C standard.
For further discussion and two alternative approaches, see the `ASPN cookbook
recipes for accurate floating point summation
- <http://code.activestate.com/recipes/393090/>`_\.
+ <https://code.activestate.com/recipes/393090/>`_\.
.. function:: gcd(a, b)
Return ``e**x - 1``. For small floats *x*, the subtraction in ``exp(x) - 1``
can result in a `significant loss of precision
- <http://en.wikipedia.org/wiki/Loss_of_significance>`_\; the :func:`expm1`
+ <https://en.wikipedia.org/wiki/Loss_of_significance>`_\; the :func:`expm1`
function provides a way to compute this quantity to full precision::
>>> from math import exp, expm1
Hyperbolic functions
--------------------
-`Hyperbolic functions <http://en.wikipedia.org/wiki/Hyperbolic_function>`_
+`Hyperbolic functions <https://en.wikipedia.org/wiki/Hyperbolic_function>`_
are analogs of trigonometric functions that are based on hyperbolas
instead of circles.
.. function:: erf(x)
- Return the `error function <http://en.wikipedia.org/wiki/Error_function>`_ at
+ Return the `error function <https://en.wikipedia.org/wiki/Error_function>`_ at
*x*.
The :func:`erf` function can be used to compute traditional statistical
functions such as the `cumulative standard normal distribution
- <http://en.wikipedia.org/wiki/Normal_distribution#Cumulative_distribution_function>`_::
+ <https://en.wikipedia.org/wiki/Normal_distribution#Cumulative_distribution_function>`_::
def phi(x):
'Cumulative distribution function for the standard normal distribution'
.. function:: erfc(x)
Return the complementary error function at *x*. The `complementary error
- function <http://en.wikipedia.org/wiki/Error_function>`_ is defined as
+ function <https://en.wikipedia.org/wiki/Error_function>`_ is defined as
``1.0 - erf(x)``. It is used for large values of *x* where a subtraction
from one would cause a `loss of significance
- <http://en.wikipedia.org/wiki/Loss_of_significance>`_\.
+ <https://en.wikipedia.org/wiki/Loss_of_significance>`_\.
.. versionadded:: 3.2
.. function:: gamma(x)
- Return the `Gamma function <http://en.wikipedia.org/wiki/Gamma_function>`_ at
+ Return the `Gamma function <https://en.wikipedia.org/wiki/Gamma_function>`_ at
*x*.
.. versionadded:: 3.2
.. module:: mimetypes
:synopsis: Mapping of filename extensions to MIME types.
+
.. sectionauthor:: Fred L. Drake, Jr. <fdrake@acm.org>
+**Source code:** :source:`Lib/mimetypes.py`
.. index:: pair: MIME; content type
-**Source code:** :source:`Lib/mimetypes.py`
-
--------------
The :mod:`mimetypes` module converts between a filename or URL and the MIME type
The optional *strict* argument is a flag specifying whether the list of known MIME types
is limited to only the official types `registered with IANA
- <http://www.iana.org/assignments/media-types/media-types.xhtml>`_.
+ <https://www.iana.org/assignments/media-types/media-types.xhtml>`_.
When *strict* is ``True`` (the default), only the IANA types are supported; when
*strict* is ``False``, some additional non-standard but commonly used MIME types
are also recognized.
.. module:: mmap
:synopsis: Interface to memory-mapped files for Unix and Windows.
+--------------
Memory-mapped file objects behave like both :class:`bytearray` and like
:term:`file objects <file object>`. You can use mmap objects in most places
import mmap
with mmap.mmap(-1, 13) as mm:
- mm.write("Hello world!")
+ mm.write(b"Hello world!")
.. versionadded:: 3.2
Context manager support.
pid = os.fork()
- if pid == 0: # In a child process
+ if pid == 0: # In a child process
mm.seek(0)
print(mm.readline())
Optional arguments *start* and *end* are interpreted as in slice notation.
Returns ``-1`` on failure.
- .. versionchanged: 3.5
+ .. versionchanged:: 3.5
Writable :term:`bytes-like object` is now accepted.
Optional arguments *start* and *end* are interpreted as in slice notation.
Returns ``-1`` on failure.
- .. versionchanged: 3.5
+ .. versionchanged:: 3.5
Writable :term:`bytes-like object` is now accepted.
were written. If the mmap was created with :const:`ACCESS_READ`, then
writing to it will raise a :exc:`TypeError` exception.
- .. versionchanged: 3.5
+ .. versionchanged:: 3.5
Writable :term:`bytes-like object` is now accepted.
:mod:`modulefinder` --- Find modules used by a script
=====================================================
-.. sectionauthor:: A.M. Kuchling <amk@amk.ca>
-
-
.. module:: modulefinder
:synopsis: Find modules used by a script.
+.. sectionauthor:: A.M. Kuchling <amk@amk.ca>
+
**Source code:** :source:`Lib/modulefinder.py`
--------------
.. module:: msilib
:platform: Windows
:synopsis: Creation of Microsoft Installer files, and CAB files.
+
.. moduleauthor:: Martin v. Löwis <martin@v.loewis.de>
.. sectionauthor:: Martin v. Löwis <martin@v.loewis.de>
+**Source code:** :source:`Lib/msilib/__init__.py`
.. index:: single: msi
+--------------
+
The :mod:`msilib` supports the creation of Microsoft Installer (``.msi``) files.
Because these files often contain an embedded "cabinet" file (``.cab``), it also
exposes an API to create CAB files. Support for reading ``.cab`` files is
.. seealso::
- `FCICreateFile <http://msdn.microsoft.com/library?url=/library/en-us/devnotes/winprog/fcicreate.asp>`_
- `UuidCreate <http://msdn.microsoft.com/library?url=/library/en-us/rpc/rpc/uuidcreate.asp>`_
- `UuidToString <http://msdn.microsoft.com/library?url=/library/en-us/rpc/rpc/uuidtostring.asp>`_
+ `FCICreateFile <https://msdn.microsoft.com/library?url=/library/en-us/devnotes/winprog/fcicreate.asp>`_
+ `UuidCreate <https://msdn.microsoft.com/library?url=/library/en-us/rpc/rpc/uuidcreate.asp>`_
+ `UuidToString <https://msdn.microsoft.com/library?url=/library/en-us/rpc/rpc/uuidtostring.asp>`_
.. _database-objects:
.. seealso::
- `MSIDatabaseOpenView <http://msdn.microsoft.com/library?url=/library/en-us/msi/setup/msidatabaseopenview.asp>`_
- `MSIDatabaseCommit <http://msdn.microsoft.com/library?url=/library/en-us/msi/setup/msidatabasecommit.asp>`_
- `MSIGetSummaryInformation <http://msdn.microsoft.com/library?url=/library/en-us/msi/setup/msigetsummaryinformation.asp>`_
+ `MSIDatabaseOpenView <https://msdn.microsoft.com/library?url=/library/en-us/msi/setup/msidatabaseopenview.asp>`_
+ `MSIDatabaseCommit <https://msdn.microsoft.com/library?url=/library/en-us/msi/setup/msidatabasecommit.asp>`_
+ `MSIGetSummaryInformation <https://msdn.microsoft.com/library?url=/library/en-us/msi/setup/msigetsummaryinformation.asp>`_
.. _view-objects:
.. seealso::
- `MsiViewExecute <http://msdn.microsoft.com/library?url=/library/en-us/msi/setup/msiviewexecute.asp>`_
- `MSIViewGetColumnInfo <http://msdn.microsoft.com/library?url=/library/en-us/msi/setup/msiviewgetcolumninfo.asp>`_
- `MsiViewFetch <http://msdn.microsoft.com/library?url=/library/en-us/msi/setup/msiviewfetch.asp>`_
- `MsiViewModify <http://msdn.microsoft.com/library?url=/library/en-us/msi/setup/msiviewmodify.asp>`_
- `MsiViewClose <http://msdn.microsoft.com/library?url=/library/en-us/msi/setup/msiviewclose.asp>`_
+ `MsiViewExecute <https://msdn.microsoft.com/library?url=/library/en-us/msi/setup/msiviewexecute.asp>`_
+ `MSIViewGetColumnInfo <https://msdn.microsoft.com/library?url=/library/en-us/msi/setup/msiviewgetcolumninfo.asp>`_
+ `MsiViewFetch <https://msdn.microsoft.com/library?url=/library/en-us/msi/setup/msiviewfetch.asp>`_
+ `MsiViewModify <https://msdn.microsoft.com/library?url=/library/en-us/msi/setup/msiviewmodify.asp>`_
+ `MsiViewClose <https://msdn.microsoft.com/library?url=/library/en-us/msi/setup/msiviewclose.asp>`_
.. _summary-objects:
.. seealso::
- `MsiSummaryInfoGetProperty <http://msdn.microsoft.com/library?url=/library/en-us/msi/setup/msisummaryinfogetproperty.asp>`_
- `MsiSummaryInfoGetPropertyCount <http://msdn.microsoft.com/library?url=/library/en-us/msi/setup/msisummaryinfogetpropertycount.asp>`_
- `MsiSummaryInfoSetProperty <http://msdn.microsoft.com/library?url=/library/en-us/msi/setup/msisummaryinfosetproperty.asp>`_
- `MsiSummaryInfoPersist <http://msdn.microsoft.com/library?url=/library/en-us/msi/setup/msisummaryinfopersist.asp>`_
+ `MsiSummaryInfoGetProperty <https://msdn.microsoft.com/library?url=/library/en-us/msi/setup/msisummaryinfogetproperty.asp>`_
+ `MsiSummaryInfoGetPropertyCount <https://msdn.microsoft.com/library?url=/library/en-us/msi/setup/msisummaryinfogetpropertycount.asp>`_
+ `MsiSummaryInfoSetProperty <https://msdn.microsoft.com/library?url=/library/en-us/msi/setup/msisummaryinfosetproperty.asp>`_
+ `MsiSummaryInfoPersist <https://msdn.microsoft.com/library?url=/library/en-us/msi/setup/msisummaryinfopersist.asp>`_
.. _record-objects:
.. seealso::
- `MsiRecordGetFieldCount <http://msdn.microsoft.com/library?url=/library/en-us/msi/setup/msirecordgetfieldcount.asp>`_
- `MsiRecordSetString <http://msdn.microsoft.com/library?url=/library/en-us/msi/setup/msirecordsetstring.asp>`_
- `MsiRecordSetStream <http://msdn.microsoft.com/library?url=/library/en-us/msi/setup/msirecordsetstream.asp>`_
- `MsiRecordSetInteger <http://msdn.microsoft.com/library?url=/library/en-us/msi/setup/msirecordsetinteger.asp>`_
- `MsiRecordClear <http://msdn.microsoft.com/library?url=/library/en-us/msi/setup/msirecordclear.asp>`_
+ `MsiRecordGetFieldCount <https://msdn.microsoft.com/library?url=/library/en-us/msi/setup/msirecordgetfieldcount.asp>`_
+ `MsiRecordSetString <https://msdn.microsoft.com/library?url=/library/en-us/msi/setup/msirecordsetstring.asp>`_
+ `MsiRecordSetStream <https://msdn.microsoft.com/library?url=/library/en-us/msi/setup/msirecordsetstream.asp>`_
+ `MsiRecordSetInteger <https://msdn.microsoft.com/library?url=/library/en-us/msi/setup/msirecordsetinteger.asp>`_
+ `MsiRecordClear <https://msdn.microsoft.com/library?url=/library/en-us/msi/setup/msirecordclear.asp>`_
.. _msi-errors:
.. seealso::
- `Directory Table <http://msdn.microsoft.com/library?url=/library/en-us/msi/setup/directory_table.asp>`_
- `File Table <http://msdn.microsoft.com/library?url=/library/en-us/msi/setup/file_table.asp>`_
- `Component Table <http://msdn.microsoft.com/library?url=/library/en-us/msi/setup/component_table.asp>`_
- `FeatureComponents Table <http://msdn.microsoft.com/library?url=/library/en-us/msi/setup/featurecomponents_table.asp>`_
+ `Directory Table <https://msdn.microsoft.com/library?url=/library/en-us/msi/setup/directory_table.asp>`_
+ `File Table <https://msdn.microsoft.com/library?url=/library/en-us/msi/setup/file_table.asp>`_
+ `Component Table <https://msdn.microsoft.com/library?url=/library/en-us/msi/setup/component_table.asp>`_
+ `FeatureComponents Table <https://msdn.microsoft.com/library?url=/library/en-us/msi/setup/featurecomponents_table.asp>`_
.. _features:
.. seealso::
- `Feature Table <http://msdn.microsoft.com/library?url=/library/en-us/msi/setup/feature_table.asp>`_
+ `Feature Table <https://msdn.microsoft.com/library?url=/library/en-us/msi/setup/feature_table.asp>`_
.. _msi-gui:
.. seealso::
- `Dialog Table <http://msdn.microsoft.com/library?url=/library/en-us/msi/setup/dialog_table.asp>`_
- `Control Table <http://msdn.microsoft.com/library?url=/library/en-us/msi/setup/control_table.asp>`_
- `Control Types <http://msdn.microsoft.com/library?url=/library/en-us/msi/setup/controls.asp>`_
- `ControlCondition Table <http://msdn.microsoft.com/library?url=/library/en-us/msi/setup/controlcondition_table.asp>`_
- `ControlEvent Table <http://msdn.microsoft.com/library?url=/library/en-us/msi/setup/controlevent_table.asp>`_
- `EventMapping Table <http://msdn.microsoft.com/library?url=/library/en-us/msi/setup/eventmapping_table.asp>`_
- `RadioButton Table <http://msdn.microsoft.com/library?url=/library/en-us/msi/setup/radiobutton_table.asp>`_
+ `Dialog Table <https://msdn.microsoft.com/library?url=/library/en-us/msi/setup/dialog_table.asp>`_
+ `Control Table <https://msdn.microsoft.com/library?url=/library/en-us/msi/setup/control_table.asp>`_
+ `Control Types <https://msdn.microsoft.com/library?url=/library/en-us/msi/setup/controls.asp>`_
+ `ControlCondition Table <https://msdn.microsoft.com/library?url=/library/en-us/msi/setup/controlcondition_table.asp>`_
+ `ControlEvent Table <https://msdn.microsoft.com/library?url=/library/en-us/msi/setup/controlevent_table.asp>`_
+ `EventMapping Table <https://msdn.microsoft.com/library?url=/library/en-us/msi/setup/eventmapping_table.asp>`_
+ `RadioButton Table <https://msdn.microsoft.com/library?url=/library/en-us/msi/setup/radiobutton_table.asp>`_
.. _msi-tables:
.. module:: msvcrt
:platform: Windows
:synopsis: Miscellaneous useful routines from the MS VC++ runtime.
+
.. sectionauthor:: Fred L. Drake, Jr. <fdrake@acm.org>
+--------------
These functions provide access to some useful capabilities on Windows platforms.
Some higher-level modules use these functions to build the Windows
.. module:: multiprocessing
:synopsis: Process-based parallelism.
+**Source code:** :source:`Lib/multiprocessing/`
+
+--------------
Introduction
------------
proxies.
A manager returned by :func:`Manager` will support types
- :class:`list`, :class:`dict`, :class:`Namespace`, :class:`Lock`,
+ :class:`list`, :class:`dict`, :class:`~managers.Namespace`, :class:`Lock`,
:class:`RLock`, :class:`Semaphore`, :class:`BoundedSemaphore`,
:class:`Condition`, :class:`Event`, :class:`Barrier`,
:class:`Queue`, :class:`Value` and :class:`Array`. For example, ::
For example::
- from multiprocessing import Pool
- from time import sleep
+ from multiprocessing import Pool, TimeoutError
+ import time
+ import os
def f(x):
return x*x
for i in pool.imap_unordered(f, range(10)):
print(i)
- # evaluate "f(10)" asynchronously
- res = pool.apply_async(f, [10])
- print(res.get(timeout=1)) # prints "100"
+ # evaluate "f(20)" asynchronously
+ res = pool.apply_async(f, (20,)) # runs in *only* one process
+ print(res.get(timeout=1)) # prints "400"
+
+ # evaluate "os.getpid()" asynchronously
+ res = pool.apply_async(os.getpid, ()) # runs in *only* one process
+ print(res.get(timeout=1)) # prints the PID of that process
+
+ # launching multiple evaluations asynchronously *may* use more processes
+ multiple_results = [pool.apply_async(os.getpid, ()) for i in range(4)]
+ print([res.get(timeout=1) for res in multiple_results])
- # make worker sleep for 10 secs
- res = pool.apply_async(sleep, [10])
- print(res.get(timeout=1)) # raises multiprocessing.TimeoutError
+ # make a single worker sleep for 10 secs
+ res = pool.apply_async(time.sleep, (10,))
+ try:
+ print(res.get(timeout=1))
+ except TimeoutError:
+ print("We lacked patience and got a multiprocessing.TimeoutError")
+
+ print("For the moment, the pool remains available for more work")
# exiting the 'with'-block has stopped the pool
+ print("Now the pool is closed and no longer available")
Note that the methods of a pool should only ever be used by the
process which created it.
If the ``freeze_support()`` line is omitted then trying to run the frozen
executable will raise :exc:`RuntimeError`.
- If the module is being run normally by the Python interpreter then
- :func:`freeze_support` has no effect.
+ Calling ``freeze_support()`` has no effect when invoked on any operating
+ system other than Windows. In addition, if the module is being run
+ normally by the Python interpreter on Windows (the program has not been
+ frozen), then ``freeze_support()`` has no effect.
.. function:: get_all_start_methods()
lproxy[0] = d
-Namespace objects
->>>>>>>>>>>>>>>>>
+.. class:: Namespace
-A namespace object has no public methods, but does have writable attributes.
-Its representation shows the values of its attributes.
+ A type that can register with :class:`SyncManager`.
-However, when using a proxy for a namespace object, an attribute beginning with
-``'_'`` will be an attribute of the proxy and not an attribute of the referent:
+ A namespace object has no public methods, but does have writable attributes.
+ Its representation shows the values of its attributes.
-.. doctest::
+ However, when using a proxy for a namespace object, an attribute beginning
+ with ``'_'`` will be an attribute of the proxy and not an attribute of the
+ referent:
+
+ .. doctest::
- >>> manager = multiprocessing.Manager()
- >>> Global = manager.Namespace()
- >>> Global.x = 10
- >>> Global.y = 'hello'
- >>> Global._z = 12.3 # this is an attribute of the proxy
- >>> print(Global)
- Namespace(x=10, y='hello')
+ >>> manager = multiprocessing.Manager()
+ >>> Global = manager.Namespace()
+ >>> Global.x = 10
+ >>> Global.y = 'hello'
+ >>> Global._z = 12.3 # this is an attribute of the proxy
+ >>> print(Global)
+ Namespace(x=10, y='hello')
Customized managers
The following example demonstrates the use of a pool::
from multiprocessing import Pool
+ import time
def f(x):
return x*x
if __name__ == '__main__':
with Pool(processes=4) as pool: # start 4 worker processes
- result = pool.apply_async(f, (10,)) # evaluate "f(10)" asynchronously
+ result = pool.apply_async(f, (10,)) # evaluate "f(10)" asynchronously in a single process
print(result.get(timeout=1)) # prints "100" unless your computer is *very* slow
print(pool.map(f, range(10))) # prints "[0, 1, 4,..., 81]"
print(next(it)) # prints "1"
print(it.next(timeout=1)) # prints "4" unless your computer is *very* slow
- import time
result = pool.apply_async(time.sleep, (10,))
- print(result.get(timeout=1)) # raises TimeoutError
+ print(result.get(timeout=1)) # raises multiprocessing.TimeoutError
.. _multiprocessing-listeners-clients:
If authentication is requested but no authentication key is specified then the
return value of ``current_process().authkey`` is used (see
-:class:`~multiprocessing.Process`). This value will automatically inherited by
+:class:`~multiprocessing.Process`). This value will be automatically inherited by
any :class:`~multiprocessing.Process` object that the current process creates.
This means that (by default) all processes of a multi-process program will share
a single authentication key which can be used when setting up connections
... do something using "lock" ...
if __name__ == '__main__':
- lock = Lock()
- for i in range(10):
+ lock = Lock()
+ for i in range(10):
Process(target=f).start()
should be rewritten as ::
... do something using "l" ...
if __name__ == '__main__':
- lock = Lock()
- for i in range(10):
+ lock = Lock()
+ for i in range(10):
Process(target=f, args=(lock,)).start()
Beware of replacing :data:`sys.stdin` with a "file like object"
in issues with processes-in-processes. This has been changed to::
sys.stdin.close()
- sys.stdin = open(os.devnull)
+ sys.stdin = open(os.open(os.devnull, os.O_RDONLY), closefd=False)
Which solves the fundamental issue of processes colliding with each other
resulting in a bad file descriptor error, but introduces a potential danger
.. module:: netrc
:synopsis: Loading of .netrc files.
+
.. moduleauthor:: Eric S. Raymond <esr@snark.thyrsus.com>
.. sectionauthor:: Eric S. Raymond <esr@snark.thyrsus.com>
.. module:: nis
:platform: Unix
:synopsis: Interface to Sun's NIS (Yellow Pages) library.
+
.. moduleauthor:: Fred Gansevles <Fred.Gansevles@cs.utwente.nl>
.. sectionauthor:: Moshe Zadka <moshez@zadka.site.co.il>
+--------------
The :mod:`nis` module gives a thin wrapper around the NIS library, useful for
central administration of several hosts.
Note that *mapname* is first checked if it is an alias to another name.
- The *domain* argument allows to override the NIS domain used for the lookup. If
+ The *domain* argument allows overriding the NIS domain used for the lookup. If
unspecified, lookup is in the default NIS domain.
Note that *mapname* is first checked if it is an alias to another name.
- The *domain* argument allows to override the NIS domain used for the lookup. If
+ The *domain* argument allows overriding the NIS domain used for the lookup. If
unspecified, lookup is in the default NIS domain.
Return a list of all valid maps.
- The *domain* argument allows to override the NIS domain used for the lookup. If
+ The *domain* argument allows overriding the NIS domain used for the lookup. If
unspecified, lookup is in the default NIS domain.
.. module:: nntplib
:synopsis: NNTP protocol client (requires sockets).
+**Source code:** :source:`Lib/nntplib.py`
.. index::
pair: NNTP; protocol
single: Network News Transfer Protocol
-**Source code:** :source:`Lib/nntplib.py`
-
--------------
This module defines the class :class:`NNTP` which implements the client side of
.. module:: numbers
:synopsis: Numeric abstract base classes (Complex, Real, Integral, etc.).
+**Source code:** :source:`Lib/numbers.py`
+
+--------------
The :mod:`numbers` module (:pep:`3141`) defines a hierarchy of numeric
:term:`abstract base classes <abstract base class>` which progressively define
Abstract. Retrieves the imaginary component of this number.
- .. method:: conjugate()
+ .. abstractmethod:: conjugate()
Abstract. Returns the complex conjugate. For example, ``(1+3j).conjugate()
== (1-3j)``.
.. module:: operator
:synopsis: Functions corresponding to the standard operators.
+
.. sectionauthor:: Skip Montanaro <skip@automatrix.com>
+**Source code:** :source:`Lib/operator.py`
.. testsetup::
import operator
from operator import itemgetter, iadd
-**Source code:** :source:`Lib/operator.py`
-
--------------
The :mod:`operator` module exports a set of efficient functions corresponding to
.. module:: optparse
:synopsis: Command-line option parsing library.
:deprecated:
+
.. moduleauthor:: Greg Ward <gward@python.net>
.. sectionauthor:: Greg Ward <gward@python.net>
+**Source code:** :source:`Lib/optparse.py`
+
.. deprecated:: 3.2
The :mod:`optparse` module is deprecated and will not be developed further;
development will continue with the :mod:`argparse` module.
-**Source code:** :source:`Lib/optparse.py`
-
--------------
:mod:`optparse` is a more convenient, flexible, and powerful library for parsing
Here's an example of using :mod:`optparse` in a simple script::
from optparse import OptionParser
- [...]
+ ...
parser = OptionParser()
parser.add_option("-f", "--file", dest="filename",
help="write report to FILE", metavar="FILE")
program, create an OptionParser instance::
from optparse import OptionParser
- [...]
+ ...
parser = OptionParser()
Then you can start defining options. The basic syntax is::
condition::
(options, args) = parser.parse_args()
- [...]
+ ...
if options.a and options.b:
parser.error("options -a and -b are mutually exclusive")
Here's what :mod:`optparse`\ -based scripts usually look like::
from optparse import OptionParser
- [...]
+ ...
def main():
usage = "usage: %prog [options] arg"
parser = OptionParser(usage)
action="store_true", dest="verbose")
parser.add_option("-q", "--quiet",
action="store_false", dest="verbose")
- [...]
+ ...
(options, args) = parser.parse_args()
if len(args) != 1:
parser.error("incorrect number of arguments")
if options.verbose:
print("reading %s..." % options.filename)
- [...]
+ ...
if __name__ == "__main__":
main()
strings::
parser.add_option("-n", "--dry-run", ...)
- [...]
+ ...
parser.add_option("-n", "--noisy", ...)
(This is particularly true if you've defined your own OptionParser subclass with
Options:
--dry-run do no harm
- [...]
+ ...
-n, --noisy be noisy
It's possible to whittle away the option strings for a previously-added option
accessible, so :mod:`optparse` removes it, leaving this help text::
Options:
- [...]
+ ...
-n, --noisy be noisy
--dry-run new dry-run option
if parser.values.b:
raise OptionValueError("can't use -a after -b")
parser.values.a = 1
- [...]
+ ...
parser.add_option("-a", action="callback", callback=check_order)
parser.add_option("-b", action="store_true", dest="b")
if parser.values.b:
raise OptionValueError("can't use %s after -b" % opt_str)
setattr(parser.values, option.dest, 1)
- [...]
+ ...
parser.add_option("-a", action="callback", callback=check_order, dest='a')
parser.add_option("-b", action="store_true", dest="b")
parser.add_option("-c", action="callback", callback=check_order, dest='c')
raise OptionValueError("%s option invalid when moon is full"
% opt_str)
setattr(parser.values, option.dest, 1)
- [...]
+ ...
parser.add_option("--foo",
action="callback", callback=check_moon, dest="foo")
def store_value(option, opt_str, value, parser):
setattr(parser.values, option.dest, value)
- [...]
+ ...
parser.add_option("--foo",
action="callback", callback=store_value,
type="int", nargs=3, dest="foo")
del parser.rargs[:len(value)]
setattr(parser.values, option.dest, value)
- [...]
- parser.add_option("-c", "--callback", dest="vararg_attr",
- action="callback", callback=vararg_callback)
+ ...
+ parser.add_option("-c", "--callback", dest="vararg_attr",
+ action="callback", callback=vararg_callback)
.. _optparse-extending-optparse:
.. module:: os.path
:synopsis: Operations on pathnames.
+**Source code:** :source:`Lib/posixpath.py` (for POSIX),
+:source:`Lib/ntpath.py` (for Windows NT),
+and :source:`Lib/macpath.py` (for Macintosh)
+
.. index:: single: path; operations
+--------------
+
This module implements some useful functions on pathnames. To read or
write files see :func:`open`, and for accessing the filesystem see the
:mod:`os` module. The path parameters can be passed as either strings,
.. function:: islink(path)
Return ``True`` if *path* refers to a directory entry that is a symbolic link.
- Always ``False`` if symbolic links are not supported by the python runtime.
+ Always ``False`` if symbolic links are not supported by the Python runtime.
.. function:: ismount(path)
.. module:: os
:synopsis: Miscellaneous operating system interfaces.
+**Source code:** :source:`Lib/os.py`
+
+--------------
This module provides a portable way of using operating system dependent
functionality. If you just want to read or write a file see :func:`open`, if
:func:`~os.open` function. They can be combined using the bitwise OR operator
``|``. Some of them are not available on all platforms. For descriptions of
their availability and use, consult the :manpage:`open(2)` manual page on Unix
-or `the MSDN <http://msdn.microsoft.com/en-us/library/z0kc8e3z.aspx>`_ on Windows.
+or `the MSDN <https://msdn.microsoft.com/en-us/library/z0kc8e3z.aspx>`_ on Windows.
.. data:: O_RDONLY
Create a directory named *path* with numeric mode *mode*.
+ If the directory already exists, :exc:`FileExistsError` is raised.
+
+ .. _mkdir_modebits:
+
On some systems, *mode* is ignored. Where it is used, the current umask
- value is first masked out. If the directory already exists, :exc:`OSError`
- is raised.
+ value is first masked out. If bits other than the last 9 (i.e. the last 3
+ digits of the octal representation of the *mode*) are set, their meaning is
+ platform-dependent. On some platforms, they are ignored and you should call
+ :func:`chmod` explicitly to set them.
This function can also support :ref:`paths relative to directory descriptors
<dir_fd>`.
Recursive directory creation function. Like :func:`mkdir`, but makes all
intermediate-level directories needed to contain the leaf directory.
- The default *mode* is ``0o777`` (octal). On some systems, *mode* is
- ignored. Where it is used, the current umask value is first masked out.
+ The *mode* parameter is passed to :func:`mkdir`; see :ref:`the mkdir()
+ description <mkdir_modebits>` for how it is interpreted.
If *exist_ok* is ``False`` (the default), an :exc:`OSError` is raised if the
target directory already exists.
``os.path.join(os.path.dirname(path), result)``.
If the *path* is a string object, the result will also be a string object,
- and the call may raise an UnicodeDecodeError. If the *path* is a bytes
+ and the call may raise a UnicodeDecodeError. If the *path* is a bytes
object, the result will be a bytes object.
This function can also support :ref:`paths relative to directory descriptors
be raised; on Unix, the directory entry is removed but the storage allocated
to the file is not made available until the original file is no longer in use.
- This function is identical to :func:`unlink`.
+ This function is semantically identical to :func:`unlink`.
.. versionadded:: 3.3
The *dir_fd* argument.
and
`readdir() <http://pubs.opengroup.org/onlinepubs/009695399/functions/readdir_r.html>`_
functions. On Windows, it uses the Win32
- `FindFirstFileW <http://msdn.microsoft.com/en-us/library/windows/desktop/aa364418(v=vs.85).aspx>`_
+ `FindFirstFileW <https://msdn.microsoft.com/en-us/library/windows/desktop/aa364418(v=vs.85).aspx>`_
and
- `FindNextFileW <http://msdn.microsoft.com/en-us/library/windows/desktop/aa364428(v=vs.85).aspx>`_
+ `FindNextFileW <https://msdn.microsoft.com/en-us/library/windows/desktop/aa364428(v=vs.85).aspx>`_
functions.
.. versionadded:: 3.5
Return the inode number of the entry.
- The result is cached on the ``DirEntry`` object, use ``os.stat(entry.path,
+ The result is cached on the ``DirEntry`` object. Use ``os.stat(entry.path,
follow_symlinks=False).st_ino`` to fetch up-to-date information.
- On Unix, no system call is required.
+ On the first, uncached call, a system call is required on Windows but
+ not on Unix.
.. method:: is_dir(\*, follow_symlinks=True)
- If *follow_symlinks* is ``True`` (the default), return ``True`` if the
- entry is a directory or a symbolic link pointing to a directory;
- return ``False`` if it is or points to any other kind of file, or if it
- doesn't exist anymore.
+ Return ``True`` if this entry is a directory or a symbolic link pointing
+ to a directory; return ``False`` if the entry is or points to any other
+ kind of file, or if it doesn't exist anymore.
If *follow_symlinks* is ``False``, return ``True`` only if this entry
- is a directory; return ``False`` if it is any other kind of file
- or if it doesn't exist anymore.
+ is a directory (without following symlinks); return ``False`` if the
+ entry is any other kind of file or if it doesn't exist anymore.
- The result is cached on the ``DirEntry`` object. Call :func:`os.stat`
- along with :func:`stat.S_ISDIR` to fetch up-to-date information.
+ The result is cached on the ``DirEntry`` object, with a separate cache
+ for *follow_symlinks* ``True`` and ``False``. Call :func:`os.stat` along
+ with :func:`stat.S_ISDIR` to fetch up-to-date information.
+
+ On the first, uncached call, no system call is required in most cases.
+ Specifically, for non-symlinks, neither Windows or Unix require a system
+ call, except on certain Unix file systems, such as network file systems,
+ that return ``dirent.d_type == DT_UNKNOWN``. If the entry is a symlink,
+ a system call will be required to follow the symlink unless
+ *follow_symlinks* is ``False``.
This method can raise :exc:`OSError`, such as :exc:`PermissionError`,
but :exc:`FileNotFoundError` is caught and not raised.
- In most cases, no system call is required.
-
.. method:: is_file(\*, follow_symlinks=True)
- If *follow_symlinks* is ``True`` (the default), return ``True`` if the
- entry is a file or a symbolic link pointing to a file; return ``False``
- if it is or points to a directory or other non-file entry, or if it
- doesn't exist anymore.
+ Return ``True`` if this entry is a file or a symbolic link pointing to a
+ file; return ``False`` if the entry is or points to a directory or other
+ non-file entry, or if it doesn't exist anymore.
If *follow_symlinks* is ``False``, return ``True`` only if this entry
- is a file; return ``False`` if it is a directory or other non-file entry,
- or if it doesn't exist anymore.
-
- The result is cached on the ``DirEntry`` object. Call :func:`os.stat`
- along with :func:`stat.S_ISREG` to fetch up-to-date information.
+ is a file (without following symlinks); return ``False`` if the entry is
+ a directory or other non-file entry, or if it doesn't exist anymore.
- This method can raise :exc:`OSError`, such as :exc:`PermissionError`,
- but :exc:`FileNotFoundError` is caught and not raised.
-
- In most cases, no system call is required.
+ The result is cached on the ``DirEntry`` object. Caching, system calls
+ made, and exceptions raised are as per :func:`~DirEntry.is_dir`.
.. method:: is_symlink()
Return ``True`` if this entry is a symbolic link (even if broken);
- return ``False`` if it points to a directory or any kind of file,
+ return ``False`` if the entry points to a directory or any kind of file,
or if it doesn't exist anymore.
The result is cached on the ``DirEntry`` object. Call
:func:`os.path.islink` to fetch up-to-date information.
- The method can raise :exc:`OSError`, such as :exc:`PermissionError`,
- but :exc:`FileNotFoundError` is caught and not raised.
+ On the first, uncached call, no system call is required in most cases.
+ Specifically, neither Windows or Unix require a system call, except on
+ certain Unix file systems, such as network file systems, that return
+ ``dirent.d_type == DT_UNKNOWN``.
- In most cases, no system call is required.
+ This method can raise :exc:`OSError`, such as :exc:`PermissionError`,
+ but :exc:`FileNotFoundError` is caught and not raised.
.. method:: stat(\*, follow_symlinks=True)
follows symbolic links by default; to stat a symbolic link add the
``follow_symlinks=False`` argument.
- On Unix, this method always requires a system call. On Windows,
- ``DirEntry.stat()`` requires a system call only if the
- entry is a symbolic link, and ``DirEntry.stat(follow_symlinks=False)``
- never requires a system call.
+ On Unix, this method always requires a system call. On Windows, it
+ only requires a system call if *follow_symlinks* is ``True`` and the
+ entry is a symbolic link.
On Windows, the ``st_ino``, ``st_dev`` and ``st_nlink`` attributes of the
:class:`stat_result` are always set to zero. Call :func:`os.stat` to
get these attributes.
- The result is cached on the ``DirEntry`` object. Call :func:`os.stat`
- to fetch up-to-date information.
+ The result is cached on the ``DirEntry`` object, with a separate cache
+ for *follow_symlinks* ``True`` and ``False``. Call :func:`os.stat` to
+ fetch up-to-date information.
+
+ Note that there is a nice correspondence between several attributes
+ and methods of ``DirEntry`` and of :class:`pathlib.Path`. In
+ particular, the ``name`` and ``path`` attributes have the same
+ meaning, as do the ``is_dir()``, ``is_file()``, ``is_symlink()``
+ and ``stat()`` methods.
.. versionadded:: 3.5
.. function:: unlink(path, *, dir_fd=None)
- Remove (delete) the file *path*. This function is identical to
- :func:`remove`; the ``unlink`` name is its traditional Unix
- name. Please see the documentation for :func:`remove` for
- further information.
+ Remove (delete) the file *path*. This function is semantically
+ identical to :func:`remove`; the ``unlink`` name is its
+ traditional Unix name. Please see the documentation for
+ :func:`remove` for further information.
.. versionadded:: 3.3
The *dir_fd* parameter.
.. data:: SCHED_RESET_ON_FORK
- This flag can OR'ed with any other scheduling policy. When a process with
+ This flag can be OR'ed with any other scheduling policy. When a process with
this flag set forks, its child's scheduling policy and priority are reset to
the default.
This function returns random bytes from an OS-specific randomness source. The
returned data should be unpredictable enough for cryptographic applications,
- though its exact quality depends on the OS implementation. On a Unix-like
- system this will query ``/dev/urandom``, and on Windows it will use
- ``CryptGenRandom()``. If a randomness source is not found,
+ though its exact quality depends on the OS implementation.
+
+ On Linux, ``getrandom()`` syscall is used if available and the urandom
+ entropy pool is initialized (``getrandom()`` does not block).
+ On a Unix-like system this will query ``/dev/urandom``. On Windows, it
+ will use ``CryptGenRandom()``. If a randomness source is not found,
:exc:`NotImplementedError` will be raised.
For an easy-to-use interface to the random number generator
provided by your platform, please see :class:`random.SystemRandom`.
+ .. versionchanged:: 3.5.2
+ On Linux, if ``getrandom()`` blocks (the urandom entropy pool is not
+ initialized yet), fall back on reading ``/dev/urandom``.
+
.. versionchanged:: 3.5
On Linux 3.17 and newer, the ``getrandom()`` syscall is now used
when available. On OpenBSD 5.6 and newer, the C ``getentropy()``
:platform: Linux, FreeBSD
:synopsis: Access to OSS-compatible audio devices.
+--------------
This module allows you to access the OSS (Open Sound System) audio interface.
OSS is available for a wide range of open-source and commercial Unices, and is
data may not be written
---see :meth:`writeall`.
- .. versionchanged: 3.5
+ .. versionchanged:: 3.5
Writable :term:`bytes-like object` is now accepted.
no return value, since the amount of data written is always equal to the
amount of data supplied.
- .. versionchanged: 3.5
+ .. versionchanged:: 3.5
Writable :term:`bytes-like object` is now accepted.
.. seealso::
- `PyGObject <https://live.gnome.org/PyGObject>`_
+ `PyGObject <https://wiki.gnome.org/Projects/PyGObject>`_
provides introspection bindings for C libraries using
`GObject <https://developer.gnome.org/gobject/stable/>`_. One of
these libraries is the `GTK+ 3 <http://www.gtk.org/>`_ widget set.
GTK+ comes with many more widgets than Tkinter provides. An online
- `Python GTK+ 3 Tutorial <http://python-gtk-3-tutorial.readthedocs.org/en/latest/>`_
+ `Python GTK+ 3 Tutorial <https://python-gtk-3-tutorial.readthedocs.org/en/latest/>`_
is available.
`PyGTK <http://www.pygtk.org/>`_ provides bindings for an older version
of the library, GTK+ 2. It provides an object oriented interface that
is slightly higher level than the C one. There are also bindings to
- `GNOME <http://www.gnome.org>`_. An online `tutorial
+ `GNOME <https://www.gnome.org/>`_. An online `tutorial
<http://www.pygtk.org/pygtk2tutorial/index.html>`_ is available.
- `PyQt <http://www.riverbankcomputing.co.uk/software/pyqt/intro>`_
+ `PyQt <https://riverbankcomputing.com/software/pyqt/intro>`_
PyQt is a :program:`sip`\ -wrapped binding to the Qt toolkit. Qt is an
extensive C++ GUI application development framework that is
available for Unix, Windows and Mac OS X. :program:`sip` is a tool
for generating bindings for C++ libraries as Python classes, and
is specifically designed for Python. The *PyQt3* bindings have a
book, `GUI Programming with Python: QT Edition
- <http://www.commandprompt.com/community/pyqt/>`_ by Boudewijn
+ <https://www.commandprompt.com/community/pyqt/>`_ by Boudewijn
Rempt. The *PyQt4* bindings also have a book, `Rapid GUI Programming
- with Python and Qt <http://www.qtrac.eu/pyqtbook.html>`_, by Mark
+ with Python and Qt <https://www.qtrac.eu/pyqtbook.html>`_, by Mark
Summerfield.
- `PySide <http://qt-project.org/wiki/PySide>`_
+ `PySide <https://wiki.qt.io/PySide>`_
is a newer binding to the Qt toolkit, provided by Nokia.
Compared to PyQt, its licensing scheme is friendlier to non-open source
applications.
`wxPython <http://www.wxpython.org>`_
wxPython is a cross-platform GUI toolkit for Python that is built around
- the popular `wxWidgets <http://www.wxwidgets.org/>`_ (formerly wxWindows)
+ the popular `wxWidgets <https://www.wxwidgets.org/>`_ (formerly wxWindows)
C++ toolkit. It provides a native look and feel for applications on
Windows, Mac OS X, and Unix systems by using each platform's native
widgets where ever possible, (GTK+ on Unix-like systems). In addition to
low-level device context drawing, drag and drop, system clipboard access,
an XML-based resource format and more, including an ever growing library
of user-contributed modules. wxPython has a book, `wxPython in Action
- <http://www.manning.com/rappin/>`_, by Noel Rappin and
+ <https://www.manning.com/books/wxpython-in-action>`_, by Noel Rappin and
Robin Dunn.
PyGTK, PyQt, and wxPython, all have a modern look and feel and more
.. module:: parser
:synopsis: Access parse trees for Python source code.
+
.. moduleauthor:: Fred L. Drake, Jr. <fdrake@acm.org>
.. sectionauthor:: Fred L. Drake, Jr. <fdrake@acm.org>
-
.. Copyright 1995 Virginia Polytechnic Institute and State University and Fred
L. Drake, Jr. This copyright notice must be distributed on all copies, but
this document otherwise may be distributed as part of the Python
.. index:: single: parsing; Python source code
+--------------
+
The :mod:`parser` module provides an interface to Python's internal parser and
byte-code compiler. The primary purpose for this interface is to allow Python
code to edit the parse tree of a Python expression and create executable code
.. module:: pathlib
:synopsis: Object-oriented filesystem paths
+.. versionadded:: 3.4
+
+**Source code:** :source:`Lib/pathlib.py`
+
.. index:: single: path; operations
-.. versionadded:: 3.4
+--------------
This module offers classes representing filesystem paths with semantics
appropriate for different operating systems. Path classes are divided
**Source code:** :source:`Lib/pdb.py`
---------------
-
.. index:: single: debugging
+--------------
+
The module :mod:`pdb` defines an interactive source code debugger for Python
programs. It supports setting (conditional) breakpoints and single stepping at
the source line level, inspection of stack frames, source code listing, and
:mod:`pickle` --- Python object serialization
=============================================
+.. module:: pickle
+ :synopsis: Convert Python objects to streams of bytes and back.
+
+.. sectionauthor:: Jim Kerr <jbkerr@sr.hp.com>.
+.. sectionauthor:: Barry Warsaw <barry@python.org>
+
+**Source code:** :source:`Lib/pickle.py`
+
.. index::
single: persistence
pair: persistent; objects
pair: flattening; objects
pair: pickling; objects
-.. module:: pickle
- :synopsis: Convert Python objects to streams of bytes and back.
-.. sectionauthor:: Jim Kerr <jbkerr@sr.hp.com>.
-.. sectionauthor:: Barry Warsaw <barry@python.org>
-
+--------------
The :mod:`pickle` module implements binary protocols for serializing and
de-serializing a Python object structure. *"Pickling"* is the process
.. module:: pipes
:platform: Unix
:synopsis: A Python interface to Unix shell pipelines.
+
.. sectionauthor:: Moshe Zadka <moshez@zadka.site.co.il>
**Source code:** :source:`Lib/pipes.py`
.. function:: iter_modules(path=None, prefix='')
Yields ``(module_finder, name, ispkg)`` for all submodules on *path*, or, if
- path is ``None``, all top-level modules on ``sys.path``.
+ *path* is ``None``, all top-level modules on ``sys.path``.
*path* should be either ``None`` or a list of paths to look for modules in.
.. function:: walk_packages(path=None, prefix='', onerror=None)
Yields ``(module_finder, name, ispkg)`` for all modules recursively on
- *path*, or, if path is ``None``, all accessible modules.
+ *path*, or, if *path* is ``None``, all accessible modules.
*path* should be either ``None`` or a list of paths to look for modules in.
.. module:: platform
:synopsis: Retrieves as much platform identifying data as possible.
+
.. moduleauthor:: Marc-André Lemburg <mal@egenix.com>
.. sectionauthor:: Bjorn Pettersen <bpettersen@corp.fairisaac.com>
.. module:: plistlib
:synopsis: Generate and parse Mac OS X plist files.
+
.. moduleauthor:: Jack Jansen
.. sectionauthor:: Georg Brandl <georg@python.org>
.. (harvested from docstrings in the original file)
+**Source code:** :source:`Lib/plistlib.py`
+
.. index::
pair: plist; file
single: property list
-**Source code:** :source:`Lib/plistlib.py`
-
--------------
This module provides an interface for reading and writing the "property list"
.. module:: poplib
:synopsis: POP3 protocol client (requires sockets).
+
.. sectionauthor:: Andrew T. Csillag
.. revised by ESR, January 2000
-.. index:: pair: POP3; protocol
-
**Source code:** :source:`Lib/poplib.py`
+.. index:: pair: POP3; protocol
+
--------------
This module defines a class, :class:`POP3`, which encapsulates a connection to a
:platform: Unix
:synopsis: The most common POSIX system calls (normally used via module os).
+--------------
This module provides access to operating system functionality that is
standardized by the C Standard and the POSIX standard (a thinly disguised Unix
.. module:: pprint
:synopsis: Data pretty printer.
+
.. moduleauthor:: Fred L. Drake, Jr. <fdrake@acm.org>
.. sectionauthor:: Fred L. Drake, Jr. <fdrake@acm.org>
the current presentation context (direct and indirect containers for *object*
that are affecting the presentation) as the keys; if an object needs to be
presented which is already represented in *context*, the third return value
- should be ``True``. Recursive calls to the :meth:`format` method should add
+ should be ``True``. Recursive calls to the :meth:`.format` method should add
additional entries for containers to this dictionary. The third argument,
*maxlevels*, gives the requested limit to recursion; this will be ``0`` if there
is no requested limit. This argument should be passed unmodified to recursive
.. module:: pty
:platform: Linux
:synopsis: Pseudo-Terminal Handling for Linux.
+
.. moduleauthor:: Steen Lumholt
.. sectionauthor:: Moshe Zadka <moshez@zadka.site.co.il>
+**Source code:** :source:`Lib/pty.py`
+
+--------------
The :mod:`pty` module defines operations for handling the pseudo-terminal
concept: starting another process and being able to write to and read from its
:platform: Unix
:synopsis: The password database (getpwnam() and friends).
+--------------
This module provides access to the Unix user account and password database. It
is available on all Unix versions.
.. module:: py_compile
:synopsis: Generate byte-code files from Python source files.
+
.. sectionauthor:: Fred L. Drake, Jr. <fdrake@acm.org>
.. documentation based on module docstrings
-.. index:: pair: file; byte-code
-
**Source code:** :source:`Lib/py_compile.py`
+.. index:: pair: file; byte-code
+
--------------
The :mod:`py_compile` module provides a function to generate a byte-code file
.. module:: pyclbr
:synopsis: Supports information extraction for a Python class browser.
+
.. sectionauthor:: Fred L. Drake, Jr. <fdrake@acm.org>
**Source code:** :source:`Lib/pyclbr.py`
.. module:: pydoc
:synopsis: Documentation generator and online help system.
+
.. moduleauthor:: Ka-Ping Yee <ping@lfw.org>
.. sectionauthor:: Ka-Ping Yee <ping@lfw.org>
+**Source code:** :source:`Lib/pydoc.py`
.. index::
single: documentation; generation
single: documentation; online
single: help; online
-**Source code:** :source:`Lib/pydoc.py`
-
--------------
The :mod:`pydoc` module automatically generates documentation from Python
.. module:: xml.parsers.expat
:synopsis: An interface to the Expat non-validating XML parser.
+
.. moduleauthor:: Paul Prescod <paul@prescod.net>
+--------------
.. Markup notes:
.. sectionauthor:: Fred L. Drake, Jr. <fdrake@acm.org>
-Content modules are described using nested tuples. Each tuple contains four
+Content models are described using nested tuples. Each tuple contains four
values: the type, the quantifier, the name, and a tuple of children. Children
-are simply additional content module descriptions.
+are simply additional content model descriptions.
The values of the first two fields are constants defined in the
:mod:`xml.parsers.expat.model` module. These constants can be collected in two
.. [#] The encoding string included in XML output should conform to the
appropriate standards. For example, "UTF-8" is valid, but "UTF8" is
- not. See http://www.w3.org/TR/2006/REC-xml11-20060816/#NT-EncodingDecl
- and http://www.iana.org/assignments/character-sets/character-sets.xhtml.
+ not. See https://www.w3.org/TR/2006/REC-xml11-20060816/#NT-EncodingDecl
+ and https://www.iana.org/assignments/character-sets/character-sets.xhtml.
.. module:: quopri
:synopsis: Encode and decode files using the MIME quoted-printable encoding.
+**Source code:** :source:`Lib/quopri.py`
.. index::
pair: quoted-printable; encoding
single: MIME; quoted-printable encoding
-**Source code:** :source:`Lib/quopri.py`
-
--------------
This module performs quoted-printable transport encoding and decoding, as
lognormal, negative exponential, gamma, and beta distributions. For generating
distributions of angles, the von Mises distribution is available.
-Almost all module functions depend on the basic function :func:`random`, which
+Almost all module functions depend on the basic function :func:`.random`, which
generates a random float uniformly in the semi-open range [0.0, 1.0). Python
uses the Mersenne Twister as the core generator. It produces 53-bit precision
floats and has a period of 2\*\*19937-1. The underlying implementation in C is
instances of :class:`Random` to get generators that don't share state.
Class :class:`Random` can also be subclassed if you want to use a different
-basic generator of your own devising: in that case, override the :meth:`random`,
-:meth:`seed`, :meth:`getstate`, and :meth:`setstate` methods.
-Optionally, a new generator can supply a :meth:`getrandbits` method --- this
+basic generator of your own devising: in that case, override the :meth:`~Random.random`,
+:meth:`~Random.seed`, :meth:`~Random.getstate`, and :meth:`~Random.setstate` methods.
+Optionally, a new generator can supply a :meth:`~Random.getrandbits` method --- this
allows :meth:`randrange` to produce selections over an arbitrarily large range.
The :mod:`random` module also provides the :class:`SystemRandom` class which
Shuffle the sequence *x* in place. The optional argument *random* is a
0-argument function returning a random float in [0.0, 1.0); by default, this is
- the function :func:`random`.
+ the function :func:`.random`.
Note that for even rather small ``len(x)``, the total number of permutations of
*x* is larger than the period of most random number generators; this implies
`Complementary-Multiply-with-Carry recipe
- <http://code.activestate.com/recipes/576707/>`_ for a compatible alternative
+ <https://code.activestate.com/recipes/576707/>`_ for a compatible alternative
random number generator with a long period and comparatively simple update
operations.
* If a new seeding method is added, then a backward compatible seeder will be
offered.
-* The generator's :meth:`random` method will continue to produce the same
+* The generator's :meth:`~Random.random` method will continue to produce the same
sequence when the compatible seeder is given the same seed.
.. _random-examples:
.. module:: re
:synopsis: Regular expression operations.
+
.. moduleauthor:: Fredrik Lundh <fredrik@pythonware.com>
.. sectionauthor:: Andrew M. Kuchling <amk@amk.ca>
+**Source code:** :source:`Lib/re.py`
+
+--------------
This module provides regular expression matching operations similar to
those found in Perl.
Both patterns and strings to be searched can be Unicode strings as well as
8-bit strings. However, Unicode strings and 8-bit strings cannot be mixed:
-that is, you cannot match an Unicode string with a byte pattern or
+that is, you cannot match a Unicode string with a byte pattern or
vice-versa; similarly, when asking for a substitution, the replacement
string must be of the same type as both the pattern and the search string.
``*?``, ``+?``, ``??``
The ``'*'``, ``'+'``, and ``'?'`` qualifiers are all :dfn:`greedy`; they match
as much text as possible. Sometimes this behaviour isn't desired; if the RE
- ``<.*>`` is matched against ``'<H1>title</H1>'``, it will match the entire
- string, and not just ``'<H1>'``. Adding ``'?'`` after the qualifier makes it
+ ``<.*>`` is matched against ``<a> b <c>``, it will match the entire
+ string, and not just ``<a>``. Adding ``?`` after the qualifier makes it
perform the match in :dfn:`non-greedy` or :dfn:`minimal` fashion; as *few*
- characters as possible will be matched. Using ``.*?`` in the previous
- expression will match only ``'<H1>'``.
+ characters as possible will be matched. Using the RE ``<.*?>`` will match
+ only ``<a>``.
``{m}``
Specifies that exactly *m* copies of the previous RE should be matched; fewer
>>> m.group(0)
'egg'
- .. versionchanged: 3.5
+ .. versionchanged:: 3.5
Added support for group references of fixed length.
``(?<!...)``
.. method:: regex.search(string[, pos[, endpos]])
- Scan through *string* looking for a location where this regular expression
- produces a match, and return a corresponding :ref:`match object
+ Scan through *string* looking for the first location where this regular
+ expression produces a match, and return a corresponding :ref:`match object
<match-objects>`. Return ``None`` if no position in the string matches the
pattern; note that this is different from finding a zero-length match at some
point in the string.
For example::
- >>> re.match("c", "abcdef") # No match
- >>> re.search("c", "abcdef") # Match
+ >>> re.match("c", "abcdef") # No match
+ >>> re.search("c", "abcdef") # Match
<_sre.SRE_Match object; span=(2, 3), match='c'>
Regular expressions beginning with ``'^'`` can be used with :func:`search` to
restrict the match at the beginning of the string::
- >>> re.match("c", "abcdef") # No match
- >>> re.search("^c", "abcdef") # No match
+ >>> re.match("c", "abcdef") # No match
+ >>> re.search("^c", "abcdef") # No match
>>> re.search("^a", "abcdef") # Match
<_sre.SRE_Match object; span=(0, 1), match='a'>
in each word of a sentence except for the first and last characters::
>>> def repl(m):
- ... inner_word = list(m.group(2))
- ... random.shuffle(inner_word)
- ... return m.group(1) + "".join(inner_word) + m.group(3)
+ ... inner_word = list(m.group(2))
+ ... random.shuffle(inner_word)
+ ... return m.group(1) + "".join(inner_word) + m.group(3)
>>> text = "Professor Abdolmalek, please report your absences promptly."
>>> re.sub(r"(\w)(\w+)(\w)", repl, text)
'Poefsrosr Aealmlobdk, pslaee reorpt your abnseces plmrptoy.'
Writing a Tokenizer
^^^^^^^^^^^^^^^^^^^
-A `tokenizer or scanner <http://en.wikipedia.org/wiki/Lexical_analysis>`_
+A `tokenizer or scanner <https://en.wikipedia.org/wiki/Lexical_analysis>`_
analyzes a string to categorize groups of characters. This is a useful first
step in writing a compiler or interpreter.
def tokenize(code):
keywords = {'IF', 'THEN', 'ENDIF', 'FOR', 'NEXT', 'GOSUB', 'RETURN'}
token_specification = [
- ('NUMBER', r'\d+(\.\d*)?'), # Integer or decimal number
- ('ASSIGN', r':='), # Assignment operator
- ('END', r';'), # Statement terminator
- ('ID', r'[A-Za-z]+'), # Identifiers
- ('OP', r'[+\-*/]'), # Arithmetic operators
- ('NEWLINE', r'\n'), # Line endings
- ('SKIP', r'[ \t]+'), # Skip over spaces and tabs
- ('MISMATCH',r'.'), # Any other character
+ ('NUMBER', r'\d+(\.\d*)?'), # Integer or decimal number
+ ('ASSIGN', r':='), # Assignment operator
+ ('END', r';'), # Statement terminator
+ ('ID', r'[A-Za-z]+'), # Identifiers
+ ('OP', r'[+\-*/]'), # Arithmetic operators
+ ('NEWLINE', r'\n'), # Line endings
+ ('SKIP', r'[ \t]+'), # Skip over spaces and tabs
+ ('MISMATCH',r'.'), # Any other character
]
tok_regex = '|'.join('(?P<%s>%s)' % pair for pair in token_specification)
line_num = 1
.. module:: readline
:platform: Unix
:synopsis: GNU readline support for Python.
+
.. sectionauthor:: Skip Montanaro <skip@pobox.com>
+--------------
The :mod:`readline` module defines a number of functions to facilitate
completion and reading/writing of history files from the Python interpreter.
-This module can be used directly or via the :mod:`rlcompleter` module. Settings
+This module can be used directly, or via the :mod:`rlcompleter` module, which
+supports completion of Python identifiers at the interactive prompt. Settings
made using this module affect the behaviour of both the interpreter's
interactive prompt and the prompts offered by the built-in :func:`input`
function.
.. note::
- On MacOS X the :mod:`readline` module can be implemented using
+ The underlying Readline library API may be implemented by
the ``libedit`` library instead of GNU readline.
+ On MacOS X the :mod:`readline` module detects which library is being used
+ at run time.
The configuration file for ``libedit`` is different from that
of GNU readline. If you programmatically load configuration strings
you can check for the text "libedit" in :const:`readline.__doc__`
to differentiate between GNU readline and libedit.
+Readline keybindings may be configured via an initialization file, typically
+``.inputrc`` in your home directory. See `Readline Init File
+<https://cnswww.cns.cwru.edu/php/chet/readline/rluserman.html#SEC9>`_
+in the GNU Readline manual for information about the format and
+allowable constructs of that file, and the capabilities of the
+Readline library in general.
+
+
+Init file
+---------
-The :mod:`readline` module defines the following functions:
+The following functions relate to the init file and user configuration:
.. function:: parse_and_bind(string)
- Parse and execute single line of a readline init file.
+ Execute the init line provided in the *string* argument. This calls
+ :c:func:`rl_parse_and_bind` in the underlying library.
+
+
+.. function:: read_init_file([filename])
+
+ Execute a readline initialization file. The default filename is the last filename
+ used. This calls :c:func:`rl_read_init_file` in the underlying library.
+
+
+Line buffer
+-----------
+
+The following functions operate on the line buffer:
.. function:: get_line_buffer()
- Return the current contents of the line buffer.
+ Return the current contents of the line buffer (:c:data:`rl_line_buffer`
+ in the underlying library).
.. function:: insert_text(string)
- Insert text into the command line.
+ Insert text into the line buffer at the cursor position. This calls
+ :c:func:`rl_insert_text` in the underlying library, but ignores
+ the return value.
-.. function:: read_init_file([filename])
+.. function:: redisplay()
+
+ Change what's displayed on the screen to reflect the current contents of the
+ line buffer. This calls :c:func:`rl_redisplay` in the underlying library.
- Parse a readline initialization file. The default filename is the last filename
- used.
+
+History file
+------------
+
+The following functions operate on a history file:
.. function:: read_history_file([filename])
- Load a readline history file. The default filename is :file:`~/.history`.
+ Load a readline history file, and append it to the history list.
+ The default filename is :file:`~/.history`. This calls
+ :c:func:`read_history` in the underlying library.
.. function:: write_history_file([filename])
- Save a readline history file. The default filename is :file:`~/.history`.
+ Save the history list to a readline history file, overwriting any
+ existing file. The default filename is :file:`~/.history`. This calls
+ :c:func:`write_history` in the underlying library.
.. function:: append_history_file(nelements[, filename])
- Append the last *nelements* of history to a file. The default filename is
- :file:`~/.history`. The file must already exist.
+ Append the last *nelements* items of history to a file. The default filename is
+ :file:`~/.history`. The file must already exist. This calls
+ :c:func:`append_history` in the underlying library.
.. versionadded:: 3.5
-.. function:: clear_history()
+.. function:: get_history_length()
+ set_history_length(length)
- Clear the current history. (Note: this function is not available if the
- installed version of GNU readline doesn't support it.)
+ Set or return the desired number of lines to save in the history file.
+ The :func:`write_history_file` function uses this value to truncate
+ the history file, by calling :c:func:`history_truncate_file` in
+ the underlying library. Negative values imply
+ unlimited history file size.
-.. function:: get_history_length()
+History list
+------------
- Return the desired length of the history file. Negative values imply unlimited
- history file size.
+The following functions operate on a global history list:
-.. function:: set_history_length(length)
+.. function:: clear_history()
- Set the number of lines to save in the history file. :func:`write_history_file`
- uses this value to truncate the history file when saving. Negative values imply
- unlimited history file size.
+ Clear the current history. This calls :c:func:`clear_history` in the
+ underlying library. The Python function only exists if Python was
+ compiled for a version of the library that supports it.
.. function:: get_current_history_length()
- Return the number of lines currently in the history. (This is different from
+ Return the number of items currently in the history. (This is different from
:func:`get_history_length`, which returns the maximum number of lines that will
be written to a history file.)
.. function:: get_history_item(index)
- Return the current contents of history item at *index*.
+ Return the current contents of history item at *index*. The item index
+ is one-based. This calls :c:func:`history_get` in the underlying library.
.. function:: remove_history_item(pos)
Remove history item specified by its position from the history.
+ The position is zero-based. This calls :c:func:`remove_history` in
+ the underlying library.
.. function:: replace_history_item(pos, line)
- Replace history item specified by its position with the given line.
+ Replace history item specified by its position with *line*.
+ The position is zero-based. This calls :c:func:`replace_history_entry`
+ in the underlying library.
-.. function:: redisplay()
+.. function:: add_history(line)
- Change what's displayed on the screen to reflect the current contents of the
- line buffer.
+ Append *line* to the history buffer, as if it was the last line typed.
+ This calls :c:func:`add_history` in the underlying library.
+
+
+Startup hooks
+-------------
.. function:: set_startup_hook([function])
- Set or remove the startup_hook function. If *function* is specified, it will be
- used as the new startup_hook function; if omitted or ``None``, any hook function
- already installed is removed. The startup_hook function is called with no
+ Set or remove the function invoked by the :c:data:`rl_startup_hook`
+ callback of the underlying library. If *function* is specified, it will
+ be used as the new hook function; if omitted or ``None``, any function
+ already installed is removed. The hook is called with no
arguments just before readline prints the first prompt.
.. function:: set_pre_input_hook([function])
- Set or remove the pre_input_hook function. If *function* is specified, it will
- be used as the new pre_input_hook function; if omitted or ``None``, any hook
- function already installed is removed. The pre_input_hook function is called
+ Set or remove the function invoked by the :c:data:`rl_pre_input_hook`
+ callback of the underlying library. If *function* is specified, it will
+ be used as the new hook function; if omitted or ``None``, any
+ function already installed is removed. The hook is called
with no arguments after the first prompt has been printed and just before
readline starts reading input characters.
+Completion
+----------
+
+The following functions relate to implementing a custom word completion
+function. This is typically operated by the Tab key, and can suggest and
+automatically complete a word being typed. By default, Readline is set up
+to be used by :mod:`rlcompleter` to complete Python identifiers for
+the interactive interpreter. If the :mod:`readline` module is to be used
+with a custom completer, a different set of word delimiters should be set.
+
+
.. function:: set_completer([function])
Set or remove the completer function. If *function* is specified, it will be
returns a non-string value. It should return the next possible completion
starting with *text*.
+ The installed completer function is invoked by the *entry_func* callback
+ passed to :c:func:`rl_completion_matches` in the underlying library.
+ The *text* string comes from the first parameter to the
+ :c:data:`rl_attempted_completion_function` callback of the
+ underlying library.
+
.. function:: get_completer()
.. function:: get_completion_type()
- Get the type of completion being attempted.
+ Get the type of completion being attempted. This returns the
+ :c:data:`rl_completion_type` variable in the underlying library as
+ an integer.
.. function:: get_begidx()
+ get_endidx()
- Get the beginning index of the readline tab-completion scope.
-
-
-.. function:: get_endidx()
-
- Get the ending index of the readline tab-completion scope.
+ Get the beginning or ending index of the completion scope.
+ These indexes are the *start* and *end* arguments passed to the
+ :c:data:`rl_attempted_completion_function` callback of the
+ underlying library.
.. function:: set_completer_delims(string)
+ get_completer_delims()
- Set the readline word delimiters for tab-completion.
-
-
-.. function:: get_completer_delims()
-
- Get the readline word delimiters for tab-completion.
+ Set or get the word delimiters for completion. These determine the
+ start of the word to be considered for completion (the completion scope).
+ These functions access the :c:data:`rl_completer_word_break_characters`
+ variable in the underlying library.
.. function:: set_completion_display_matches_hook([function])
Set or remove the completion display function. If *function* is
specified, it will be used as the new completion display function;
if omitted or ``None``, any completion display function already
- installed is removed. The completion display function is called as
+ installed is removed. This sets or clears the
+ :c:data:`rl_completion_display_matches_hook` callback in the
+ underlying library. The completion display function is called as
``function(substitution, [matches], longest_match_length)`` once
each time matches need to be displayed.
-.. function:: add_history(line)
-
- Append a line to the history buffer, as if it was the last line typed.
-
-.. seealso::
-
- Module :mod:`rlcompleter`
- Completion of Python identifiers at the interactive prompt.
-
-
.. _readline-example:
Example
histfile = os.path.join(os.path.expanduser("~"), ".python_history")
try:
readline.read_history_file(histfile)
+ # default history len is -1 (infinite), which may grow unruly
+ readline.set_history_length(1000)
except FileNotFoundError:
pass
def save(prev_h_len, histfile):
new_h_len = readline.get_history_length()
+ readline.set_history_length(1000)
readline.append_history_file(new_h_len - prev_h_len, histfile)
atexit.register(save, h_len, histfile)
atexit.register(self.save_history, histfile)
def save_history(self, histfile):
+ readline.set_history_length(1000)
readline.write_history_file(histfile)
.. module:: reprlib
:synopsis: Alternate repr() implementation with size limits.
+
.. sectionauthor:: Fred L. Drake, Jr. <fdrake@acm.org>
**Source code:** :source:`Lib/reprlib.py`
.. module:: resource
:platform: Unix
:synopsis: An interface to provide resource usage information on the current process.
+
.. moduleauthor:: Jeremy Hylton <jeremy@alum.mit.edu>
.. sectionauthor:: Jeremy Hylton <jeremy@alum.mit.edu>
+--------------
This module provides basic mechanisms for measuring and controlling system
resources utilized by a program.
.. module:: rlcompleter
:synopsis: Python identifier completion, suitable for the GNU readline library.
+
.. sectionauthor:: Moshe Zadka <moshez@zadka.site.co.il>
**Source code:** :source:`Lib/rlcompleter.py`
.. module:: runpy
:synopsis: Locate and run Python modules without importing them first.
+
.. moduleauthor:: Nick Coghlan <ncoghlan@gmail.com>
**Source code:** :source:`Lib/runpy.py`
import mechanism (refer to :pep:`302` for details) and then executed in a
fresh module namespace.
- If the supplied module name refers to a package rather than a normal
+ The *mod_name* argument should be an absolute module name.
+ If the module name refers to a package rather than a normal
module, then that package is imported and the ``__main__`` submodule within
that package is then executed and the resulting module globals dictionary
returned.
.. module:: sched
:synopsis: General purpose event scheduler.
-.. sectionauthor:: Moshe Zadka <moshez@zadka.site.co.il>
-.. index:: single: event scheduling
+.. sectionauthor:: Moshe Zadka <moshez@zadka.site.co.il>
**Source code:** :source:`Lib/sched.py`
+.. index:: single: event scheduling
+
--------------
The :mod:`sched` module defines a class which implements a general purpose event
.. module:: select
:synopsis: Wait for I/O completion on multiple streams.
+--------------
This module provides access to the :c:func:`select` and :c:func:`poll` functions
available in most operating systems, :c:func:`devpoll` available on
Kevent Objects
--------------
-http://www.freebsd.org/cgi/man.cgi?query=kqueue&sektion=2
+https://www.freebsd.org/cgi/man.cgi?query=kqueue&sektion=2
.. attribute:: kevent.ident
.. versionadded:: 3.4
+**Source code:** :source:`Lib/selectors.py`
+
+--------------
Introduction
------------
:class:`BaseSelector` and its concrete implementations support the
:term:`context manager` protocol.
- .. method:: register(fileobj, events, data=None)
+ .. abstractmethod:: register(fileobj, events, data=None)
Register a file object for selection, monitoring it for I/O events.
:exc:`ValueError` in case of invalid event mask or file descriptor, or
:exc:`KeyError` if the file object is already registered.
- .. method:: unregister(fileobj)
+ .. abstractmethod:: unregister(fileobj)
Unregister a file object from selection, removing it from monitoring. A
file object shall be unregistered prior to being closed.
:exc:`ValueError` in case of invalid event mask or file descriptor, or
:exc:`KeyError` if the file object is not registered.
- .. method:: select(timeout=None)
+ .. abstractmethod:: select(timeout=None)
Wait until some registered file objects become ready, or the timeout
expires.
This returns the :class:`SelectorKey` instance associated to this file
object, or raises :exc:`KeyError` if the file object is not registered.
- .. method:: get_map()
+ .. abstractmethod:: get_map()
Return a mapping of file objects to selector keys.
.. module:: shelve
:synopsis: Python object persistence.
+**Source code:** :source:`Lib/shelve.py`
.. index:: module: pickle
-**Source code:** :source:`Lib/shelve.py`
-
--------------
A "shelf" is a persistent, dictionary-like object. The difference with "dbm"
.. seealso::
- `Persistent dictionary recipe <http://code.activestate.com/recipes/576642/>`_
+ `Persistent dictionary recipe <https://code.activestate.com/recipes/576642/>`_
with widely supported storage formats and having the speed of native
dictionaries.
A subclass of :class:`Shelf` which exposes :meth:`first`, :meth:`!next`,
:meth:`previous`, :meth:`last` and :meth:`set_location` which are available
in the third-party :mod:`bsddb` module from `pybsddb
- <http://www.jcea.es/programacion/pybsddb.htm>`_ but not in other database
+ <https://www.jcea.es/programacion/pybsddb.htm>`_ but not in other database
modules. The *dict* object passed to the constructor must support those
methods. This is generally accomplished by calling one of
:func:`bsddb.hashopen`, :func:`bsddb.btopen` or :func:`bsddb.rnopen`. The
import shelve
- d = shelve.open(filename) # open -- file may get suffix added by low-level
- # library
+ d = shelve.open(filename) # open -- file may get suffix added by low-level
+ # library
+
+ d[key] = data # store data at key (overwrites old data if
+ # using an existing key)
+ data = d[key] # retrieve a COPY of data at key (raise KeyError
+ # if no such key)
+ del d[key] # delete data stored at key (raises KeyError
+ # if no such key)
- d[key] = data # store data at key (overwrites old data if
- # using an existing key)
- data = d[key] # retrieve a COPY of data at key (raise KeyError if no
- # such key)
- del d[key] # delete data stored at key (raises KeyError
- # if no such key)
- flag = key in d # true if the key exists
- klist = list(d.keys()) # a list of all existing keys (slow!)
+ flag = key in d # true if the key exists
+ klist = list(d.keys()) # a list of all existing keys (slow!)
# as d was opened WITHOUT writeback=True, beware:
- d['xx'] = [0, 1, 2] # this works as expected, but...
- d['xx'].append(3) # *this doesn't!* -- d['xx'] is STILL [0, 1, 2]!
+ d['xx'] = [0, 1, 2] # this works as expected, but...
+ d['xx'].append(3) # *this doesn't!* -- d['xx'] is STILL [0, 1, 2]!
# having opened d without writeback=True, you need to code carefully:
- temp = d['xx'] # extracts the copy
- temp.append(5) # mutates the copy
- d['xx'] = temp # stores the copy right back, to persist it
+ temp = d['xx'] # extracts the copy
+ temp.append(5) # mutates the copy
+ d['xx'] = temp # stores the copy right back, to persist it
# or, d=shelve.open(filename,writeback=True) would let you just code
# d['xx'].append(5) and have it work as expected, BUT it would also
# consume more memory and make the d.close() operation slower.
- d.close() # close it
+ d.close() # close it
.. seealso::
.. module:: shlex
:synopsis: Simple lexical analysis for Unix shell-like languages.
+
.. moduleauthor:: Eric S. Raymond <esr@snark.thyrsus.com>
.. moduleauthor:: Gustavo Niemeyer <niemeyer@conectiva.com>
.. sectionauthor:: Eric S. Raymond <esr@snark.thyrsus.com>
This attribute is ``None`` by default. If you assign a string to it, that
string will be recognized as a lexical-level inclusion request similar to the
``source`` keyword in various shells. That is, the immediately following token
- will opened as a filename and input taken from that stream until EOF, at which
+ will be opened as a filename and input will
+ be taken from that stream until EOF, at which
point the :meth:`~io.IOBase.close` method of that stream will be called and
the input source will again become the original input stream. Source
requests may be stacked any number of levels deep.
.. module:: shutil
:synopsis: High-level file operations, including copying.
+
.. sectionauthor:: Fred L. Drake, Jr. <fdrake@acm.org>
.. partly based on the docstrings
+**Source code:** :source:`Lib/shutil.py`
+
.. index::
single: file; copying
single: copying files
-**Source code:** :source:`Lib/shutil.py`
-
--------------
The :mod:`shutil` module offers a number of high-level operations on files and
Return the path to an executable which would be run if the given *cmd* was
called. If no *cmd* would be called, return ``None``.
- *mode* is a permission mask passed a to :func:`os.access`, by default
+ *mode* is a permission mask passed to :func:`os.access`, by default
determining if the file exists and executable.
When no *path* is specified, the results of :func:`os.environ` are used,
.. module:: signal
:synopsis: Set handlers for asynchronous events.
+--------------
This module provides mechanisms to use signal handlers in Python.
General rules
-------------
-The :func:`signal.signal` function allows to define custom handlers to be
+The :func:`signal.signal` function allows defining custom handlers to be
executed when a signal is received. A small number of default handlers are
installed: :const:`SIGPIPE` is ignored (so write errors on pipes and sockets
can be reported as ordinary Python exceptions) and :const:`SIGINT` is
underlying implementation), with the exception of the handler for
:const:`SIGCHLD`, which follows the underlying implementation.
-There is no way to "block" signals temporarily from critical sections (since
-this is not supported by all Unix flavors).
-
Execution of Python signal handlers
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
On Windows, :func:`signal` can only be called with :const:`SIGABRT`,
:const:`SIGFPE`, :const:`SIGILL`, :const:`SIGINT`, :const:`SIGSEGV`, or
:const:`SIGTERM`. A :exc:`ValueError` will be raised in any other case.
+ Note that not all systems define the same set of signal names; an
+ :exc:`AttributeError` will be raised if a signal name is not defined as
+ ``SIG*`` module level constant.
.. function:: sigpending()
A path configuration file is a file whose name has the form :file:`{name}.pth`
and exists in one of the four directories mentioned above; its contents are
additional items (one per line) to be added to ``sys.path``. Non-existing items
-are never added to ``sys.path``, and no check is made that the item refers to a
-directory rather than a file. No item is added to ``sys.path`` more than
+are never added to ``sys.path``. No item is added to ``sys.path`` more than
once. Blank lines and lines beginning with ``#`` are skipped. Lines starting
with ``import`` (followed by space or tab) are executed.
.. module:: smtplib
:synopsis: SMTP protocol client (requires sockets).
+
.. sectionauthor:: Eric S. Raymond <esr@snark.thyrsus.com>
+**Source code:** :source:`Lib/smtplib.py`
.. index::
pair: SMTP; protocol
single: Simple Mail Transfer Protocol
-**Source code:** :source:`Lib/smtplib.py`
-
--------------
The :mod:`smtplib` module defines an SMTP client session object that can be used
*timeout* parameter specifies a timeout in seconds for blocking operations
like the connection attempt (if not specified, the global default timeout
setting will be used). If the timeout expires, :exc:`socket.timeout` is
- raised. The optional source_address parameter allows to bind
+ raised. The optional source_address parameter allows binding
to some specific source address in a machine with multiple network
interfaces, and/or to some specific source TCP port. It takes a 2-tuple
(host, port), for the socket to bind to as its source address before
*port* is zero, the standard SMTP-over-SSL port (465) is used. The optional
arguments *local_hostname*, *timeout* and *source_address* have the same
meaning as they do in the :class:`SMTP` class. *context*, also optional,
- can contain a :class:`~ssl.SSLContext` and allows to configure various
+ can contain a :class:`~ssl.SSLContext` and allows configuring various
aspects of the secure connection. Please read :ref:`ssl-security` for
best practices.
.. module:: sndhdr
:synopsis: Determine type of a sound file.
+
.. sectionauthor:: Fred L. Drake, Jr. <fdrake@acm.org>
.. Based on comments in the module source file.
+**Source code:** :source:`Lib/sndhdr.py`
+
.. index::
single: A-LAW
single: u-LAW
-**Source code:** :source:`Lib/sndhdr.py`
-
--------------
The :mod:`sndhdr` provides utility functions which attempt to determine the type
.. module:: socket
:synopsis: Low-level networking interface.
+**Source code:** :source:`Lib/socket.py`
+
+--------------
This module provides access to the BSD *socket* interface. It is available on
all modern Unix systems, Windows, MacOS, and probably additional platforms.
Previously, :const:`AF_UNIX` socket paths were assumed to use UTF-8
encoding.
- .. versionchanged: 3.5
+ .. versionchanged:: 3.5
Writable :term:`bytes-like object` is now accepted.
- A pair ``(host, port)`` is used for the :const:`AF_INET` address family,
.. versionchanged:: 3.2
*source_address* was added.
- .. versionchanged:: 3.2
- support for the :keyword:`with` statement was added.
-
.. function:: fromfd(fd, family, type, proto=0)
Return a string containing the hostname of the machine where the Python
interpreter is currently executing.
- If you want to know the current machine's IP address, you may want to use
- ``gethostbyname(gethostname())``. This operation assumes that there is a
- valid address-to-host mapping for the host, and the assumption does not
- always hold.
-
Note: :func:`gethostname` doesn't always return the fully qualified domain
name; use :func:`getfqdn` for that.
support IPv6, and :func:`inet_ntop` should be used instead for IPv4/v6 dual
stack support.
- .. versionchanged: 3.5
+ .. versionchanged:: 3.5
Writable :term:`bytes-like object` is now accepted.
.. versionchanged:: 3.4
Windows support added
- .. versionchanged: 3.5
+ .. versionchanged:: 3.5
Writable :term:`bytes-like object` is now accepted.
:meth:`~socket.makefile`, these correspond to Unix system calls applicable
to sockets.
+.. versionchanged:: 3.2
+ Support for the :term:`context manager` protocol was added. Exiting the
+ context manager is equivalent to calling :meth:`~socket.close`.
+
.. method:: socket.accept()
.. method:: socket.fileno()
- Return the socket's file descriptor (a small integer). This is useful with
- :func:`select.select`.
+ Return the socket's file descriptor (a small integer), or -1 on failure. This
+ is useful with :func:`select.select`.
Under Windows the small integer returned by this method cannot be used where a
file descriptor can be used (such as :func:`os.fdopen`). Unix does not have
this limitation.
-
.. method:: socket.get_inheritable()
Get the :ref:`inheritable flag <fd_inheritance>` of the socket's file
The :meth:`ioctl` method is a limited interface to the WSAIoctl system
interface. Please refer to the `Win32 documentation
- <http://msdn.microsoft.com/en-us/library/ms741621%28VS.85%29.aspx>`_ for more
+ <https://msdn.microsoft.com/en-us/library/ms741621%28VS.85%29.aspx>`_ for more
information.
On other platforms, the generic :func:`fcntl.fcntl` and :func:`fcntl.ioctl`
Return a :term:`file object` associated with the socket. The exact returned
type depends on the arguments given to :meth:`makefile`. These arguments are
- interpreted the same way as by the built-in :func:`open` function.
+ interpreted the same way as by the built-in :func:`open` function, except
+ the only supported *mode* values are ``'r'`` (default), ``'w'`` and ``'b'``.
The socket must be in blocking mode; it can have a timeout, but the file
object's internal buffer may end up in an inconsistent state if a timeout
ensure that the bytestring contains the proper bits (see the optional built-in
module :mod:`struct` for a way to encode C structures as bytestrings).
- .. versionchanged: 3.5
+ .. versionchanged:: 3.5
Writable :term:`bytes-like object` is now accepted.
HOST = '' # Symbolic name meaning all available interfaces
PORT = 50007 # Arbitrary non-privileged port
- s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- s.bind((HOST, PORT))
- s.listen(1)
- conn, addr = s.accept()
- print('Connected by', addr)
- while True:
- data = conn.recv(1024)
- if not data: break
- conn.sendall(data)
- conn.close()
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
+ s.bind((HOST, PORT))
+ s.listen(1)
+ conn, addr = s.accept()
+ with conn:
+ print('Connected by', addr)
+ while True:
+ data = conn.recv(1024)
+ if not data: break
+ conn.sendall(data)
::
HOST = 'daring.cwi.nl' # The remote host
PORT = 50007 # The same port as used by the server
- s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- s.connect((HOST, PORT))
- s.sendall(b'Hello, world')
- data = s.recv(1024)
- s.close()
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
+ s.connect((HOST, PORT))
+ s.sendall(b'Hello, world')
+ data = s.recv(1024)
print('Received', repr(data))
The next two examples are identical to the above two, but support both IPv4 and
print('could not open socket')
sys.exit(1)
conn, addr = s.accept()
- print('Connected by', addr)
- while True:
- data = conn.recv(1024)
- if not data: break
- conn.send(data)
- conn.close()
+ with conn:
+ print('Connected by', addr)
+ while True:
+ data = conn.recv(1024)
+ if not data: break
+ conn.send(data)
::
if s is None:
print('could not open socket')
sys.exit(1)
- s.sendall(b'Hello, world')
- data = s.recv(1024)
- s.close()
+ with s:
+ s.sendall(b'Hello, world')
+ data = s.recv(1024)
print('Received', repr(data))
The :mod:`socketserver` module simplifies the task of writing network servers.
-There are four basic server classes: :class:`TCPServer` uses the Internet TCP
-protocol, which provides for continuous streams of data between the client and
-server. :class:`UDPServer` uses datagrams, which are discrete packets of
-information that may arrive out of order or be lost while in transit. The more
-infrequently used :class:`UnixStreamServer` and :class:`UnixDatagramServer`
-classes are similar, but use Unix domain sockets; they're not available on
-non-Unix platforms. For more details on network programming, consult a book
-such as
-W. Richard Steven's UNIX Network Programming or Ralph Davis's Win32 Network
-Programming.
+There are four basic concrete server classes:
+
+
+.. class:: TCPServer(server_address, RequestHandlerClass, bind_and_activate=True)
+
+ This uses the Internet TCP protocol, which provides for
+ continuous streams of data between the client and server.
+ If *bind_and_activate* is true, the constructor automatically attempts to
+ invoke :meth:`~BaseServer.server_bind` and
+ :meth:`~BaseServer.server_activate`. The other parameters are passed to
+ the :class:`BaseServer` base class.
+
+
+.. class:: UDPServer(server_address, RequestHandlerClass, bind_and_activate=True)
+
+ This uses datagrams, which are discrete packets of information that may
+ arrive out of order or be lost while in transit. The parameters are
+ the same as for :class:`TCPServer`.
+
+
+.. class:: UnixStreamServer(server_address, RequestHandlerClass, bind_and_activate=True)
+ UnixDatagramServer(server_address, RequestHandlerClass, bind_and_activate=True)
+
+ These more infrequently used classes are similar to the TCP and
+ UDP classes, but use Unix domain sockets; they're not available on
+ non-Unix platforms. The parameters are the same as for
+ :class:`TCPServer`.
+
These four classes process requests :dfn:`synchronously`; each request must be
completed before the next request can be started. This isn't suitable if each
Creating a server requires several steps. First, you must create a request
handler class by subclassing the :class:`BaseRequestHandler` class and
-overriding its :meth:`handle` method; this method will process incoming
+overriding its :meth:`~BaseRequestHandler.handle` method;
+this method will process incoming
requests. Second, you must instantiate one of the server classes, passing it
the server's address and the request handler class. Then call the
-:meth:`handle_request` or :meth:`serve_forever` method of the server object to
+:meth:`~BaseServer.handle_request` or
+:meth:`~BaseServer.serve_forever` method of the server object to
process one or many requests. Finally, call :meth:`~BaseServer.server_close`
to close the socket.
stream server is the address family, which is simply repeated in both Unix
server classes.
-Forking and threading versions of each type of server can be created using the
-:class:`ForkingMixIn` and :class:`ThreadingMixIn` mix-in classes. For instance,
-a threading UDP server class is created as follows::
- class ThreadingUDPServer(ThreadingMixIn, UDPServer): pass
+.. class:: ForkingMixIn
+ ThreadingMixIn
+
+ Forking and threading versions of each type of server can be created
+ using these mix-in classes. For instance, :class:`ThreadingUDPServer`
+ is created as follows::
+
+ class ThreadingUDPServer(ThreadingMixIn, UDPServer):
+ pass
+
+ The mix-in class comes first, since it overrides a method defined in
+ :class:`UDPServer`. Setting the various attributes also changes the
+ behavior of the underlying server mechanism.
+
+
+.. class:: ForkingTCPServer
+ ForkingUDPServer
+ ThreadingTCPServer
+ ThreadingUDPServer
+
+ These classes are pre-defined using the mix-in classes.
-The mix-in class must come first, since it overrides a method defined in
-:class:`UDPServer`. Setting the various attributes also change the
-behavior of the underlying server mechanism.
To implement a service, you must derive a class from :class:`BaseRequestHandler`
-and redefine its :meth:`handle` method. You can then run various versions of
+and redefine its :meth:`~BaseRequestHandler.handle` method.
+You can then run various versions of
the service by combining one of the server classes with your request handler
class. The request handler class must be different for datagram or stream
services. This can be hidden by using the handler subclasses
In some cases, it may be appropriate to process part of a request synchronously,
but to finish processing in a forked child depending on the request data. This
can be implemented by using a synchronous server and doing an explicit fork in
-the request handler class :meth:`handle` method.
+the request handler class :meth:`~BaseRequestHandler.handle` method.
Another approach to handling multiple simultaneous requests in an environment
that supports neither threads nor :func:`~os.fork` (or where these are too
Server Objects
--------------
-.. class:: BaseServer
+.. class:: BaseServer(server_address, RequestHandlerClass)
This is the superclass of all Server objects in the module. It defines the
interface, given below, but does not implement most of the methods, which is
- done in subclasses.
+ done in subclasses. The two parameters are stored in the respective
+ :attr:`server_address` and :attr:`RequestHandlerClass` attributes.
+
+
+ .. method:: fileno()
+ Return an integer file descriptor for the socket on which the server is
+ listening. This function is most commonly passed to :mod:`selectors`, to
+ allow monitoring multiple servers in the same process.
-.. method:: BaseServer.fileno()
- Return an integer file descriptor for the socket on which the server is
- listening. This function is most commonly passed to :mod:`selectors`, to
- allow monitoring multiple servers in the same process.
+ .. method:: handle_request()
+ Process a single request. This function calls the following methods in
+ order: :meth:`get_request`, :meth:`verify_request`, and
+ :meth:`process_request`. If the user-provided
+ :meth:`~BaseRequestHandler.handle` method of the
+ handler class raises an exception, the server's :meth:`handle_error` method
+ will be called. If no request is received within :attr:`timeout`
+ seconds, :meth:`handle_timeout` will be called and :meth:`handle_request`
+ will return.
-.. method:: BaseServer.handle_request()
- Process a single request. This function calls the following methods in
- order: :meth:`get_request`, :meth:`verify_request`, and
- :meth:`process_request`. If the user-provided :meth:`handle` method of the
- handler class raises an exception, the server's :meth:`handle_error` method
- will be called. If no request is received within :attr:`self.timeout`
- seconds, :meth:`handle_timeout` will be called and :meth:`handle_request`
- will return.
+ .. method:: serve_forever(poll_interval=0.5)
+ Handle requests until an explicit :meth:`shutdown` request. Poll for
+ shutdown every *poll_interval* seconds.
+ Ignores the :attr:`timeout` attribute. It
+ also calls :meth:`service_actions`, which may be used by a subclass or mixin
+ to provide actions specific to a given service. For example, the
+ :class:`ForkingMixIn` class uses :meth:`service_actions` to clean up zombie
+ child processes.
-.. method:: BaseServer.serve_forever(poll_interval=0.5)
+ .. versionchanged:: 3.3
+ Added ``service_actions`` call to the ``serve_forever`` method.
- Handle requests until an explicit :meth:`shutdown` request. Poll for
- shutdown every *poll_interval* seconds. Ignores :attr:`self.timeout`. It
- also calls :meth:`service_actions`, which may be used by a subclass or mixin
- to provide actions specific to a given service. For example, the
- :class:`ForkingMixIn` class uses :meth:`service_actions` to clean up zombie
- child processes.
- .. versionchanged:: 3.3
- Added ``service_actions`` call to the ``serve_forever`` method.
+ .. method:: service_actions()
+ This is called in the :meth:`serve_forever` loop. This method can be
+ overridden by subclasses or mixin classes to perform actions specific to
+ a given service, such as cleanup actions.
-.. method:: BaseServer.service_actions()
+ .. versionadded:: 3.3
- This is called in the :meth:`serve_forever` loop. This method can be
- overridden by subclasses or mixin classes to perform actions specific to
- a given service, such as cleanup actions.
+ .. method:: shutdown()
- .. versionadded:: 3.3
+ Tell the :meth:`serve_forever` loop to stop and wait until it does.
-.. method:: BaseServer.shutdown()
- Tell the :meth:`serve_forever` loop to stop and wait until it does.
+ .. method:: server_close()
+ Clean up the server. May be overridden.
-.. method:: BaseServer.server_close()
- Clean up the server. May be overridden.
+ .. attribute:: address_family
- .. versionadded:: 2.6
+ The family of protocols to which the server's socket belongs.
+ Common examples are :const:`socket.AF_INET` and :const:`socket.AF_UNIX`.
-.. attribute:: BaseServer.address_family
+ .. attribute:: RequestHandlerClass
- The family of protocols to which the server's socket belongs.
- Common examples are :const:`socket.AF_INET` and :const:`socket.AF_UNIX`.
+ The user-provided request handler class; an instance of this class is created
+ for each request.
-.. attribute:: BaseServer.RequestHandlerClass
+ .. attribute:: server_address
- The user-provided request handler class; an instance of this class is created
- for each request.
+ The address on which the server is listening. The format of addresses varies
+ depending on the protocol family;
+ see the documentation for the :mod:`socket` module
+ for details. For Internet protocols, this is a tuple containing a string giving
+ the address, and an integer port number: ``('127.0.0.1', 80)``, for example.
-.. attribute:: BaseServer.server_address
+ .. attribute:: socket
- The address on which the server is listening. The format of addresses varies
- depending on the protocol family; see the documentation for the socket module
- for details. For Internet protocols, this is a tuple containing a string giving
- the address, and an integer port number: ``('127.0.0.1', 80)``, for example.
+ The socket object on which the server will listen for incoming requests.
-.. attribute:: BaseServer.socket
+ The server classes support the following class variables:
- The socket object on which the server will listen for incoming requests.
+ .. XXX should class variables be covered before instance variables, or vice versa?
+ .. attribute:: allow_reuse_address
-The server classes support the following class variables:
+ Whether the server will allow the reuse of an address. This defaults to
+ :const:`False`, and can be set in subclasses to change the policy.
-.. XXX should class variables be covered before instance variables, or vice versa?
-.. attribute:: BaseServer.allow_reuse_address
+ .. attribute:: request_queue_size
- Whether the server will allow the reuse of an address. This defaults to
- :const:`False`, and can be set in subclasses to change the policy.
+ The size of the request queue. If it takes a long time to process a single
+ request, any requests that arrive while the server is busy are placed into a
+ queue, up to :attr:`request_queue_size` requests. Once the queue is full,
+ further requests from clients will get a "Connection denied" error. The default
+ value is usually 5, but this can be overridden by subclasses.
-.. attribute:: BaseServer.request_queue_size
+ .. attribute:: socket_type
- The size of the request queue. If it takes a long time to process a single
- request, any requests that arrive while the server is busy are placed into a
- queue, up to :attr:`request_queue_size` requests. Once the queue is full,
- further requests from clients will get a "Connection denied" error. The default
- value is usually 5, but this can be overridden by subclasses.
+ The type of socket used by the server; :const:`socket.SOCK_STREAM` and
+ :const:`socket.SOCK_DGRAM` are two common values.
-.. attribute:: BaseServer.socket_type
+ .. attribute:: timeout
- The type of socket used by the server; :const:`socket.SOCK_STREAM` and
- :const:`socket.SOCK_DGRAM` are two common values.
+ Timeout duration, measured in seconds, or :const:`None` if no timeout is
+ desired. If :meth:`handle_request` receives no incoming requests within the
+ timeout period, the :meth:`handle_timeout` method is called.
-.. attribute:: BaseServer.timeout
+ There are various server methods that can be overridden by subclasses of base
+ server classes like :class:`TCPServer`; these methods aren't useful to external
+ users of the server object.
- Timeout duration, measured in seconds, or :const:`None` if no timeout is
- desired. If :meth:`handle_request` receives no incoming requests within the
- timeout period, the :meth:`handle_timeout` method is called.
+ .. XXX should the default implementations of these be documented, or should
+ it be assumed that the user will look at socketserver.py?
+ .. method:: finish_request()
-There are various server methods that can be overridden by subclasses of base
-server classes like :class:`TCPServer`; these methods aren't useful to external
-users of the server object.
+ Actually processes the request by instantiating :attr:`RequestHandlerClass` and
+ calling its :meth:`~BaseRequestHandler.handle` method.
-.. XXX should the default implementations of these be documented, or should
- it be assumed that the user will look at socketserver.py?
-.. method:: BaseServer.finish_request()
+ .. method:: get_request()
- Actually processes the request by instantiating :attr:`RequestHandlerClass` and
- calling its :meth:`handle` method.
+ Must accept a request from the socket, and return a 2-tuple containing the *new*
+ socket object to be used to communicate with the client, and the client's
+ address.
-.. method:: BaseServer.get_request()
+ .. method:: handle_error(request, client_address)
- Must accept a request from the socket, and return a 2-tuple containing the *new*
- socket object to be used to communicate with the client, and the client's
- address.
+ This function is called if the :meth:`~BaseRequestHandler.handle`
+ method of a :attr:`RequestHandlerClass` instance raises
+ an exception. The default action is to print the traceback to
+ standard output and continue handling further requests.
-.. method:: BaseServer.handle_error(request, client_address)
+ .. method:: handle_timeout()
- This function is called if the :attr:`RequestHandlerClass`'s :meth:`handle`
- method raises an exception. The default action is to print the traceback to
- standard output and continue handling further requests.
+ This function is called when the :attr:`timeout` attribute has been set to a
+ value other than :const:`None` and the timeout period has passed with no
+ requests being received. The default action for forking servers is
+ to collect the status of any child processes that have exited, while
+ in threading servers this method does nothing.
-.. method:: BaseServer.handle_timeout()
+ .. method:: process_request(request, client_address)
- This function is called when the :attr:`timeout` attribute has been set to a
- value other than :const:`None` and the timeout period has passed with no
- requests being received. The default action for forking servers is
- to collect the status of any child processes that have exited, while
- in threading servers this method does nothing.
+ Calls :meth:`finish_request` to create an instance of the
+ :attr:`RequestHandlerClass`. If desired, this function can create a new process
+ or thread to handle the request; the :class:`ForkingMixIn` and
+ :class:`ThreadingMixIn` classes do this.
-.. method:: BaseServer.process_request(request, client_address)
+ .. Is there any point in documenting the following two functions?
+ What would the purpose of overriding them be: initializing server
+ instance variables, adding new network families?
- Calls :meth:`finish_request` to create an instance of the
- :attr:`RequestHandlerClass`. If desired, this function can create a new process
- or thread to handle the request; the :class:`ForkingMixIn` and
- :class:`ThreadingMixIn` classes do this.
+ .. method:: server_activate()
+ Called by the server's constructor to activate the server. The default behavior
+ for a TCP server just invokes :meth:`~socket.socket.listen`
+ on the server's socket. May be overridden.
-.. Is there any point in documenting the following two functions?
- What would the purpose of overriding them be: initializing server
- instance variables, adding new network families?
-.. method:: BaseServer.server_activate()
+ .. method:: server_bind()
- Called by the server's constructor to activate the server. The default behavior
- just :meth:`listen`\ s to the server's socket. May be overridden.
+ Called by the server's constructor to bind the socket to the desired address.
+ May be overridden.
-.. method:: BaseServer.server_bind()
+ .. method:: verify_request(request, client_address)
- Called by the server's constructor to bind the socket to the desired address.
- May be overridden.
+ Must return a Boolean value; if the value is :const:`True`, the request will
+ be processed, and if it's :const:`False`, the request will be denied. This
+ function can be overridden to implement access controls for a server. The
+ default implementation always returns :const:`True`.
-.. method:: BaseServer.verify_request(request, client_address)
+Request Handler Objects
+-----------------------
- Must return a Boolean value; if the value is :const:`True`, the request will
- be processed, and if it's :const:`False`, the request will be denied. This
- function can be overridden to implement access controls for a server. The
- default implementation always returns :const:`True`.
+.. class:: BaseRequestHandler
+ This is the superclass of all request handler objects. It defines
+ the interface, given below. A concrete request handler subclass must
+ define a new :meth:`handle` method, and can override any of
+ the other methods. A new instance of the subclass is created for each
+ request.
-RequestHandler Objects
-----------------------
-The request handler class must define a new :meth:`handle` method, and can
-override any of the following methods. A new instance is created for each
-request.
+ .. method:: setup()
+ Called before the :meth:`handle` method to perform any initialization actions
+ required. The default implementation does nothing.
-.. method:: RequestHandler.finish()
- Called after the :meth:`handle` method to perform any clean-up actions
- required. The default implementation does nothing. If :meth:`setup`
- raises an exception, this function will not be called.
+ .. method:: handle()
+ This function must do all the work required to service a request. The
+ default implementation does nothing. Several instance attributes are
+ available to it; the request is available as :attr:`self.request`; the client
+ address as :attr:`self.client_address`; and the server instance as
+ :attr:`self.server`, in case it needs access to per-server information.
-.. method:: RequestHandler.handle()
+ The type of :attr:`self.request` is different for datagram or stream
+ services. For stream services, :attr:`self.request` is a socket object; for
+ datagram services, :attr:`self.request` is a pair of string and socket.
- This function must do all the work required to service a request. The
- default implementation does nothing. Several instance attributes are
- available to it; the request is available as :attr:`self.request`; the client
- address as :attr:`self.client_address`; and the server instance as
- :attr:`self.server`, in case it needs access to per-server information.
- The type of :attr:`self.request` is different for datagram or stream
- services. For stream services, :attr:`self.request` is a socket object; for
- datagram services, :attr:`self.request` is a pair of string and socket.
- However, this can be hidden by using the request handler subclasses
- :class:`StreamRequestHandler` or :class:`DatagramRequestHandler`, which
- override the :meth:`setup` and :meth:`finish` methods, and provide
- :attr:`self.rfile` and :attr:`self.wfile` attributes. :attr:`self.rfile` and
- :attr:`self.wfile` can be read or written, respectively, to get the request
- data or return data to the client.
+ .. method:: finish()
+ Called after the :meth:`handle` method to perform any clean-up actions
+ required. The default implementation does nothing. If :meth:`setup`
+ raises an exception, this function will not be called.
-.. method:: RequestHandler.setup()
- Called before the :meth:`handle` method to perform any initialization actions
- required. The default implementation does nothing.
+.. class:: StreamRequestHandler
+ DatagramRequestHandler
+
+ These :class:`BaseRequestHandler` subclasses override the
+ :meth:`~BaseRequestHandler.setup` and :meth:`~BaseRequestHandler.finish`
+ methods, and provide :attr:`self.rfile` and :attr:`self.wfile` attributes.
+ The :attr:`self.rfile` and :attr:`self.wfile` attributes can be
+ read or written, respectively, to get the request data or return data
+ to the client.
Examples
class MyTCPHandler(socketserver.BaseRequestHandler):
"""
- The RequestHandler class for our server.
+ The request handler class for our server.
It is instantiated once per connection to the server, and must
override the handle() method to implement communication to the
data = " ".join(sys.argv[1:])
# Create a socket (SOCK_STREAM means a TCP socket)
- sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-
- try:
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
# Connect to server and send data
sock.connect((HOST, PORT))
sock.sendall(bytes(data + "\n", "utf-8"))
# Receive data from the server and shut down
received = str(sock.recv(1024), "utf-8")
- finally:
- sock.close()
print("Sent: {}".format(data))
print("Received: {}".format(received))
pass
def client(ip, port, message):
- sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- sock.connect((ip, port))
- try:
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
+ sock.connect((ip, port))
sock.sendall(bytes(message, 'ascii'))
response = str(sock.recv(1024), 'ascii')
print("Received: {}".format(response))
- finally:
- sock.close()
if __name__ == "__main__":
# Port 0 means to select an arbitrary unused port
:platform: Unix
:synopsis: The shadow password database (getspnam() and friends).
+--------------
This module provides access to the Unix shadow password database. It is
available on various Unix versions.
.. module:: sqlite3
:synopsis: A DB-API 2.0 implementation using SQLite 3.x.
+
.. sectionauthor:: Gerhard Häring <gh@ghaering.de>
+**Source code:** :source:`Lib/sqlite3/`
+
+--------------
SQLite is a C library that provides a lightweight disk-based database that
doesn't require a separate server process and allows accessing the database
Usually your SQL operations will need to use values from Python variables. You
shouldn't assemble your query using Python's string operations because doing so
is insecure; it makes your program vulnerable to an SQL injection attack
-(see http://xkcd.com/327/ for humorous example of what can go wrong).
+(see https://xkcd.com/327/ for humorous example of what can go wrong).
Instead, use the DB-API's parameter substitution. Put ``?`` as a placeholder
wherever you want to use a value, and then provide a tuple of values as the
The pysqlite web page -- sqlite3 is developed externally under the name
"pysqlite".
- http://www.sqlite.org
+ https://www.sqlite.org
The SQLite web page; the documentation describes the syntax and the
available data types for the supported SQL dialect.
any combination of :const:`PARSE_DECLTYPES` and :const:`PARSE_COLNAMES` to turn
type detection on.
+ By default, *check_same_thread* is :const:`True` and only the creating thread may
+ use the connection. If set :const:`False`, the returned connection may be shared
+ across multiple threads. When using multiple threads with the same connection
+ writing operations should be serialized by the user to avoid data corruption.
+
By default, the :mod:`sqlite3` module uses its :class:`Connection` class for the
connect call. You can, however, subclass the :class:`Connection` class and make
:func:`connect` use your class instead by providing your class for the *factory*
db = sqlite3.connect('file:path/to/database?mode=ro', uri=True)
More information about this feature, including a list of recognized options, can
- be found in the `SQLite URI documentation <http://www.sqlite.org/uri.html>`_.
+ be found in the `SQLite URI documentation <https://www.sqlite.org/uri.html>`_.
.. versionchanged:: 3.4
Added the *uri* parameter.
Creates a user-defined function that you can later use from within SQL
statements under the function name *name*. *num_params* is the number of
- parameters the function accepts, and *func* is a Python callable that is called
- as the SQL function.
+ parameters the function accepts (if *num_params* is -1, the function may
+ take any number of arguments), and *func* is a Python callable that is
+ called as the SQL function.
The function can return any of the types supported by SQLite: bytes, str, int,
float and None.
Creates a user-defined aggregate function.
The aggregate class must implement a ``step`` method, which accepts the number
- of parameters *num_params*, and a ``finalize`` method which will return the
+ of parameters *num_params* (if *num_params* is -1, the function may take
+ any number of arguments), and a ``finalize`` method which will return the
final result of the aggregate.
The ``finalize`` method can return any of the types supported by SQLite:
deleted since the database connection was opened.
- .. attribute:: iterdump
+ .. method:: iterdump
Returns an iterator to dump the database in an SQL text format. Useful when
saving an in-memory database for later restoration. This function provides
Example::
# Convert file existing_db.db to SQL dump file dump.sql
- import sqlite3, os
+ import sqlite3
con = sqlite3.connect('existing_db.db')
with open('dump.sql', 'w') as f:
the cursor's arraysize attribute can affect the performance of this operation.
An empty list is returned when no rows are available.
+ .. method:: close()
+
+ Close the cursor now (rather than whenever ``__del__`` is called).
+
+ The cursor will be unusable from this point forward; a ``ProgrammingError``
+ exception will be raised if any operation is attempted with the cursor.
.. attribute:: rowcount
It is set for ``SELECT`` statements without any matching rows as well.
+ .. attribute:: connection
+
+ This read-only attribute provides the SQLite database :class:`Connection`
+ used by the :class:`Cursor` object. A :class:`Cursor` object created by
+ calling :meth:`con.cursor() <Connection.cursor>` will have a
+ :attr:`connection` attribute that refers to *con*::
+
+ >>> con = sqlite3.connect(":memory:")
+ >>> cur = con.cursor()
+ >>> cur.connection == con
+ True
+
.. _sqlite3-row-objects:
Row Objects
.. moduleauthor:: Bill Janssen <bill.janssen@gmail.com>
.. sectionauthor:: Bill Janssen <bill.janssen@gmail.com>
+**Source code:** :source:`Lib/ssl.py`
.. index:: single: OpenSSL; (use in module ssl)
.. index:: TLS, SSL, Transport Layer Security, Secure Sockets Layer
-**Source code:** :source:`Lib/ssl.py`
-
--------------
This module provides access to Transport Layer Security (often known as "Secure
The *ciphers* parameter sets the available ciphers for this SSL object.
It should be a string in the `OpenSSL cipher list format
- <http://www.openssl.org/docs/apps/ciphers.html#CIPHER_LIST_FORMAT>`_.
+ <https://www.openssl.org/docs/apps/ciphers.html#CIPHER-LIST-FORMAT>`_.
The parameter ``do_handshake_on_connect`` specifies whether to do the SSL
handshake automatically after doing a :meth:`socket.connect`, or whether the
Read the Wikipedia article, `Cryptographically secure pseudorandom number
generator (CSPRNG)
- <http://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator>`_,
+ <https://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator>`_,
to get the requirements of a cryptographically generator.
.. versionadded:: 3.3
string (so you can always use :const:`0.0`). See :rfc:`1750` for more
information on sources of entropy.
- .. versionchanged: 3.5
+ .. versionchanged:: 3.5
Writable :term:`bytes-like object` is now accepted.
Certificate handling
Whether the OpenSSL library has built-in support for *Next Protocol
Negotiation* as described in the `NPN draft specification
- <http://tools.ietf.org/html/draft-agl-tls-nextprotoneg>`_. When true,
+ <https://tools.ietf.org/html/draft-agl-tls-nextprotoneg>`_. When true,
you can use the :meth:`SSLContext.set_npn_protocols` method to advertise
which protocols you want to support.
ALERT_DESCRIPTION_*
Alert Descriptions from :rfc:`5246` and others. The `IANA TLS Alert Registry
- <http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-6>`_
+ <https://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-6>`_
contains this list and references to the RFCs where their meaning is defined.
Used as the return value of the callback function in
SSL sockets also have the following additional methods and attributes:
-.. method:: SSLSocket.read(len=0, buffer=None)
+.. method:: SSLSocket.read(len=1024, buffer=None)
Read up to *len* bytes of data from the SSL socket and return the result as
a ``bytes`` instance. If *buffer* is specified, then read into the buffer
The *capath* string, if present, is
the path to a directory containing several CA certificates in PEM format,
following an `OpenSSL specific layout
- <http://www.openssl.org/docs/ssl/SSL_CTX_load_verify_locations.html>`_.
+ <https://www.openssl.org/docs/ssl/SSL_CTX_load_verify_locations.html>`_.
The *cadata* object, if present, is either an ASCII string of one or more
PEM-encoded certificates or a :term:`bytes-like object` of DER-encoded
Set the available ciphers for sockets created with this context.
It should be a string in the `OpenSSL cipher list format
- <http://www.openssl.org/docs/apps/ciphers.html#CIPHER_LIST_FORMAT>`_.
+ <https://www.openssl.org/docs/apps/ciphers.html#CIPHER-LIST-FORMAT>`_.
If no cipher can be selected (because compile-time options or other
configuration forbids use of all the specified ciphers), an
:class:`SSLError` will be raised.
handshake. It should be a list of strings, like ``['http/1.1', 'spdy/2']``,
ordered by preference. The selection of a protocol will happen during the
handshake, and will play out according to the `NPN draft specification
- <http://tools.ietf.org/html/draft-agl-tls-nextprotoneg>`_. After a
+ <https://tools.ietf.org/html/draft-agl-tls-nextprotoneg>`_. After a
successful handshake, the :meth:`SSLSocket.selected_npn_protocol` method will
return the agreed-upon protocol.
Get statistics about the SSL sessions created or managed by this context.
A dictionary is returned which maps the names of each `piece of information
- <http://www.openssl.org/docs/ssl/SSL_CTX_sess_number.html>`_ to their
+ <https://www.openssl.org/docs/ssl/SSL_CTX_sess_number.html>`_ to their
numeric values. For example, here is the total number of hits and misses
in the session cache since the context was created::
except ImportError:
pass
else:
- ... # do something that requires SSL support
+ ... # do something that requires SSL support
Client-side operation
^^^^^^^^^^^^^^^^^^^^^
:meth:`SSLContext.set_ciphers` method. Starting from Python 3.2.3, the
ssl module disables certain weak ciphers by default, but you may want
to further restrict the cipher choice. Be sure to read OpenSSL's documentation
-about the `cipher list format <http://www.openssl.org/docs/apps/ciphers.html#CIPHER_LIST_FORMAT>`_.
+about the `cipher list format <https://www.openssl.org/docs/apps/ciphers.html#CIPHER-LIST-FORMAT>`_.
If you want to check which ciphers are enabled by a given cipher list, use the
``openssl ciphers`` command on your system.
Class :class:`socket.socket`
Documentation of underlying :mod:`socket` class
- `SSL/TLS Strong Encryption: An Introduction <http://httpd.apache.org/docs/trunk/en/ssl/ssl_intro.html>`_
+ `SSL/TLS Strong Encryption: An Introduction <https://httpd.apache.org/docs/trunk/en/ssl/ssl_intro.html>`_
Intro from the Apache webserver documentation
- `RFC 1422: Privacy Enhancement for Internet Electronic Mail: Part II: Certificate-Based Key Management <http://www.ietf.org/rfc/rfc1422>`_
+ `RFC 1422: Privacy Enhancement for Internet Electronic Mail: Part II: Certificate-Based Key Management <https://www.ietf.org/rfc/rfc1422>`_
Steve Kent
- `RFC 1750: Randomness Recommendations for Security <http://www.ietf.org/rfc/rfc1750>`_
+ `RFC 1750: Randomness Recommendations for Security <https://www.ietf.org/rfc/rfc1750>`_
D. Eastlake et. al.
- `RFC 3280: Internet X.509 Public Key Infrastructure Certificate and CRL Profile <http://www.ietf.org/rfc/rfc3280>`_
+ `RFC 3280: Internet X.509 Public Key Infrastructure Certificate and CRL Profile <https://www.ietf.org/rfc/rfc3280>`_
Housley et. al.
- `RFC 4366: Transport Layer Security (TLS) Extensions <http://www.ietf.org/rfc/rfc4366>`_
+ `RFC 4366: Transport Layer Security (TLS) Extensions <https://www.ietf.org/rfc/rfc4366>`_
Blake-Wilson et. al.
- `RFC 5246: The Transport Layer Security (TLS) Protocol Version 1.2 <http://tools.ietf.org/html/rfc5246>`_
+ `RFC 5246: The Transport Layer Security (TLS) Protocol Version 1.2 <https://tools.ietf.org/html/rfc5246>`_
T. Dierks et. al.
- `RFC 6066: Transport Layer Security (TLS) Extensions <http://tools.ietf.org/html/rfc6066>`_
+ `RFC 6066: Transport Layer Security (TLS) Extensions <https://tools.ietf.org/html/rfc6066>`_
D. Eastlake
- `IANA TLS: Transport Layer Security (TLS) Parameters <http://www.iana.org/assignments/tls-parameters/tls-parameters.xml>`_
+ `IANA TLS: Transport Layer Security (TLS) Parameters <https://www.iana.org/assignments/tls-parameters/tls-parameters.xml>`_
IANA
.. module:: stat
:synopsis: Utilities for interpreting the results of os.stat(),
os.lstat() and os.fstat().
+
.. sectionauthor:: Skip Montanaro <skip@automatrix.com>
-**Source code:** :source:`Modules/_stat.c`
- :source:`Lib/stat.py`
+**Source code:** :source:`Lib/stat.py`
--------------
On Windows, the following file attribute constants are available for use when
testing bits in the ``st_file_attributes`` member returned by :func:`os.stat`.
See the `Windows API documentation
-<http://msdn.microsoft.com/en-us/library/windows/desktop/gg258117.aspx>`_
+<https://msdn.microsoft.com/en-us/library/windows/desktop/gg258117.aspx>`_
for more detail on the meaning of these constants.
.. data:: FILE_ATTRIBUTE_ARCHIVE
.. module:: statistics
:synopsis: mathematical statistics functions
+
.. moduleauthor:: Steven D'Aprano <steve+python@pearwood.info>
.. sectionauthor:: Steven D'Aprano <steve+python@pearwood.info>
.. versionadded:: 3.4
+**Source code:** :source:`Lib/statistics.py`
+
.. testsetup:: *
from statistics import *
__name__ = '<doctest>'
-**Source code:** :source:`Lib/statistics.py`
-
--------------
This module provides functions for calculating mathematical statistics of
* "Statistics for the Behavioral Sciences", Frederick J Gravetter and
Larry B Wallnau (8th Edition).
- * Calculating the `median <http://www.ualberta.ca/~opscan/median.html>`_.
+ * Calculating the `median <https://www.ualberta.ca/~opscan/median.html>`_.
* The `SSMEDIAN
<https://help.gnome.org/users/gnumeric/stable/gnumeric.html#gnumeric-function-SSMEDIAN>`_
All :class:`numbers.Real` types (:class:`int` and :class:`float`) also include
the following operations:
-+--------------------+------------------------------------+--------+
-| Operation | Result | Notes |
-+====================+====================================+========+
-| ``math.trunc(x)`` | *x* truncated to Integral | |
-+--------------------+------------------------------------+--------+
-| ``round(x[, n])`` | *x* rounded to n digits, | |
-| | rounding half to even. If n is | |
-| | omitted, it defaults to 0. | |
-+--------------------+------------------------------------+--------+
-| ``math.floor(x)`` | the greatest integral float <= *x* | |
-+--------------------+------------------------------------+--------+
-| ``math.ceil(x)`` | the least integral float >= *x* | |
-+--------------------+------------------------------------+--------+
++--------------------+---------------------------------------------+
+| Operation | Result |
++====================+=============================================+
+| :func:`math.trunc(\| *x* truncated to :class:`~numbers.Integral` |
+| x) <math.trunc>` | |
++--------------------+---------------------------------------------+
+| :func:`round(x[, | *x* rounded to *n* digits, |
+| n]) <round>` | rounding half to even. If *n* is |
+| | omitted, it defaults to 0. |
++--------------------+---------------------------------------------+
+| :func:`math.floor(\| the greatest :class:`~numbers.Integral` |
+| x) <math.floor>` | <= *x* |
++--------------------+---------------------------------------------+
+| :func:`math.ceil(x)| the least :class:`~numbers.Integral` >= *x* |
+| <math.ceil>` | |
++--------------------+---------------------------------------------+
For additional numeric operations see the :mod:`math` and :mod:`cmath`
modules.
operator: >>
Bitwise operations only make sense for integers. Negative numbers are treated
-as their 2's complement value (this assumes a sufficiently large number of bits
-that no overflow occurs during the operation).
+as their 2's complement value (this assumes that there are enough bits so that
+no overflow occurs during the operation).
The priorities of the binary bitwise operations are all lower than the numeric
operations and higher than the comparisons; the unary operation ``~`` has the
only represent sequences that follow a strict pattern and repetition and
concatenation will usually violate that pattern).
- .. data: start
+ .. attribute:: start
The value of the *start* parameter (or ``0`` if the parameter was
not supplied)
- .. data: stop
+ .. attribute:: stop
The value of the *stop* parameter
- .. data: step
+ .. attribute:: step
The value of the *step* parameter (or ``1`` if the parameter was
not supplied)
For more information on the ``str`` class and its methods, see
:ref:`textseq` and the :ref:`string-methods` section below. To output
- formatted strings, see the :ref:`string-formatting` section. In addition,
+ formatted strings, see the :ref:`formatstrings` section. In addition,
see the :ref:`stringservices` section.
.. method:: str.find(sub[, start[, end]])
- Return the lowest index in the string where substring *sub* is found, such
- that *sub* is contained in the slice ``s[start:end]``. Optional arguments
- *start* and *end* are interpreted as in slice notation. Return ``-1`` if
- *sub* is not found.
+ Return the lowest index in the string where substring *sub* is found within
+ the slice ``s[start:end]``. Optional arguments *start* and *end* are
+ interpreted as in slice notation. Return ``-1`` if *sub* is not found.
.. note::
Return true if all bytes in the sequence are ASCII whitespace and the
sequence is not empty, false otherwise. ASCII whitespace characters are
- those byte values in the sequence b' \t\n\r\x0b\f' (space, tab, newline,
+ those byte values in the sequence ``b' \t\n\r\x0b\f'`` (space, tab, newline,
carriage return, vertical tab, form feed).
.. describe:: len(s)
- Return the cardinality of set *s*.
+ Return the number of elements in set *s* (cardinality of *s*).
.. describe:: x in s
See :ref:`types` for more information.
+.. index:: object; code, code object
+
.. _bltin-code-objects:
Code Objects
------------
-.. index:: object: code
-
.. index::
builtin: compile
single: __code__ (function object attribute)
.. _string-formatting:
-String Formatting
------------------
+Custom String Formatting
+------------------------
The built-in string class provides the ability to do complex variable
-substitutions and value formatting via the :func:`format` method described in
+substitutions and value formatting via the :meth:`~str.format` method described in
:pep:`3101`. The :class:`Formatter` class in the :mod:`string` module allows
you to create and customize your own string formatting behaviors using the same
-implementation as the built-in :meth:`format` method.
+implementation as the built-in :meth:`~str.format` method.
.. class:: Formatter
.. method:: format(format_string, *args, **kwargs)
- :meth:`format` is the primary API method. It takes a format string and
+ The primary API method. It takes a format string and
an arbitrary set of positional and keyword arguments.
- :meth:`format` is just a wrapper that calls :meth:`vformat`.
+ It is just a wrapper that calls :meth:`vformat`.
.. deprecated:: 3.5
Passing a format string as keyword argument *format_string* has been
Some simple format string examples::
- "First, thou shalt count to {0}" # References first positional argument
- "Bring me a {}" # Implicitly references the first positional argument
- "From {} to {}" # Same as "From {0} to {1}"
- "My quest is {name}" # References keyword argument 'name'
- "Weight in tons {0.weight}" # 'weight' attribute of first positional arg
- "Units destroyed: {players[0]}" # First element of keyword argument 'players'.
+ "First, thou shalt count to {0}" # References first positional argument
+ "Bring me a {}" # Implicitly references the first positional argument
+ "From {} to {}" # Same as "From {0} to {1}"
+ "My quest is {name}" # References keyword argument 'name'
+ "Weight in tons {0.weight}" # 'weight' attribute of first positional arg
+ "Units destroyed: {players[0]}" # First element of keyword argument 'players'.
The *conversion* field causes a type coercion before formatting. Normally, the
job of formatting a value is done by the :meth:`__format__` method of the value
described in the next section.
A *format_spec* field can also include nested replacement fields within it.
-These nested replacement fields can contain only a field name; conversion flags
-and format specifications are not allowed. The replacement fields within the
+These nested replacement fields may contain a field name, conversion flag
+and format specification, but deeper nesting is
+not allowed. The replacement fields within the
format_spec are substituted before the *format_spec* string is interpreted.
This allows the formatting of a value to be dynamically specified.
If a valid *align* value is specified, it can be preceded by a *fill*
character that can be any character and defaults to a space if omitted.
-Note that it is not possible to use ``{`` and ``}`` as *fill* char while
-using the :meth:`str.format` method; this limitation however doesn't
+It is not possible to use a literal curly brace ("``{``" or "``}``") as
+the *fill* character when using the :meth:`str.format`
+method. However, it is possible to insert a curly brace
+with a nested replacement field. This limitation doesn't
affect the :func:`format` function.
The meaning of the various alignment options is as follows:
| ``'='`` | Forces the padding to be placed after the sign (if any) |
| | but before the digits. This is used for printing fields |
| | in the form '+000000120'. This alignment option is only |
- | | valid for numeric types. |
+ | | valid for numeric types. It becomes the default when '0'|
+ | | immediately precedes the field width. |
+---------+----------------------------------------------------------+
| ``'^'`` | Forces the field to be centered within the available |
| | space. |
*width* is a decimal integer defining the minimum field width. If not
specified, then the field width will be determined by the content.
-Preceding the *width* field by a zero (``'0'``) character enables
+When no explicit alignment is given, preceding the *width* field by a zero
+(``'0'``) character enables
sign-aware zero-padding for numeric types. This is equivalent to a *fill*
character of ``'0'`` with an *alignment* type of ``'='``.
Format examples
^^^^^^^^^^^^^^^
-This section contains examples of the new format syntax and comparison with
-the old ``%``-formatting.
+This section contains examples of the :meth:`str.format` syntax and
+comparison with the old ``%``-formatting.
In most of the cases the syntax is similar to the old ``%``-formatting, with the
addition of the ``{}`` and with ``:`` used instead of ``%``.
.. module:: stringprep
:synopsis: String preparation, as per RFC 3453
+
.. moduleauthor:: Martin v. Löwis <martin@v.loewis.de>
.. sectionauthor:: Martin v. Löwis <martin@v.loewis.de>
+**Source code:** :source:`Lib/stringprep.py`
+
+--------------
When identifying things (such as host names) in the internet, it is often
necessary to compare such identifications for "equality". Exactly how this
.. module:: struct
:synopsis: Interpret bytes as packed binary data.
+**Source code:** :source:`Lib/struct.py`
+
.. index::
pair: C; structures
triple: packing; binary; data
+--------------
+
This module performs conversions between Python values and C structs represented
as Python :class:`bytes` objects. This can be used in handling binary data
stored in files or from network connections, among other sources. It uses
Unpack from the buffer *buffer* (presumably packed by ``pack(fmt, ...)``)
according to the format string *fmt*. The result is a tuple even if it
- contains exactly one item. The buffer must contain exactly the amount of
- data required by the format (``len(bytes)`` must equal ``calcsize(fmt)``).
+ contains exactly one item. The buffer's size in bytes must match the
+ size required by the format, as reflected by :func:`calcsize`.
.. function:: unpack_from(fmt, buffer, offset=0)
Unpack from *buffer* starting at position *offset*, according to the format
string *fmt*. The result is a tuple even if it contains exactly one
- item. *buffer* must contain at least the amount of data required by the
- format (``len(buffer[offset:])`` must be at least ``calcsize(fmt)``).
+ item. The buffer's size in bytes, minus *offset*, must be at least
+ the size required by the format, as reflected by :func:`calcsize`.
.. function:: iter_unpack(fmt, buffer)
Iteratively unpack from the buffer *buffer* according to the format
string *fmt*. This function returns an iterator which will read
equally-sized chunks from the buffer until all its contents have been
- consumed. The buffer's size in bytes must be a multiple of the amount
- of data required by the format, as reflected by :func:`calcsize`.
+ consumed. The buffer's size in bytes must be a multiple of the size
+ required by the format, as reflected by :func:`calcsize`.
Each iteration yields a tuple as specified by the format string.
.. method:: pack(v1, v2, ...)
Identical to the :func:`pack` function, using the compiled format.
- (``len(result)`` will equal :attr:`self.size`.)
+ (``len(result)`` will equal :attr:`size`.)
.. method:: pack_into(buffer, offset, v1, v2, ...)
.. method:: unpack(buffer)
Identical to the :func:`unpack` function, using the compiled format.
- (``len(buffer)`` must equal :attr:`self.size`).
+ The buffer's size in bytes must equal :attr:`size`.
.. method:: unpack_from(buffer, offset=0)
Identical to the :func:`unpack_from` function, using the compiled format.
- (``len(buffer[offset:])`` must be at least :attr:`self.size`).
+ The buffer's size in bytes, minus *offset*, must be at least
+ :attr:`size`.
.. method:: iter_unpack(buffer)
Identical to the :func:`iter_unpack` function, using the compiled format.
- (``len(buffer)`` must be a multiple of :attr:`self.size`).
+ The buffer's size in bytes must be a multiple of :attr:`size`.
.. versionadded:: 3.4
.. module:: subprocess
:synopsis: Subprocess management.
+
.. moduleauthor:: Peter Åstrand <astrand@lysator.liu.se>
.. sectionauthor:: Peter Åstrand <astrand@lysator.liu.se>
+**Source code:** :source:`Lib/subprocess.py`
+
+--------------
The :mod:`subprocess` module allows you to spawn new processes, connect to their
input/output/error pipes, and obtain their return codes. This module intends to
.. attribute:: returncode
- Exit status of the child process.
+ Exit status of the child process. If the process exited due to a
+ signal, this will be the negative signal number.
.. attribute:: cmd
execute. On Windows, in order to run a `side-by-side assembly`_ the
specified *env* **must** include a valid :envvar:`SystemRoot`.
- .. _side-by-side assembly: http://en.wikipedia.org/wiki/Side-by-Side_Assembly
+ .. _side-by-side assembly: https://en.wikipedia.org/wiki/Side-by-Side_Assembly
If *universal_newlines* is ``True``, the file objects *stdin*, *stdout*
and *stderr* are opened as text streams in universal newlines mode, as
If the shell is invoked explicitly, via ``shell=True``, it is the application's
responsibility to ensure that all whitespace and metacharacters are
quoted appropriately to avoid
-`shell injection <http://en.wikipedia.org/wiki/Shell_injection#Shell_injection>`_
+`shell injection <https://en.wikipedia.org/wiki/Shell_injection#Shell_injection>`_
vulnerabilities.
When using ``shell=True``, the :func:`shlex.quote` function can be
.. class:: STARTUPINFO()
Partial support of the Windows
- `STARTUPINFO <http://msdn.microsoft.com/en-us/library/ms686331(v=vs.85).aspx>`__
+ `STARTUPINFO <https://msdn.microsoft.com/en-us/library/ms686331(v=vs.85).aspx>`__
structure is used for :class:`Popen` creation.
.. attribute:: dwFlags
If :attr:`dwFlags` specifies :data:`STARTF_USESHOWWINDOW`, this attribute
can be any of the values that can be specified in the ``nCmdShow``
parameter for the
- `ShowWindow <http://msdn.microsoft.com/en-us/library/ms633548(v=vs.85).aspx>`__
+ `ShowWindow <https://msdn.microsoft.com/en-us/library/ms633548(v=vs.85).aspx>`__
function, except for ``SW_SHOWDEFAULT``. Otherwise, this attribute is
ignored.
.. module:: sunau
:synopsis: Provide an interface to the Sun AU sound format.
+
.. sectionauthor:: Moshe Zadka <moshez@zadka.site.co.il>
**Source code:** :source:`Lib/sunau.py`
.. module:: symbol
:synopsis: Constants representing internal nodes of the parse tree.
+
.. sectionauthor:: Fred L. Drake, Jr. <fdrake@acm.org>
**Source code:** :source:`Lib/symbol.py`
.. module:: sys
:synopsis: Access system-specific parameters and functions.
+--------------
This module provides access to some variables used or maintained by the
interpreter and to functions that interact strongly with the interpreter. It is
additional garbage collector overhead if the object is managed by the garbage
collector.
- See `recursive sizeof recipe <http://code.activestate.com/recipes/577504>`_
+ See `recursive sizeof recipe <https://code.activestate.com/recipes/577504>`_
for an example of using :func:`getsizeof` recursively to find the size of
containers and all their contents.
.. data:: meta_path
- A list of :term:`finder` objects that have their :meth:`find_module`
- methods called to see if one of the objects can find the module to be
- imported. The :meth:`find_module` method is called at least with the
- absolute name of the module being imported. If the module to be imported is
- contained in package then the parent package's :attr:`__path__` attribute
- is passed in as a second argument. The method returns ``None`` if
- the module cannot be found, else returns a :term:`loader`.
-
- :data:`sys.meta_path` is searched before any implicit default finders or
- :data:`sys.path`.
-
- See :pep:`302` for the original specification.
-
+ A list of :term:`meta path finder` objects that have their
+ :meth:`~importlib.abc.MetaPathFinder.find_spec` methods called to see if one
+ of the objects can find the module to be imported. The
+ :meth:`~importlib.abc.MetaPathFinder.find_spec` method is called with at
+ least the absolute name of the module being imported. If the module to be
+ imported is contained in a package, then the parent package's :attr:`__path__`
+ attribute is passed in as a second argument. The method returns a
+ :term:`module spec`, or ``None`` if the module cannot be found.
+
+ .. seealso::
+
+ :class:`importlib.abc.MetaPathFinder`
+ The abstract base class defining the interface of finder objects on
+ :data:`meta_path`.
+ :class:`importlib.machinery.ModuleSpec`
+ The concrete class which
+ :meth:`~importlib.abc.MetaPathFinder.find_spec` should return
+ instances of.
+
+ .. versionchanged:: 3.4
+
+ :term:`Module specs <module spec>` were introduced in Python 3.4, by
+ :pep:`451`. Earlier versions of Python looked for a method called
+ :meth:`~importlib.abc.MetaPathFinder.find_module`.
+ This is still called as a fallback if a :data:`meta_path` entry doesn't
+ have a :meth:`~importlib.abc.MetaPathFinder.find_spec` method.
.. data:: modules
.. module:: sysconfig
:synopsis: Python's configuration information
+
.. moduleauthor:: Tarek Ziadé <tarek@ziade.org>
.. sectionauthor:: Tarek Ziadé <tarek@ziade.org>
-.. index::
- single: configuration information
-
.. versionadded:: 3.2
**Source code:** :source:`Lib/sysconfig.py`
+.. index::
+ single: configuration information
+
--------------
The :mod:`sysconfig` module provides access to Python's configuration
:platform: Unix
:synopsis: An interface to the Unix syslog library routines.
+--------------
This module provides an interface to the Unix ``syslog`` library routines.
Refer to the Unix manual pages for a detailed description of the ``syslog``
.. module:: tabnanny
:synopsis: Tool for detecting white space related problems in Python
source files in a directory tree.
+
.. moduleauthor:: Tim Peters <tim_one@users.sourceforge.net>
.. sectionauthor:: Peter Funk <pf@artcom-gmbh.de>
.. module:: tarfile
:synopsis: Read and write tar-format archive files.
-
.. moduleauthor:: Lars Gustäbel <lars@gustaebel.de>
.. sectionauthor:: Lars Gustäbel <lars@gustaebel.de>
For modes ``'w:gz'``, ``'r:gz'``, ``'w:bz2'``, ``'r:bz2'``, ``'x:gz'``,
``'x:bz2'``, :func:`tarfile.open` accepts the keyword argument
- *compresslevel* to specify the compression level of the file.
+ *compresslevel* (default ``9``) to specify the compression level of the file.
For special purposes, there is a second format for *mode*:
``'filemode|[compression]'``. :func:`tarfile.open` will return a :class:`TarFile`
specifies the blocksize and defaults to ``20 * 512`` bytes. Use this variant
in combination with e.g. ``sys.stdin``, a socket :term:`file object` or a tape
device. However, such a :class:`TarFile` object is limited in that it does
- not allow to be accessed randomly, see :ref:`tar-examples`. The currently
+ not allow random access, see :ref:`tar-examples`. The currently
possible modes:
+-------------+--------------------------------------------+
| ``'r|bz2'`` | Open a bzip2 compressed *stream* for |
| | reading. |
+-------------+--------------------------------------------+
- | ``'r|xz'`` | Open a lzma compressed *stream* for |
+ | ``'r|xz'`` | Open an lzma compressed *stream* for |
| | reading. |
+-------------+--------------------------------------------+
| ``'w|'`` | Open an uncompressed *stream* for writing. |
Documentation of the higher-level archiving facilities provided by the
standard :mod:`shutil` module.
- `GNU tar manual, Basic Tar Format <http://www.gnu.org/software/tar/manual/html_node/Standard.html>`_
+ `GNU tar manual, Basic Tar Format <https://www.gnu.org/software/tar/manual/html_node/Standard.html>`_
Documentation for tar archive files, including GNU tar extensions.
.. method:: TarFile.addfile(tarinfo, fileobj=None)
Add the :class:`TarInfo` object *tarinfo* to the archive. If *fileobj* is given,
+ it should be a :term:`binary file`, and
``tarinfo.size`` bytes are read from it and added to the archive. You can
- create :class:`TarInfo` objects using :meth:`gettarinfo`.
-
- .. note::
-
- On Windows platforms, *fileobj* should always be opened with mode ``'rb'`` to
- avoid irritation about the file size.
+ create :class:`TarInfo` objects directly, or by using :meth:`gettarinfo`.
.. method:: TarFile.gettarinfo(name=None, arcname=None, fileobj=None)
- Create a :class:`TarInfo` object for either the file *name* or the :term:`file
- object` *fileobj* (using :func:`os.fstat` on its file descriptor). You can modify
- some of the :class:`TarInfo`'s attributes before you add it using :meth:`addfile`.
- If given, *arcname* specifies an alternative name for the file in the archive.
+ Create a :class:`TarInfo` object from the result of :func:`os.stat` or
+ equivalent on an existing file. The file is either named by *name*, or
+ specified as a :term:`file object` *fileobj* with a file descriptor. If
+ given, *arcname* specifies an alternative name for the file in the
+ archive, otherwise, the name is taken from *fileobj*’s
+ :attr:`~io.FileIO.name` attribute, or the *name* argument. The name
+ should be a text string.
+
+ You can modify
+ some of the :class:`TarInfo`’s attributes before you add it using :meth:`addfile`.
+ If the file object is not an ordinary file object positioned at the
+ beginning of the file, attributes such as :attr:`~TarInfo.size` may need
+ modifying. This is the case for objects such as :class:`~gzip.GzipFile`.
+ The :attr:`~TarInfo.name` may also be modified, in which case *arcname*
+ could be a dummy string.
.. method:: TarFile.close()
.. module:: telnetlib
:synopsis: Telnet client class.
+
.. sectionauthor:: Skip Montanaro <skip@pobox.com>
+**Source code:** :source:`Lib/telnetlib.py`
.. index:: single: protocol; Telnet
-**Source code:** :source:`Lib/telnetlib.py`
-
--------------
The :mod:`telnetlib` module provides a :class:`Telnet` class that implements the
:mod:`tempfile` --- Generate temporary files and directories
============================================================
-.. sectionauthor:: Zack Weinberg <zack@codesourcery.com>
-
-
.. module:: tempfile
:synopsis: Generate temporary files and directories.
+.. sectionauthor:: Zack Weinberg <zack@codesourcery.com>
+
+**Source code:** :source:`Lib/tempfile.py`
.. index::
pair: temporary; file name
pair: temporary; file
-**Source code:** :source:`Lib/tempfile.py`
-
--------------
This module creates temporary files and directories. It works on all
This function operates exactly as :func:`TemporaryFile` does, except that
the file is guaranteed to have a visible name in the file system (on
Unix, the directory entry is not unlinked). That name can be retrieved
- from the :attr:`name` attribute of the file object. Whether the name can be
+ from the :attr:`name` attribute of the returned
+ file-like object. Whether the name can be
used to open the file a second time, while the named temporary file is
still open, varies across platforms (it can be so used on Unix; it cannot
on Windows NT or later). If *delete* is true (the default), the file is
module.
If ``tempdir`` is unset or ``None`` at any call to any of the above
- functions except :func:`gettempprefix` it is initalized following the
+ functions except :func:`gettempprefix` it is initialized following the
algorithm described in :func:`gettempdir`.
.. _tempfile-examples:
:platform: Unix
:synopsis: POSIX style tty control.
-
.. index::
pair: POSIX; I/O control
pair: tty; I/O control
-This module provides an interface to the POSIX calls for tty I/O control. For a
-complete description of these calls, see the POSIX or Unix manual pages. It is
-only available for those Unix versions that support POSIX *termios* style tty
-I/O control (and then only if configured at installation time).
+--------------
+
+This module provides an interface to the POSIX calls for tty I/O control. For a
+complete description of these calls, see :manpage:`termios(2)` Unix manual
+page. It is only available for those Unix versions that support POSIX
+*termios* style tty I/O control configured during installation.
All functions in this module take a file descriptor *fd* as their first
argument. This can be an integer file descriptor, such as returned by
.. module:: test
:synopsis: Regression tests package containing the testing suite for Python.
+
.. sectionauthor:: Brett Cannon <brett@python.org>
.. note::
mentioned here can change or be removed without notice between releases of
Python.
+--------------
The :mod:`test` package contains all regression tests for Python as well as the
modules :mod:`test.support` and :mod:`test.regrtest`.
or passed to an external program (i.e. the ``-accept`` argument to
openssl's s_server mode). Always prefer :func:`bind_port` over
:func:`find_unused_port` where possible. Using a hard coded port is
- discouraged since it can makes multiple instances of the test impossible to
+ discouraged since it can make multiple instances of the test impossible to
run simultaneously, which is a problem for buildbots.
are expected to crash a subprocess.
On Windows, it disables Windows Error Reporting dialogs using
- `SetErrorMode <http://msdn.microsoft.com/en-us/library/windows/desktop/ms680621.aspx>`_.
+ `SetErrorMode <https://msdn.microsoft.com/en-us/library/windows/desktop/ms680621.aspx>`_.
On UNIX, :func:`resource.setrlimit` is used to set
:attr:`resource.RLIMIT_CORE`'s soft limit to 0 to prevent coredump file
.. module:: textwrap
:synopsis: Text wrapping and filling
+
.. moduleauthor:: Greg Ward <gward@python.net>
.. sectionauthor:: Greg Ward <gward@python.net>
print("hello, world")
t = Timer(30.0, hello)
- t.start() # after 30 seconds, "hello, world" will be printed
+ t.start() # after 30 seconds, "hello, world" will be printed
.. class:: Timer(interval, function, args=None, kwargs=None)
.. module:: time
:synopsis: Time access and conversions.
+--------------
This module provides various time-related functions. For related
functionality, see also the :mod:`datetime` and :mod:`calendar` modules.
+-------+-------------------+---------------------------------+
Note that unlike the C structure, the month value is a range of [1, 12], not
- [0, 11]. A ``-1`` argument as the daylight
- savings flag, passed to :func:`mktime` will usually result in the correct
- daylight savings state to be filled in.
+ [0, 11].
+
+ In calls to :func:`mktime`, :attr:`tm_isdst` may be set to 1 when daylight
+ savings time is in effect, and 0 when it is not. A value of -1 indicates that
+ this is not known, and will usually result in the correct state being filled in.
When a tuple with an incorrect length is passed to a function expecting a
:class:`struct_time`, or having elements of the wrong type, a
.. module:: timeit
:synopsis: Measure the execution time of small code snippets.
+**Source code:** :source:`Lib/timeit.py`
.. index::
single: Benchmarking
single: Performance
-**Source code:** :source:`Lib/timeit.py`
-
--------------
This module provides a simple way to time small bits of Python code. It has both
-a :ref:`command-line-interface` as well as a :ref:`callable <python-interface>`
+a :ref:`timeit-command-line-interface` as well as a :ref:`callable <python-interface>`
one. It avoids a number of common traps for measuring execution times.
See also Tim Peters' introduction to the "Algorithms" chapter in the *Python
Cookbook*, published by O'Reilly.
Basic Examples
--------------
-The following example shows how the :ref:`command-line-interface`
+The following example shows how the :ref:`timeit-command-line-interface`
can be used to compare three different expressions:
.. code-block:: sh
where the traceback is sent; it defaults to :data:`sys.stderr`.
-.. _command-line-interface:
+.. _timeit-command-line-interface:
Command-Line Interface
----------------------
.. module:: tkinter
:synopsis: Interface to Tcl/Tk for graphical user interfaces
+
.. moduleauthor:: Guido van Rossum <guido@Python.org>
+**Source code:** :source:`Lib/tkinter/__init__.py`
+
+--------------
The :mod:`tkinter` package ("Tk interface") is the standard Python interface to
the Tk GUI toolkit. Both Tk and :mod:`tkinter` are available on most Unix
`TKDocs <http://www.tkdocs.com/>`_
Extensive tutorial plus friendlier widget pages for some of the widgets.
- `Tkinter reference: a GUI for Python <http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/index.html>`_
+ `Tkinter reference: a GUI for Python <https://infohost.nmt.edu/tcc/help/pubs/tkinter/web/index.html>`_
On-line reference material.
`Tkinter docs from effbot <http://effbot.org/tkinterbook/>`_
Online reference for tkinter supported by effbot.org.
- `Tcl/Tk manual <http://www.tcl.tk/man/tcl8.5/>`_
+ `Tcl/Tk manual <https://www.tcl.tk/man/tcl8.5/>`_
Official manual for the latest tcl/tk version.
- `Programming Python <http://www.rmi.net/~lutz/about-pp4e.html>`_
+ `Programming Python <http://learning-python.com/books/about-pp4e.html>`_
Book by Mark Lutz, has excellent coverage of Tkinter.
`Modern Tkinter for Busy Python Developers <http://www.amazon.com/Modern-Tkinter-Python-Developers-ebook/dp/B0071QDNLO/>`_
Book by Mark Rozerman about building attractive and modern graphical user interfaces with Python and Tkinter.
- `Python and Tkinter Programming <http://www.manning.com/grayson/>`_
+ `Python and Tkinter Programming <https://www.manning.com/books/python-and-tkinter-programming>`_
The book by John Grayson (ISBN 1-884777-81-3).
.. seealso::
- `Tcl/Tk 8.6 man pages <http://www.tcl.tk/man/tcl8.6/>`_
+ `Tcl/Tk 8.6 man pages <https://www.tcl.tk/man/tcl8.6/>`_
The Tcl/Tk manual on www.tcl.tk.
`ActiveState Tcl Home Page <http://tcl.activestate.com/>`_
self.hi_there.pack(side="top")
self.QUIT = tk.Button(self, text="QUIT", fg="red",
- command=root.destroy)
+ command=root.destroy)
self.QUIT.pack(side="bottom")
def say_hi(self):
.. module:: tkinter.scrolledtext
:platform: Tk
:synopsis: Text widget with a vertical scroll bar.
+
.. sectionauthor:: Fred L. Drake, Jr. <fdrake@acm.org>
+**Source code:** :source:`Lib/tkinter/scrolledtext.py`
+
+--------------
The :mod:`tkinter.scrolledtext` module provides a class of the same name which
implements a basic text widget which has a vertical scroll bar configured to do
.. module:: tkinter.tix
:synopsis: Tk Extension Widgets for Tkinter
+
.. sectionauthor:: Mike Clarkson <mikeclarkson@users.sourceforge.net>
+**Source code:** :source:`Lib/tkinter/tix.py`
.. index:: single: Tix
+--------------
+
The :mod:`tkinter.tix` (Tk Interface Extension) module provides an additional
rich set of widgets. Although the standard Tk library has many useful widgets,
they are far from complete. The :mod:`tkinter.tix` library provides most of the
The `LabelEntry
<http://tix.sourceforge.net/dist/current/man/html/TixCmd/tixLabelEntry.htm>`_
- widget packages an entry widget and a label into one mega widget. It can be used
+ widget packages an entry widget and a label into one mega widget. It can
be used to simplify the creation of "entry-form" type of interface.
.. Python Demo of:
The `ExFileSelectBox
<http://tix.sourceforge.net/dist/current/man/html/TixCmd/tixExFileSelectBox.htm>`_
- widget is usually embedded in a tixExFileSelectDialog widget. It provides an
+ widget is usually embedded in a tixExFileSelectDialog widget. It provides a
convenient method for the user to select files. The style of the
:class:`ExFileSelectBox` widget is very similar to the standard file dialog on
MS Windows 3.1.
.. module:: tkinter.ttk
:synopsis: Tk themed widget set
+
.. sectionauthor:: Guilherme Polo <ggpolo@gmail.com>
+**Source code:** :source:`Lib/tkinter/ttk.py`
.. index:: single: ttk
+--------------
+
The :mod:`tkinter.ttk` module provides access to the Tk themed widget set,
introduced in Tk 8.5. If Python has not been compiled against Tk 8.5, this
module can still be accessed if *Tile* has been installed. The former
.. seealso::
- `Tk Widget Styling Support <http://www.tcl.tk/cgi-bin/tct/tip/48>`_
+ `Tk Widget Styling Support <https://www.tcl.tk/cgi-bin/tct/tip/48>`_
A document introducing theming support for Tk
:meth:`Widget.configure`, :meth:`Widget.identify`, :meth:`Widget.instate`
and :meth:`Widget.state`, and the following inherited from :class:`Entry`:
:meth:`Entry.bbox`, :meth:`Entry.delete`, :meth:`Entry.icursor`,
-:meth:`Entry.index`, :meth:`Entry.inset`, :meth:`Entry.selection`,
+:meth:`Entry.index`, :meth:`Entry.insert`, :meth:`Entry.selection`,
:meth:`Entry.xview`, it has some other methods, described at
:class:`ttk.Combobox`.
headings. Columns may be accessed by number or symbolic names listed in the
widget option columns. See `Column Identifiers`_.
-Each item is identified by an unique name. The widget will generate item IDs
+Each item is identified by a unique name. The widget will generate item IDs
if they are not supplied by the caller. There is a distinguished root item,
named ``{}``. The root item itself is not displayed; its children appear at the
top level of the hierarchy.
.. module:: token
:synopsis: Constants representing terminal nodes of the parse tree.
+
.. sectionauthor:: Fred L. Drake, Jr. <fdrake@acm.org>
**Source code:** :source:`Lib/token.py`
RARROW
ELLIPSIS
OP
+ AWAIT
+ ASYNC
ERRORTOKEN
N_TOKENS
NT_OFFSET
+ .. versionchanged:: 3.5
+ Added :data:`AWAIT` and :data:`ASYNC` tokens. Starting with
+ Python 3.7, "async" and "await" will be tokenized as :data:`NAME`
+ tokens, and :data:`AWAIT` and :data:`ASYNC` will be removed.
.. seealso::
.. module:: tokenize
:synopsis: Lexical scanner for Python source code.
+
.. moduleauthor:: Ka Ping Yee
.. sectionauthor:: Fred L. Drake, Jr. <fdrake@acm.org>
.. function:: tokenize(readline)
- The :func:`tokenize` generator requires one argument, *readline*, which
+ The :func:`.tokenize` generator requires one argument, *readline*, which
must be a callable object which provides the same interface as the
:meth:`io.IOBase.readline` method of file objects. Each call to the
function should return one line of input as bytes.
.. versionchanged:: 3.3
Added support for ``exact_type``.
- :func:`tokenize` determines the source encoding of the file by looking for a
+ :func:`.tokenize` determines the source encoding of the file by looking for a
UTF-8 BOM or encoding cookie, according to :pep:`263`.
.. data:: ENCODING
Token value that indicates the encoding used to decode the source bytes
- into text. The first token returned by :func:`tokenize` will always be an
+ into text. The first token returned by :func:`.tokenize` will always be an
ENCODING token.
positions) may change.
It returns bytes, encoded using the ENCODING token, which is the first
- token sequence output by :func:`tokenize`.
+ token sequence output by :func:`.tokenize`.
-:func:`tokenize` needs to detect the encoding of source files it tokenizes. The
+:func:`.tokenize` needs to detect the encoding of source files it tokenizes. The
function it uses to do this is available:
.. function:: detect_encoding(readline)
The :func:`detect_encoding` function is used to detect the encoding that
should be used to decode a Python source file. It requires one argument,
- readline, in the same way as the :func:`tokenize` generator.
+ readline, in the same way as the :func:`.tokenize` generator.
It will call readline a maximum of twice, and return the encoding used
(as a string) and a list of any lines (not decoded from bytes) it has read
If no encoding is specified, then the default of ``'utf-8'`` will be
returned.
- Use :func:`open` to open Python source files: it uses
+ Use :func:`.open` to open Python source files: it uses
:func:`detect_encoding` to detect the file encoding.
we're only showing 12 digits, and the 13th isn't close to 5, the
rest of the output should be platform-independent.
- >>> exec(s) #doctest: +ELLIPSIS
+ >>> exec(s) #doctest: +ELLIPSIS
-3.21716034272e-0...7
Output from calculations with Decimal should be identical across all
-3.217160342717258261933904529E-7
"""
result = []
- g = tokenize(BytesIO(s.encode('utf-8')).readline) # tokenize the string
- for toknum, tokval, _, _, _ in g:
+ g = tokenize(BytesIO(s.encode('utf-8')).readline) # tokenize the string
+ for toknum, tokval, _, _, _ in g:
if toknum == NUMBER and '.' in tokval: # replace NUMBER tokens
result.extend([
(NAME, 'Decimal'),
.. module:: traceback
:synopsis: Print or retrieve a stack traceback.
+**Source code:** :source:`Lib/traceback.py`
+
+--------------
This module provides a standard interface to extract, format and print stack
traces of Python programs. It exactly mimics the behavior of the Python
The module defines the following functions:
-.. function:: print_tb(traceback, limit=None, file=None)
+.. function:: print_tb(tb, limit=None, file=None)
- Print up to *limit* stack trace entries from *traceback* (starting from
- the caller's frame) if *limit* is positive. Otherwise, print the last
- ``abs(limit)`` entries. If *limit* is omitted or ``None``, all entries
- are printed. If *file* is omitted or ``None``, the output goes to
- ``sys.stderr``; otherwise it should be an open file or file-like object
- to receive the output.
+ Print up to *limit* stack trace entries from traceback object *tb* (starting
+ from the caller's frame) if *limit* is positive. Otherwise, print the last
+ ``abs(limit)`` entries. If *limit* is omitted or ``None``, all entries are
+ printed. If *file* is omitted or ``None``, the output goes to
+ ``sys.stderr``; otherwise it should be an open file or file-like object to
+ receive the output.
.. versionchanged:: 3.5
Added negative *limit* support.
-.. function:: print_exception(type, value, traceback, limit=None, file=None, chain=True)
+.. function:: print_exception(etype, value, tb, limit=None, file=None, chain=True)
- Print exception information and stack trace entries from
- *traceback* to *file*. This differs from :func:`print_tb` in the following
+ Print exception information and stack trace entries from traceback object
+ *tb* to *file*. This differs from :func:`print_tb` in the following
ways:
- * if *traceback* is not ``None``, it prints a header ``Traceback (most recent
+ * if *tb* is not ``None``, it prints a header ``Traceback (most recent
call last):``
- * it prints the exception *type* and *value* after the stack trace
- * if *type* is :exc:`SyntaxError` and *value* has the appropriate format, it
+ * it prints the exception *etype* and *value* after the stack trace
+ * if *etype* is :exc:`SyntaxError` and *value* has the appropriate format, it
prints the line where the syntax error occurred with a caret indicating the
approximate position of the error.
Added negative *limit* support.
-.. function:: extract_tb(traceback, limit=None)
+.. function:: extract_tb(tb, limit=None)
Return a list of "pre-processed" stack trace entries extracted from the
- traceback object *traceback*. It is useful for alternate formatting of
+ traceback object *tb*. It is useful for alternate formatting of
stack traces. The optional *limit* argument has the same meaning as for
:func:`print_tb`. A "pre-processed" stack trace entry is a 4-tuple
(*filename*, *line number*, *function name*, *text*) representing the
arguments have the same meaning as for :func:`print_stack`.
-.. function:: format_list(list)
+.. function:: format_list(extracted_list)
Given a list of tuples as returned by :func:`extract_tb` or
- :func:`extract_stack`, return a list of strings ready for printing. Each string
- in the resulting list corresponds to the item with the same index in the
- argument list. Each string ends in a newline; the strings may contain internal
- newlines as well, for those items whose source text line is not ``None``.
+ :func:`extract_stack`, return a list of strings ready for printing. Each
+ string in the resulting list corresponds to the item with the same index in
+ the argument list. Each string ends in a newline; the strings may contain
+ internal newlines as well, for those items whose source text line is not
+ ``None``.
-.. function:: format_exception_only(type, value)
+.. function:: format_exception_only(etype, value)
- Format the exception part of a traceback. The arguments are the exception type
- and value such as given by ``sys.last_type`` and ``sys.last_value``. The return
- value is a list of strings, each ending in a newline. Normally, the list
- contains a single string; however, for :exc:`SyntaxError` exceptions, it
- contains several lines that (when printed) display detailed information about
- where the syntax error occurred. The message indicating which exception
- occurred is the always last string in the list.
+ Format the exception part of a traceback. The arguments are the exception
+ type and value such as given by ``sys.last_type`` and ``sys.last_value``.
+ The return value is a list of strings, each ending in a newline. Normally,
+ the list contains a single string; however, for :exc:`SyntaxError`
+ exceptions, it contains several lines that (when printed) display detailed
+ information about where the syntax error occurred. The message indicating
+ which exception occurred is the always last string in the list.
-.. function:: format_exception(type, value, tb, limit=None, chain=True)
+.. function:: format_exception(etype, value, tb, limit=None, chain=True)
Format a stack trace and the exception information. The arguments have the
same meaning as the corresponding arguments to :func:`print_exception`. The
- return value is a list of strings, each ending in a newline and some containing
- internal newlines. When these lines are concatenated and printed, exactly the
- same text is printed as does :func:`print_exception`.
+ return value is a list of strings, each ending in a newline and some
+ containing internal newlines. When these lines are concatenated and printed,
+ exactly the same text is printed as does :func:`print_exception`.
.. function:: format_exc(limit=None, chain=True)
- This is like ``print_exc(limit)`` but returns a string instead of printing to a
- file.
+ This is like ``print_exc(limit)`` but returns a string instead of printing to
+ a file.
.. function:: format_tb(tb, limit=None)
.. versionadded:: 3.4
+**Source code:** :source:`Lib/tracemalloc.py`
+
+--------------
+
The tracemalloc module is a debug tool to trace memory blocks allocated by
Python. It provides the following information:
*limit* is set, only format the *limit* most recent frames.
Similar to the :func:`traceback.format_tb` function, except that
- :meth:`format` does not include newlines.
+ :meth:`.format` does not include newlines.
Example::
.. module:: tty
:platform: Unix
:synopsis: Utility functions that perform common terminal control operations.
+
.. moduleauthor:: Steen Lumholt
.. sectionauthor:: Moshe Zadka <moshez@zadka.site.co.il>
+**Source code:** :source:`Lib/tty.py`
+
+--------------
The :mod:`tty` module defines functions for putting the tty into cbreak and raw
modes.
.. module:: turtle
:synopsis: An educational framework for simple graphics applications
+
.. sectionauthor:: Gregor Lingl <gregor.lingl@aon.at>
+**Source code:** :source:`Lib/turtle.py`
+
.. testsetup:: default
from turtle import *
turtle = Turtle()
+--------------
+
Introduction
============
class SimpleNamespace:
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
+
def __repr__(self):
keys = sorted(self.__dict__)
items = ("{}={!r}".format(k, self.__dict__[k]) for k in keys)
return "{}({})".format(type(self).__name__, ", ".join(items))
+
def __eq__(self, other):
return self.__dict__ == other.__dict__
.. module:: typing
:synopsis: Support for type hints (see PEP 484).
+.. versionadded:: 3.5
+
**Source code:** :source:`Lib/typing.py`
--------------
def greeting(name: str) -> str:
return 'Hello ' + name
-In the function ``greeting``, the argument ``name`` is expected to by of type
+In the function ``greeting``, the argument ``name`` is expected to be of type
:class:`str` and the return type :class:`str`. Subtypes are accepted as
arguments.
class LinkedList(Sized, Generic[T]):
...
-When inheriting from generic classes, some type variables could fixed::
+When inheriting from generic classes, some type variables could be fixed::
from typing import TypeVar, Mapping
``Optional[X]`` is equivalent to ``Union[X, type(None)]``.
+ Note that this is not the same concept as an optional argument,
+ which is one that has a default. An optional argument with a
+ default needn't use the ``Optional`` qualifier on its type
+ annotation (although it is inferred if the default is ``None``).
+ A mandatory argument may still have an ``Optional`` type if an
+ explicit value of ``None`` is allowed.
+
.. class:: Tuple
- Tuple type; ``Tuple[X, Y]`` is the is the type of a tuple of two items
+ Tuple type; ``Tuple[X, Y]`` is the type of a tuple of two items
with the first item of type X and the second of type Y.
Example: ``Tuple[T1, T2]`` is a tuple of two elements corresponding
def slice__to_4(vector: Sequence[T]) -> List[T]:
return vector[0:4]
-.. class:: AbstractSet(set, MutableSet[T])
+.. class:: Set(set, MutableSet[T])
- A generic version of :class:`collections.abc.Set`.
+ A generic version of :class:`builtins.set <set>`.
.. class:: MappingView(Sized, Iterable[T_co])
.. module:: unicodedata
:synopsis: Access the Unicode Database.
+
.. moduleauthor:: Marc-André Lemburg <mal@lemburg.com>
.. sectionauthor:: Marc-André Lemburg <mal@lemburg.com>
.. sectionauthor:: Martin v. Löwis <martin@v.loewis.de>
-
.. index::
single: Unicode
single: character
pair: Unicode; database
+--------------
+
This module provides access to the Unicode Character Database (UCD) which
defines character properties for all Unicode characters. The data contained in
this database is compiled from the `UCD version 8.0.0
A nice pattern is to actually decorate test methods themselves:
- >>> class MyTest(unittest2.TestCase):
+ >>> class MyTest(unittest.TestCase):
... @patch.object(SomeClass, 'attribute', sentinel.attribute)
... def test_something(self):
... self.assertEqual(SomeClass.attribute, sentinel.attribute)
(or :func:`patch.object` with two arguments). The mock will be created for you and
passed into the test function / method:
- >>> class MyTest(unittest2.TestCase):
+ >>> class MyTest(unittest.TestCase):
... @patch.object(SomeClass, 'static_method')
... def test_something(self, mock_method):
... SomeClass.static_method()
You can stack up multiple patch decorators using this pattern:
- >>> class MyTest(unittest2.TestCase):
+ >>> class MyTest(unittest.TestCase):
... @patch('package.module.ClassName1')
... @patch('package.module.ClassName2')
... def test_something(self, MockClass2, MockClass1):
An alternative way of dealing with mocking dates, or other builtin classes,
is discussed in `this blog entry
-<http://www.williamjohnbert.com/2011/07/how-to-unit-testing-in-django-with-mocking-and-patching/>`_.
+<https://williambert.online/2011/07/how-to-unit-testing-in-django-with-mocking-and-patching/>`_.
Mocking a Generator Method
Sometimes this is inconvenient. For example, `one user
<https://code.google.com/p/mock/issues/detail?id=105>`_ is subclassing mock to
created a `Twisted adaptor
-<http://twistedmatrix.com/documents/11.0.0/api/twisted.python.components.html>`_.
+<https://twistedmatrix.com/documents/11.0.0/api/twisted.python.components.html>`_.
Having this applied to attributes too actually causes errors.
``Mock`` (in all its flavours) uses a method called ``_get_child_mock`` to create
:exc:`AssertionError` directly and provide a more useful failure message.
As of version 1.5, the Python testing library `PyHamcrest
-<https://pypi.python.org/pypi/PyHamcrest>`_ provides similar functionality,
+<https://pyhamcrest.readthedocs.org/>`_ provides similar functionality,
that may be useful here, in the form of its equality matcher
(`hamcrest.library.integration.match_equality
-<http://pythonhosted.org/PyHamcrest/integration.html#hamcrest.library.integration.match_equality.match_equality>`_).
+<https://pyhamcrest.readthedocs.org/en/release-1.8/integration/#module-hamcrest.library.integration.match_equality>`_).
.. module:: unittest.mock
:synopsis: Mock object library.
+
.. moduleauthor:: Michael Foord <michael@python.org>
.. currentmodule:: unittest.mock
.. versionadded:: 3.3
+**Source code:** :source:`Lib/unittest/mock.py`
+
+--------------
+
:mod:`unittest.mock` is a library for testing in Python. It allows you to
replace parts of your system under test with mock objects and make assertions
about how they have been used.
There is a backport of :mod:`unittest.mock` for earlier versions of Python,
available as `mock on PyPI <https://pypi.python.org/pypi/mock>`_.
-**Source code:** :source:`Lib/unittest/mock.py`
-
Quick Guide
-----------
* ``__ge__``: NotImplemented
* ``__int__``: 1
* ``__contains__``: False
-* ``__len__``: 1
+* ``__len__``: 0
* ``__iter__``: iter([])
* ``__exit__``: False
* ``__complex__``: 1j
.. module:: unittest
:synopsis: Unit testing framework for Python.
+
.. moduleauthor:: Steve Purcell <stephen_purcell@yahoo.com>
.. sectionauthor:: Steve Purcell <stephen_purcell@yahoo.com>
.. sectionauthor:: Fred L. Drake, Jr. <fdrake@acm.org>
.. sectionauthor:: Raymond Hettinger <python@rcn.com>
+**Source code:** :source:`Lib/unittest/__init__.py`
+
+--------------
+
(If you are already familiar with the basic concepts of testing, you might want
to skip to :ref:`the list of assert methods <assert-methods>`.)
a GUI tool for test discovery and execution. This is intended largely for ease of use
for those new to unit testing. For production environments it is
recommended that tests be driven by a continuous integration system such as
- `Buildbot <http://buildbot.net/>`_, `Jenkins <http://jenkins-ci.org/>`_
+ `Buildbot <https://buildbot.net/>`_, `Jenkins <https://jenkins.io/>`_
or `Hudson <http://hudson-ci.org/>`_.
class TestStringMethods(unittest.TestCase):
- def test_upper(self):
- self.assertEqual('foo'.upper(), 'FOO')
+ def test_upper(self):
+ self.assertEqual('foo'.upper(), 'FOO')
- def test_isupper(self):
- self.assertTrue('FOO'.isupper())
- self.assertFalse('Foo'.isupper())
+ def test_isupper(self):
+ self.assertTrue('FOO'.isupper())
+ self.assertFalse('Foo'.isupper())
- def test_split(self):
- s = 'hello world'
- self.assertEqual(s.split(), ['hello', 'world'])
- # check that s.split fails when the separator is not a string
- with self.assertRaises(TypeError):
- s.split(2)
+ def test_split(self):
+ s = 'hello world'
+ self.assertEqual(s.split(), ['hello', 'world'])
+ # check that s.split fails when the separator is not a string
+ with self.assertRaises(TypeError):
+ s.split(2)
if __name__ == '__main__':
unittest.main()
The :meth:`~TestCase.setUp` and :meth:`~TestCase.tearDown` methods allow you
to define instructions that will be executed before and after each test method.
-They are covered in more details in the section :ref:`organizing-tests`.
+They are covered in more detail in the section :ref:`organizing-tests`.
The final block shows a simple way to run the tests. :func:`unittest.main`
provides a command-line interface to the test script. When run from the command
Method called immediately after the test method has been called and the
result recorded. This is called even if the test method raised an
exception, so the implementation in subclasses may need to be particularly
- careful about checking internal state. Any exception, other than :exc:`AssertionError`
- or :exc:`SkipTest`, raised by this method will be considered an error rather than a
- test failure. This method will only be called if the :meth:`setUp` succeeds,
- regardless of the outcome of the test method. The default implementation does nothing.
+ careful about checking internal state. Any exception, other than
+ :exc:`AssertionError` or :exc:`SkipTest`, raised by this method will be
+ considered an additional error rather than a test failure (thus increasing
+ the total number of reported errors). This method will only be called if
+ the :meth:`setUp` succeeds, regardless of the outcome of the test method.
+ The default implementation does nothing.
.. method:: setUpClass()
.. _assert-methods:
- The :class:`TestCase` class provides a number of methods to check for and
- report failures, such as:
+ The :class:`TestCase` class provides several assert methods to check for and
+ report failures. The following table lists the most commonly used methods
+ (see the tables below for more assert methods):
+-----------------------------------------+-----------------------------+---------------+
| Method | Checks that | New in |
- It is also possible to check the production of exceptions, warnings and
+ It is also possible to check the production of exceptions, warnings, and
log messages using the following methods:
+---------------------------------------------------------+--------------------------------------+------------+
.. module:: urllib.error
:synopsis: Exception classes raised by urllib.request.
+
.. moduleauthor:: Jeremy Hylton <jeremy@alum.mit.edu>
.. sectionauthor:: Senthil Kumaran <orsenthil@gmail.com>
+**Source code:** :source:`Lib/urllib/error.py`
+
+--------------
The :mod:`urllib.error` module defines the exception classes for exceptions
raised by :mod:`urllib.request`. The base exception class is :exc:`URLError`.
.. module:: urllib.parse
:synopsis: Parse URLs into or assemble them from components.
+**Source code:** :source:`Lib/urllib/parse.py`
.. index::
single: WWW
pair: URL; parsing
pair: relative; URL
-**Source code:** :source:`Lib/urllib/parse.py`
-
--------------
This module defines a standard interface to break Uniform Resource Locator (URL)
errors=None, quote_via=quote_plus)
Convert a mapping object or a sequence of two-element tuples, which may
- contain :class:`str` or :class:`bytes` objects, to a "percent-encoded"
- string. If the resultant string is to be used as a *data* for POST
- operation with :func:`~urllib.request.urlopen` function, then it should be
- properly encoded to bytes, otherwise it would result in a :exc:`TypeError`.
+ contain :class:`str` or :class:`bytes` objects, to a percent-encoded ASCII
+ text string. If the resultant string is to be used as a *data* for POST
+ operation with the :func:`~urllib.request.urlopen` function, then
+ it should be encoded to bytes, otherwise it would result in a
+ :exc:`TypeError`.
The resulting string is a series of ``key=value`` pairs separated by ``'&'``
characters, where both *key* and *value* are quoted using the *quote_via*
Names (URNs) and Uniform Resource Locators (URLs).
:rfc:`2368` - The mailto URL scheme.
- Parsing requirements for mailto url schemes.
+ Parsing requirements for mailto URL schemes.
:rfc:`1808` - Relative Uniform Resource Locators
This Request For Comments includes the rules for joining an absolute and a
.. module:: urllib.request
:synopsis: Extensible library for opening URLs.
+
.. moduleauthor:: Jeremy Hylton <jeremy@alum.mit.edu>
.. sectionauthor:: Moshe Zadka <moshez@users.sourceforge.net>
.. sectionauthor:: Senthil Kumaran <senthil@uthcode.com>
+**Source code:** :source:`Lib/urllib/request.py`
+
+--------------
The :mod:`urllib.request` module defines functions and classes which help in
opening URLs (mostly HTTP) in a complex world --- basic and digest
.. seealso::
- The `Requests package <http://requests.readthedocs.org/>`_
- is recommended for a higher-level http client interface.
+ The `Requests package <https://requests.readthedocs.org/>`_
+ is recommended for a higher-level HTTP client interface.
The :mod:`urllib.request` module defines the following functions:
*data* should be a buffer in the standard
:mimetype:`application/x-www-form-urlencoded` format. The
:func:`urllib.parse.urlencode` function takes a mapping or sequence of
- 2-tuples and returns a string in this format. It should be encoded to bytes
- before being used as the *data* parameter. The charset parameter in
- ``Content-Type`` header may be used to specify the encoding. If charset
- parameter is not sent with the Content-Type header, the server following the
- HTTP 1.1 recommendation may assume that the data is encoded in ISO-8859-1
- encoding. It is advisable to use charset parameter with encoding used in
- ``Content-Type`` header with the :class:`Request`.
+ 2-tuples and returns an ASCII text string in this format. It should
+ be encoded to bytes before being used as the *data* parameter.
urllib.request module uses HTTP/1.1 and includes ``Connection:close`` header
in its HTTP requests.
The *cadefault* parameter is ignored.
- For http and https urls, this function returns a
- :class:`http.client.HTTPResponse` object which has the following
- :ref:`httpresponse-objects` methods.
-
- For ftp, file, and data urls and requests explicitly handled by legacy
- :class:`URLopener` and :class:`FancyURLopener` classes, this function
- returns a :class:`urllib.response.addinfourl` object which can work as
+ This function always returns an object which can work as a
:term:`context manager` and has methods such as
* :meth:`~urllib.response.addinfourl.geturl` --- return the URL of the resource retrieved,
* :meth:`~urllib.response.addinfourl.info` --- return the meta-information of the page, such as headers,
in the form of an :func:`email.message_from_string` instance (see
- `Quick Reference to HTTP Headers <http://www.cs.tut.fi/~jkorpela/http.html>`_)
+ `Quick Reference to HTTP Headers <https://www.cs.tut.fi/~jkorpela/http.html>`_)
* :meth:`~urllib.response.addinfourl.getcode` -- return the HTTP status code of the response.
- Raises :exc:`~urllib.error.URLError` on errors.
+ For HTTP and HTTPS URLs, this function returns a
+ :class:`http.client.HTTPResponse` object slightly modified. In addition
+ to the three new methods above, the msg attribute contains the
+ same information as the :attr:`~http.client.HTTPResponse.reason`
+ attribute --- the reason phrase returned by server --- instead of
+ the response headers as it is specified in the documentation for
+ :class:`~http.client.HTTPResponse`.
+
+ For FTP, file, and data URLs and requests explicitly handled by legacy
+ :class:`URLopener` and :class:`FancyURLopener` classes, this function
+ returns a :class:`urllib.response.addinfourl` object.
+
+ Raises :exc:`~urllib.error.URLError` on protocol errors.
Note that ``None`` may be returned if no handler handles the request (though
the default installed global :class:`OpenerDirector` uses
in a case insensitive approach, for all operating systems first, and when it
cannot find it, looks for proxy information from Mac OSX System
Configuration for Mac OS X and Windows Systems Registry for Windows.
+ If both lowercase and uppercase environment variables exist (and disagree),
+ lowercase is preferred.
The following classes are provided:
the only ones that use *data*; the HTTP request will be a POST instead of a
GET when the *data* parameter is provided. *data* should be a buffer in the
standard :mimetype:`application/x-www-form-urlencoded` format.
-
The :func:`urllib.parse.urlencode` function takes a mapping or sequence of
- 2-tuples and returns a string in this format. It should be encoded to bytes
- before being used as the *data* parameter. The charset parameter in
- ``Content-Type`` header may be used to specify the encoding. If charset
- parameter is not sent with the Content-Type header, the server following the
- HTTP 1.1 recommendation may assume that the data is encoded in ISO-8859-1
- encoding. It is advisable to use charset parameter with encoding used in
- ``Content-Type`` header with the :class:`Request`.
-
+ 2-tuples and returns an ASCII string in this format. It should be
+ encoded to bytes before being used as the *data* parameter.
*headers* should be a dictionary, and will be treated as if
:meth:`add_header` was called with each key and value as arguments.
- This is often used to "spoof" the ``User-Agent`` header, which is
+ This is often used to "spoof" the ``User-Agent`` header value, which is
used by a browser to identify itself -- some HTTP servers only
allow requests coming from common browsers as opposed to scripts.
For example, Mozilla Firefox may identify itself as ``"Mozilla/5.0
``"Python-urllib/2.6"`` (on Python 2.6).
An example of using ``Content-Type`` header with *data* argument would be
- sending a dictionary like ``{"Content-Type":" application/x-www-form-urlencoded;charset=utf-8"}``.
+ sending a dictionary like ``{"Content-Type": "application/x-www-form-urlencoded"}``.
The final two arguments are only of interest for correct handling
of third-party HTTP cookies:
To disable autodetected proxy pass an empty dictionary.
+ The :envvar:`no_proxy` environment variable can be used to specify hosts
+ which shouldn't be reached via proxy; if set, it should be a comma-separated
+ list of hostname suffixes, optionally with ``:port`` appended, for example
+ ``cern.ch,ncsa.uiuc.edu,some.host:8080``.
+
.. class:: HTTPPasswordMgr()
.. attribute:: Request.selector
The URI path. If the :class:`Request` uses a proxy, then selector
- will be the full url that is passed to the proxy.
+ will be the full URL that is passed to the proxy.
.. attribute:: Request.data
details of the precise meanings of the various redirection codes.
An :class:`HTTPError` exception raised as a security consideration if the
- HTTPRedirectHandler is presented with a redirected url which is not an HTTP,
- HTTPS or FTP url.
+ HTTPRedirectHandler is presented with a redirected URL which is not an HTTP,
+ HTTPS or FTP URL.
.. method:: HTTPRedirectHandler.redirect_request(req, fp, code, msg, hdrs, newurl)
Examples
--------
+In addition to the examples below, more examples are given in
+:ref:`urllib-howto`.
+
This example gets the python.org main page and displays the first 300 bytes of
it. ::
Note that urlopen returns a bytes object. This is because there is no way
for urlopen to automatically determine the encoding of the byte stream
-it receives from the http server. In general, a program will decode
+it receives from the HTTP server. In general, a program will decode
the returned bytes object to string once it determines or guesses
the appropriate encoding.
-The following W3C document, http://www.w3.org/International/O-charset\ , lists
+The following W3C document, https://www.w3.org/International/O-charset\ , lists
the various ways in which a (X)HTML or a XML document could have specified its
encoding information.
Here is an example of doing a ``PUT`` request using :class:`Request`::
import urllib.request
- DATA=b'some data'
+ DATA = b'some data'
req = urllib.request.Request(url='http://localhost:8080', data=DATA,method='PUT')
with urllib.request.urlopen(req) as f:
pass
import urllib.request
req = urllib.request.Request('http://www.example.com/')
req.add_header('Referer', 'http://www.python.org/')
+ # Customize the default User-Agent header value:
+ req.add_header('User-Agent', 'urllib-example/0.1 (Contact: . . .)')
r = urllib.request.urlopen(req)
:class:`OpenerDirector` automatically adds a :mailheader:`User-Agent` header to
opener.open('http://www.example.com/')
Also, remember that a few standard headers (:mailheader:`Content-Length`,
-:mailheader:`Content-Type` without charset parameter and :mailheader:`Host`)
+:mailheader:`Content-Type` and :mailheader:`Host`)
are added when the :class:`Request` is passed to :func:`urlopen` (or
:meth:`OpenerDirector.open`).
>>> import urllib.request
>>> import urllib.parse
>>> data = urllib.parse.urlencode({'spam': 1, 'eggs': 2, 'bacon': 0})
- >>> data = data.encode('utf-8')
- >>> request = urllib.request.Request("http://requestb.in/xrbl82xr")
- >>> # adding charset parameter to the Content-Type header.
- >>> request.add_header("Content-Type","application/x-www-form-urlencoded;charset=utf-8")
- >>> with urllib.request.urlopen(request, data) as f:
+ >>> data = data.encode('ascii')
+ >>> with urllib.request.urlopen("http://requestb.in/xrbl82xr", data) as f:
... print(f.read().decode('utf-8'))
...
.. module:: urllib.robotparser
:synopsis: Load a robots.txt file and answer questions about
fetchability of other URLs.
+
.. sectionauthor:: Skip Montanaro <skip@pobox.com>
+**Source code:** :source:`Lib/urllib/robotparser.py`
.. index::
single: WWW
single: URL
single: robots.txt
+--------------
+
This module provides a single class, :class:`RobotFileParser`, which answers
questions about whether or not a particular user agent can fetch a URL on the
Web site that published the :file:`robots.txt` file. For more details on the
.. module:: urllib
+**Source code:** :source:`Lib/urllib/`
+
+--------------
+
``urllib`` is a package that collects several modules for working with URLs:
* :mod:`urllib.request` for opening and reading URLs
.. module:: uu
:synopsis: Encode and decode files in uuencode format.
+
.. moduleauthor:: Lance Ellinghouse
**Source code:** :source:`Lib/uu.py`
.. moduleauthor:: Ka-Ping Yee <ping@zesty.ca>
.. sectionauthor:: George Yoshida <quiver@users.sourceforge.net>
+**Source code:** :source:`Lib/uuid.py`
+
+--------------
This module provides immutable :class:`UUID` objects (the :class:`UUID` class)
and the functions :func:`uuid1`, :func:`uuid3`, :func:`uuid4`, :func:`uuid5` for
.. module:: venv
:synopsis: Creation of virtual environments.
+
.. moduleauthor:: Vinay Sajip <vinay_sajip@yahoo.co.uk>
.. sectionauthor:: Vinay Sajip <vinay_sajip@yahoo.co.uk>
-
-.. index:: pair: Environments; virtual
-
.. versionadded:: 3.3
-**Source code:** :source:`Lib/venv`
+**Source code:** :source:`Lib/venv/`
+
+.. index:: pair: Environments; virtual
--------------
Common installation tools such as ``Setuptools`` and ``pip`` work as
expected with venvs - i.e. when a venv is active, they install Python
packages into the venv without needing to be told to do so explicitly.
- Of course, you need to install them into the venv first: this could be
- done by running ``ez_setup.py`` with the venv activated,
- followed by running ``easy_install pip``. Alternatively, you could download
- the source tarballs and run ``python setup.py install`` after unpacking,
- with the venv activated.
When a venv is active (i.e. the venv's Python interpreter is running), the
attributes :attr:`sys.prefix` and :attr:`sys.exec_prefix` point to the base
:mod:`warnings` --- Warning control
===================================
-.. index:: single: warnings
-
.. module:: warnings
:synopsis: Issue warning messages and control their disposition.
**Source code:** :source:`Lib/warnings.py`
+.. index:: single: warnings
+
--------------
Warning messages are typically issued in situations where it is useful to alert
Warnings that are only of interest to the developer are ignored by default. As
such you should make sure to test your code with typically ignored warnings
-made visible. You can do this from the command-line by passing :option:`-Wd`
+made visible. You can do this from the command-line by passing :option:`-Wd <-W>`
to the interpreter (this is shorthand for :option:`-W default`). This enables
default handling for all warnings, including those that are ignored by default.
To change what action is taken for encountered warnings you simply change what
.. module:: wave
:synopsis: Provide an interface to the WAV sound format.
+
.. sectionauthor:: Moshe Zadka <moshez@zadka.site.co.il>
.. Documentations stolen from comments in file.
.. module:: weakref
:synopsis: Support for weak references and weak dictionaries.
+
.. moduleauthor:: Fred L. Drake, Jr. <fdrake@acm.org>
.. moduleauthor:: Neil Schemenauer <nas@arctrix.com>
.. moduleauthor:: Martin von Löwis <martin@loewis.home.cs.tu-berlin.de>
.. seealso::
- :pep:`0205` - Weak References
+ :pep:`205` - Weak References
The proposal and rationale for this feature, including links to earlier
implementations and information about similar features in other languages.
.. module:: webbrowser
:synopsis: Easy-to-use controller for Web browsers.
+
.. moduleauthor:: Fred L. Drake, Jr. <fdrake@acm.org>
.. sectionauthor:: Fred L. Drake, Jr. <fdrake@acm.org>
browser and wait.
The script :program:`webbrowser` can be used as a command-line interface for the
-module. It accepts an URL as the argument. It accepts the following optional
+module. It accepts a URL as the argument. It accepts the following optional
parameters: ``-n`` opens the URL in a new browser window, if possible;
``-t`` opens the URL in a new browser page ("tab"). The options are,
naturally, mutually exclusive. Usage example::
.. module:: winreg
:platform: Windows
:synopsis: Routines and objects for manipulating the Windows registry.
+
.. sectionauthor:: Mark Hammond <MarkH@ActiveState.com>
+--------------
These functions expose the Windows registry API to Python. Instead of using an
integer as the registry handle, a :ref:`handle object <handle-object>` is used
The :func:`DeleteKeyEx` function is implemented with the RegDeleteKeyEx
Windows API function, which is specific to 64-bit versions of Windows.
See the `RegDeleteKeyEx documentation
- <http://msdn.microsoft.com/en-us/library/ms724847%28VS.85%29.aspx>`__.
+ <https://msdn.microsoft.com/en-us/library/ms724847%28VS.85%29.aspx>`__.
*key* is an already open key, or one of the predefined
:ref:`HKEY_* constants <hkey-constants>`.
A call to :func:`LoadKey` fails if the calling process does not have the
:const:`SE_RESTORE_PRIVILEGE` privilege. Note that privileges are different
from permissions -- see the `RegLoadKey documentation
- <http://msdn.microsoft.com/en-us/library/ms724889%28v=VS.85%29.aspx>`__ for
+ <https://msdn.microsoft.com/en-us/library/ms724889%28v=VS.85%29.aspx>`__ for
more details.
If *key* is a handle returned by :func:`ConnectRegistry`, then the path
possess the :const:`SeBackupPrivilege` security privilege. Note that
privileges are different than permissions -- see the
`Conflicts Between User Rights and Permissions documentation
- <http://msdn.microsoft.com/en-us/library/ms724878%28v=VS.85%29.aspx>`__
+ <https://msdn.microsoft.com/en-us/library/ms724878%28v=VS.85%29.aspx>`__
for more details.
This function passes NULL for *security_attributes* to the API.
+++++++++++++
For more information, see `Registry Key Security and Access
-<http://msdn.microsoft.com/en-us/library/ms724878%28v=VS.85%29.aspx>`__.
+<https://msdn.microsoft.com/en-us/library/ms724878%28v=VS.85%29.aspx>`__.
.. data:: KEY_ALL_ACCESS
***************
For more information, see `Accessing an Alternate Registry View
-<http://msdn.microsoft.com/en-us/library/aa384129(v=VS.85).aspx>`__.
+<https://msdn.microsoft.com/en-us/library/aa384129(v=VS.85).aspx>`__.
.. data:: KEY_WOW64_64KEY
+++++++++++
For more information, see `Registry Value Types
-<http://msdn.microsoft.com/en-us/library/ms724884%28v=VS.85%29.aspx>`__.
+<https://msdn.microsoft.com/en-us/library/ms724884%28v=VS.85%29.aspx>`__.
.. data:: REG_BINARY
.. module:: winsound
:platform: Windows
:synopsis: Access to the sound-playing machinery for Windows.
+
.. moduleauthor:: Toby Dickenson <htrd90@zepler.org>
.. sectionauthor:: Fred L. Drake, Jr. <fdrake@acm.org>
+--------------
The :mod:`winsound` module provides access to the basic sound-playing machinery
provided by Windows platforms. It includes functions and several constants.
.. module:: wsgiref
:synopsis: WSGI Utilities and Reference Implementation.
+
.. moduleauthor:: Phillip J. Eby <pje@telecommunity.com>
.. sectionauthor:: Phillip J. Eby <pje@telecommunity.com>
+--------------
The Web Server Gateway Interface (WSGI) is a standard interface between web
server software and web applications written in Python. Having a standard
and a validation tool that checks WSGI servers and applications for conformance
to the WSGI specification (:pep:`3333`).
-See http://www.wsgi.org for more information about WSGI, and links to tutorials
-and other resources.
+See https://wsgi.readthedocs.org/ for more information about WSGI, and links to
+tutorials and other resources.
.. XXX If you're just trying to write a web application...
# Our callable object which is intentionally not compliant to the
# standard, so the validator is going to break
def simple_app(environ, start_response):
- status = '200 OK' # HTTP Status
- headers = [('Content-type', 'text/plain')] # HTTP Headers
+ status = '200 OK' # HTTP Status
+ headers = [('Content-type', 'text/plain')] # HTTP Headers
start_response(status, headers)
# This is going to break because we need to return a list, and
streams are stored in the :attr:`stdin`, :attr:`stdout`, :attr:`stderr`, and
:attr:`environ` attributes.
+ The :meth:`~io.BufferedIOBase.write` method of *stdout* should write
+ each chunk in full, like :class:`io.BufferedIOBase`.
+
.. class:: BaseHandler()
# is a dictionary containing CGI-style environment variables and the
# second variable is the callable object (see PEP 333).
def hello_world_app(environ, start_response):
- status = '200 OK' # HTTP Status
- headers = [('Content-type', 'text/plain; charset=utf-8')] # HTTP Headers
+ status = '200 OK' # HTTP Status
+ headers = [('Content-type', 'text/plain; charset=utf-8')] # HTTP Headers
start_response(status, headers)
# The returned object is going to be printed
.. module:: xdrlib
:synopsis: Encoders and decoders for the External Data Representation (XDR).
+**Source code:** :source:`Lib/xdrlib.py`
.. index::
single: XDR
single: External Data Representation
-**Source code:** :source:`Lib/xdrlib.py`
-
--------------
The :mod:`xdrlib` module supports the External Data Representation Standard as
.. module:: xml.dom.minidom
:synopsis: Minimal Document Object Model (DOM) implementation.
+
.. moduleauthor:: Paul Prescod <paul@prescod.net>
.. sectionauthor:: Paul Prescod <paul@prescod.net>
.. sectionauthor:: Martin v. Löwis <martin@v.loewis.de>
from xml.dom.minidom import parse, parseString
- dom1 = parse('c:\\temp\\mydata.xml') # parse an XML file by name
+ dom1 = parse('c:\\temp\\mydata.xml') # parse an XML file by name
datasource = open('c:\\temp\\mydata.xml')
- dom2 = parse(datasource) # parse an open file
+ dom2 = parse(datasource) # parse an open file
dom3 = parseString('<myxml>Some data<empty/> some more data</myxml>')
.. seealso::
- `Document Object Model (DOM) Level 1 Specification <http://www.w3.org/TR/REC-DOM-Level-1/>`_
+ `Document Object Model (DOM) Level 1 Specification <https://www.w3.org/TR/REC-DOM-Level-1/>`_
The W3C recommendation for the DOM supported by :mod:`xml.dom.minidom`.
the appropriate standards. For example, "UTF-8" is valid, but
"UTF8" is not valid in an XML document's declaration, even though
Python accepts it as an encoding name.
- See http://www.w3.org/TR/2006/REC-xml11-20060816/#NT-EncodingDecl
- and http://www.iana.org/assignments/character-sets/character-sets.xhtml.
+ See https://www.w3.org/TR/2006/REC-xml11-20060816/#NT-EncodingDecl
+ and https://www.iana.org/assignments/character-sets/character-sets.xhtml.
.. module:: xml.dom.pulldom
:synopsis: Support for building partial DOM trees from SAX events.
+
.. moduleauthor:: Paul Prescod <paul@prescod.net>
**Source code:** :source:`Lib/xml/dom/pulldom.py`
Expands all children of *node* into *node*. Example::
+ from xml.dom import pulldom
+
xml = '<html><title>Foo</title> <p>Some text <div>and more</div></p> </html>'
doc = pulldom.parseString(xml)
for event, node in doc:
if event == pulldom.START_ELEMENT and node.tagName == 'p':
# Following statement only prints '<p/>'
print(node.toxml())
- doc.exandNode(node)
+ doc.expandNode(node)
# Following statement prints node with all its children '<p>Some text <div>and more</div></p>'
print(node.toxml())
.. module:: xml.dom
:synopsis: Document Object Model API for Python.
+
.. sectionauthor:: Paul Prescod <paul@prescod.net>
.. sectionauthor:: Martin v. Löwis <martin@v.loewis.de>
+**Source code:** :source:`Lib/xml/dom/__init__.py`
+
+--------------
The Document Object Model, or "DOM," is a cross-language API from the World Wide
Web Consortium (W3C) for accessing and modifying XML documents. A DOM
.. seealso::
- `Document Object Model (DOM) Level 2 Specification <http://www.w3.org/TR/DOM-Level-2-Core/>`_
+ `Document Object Model (DOM) Level 2 Specification <https://www.w3.org/TR/DOM-Level-2-Core/>`_
The W3C recommendation upon which the Python DOM API is based.
- `Document Object Model (DOM) Level 1 Specification <http://www.w3.org/TR/REC-DOM-Level-1/>`_
+ `Document Object Model (DOM) Level 1 Specification <https://www.w3.org/TR/REC-DOM-Level-1/>`_
The W3C recommendation for the DOM supported by :mod:`xml.dom.minidom`.
`Python Language Mapping Specification <http://www.omg.org/spec/PYTH/1.2/PDF>`_
.. data:: XML_NAMESPACE
The namespace URI associated with the reserved prefix ``xml``, as defined by
- `Namespaces in XML <http://www.w3.org/TR/REC-xml-names/>`_ (section 4).
+ `Namespaces in XML <https://www.w3.org/TR/REC-xml-names/>`_ (section 4).
.. data:: XMLNS_NAMESPACE
The namespace URI for namespace declarations, as defined by `Document Object
Model (DOM) Level 2 Core Specification
- <http://www.w3.org/TR/DOM-Level-2-Core/core.html>`_ (section 1.1.8).
+ <https://www.w3.org/TR/DOM-Level-2-Core/core.html>`_ (section 1.1.8).
.. data:: XHTML_NAMESPACE
The URI of the XHTML namespace as defined by `XHTML 1.0: The Extensible
- HyperText Markup Language <http://www.w3.org/TR/xhtml1/>`_ (section 3.1.1).
+ HyperText Markup Language <https://www.w3.org/TR/xhtml1/>`_ (section 3.1.1).
In addition, :mod:`xml.dom` contains a base :class:`Node` class and the DOM
.. exception:: NamespaceErr
If an attempt is made to change any object in a way that is not permitted with
- regard to the `Namespaces in XML <http://www.w3.org/TR/REC-xml-names/>`_
+ regard to the `Namespaces in XML <https://www.w3.org/TR/REC-xml-names/>`_
recommendation, this exception is raised.
.. module:: xml.etree.ElementTree
:synopsis: Implementation of the ElementTree API.
+
.. moduleauthor:: Fredrik Lundh <fredrik@pythonware.com>
+**Source code:** :source:`Lib/xml/etree/ElementTree.py`
+
+--------------
+
The :mod:`xml.etree.ElementTree` module implements a simple and efficient API
for parsing and creating XML data.
It also has children nodes over which we can iterate::
>>> for child in root:
- ... print(child.tag, child.attrib)
+ ... print(child.tag, child.attrib)
...
country {'name': 'Liechtenstein'}
country {'name': 'Singapore'}
[('start', <Element 'mytag' at 0x7fa66db2be58>)]
>>> parser.feed(' more text</mytag>')
>>> for event, elem in parser.read_events():
- ... print(event)
- ... print(elem.tag, 'text=', elem.text)
+ ... print(event)
+ ... print(elem.tag, 'text=', elem.text)
...
end
:meth:`Element.iter`::
>>> for neighbor in root.iter('neighbor'):
- ... print(neighbor.attrib)
+ ... print(neighbor.attrib)
...
{'name': 'Austria', 'direction': 'E'}
{'name': 'Switzerland', 'direction': 'W'}
content. :meth:`Element.get` accesses the element's attributes::
>>> for country in root.findall('country'):
- ... rank = country.find('rank').text
- ... name = country.get('name')
- ... print(name, rank)
+ ... rank = country.find('rank').text
+ ... name = country.get('name')
+ ... print(name, rank)
...
Liechtenstein 1
Singapore 4
attribute to the rank element::
>>> for rank in root.iter('rank'):
- ... new_rank = int(rank.text) + 1
- ... rank.text = str(new_rank)
- ... rank.set('updated', 'yes')
+ ... new_rank = int(rank.text) + 1
+ ... rank.text = str(new_rank)
+ ... rank.set('updated', 'yes')
...
>>> tree.write('output.xml')
remove all countries with a rank higher than 50::
>>> for country in root.findall('country'):
- ... rank = int(country.find('rank').text)
- ... if rank > 50:
- ... root.remove(country)
+ ... rank = int(country.find('rank').text)
+ ... if rank > 50:
+ ... root.remove(country)
...
>>> tree.write('output.xml')
with prefixes in the form ``prefix:sometag`` get expanded to
``{uri}sometag`` where the *prefix* is replaced by the full *URI*.
Also, if there is a `default namespace
-<http://www.w3.org/TR/2006/REC-xml-names-20060816/#defaulting>`__,
+<https://www.w3.org/TR/2006/REC-xml-names-20060816/#defaulting>`__,
that full URI gets prepended to all of the non-prefixed tags.
Here is an XML example that incorporates two namespaces, one with the
-------------
This module provides limited support for
-`XPath expressions <http://www.w3.org/TR/xpath>`_ for locating elements in a
+`XPath expressions <https://www.w3.org/TR/xpath>`_ for locating elements in a
tree. The goal is to support a small subset of the abbreviated syntax; a full
XPath engine is outside the scope of the module.
to get proper namespace handling on output. *text_or_uri* is a string
containing the QName value, in the form {uri}local, or, if the tag argument
is given, the URI part of a QName. If *tag* is given, the first argument is
- interpreted as an URI, and this argument is interpreted as a local name.
+ interpreted as a URI, and this argument is interpreted as a local name.
:class:`QName` instances are opaque.
This class is the low-level building block of the module. It uses
:mod:`xml.parsers.expat` for efficient, event-based parsing of XML. It can
- be fed XML data incrementall with the :meth:`feed` method, and parsing events
- are translated to a push API - by invoking callbacks on the *target* object.
- If *target* is omitted, the standard :class:`TreeBuilder` is used. The
- *html* argument was historically used for backwards compatibility and is now
- deprecated. If *encoding* [1]_ is given, the value overrides the encoding
- specified in the XML file.
+ be fed XML data incrementally with the :meth:`feed` method, and parsing
+ events are translated to a push API - by invoking callbacks on the *target*
+ object. If *target* is omitted, the standard :class:`TreeBuilder` is used.
+ The *html* argument was historically used for backwards compatibility and is
+ now deprecated. If *encoding* [1]_ is given, the value overrides the
+ encoding specified in the XML file.
.. deprecated:: 3.4
The *html* argument. The remaining arguments should be passed via
- keywword to prepare for the removal of the *html* argument.
+ keyword to prepare for the removal of the *html* argument.
.. method:: close()
.. [#] The encoding string included in XML output should conform to the
appropriate standards. For example, "UTF-8" is valid, but "UTF8" is
- not. See http://www.w3.org/TR/2006/REC-xml11-20060816/#NT-EncodingDecl
- and http://www.iana.org/assignments/character-sets/character-sets.xhtml.
+ not. See https://www.w3.org/TR/2006/REC-xml11-20060816/#NT-EncodingDecl
+ and https://www.iana.org/assignments/character-sets/character-sets.xhtml.
.. module:: xml
:synopsis: Package containing XML processing modules
+
.. sectionauthor:: Christian Heimes <christian@python.org>
.. sectionauthor:: Georg Brandl <georg@python.org>
+**Source code:** :source:`Lib/xml/`
+
+--------------
Python's interfaces for processing XML are grouped in the ``xml`` package.
billion laughs **Yes** **Yes** **Yes** **Yes** **Yes**
quadratic blowup **Yes** **Yes** **Yes** **Yes** **Yes**
external entity expansion **Yes** No (1) No (2) **Yes** No (3)
-DTD retrieval **Yes** No No **Yes** No
+`DTD`_ retrieval **Yes** No No **Yes** No
decompression bomb No No No No **Yes**
========================= ======== ========= ========= ======== =========
also point to external resources or local files. The XML
parser accesses the resource and embeds the content into the XML document.
-DTD retrieval
+`DTD`_ retrieval
Some XML libraries like Python's :mod:`xml.dom.pulldom` retrieve document type
definitions from remote or local locations. The feature has similar
implications as the external entity expansion issue.
.. _defusedxml: https://pypi.python.org/pypi/defusedxml/
.. _defusedexpat: https://pypi.python.org/pypi/defusedexpat/
-.. _Billion Laughs: http://en.wikipedia.org/wiki/Billion_laughs
-.. _ZIP bomb: http://en.wikipedia.org/wiki/Zip_bomb
-.. _DTD: http://en.wikipedia.org/wiki/Document_Type_Definition
+.. _Billion Laughs: https://en.wikipedia.org/wiki/Billion_laughs
+.. _ZIP bomb: https://en.wikipedia.org/wiki/Zip_bomb
+.. _DTD: https://en.wikipedia.org/wiki/Document_type_definition
.. module:: xml.sax.handler
:synopsis: Base classes for SAX event handlers.
+
.. moduleauthor:: Lars Marius Garshol <larsga@garshol.priv.no>
.. sectionauthor:: Martin v. Löwis <martin@v.loewis.de>
+**Source code:** :source:`Lib/xml/sax/handler.py`
+
+--------------
The SAX API defines four kinds of handlers: content handlers, DTD handlers,
error handlers, and entity resolvers. Applications normally only need to
.. module:: xml.sax.xmlreader
:synopsis: Interface which SAX-compliant XML parsers must implement.
+
.. moduleauthor:: Lars Marius Garshol <larsga@garshol.priv.no>
.. sectionauthor:: Martin v. Löwis <martin@v.loewis.de>
+**Source code:** :source:`Lib/xml/sax/xmlreader.py`
+
+--------------
SAX parsers implement the :class:`XMLReader` interface. They are implemented in
a Python module, which must provide a function :func:`create_parser`. This
Process an input source, producing SAX events. The *source* object can be a
system identifier (a string identifying the input source -- typically a file
- name or an URL), a file-like object, or an :class:`InputSource` object. When
+ name or a URL), a file-like object, or an :class:`InputSource` object. When
:meth:`parse` returns, the input is completely processed, and the parser object
can be discarded or reset.
.. method:: Locator.getColumnNumber()
- Return the column number where the current event ends.
+ Return the column number where the current event begins.
.. method:: Locator.getLineNumber()
- Return the line number where the current event ends.
+ Return the line number where the current event begins.
.. method:: Locator.getPublicId()
.. module:: xml.sax
:synopsis: Package containing SAX2 base classes and convenience functions.
+
.. moduleauthor:: Lars Marius Garshol <larsga@garshol.priv.no>
.. sectionauthor:: Fred L. Drake, Jr. <fdrake@acm.org>
.. sectionauthor:: Martin v. Löwis <martin@v.loewis.de>
+**Source code:** :source:`Lib/xml/sax/__init__.py`
+
+--------------
The :mod:`xml.sax` package provides a number of modules which implement the
Simple API for XML (SAX) interface for Python. The package itself provides the
.. module:: xml.sax.saxutils
:synopsis: Convenience functions and classes for use with SAX.
+
.. moduleauthor:: Lars Marius Garshol <larsga@garshol.priv.no>
.. sectionauthor:: Martin v. Löwis <martin@v.loewis.de>
+**Source code:** :source:`Lib/xml/sax/saxutils.py`
+
+--------------
The module :mod:`xml.sax.saxutils` contains a number of classes and functions
that are commonly useful when creating SAX applications, either in direct use,
.. module:: xmlrpc.client
:synopsis: XML-RPC client access.
+
.. moduleauthor:: Fredrik Lundh <fredrik@pythonware.com>
.. sectionauthor:: Eric S. Raymond <esr@snark.thyrsus.com>
+**Source code:** :source:`Lib/xmlrpc/client.py`
.. XXX Not everything is documented yet. It might be good to describe
Marshaller, Unmarshaller, getparser and Transport.
-**Source code:** :source:`Lib/xmlrpc/client.py`
-
--------------
-XML-RPC is a Remote Procedure Call method that uses XML passed via HTTP as a
+XML-RPC is a Remote Procedure Call method that uses XML passed via HTTP(S) as a
transport. With it, a client can call methods with parameters on a remote
server (the server is named by a URI) and get back structured data. This module
supports writing XML-RPC client code; it handles all the details of translating
.. versionchanged:: 3.5
- For https URIs, :mod:`xmlrpc.client` now performs all the necessary
- certificate and hostname checks by default
+ For HTTPS URIs, :mod:`xmlrpc.client` now performs all the necessary
+ certificate and hostname checks by default.
.. class:: ServerProxy(uri, transport=None, encoding=None, verbose=False, \
allow_none=False, use_datetime=False, \
:class:`SafeTransport` instance for https: URLs and an internal HTTP
:class:`Transport` instance otherwise. The optional third argument is an
encoding, by default UTF-8. The optional fourth argument is a debugging flag.
+
+ The following parameters govern the use of the returned proxy instance.
If *allow_none* is true, the Python constant ``None`` will be translated into
XML; the default behaviour is for ``None`` to raise a :exc:`TypeError`. This is
a commonly-used extension to the XML-RPC specification, but isn't supported by
- all clients and servers; see http://ontosys.com/xml-rpc/extensions.php for a
- description. The *use_builtin_types* flag can be used to cause date/time values
+ all clients and servers; see `http://ontosys.com/xml-rpc/extensions.php
+ <https://web.archive.org/web/20130120074804/http://ontosys.com/xml-rpc/extensions.php>`_
+ for a description.
+ The *use_builtin_types* flag can be used to cause date/time values
to be presented as :class:`datetime.datetime` objects and binary data to be
presented as :class:`bytes` objects; this flag is false by default.
- :class:`datetime.datetime` and :class:`bytes` objects may be passed to calls.
-
+ :class:`datetime.datetime`, :class:`bytes` and :class:`bytearray` objects
+ may be passed to calls.
The obsolete *use_datetime* flag is similar to *use_builtin_types* but it
applies only to date/time values.
portion will be base64-encoded as an HTTP 'Authorization' header, and sent to
the remote server as part of the connection process when invoking an XML-RPC
method. You only need to use this if the remote server requires a Basic
- Authentication user and password. If an HTTPS url is provided, *context* may
+ Authentication user and password. If an HTTPS URL is provided, *context* may
be :class:`ssl.SSLContext` and configures the SSL settings of the underlying
HTTPS connection.
methods it supports (service discovery) and fetch other server-associated
metadata.
- :class:`ServerProxy` instance methods take Python basic types and objects as
- arguments and return Python basic types and classes. Types that are conformable
- (e.g. that can be marshalled through XML), include the following (and except
- where noted, they are unmarshalled as the same Python type):
+ Types that are conformable (e.g. that can be marshalled through XML),
+ include the following (and except where noted, they are unmarshalled
+ as the same Python type):
.. tabularcolumns:: |l|L|
- +---------------------------------+---------------------------------------------+
- | Name | Meaning |
- +=================================+=============================================+
- | :const:`boolean` | The :const:`True` and :const:`False` |
- | | constants |
- +---------------------------------+---------------------------------------------+
- | :const:`integers` | Pass in directly |
- +---------------------------------+---------------------------------------------+
- | :const:`floating-point numbers` | Pass in directly |
- +---------------------------------+---------------------------------------------+
- | :const:`strings` | Pass in directly |
- +---------------------------------+---------------------------------------------+
- | :const:`arrays` | Any Python sequence type containing |
- | | conformable elements. Arrays are returned |
- | | as lists |
- +---------------------------------+---------------------------------------------+
- | :const:`structures` | A Python dictionary. Keys must be strings, |
- | | values may be any conformable type. Objects |
- | | of user-defined classes can be passed in; |
- | | only their *__dict__* attribute is |
- | | transmitted. |
- +---------------------------------+---------------------------------------------+
- | :const:`dates` | In seconds since the epoch. Pass in an |
- | | instance of the :class:`DateTime` class or |
- | | a :class:`datetime.datetime` instance. |
- +---------------------------------+---------------------------------------------+
- | :const:`binary data` | Pass in an instance of the :class:`Binary` |
- | | wrapper class or a :class:`bytes` instance. |
- +---------------------------------+---------------------------------------------+
+ +----------------------+-------------------------------------------------------+
+ | XML-RPC type | Python type |
+ +======================+=======================================================+
+ | ``boolean`` | :class:`bool` |
+ +----------------------+-------------------------------------------------------+
+ | ``int`` or ``i4`` | :class:`int` in range from -2147483648 to 2147483647. |
+ +----------------------+-------------------------------------------------------+
+ | ``double`` | :class:`float` |
+ +----------------------+-------------------------------------------------------+
+ | ``string`` | :class:`str` |
+ +----------------------+-------------------------------------------------------+
+ | ``array`` | :class:`list` or :class:`tuple` containing |
+ | | conformable elements. Arrays are returned as |
+ | | :class:`lists <list>`. |
+ +----------------------+-------------------------------------------------------+
+ | ``struct`` | :class:`dict`. Keys must be strings, values may be |
+ | | any conformable type. Objects of user-defined |
+ | | classes can be passed in; only their |
+ | | :attr:`~object.__dict__` attribute is transmitted. |
+ +----------------------+-------------------------------------------------------+
+ | ``dateTime.iso8601`` | :class:`DateTime` or :class:`datetime.datetime`. |
+ | | Returned type depends on values of |
+ | | *use_builtin_types* and *use_datetime* flags. |
+ +----------------------+-------------------------------------------------------+
+ | ``base64`` | :class:`Binary`, :class:`bytes` or |
+ | | :class:`bytearray`. Returned type depends on the |
+ | | value of the *use_builtin_types* flag. |
+ +----------------------+-------------------------------------------------------+
+ | ``nil`` | The ``None`` constant. Passing is allowed only if |
+ | | *allow_none* is true. |
+ +----------------------+-------------------------------------------------------+
This is the full set of data types supported by XML-RPC. Method calls may also
raise a special :exc:`Fault` instance, used to signal XML-RPC server errors, or
the control characters with ASCII values between 0 and 31 (except, of course,
tab, newline and carriage return); failing to do this will result in an XML-RPC
request that isn't well-formed XML. If you have to pass arbitrary bytes
- via XML-RPC, use the :class:`bytes` class or the class:`Binary` wrapper class
- described below.
+ via XML-RPC, use :class:`bytes` or :class:`bytearray` classes or the
+ :class:`Binary` wrapper class described below.
:class:`Server` is retained as an alias for :class:`ServerProxy` for backwards
compatibility. New code should use :class:`ServerProxy`.
`XML-RPC Introspection <http://xmlrpc-c.sourceforge.net/introspection.html>`_
Describes the XML-RPC protocol extension for introspection.
- `XML-RPC Specification <http://www.xmlrpc.com/spec>`_
+ `XML-RPC Specification <http://xmlrpc.scripting.com/spec.html>`_
The official specification.
`Unofficial XML-RPC Errata <http://effbot.org/zone/xmlrpc-errata.htm>`_
:class:`Fault` or :class:`ProtocolError` object indicating an error.
Servers that support the XML introspection API support some common methods
-grouped under the reserved :attr:`system` attribute:
+grouped under the reserved :attr:`~ServerProxy.system` attribute:
.. method:: ServerProxy.system.listMethods()
from xmlrpc.server import SimpleXMLRPCServer
def is_even(n):
- return n%2 == 0
+ return n % 2 == 0
server = SimpleXMLRPCServer(("localhost", 8000))
print("Listening on port 8000...")
DateTime Objects
----------------
-This class may be initialized with seconds since the epoch, a time
-tuple, an ISO 8601 time/date string, or a :class:`datetime.datetime`
-instance. It has the following methods, supported mainly for internal
-use by the marshalling/unmarshalling code:
+.. class:: DateTime
+
+ This class may be initialized with seconds since the epoch, a time
+ tuple, an ISO 8601 time/date string, or a :class:`datetime.datetime`
+ instance. It has the following methods, supported mainly for internal
+ use by the marshalling/unmarshalling code:
-.. method:: DateTime.decode(string)
+ .. method:: decode(string)
- Accept a string as the instance's new time value.
+ Accept a string as the instance's new time value.
-.. method:: DateTime.encode(out)
+ .. method:: encode(out)
- Write the XML-RPC encoding of this :class:`DateTime` item to the *out* stream
- object.
+ Write the XML-RPC encoding of this :class:`DateTime` item to the *out* stream
+ object.
-It also supports certain of Python's built-in operators through rich comparison
-and :meth:`__repr__` methods.
+ It also supports certain of Python's built-in operators through rich comparison
+ and :meth:`__repr__` methods.
A working example follows. The server code::
Binary Objects
--------------
-This class may be initialized from bytes data (which may include NULs). The
-primary access to the content of a :class:`Binary` object is provided by an
-attribute:
+.. class:: Binary
+ This class may be initialized from bytes data (which may include NULs). The
+ primary access to the content of a :class:`Binary` object is provided by an
+ attribute:
-.. attribute:: Binary.data
- The binary data encapsulated by the :class:`Binary` instance. The data is
- provided as a :class:`bytes` object.
+ .. attribute:: data
-:class:`Binary` objects have the following methods, supported mainly for
-internal use by the marshalling/unmarshalling code:
+ The binary data encapsulated by the :class:`Binary` instance. The data is
+ provided as a :class:`bytes` object.
+ :class:`Binary` objects have the following methods, supported mainly for
+ internal use by the marshalling/unmarshalling code:
-.. method:: Binary.decode(bytes)
- Accept a base64 :class:`bytes` object and decode it as the instance's new data.
+ .. method:: decode(bytes)
+ Accept a base64 :class:`bytes` object and decode it as the instance's new data.
-.. method:: Binary.encode(out)
- Write the XML-RPC base 64 encoding of this binary item to the out stream object.
+ .. method:: encode(out)
- The encoded data will have newlines every 76 characters as per
- `RFC 2045 section 6.8 <http://tools.ietf.org/html/rfc2045#section-6.8>`_,
- which was the de facto standard base64 specification when the
- XML-RPC spec was written.
+ Write the XML-RPC base 64 encoding of this binary item to the *out* stream object.
-It also supports certain of Python's built-in operators through :meth:`__eq__`
-and :meth:`__ne__` methods.
+ The encoded data will have newlines every 76 characters as per
+ `RFC 2045 section 6.8 <https://tools.ietf.org/html/rfc2045#section-6.8>`_,
+ which was the de facto standard base64 specification when the
+ XML-RPC spec was written.
+
+ It also supports certain of Python's built-in operators through :meth:`__eq__`
+ and :meth:`__ne__` methods.
Example usage of the binary objects. We're going to transfer an image over
XMLRPC::
Fault Objects
-------------
-A :class:`Fault` object encapsulates the content of an XML-RPC fault tag. Fault
-objects have the following attributes:
+.. class:: Fault
+
+ A :class:`Fault` object encapsulates the content of an XML-RPC fault tag. Fault
+ objects have the following attributes:
-.. attribute:: Fault.faultCode
+ .. attribute:: faultCode
- A string indicating the fault type.
+ A string indicating the fault type.
-.. attribute:: Fault.faultString
+ .. attribute:: faultString
- A string containing a diagnostic message associated with the fault.
+ A string containing a diagnostic message associated with the fault.
In the following example we're going to intentionally cause a :exc:`Fault` by
returning a complex type object. The server code::
# A marshalling error is going to occur because we're returning a
# complex number
- def add(x,y):
+ def add(x, y):
return x+y+0j
server = SimpleXMLRPCServer(("localhost", 8000))
ProtocolError Objects
---------------------
-A :class:`ProtocolError` object describes a protocol error in the underlying
-transport layer (such as a 404 'not found' error if the server named by the URI
-does not exist). It has the following attributes:
+.. class:: ProtocolError
+
+ A :class:`ProtocolError` object describes a protocol error in the underlying
+ transport layer (such as a 404 'not found' error if the server named by the URI
+ does not exist). It has the following attributes:
-.. attribute:: ProtocolError.url
+ .. attribute:: url
- The URI or URL that triggered the error.
+ The URI or URL that triggered the error.
-.. attribute:: ProtocolError.errcode
+ .. attribute:: errcode
- The error code.
+ The error code.
-.. attribute:: ProtocolError.errmsg
+ .. attribute:: errmsg
- The error message or diagnostic string.
+ The error message or diagnostic string.
-.. attribute:: ProtocolError.headers
+ .. attribute:: headers
- A dict containing the headers of the HTTP/HTTPS request that triggered the
- error.
+ A dict containing the headers of the HTTP/HTTPS request that triggered the
+ error.
In the following example we're going to intentionally cause a :exc:`ProtocolError`
by providing an invalid URI::
import xmlrpc.client
- # create a ServerProxy with an URI that doesn't respond to XMLRPC requests
+ # create a ServerProxy with a URI that doesn't respond to XMLRPC requests
proxy = xmlrpc.client.ServerProxy("http://google.com/")
try:
except Error as v:
print("ERROR", v)
-To access an XML-RPC server through a proxy, you need to define a custom
+To access an XML-RPC server through a HTTP proxy, you need to define a custom
transport. The following example shows how:
.. Example taken from http://lowlife.jp/nobonobo/wiki/xmlrpcwithproxy.html
class ProxiedTransport(xmlrpc.client.Transport):
def set_proxy(self, proxy):
self.proxy = proxy
+
def make_connection(self, host):
self.realhost = host
- h = http.client.HTTP(self.proxy)
+ h = http.client.HTTPConnection(self.proxy)
return h
- def send_request(self, connection, handler, request_body):
+
+ def send_request(self, connection, handler, request_body, debug):
connection.putrequest("POST", 'http://%s%s' % (self.realhost, handler))
+
def send_host(self, connection, host):
connection.putheader('Host', self.realhost)
p = ProxiedTransport()
p.set_proxy('proxy-server:8080')
- server = xmlrpc.client.Server('http://time.xmlrpc.com/RPC2', transport=p)
+ server = xmlrpc.client.ServerProxy('http://time.xmlrpc.com/RPC2', transport=p)
print(server.currentTime.getCurrentTime())
.. rubric:: Footnotes
.. [#] This approach has been first presented in `a discussion on xmlrpc.com
- <http://web.archive.org/web/20060624230303/http://www.xmlrpc.com/discuss/msgReader$1208?mode=topic>`_.
+ <https://web.archive.org/web/20060624230303/http://www.xmlrpc.com/discuss/msgReader$1208?mode=topic>`_.
.. the link now points to webarchive since the one at
.. http://www.xmlrpc.com/discuss/msgReader%241208 is broken (and webadmin
.. doesn't reply)
.. module:: xmlrpc.server
:synopsis: Basic XML-RPC server implementations.
+
.. moduleauthor:: Brian Quinlan <brianq@activestate.com>
.. sectionauthor:: Fred L. Drake, Jr. <fdrake@acm.org>
.. warning::
- The :mod:`xmlrpc.client` module is not secure against maliciously
+ The :mod:`xmlrpc.server` module is not secure against maliciously
constructed data. If you need to parse untrusted or unauthenticated data see
:ref:`xml-vulnerabilities`.
.. module:: zipapp
:synopsis: Manage executable python zip archives
-
-.. index::
- single: Executable Zip Files
-
.. versionadded:: 3.5
**Source code:** :source:`Lib/zipapp.py`
+.. index::
+ single: Executable Zip Files
+
--------------
This module provides tools to manage the creation of zip files containing
Basic Example
-------------
-The following example shows how the :ref:`command-line-interface`
+The following example shows how the :ref:`zipapp-command-line-interface`
can be used to create an executable archive from a directory containing
Python code. When run, the archive will execute the ``main`` function from
the module ``myapp`` in the archive.
.. module:: zipfile
:synopsis: Read and write ZIP-format archive files.
+
.. moduleauthor:: James C. Ahlstrom <jim@interet.com>
.. sectionauthor:: James C. Ahlstrom <jim@interet.com>
The ZIP file format is a common archive and compression standard. This module
provides tools to create, read, write, append, and list a ZIP file. Any
advanced use of this module will require an understanding of the format, as
-defined in `PKZIP Application Note
-<http://www.pkware.com/documents/casestudies/APPNOTE.TXT>`_.
+defined in `PKZIP Application Note`_.
This module does not currently handle multi-disk ZIP files.
It can handle ZIP files that use the ZIP64 extensions
.. seealso::
- `PKZIP Application Note <http://www.pkware.com/documents/casestudies/APPNOTE.TXT>`_
+ `PKZIP Application Note`_
Documentation on the ZIP file format by Phil Katz, the creator of the format and
algorithms used.
Open a ZIP file, where *file* can be either a path to a file (a string) or a
file-like object. The *mode* parameter should be ``'r'`` to read an existing
- file, ``'w'`` to truncate and write a new file, ``'x'`` to exclusive create
- and write a new file, or ``'a'`` to append to an existing file.
+ file, ``'w'`` to truncate and write a new file, ``'a'`` to append to an
+ existing file, or ``'x'`` to exclusively create and write a new file.
If *mode* is ``'x'`` and *file* refers to an existing file,
a :exc:`FileExistsError` will be raised.
If *mode* is ``'a'`` and *file* refers to an existing ZIP
.. attribute:: ZipInfo.extra
- Expansion field data. The `PKZIP Application Note
- <http://www.pkware.com/documents/casestudies/APPNOTE.TXT>`_ contains
+ Expansion field data. The `PKZIP Application Note`_ contains
some comments on the internal structure of the data contained in this string.
.. attribute:: ZipInfo.file_size
Size of the uncompressed file.
+
+.. _PKZIP Application Note: https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT
.. module:: zipimport
:synopsis: support for importing Python modules from ZIP archives.
+
.. moduleauthor:: Just van Rossum <just@letterror.com>
+--------------
This module adds the ability to import Python modules (:file:`\*.py`,
:file:`\*.py[co]`) and packages from ZIP-format archives. It is usually not
.. seealso::
- `PKZIP Application Note <http://www.pkware.com/documents/casestudies/APPNOTE.TXT>`_
+ `PKZIP Application Note <https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT>`_
Documentation on the ZIP file format by Phil Katz, the creator of the format and
algorithms used.
:synopsis: Low-level interface to compression and decompression routines
compatible with gzip.
+--------------
For applications that require data compression, the functions in this module
allow compression and decompression, using the zlib library. The zlib library
.. function:: adler32(data[, value])
Computes an Adler-32 checksum of *data*. (An Adler-32 checksum is almost as
- reliable as a CRC32 but can be computed much more quickly.) If *value* is
- present, it is used as the starting value of the checksum; otherwise, a fixed
- default value is used. This allows computing a running checksum over the
+ reliable as a CRC32 but can be computed much more quickly.) The result
+ is an unsigned 32-bit integer. If *value* is present, it is used as
+ the starting value of the checksum; otherwise, a default value of 1
+ is used. Passing in *value* allows computing a running checksum over the
concatenation of several inputs. The algorithm is not cryptographically
strong, and should not be used for authentication or digital signatures. Since
the algorithm is designed for use as a checksum algorithm, it is not suitable
for use as a general hash algorithm.
- Always returns an unsigned 32-bit integer.
-
-.. note::
- To generate the same numeric value across all Python versions and
- platforms use adler32(data) & 0xffffffff. If you are only using
- the checksum in packed binary format this is not necessary as the
- return value is the correct 32bit binary representation
- regardless of sign.
+ .. versionchanged:: 3.0
+ Always returns an unsigned value.
+ To generate the same numeric value across all Python versions and
+ platforms, use ``adler32(data) & 0xffffffff``.
.. function:: compress(data[, level])
Returns a compression object, to be used for compressing data streams that won't
fit into memory at once.
- *level* is the compression level -- an integer from ``0`` to ``9``. A value
- of ``1`` is fastest and produces the least compression, while a value of
+ *level* is the compression level -- an integer from ``0`` to ``9`` or ``-1``.
+ A value of ``1`` is fastest and produces the least compression, while a value of
``9`` is slowest and produces the most. ``0`` is no compression. The default
- value is ``6``.
+ value is ``-1`` (Z_DEFAULT_COMPRESSION). Z_DEFAULT_COMPRESSION represents a default
+ compromise between speed and compression (currently equivalent to level 6).
*method* is the compression algorithm. Currently, the only supported value is
``DEFLATED``.
- *wbits* is the base two logarithm of the size of the window buffer. This
- should be an integer from ``8`` to ``15``. Higher values give better
- compression, but use more memory.
+ The *wbits* argument controls the size of the history buffer (or the
+ "window size") used when compressing data, and whether a header and
+ trailer is included in the output. It can take several ranges of values:
+
+ * +9 to +15: The base-two logarithm of the window size, which
+ therefore ranges between 512 and 32768. Larger values produce
+ better compression at the expense of greater memory usage. The
+ resulting output will include a zlib-specific header and trailer.
+
+ * −9 to −15: Uses the absolute value of *wbits* as the
+ window size logarithm, while producing a raw output stream with no
+ header or trailing checksum.
+
+ * +25 to +31 = 16 + (9 to 15): Uses the low 4 bits of the value as the
+ window size logarithm, while including a basic :program:`gzip` header
+ and trailing checksum in the output.
The *memLevel* argument controls the amount of memory used for the
internal compression state. Valid values range from ``1`` to ``9``.
single: Cyclic Redundancy Check
single: checksum; Cyclic Redundancy Check
- Computes a CRC (Cyclic Redundancy Check) checksum of *data*. If *value* is
- present, it is used as the starting value of the checksum; otherwise, a fixed
- default value is used. This allows computing a running checksum over the
+ Computes a CRC (Cyclic Redundancy Check) checksum of *data*. The
+ result is an unsigned 32-bit integer. If *value* is present, it is used
+ as the starting value of the checksum; otherwise, a default value of 0
+ is used. Passing in *value* allows computing a running checksum over the
concatenation of several inputs. The algorithm is not cryptographically
strong, and should not be used for authentication or digital signatures. Since
the algorithm is designed for use as a checksum algorithm, it is not suitable
for use as a general hash algorithm.
- Always returns an unsigned 32-bit integer.
-
- .. note::
-
+ .. versionchanged:: 3.0
+ Always returns an unsigned value.
To generate the same numeric value across all Python versions and
- platforms, use ``crc32(data) & 0xffffffff``. If you are only using
- the checksum in packed binary format this is not necessary as the
- return value is the correct 32-bit binary representation
- regardless of sign.
+ platforms, use ``crc32(data) & 0xffffffff``.
.. function:: decompress(data[, wbits[, bufsize]])
Decompresses the bytes in *data*, returning a bytes object containing the
- uncompressed data. The *wbits* parameter controls the size of the window
- buffer, and is discussed further below.
+ uncompressed data. The *wbits* parameter depends on
+ the format of *data*, and is discussed further below.
If *bufsize* is given, it is used as the initial size of the output
buffer. Raises the :exc:`error` exception if any error occurs.
- The absolute value of *wbits* is the base two logarithm of the size of the
- history buffer (the "window size") used when compressing data. Its absolute
- value should be between 8 and 15 for the most recent versions of the zlib
- library, larger values resulting in better compression at the expense of greater
- memory usage. When decompressing a stream, *wbits* must not be smaller
+ .. _decompress-wbits:
+
+ The *wbits* parameter controls the size of the history buffer
+ (or "window size"), and what header and trailer format is expected.
+ It is similar to the parameter for :func:`compressobj`, but accepts
+ more ranges of values:
+
+ * +8 to +15: The base-two logarithm of the window size. The input
+ must include a zlib header and trailer.
+
+ * 0: Automatically determine the window size from the zlib header.
+ Only supported since zlib 1.2.3.5.
+
+ * −8 to −15: Uses the absolute value of *wbits* as the window size
+ logarithm. The input must be a raw stream with no header or trailer.
+
+ * +24 to +31 = 16 + (8 to 15): Uses the low 4 bits of the value as
+ the window size logarithm. The input must include a gzip header and
+ trailer.
+
+ * +40 to +47 = 32 + (8 to 15): Uses the low 4 bits of the value as
+ the window size logarithm, and automatically accepts either
+ the zlib or gzip format.
+
+ When decompressing a stream, the window size must not be smaller
than the size originally used to compress the stream; using a too-small
- value will result in an exception. The default value is therefore the
- highest value, 15. When *wbits* is negative, the standard
- :program:`gzip` header is suppressed.
+ value may result in an :exc:`error` exception. The default *wbits* value
+ is 15, which corresponds to the largest window size and requires a zlib
+ header and trailer to be included.
*bufsize* is the initial size of the buffer used to hold decompressed data. If
more space is required, the buffer size will be increased as needed, so you
Returns a decompression object, to be used for decompressing data streams that
won't fit into memory at once.
- The *wbits* parameter controls the size of the window buffer.
+ The *wbits* parameter controls the size of the history buffer (or the
+ "window size"), and what header and trailer format is expected. It has
+ the same meaning as `described for decompress() <#decompress-wbits>`__.
The *zdict* parameter specifies a predefined compression dictionary. If
provided, this must be the same dictionary as was used by the compressor that
=======================
Python was created in the early 1990s by Guido van Rossum at Stichting
-Mathematisch Centrum (CWI, see http://www.cwi.nl/) in the Netherlands as a
+Mathematisch Centrum (CWI, see https://www.cwi.nl/) in the Netherlands as a
successor of a language called ABC. Guido remains Python's principal author,
although it includes many contributions from others.
In 1995, Guido continued his work on Python at the Corporation for National
-Research Initiatives (CNRI, see http://www.cnri.reston.va.us/) in Reston,
+Research Initiatives (CNRI, see https://www.cnri.reston.va.us/) in Reston,
Virginia where he released several versions of the software.
In May 2000, Guido and the Python core development team moved to BeOpen.com to
specifically to own Python-related Intellectual Property. Zope Corporation is a
sponsoring member of the PSF.
-All Python releases are Open Source (see http://opensource.org/ for the Open
+All Python releases are Open Source (see https://opensource.org/ for the Open
Source Definition). Historically, most, but not all, Python releases have also
been GPL-compatible; the table below summarizes the various releases.
============================================================
-.. centered:: PSF LICENSE AGREEMENT FOR PYTHON |release|
-
-#. This LICENSE AGREEMENT is between the Python Software Foundation ("PSF"), and
- the Individual or Organization ("Licensee") accessing and otherwise using Python
- |release| software in source or binary form and its associated documentation.
-
-#. Subject to the terms and conditions of this License Agreement, PSF hereby
- grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce,
- analyze, test, perform and/or display publicly, prepare derivative works,
- distribute, and otherwise use Python |release| alone or in any derivative
- version, provided, however, that PSF's License Agreement and PSF's notice of
- copyright, i.e., "Copyright © 2001-2015 Python Software Foundation; All
- Rights Reserved" are retained in Python |release| alone or in any derivative
- version prepared by Licensee.
-
-#. In the event Licensee prepares a derivative work that is based on or
- incorporates Python |release| or any part thereof, and wants to make the
- derivative work available to others as provided herein, then Licensee hereby
- agrees to include in any such work a brief summary of the changes made to Python
- |release|.
-
-#. PSF is making Python |release| available to Licensee on an "AS IS" basis.
- PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF
- EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND DISCLAIMS ANY REPRESENTATION OR
- WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE
- USE OF PYTHON |release| WILL NOT INFRINGE ANY THIRD PARTY RIGHTS.
-
-#. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON |release|
- FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF
- MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON |release|, OR ANY DERIVATIVE
- THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
-
-#. This License Agreement will automatically terminate upon a material breach of
- its terms and conditions.
-
-#. Nothing in this License Agreement shall be deemed to create any relationship
- of agency, partnership, or joint venture between PSF and Licensee. This License
- Agreement does not grant permission to use PSF trademarks or trade name in a
- trademark sense to endorse or promote products or services of Licensee, or any
- third party.
-
-#. By copying, installing or otherwise using Python |release|, Licensee agrees
- to be bound by the terms and conditions of this License Agreement.
-
-
-.. centered:: BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0
-
-
-.. centered:: BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1
-
-#. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an office at
- 160 Saratoga Avenue, Santa Clara, CA 95051, and the Individual or Organization
- ("Licensee") accessing and otherwise using this software in source or binary
- form and its associated documentation ("the Software").
-
-#. Subject to the terms and conditions of this BeOpen Python License Agreement,
- BeOpen hereby grants Licensee a non-exclusive, royalty-free, world-wide license
- to reproduce, analyze, test, perform and/or display publicly, prepare derivative
- works, distribute, and otherwise use the Software alone or in any derivative
- version, provided, however, that the BeOpen Python License is retained in the
- Software, alone or in any derivative version prepared by Licensee.
-
-#. BeOpen is making the Software available to Licensee on an "AS IS" basis.
- BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF
- EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND DISCLAIMS ANY REPRESENTATION OR
- WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE
- USE OF THE SOFTWARE WILL NOT INFRINGE ANY THIRD PARTY RIGHTS.
-
-#. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE SOFTWARE FOR
- ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF USING,
- MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY DERIVATIVE THEREOF, EVEN IF
- ADVISED OF THE POSSIBILITY THEREOF.
-
-#. This License Agreement will automatically terminate upon a material breach of
- its terms and conditions.
-
-#. This License Agreement shall be governed by and interpreted in all respects
- by the law of the State of California, excluding conflict of law provisions.
- Nothing in this License Agreement shall be deemed to create any relationship of
- agency, partnership, or joint venture between BeOpen and Licensee. This License
- Agreement does not grant permission to use BeOpen trademarks or trade names in a
- trademark sense to endorse or promote products or services of Licensee, or any
- third party. As an exception, the "BeOpen Python" logos available at
- http://www.pythonlabs.com/logos.html may be used according to the permissions
- granted on that web page.
-
-#. By copying, installing or otherwise using the software, Licensee agrees to be
- bound by the terms and conditions of this License Agreement.
-
-
-.. centered:: CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1
-
-#. This LICENSE AGREEMENT is between the Corporation for National Research
- Initiatives, having an office at 1895 Preston White Drive, Reston, VA 20191
- ("CNRI"), and the Individual or Organization ("Licensee") accessing and
- otherwise using Python 1.6.1 software in source or binary form and its
- associated documentation.
-
-#. Subject to the terms and conditions of this License Agreement, CNRI hereby
- grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce,
- analyze, test, perform and/or display publicly, prepare derivative works,
- distribute, and otherwise use Python 1.6.1 alone or in any derivative version,
- provided, however, that CNRI's License Agreement and CNRI's notice of copyright,
- i.e., "Copyright © 1995-2001 Corporation for National Research Initiatives; All
- Rights Reserved" are retained in Python 1.6.1 alone or in any derivative version
- prepared by Licensee. Alternately, in lieu of CNRI's License Agreement,
- Licensee may substitute the following text (omitting the quotes): "Python 1.6.1
- is made available subject to the terms and conditions in CNRI's License
- Agreement. This Agreement together with Python 1.6.1 may be located on the
- Internet using the following unique, persistent identifier (known as a handle):
- 1895.22/1013. This Agreement may also be obtained from a proxy server on the
- Internet using the following URL: http://hdl.handle.net/1895.22/1013."
-
-#. In the event Licensee prepares a derivative work that is based on or
- incorporates Python 1.6.1 or any part thereof, and wants to make the derivative
- work available to others as provided herein, then Licensee hereby agrees to
- include in any such work a brief summary of the changes made to Python 1.6.1.
-
-#. CNRI is making Python 1.6.1 available to Licensee on an "AS IS" basis. CNRI
- MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE,
- BUT NOT LIMITATION, CNRI MAKES NO AND DISCLAIMS ANY REPRESENTATION OR WARRANTY
- OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF
- PYTHON 1.6.1 WILL NOT INFRINGE ANY THIRD PARTY RIGHTS.
-
-#. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON 1.6.1 FOR
- ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF
- MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1, OR ANY DERIVATIVE
- THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
-
-#. This License Agreement will automatically terminate upon a material breach of
- its terms and conditions.
-
-#. This License Agreement shall be governed by the federal intellectual property
- law of the United States, including without limitation the federal copyright
- law, and, to the extent such U.S. federal law does not apply, by the law of the
- Commonwealth of Virginia, excluding Virginia's conflict of law provisions.
- Notwithstanding the foregoing, with regard to derivative works based on Python
- 1.6.1 that incorporate non-separable material that was previously distributed
- under the GNU General Public License (GPL), the law of the Commonwealth of
- Virginia shall govern this License Agreement only as to issues arising under or
- with respect to Paragraphs 4, 5, and 7 of this License Agreement. Nothing in
- this License Agreement shall be deemed to create any relationship of agency,
- partnership, or joint venture between CNRI and Licensee. This License Agreement
- does not grant permission to use CNRI trademarks or trade name in a trademark
- sense to endorse or promote products or services of Licensee, or any third
- party.
-
-#. By clicking on the "ACCEPT" button where indicated, or by copying, installing
- or otherwise using Python 1.6.1, Licensee agrees to be bound by the terms and
- conditions of this License Agreement.
-
-
-.. centered:: ACCEPT
-
-
-.. centered:: CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2
-
-Copyright © 1991 - 1995, Stichting Mathematisch Centrum Amsterdam, The
-Netherlands. All rights reserved.
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted, provided that
-the above copyright notice appear in all copies and that both that copyright
-notice and this permission notice appear in supporting documentation, and that
-the name of Stichting Mathematisch Centrum or CWI not be used in advertising or
-publicity pertaining to distribution of the software without specific, written
-prior permission.
-
-STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
-SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
-EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE FOR ANY SPECIAL, INDIRECT
-OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
-DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
-ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
+PSF LICENSE AGREEMENT FOR PYTHON |release|
+------------------------------------------
+
+.. parsed-literal::
+
+ 1. This LICENSE AGREEMENT is between the Python Software Foundation ("PSF"), and
+ the Individual or Organization ("Licensee") accessing and otherwise using Python
+ |release| software in source or binary form and its associated documentation.
+
+ 2. Subject to the terms and conditions of this License Agreement, PSF hereby
+ grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce,
+ analyze, test, perform and/or display publicly, prepare derivative works,
+ distribute, and otherwise use Python |release| alone or in any derivative
+ version, provided, however, that PSF's License Agreement and PSF's notice of
+ copyright, i.e., "Copyright © 2001-2016 Python Software Foundation; All Rights
+ Reserved" are retained in Python |release| alone or in any derivative version
+ prepared by Licensee.
+
+ 3. In the event Licensee prepares a derivative work that is based on or
+ incorporates Python |release| or any part thereof, and wants to make the
+ derivative work available to others as provided herein, then Licensee hereby
+ agrees to include in any such work a brief summary of the changes made to Python
+ |release|.
+
+ 4. PSF is making Python |release| available to Licensee on an "AS IS" basis.
+ PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF
+ EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND DISCLAIMS ANY REPRESENTATION OR
+ WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE
+ USE OF PYTHON |release| WILL NOT INFRINGE ANY THIRD PARTY RIGHTS.
+
+ 5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON |release|
+ FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF
+ MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON |release|, OR ANY DERIVATIVE
+ THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
+
+ 6. This License Agreement will automatically terminate upon a material breach of
+ its terms and conditions.
+
+ 7. Nothing in this License Agreement shall be deemed to create any relationship
+ of agency, partnership, or joint venture between PSF and Licensee. This License
+ Agreement does not grant permission to use PSF trademarks or trade name in a
+ trademark sense to endorse or promote products or services of Licensee, or any
+ third party.
+
+ 8. By copying, installing or otherwise using Python |release|, Licensee agrees
+ to be bound by the terms and conditions of this License Agreement.
+
+
+BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0
+-------------------------------------------
+
+BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1
+
+.. parsed-literal::
+
+ 1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an office at
+ 160 Saratoga Avenue, Santa Clara, CA 95051, and the Individual or Organization
+ ("Licensee") accessing and otherwise using this software in source or binary
+ form and its associated documentation ("the Software").
+
+ 2. Subject to the terms and conditions of this BeOpen Python License Agreement,
+ BeOpen hereby grants Licensee a non-exclusive, royalty-free, world-wide license
+ to reproduce, analyze, test, perform and/or display publicly, prepare derivative
+ works, distribute, and otherwise use the Software alone or in any derivative
+ version, provided, however, that the BeOpen Python License is retained in the
+ Software, alone or in any derivative version prepared by Licensee.
+
+ 3. BeOpen is making the Software available to Licensee on an "AS IS" basis.
+ BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF
+ EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND DISCLAIMS ANY REPRESENTATION OR
+ WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE
+ USE OF THE SOFTWARE WILL NOT INFRINGE ANY THIRD PARTY RIGHTS.
+
+ 4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE SOFTWARE FOR
+ ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF USING,
+ MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY DERIVATIVE THEREOF, EVEN IF
+ ADVISED OF THE POSSIBILITY THEREOF.
+
+ 5. This License Agreement will automatically terminate upon a material breach of
+ its terms and conditions.
+
+ 6. This License Agreement shall be governed by and interpreted in all respects
+ by the law of the State of California, excluding conflict of law provisions.
+ Nothing in this License Agreement shall be deemed to create any relationship of
+ agency, partnership, or joint venture between BeOpen and Licensee. This License
+ Agreement does not grant permission to use BeOpen trademarks or trade names in a
+ trademark sense to endorse or promote products or services of Licensee, or any
+ third party. As an exception, the "BeOpen Python" logos available at
+ http://www.pythonlabs.com/logos.html may be used according to the permissions
+ granted on that web page.
+
+ 7. By copying, installing or otherwise using the software, Licensee agrees to be
+ bound by the terms and conditions of this License Agreement.
+
+
+CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1
+---------------------------------------
+
+.. parsed-literal::
+
+ 1. This LICENSE AGREEMENT is between the Corporation for National Research
+ Initiatives, having an office at 1895 Preston White Drive, Reston, VA 20191
+ ("CNRI"), and the Individual or Organization ("Licensee") accessing and
+ otherwise using Python 1.6.1 software in source or binary form and its
+ associated documentation.
+
+ 2. Subject to the terms and conditions of this License Agreement, CNRI hereby
+ grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce,
+ analyze, test, perform and/or display publicly, prepare derivative works,
+ distribute, and otherwise use Python 1.6.1 alone or in any derivative version,
+ provided, however, that CNRI's License Agreement and CNRI's notice of copyright,
+ i.e., "Copyright © 1995-2001 Corporation for National Research Initiatives; All
+ Rights Reserved" are retained in Python 1.6.1 alone or in any derivative version
+ prepared by Licensee. Alternately, in lieu of CNRI's License Agreement,
+ Licensee may substitute the following text (omitting the quotes): "Python 1.6.1
+ is made available subject to the terms and conditions in CNRI's License
+ Agreement. This Agreement together with Python 1.6.1 may be located on the
+ Internet using the following unique, persistent identifier (known as a handle):
+ 1895.22/1013. This Agreement may also be obtained from a proxy server on the
+ Internet using the following URL: http://hdl.handle.net/1895.22/1013."
+
+ 3. In the event Licensee prepares a derivative work that is based on or
+ incorporates Python 1.6.1 or any part thereof, and wants to make the derivative
+ work available to others as provided herein, then Licensee hereby agrees to
+ include in any such work a brief summary of the changes made to Python 1.6.1.
+
+ 4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS" basis. CNRI
+ MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE,
+ BUT NOT LIMITATION, CNRI MAKES NO AND DISCLAIMS ANY REPRESENTATION OR WARRANTY
+ OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF
+ PYTHON 1.6.1 WILL NOT INFRINGE ANY THIRD PARTY RIGHTS.
+
+ 5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON 1.6.1 FOR
+ ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF
+ MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1, OR ANY DERIVATIVE
+ THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
+
+ 6. This License Agreement will automatically terminate upon a material breach of
+ its terms and conditions.
+
+ 7. This License Agreement shall be governed by the federal intellectual property
+ law of the United States, including without limitation the federal copyright
+ law, and, to the extent such U.S. federal law does not apply, by the law of the
+ Commonwealth of Virginia, excluding Virginia's conflict of law provisions.
+ Notwithstanding the foregoing, with regard to derivative works based on Python
+ 1.6.1 that incorporate non-separable material that was previously distributed
+ under the GNU General Public License (GPL), the law of the Commonwealth of
+ Virginia shall govern this License Agreement only as to issues arising under or
+ with respect to Paragraphs 4, 5, and 7 of this License Agreement. Nothing in
+ this License Agreement shall be deemed to create any relationship of agency,
+ partnership, or joint venture between CNRI and Licensee. This License Agreement
+ does not grant permission to use CNRI trademarks or trade name in a trademark
+ sense to endorse or promote products or services of Licensee, or any third
+ party.
+
+ 8. By clicking on the "ACCEPT" button where indicated, or by copying, installing
+ or otherwise using Python 1.6.1, Licensee agrees to be bound by the terms and
+ conditions of this License Agreement.
+
+
+CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2
+--------------------------------------------------
+
+.. parsed-literal::
+
+ Copyright © 1991 - 1995, Stichting Mathematisch Centrum Amsterdam, The
+ Netherlands. All rights reserved.
+
+ Permission to use, copy, modify, and distribute this software and its
+ documentation for any purpose and without fee is hereby granted, provided that
+ the above copyright notice appear in all copies and that both that copyright
+ notice and this permission notice appear in supporting documentation, and that
+ the name of Stichting Mathematisch Centrum or CWI not be used in advertising or
+ publicity pertaining to distribution of the software without specific, written
+ prior permission.
+
+ STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE FOR ANY SPECIAL, INDIRECT
+ OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ SOFTWARE.
Licenses and Acknowledgements for Incorporated Software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
- GAI_ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
- FOR GAI_ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- HOWEVER CAUSED AND ON GAI_ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN GAI_ANY WAY
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
-
-
.. seealso::
- :pep:`0343` - The "with" statement
+ :pep:`343` - The "with" statement
The specification, background, and examples for the Python :keyword:`with`
statement.
.. productionlist::
funcdef: [`decorators`] "def" `funcname` "(" [`parameter_list`] ")" ["->" `expression`] ":" `suite`
decorators: `decorator`+
- decorator: "@" `dotted_name` ["(" [`parameter_list` [","]] ")"] NEWLINE
+ decorator: "@" `dotted_name` ["(" [`argument_list` [","]] ")"] NEWLINE
dotted_name: `identifier` ("." `identifier`)*
parameter_list: (`defparameter` ",")*
: | "*" [`parameter`] ("," `defparameter`)* ["," "**" `parameter`]
.. productionlist::
classdef: [`decorators`] "class" `classname` [`inheritance`] ":" `suite`
- inheritance: "(" [`parameter_list`] ")"
+ inheritance: "(" [`argument_list`] ")"
classname: `identifier`
A class definition is an executable statement. The inheritance list usually
Is semantically equivalent to::
iter = (ITER)
- iter = await type(iter).__aiter__(iter)
+ iter = type(iter).__aiter__(iter)
running = True
while running:
try:
definitions may change with future versions of the interpreter, but they are
mentioned here for completeness.
- Code objects
- .. index::
- single: bytecode
- object: code
+ .. index:: bytecode, object; code, code object
+ Code objects
Code objects represent *byte-compiled* executable Python code, or :term:`bytecode`.
The difference between a code object and a function object is that the function
object contains an explicit reference to the function's globals (the module in
included in the class definition (if any) and the resulting object is bound
in the local namespace as the defined class.
+When a new class is created by ``type.__new__``, the object provided as the
+namespace parameter is copied to a standard Python dictionary and the original
+object is discarded. The new copy becomes the :attr:`~object.__dict__` attribute
+of the class object.
+
.. seealso::
:pep:`3135` - New super
class OrderedClass(type):
- @classmethod
- def __prepare__(metacls, name, bases, **kwds):
+ @classmethod
+ def __prepare__(metacls, name, bases, **kwds):
return collections.OrderedDict()
- def __new__(cls, name, bases, namespace, **kwds):
+ def __new__(cls, name, bases, namespace, **kwds):
result = type.__new__(cls, name, bases, dict(namespace))
result.members = tuple(namespace)
return result
.. seealso::
- :pep:`0343` - The "with" statement
+ :pep:`343` - The "with" statement
The specification, background, and examples for the Python :keyword:`with`
statement.
those of generators (see :ref:`generator-methods`). However, unlike
generators, coroutines do not directly support iteration.
+.. versionchanged:: 3.5.2
+ It is a :exc:`RuntimeError` to await on a coroutine more than once.
+
+
.. method:: coroutine.send(value)
Starts or resumes execution of the coroutine. If *value* is ``None``,
Coroutine objects are automatically closed using the above process when
they are about to be destroyed.
+.. _async-iterators:
Asynchronous Iterators
----------------------
.. method:: object.__aiter__(self)
- Must return an *awaitable* resulting in an *asynchronous iterator* object.
+ Must return an *asynchronous iterator* object.
.. method:: object.__anext__(self)
async def readline(self):
...
- async def __aiter__(self):
+ def __aiter__(self):
return self
async def __anext__(self):
.. versionadded:: 3.5
+.. note::
+
+ .. versionchanged:: 3.5.2
+ Starting with CPython 3.5.2, ``__aiter__`` can directly return
+ :term:`asynchronous iterators <asynchronous iterator>`. Returning
+ an :term:`awaitable` object will result in a
+ :exc:`PendingDeprecationWarning`.
+
+ The recommended way of writing backwards compatible code in
+ CPython 3.5.x is to continue returning awaitables from
+ ``__aiter__``. If you want to avoid the PendingDeprecationWarning
+ and keep the code backwards compatible, the following decorator
+ can be used::
+
+ import functools
+ import sys
+
+ if sys.version_info < (3, 5, 2):
+ def aiter_compat(func):
+ @functools.wraps(func)
+ async def wrapper(self):
+ return func(self)
+ return wrapper
+ else:
+ def aiter_compat(func):
+ return func
+
+ Example::
+
+ class AsyncIterator:
+
+ @aiter_compat
+ def __aiter__(self):
+ return self
+
+ async def __anext__(self):
+ ...
+
+ Starting with CPython 3.6, the :exc:`PendingDeprecationWarning`
+ will be replaced with the :exc:`DeprecationWarning`.
+ In CPython 3.7, returning an awaitable from ``__aiter__`` will
+ result in a :exc:`RuntimeError`.
+
Asynchronous Context Managers
-----------------------------
A parenthesized form is an optional expression list enclosed in parentheses:
.. productionlist::
- parenth_form: "(" [`expression_list`] ")"
+ parenth_form: "(" [`starred_expression`] ")"
A parenthesized expression list yields whatever that expression list yields: if
the list contains at least one comma, it yields a tuple; otherwise, it yields
brackets:
.. productionlist::
- list_display: "[" [`expression_list` | `comprehension`] "]"
+ list_display: "[" [`starred_list` | `comprehension`] "]"
A list display yields a new list object, the contents being specified by either
a list of expressions or a comprehension. When a comma-separated list of
displays by the lack of colons separating keys and values:
.. productionlist::
- set_display: "{" (`expression_list` | `comprehension`) "}"
+ set_display: "{" (`starred_list` | `comprehension`) "}"
A set display yields a new mutable set object, the contents being specified by
either a sequence of expressions or a comprehension. When a comma-separated
.. productionlist::
dict_display: "{" [`key_datum_list` | `dict_comprehension`] "}"
key_datum_list: `key_datum` ("," `key_datum`)* [","]
- key_datum: `expression` ":" `expression`
+ key_datum: `expression` ":" `expression` | "**" `or_expr`
dict_comprehension: `expression` ":" `expression` `comp_for`
A dictionary display yields a new dictionary object.
that you can specify the same key multiple times in the key/datum list, and the
final dictionary's value for that key will be the last one given.
+.. index:: unpacking; dictionary, **; in dictionary displays
+
+A double asterisk ``**`` denotes :dfn:`dictionary unpacking`.
+Its operand must be a :term:`mapping`. Each mapping item is added
+to the new dictionary. Later values replace values already set by
+earlier key/datum pairs and earlier dictionary unpackings.
+
+.. versionadded:: 3.5
+ Unpacking into dictionary displays, originally proposed by :pep:`448`.
+
A dict comprehension, in contrast to list and set comprehensions, needs two
expressions separated with a colon followed by the usual "for" and "if" clauses.
When the comprehension is run, the resulting key and value elements are inserted
.. seealso::
- :pep:`0255` - Simple Generators
+ :pep:`255` - Simple Generators
The proposal for adding generators and the :keyword:`yield` statement to Python.
- :pep:`0342` - Coroutines via Enhanced Generators
+ :pep:`342` - Coroutines via Enhanced Generators
The proposal to enhance the API and syntax of generators, making them
usable as simple coroutines.
- :pep:`0380` - Syntax for Delegating to a Subgenerator
+ :pep:`380` - Syntax for Delegating to a Subgenerator
The proposal to introduce the :token:`yield_from` syntax, making delegation
to sub-generators easy.
.. productionlist::
call: `primary` "(" [`argument_list` [","] | `comprehension`] ")"
- argument_list: `positional_arguments` ["," `keyword_arguments`]
- : ["," "*" `expression`] ["," `keyword_arguments`]
- : ["," "**" `expression`]
- : | `keyword_arguments` ["," "*" `expression`]
- : ["," `keyword_arguments`] ["," "**" `expression`]
- : | "*" `expression` ["," `keyword_arguments`] ["," "**" `expression`]
- : | "**" `expression`
- positional_arguments: `expression` ("," `expression`)*
- keyword_arguments: `keyword_item` ("," `keyword_item`)*
+ argument_list: `positional_arguments` ["," `starred_and_keywords`]
+ : ["," `keywords_arguments`]
+ : | `starred_and_keywords` ["," `keywords_arguments`]
+ : | `keywords_arguments`
+ positional_arguments: ["*"] `expression` ("," ["*"] `expression`)*
+ starred_and_keywords: ("*" `expression` | `keyword_item`)
+ : ("," "*" `expression` | "," `keyword_item`)*
+ keywords_arguments: (`keyword_item` | "**" `expression`)
+ : ("," `keyword_item` | "**" `expression`)*
keyword_item: `identifier` "=" `expression`
An optional trailing comma may be present after the positional and keyword arguments
.. index::
single: *; in function calls
+ single: unpacking; in function calls
If the syntax ``*expression`` appears in the function call, ``expression`` must
-evaluate to an iterable. Elements from this iterable are treated as if they
-were additional positional arguments; if there are positional arguments
-*x1*, ..., *xN*, and ``expression`` evaluates to a sequence *y1*, ..., *yM*,
-this is equivalent to a call with M+N positional arguments *x1*, ..., *xN*,
-*y1*, ..., *yM*.
+evaluate to an :term:`iterable`. Elements from these iterables are
+treated as if they were additional positional arguments. For the call
+``f(x1, x2, *y, x3, x4)``, if *y* evaluates to a sequence *y1*, ..., *yM*,
+this is equivalent to a call with M+4 positional arguments *x1*, *x2*,
+*y1*, ..., *yM*, *x3*, *x4*.
A consequence of this is that although the ``*expression`` syntax may appear
-*after* some keyword arguments, it is processed *before* the keyword arguments
-(and the ``**expression`` argument, if any -- see below). So::
+*after* explicit keyword arguments, it is processed *before* the
+keyword arguments (and any ``**expression`` arguments -- see below). So::
>>> def f(a, b):
- ... print(a, b)
+ ... print(a, b)
...
>>> f(b=1, *(2,))
2 1
single: **; in function calls
If the syntax ``**expression`` appears in the function call, ``expression`` must
-evaluate to a mapping, the contents of which are treated as additional keyword
-arguments. In the case of a keyword appearing in both ``expression`` and as an
-explicit keyword argument, a :exc:`TypeError` exception is raised.
+evaluate to a :term:`mapping`, the contents of which are treated as
+additional keyword arguments. If a keyword is already present
+(as an explicit keyword argument, or from another unpacking),
+a :exc:`TypeError` exception is raised.
Formal parameters using the syntax ``*identifier`` or ``**identifier`` cannot be
used as positional argument slots or as keyword argument names.
+.. versionchanged:: 3.5
+ Function calls accept any number of ``*`` and ``**`` unpackings,
+ positional arguments may follow iterable unpackings (``*``),
+ and keyword arguments may follow dictionary unpackings (``**``).
+ Originally proposed by :pep:`448`.
+
A call always returns some value, possibly ``None``, unless it raises an
exception. How this value is computed depends on the type of the callable
object.
Can only be used inside a :term:`coroutine function`.
.. productionlist::
- await: ["await"] `primary`
+ await_expr: "await" `primary`
.. versionadded:: 3.5
less tightly than unary operators on its right. The syntax is:
.. productionlist::
- power: `await` ["**" `u_expr`]
+ power: ( `await_expr` | `primary` ) ["**" `u_expr`]
Thus, in an unparenthesized sequence of power and unary operators, the operators
are evaluated from right to left (this does not constrain the evaluation order
.. productionlist::
expression_list: `expression` ( "," `expression` )* [","]
+ starred_list: `starred_item` ( "," `starred_item` )* [","]
+ starred_expression: `expression` | ( `starred_item` "," )* [`starred_item`]
+ starred_item: `expression` | "*" `or_expr`
.. index:: object: tuple
-An expression list containing at least one comma yields a tuple. The length of
+Except when part of a list or set display, an expression list
+containing at least one comma yields a tuple. The length of
the tuple is the number of expressions in the list. The expressions are
evaluated from left to right.
+.. index::
+ pair: iterable; unpacking
+ single: *; in expression lists
+
+An asterisk ``*`` denotes :dfn:`iterable unpacking`. Its operand must be
+an :term:`iterable`. The iterable is expanded into a sequence of items,
+which are included in the new tuple, list, or set, at the site of
+the unpacking.
+
+.. versionadded:: 3.5
+ Iterable unpacking in expression lists, originally proposed by :pep:`448`.
+
.. index:: pair: trailing; comma
The trailing comma is required only to create a single tuple (a.k.a. a
a name binding operation.
When calling :func:`__import__` as part of an import statement, the
-import system first checks the module global namespace for a function by
-that name. If it is not found, then the standard builtin :func:`__import__`
-is called. Other mechanisms for invoking the import system (such as
-:func:`importlib.import_module`) do not perform this check and will always
-use the standard import system.
+standard builtin :func:`__import__` is called. Other mechanisms for
+invoking the import system (such as :func:`importlib.import_module`) may
+choose to subvert :func:`__import__` and use its own solution to
+implement import semantics.
When a module is first imported, Python searches for the module and if found,
it creates a module object [#fnmo]_, initializing it. If the named module
This implementation actually uses the CPython implementation, but is a managed
.NET application and makes .NET libraries available. It was created by Brian
Lloyd. For more information, see the `Python for .NET home page
- <http://pythonnet.sourceforge.net>`_.
+ <https://pythonnet.github.io/>`_.
IronPython
An alternate Python for .NET. Unlike Python.NET, this is a complete Python
A non-normative HTML file listing all valid identifier characters for Unicode
4.1 can be found at
-http://www.dcl.hpi.uni-potsdam.de/home/loewis/table-3131.html.
+https://www.dcl.hpi.uni-potsdam.de/home/loewis/table-3131.html.
.. _keywords:
Support for name aliases [#]_ has been added.
(5)
- Individual code units which form parts of a surrogate pair can be encoded using
- this escape sequence. Exactly four hex digits are required.
+ Exactly four hex digits are required.
(6)
Any Unicode character can be encoded this way. Exactly eight hex digits
expression statement is:
.. productionlist::
- expression_stmt: `expression_list`
+ expression_stmt: `starred_expression`
An expression statement evaluates the expression list (which may be a single
expression).
attributes or items of mutable objects:
.. productionlist::
- assignment_stmt: (`target_list` "=")+ (`expression_list` | `yield_expression`)
+ assignment_stmt: (`target_list` "=")+ (`starred_expression` | `yield_expression`)
target_list: `target` ("," `target`)* [","]
target: `identifier`
: | "(" `target_list` ")"
- : | "[" `target_list` "]"
+ : | "[" [`target_list`] "]"
: | `attributeref`
: | `subscription`
: | `slicing`
Assignment of an object to a target list, optionally enclosed in parentheses or
square brackets, is recursively defined as follows.
-* If the target list is a single target: The object is assigned to that target.
+* If the target list is empty: The object must also be an empty iterable.
-* If the target list is a comma-separated list of targets: The object must be an
- iterable with the same number of items as there are targets in the target list,
- and the items are assigned, from left to right, to the corresponding targets.
+* If the target list is a single target in parentheses: The object is assigned
+ to that target.
+
+* If the target list is a comma-separated list of targets, or a single target
+ in square brackets: The object must be an iterable with the same number of
+ items as there are targets in the target list, and the items are assigned,
+ from left to right, to the corresponding targets.
* If the target list contains one target prefixed with an asterisk, called a
- "starred" target: The object must be a sequence with at least as many items
+ "starred" target: The object must be an iterable with at least as many items
as there are targets in the target list, minus one. The first items of the
- sequence are assigned, from left to right, to the targets before the starred
- target. The final items of the sequence are assigned to the targets after
- the starred target. A list of the remaining items in the sequence is then
+ iterable are assigned, from left to right, to the targets before the starred
+ target. The final items of the iterable are assigned to the targets after
+ the starred target. A list of the remaining items in the iterable is then
assigned to the starred target (the list can be empty).
- * Else: The object must be a sequence with the same number of items as there
+ * Else: The object must be an iterable with the same number of items as there
are targets in the target list, and the items are assigned, from left to
right, to the corresponding targets.
count for the object previously bound to the name to reach zero, causing the
object to be deallocated and its destructor (if it has one) to be called.
-* If the target is a target list enclosed in parentheses or in square brackets:
- The object must be an iterable with the same number of items as there are
- targets in the target list, and its items are assigned, from left to right,
- to the corresponding targets.
-
.. index:: pair: attribute; assignment
* If the target is an attribute reference: The primary expression in the
phase, causing less detailed error messages.
Although the definition of assignment implies that overlaps between the
-left-hand side and the right-hand side are 'simultanenous' (for example ``a, b =
+left-hand side and the right-hand side are 'simultaneous' (for example ``a, b =
b, a`` swaps two variables), overlaps *within* the collection of assigned-to
variables occur left-to-right, sometimes resulting in confusion. For instance,
the following program prints ``[0, 2]``::
The simple form, ``assert expression``, is equivalent to ::
if __debug__:
- if not expression: raise AssertionError
+ if not expression: raise AssertionError
The extended form, ``assert expression1, expression2``, is equivalent to ::
if __debug__:
- if not expression1: raise AssertionError(expression2)
+ if not expression1: raise AssertionError(expression2)
.. index::
single: __debug__
When the statement contains multiple clauses (separated by
commas) the two steps are carried out separately for each clause, just
-as though the clauses had been separated out into individiual import
+as though the clauses had been separated out into individual import
statements.
The details of the first step, finding and loading modules are described in
nonlocal_stmt: "nonlocal" `identifier` ("," `identifier`)*
.. XXX add when implemented
- : ["=" (`target_list` "=")+ expression_list]
+ : ["=" (`target_list` "=")+ starred_expression]
: | "nonlocal" identifier augop expression_list
The :keyword:`nonlocal` statement causes the listed identifiers to refer to
return PyClassmember.run(self)
+class PyAbstractMethod(PyClassmember):
+
+ def handle_signature(self, sig, signode):
+ ret = super(PyAbstractMethod, self).handle_signature(sig, signode)
+ signode.insert(0, addnodes.desc_annotation('abstractmethod ',
+ 'abstractmethod '))
+ return ret
+
+ def run(self):
+ self.name = 'py:method'
+ return PyClassmember.run(self)
+
+
# Support for documenting version of removal in deprecations
class DeprecatedRemoved(Directive):
app.add_directive_to_domain('py', 'decoratormethod', PyDecoratorMethod)
app.add_directive_to_domain('py', 'coroutinefunction', PyCoroutineFunction)
app.add_directive_to_domain('py', 'coroutinemethod', PyCoroutineMethod)
+ app.add_directive_to_domain('py', 'abstractmethod', PyAbstractMethod)
app.add_directive('miscnews', MiscNews)
return {'version': '1.0', 'parallel_read_safe': True}
.stableabi {
color: #229;
}
+
+.highlight {
+ background: none !important;
+}
+
]
all_directives = '(' + '|'.join(directives) + ')'
-seems_directive_re = re.compile(r'\.\. %s([^a-z:]|:(?!:))' % all_directives)
+seems_directive_re = re.compile(r'(?<!\.)\.\. %s([^a-z:]|:(?!:))' % all_directives)
default_role_re = re.compile(r'(^| )`\w([^`]*?\w)?`($| )')
leaked_markup_re = re.compile(r'[a-z]::\s|`|\.\.\s*\w+:')
"""Check for suspicious reST constructs."""
inprod = False
for lno, line in enumerate(lines):
- if seems_directive_re.match(line):
+ if seems_directive_re.search(line):
yield lno+1, 'comment seems to be intended as a directive'
if '.. productionlist::' in line:
inprod = True
var button = $('<span class="copybutton">>>></span>');
button.css(button_styles)
button.attr('title', hide_text);
+ button.data('hidden', 'false');
jthis.prepend(button);
}
// tracebacks (.gt) contain bare text elements that need to be
});
// define the behavior of the button when it's clicked
- $('.copybutton').toggle(
- function() {
- var button = $(this);
+ $('.copybutton').click(function(e){
+ e.preventDefault();
+ var button = $(this);
+ if (button.data('hidden') === 'false') {
+ // hide the code output
button.parent().find('.go, .gp, .gt').hide();
button.next('pre').find('.gt').nextUntil('.gp, .go').css('visibility', 'hidden');
button.css('text-decoration', 'line-through');
button.attr('title', show_text);
- },
- function() {
- var button = $(this);
+ button.data('hidden', 'true');
+ } else {
+ // show the code output
button.parent().find('.go, .gp, .gt').show();
button.next('pre').find('.gt').nextUntil('.gp, .go').css('visibility', 'visible');
button.css('text-decoration', 'none');
button.attr('title', hide_text);
- });
+ button.data('hidden', 'false');
+ }
+ });
});
howto/pyporting,,::,Programming Language :: Python :: 3
howto/regex,,::,
howto/regex,,:foo,(?:foo)
-howto/urllib2,,:example,"for example ""joe@password:example.com"""
+howto/urllib2,,:password,"for example ""joe:password@example.com"""
library/audioop,,:ipos,"# factor = audioop.findfactor(in_test[ipos*2:ipos*2+len(out_test)],"
library/bisect,32,:hi,all(val >= x for val in a[i:hi])
library/bisect,42,:hi,all(val > x for val in a[i:hi])
library/unittest,,:foo,'ERROR:foo.bar:second message'])
library/unittest,,:second,'ERROR:foo.bar:second message'])
library/urllib.request,,:close,Connection:close
+library/urllib.request,,:port,:port
library/urllib.request,,:lang,"xmlns=""http://www.w3.org/1999/xhtml"" xml:lang=""en"" lang=""en"">\n\n<head>\n"
library/urllib.request,,:password,"""joe:password@python.org"""
library/uuid,,:uuid,urn:uuid:12345678-1234-5678-1234-567812345678
using/cmdline,,:line,file:line: category: message
using/cmdline,,:message,action:message:category:module:line
using/cmdline,,:module,action:message:category:module:line
-using/unix,,:Packaging,http://en.opensuse.org/Portal:Packaging
+using/unix,,:Packaging,https://en.opensuse.org/Portal:Packaging
whatsnew/2.0,418,:len,
whatsnew/2.3,,::,
whatsnew/2.3,,:config,
library/xml.etree.elementtree,301,:character,<fictional:character>Sir Robin</fictional:character>
library/xml.etree.elementtree,301,:character,<fictional:character>Gunther</fictional:character>
library/xml.etree.elementtree,301,:character,<fictional:character>Commander Clement</fictional:character>
-library/xml.etree.elementtree,332,:actor,"for actor in root.findall('real_person:actor', ns):"
-library/xml.etree.elementtree,332,:name,"name = actor.find('real_person:name', ns)"
-library/xml.etree.elementtree,332,:character,"for char in actor.findall('role:character', ns):"
+library/xml.etree.elementtree,,:actor,"for actor in root.findall('real_person:actor', ns):"
+library/xml.etree.elementtree,,:name,"name = actor.find('real_person:name', ns)"
+library/xml.etree.elementtree,,:character,"for char in actor.findall('role:character', ns):"
library/zipapp,31,:main,"$ python -m zipapp myapp -m ""myapp:main"""
library/zipapp,82,:fn,"argument should have the form ""pkg.mod:fn"", where ""pkg.mod"" is a"
library/zipapp,155,:callable,"""pkg.module:callable"" and the archive will be run by importing"
{% extends "defindex.html" %}
{% block tables %}
- <p><strong>Parts of the documentation:</strong></p>
+ <p><strong>{% trans %}Parts of the documentation:{% endtrans %}</strong></p>
<table class="contentstable" align="center"><tr>
<td width="50%">
- <p class="biglink"><a class="biglink" href="{{ pathto("whatsnew/" + version) }}">What's new in Python {{ version }}?</a><br/>
- <span class="linkdescr">or <a href="{{ pathto("whatsnew/index") }}">all "What's new" documents</a> since 2.0</span></p>
- <p class="biglink"><a class="biglink" href="{{ pathto("tutorial/index") }}">Tutorial</a><br/>
- <span class="linkdescr">start here</span></p>
- <p class="biglink"><a class="biglink" href="{{ pathto("library/index") }}">Library Reference</a><br/>
- <span class="linkdescr">keep this under your pillow</span></p>
- <p class="biglink"><a class="biglink" href="{{ pathto("reference/index") }}">Language Reference</a><br/>
- <span class="linkdescr">describes syntax and language elements</span></p>
- <p class="biglink"><a class="biglink" href="{{ pathto("using/index") }}">Python Setup and Usage</a><br/>
- <span class="linkdescr">how to use Python on different platforms</span></p>
- <p class="biglink"><a class="biglink" href="{{ pathto("howto/index") }}">Python HOWTOs</a><br/>
- <span class="linkdescr">in-depth documents on specific topics</span></p>
+ <p class="biglink"><a class="biglink" href="{{ pathto("whatsnew/" + version) }}">{% trans %}What's new in Python {{ version }}?{% endtrans %}</a><br/>
+ <span class="linkdescr"> {% trans whatsnew_index=pathto("whatsnew/index") %}or <a href="{{ whatsnew_index }}">all "What's new" documents</a> since 2.0{% endtrans %}</span></p>
+ <p class="biglink"><a class="biglink" href="{{ pathto("tutorial/index") }}">{% trans %}Tutorial{% endtrans %}</a><br/>
+ <span class="linkdescr">{% trans %}start here{% endtrans %}</span></p>
+ <p class="biglink"><a class="biglink" href="{{ pathto("library/index") }}">{% trans %}Library Reference{% endtrans %}</a><br/>
+ <span class="linkdescr">{% trans %}keep this under your pillow{% endtrans %}</span></p>
+ <p class="biglink"><a class="biglink" href="{{ pathto("reference/index") }}">{% trans %}Language Reference{% endtrans %}</a><br/>
+ <span class="linkdescr">{% trans %}describes syntax and language elements{% endtrans %}</span></p>
+ <p class="biglink"><a class="biglink" href="{{ pathto("using/index") }}">{% trans %}Python Setup and Usage{% endtrans %}</a><br/>
+ <span class="linkdescr">{% trans %}how to use Python on different platforms{% endtrans %}</span></p>
+ <p class="biglink"><a class="biglink" href="{{ pathto("howto/index") }}">{% trans %}Python HOWTOs{% endtrans %}</a><br/>
+ <span class="linkdescr">{% trans %}in-depth documents on specific topics{% endtrans %}</span></p>
</td><td width="50%">
- <p class="biglink"><a class="biglink" href="{{ pathto("installing/index") }}">Installing Python Modules</a><br/>
- <span class="linkdescr">installing from the Python Package Index & other sources</span></p>
- <p class="biglink"><a class="biglink" href="{{ pathto("distributing/index") }}">Distributing Python Modules</a><br/>
- <span class="linkdescr">publishing modules for installation by others</span></p>
- <p class="biglink"><a class="biglink" href="{{ pathto("extending/index") }}">Extending and Embedding</a><br/>
- <span class="linkdescr">tutorial for C/C++ programmers</span></p>
- <p class="biglink"><a class="biglink" href="{{ pathto("c-api/index") }}">Python/C API</a><br/>
- <span class="linkdescr">reference for C/C++ programmers</span></p>
- <p class="biglink"><a class="biglink" href="{{ pathto("faq/index") }}">FAQs</a><br/>
- <span class="linkdescr">frequently asked questions (with answers!)</span></p>
+ <p class="biglink"><a class="biglink" href="{{ pathto("installing/index") }}">{% trans %}Installing Python Modules{% endtrans %}</a><br/>
+ <span class="linkdescr">{% trans %}installing from the Python Package Index & other sources{% endtrans %}</span></p>
+ <p class="biglink"><a class="biglink" href="{{ pathto("distributing/index") }}">{% trans %}Distributing Python Modules{% endtrans %}</a><br/>
+ <span class="linkdescr">{% trans %}publishing modules for installation by others{% endtrans %}</span></p>
+ <p class="biglink"><a class="biglink" href="{{ pathto("extending/index") }}">{% trans %}Extending and Embedding{% endtrans %}</a><br/>
+ <span class="linkdescr">{% trans %}tutorial for C/C++ programmers{% endtrans %}</span></p>
+ <p class="biglink"><a class="biglink" href="{{ pathto("c-api/index") }}">{% trans %}Python/C API{% endtrans %}</a><br/>
+ <span class="linkdescr">{% trans %}reference for C/C++ programmers{% endtrans %}</span></p>
+ <p class="biglink"><a class="biglink" href="{{ pathto("faq/index") }}">{% trans %}FAQs{% endtrans %}</a><br/>
+ <span class="linkdescr">{% trans %}frequently asked questions (with answers!){% endtrans %}</span></p>
</td></tr>
</table>
- <p><strong>Indices and tables:</strong></p>
+ <p><strong>{% trans %}Indices and tables:{% endtrans %}</strong></p>
<table class="contentstable" align="center"><tr>
<td width="50%">
- <p class="biglink"><a class="biglink" href="{{ pathto("py-modindex") }}">Global Module Index</a><br/>
- <span class="linkdescr">quick access to all modules</span></p>
- <p class="biglink"><a class="biglink" href="{{ pathto("genindex") }}">General Index</a><br/>
- <span class="linkdescr">all functions, classes, terms</span></p>
- <p class="biglink"><a class="biglink" href="{{ pathto("glossary") }}">Glossary</a><br/>
- <span class="linkdescr">the most important terms explained</span></p>
+ <p class="biglink"><a class="biglink" href="{{ pathto("py-modindex") }}">{% trans %}Global Module Index{% endtrans %}</a><br/>
+ <span class="linkdescr">{% trans %}quick access to all modules{% endtrans %}</span></p>
+ <p class="biglink"><a class="biglink" href="{{ pathto("genindex") }}">{% trans %}General Index{% endtrans %}</a><br/>
+ <span class="linkdescr">{% trans %}all functions, classes, terms{% endtrans %}</span></p>
+ <p class="biglink"><a class="biglink" href="{{ pathto("glossary") }}">{% trans %}Glossary{% endtrans %}</a><br/>
+ <span class="linkdescr">{% trans %}the most important terms explained{% endtrans %}</span></p>
</td><td width="50%">
- <p class="biglink"><a class="biglink" href="{{ pathto("search") }}">Search page</a><br/>
- <span class="linkdescr">search this documentation</span></p>
- <p class="biglink"><a class="biglink" href="{{ pathto("contents") }}">Complete Table of Contents</a><br/>
- <span class="linkdescr">lists all sections and subsections</span></p>
+ <p class="biglink"><a class="biglink" href="{{ pathto("search") }}">{% trans %}Search page{% endtrans %}</a><br/>
+ <span class="linkdescr">{% trans %}search this documentation{% endtrans %}</span></p>
+ <p class="biglink"><a class="biglink" href="{{ pathto("contents") }}">{% trans %}Complete Table of Contents{% endtrans %}</a><br/>
+ <span class="linkdescr">{% trans %}lists all sections and subsections{% endtrans %}</span></p>
</td></tr>
</table>
- <p><strong>Meta information:</strong></p>
+ <p><strong>{% trans %}Meta information:{% endtrans %}</strong></p>
<table class="contentstable" align="center"><tr>
<td width="50%">
- <p class="biglink"><a class="biglink" href="{{ pathto("bugs") }}">Reporting bugs</a></p>
- <p class="biglink"><a class="biglink" href="{{ pathto("about") }}">About the documentation</a></p>
+ <p class="biglink"><a class="biglink" href="{{ pathto("bugs") }}">{% trans %}Reporting bugs{% endtrans %}</a></p>
+ <p class="biglink"><a class="biglink" href="{{ pathto("about") }}">{% trans %}About the documentation{% endtrans %}</a></p>
</td><td width="50%">
- <p class="biglink"><a class="biglink" href="{{ pathto("license") }}">History and License of Python</a></p>
- <p class="biglink"><a class="biglink" href="{{ pathto("copyright") }}">Copyright</a></p>
+ <p class="biglink"><a class="biglink" href="{{ pathto("license") }}">{% trans %}History and License of Python{% endtrans %}</a></p>
+ <p class="biglink"><a class="biglink" href="{{ pathto("copyright") }}">{% trans %}Copyright{% endtrans %}</a></p>
</td></tr>
</table>
{% endblock %}
-<h3>Download</h3>
-<p><a href="{{ pathto('download') }}">Download these documents</a></p>
-<h3>Docs for other versions</h3>
+<h3>{% trans %}Download{% endtrans %}</h3>
+<p><a href="{{ pathto('download') }}">{% trans %}Download these documents{% endtrans %}</a></p>
+<h3>{% trans %}Docs for other versions{% endtrans %}</h3>
<ul>
- <li><a href="https://docs.python.org/2.7/">Python 2.7 (stable)</a></li>
- <li><a href="https://docs.python.org/3.4/">Python 3.4 (stable)</a></li>
- <li><a href="https://www.python.org/doc/versions/">Old versions</a></li>
+ <li><a href="https://docs.python.org/2.7/">{% trans %}Python 2.7 (stable){% endtrans %}</a></li>
+ <li><a href="https://docs.python.org/3.4/">{% trans %}Python 3.4 (stable){% endtrans %}</a></li>
+ <li><a href="https://www.python.org/doc/versions/">{% trans %}Old versions{% endtrans %}</a></li>
</ul>
-<h3>Other resources</h3>
+<h3>{% trans %}Other resources{% endtrans %}</h3>
<ul>
{# XXX: many of these should probably be merged in the main docs #}
- <li><a href="https://www.python.org/dev/peps/">PEP Index</a></li>
- <li><a href="https://wiki.python.org/moin/BeginnersGuide">Beginner's Guide</a></li>
- <li><a href="https://wiki.python.org/moin/PythonBooks">Book List</a></li>
- <li><a href="https://www.python.org/doc/av/">Audio/Visual Talks</a></li>
+ <li><a href="https://www.python.org/dev/peps/">{% trans %}PEP Index{% endtrans %}</a></li>
+ <li><a href="https://wiki.python.org/moin/BeginnersGuide">{% trans %}Beginner's Guide{% endtrans %}</a></li>
+ <li><a href="https://wiki.python.org/moin/PythonBooks">{% trans %}Book List{% endtrans %}</a></li>
+ <li><a href="https://www.python.org/doc/av/">{% trans %}Audio/Visual Talks{% endtrans %}</a></li>
</ul>
<li>
{%- if versionswitcher is defined %}
<span class="version_switcher_placeholder">{{ release }}</span>
- <a href="{{ pathto('index') }}">Documentation</a>{{ reldelim1 }}
+ <a href="{{ pathto('index') }}">{% trans %}Documentation {% endtrans %}</a>{{ reldelim1 }}
{%- else %}
<a href="{{ pathto('index') }}">{{ shorttitle }}</a>{{ reldelim1 }}
{%- endif %}
<link rel="shortcut icon" type="image/png" href="{{ pathto('_static/py.png', 1) }}" />
{% if not embedded %}<script type="text/javascript" src="{{ pathto('_static/copybutton.js', 1) }}"></script>{% endif %}
{% if versionswitcher is defined and not embedded %}<script type="text/javascript" src="{{ pathto('_static/version_switch.js', 1) }}"></script>{% endif %}
- {% if pagename == 'whatsnew/changelog' %}
+ {% if pagename == 'whatsnew/changelog' and not embedded %}
<script type="text/javascript">
$(document).ready(function() {
// add the search form and bind the events
{% endblock %}
{% block footer %}
<div class="footer">
- © <a href="{{ pathto('copyright') }}">Copyright</a> {{ copyright|e }}.
+ © <a href="{{ pathto('copyright') }}">{% trans %}Copyright{% endtrans %}</a> {{ copyright|e }}.
<br />
- The Python Software Foundation is a non-profit corporation.
- <a href="https://www.python.org/psf/donations/">Please donate.</a>
+ {% trans %}The Python Software Foundation is a non-profit corporation.{% endtrans %}
+ <a href="https://www.python.org/psf/donations/">{% trans %}Please donate.{% endtrans %}</a>
<br />
- Last updated on {{ last_updated|e }}.
- <a href="{{ pathto('bugs') }}">Found a bug</a>?
+ {% trans last_updated=last_updated|e %}Last updated on {{ last_updated }}.{% endtrans %}
+ {% trans pathto_bugs=pathto('bugs') %}<a href="{{ pathto_bugs }}">Found a bug</a>?{% endtrans %}
<br />
- Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> {{ sphinx_version|e }}.
+ {% trans sphinx_version=sphinx_version|e %}Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> {{ sphinx_version }}.{% endtrans %}
</div>
{% endblock %}
{% block sidebarsourcelink %}
{%- if show_source and has_source and sourcename %}
<h3>{{ _('This Page') }}</h3>
<ul class="this-page-menu">
- <li><a href="{{ pathto('bugs') }}">Report a Bug</a></li>
+ <li><a href="{{ pathto('bugs') }}">{% trans %}Report a Bug{% endtrans %}</a></li>
<li><a href="{{ pathto('_sources/' + sourcename, true)|e }}"
- rel="nofollow">Show Source</a></li>
+ rel="nofollow">{% trans %}Show Source{% endtrans %}</a></li>
</ul>
{%- endif %}
{% endblock %}
filename = os.environ.get('PYTHONSTARTUP')
if filename and os.path.isfile(filename):
with open(filename) as fobj:
- startup_file = fobj.read()
+ startup_file = fobj.read()
exec(startup_file)
If a name is declared global, then all references and assignments go directly to
the middle scope containing the module's global names. To rebind variables
found outside of the innermost scope, the :keyword:`nonlocal` statement can be
-used; if not declared nonlocal, those variable are read-only (an attempt to
+used; if not declared nonlocal, those variables are read-only (an attempt to
write to such a variable will simply create a *new* local variable in the
innermost scope, leaving the identically named outer variable unchanged).
def scope_test():
def do_local():
spam = "local spam"
+
def do_nonlocal():
nonlocal spam
spam = "nonlocal spam"
+
def do_global():
global spam
spam = "global spam"
+
spam = "test spam"
do_local()
print("After local assignment:", spam)
class MyClass:
"""A simple example class"""
i = 12345
+
def f(self):
return 'hello world'
class C:
f = f1
+
def g(self):
return 'hello world'
+
h = g
Now ``f``, ``g`` and ``h`` are all attributes of class :class:`C` that refer to
class Bag:
def __init__(self):
self.data = []
+
def add(self, x):
self.data.append(x)
+
def addtwice(self, x):
self.add(x)
self.add(x)
class Employee:
pass
- john = Employee() # Create an empty employee record
+ john = Employee() # Create an empty employee record
# Fill the fields of the record
john.name = 'John Doe'
def __init__(self, data):
self.data = data
self.index = len(data)
+
def __iter__(self):
return self
+
def __next__(self):
if self.index == 0:
raise StopIteration
It is simple to write a function that returns a list of the numbers of the
Fibonacci series, instead of printing it::
- >>> def fib2(n): # return Fibonacci series up to n
+ >>> def fib2(n): # return Fibonacci series up to n
... """Return a list containing the Fibonacci series up to n."""
... result = []
... a, b = 0, 1
This creates a function that can be called with fewer arguments than it is
defined to allow. For example::
- def ask_ok(prompt, retries=4, complaint='Yes or no, please!'):
+ def ask_ok(prompt, retries=4, reminder='Please try again!'):
while True:
ok = input(prompt)
if ok in ('y', 'ye', 'yes'):
return False
retries = retries - 1
if retries < 0:
- raise OSError('uncooperative user')
- print(complaint)
+ raise ValueError('invalid user response')
+ print(reminder)
This function can be called in several ways:
keywords rather than positional arguments. ::
>>> def concat(*args, sep="/"):
- ... return sep.join(args)
+ ... return sep.join(args)
...
>>> concat("earth", "mars", "venus")
'earth/mars/venus'
Though tuples may seem similar to lists, they are often used in different
situations and for different purposes.
-Tuples are :term:`immutable`, and usually contain an heterogeneous sequence of
+Tuples are :term:`immutable`, and usually contain a heterogeneous sequence of
elements that are accessed via unpacking (see later in this section) or indexing
(or even by attribute in the case of :func:`namedtuples <collections.namedtuple>`).
Lists are :term:`mutable`, and their elements are usually homogeneous and are
raising it and add any attributes to it as desired. ::
>>> try:
- ... raise Exception('spam', 'eggs')
+ ... raise Exception('spam', 'eggs')
... except Exception as inst:
- ... print(type(inst)) # the exception instance
- ... print(inst.args) # arguments stored in .args
- ... print(inst) # __str__ allows args to be printed directly,
- ... # but may be overridden in exception subclasses
- ... x, y = inst.args # unpack args
- ... print('x =', x)
- ... print('y =', y)
+ ... print(type(inst)) # the exception instance
+ ... print(inst.args) # arguments stored in .args
+ ... print(inst) # __str__ allows args to be printed directly,
+ ... # but may be overridden in exception subclasses
+ ... x, y = inst.args # unpack args
+ ... print('x =', x)
+ ... print('y =', y)
...
<class 'Exception'>
('spam', 'eggs')
If you are a heavy user of floating point operations you should take a look
at the Numerical Python package and many other packages for mathematical and
-statistical operations supplied by the SciPy project. See <http://scipy.org>.
+statistical operations supplied by the SciPy project. See <https://scipy.org>.
Python provides tools that may help on those rare occasions when you really
*do* want to know the exact value of a float. The
``'!a'`` (apply :func:`ascii`), ``'!s'`` (apply :func:`str`) and ``'!r'``
(apply :func:`repr`) can be used to convert the value before it is formatted::
- >>> import math
- >>> print('The value of PI is approximately {}.'.format(math.pi))
- The value of PI is approximately 3.14159265359.
- >>> print('The value of PI is approximately {!r}.'.format(math.pi))
- The value of PI is approximately 3.141592653589793.
+ >>> contents = 'eels'
+ >>> print('My hovercraft is full of {}.'.format(contents))
+ My hovercraft is full of eels.
+ >>> print('My hovercraft is full of {!r}.'.format(contents))
+ My hovercraft is full of 'eels'.
An optional ``':'`` and format specifier can follow the field name. This allows
greater control over how the value is formatted. The following example
``f`` has already been created.
To read a file's contents, call ``f.read(size)``, which reads some quantity of
-data and returns it as a string or bytes object. *size* is an optional numeric
-argument. When *size* is omitted or negative, the entire contents of the file
-will be read and returned; it's your problem if the file is twice as large as
-your machine's memory. Otherwise, at most *size* bytes are read and returned.
+data and returns it as a string (in text mode) or bytes object (in binary mode).
+*size* is an optional numeric argument. When *size* is omitted or negative, the
+entire contents of the file will be read and returned; it's your problem if the
+file is twice as large as your machine's memory. Otherwise, at most *size* bytes
+are read and returned.
If the end of the file has been reached, ``f.read()`` will return an empty
string (``''``). ::
>>> f.write('This is a test\n')
15
-To write something other than a string, it needs to be converted to a string
-first::
+Other types of objects need to be converted -- either to a string (in text mode)
+or a bytes object (in binary mode) -- before writing them::
>>> value = ('the answer', 42)
- >>> s = str(value)
+ >>> s = str(value) # convert the tuple to string
>>> f.write(s)
18
>>> f = open('workfile', 'rb+')
>>> f.write(b'0123456789abcdef')
16
- >>> f.seek(5) # Go to the 6th byte in the file
+ >>> f.seek(5) # Go to the 6th byte in the file
5
>>> f.read(1)
b'5'
- >>> f.seek(-3, 2) # Go to the 3rd byte before the end
+ >>> f.seek(-3, 2) # Go to the 3rd byte before the end
13
>>> f.read(1)
b'd'
bpython_.
-.. _GNU Readline: http://tiswww.case.edu/php/chet/readline/rltop.html
-.. _IPython: http://ipython.scipy.org/
+.. _GNU Readline: https://tiswww.case.edu/php/chet/readline/rltop.html
+.. _IPython: https://ipython.org/
.. _bpython: http://www.bpython-interpreter.org/
This feature is particularly useful when you want to break long strings::
>>> text = ('Put several strings within parentheses '
- 'to have them joined together.')
+ ... 'to have them joined together.')
>>> text
'Put several strings within parentheses to have them joined together.'
Slice indices have useful defaults; an omitted first index defaults to zero, an
omitted second index defaults to the size of the string being sliced. ::
- >>> word[:2] # character from the beginning to position 2 (excluded)
+ >>> word[:2] # character from the beginning to position 2 (excluded)
'Py'
- >>> word[4:] # characters from position 4 (included) to the end
+ >>> word[4:] # characters from position 4 (included) to the end
'on'
- >>> word[-2:] # characters from the second-last (included) to the end
+ >>> word[-2:] # characters from the second-last (included) to the end
'on'
One way to remember how slices work is to think of the indices as pointing
Strings support a large number of methods for
basic transformations and searching.
- :ref:`string-formatting`
- Information about string formatting with :meth:`str.format` is described
- here.
+ :ref:`formatstrings`
+ Information about string formatting with :meth:`str.format`.
:ref:`old-string-formatting`
The old formatting operations invoked when strings and Unicode strings are
a, b = b, a+b
print()
- def fib2(n): # return Fibonacci series up to n
+ def fib2(n): # return Fibonacci series up to n
result = []
a, b = 0, 1
while b < n:
For efficiency reasons, each module is only imported once per interpreter
session. Therefore, if you change your modules, you must restart the
interpreter -- or, if it's just one module you want to test interactively,
- use :func:`imp.reload`, e.g. ``import imp; imp.reload(modulename)``.
+ use :func:`importlib.reload`, e.g. ``import importlib;
+ importlib.reload(modulename)``.
.. _tut-modulesasscripts:
>>> statistics.variance(data)
1.3720238095238095
-The SciPy project <http://scipy.org> has many other modules for numerical
+The SciPy project <https://scipy.org> has many other modules for numerical
computations.
.. _tut-internet-access:
with self.assertRaises(TypeError):
average(20, 30, 70)
- unittest.main() # Calling from the command line invokes all tests
+ unittest.main() # Calling from the command line invokes all tests
.. _tut-batteries-included:
threading.Thread.__init__(self)
self.infile = infile
self.outfile = outfile
+
def run(self):
f = zipfile.ZipFile(self.outfile, 'w', zipfile.ZIP_DEFLATED)
f.write(self.infile)
for download. Once you begin releasing code, you can register it here so that
others can find it.
-* http://code.activestate.com/recipes/langs/python/: The Python Cookbook is a
+* https://code.activestate.com/recipes/langs/python/: The Python Cookbook is a
sizable collection of code examples, larger modules, and useful scripts.
Particularly notable contributions are collected in a book also titled Python
Cookbook (O'Reilly & Associates, ISBN 0-596-00797-3.)
* http://www.pyvideo.org collects links to Python-related videos from
conferences and user-group meetings.
-* http://scipy.org: The Scientific Python project includes modules for fast
+* https://scipy.org: The Scientific Python project includes modules for fast
array computations and manipulations plus a host of packages for such
things as linear algebra, Fourier transforms, non-linear solvers,
random number distributions, statistical analysis and the like.
the :mod:`__main__` module.
Since the argument is a *module* name, you must not give a file extension
- (``.py``). The ``module-name`` should be a valid Python module name, but
+ (``.py``). The module name should be a valid absolute Python module name, but
the implementation may not always enforce this (e.g. it may allow you to
use a name that includes a hyphen).
:class:`str` or :class:`bytes` with :class:`int`. Issue an error when the
option is given twice (:option:`-bb`).
- .. versionchanged: 3.5
+ .. versionchanged:: 3.5
Affects comparisons of :class:`bytes` with :class:`int`.
.. cmdoption:: -B
tracing with a traceback limit of *NFRAME* frames. See the
:func:`tracemalloc.start` for more information.
- It also allows to pass arbitrary values and retrieve them through the
+ It also allows passing arbitrary values and retrieving them through the
:data:`sys._xoptions` dictionary.
.. versionchanged:: 3.2
What you get after installing is a number of things:
-* A :file:`MacPython 3.4` folder in your :file:`Applications` folder. In here
+* A :file:`MacPython 3.5` folder in your :file:`Applications` folder. In here
you find IDLE, the development environment that is a standard part of official
Python distributions; PythonLauncher, which handles double-clicking Python
scripts from the Finder; and the "Build Applet" tool, which allows you to
:program:`emacs` among them. If you want a more Mac-like editor,
:program:`BBEdit` or :program:`TextWrangler` from Bare Bones Software (see
http://www.barebones.com/products/bbedit/index.html) are good choices, as is
-:program:`TextMate` (see http://macromates.com/). Other editors include
+:program:`TextMate` (see https://macromates.com/). Other editors include
:program:`Gvim` (http://macvim.org) and :program:`Aquamacs`
(http://aquamacs.org/).
anything that has a GUI) need to be run in a special way. Use :program:`pythonw`
instead of :program:`python` to start such scripts.
-With Python 3.4, you can use either :program:`python` or :program:`pythonw`.
+With Python 3.5, you can use either :program:`python` or :program:`pythonw`.
Configuration
available from https://pythonhosted.org/pyobjc/.
The standard Python GUI toolkit is :mod:`tkinter`, based on the cross-platform
-Tk toolkit (http://www.tcl.tk). An Aqua-native version of Tk is bundled with OS
+Tk toolkit (https://www.tcl.tk). An Aqua-native version of Tk is bundled with OS
X by Apple, and the latest version can be downloaded and installed from
-http://www.activestate.com; it can also be built from source.
+https://www.activestate.com; it can also be built from source.
*wxPython* is another popular cross-platform GUI toolkit that runs natively on
Mac OS X. Packages and documentation are available from http://www.wxpython.org.
*PyQt* is another popular cross-platform GUI toolkit that runs natively on Mac
OS X. More information can be found at
-http://www.riverbankcomputing.co.uk/software/pyqt/intro.
+https://riverbankcomputing.com/software/pyqt/intro.
Distributing Python Applications on the Mac
===========================================
-The "Build Applet" tool that is placed in the MacPython 3.4 folder is fine for
+The "Build Applet" tool that is placed in the MacPython 3.5 folder is fine for
packaging small Python scripts on your own machine to run as a standard Mac
application. This tool, however, is not robust enough to distribute Python
applications to other users.
.. seealso::
- http://www.debian.org/doc/manuals/maint-guide/first.en.html
+ https://www.debian.org/doc/manuals/maint-guide/first.en.html
for Debian users
- http://en.opensuse.org/Portal:Packaging
+ https://en.opensuse.org/Portal:Packaging
for OpenSuse users
- http://docs.fedoraproject.org/en-US/Fedora_Draft_Documentation/0.1/html/RPM_Guide/ch-creating-rpms.html
+ https://docs.fedoraproject.org/en-US/Fedora_Draft_Documentation/0.1/html/RPM_Guide/ch-creating-rpms.html
for Fedora users
http://www.slackbook.org/html/package-management-making-packages.html
for Slackware users
On OpenSolaris
--------------
-You can get Python from `OpenCSW <http://www.opencsw.org/>`_. Various versions
+You can get Python from `OpenCSW <https://www.opencsw.org/>`_. Various versions
of Python are available and can be installed with e.g. ``pkgutil -i python27``.
===============
If you want to compile CPython yourself, first thing you should do is get the
-`source <https://www.python.org/download/source/>`_. You can download either the
+`source <https://www.python.org/downloads/source/>`_. You can download either the
latest release's source or just grab a fresh `clone
<https://docs.python.org/devguide/setup.html#getting-the-source-code>`_. (If you want
to contribute patches, you will need a clone.)
information on how to code in Python in these editors, look at:
* http://www.vim.org/scripts/script.php?script_id=790
-* http://sourceforge.net/projects/python-mode
+* https://sourceforge.net/projects/python-mode
Geany is an excellent IDE with support for a lot of languages. For more
-information, read: http://www.geany.org/
+information, read: https://www.geany.org/
Komodo edit is another extremely good IDE. It also has support for a lot of
-languages. For more information, read http://komodoide.com/.
+languages. For more information, read https://komodoide.com/.
.. seealso::
`Python Packaging User Guide: Creating and using virtual environments
- <https://packaging.python.org/en/latest/installing.html#virtual-environments>`__
+ <https://packaging.python.org/en/latest/installing/#creating-virtual-environments>`__
.. highlight:: none
The command, if run with ``-h``, will show the available options::
- usage: venv [-h] [--system-site-packages] [--symlinks] [--clear]
- [--upgrade] [--without-pip] ENV_DIR [ENV_DIR ...]
+ usage: venv [-h] [--system-site-packages] [--symlinks | --copies] [--clear]
+ [--upgrade] [--without-pip]
+ ENV_DIR [ENV_DIR ...]
Creates virtual Python environments in one or more target directories.
optional arguments:
-h, --help show this help message and exit
- --system-site-packages Give access to the global site-packages dir to the
- virtual environment.
+ --system-site-packages Give the virtual environment access to the system
+ site-packages dir.
--symlinks Try to use symlinks rather than copies, when symlinks
are not the default for the platform.
--copies Try to use copies rather than symlinks, even when
symlinks are the default for the platform.
- --clear Delete the environment directory if it already exists.
- If not specified and the directory exists, an error is
- raised.
+ --clear Delete the contents of the environment directory if it
+ already exists, before environment creation.
--upgrade Upgrade the environment directory to use this version
of Python, assuming Python has been upgraded in-place.
--without-pip Skips installing or upgrading pip in the virtual
+-------------+-----------------+-----------------------------------------+
| | csh/tcsh | $ source <venv>/bin/activate.csh |
+-------------+-----------------+-----------------------------------------+
-| Windows | cmd.exe | C:\> <venv>/Scripts/activate.bat |
+| Windows | cmd.exe | C:\> <venv>\Scripts\activate.bat |
+-------------+-----------------+-----------------------------------------+
-| | PowerShell | PS C:\> <venv>/Scripts/Activate.ps1 |
+| | PowerShell | PS C:\> <venv>\Scripts\Activate.ps1 |
+-------------+-----------------+-----------------------------------------+
You don't specifically *need* to activate an environment; activation just
able to install for all users of a single machine, and a separate ZIP file is
available for application-local distributions.
+Supported Versions
+------------------
+
+As specified in :pep:`11`, a Python release only supports a Windows platform
+while Microsoft considers the platform under extended support. This means that
+Python 3.5 supports Windows Vista and newer. If you require Windows XP support
+then please install Python 3.4.
+
Installation Steps
------------------
You may also specify the ``/quiet`` option to hide the progress display.
+Modifying an install
+--------------------
+
+Once Python has been installed, you can add or remove features through the
+Programs and Features tool that is part of Windows. Select the Python entry and
+choose "Uninstall/Change" to open the installer in maintenance mode.
+
+"Modify" allows you to add or remove features by modifying the checkboxes -
+unchanged checkboxes will not install or remove anything. Some options cannot be
+changed in this mode, such as the install directory; to modify these, you will
+need to remove and then reinstall Python completely.
+
+"Repair" will verify all the files that should be installed using the current
+settings and replace any that have been removed or modified.
+
+"Uninstall" will remove Python entirely, with the exception of the
+:ref:`launcher`, which has its own entry in Programs and Features.
Other Platforms
---------------
Check :pep:`11` for details on all unsupported platforms.
* `Windows CE <http://pythonce.sourceforge.net/>`_ is still supported.
-* The `Cygwin <http://cygwin.com/>`_ installer offers to install the Python
+* The `Cygwin <https://cygwin.com/>`_ installer offers to install the Python
interpreter as well (cf. `Cygwin package source
<ftp://ftp.uni-erlangen.de/pub/pc/gnuwin32/cygwin/mirrors/cygnus/
release/python>`_, `Maintainer releases
<http://www.tishler.net/jason/software/python/>`_)
-See `Python for Windows <https://www.python.org/download/windows/>`_
+See `Python for Windows <https://www.python.org/downloads/windows/>`_
for detailed information about platforms with pre-compiled installers.
.. seealso::
- `Python on XP <http://www.richarddooling.com/index.php/2006/03/14/python-on-xp-7-minutes-to-hello-world/>`_
+ `Python on XP <http://dooling.com/index.php/2006/03/14/python-on-xp-7-minutes-to-hello-world/>`_
"7 Minutes to "Hello World!""
by Richard Dooling, 2006
by Mark Pilgrim, 2004,
ISBN 1-59059-356-1
- `For Windows users <http://www.swaroopch.com/notes/python/#install_windows>`_
+ `For Windows users <http://python.swaroopch.com/installation.html#installation-on-windows>`_
in "Installing Python"
- in "`A Byte of Python <http://www.swaroopch.com/notes/python/>`_"
+ in "`A Byte of Python <http://python.swaroopch.com/>`_"
by Swaroop C H, 2003
additional functionality. The following is a list of popular versions and their
key features:
-`ActivePython <http://www.activestate.com/activepython/>`_
+`ActivePython <https://www.activestate.com/activepython/>`_
Installer with multi-platform compatibility, documentation, PyWin32
-`Anaconda <http://www.continuum.io/downloads/>`_
+`Anaconda <https://www.continuum.io/downloads/>`_
Popular scientific modules (such as numpy, scipy and pandas) and the
``conda`` package manager.
.. seealso::
- http://support.microsoft.com/kb/100843
+ https://support.microsoft.com/kb/100843
Environment variables in Windows NT
- http://technet.microsoft.com/en-us/library/cc754250.aspx
+ https://technet.microsoft.com/en-us/library/cc754250.aspx
The SET command, for temporarily modifying environment variables
- http://technet.microsoft.com/en-us/library/cc755104.aspx
+ https://technet.microsoft.com/en-us/library/cc755104.aspx
The SETX command, for permanently modifying environment variables
- http://support.microsoft.com/kb/310519
+ https://support.microsoft.com/kb/310519
How To Manage Environment Variables in Windows XP
- http://www.chem.gla.ac.uk/~louis/software/faq/q1.html
+ https://www.chem.gla.ac.uk/~louis/software/faq/q1.html
Setting Environment variables, Louis J. Farrugia
.. _windows-path-mod:
PyWin32
-------
-The `PyWin32 <http://python.net/crew/mhammond/win32/>`_ module by Mark Hammond
+The `PyWin32 <https://pypi.python.org/pypi/pywin32>`_ module by Mark Hammond
is a collection of modules for advanced Windows-specific support. This includes
utilities for:
-* `Component Object Model <http://www.microsoft.com/com/>`_ (COM)
+* `Component Object Model <https://www.microsoft.com/com/>`_ (COM)
* Win32 API calls
* Registry
* Event log
-* `Microsoft Foundation Classes <http://msdn.microsoft.com/en-us/library/fe1cf721%28VS.80%29.aspx>`_ (MFC)
+* `Microsoft Foundation Classes <https://msdn.microsoft.com/en-us/library/fe1cf721%28VS.80%29.aspx>`_ (MFC)
user interfaces
-`PythonWin <http://web.archive.org/web/20060524042422/
+`PythonWin <https://web.archive.org/web/20060524042422/
https://www.python.org/windows/pythonwin/>`_ is a sample MFC application
shipped with PyWin32. It is an embeddable IDE with a built-in debugger.
===========================
If you want to compile CPython yourself, first thing you should do is get the
-`source <https://www.python.org/download/source/>`_. You can download either the
+`source <https://www.python.org/downloads/source/>`_. You can download either the
latest release's source or just grab a fresh `checkout
<https://docs.python.org/devguide/setup.html#getting-the-source-code>`_.
.. note::
The embedded distribution does not include the `Microsoft C Runtime
- <http://www.microsoft.com/en-us/download/details.aspx?id=48145>`_ and it is
+ <https://www.microsoft.com/en-us/download/details.aspx?id=48145>`_ and it is
the responsibility of the application installer to provide this. The
runtime may have already been installed on a user's system previously or
automatically via Windows Update, and can be detected by finding
made available by SourceForge for storing source code, tracking bug reports,
and managing the queue of patch submissions. To report bugs or submit patches
for Python 2.0, use the bug tracking and patch manager tools available from
-Python's project page, located at http://sourceforge.net/projects/python/.
+Python's project page, located at https://sourceforge.net/projects/python/.
The most important of the services now hosted at SourceForge is the Python CVS
tree, the version-controlled repository containing the source code for Python.
Read the rest of PEP 1 for the details of the PEP editorial process, style, and
format. PEPs are kept in the Python CVS tree on SourceForge, though they're not
part of the Python 2.0 distribution, and are also available in HTML form from
-https://www.python.org/peps/. As of September 2000, there are 25 PEPS, ranging
+https://www.python.org/dev/peps/. As of September 2000, there are 25 PEPS, ranging
from PEP 201, "Lockstep Iteration", to PEP 225, "Elementwise/Objectwise
Operators".
[ (x,y) for x in seq1 for y in seq2]
The idea of list comprehensions originally comes from the functional programming
-language Haskell (http://www.haskell.org). Greg Ewing argued most effectively
+language Haskell (https://www.haskell.org). Greg Ewing argued most effectively
for adding them to Python and wrote the initial list comprehension patch, which
was then discussed for a seemingly endless time on the python-dev mailing list
and kept up-to-date by Skip Montanaro.
using Python 2.1, since a new release of the Distutils will be made for users of
earlier Python versions. Version 1.0.2 of the Distutils includes the changes
described in PEP 241, as well as various bugfixes and enhancements. It will be
-available from the Distutils SIG at https://www.python.org/sigs/distutils-sig/.
+available from the Distutils SIG at https://www.python.org/community/sigs/current/distutils-sig/.
.. seealso::
...
For a fuller discussion of the line I/O changes, see the python-dev summary for
- January 1-15, 2001 at https://www.python.org/dev/summary/2001-01-1/.
+ January 1-15, 2001 at https://mail.python.org/pipermail/python-dev/2001-January/.
* A new method, :meth:`popitem`, was added to dictionaries to enable
destructively iterating through the contents of a dictionary; this can be faster
This article doesn't attempt to provide a complete specification of the new
features, but instead provides a convenient overview. For full details, you
should refer to the documentation for Python 2.2, such as the `Python Library
-Reference <https://www.python.org/doc/2.2/lib/lib.html>`_ and the `Python
-Reference Manual <https://www.python.org/doc/2.2/ref/ref.html>`_. If you want to
+Reference <https://docs.python.org/2.2/lib/lib.html>`_ and the `Python
+Reference Manual <https://docs.python.org/2.2/ref/ref.html>`_. If you want to
understand the complete implementation and design rationale for a change, refer
to the PEP for a particular new feature.
of an explanation to start you programming, but many details have been
simplified or ignored. Where should you go to get a more complete picture?
-https://www.python.org/2.2/descrintro.html is a lengthy tutorial introduction to
+https://docs.python.org/dev/howto/descriptor.html is a lengthy tutorial introduction to
the descriptor features, written by Guido van Rossum. If my description has
whetted your appetite, go read this tutorial next, because it goes into much
more detail about the new features while still remaining quite easy to read.
every square of an $NxN$ chessboard without visiting any square twice).
The idea of generators comes from other programming languages, especially Icon
-(http://www.cs.arizona.edu/icon/), where the idea of generators is central. In
+(https://www.cs.arizona.edu/icon/), where the idea of generators is central. In
Icon, every expression and function call behaves like a generator. One example
from "An Overview of the Icon Programming Language" at
-http://www.cs.arizona.edu/icon/docs/ipd266.htm gives an idea of what this looks
+https://www.cs.arizona.edu/icon/docs/ipd266.htm gives an idea of what this looks
like::
sentence := "Store it in the neighboring harbor"
(The controversy is over whether this is *really* a design flaw, and whether
it's worth breaking existing code to fix this. It's caused endless discussions
-on python-dev, and in July 2001 erupted into an storm of acidly sarcastic
+on python-dev, and in July 2001 erupted into a storm of acidly sarcastic
postings on :newsgroup:`comp.lang.python`. I won't argue for either side here
and will stick to describing what's implemented in 2.2. Read :pep:`238` for a
summary of arguments and counter-arguments.)
operators.
* Python 2.2 supports some command-line arguments for testing whether code will
- works with the changed division semantics. Running python with :option:`-Q
+ work with the changed division semantics. Running python with :option:`-Q
warn` will cause a warning to be issued whenever division is applied to two
integers. You can use this to find code that's affected by the change and fix
it. By default, Python 2.2 will simply perform classic division without a
every square of an $NxN$ chessboard without visiting any square twice).
The idea of generators comes from other programming languages, especially Icon
-(http://www.cs.arizona.edu/icon/), where the idea of generators is central. In
+(https://www.cs.arizona.edu/icon/), where the idea of generators is central. In
Icon, every expression and function call behaves like a generator. One example
from "An Overview of the Icon Programming Language" at
-http://www.cs.arizona.edu/icon/docs/ipd266.htm gives an idea of what this looks
+https://www.cs.arizona.edu/icon/docs/ipd266.htm gives an idea of what this looks
like::
sentence := "Store it in the neighboring harbor"
* A new warning, :exc:`PendingDeprecationWarning` was added to indicate features
which are in the process of being deprecated. The warning will *not* be printed
by default. To check for use of features that will be deprecated in the future,
- supply :option:`-Walways::PendingDeprecationWarning::` on the command line or
+ supply :option:`-Walways::PendingDeprecationWarning:: <-W>` on the command line or
use :func:`warnings.filterwarnings`.
* The process of deprecating string-based exceptions, as in ``raise "Error
hierarchy. Classic classes are unaffected by this change. Python 2.2
originally used a topological sort of a class's ancestors, but 2.3 now uses the
C3 algorithm as described in the paper `"A Monotonic Superclass Linearization
- for Dylan" <http://www.webcom.com/haahr/dylan/linearization-oopsla96.html>`_. To
+ for Dylan" <http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.19.3910>`_. To
understand the motivation for this change, read Michele Simionato's article
- `"Python 2.3 Method Resolution Order" <https://www.python.org/2.3/mro.html>`_, or
+ `"Python 2.3 Method Resolution Order" <http://www.phyast.pitt.edu/~micheles/mro.html>`_, or
read the thread on python-dev starting with the message at
https://mail.python.org/pipermail/python-dev/2002-October/029035.html. Samuele
Pedroni first pointed out the problem and also implemented the fix by coding the
partially sorted order such that, for every index *k*, ``heap[k] <=
heap[2*k+1]`` and ``heap[k] <= heap[2*k+2]``. This makes it quick to remove the
smallest item, and inserting a new item while maintaining the heap property is
- O(lg n). (See http://www.nist.gov/dads/HTML/priorityque.html for more
+ O(lg n). (See https://xlinux.nist.gov/dads//HTML/priorityque.html for more
information about the priority queue data structure.)
The :mod:`heapq` module provides :func:`heappush` and :func:`heappop` functions
The :mod:`getopt` module provides simple parsing of command-line arguments. The
new :mod:`optparse` module (originally named Optik) provides more elaborate
command-line parsing that follows the Unix conventions, automatically creates
-the output for :option:`--help`, and can perform different actions for different
+the output for :option:`!--help`, and can perform different actions for different
options.
You start by creating an instance of :class:`OptionParser` and telling it what
.. seealso::
- https://svn.python.org/view/python/trunk/Objects/obmalloc.c
+ https://hg.python.org/cpython/file/default/Objects/obmalloc.c
For the full details of the pymalloc implementation, see the comments at
the top of the file :file:`Objects/obmalloc.c` in the Python source code.
The above link points to the file within the python.org SVN browser.
source distribution, were updated for 2.3. (Contributed by Sean Reifschneider.)
Other new platforms now supported by Python include AtheOS
-(http://www.atheos.cx/), GNU/Hurd, and OpenVMS.
+(http://atheos.cx/), GNU/Hurd, and OpenVMS.
.. ======================================================================
the Python program as part of its execution.
* The :file:`regrtest.py` script now provides a way to allow "all resources
- except *foo*." A resource name passed to the :option:`-u` option can now be
+ except *foo*." A resource name passed to the :option:`!-u` option can now be
prefixed with a hyphen (``'-'``) to mean "remove this resource." For example,
the option '``-uall,-bsddb``' could be used to enable the use of all resources
except ``bsddb``.
wrote patches implementing function decorators, but the one that was actually
checked in was patch #979728, written by Mark Russell.
- https://www.python.org/moin/PythonDecoratorLibrary
+ https://wiki.python.org/moin/PythonDecoratorLibrary
This Wiki page contains several examples of decorators.
.. ======================================================================
The article uses Fortran code to illustrate many of the problems that floating-
point inaccuracy can cause.
- http://www2.hursley.ibm.com/decimal/
+ http://speleotrove.com/decimal/
A description of a decimal-based representation. This representation is being
proposed as a standard, and underlies the new Python decimal type. Much of this
material was written by Mike Cowlishaw, designer of the Rexx language.
:c:type:`double` to an ASCII string.
The code for these functions came from the GLib library
-(http://library.gnome.org/devel/glib/stable/), whose developers kindly
+(https://developer.gnome.org/glib/stable/), whose developers kindly
relicensed the relevant functions and donated them to the Python Software
Foundation. The :mod:`locale` module can now change the numeric locale,
letting extensions such as GTK+ produce the correct results.
* Python can now be built with additional profiling for the interpreter itself,
intended as an aid to people developing the Python core. Providing
- :option:`----enable-profiling` to the :program:`configure` script will let you
+ :option:`--enable-profiling` to the :program:`configure` script will let you
profile the interpreter with :program:`gprof`, and providing the
- :option:`----with-tsc` switch enables profiling using the Pentium's Time-Stamp-
- Counter register. Note that the :option:`----with-tsc` switch is slightly
+ :option:`--with-tsc` switch enables profiling using the Pentium's Time-Stamp-
+ Counter register. Note that the :option:`--with-tsc` switch is slightly
misnamed, because the profiling feature also works on the PowerPC platform,
though that processor architecture doesn't call that register "the TSC
register". (Contributed by Jeremy Hylton.)
:pep:`328` - Imports: Multi-Line and Absolute/Relative
PEP written by Aahz; implemented by Thomas Wouters.
- http://codespeak.net/py/current/doc/index.html
+ https://pylib.readthedocs.org/
The py library by Holger Krekel, which contains the :mod:`py.std` package.
.. ======================================================================
Earlier versions of these features were proposed in :pep:`288` by Raymond
Hettinger and :pep:`325` by Samuele Pedroni.
- http://en.wikipedia.org/wiki/Coroutine
+ https://en.wikipedia.org/wiki/Coroutine
The Wikipedia entry for coroutines.
http://www.sidhe.org/~dan/blog/archives/000178.html
log all the paths searched. In Python 2.5, a new :exc:`ImportWarning` warning is
triggered when an import would have picked up a directory as a package but no
:file:`__init__.py` was found. This warning is silently ignored by default;
- provide the :option:`-Wd` option when running the Python executable to display
+ provide the :option:`-Wd <-W>` option when running the Python executable to display
the warning message. (Implemented by Thomas Wouters.)
* The list of base classes in a class definition can now be empty. As an
Georg Brandl.)
The Python executable now accepts the standard long options :option:`--help`
-and :option:`--version`; on Windows, it also accepts the :option:`/?` option
+and :option:`--version`; on Windows, it also accepts the :option:`/? <-?>` option
for displaying a help message. (Implemented by Georg Brandl.)
.. ======================================================================
* The :mod:`socket` module now supports :const:`AF_NETLINK` sockets on Linux,
thanks to a patch from Philippe Biondi. Netlink sockets are a Linux-specific
mechanism for communications between a user-space process and kernel code; an
- introductory article about them is at http://www.linuxjournal.com/article/7356.
+ introductory article about them is at https://www.linuxjournal.com/article/7356.
In Python code, netlink addresses are represented as a tuple of 2 integers,
``(pid, group_mask)``.
* The :mod:`webbrowser` module received a number of enhancements. It's now
usable as a script with ``python -m webbrowser``, taking a URL as the argument;
there are a number of switches to control the behaviour (:option:`-n` for a new
- browser window, :option:`-t` for a new tab). New module-level functions,
+ browser window, :option:`!-t` for a new tab). New module-level functions,
:func:`open_new` and :func:`open_new_tab`, were added to support this. The
module's :func:`open` function supports an additional feature, an *autoraise*
parameter that signals whether to raise the open window when possible. A number
>>>
For more information about the SQL dialect supported by SQLite, see
-http://www.sqlite.org.
+https://www.sqlite.org.
.. seealso::
http://www.pysqlite.org
The pysqlite web page.
- http://www.sqlite.org
+ https://www.sqlite.org
The SQLite web page; the documentation describes the syntax and the available
data types for the supported SQL dialect.
provided the results of their examination of the Python source code. The
analysis found about 60 bugs that were quickly fixed. Many of the bugs were
refcounting problems, often occurring in error-handling code. See
- http://scan.coverity.com for the statistics.
+ https://scan.coverity.com for the statistics.
* The largest change to the C API came from :pep:`353`, which modifies the
interpreter to use a :c:type:`Py_ssize_t` type definition instead of
therefore posted a call for issue trackers, asking volunteers to set
up different products and import some of the bugs and patches from
SourceForge. Four different trackers were examined: `Jira
-<http://www.atlassian.com/software/jira/>`__,
-`Launchpad <http://www.launchpad.net>`__,
+<https://www.atlassian.com/software/jira/>`__,
+`Launchpad <https://launchpad.net/>`__,
`Roundup <http://roundup.sourceforge.net/>`__, and
-`Trac <http://trac.edgewall.org/>`__.
+`Trac <https://trac.edgewall.org/>`__.
The committee eventually settled on Jira
and Roundup as the two candidates. Jira is a commercial product that
offers no-cost hosted instances to free-software projects; Roundup
During the 2.6 development cycle, Georg Brandl put a lot of effort
into building a new toolchain for processing the documentation. The
resulting package is called Sphinx, and is available from
-http://sphinx.pocoo.org/.
+http://sphinx-doc.org/.
Sphinx concentrates on HTML output, producing attractively styled and
modern HTML; printed output is still supported through conversion to
:pep:`3141` - A Type Hierarchy for Numbers
PEP written by Jeffrey Yasskin.
- `Scheme's numerical tower <http://www.gnu.org/software/guile/manual/html_node/Numerical-Tower.html#Numerical-Tower>`__, from the Guile manual.
+ `Scheme's numerical tower <https://www.gnu.org/software/guile/manual/html_node/Numerical-Tower.html#Numerical-Tower>`__, from the Guile manual.
`Scheme's number datatypes <http://schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-9.html#%_sec_6.2>`__ from the R5RS Scheme specification.
* The :mod:`bsddb` module also has a new maintainer, Jesús Cea Avión, and the package
is now available as a standalone package. The web page for the package is
`www.jcea.es/programacion/pybsddb.htm
- <http://www.jcea.es/programacion/pybsddb.htm>`__.
+ <https://www.jcea.es/programacion/pybsddb.htm>`__.
The plan is to remove the package from the standard library
in Python 3.0, because its pace of releases is much more frequent than
Python's.
the left to six places. (Contributed by Skip Montanaro; :issue:`1158`.)
* The :mod:`decimal` module was updated to version 1.66 of
- `the General Decimal Specification <http://www2.hursley.ibm.com/decimal/decarith.html>`__. New features
+ `the General Decimal Specification <http://speleotrove.com/decimal/decarith.html>`__. New features
include some methods for some basic mathematical functions such as
:meth:`exp` and :meth:`log10`::
Bill Janssen made extensive improvements to Python 2.6's support for
the Secure Sockets Layer by adding a new module, :mod:`ssl`, that's
-built atop the `OpenSSL <http://www.openssl.org/>`__ library.
+built atop the `OpenSSL <https://www.openssl.org/>`__ library.
This new module provides more control over the protocol negotiated,
the X.509 certificates used, and has better support for writing SSL
servers (as opposed to clients) in Python. The existing SSL support
:func:`macostools.touched` function to be removed because it depended on the
:mod:`macfs` module. (:issue:`1490190`)
-* Many other Mac OS modules have been deprecated and will removed in
+* Many other Mac OS modules have been deprecated and will be removed in
Python 3.0:
:mod:`_builtinSuites`,
:mod:`aepack`,
The :class:`memoryview` object provides a view of another object's
memory content that matches the :class:`bytes` type's interface.
+.. doctest::
+ :options: +SKIP
+
>>> import string
>>> m = memoryview(string.letters)
>>> m
The content of the view can be converted to a string of bytes or
a list of integers:
+.. doctest::
+ :options: +SKIP
+
>>> m2.tobytes()
'abcdefghijklmnopqrstuvwxyz'
>>> m2.tolist()
:class:`memoryview` objects allow modifying the underlying object if
it's a mutable object.
+.. doctest::
+ :options: +SKIP
+
>>> m2[0] = 75
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
``{}`` continues to represent an empty dictionary; use
``set()`` for an empty set.
+ .. doctest::
+ :options: +SKIP
+
>>> {1, 2, 3, 4, 5}
set([1, 2, 3, 4, 5])
>>> set() # empty set
3.x, generalizing list/generator comprehensions to use
the literal syntax for sets and dictionaries.
+ .. doctest::
+ :options: +SKIP
+
>>> {x: x*x for x in range(6)}
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
>>> {('a'*x) for x in range(6)}
* Updated module: the :mod:`bsddb` module has been updated from 4.7.2devel9
to version 4.8.4 of
- `the pybsddb package <http://www.jcea.es/programacion/pybsddb.htm>`__.
+ `the pybsddb package <https://www.jcea.es/programacion/pybsddb.htm>`__.
The new version features better Python 3.x compatibility, various bug fixes,
and adds several new BerkeleyDB flags and methods.
(Updated by Jesús Cea Avión; :issue:`8156`. The pybsddb
>>> for letter in 'here is a sample of english text':
... c[letter] += 1
...
- >>> c
+ >>> c # doctest: +SKIP
Counter({' ': 6, 'e': 5, 's': 3, 'a': 2, 'i': 2, 'h': 2,
'l': 2, 't': 2, 'g': 1, 'f': 1, 'm': 1, 'o': 1, 'n': 1,
'p': 1, 'r': 1, 'x': 1})
* The :mod:`ctypes` module now always converts ``None`` to a C NULL
pointer for arguments declared as pointers. (Changed by Thomas
Heller; :issue:`4606`.) The underlying `libffi library
- <http://sourceware.org/libffi/>`__ has been updated to version
+ <https://sourceware.org/libffi/>`__ has been updated to version
3.0.9, containing various fixes for different platforms. (Updated
by Matthias Klose; :issue:`8142`.)
(Contributed by Kristján Valur Jónsson; :issue:`6192` and :issue:`6267`.)
* Updated module: the :mod:`sqlite3` module has been updated to
- version 2.6.0 of the `pysqlite package <http://code.google.com/p/pysqlite/>`__. Version 2.6.0 includes a number of bugfixes, and adds
+ version 2.6.0 of the `pysqlite package <https://github.com/ghaering/pysqlite>`__. Version 2.6.0 includes a number of bugfixes, and adds
the ability to load SQLite extensions from shared libraries.
Call the ``enable_load_extension(True)`` method to enable extensions,
and then call :meth:`~sqlite3.Connection.load_extension` to load a particular shared library.
*ciphers* argument that's a string listing the encryption algorithms
to be allowed; the format of the string is described
`in the OpenSSL documentation
- <http://www.openssl.org/docs/apps/ciphers.html#CIPHER_LIST_FORMAT>`__.
+ <https://www.openssl.org/docs/apps/ciphers.html#CIPHER-LIST-FORMAT>`__.
(Added by Antoine Pitrou; :issue:`8322`.)
Another change makes the extension load all of OpenSSL's ciphers and
worked around the old behaviour. For example, Python 2.6.4 or 2.5
will return the following:
+ .. doctest::
+ :options: +SKIP
+
>>> import urlparse
>>> urlparse.urlsplit('invented://host/filename?query')
('invented', '', '//host/filename?query', '', '')
Python 2.7 (and Python 2.6.5) will return:
+ .. doctest::
+ :options: +SKIP
+
>>> import urlparse
>>> urlparse.urlsplit('invented://host/filename?query')
('invented', 'host', '/filename?query', '', '')
returns a named tuple instead of a standard tuple.)
The :mod:`urlparse` module also supports IPv6 literal addresses as defined by
- :rfc:`2732` (contributed by Senthil Kumaran; :issue:`2987`). ::
+ :rfc:`2732` (contributed by Senthil Kumaran; :issue:`2987`).
+
+ .. doctest::
+ :options: +SKIP
>>> urlparse.urlparse('http://[1080::8:800:200C:417A]/foo')
ParseResult(scheme='http', netloc='[1080::8:800:200C:417A]',
To learn more, read the :mod:`ttk` module documentation. You may also
wish to read the Tcl/Tk manual page describing the
Ttk theme engine, available at
-http://www.tcl.tk/man/tcl8.5/TkCmd/ttk_intro.htm. Some
+https://www.tcl.tk/man/tcl8.5/TkCmd/ttk_intro.htm. Some
screenshots of the Python/Ttk code in use are at
http://code.google.com/p/python-ttk/wiki/Screenshots.
The :func:`~unittest.main` function supports some other new options:
-* :option:`-b` or :option:`--buffer` will buffer the standard output
+* :option:`-b <unittest -b>` or :option:`--buffer` will buffer the standard output
and standard error streams during each test. If the test passes,
any resulting output will be discarded; on failure, the buffered
output will be displayed.
-* :option:`-c` or :option:`--catch` will cause the control-C interrupt
+* :option:`-c <unittest -c>` or :option:`--catch` will cause the control-C interrupt
to be handled more gracefully. Instead of interrupting the test
process immediately, the currently running test will be completed
and then the partial results up to the interruption will be reported.
:func:`~unittest.removeHandler` decorator that can be used to mark tests that
should have the control-C handling disabled.
-* :option:`-f` or :option:`--failfast` makes
+* :option:`-f <unittest -f>` or :option:`--failfast` makes
test execution stop immediately when a test fails instead of
continuing to execute further tests. (Suggested by Cliff Dyer and
implemented by Michael Foord; :issue:`8074`.)
* The latest release of the GNU Debugger, GDB 7, can be `scripted
using Python
- <http://sourceware.org/gdb/current/onlinedocs/gdb/Python.html>`__.
+ <https://sourceware.org/gdb/current/onlinedocs/gdb/Python.html>`__.
When you begin debugging an executable program P, GDB will look for
a file named ``P-gdb.py`` and automatically read it. Dave Malcolm
contributed a :file:`python-gdb.py` that adds a number of
with *updatepath* set to false.
Security issue reported as `CVE-2008-5983
- <http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2008-5983>`_;
+ <https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2008-5983>`_;
discussed in :issue:`5753`, and fixed by Antoine Pitrou.
* New macros: the Python header files now define the following macros:
takes an integer specifying how many tests run in parallel. This
allows reducing the total runtime on multi-core machines.
This option is compatible with several other options, including the
- :option:`-R` switch which is known to produce long runtimes.
+ :option:`!-R` switch which is known to produce long runtimes.
(Added by Antoine Pitrou, :issue:`6152`.) This can also be used
with a new :option:`-F` switch that runs selected tests in a loop
until they fail. (Added by Antoine Pitrou; :issue:`7312`.)
worked around the old behaviour. For example, Python 2.6.4 or 2.5
will return the following:
+ .. doctest::
+ :options: +SKIP
+
>>> import urlparse
>>> urlparse.urlsplit('invented://host/filename?query')
('invented', '', '//host/filename?query', '', '')
Python 2.7 (and Python 2.6.5) will return:
+ .. doctest::
+ :options: +SKIP
+
>>> import urlparse
>>> urlparse.urlsplit('invented://host/filename?query')
('invented', 'host', '/filename?query', '', '')
Integers
--------
-* :pep:`0237`: Essentially, :class:`long` renamed to :class:`int`.
+* :pep:`237`: Essentially, :class:`long` renamed to :class:`int`.
That is, there is only one built-in integral type, named
:class:`int`; but it behaves mostly like the old :class:`long` type.
-* :pep:`0238`: An expression like ``1/2`` returns a float. Use
+* :pep:`238`: An expression like ``1/2`` returns a float. Use
``1//2`` to get the truncating behavior. (The latter syntax has
existed for years, at least since Python 2.2.)
* Dictionary comprehensions: ``{k: v for k, v in stuff}`` means the
same thing as ``dict(stuff)`` but is more flexible. (This is
- :pep:`0274` vindicated. :-)
+ :pep:`274` vindicated. :-)
* Set literals, e.g. ``{1, 2}``. Note that ``{}`` is an empty
dictionary; use ``set()`` for an empty set. Set comprehensions are
* The only acceptable syntax for relative imports is :samp:`from .[{module}]
import {name}`. All :keyword:`import` forms not starting with ``.`` are
- interpreted as absolute imports. (:pep:`0328`)
+ interpreted as absolute imports. (:pep:`328`)
* Classic classes are gone.
* Many old modules were removed. Some, like :mod:`gopherlib` (no
longer used) and :mod:`md5` (replaced by :mod:`hashlib`), were
- already deprecated by :pep:`0004`. Others were removed as a result
+ already deprecated by :pep:`4`. Others were removed as a result
of the removal of support for various platforms such as Irix, BeOS
- and Mac OS 9 (see :pep:`0011`). Some modules were also selected for
+ and Mac OS 9 (see :pep:`11`). Some modules were also selected for
removal in Python 3.0 due to lack of use or because a better
replacement exists. See :pep:`3108` for an exhaustive list.
core standard library has proved over time to be a particular burden
for the core developers due to testing instability and Berkeley DB's
release schedule. However, the package is alive and well,
- externally maintained at http://www.jcea.es/programacion/pybsddb.htm.
+ externally maintained at https://www.jcea.es/programacion/pybsddb.htm.
* Some modules were renamed because their old name disobeyed
- :pep:`0008`, or for various other reasons. Here's the list:
+ :pep:`8`, or for various other reasons. Here's the list:
======================= =======================
Old Name New Name
The APIs for raising and catching exception have been cleaned up and
new powerful features added:
-* :pep:`0352`: All exceptions must be derived (directly or indirectly)
+* :pep:`352`: All exceptions must be derived (directly or indirectly)
from :exc:`BaseException`. This is the root of the exception
hierarchy. This is not new as a recommendation, but the
*requirement* to inherit from :exc:`BaseException` is new. (Python
Example of calling the parser on a command string::
- >>> cmd = 'deploy sneezy.example.com sleepy.example.com -u skycaptain'
+ >>> cmd = 'deploy sneezy.example.com sleepy.example.com -u skycaptain'
>>> result = parser.parse_args(cmd.split())
>>> result.action
'deploy'
>>> import json, logging.config
>>> with open('conf.json') as f:
- conf = json.load(f)
+ ... conf = json.load(f)
+ ...
>>> logging.config.dictConfig(conf)
>>> logging.info("Transaction completed normally")
INFO : root : Transaction completed normally
'The testing project status is green as of February 15, 2011'
>>> class LowerCasedDict(dict):
- def __getitem__(self, key):
- return dict.__getitem__(self, key.lower())
+ ... def __getitem__(self, key):
+ ... return dict.__getitem__(self, key.lower())
>>> lcd = LowerCasedDict(part='widgets', quantity=10)
>>> 'There are {QUANTITY} {Part} in stock'.format_map(lcd)
'There are 10 widgets in stock'
>>> class PlaceholderDict(dict):
- def __missing__(self, key):
- return '<{}>'.format(key)
+ ... def __missing__(self, key):
+ ... return '<{}>'.format(key)
>>> 'Hello {name}, welcome to {location}'.format_map(PlaceholderDict())
'Hello <name>, welcome to <location>'
exceptions pass through::
>>> class A:
- @property
- def f(self):
- return 1 // 0
-
+ ... @property
+ ... def f(self):
+ ... return 1 // 0
+ ...
>>> a = A()
>>> hasattr(a, 'f')
Traceback (most recent call last):
def outer(x):
def inner():
- return x
+ return x
inner()
del x
def f():
def print_error():
- print(e)
+ print(e)
try:
- something
+ something
except Exception as e:
- print_error()
- # implicit "del e" here
+ print_error()
+ # implicit "del e" here
(See :issue:`4617`.)
(Contributed by Raymond Hettinger and incorporating design ideas from Jim
Baker, Miki Tebeka, and Nick Coghlan; see `recipe 498245
- <http://code.activestate.com/recipes/498245>`_\, `recipe 577479
- <http://code.activestate.com/recipes/577479>`_\, :issue:`10586`, and
+ <https://code.activestate.com/recipes/498245>`_\, `recipe 577479
+ <https://code.activestate.com/recipes/577479>`_\, :issue:`10586`, and
:issue:`10593`.)
* The :func:`functools.wraps` decorator now adds a :attr:`__wrapped__` attribute
def __eq__(self, other):
return ((self.lastname.lower(), self.firstname.lower()) ==
(other.lastname.lower(), other.firstname.lower()))
+
def __lt__(self, other):
return ((self.lastname.lower(), self.firstname.lower()) <
(other.lastname.lower(), other.firstname.lower()))
* The :class:`collections.Counter` class now has two forms of in-place
subtraction, the existing *-=* operator for `saturating subtraction
- <http://en.wikipedia.org/wiki/Saturation_arithmetic>`_ and the new
+ <https://en.wikipedia.org/wiki/Saturation_arithmetic>`_ and the new
:meth:`~collections.Counter.subtract` method for regular subtraction. The
- former is suitable for `multisets <http://en.wikipedia.org/wiki/Multiset>`_
+ former is suitable for `multisets <https://en.wikipedia.org/wiki/Multiset>`_
which only have positive counts, and the latter is more suitable for use cases
that allow negative counts:
complete.
Barriers can work with an arbitrary number of threads. This is a generalization
-of a `Rendezvous <http://en.wikipedia.org/wiki/Synchronous_rendezvous>`_ which
+of a `Rendezvous <https://en.wikipedia.org/wiki/Synchronous_rendezvous>`_ which
is defined for only two threads.
Implemented as a two-phase cyclic barrier, :class:`~threading.Barrier` objects
def get_votes(site):
ballots = conduct_election(site)
try:
- all_polls_closed.wait(timeout = midnight - time.now())
+ all_polls_closed.wait(timeout=midnight - time.now())
except BrokenBarrierError:
lockbox = seal_ballots(ballots)
queue.put(lockbox)
sealed and deposited in a queue for later handling.
See `Barrier Synchronization Patterns
-<http://parlab.eecs.berkeley.edu/wiki/_media/patterns/paraplop_g1_3.pdf>`_ for
+<https://parlab.eecs.berkeley.edu/wiki/_media/patterns/paraplop_g1_3.pdf>`_ for
more examples of how barriers can be used in parallel computing. Also, there is
a simple but thorough explanation of barriers in `The Little Book of Semaphores
<http://greenteapress.com/semaphores/downey08semaphores.pdf>`_, *section 3.6*.
0.013765762467652909
The :func:`~math.erf` function computes a probability integral or `Gaussian
-error function <http://en.wikipedia.org/wiki/Error_function>`_. The
+error function <https://en.wikipedia.org/wiki/Error_function>`_. The
complementary error function, :func:`~math.erfc`, is ``1 - erf(x)``:
>>> erf(1.0/sqrt(2.0)) # portion of normal distribution within 1 standard deviation
1.0
The :func:`~math.gamma` function is a continuous extension of the factorial
-function. See http://en.wikipedia.org/wiki/Gamma_function for details. Because
+function. See https://en.wikipedia.org/wiki/Gamma_function for details. Because
the function is related to factorials, it grows large even for small values of
*x*, so there is also a :func:`~math.lgamma` function for computing the natural
logarithm of the gamma function:
>>> REC_LEN, LOC_START, LOC_LEN = 34, 7, 11
>>> def change_location(buffer, record_number, location):
- start = record_number * REC_LEN + LOC_START
- buffer[start: start+LOC_LEN] = location
+ ... start = record_number * REC_LEN + LOC_START
+ ... buffer[start: start+LOC_LEN] = location
>>> import io
>>> byte_stream = io.BytesIO(
- b'G3805 storeroom Main chassis '
- b'X7899 shipping Reserve cog '
- b'L6988 receiving Primary sprocket'
- )
+ ... b'G3805 storeroom Main chassis '
+ ... b'X7899 shipping Reserve cog '
+ ... b'L6988 receiving Primary sprocket'
+ ... )
>>> buffer = byte_stream.getbuffer()
>>> change_location(buffer, 1, b'warehouse ')
>>> change_location(buffer, 0, b'showroom ')
:meth:`__repr__` and substituting a placeholder string instead::
>>> class MyList(list):
- @recursive_repr()
- def __repr__(self):
- return '<' + '|'.join(map(repr, self)) + '>'
-
+ ... @recursive_repr()
+ ... def __repr__(self):
+ ... return '<' + '|'.join(map(repr, self)) + '>'
+ ...
>>> m = MyList('abc')
>>> m.append(m)
>>> m.append('x')
>>> w.writeheader()
"name","dept"
>>> w.writerows([
- {'name': 'tom', 'dept': 'accounting'},
- {'name': 'susan', 'dept': 'Salesl'}])
+ ... {'name': 'tom', 'dept': 'accounting'},
+ ... {'name': 'susan', 'dept': 'Salesl'}])
"tom","accounting"
"susan","sales"
>>> import tarfile, glob
>>> def myfilter(tarinfo):
- if tarinfo.isfile(): # only save real files
- tarinfo.uname = 'monty' # redact the user name
- return tarinfo
+ ... if tarinfo.isfile(): # only save real files
+ ... tarinfo.uname = 'monty' # redact the user name
+ ... return tarinfo
>>> with tarfile.open(name='myarchive.tar.gz', mode='w:gz') as tf:
- for filename in glob.glob('*.txt'):
- tf.add(filename, filter=myfilter)
- tf.list()
+ ... for filename in glob.glob('*.txt'):
+ ... tf.add(filename, filter=myfilter)
+ ... tf.list()
-rw-r--r-- monty/501 902 2011-01-26 17:59:11 annotations.txt
-rw-r--r-- monty/501 123 2011-01-26 17:59:11 general_questions.txt
-rw-r--r-- monty/501 3514 2011-01-26 17:59:11 prion.txt
>>> import shutil, pprint
- >>> os.chdir('mydata') # change to the source directory
+ >>> os.chdir('mydata') # change to the source directory
>>> f = shutil.make_archive('/var/backup/mydata',
- 'zip') # archive the current directory
- >>> f # show the name of archive
+ ... 'zip') # archive the current directory
+ >>> f # show the name of archive
'/var/backup/mydata.zip'
- >>> os.chdir('tmp') # change to an unpacking
+ >>> os.chdir('tmp') # change to an unpacking
>>> shutil.unpack_archive('/var/backup/mydata.zip') # recover the data
- >>> pprint.pprint(shutil.get_archive_formats()) # display known formats
+ >>> pprint.pprint(shutil.get_archive_formats()) # display known formats
[('bztar', "bzip2'ed tar-file"),
('gztar', "gzip'ed tar-file"),
('tar', 'uncompressed tar file'),
('zip', 'ZIP file')]
- >>> shutil.register_archive_format( # register a new archive format
- name = 'xz',
- function = xz.compress, # callable archiving function
- extra_args = [('level', 8)], # arguments to the function
- description = 'xz compression'
- )
+ >>> shutil.register_archive_format( # register a new archive format
+ ... name='xz',
+ ... function=xz.compress, # callable archiving function
+ ... extra_args=[('level', 8)], # arguments to the function
+ ... description='xz compression'
+ ... )
(Contributed by Tarek Ziadé.)
* The :func:`ssl.wrap_socket` constructor function now takes a *ciphers*
argument. The *ciphers* string lists the allowed encryption algorithms using
the format described in the `OpenSSL documentation
- <http://www.openssl.org/docs/apps/ciphers.html#CIPHER_LIST_FORMAT>`__.
+ <https://www.openssl.org/docs/apps/ciphers.html#CIPHER-LIST-FORMAT>`__.
* When linked against recent versions of OpenSSL, the :mod:`ssl` module now
supports the Server Name Indication extension to the TLS protocol, allowing
>>> from inspect import getgeneratorstate
>>> def gen():
- yield 'demo'
+ ... yield 'demo'
>>> g = gen()
>>> getgeneratorstate(g)
'GEN_CREATED'
change state while it is searching::
>>> class A:
- @property
- def f(self):
- print('Running')
- return 10
-
+ ... @property
+ ... def f(self):
+ ... print('Running')
+ ... return 10
+ ...
>>> a = A()
>>> getattr(a, 'f')
Running
>>> parser = ConfigParser()
>>> parser.read_string("""
- [DEFAULT]
- location = upper left
- visible = yes
- editable = no
- color = blue
-
- [main]
- title = Main Menu
- color = green
-
- [options]
- title = Options
- """)
+ ... [DEFAULT]
+ ... location = upper left
+ ... visible = yes
+ ... editable = no
+ ... color = blue
+ ...
+ ... [main]
+ ... title = Main Menu
+ ... color = green
+ ...
+ ... [options]
+ ... title = Options
+ ... """)
>>> parser['main']['color']
'green'
>>> parser['main']['editable']
>>> parser = ConfigParser(interpolation=ExtendedInterpolation())
>>> parser.read_dict({'buildout': {'directory': '/home/ambv/zope9'},
- 'custom': {'prefix': '/usr/local'}})
+ ... 'custom': {'prefix': '/usr/local'}})
>>> parser.read_string("""
- [buildout]
- parts =
- zope9
- instance
- find-links =
- ${buildout:directory}/downloads/dist
-
- [zope9]
- recipe = plone.recipe.zope9install
- location = /opt/zope
-
- [instance]
- recipe = plone.recipe.zope9instance
- zope9-location = ${zope9:location}
- zope-conf = ${custom:prefix}/etc/zope.conf
- """)
+ ... [buildout]
+ ... parts =
+ ... zope9
+ ... instance
+ ... find-links =
+ ... ${buildout:directory}/downloads/dist
+ ...
+ ... [zope9]
+ ... recipe = plone.recipe.zope9install
+ ... location = /opt/zope
+ ...
+ ... [instance]
+ ... recipe = plone.recipe.zope9instance
+ ... zope9-location = ${zope9:location}
+ ... zope-conf = ${custom:prefix}/etc/zope.conf
+ ... """)
>>> parser['buildout']['find-links']
'\n/home/ambv/zope9/downloads/dist'
>>> parser['instance']['zope-conf']
A number of usability improvements were made for the :mod:`urllib.parse` module.
The :func:`~urllib.parse.urlparse` function now supports `IPv6
-<http://en.wikipedia.org/wiki/IPv6>`_ addresses as described in :rfc:`2732`:
+<https://en.wikipedia.org/wiki/IPv6>`_ addresses as described in :rfc:`2732`:
>>> import urllib.parse
>>> urllib.parse.urlparse('http://[dead:beef:cafe:5417:affe:8FA3:deaf:feed]/foo/')
:func:`~urllib.parse.quote_plus` for encoding::
>>> urllib.parse.urlencode([
- ('type', 'telenovela'),
- ('name', '¿Dónde Está Elisa?')],
- encoding='latin-1')
+ ... ('type', 'telenovela'),
+ ... ('name', '¿Dónde Está Elisa?')],
+ ... encoding='latin-1')
'type=telenovela&name=%BFD%F3nde+Est%E1+Elisa%3F'
As detailed in :ref:`parsing-ascii-encoded-bytes`, all the :mod:`urllib.parse`
(Contributed by Alexandre Vassalotti, Antoine Pitrou
and the Unladen Swallow team in :issue:`9410` and :issue:`3873`.)
-* The `Timsort algorithm <http://en.wikipedia.org/wiki/Timsort>`_ used in
+* The `Timsort algorithm <https://en.wikipedia.org/wiki/Timsort>`_ used in
:meth:`list.sort` and :func:`sorted` now runs faster and uses less memory
when called with a :term:`key function`. Previously, every element of
a list was wrapped with a temporary object that remembered the key value
Python has been updated to `Unicode 6.0.0
<http://unicode.org/versions/Unicode6.0.0/>`_. The update to the standard adds
-over 2,000 new characters including `emoji <http://en.wikipedia.org/wiki/Emoji>`_
+over 2,000 new characters including `emoji <https://en.wikipedia.org/wiki/Emoji>`_
symbols which are important for mobile phones.
In addition, the updated standard has altered the character properties for two
**Source code** :source:`Lib/functools.py`.
(Contributed by Raymond Hettinger; see
- `rationale <http://rhettinger.wordpress.com/2011/01/28/open-your-source-more/>`_.)
+ `rationale <https://rhettinger.wordpress.com/2011/01/28/open-your-source-more/>`_.)
* The docs now contain more examples and recipes. In particular, :mod:`re`
module has an extensive section, :ref:`re-examples`. Likewise, the
===============
In addition to the existing Subversion code repository at http://svn.python.org
-there is now a `Mercurial <http://mercurial.selenic.com/>`_ repository at
+there is now a `Mercurial <https://www.mercurial-scm.org/>`_ repository at
https://hg.python.org/\ .
After the 3.2 release, there are plans to switch to Mercurial as the primary
To learn to use the new version control system, see the `tutorial by Joel
Spolsky <http://hginit.com>`_ or the `Guide to Mercurial Workflows
-<http://mercurial.selenic.com/guide>`_.
+<https://www.mercurial-scm.org/guide>`_.
Build and C API Changes
:source:`Mac/BuildScript/README.txt` for details. For users running a 32/64-bit
build, there is a known problem with the default Tcl/Tk on Mac OS X 10.6.
Accordingly, we recommend installing an updated alternative such as
-`ActiveState Tcl/Tk 8.5.9 <http://www.activestate.com/activetcl/downloads>`_\.
+`ActiveState Tcl/Tk 8.5.9 <https://www.activestate.com/activetcl/downloads>`_\.
See https://www.python.org/download/mac/tcltk/ for additional details.
Porting to Python 3.2
...
>>> tallies = []
>>> acc = gather_tallies(tallies)
- >>> next(acc) # Ensure the accumulator is ready to accept values
+ >>> next(acc) # Ensure the accumulator is ready to accept values
>>> for i in range(4):
... acc.send(i)
...
- >>> acc.send(None) # Finish the first tally
+ >>> acc.send(None) # Finish the first tally
>>> for i in range(5):
... acc.send(i)
...
- >>> acc.send(None) # Finish the second tally
+ >>> acc.send(None) # Finish the second tally
>>> tallies
[6, 10]
multiprocessing
---------------
-The new :func:`multiprocessing.connection.wait` function allows to poll
+The new :func:`multiprocessing.connection.wait` function allows polling
multiple objects (such as connections, sockets and pipes) with a timeout.
(Contributed by Richard Oudkerk in :issue:`12328`.)
------
:class:`pickle.Pickler` objects now have an optional
-:attr:`~pickle.Pickler.dispatch_table` attribute allowing to set per-pickler
-reduction functions.
+:attr:`~pickle.Pickler.dispatch_table` attribute allowing per-pickler
+reduction functions to be set.
(Contributed by Richard Oudkerk in :issue:`14166`.)
Heiko Wundram)
* The :class:`~socket.socket` class now supports the PF_CAN protocol family
- (http://en.wikipedia.org/wiki/Socketcan), on Linux
- (http://lwn.net/Articles/253425).
+ (https://en.wikipedia.org/wiki/Socketcan), on Linux
+ (https://lwn.net/Articles/253425).
(Contributed by Matthias Fuchs, updated by Tiago Gonçalves in :issue:`10141`.)
* The :class:`~socket.socket` class now supports the PF_RDS protocol family
- (http://en.wikipedia.org/wiki/Reliable_Datagram_Sockets and
+ (https://en.wikipedia.org/wiki/Reliable_Datagram_Sockets and
https://oss.oracle.com/projects/rds/).
* The :class:`~socket.socket` class now supports the ``PF_SYSTEM`` protocol
all of the parent's inheritable handles, only the necessary ones.
* A new :func:`hashlib.pbkdf2_hmac` function provides
the `PKCS#5 password-based key derivation function 2
- <http://en.wikipedia.org/wiki/PBKDF2>`_.
+ <https://en.wikipedia.org/wiki/PBKDF2>`_.
* :ref:`TLSv1.1 and TLSv1.2 support <whatsnew-tls-11-12>` for :mod:`ssl`.
* :ref:`Retrieving certificates from the Windows system cert store support
<whatsnew34-win-cert-store>` for :mod:`ssl`.
method, equivalent to calling :mod:`~dis.dis` on the constructor argument, but
returned as a multi-line string::
- >>> bytecode = dis.Bytecode(lambda x: x +1, current_offset=3)
+ >>> bytecode = dis.Bytecode(lambda x: x + 1, current_offset=3)
>>> for instr in bytecode:
... print('{} ({})'.format(instr.opname, instr.opcode))
LOAD_FAST (124)
A new :func:`hashlib.pbkdf2_hmac` function provides
the `PKCS#5 password-based key derivation function 2
-<http://en.wikipedia.org/wiki/PBKDF2>`_. (Contributed by Christian
+<https://en.wikipedia.org/wiki/PBKDF2>`_. (Contributed by Christian
Heimes in :issue:`18582`.)
The :attr:`~hashlib.hash.name` attribute of :mod:`hashlib` hash objects is now
ability to query or set the resource limits for processes other than the one
making the call. (Contributed by Christian Heimes in :issue:`16595`.)
-On Linux kernel version 2.6.36 or later, there are there are also some new
+On Linux kernel version 2.6.36 or later, there are also some new
Linux specific constants: :attr:`~resource.RLIMIT_MSGQUEUE`,
:attr:`~resource.RLIMIT_NICE`, :attr:`~resource.RLIMIT_RTPRIO`,
:attr:`~resource.RLIMIT_RTTIME`, and :attr:`~resource.RLIMIT_SIGPENDING`.
A new boolean parameter to the :func:`~sqlite3.connect` function, *uri*, can be
used to indicate that the *database* parameter is a ``uri`` (see the `SQLite
-URI documentation <http://www.sqlite.org/uri.html>`_). (Contributed by poq in
+URI documentation <https://www.sqlite.org/uri.html>`_). (Contributed by poq in
:issue:`13773`.)
list of the loaded ``CA`` certificates. (Contributed by Christian Heimes in
:issue:`18147`.)
-If OpenSSL 0.9.8 or later is available, :class:`~ssl.SSLContext` has an new
+If OpenSSL 0.9.8 or later is available, :class:`~ssl.SSLContext` has a new
attribute :attr:`~ssl.SSLContext.verify_flags` that can be used to control the
certificate verification process by setting it to some combination of the new
constants :data:`~ssl.VERIFY_DEFAULT`, :data:`~ssl.VERIFY_CRL_CHECK_LEAF`,
:issue:`18596`.)
* The Windows build now uses `Address Space Layout Randomization
- <http://en.wikipedia.org/wiki/ASLR>`_ and `Data Execution Prevention
- <http://en.wikipedia.org/wiki/Data_Execution_Prevention>`_. (Contributed by
+ <https://en.wikipedia.org/wiki/Address_space_layout_randomization>`_ and `Data Execution Prevention
+ <https://en.wikipedia.org/wiki/Data_Execution_Prevention>`_. (Contributed by
Christian Heimes in :issue:`16632`.)
* New function :c:func:`PyObject_LengthHint` is the C API equivalent
Coroutine functions are intended to be run inside a compatible event loop,
such as the :ref:`asyncio loop <asyncio-event-loop>`.
+
+.. note::
+
+ .. versionchanged:: 3.5.2
+ Starting with CPython 3.5.2, ``__aiter__`` can directly return
+ :term:`asynchronous iterators <asynchronous iterator>`. Returning
+ an :term:`awaitable` object will result in a
+ :exc:`PendingDeprecationWarning`.
+
+ See more details in the :ref:`async-iterators` documentation
+ section.
+
+
.. seealso::
:pep:`492` -- Coroutines with async and await syntax
:pep:`448` extends the allowed uses of the ``*`` iterable unpacking
operator and ``**`` dictionary unpacking operator. It is now possible
-to use an arbitrary number of unpackings in function calls::
+to use an arbitrary number of unpackings in :ref:`function calls <calls>`::
>>> print(*[1], *[2], 3, *[4, 5])
1 2 3 4 5
1 2 3 4
Similarly, tuple, list, set, and dictionary displays allow multiple
-unpackings::
+unpackings (see :ref:`exprlists` and :ref:`dict`)::
>>> *range(4), 4
(0, 1, 2, 3, 4)
.. _whatsnew-pep-461:
-PEP 461 - % formatting support for bytes and bytearray
-------------------------------------------------------
+PEP 461 - percent formatting support for bytes and bytearray
+------------------------------------------------------------
:pep:`461` adds support for the ``%``
:ref:`interpolation operator <bytes-formatting>` to :class:`bytes`
argparse
--------
-The :class:`~argparse.ArgumentParser` class now allows to disable
+The :class:`~argparse.ArgumentParser` class now allows disabling
:ref:`abbreviated usage <prefix-matching>` of long options by setting
:ref:`allow_abbrev` to ``False``. (Contributed by Jonathan Paugh,
Steven Bethard, paul j3 and Daniel Eriksson in :issue:`14910`.)
now accept all kinds of :term:`awaitable objects <awaitable>`.
(Contributed by Yury Selivanov.)
+* New :func:`~asyncio.run_coroutine_threadsafe` function to submit
+ coroutines to event loops from other threads.
+ (Contributed by Vincent Michel.)
+
+* New :meth:`Transport.is_closing() <asyncio.BaseTransport.is_closing>`
+ method to check if the transport is closing or closed.
+ (Contributed by Yury Selivanov.)
+
+* The :meth:`loop.create_server() <asyncio.BaseEventLoop.create_server>`
+ method can now accept a list of hosts.
+ (Contributed by Yann Sionneau.)
+
+Updates in 3.5.2:
+
+* New :meth:`loop.create_future() <asyncio.BaseEventLoop.create_future>`
+ method to create Future objects. This allows alternative event
+ loop implementations, such as
+ `uvloop <https://github.com/MagicStack/uvloop>`_, to provide a faster
+ :class:`asyncio.Future` implementation.
+ (Contributed by Yury Selivanov.)
+
+* New :meth:`loop.get_exception_handler() <asyncio.BaseEventLoop.get_exception_handler>`
+ method to get the current exception handler.
+ (Contributed by Yury Selivanov.)
+
+* New :meth:`StreamReader.readuntil() <asyncio.StreamReader.readuntil>`
+ method to read data from the stream until a separator bytes
+ sequence appears.
+ (Contributed by Mark Korenberg.)
+
+* The :meth:`loop.create_connection() <asyncio.BaseEventLoop.create_connection>`
+ and :meth:`loop.create_server() <asyncio.BaseEventLoop.create_server>`
+ methods are optimized to avoid calling the system ``getaddrinfo``
+ function if the address is already resolved.
+ (Contributed by A. Jesse Jiryu Davis.)
+
+* The :meth:`loop.sock_connect(sock, address) <asyncio.BaseEventLoop.sock_connect>`
+ no longer requires the *address* to be resolved prior to the call.
+ (Contributed by A. Jesse Jiryu Davis.)
+
bz2
---
compileall
----------
-A new :mod:`compileall` option, :samp:`-j {N}`, allows to run *N* workers
-sumultaneously to perform parallel bytecode compilation.
+A new :mod:`compileall` option, :samp:`-j {N}`, allows running *N* workers
+simultaneously to perform parallel bytecode compilation.
The :func:`~compileall.compile_dir` function has a corresponding ``workers``
parameter. (Contributed by Claudiu Popa in :issue:`16104`.)
-Another new option, ``-r``, allows to control the maximum recursion
+Another new option, ``-r``, allows controlling the maximum recursion
level for subdirectories. (Contributed by Claudiu Popa in :issue:`19628`.)
The ``-q`` command line option can now be specified more than once, in
use ``/dev/urandom`` and avoiding failures due to potential file descriptor
exhaustion. (Contributed by Victor Stinner in :issue:`22181`.)
-New :func:`~os.get_blocking` and :func:`~os.set_blocking` functions allow to
-get and set a file descriptor's blocking mode (:data:`~os.O_NONBLOCK`.)
+New :func:`~os.get_blocking` and :func:`~os.set_blocking` functions allow
+getting and setting a file descriptor's blocking mode (:data:`~os.O_NONBLOCK`.)
(Contributed by Victor Stinner in :issue:`22054`.)
The :func:`~os.truncate` and :func:`~os.ftruncate` functions are now supported
Both the :meth:`SMTP.sendmail() <smtplib.SMTP.sendmail>` and
:meth:`SMTP.send_message() <smtplib.SMTP.send_message>` methods now
-support support :rfc:`6531` (SMTPUTF8).
+support :rfc:`6531` (SMTPUTF8).
(Contributed by Milan Oberkirch and R. David Murray in :issue:`22027`.)
Functions with timeouts now use a monotonic clock, instead of a system clock.
(Contributed by Victor Stinner in :issue:`22043`.)
-A new :meth:`socket.sendfile() <socket.socket.sendfile>` method allows to
-send a file over a socket by using the high-performance :func:`os.sendfile`
+A new :meth:`socket.sendfile() <socket.socket.sendfile>` method allows
+sending a file over a socket by using the high-performance :func:`os.sendfile`
function on UNIX, resulting in uploads being from 2 to 3 times faster than when
using plain :meth:`socket.send() <socket.socket.send>`.
(Contributed by Giampaolo Rodola' in :issue:`17552`.)
The :c:member:`PyTypeObject.tp_finalize` slot is now part of the stable ABI.
Windows builds now require Microsoft Visual C++ 14.0, which
-is available as part of `Visual Studio 2015 <http://www.visualstudio.com>`_.
+is available as part of `Visual Studio 2015 <https://www.visualstudio.com/>`_.
Extension modules now include a platform information tag in their filename on
some platforms (the tag is optional, and CPython will import extensions without
(Contributed by Serhiy Storchaka in :issue:`23671`.)
The :func:`platform.dist` and :func:`platform.linux_distribution` functions
-are now deprecated and will be removed in Python 3.7. Linux distributions use
-too many different ways of describing themselves, so the functionality is
-left to a package.
+are now deprecated. Linux distributions use too many different ways of
+describing themselves, so the functionality is left to a package.
(Contributed by Vajrasky Kok and Berker Peksag in :issue:`1322`.)
The previously undocumented ``from_function`` and ``from_builtin`` methods of
int PyObject_SetAttrString(PyObject *o, const char *attr_name, PyObject *v);
Set the value of the attribute named attr_name, for object o,
- to the value, v. Returns -1 on failure. This is
- the equivalent of the Python statement: o.attr_name=v.
+ to the value v. Raise an exception and return -1 on failure; return 0 on
+ success. This is the equivalent of the Python statement o.attr_name=v.
*/
int PyObject_SetAttr(PyObject *o, PyObject *attr_name, PyObject *v);
Set the value of the attribute named attr_name, for object o,
- to the value, v. Returns -1 on failure. This is
- the equivalent of the Python statement: o.attr_name=v.
+ to the value v. Raise an exception and return -1 on failure; return 0 on
+ success. This is the equivalent of the Python statement o.attr_name=v.
*/
PyAPI_FUNC(int) PyObject_SetItem(PyObject *o, PyObject *key, PyObject *v);
/*
- Map the object, key, to the value, v. Returns
- -1 on failure. This is the equivalent of the Python
- statement: o[key]=v.
+ Map the object key to the value v. Raise an exception and return -1
+ on failure; return 0 on success. This is the equivalent of the Python
+ statement o[key]=v.
*/
PyAPI_FUNC(int) PyObject_DelItemString(PyObject *o, const char *key);
PyAPI_FUNC(int) PySequence_SetItem(PyObject *o, Py_ssize_t i, PyObject *v);
/*
- Assign object v to the ith element of o. Returns
- -1 on failure. This is the equivalent of the Python
- statement: o[i]=v.
+ Assign object v to the ith element of o. Raise an exception and return
+ -1 on failure; return 0 on success. This is the equivalent of the
+ Python statement o[i]=v.
*/
PyAPI_FUNC(int) PySequence_DelItem(PyObject *o, Py_ssize_t i);
PyAPI_FUNC(PyObject *) PyMapping_Keys(PyObject *o);
/*
- On success, return a list or tuple of the keys in object o.
- On failure, return NULL.
+ On success, return a list, a tuple or a dictionary view in case of a dict,
+ of the keys in object o. On failure, return NULL.
*/
PyAPI_FUNC(PyObject *) PyMapping_Values(PyObject *o);
/*
- On success, return a list or tuple of the values in object o.
- On failure, return NULL.
+ On success, return a list, a tuple or a dictionary view in case of a dict,
+ of the values in object o. On failure, return NULL.
*/
PyAPI_FUNC(PyObject *) PyMapping_Items(PyObject *o);
/*
- On success, return a list or tuple of the items in object o,
- where each item is a tuple containing a key-value pair.
- On failure, return NULL.
+ On success, return a list, a tuple or a dictionary view in case of a dict,
+ of the items in object o, where each item is a tuple containing a key-value
+ pair. On failure, return NULL.
*/
#endif
/* Provides access to the internal data buffer and size of a string
- object or the default encoded version of an Unicode object. Passing
+ object or the default encoded version of a Unicode object. Passing
NULL as *len parameter will force the string buffer to be
0-terminated (passing a string with embedded NULL characters will
cause an exception). */
int ap_upper;
} PyAddrPair;
+#ifndef Py_LIMITED_API
/* Update *bounds to describe the first and one-past-the-last instructions in the
same line as lasti. Return the number of that line.
*/
-#ifndef Py_LIMITED_API
PyAPI_FUNC(int) _PyCode_CheckLineNumber(PyCodeObject* co,
int lasti, PyAddrPair *bounds);
+
+/* Create a comparable key used to compare constants taking in account the
+ * object type. It is used to make sure types are not coerced (e.g., float and
+ * complex) _and_ to distinguish 0.0 from -0.0 e.g. on IEEE platforms
+ *
+ * Return (type(obj), obj, ...): a tuple with variable size (at least 2 items)
+ * depending on the type and the value. The type is the first item to not
+ * compare bytes and str which can raise a BytesWarning exception. */
+PyAPI_FUNC(PyObject*) _PyCode_ConstantKey(PyObject *obj);
#endif
PyAPI_FUNC(PyObject*) PyCode_Optimize(PyObject *code, PyObject* consts,
PyAPI_FUNC(void) _PyDict_MaybeUntrack(PyObject *mp);
PyAPI_FUNC(int) _PyDict_HasOnlyStringKeys(PyObject *mp);
Py_ssize_t _PyDict_KeysSize(PyDictKeysObject *keys);
-PyObject *_PyDict_SizeOf(PyDictObject *);
+Py_ssize_t _PyDict_SizeOf(PyDictObject *);
PyObject *_PyDict_Pop(PyDictObject *, PyObject *, PyObject *);
PyObject *_PyDict_FromKeys(PyObject *, PyObject *, PyObject *);
#define _PyDict_HasSplitTable(d) ((d)->ma_values != NULL)
PyObject **f_stacktop;
PyObject *f_trace; /* Trace function */
- /* In a generator, we need to be able to swap between the exception
- state inside the generator and the exception state of the calling
- frame (which shouldn't be impacted when the generator "yields"
- from an except handler).
- These three fields exist exactly for that, and are unused for
- non-generator frames. See the save_exc_state and swap_exc_state
- functions in ceval.c for details of their use. */
+ /* In a generator, we need to be able to swap between the exception
+ state inside the generator and the exception state of the calling
+ frame (which shouldn't be impacted when the generator "yields"
+ from an except handler).
+ These three fields exist exactly for that, and are unused for
+ non-generator frames. See the save_exc_state and swap_exc_state
+ functions in ceval.c for details of their use. */
PyObject *f_exc_type, *f_exc_value, *f_exc_traceback;
/* Borrowed reference to a generator, or NULL */
PyObject *f_gen;
PyAPI_FUNC(int) PyGen_NeedsFinalizing(PyGenObject *);
PyAPI_FUNC(int) _PyGen_FetchStopIterationValue(PyObject **);
PyObject *_PyGen_Send(PyGenObject *, PyObject *);
+PyObject *_PyGen_yf(PyGenObject *);
PyAPI_FUNC(void) _PyGen_Finalize(PyObject *self);
#ifndef Py_LIMITED_API
PyAPI_DATA(PyTypeObject) PyCoro_Type;
PyAPI_DATA(PyTypeObject) _PyCoroWrapper_Type;
+PyAPI_DATA(PyTypeObject) _PyAIterWrapper_Type;
+PyObject *_PyAIterWrapper_New(PyObject *aiter);
+
#define PyCoro_CheckExact(op) (Py_TYPE(op) == &PyCoro_Type)
PyObject *_PyCoro_GetAwaitableIter(PyObject *o);
PyAPI_FUNC(PyObject *) PyCoro_New(struct _frame *,
/* List object interface */
/*
-Another generally useful object type is an list of object pointers.
+Another generally useful object type is a list of object pointers.
This is a mutable type: the list items can be changed, and items can be
added or removed. Out-of-range indices or non-list objects are ignored.
usage, the string "foo" is interned, and the structures are linked. On interpreter
shutdown, all strings are released (through _PyUnicode_ClearStaticStrings).
- Alternatively, _Py_static_string allows to choose the variable name.
+ Alternatively, _Py_static_string allows choosing the variable name.
_PyUnicode_FromId returns a borrowed reference to the interned string.
_PyObject_{Get,Set,Has}AttrId are __getattr__ versions using _Py_Identifier*.
*/
Py_DECREF(_py_xdecref_tmp); \
} while (0)
+#ifndef Py_LIMITED_API
+/* Safely decref `op` and set `op` to `op2`.
+ *
+ * As in case of Py_CLEAR "the obvious" code can be deadly:
+ *
+ * Py_DECREF(op);
+ * op = op2;
+ *
+ * The safe way is:
+ *
+ * Py_SETREF(op, op2);
+ *
+ * That arranges to set `op` to `op2` _before_ decref'ing, so that any code
+ * triggered as a side-effect of `op` getting torn down no longer believes
+ * `op` points to a valid object.
+ *
+ * Py_XSETREF is a variant of Py_SETREF that uses Py_XDECREF instead of
+ * Py_DECREF.
+ */
+
+#define Py_SETREF(op, op2) \
+ do { \
+ PyObject *_py_tmp = (PyObject *)(op); \
+ (op) = (op2); \
+ Py_DECREF(_py_tmp); \
+ } while (0)
+
+#define Py_XSETREF(op, op2) \
+ do { \
+ PyObject *_py_tmp = (PyObject *)(op); \
+ (op) = (op2); \
+ Py_XDECREF(_py_tmp); \
+ } while (0)
+
+#endif /* ifndef Py_LIMITED_API */
+
/*
These are provided as conveniences to Python runtime embedders, so that
they can have object code that is not dependent on Python compilation flags.
/*--start constants--*/
#define PY_MAJOR_VERSION 3
#define PY_MINOR_VERSION 5
-#define PY_MICRO_VERSION 1
+#define PY_MICRO_VERSION 2
#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_FINAL
#define PY_RELEASE_SERIAL 0
/* Version as a string */
-#define PY_VERSION "3.5.1"
+#define PY_VERSION "3.5.2"
/*--end constants--*/
/* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2.
} _Py_memory_order;
typedef struct _Py_atomic_address {
- _Atomic void *_value;
+ atomic_uintptr_t _value;
} _Py_atomic_address;
typedef struct _Py_atomic_int {
} _Py_memory_order;
typedef struct _Py_atomic_address {
- void *_value;
+ Py_uintptr_t _value;
} _Py_atomic_address;
typedef struct _Py_atomic_int {
} _Py_memory_order;
typedef struct _Py_atomic_address {
- void *_value;
+ Py_uintptr_t _value;
} _Py_atomic_address;
typedef struct _Py_atomic_int {
* Therefore surpress the toolbox-glue in 64-bit mode.
*/
- /* In 64-bit mode setpgrp always has no argments, in 32-bit
+ /* In 64-bit mode setpgrp always has no arguments, in 32-bit
* mode that depends on the compilation environment
*/
# undef SETPGRP_HAVE_ARG
PyAPI_FUNC(void) _PyGILState_Reinit(void);
#endif
+/* Return the current thread state. The global interpreter lock must be held.
+ * When the current thread state is NULL, this issues a fatal error (so that
+ * the caller needn't check for NULL). */
PyAPI_FUNC(PyThreadState *) PyThreadState_Get(void);
+
+/* Similar to PyThreadState_Get(), but don't issue a fatal error
+ * if it is NULL. */
+PyAPI_FUNC(PyThreadState *) _PyThreadState_UncheckedGet(void);
+
PyAPI_FUNC(PyThreadState *) PyThreadState_Swap(PyThreadState *);
PyAPI_FUNC(PyObject *) PyThreadState_GetDict(void);
PyAPI_FUNC(int) PyThreadState_SetAsyncExc(long, PyObject *);
/* Stack size, in "pointers" (so we get extra safety margins
on 64-bit platforms). On a 32-bit platform, this translates
- to a 8k margin. */
+ to an 8k margin. */
#define PYOS_STACK_MARGIN 2048
#if defined(WIN32) && !defined(MS_WIN64) && defined(_MSC_VER) && _MSC_VER >= 1300
This function is signal safe. */
-PyAPI_DATA(void) _Py_DumpTraceback(
+PyAPI_FUNC(void) _Py_DumpTraceback(
int fd,
PyThreadState *tstate);
This function is signal safe. */
-PyAPI_DATA(const char*) _Py_DumpTracebackThreads(
+PyAPI_FUNC(const char*) _Py_DumpTracebackThreads(
int fd, PyInterpreterState *interp,
PyThreadState *current_thread);
PyAPI_FUNC(Py_UNICODE) PyUnicode_GetMax(void);
#endif
-/* Resize an Unicode object. The length is the number of characters, except
+/* Resize a Unicode object. The length is the number of characters, except
if the kind of the string is PyUnicode_WCHAR_KIND: in this case, the length
is the number of Py_UNICODE characters.
Py_ssize_t length /* New length */
);
-/* Coerce obj to an Unicode object and return a reference with
- *incremented* refcount.
+/* Decode obj to a Unicode object.
- Coercion is done in the following way:
+ bytes, bytearray and other bytes-like objects are decoded according to the
+ given encoding and error handler. The encoding and error handler can be
+ NULL to have the interface use UTF-8 and "strict".
- 1. bytes, bytearray and other bytes-like objects are decoded
- under the assumptions that they contain data using the UTF-8
- encoding. Decoding is done in "strict" mode.
-
- 2. All other objects (including Unicode objects) raise an
- exception.
+ All other objects (including Unicode objects) raise an exception.
The API returns NULL in case of an error. The caller is responsible
for decref'ing the returned objects.
const char *errors /* error handling */
);
-/* Coerce obj to an Unicode object and return a reference with
- *incremented* refcount.
-
- Unicode objects are passed back as-is (subclasses are converted to
- true Unicode objects), all other objects are delegated to
- PyUnicode_FromEncodedObject(obj, NULL, "strict") which results in
- using UTF-8 encoding as basis for decoding the object.
+/* Copy an instance of a Unicode subtype to a new true Unicode object if
+ necessary. If obj is already a true Unicode object (not a subtype), return
+ the reference with *incremented* refcount.
The API returns NULL in case of an error. The caller is responsible
for decref'ing the returned objects.
Py_ssize_t len /* length in bytes */
);
-/* Get the value of the writer as an Unicode string. Clear the
+/* Get the value of the writer as a Unicode string. Clear the
buffer of the writer. Raise an exception and return NULL
on error. */
PyAPI_FUNC(PyObject *)
/* Checks whether element is contained in container and return 1/0
accordingly.
- element has to coerce to an one element Unicode string. -1 is
+ element has to coerce to a one element Unicode string. -1 is
returned in case of an error. */
PyAPI_FUNC(int) PyUnicode_Contains(
distribute, and otherwise use Python alone or in any derivative version,
provided, however, that PSF's License Agreement and PSF's notice of copyright,
i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
-2011, 2012, 2013, 2014, 2015 Python Software Foundation; All Rights Reserved"
-are retained in Python alone or in any derivative version prepared by Licensee.
+2011, 2012, 2013, 2014, 2015, 2016 Python Software Foundation; All Rights
+Reserved" are retained in Python alone or in any derivative version prepared by
+Licensee.
3. In the event Licensee prepares a derivative work that is based on
or incorporates Python or any part thereof, and wants to make
__slots__ = ()
@abstractmethod
- async def __aiter__(self):
+ def __aiter__(self):
return AsyncIterator()
@classmethod
"""Return the next item or raise StopAsyncIteration when exhausted."""
raise StopAsyncIteration
- async def __aiter__(self):
+ def __aiter__(self):
return self
@classmethod
'DocXMLRPCServer': 'xmlrpc.server',
'SimpleHTTPServer': 'http.server',
'CGIHTTPServer': 'http.server',
+ # For compatibility with broken pickles saved in old Python 3 versions
+ 'UserDict': 'collections',
+ 'UserList': 'collections',
+ 'UserString': 'collections',
+ 'whichdb': 'dbm',
+ 'StringIO': 'io',
+ 'cStringIO': 'io',
})
REVERSE_IMPORT_MAPPING.update({
# can only be found inside Xcode.app if the "Command Line Tools"
# are not installed.
#
- # Futhermore, the compiler that can be used varies between
+ # Furthermore, the compiler that can be used varies between
# Xcode releases. Up to Xcode 4 it was possible to use 'gcc-4.2'
# as the compiler, after that 'clang' should be used because
# gcc-4.2 is either not present, or a copy of 'llvm-gcc' that
# miscompiles Python.
- # skip checks if the compiler was overriden with a CC env variable
+ # skip checks if the compiler was overridden with a CC env variable
if 'CC' in os.environ:
return _config_vars
if cc != oldcc:
# Found a replacement compiler.
# Modify config vars using new compiler, if not already explicitly
- # overriden by an env variable, preserving additional arguments.
+ # overridden by an env variable, preserving additional arguments.
for cv in _COMPILER_CONFIG_VARS:
if cv in _config_vars and cv not in os.environ:
cv_split = _config_vars[cv].split()
"""Remove all universal build arguments from config vars"""
for cv in _UNIVERSAL_CONFIG_VARS:
- # Do not alter a config var explicitly overriden by env var
+ # Do not alter a config var explicitly overridden by env var
if cv in _config_vars and cv not in os.environ:
flags = _config_vars[cv]
flags = re.sub('-arch\s+\w+\s', ' ', flags, re.ASCII)
# build extensions on OSX 10.7 and later with the prebuilt
# 32-bit installer on the python.org website.
- # skip checks if the compiler was overriden with a CC env variable
+ # skip checks if the compiler was overridden with a CC env variable
if 'CC' in os.environ:
return _config_vars
# across Xcode and compiler versions, there is no reliable way
# to be sure why it failed. Assume here it was due to lack of
# PPC support and remove the related '-arch' flags from each
- # config variables not explicitly overriden by an environment
+ # config variables not explicitly overridden by an environment
# variable. If the error was for some other reason, we hope the
# failure will show up again when trying to compile an extension
# module.
sdk = m.group(1)
if not os.path.exists(sdk):
for cv in _UNIVERSAL_CONFIG_VARS:
- # Do not alter a config var explicitly overriden by env var
+ # Do not alter a config var explicitly overridden by env var
if cv in _config_vars and cv not in os.environ:
flags = _config_vars[cv]
flags = re.sub(r'-isysroot\s+\S+(?:\s|$)', ' ', flags)
class ConversionSyntax(InvalidOperation):
"""Trying to convert badly formed string.
- This occurs and signals invalid-operation if an string is being
+ This occurs and signals invalid-operation if a string is being
converted to a number and it does not conform to the numeric string
syntax. The result is [0,qNaN].
"""
def __pos__(self, context=None):
"""Returns a copy, unless it is a sNaN.
- Rounds the number (if more then precision digits)
+ Rounds the number (if more than precision digits)
"""
if self._is_special:
ans = self._check_nans(context=context)
called.
The basic type used for binary data read from or written to a file is
- bytes. bytearrays are accepted too, and in some cases (such as
- readinto) needed. Text I/O classes work with str data.
+ bytes. Other bytes-like objects are accepted as method arguments too. In
+ some cases (such as readinto), a writable object is required. Text I/O
+ classes work with str data.
Note that calling any method (even inquiries) on a closed stream is
undefined. Implementations may raise OSError in this case.
def seekable(self):
"""Return a bool indicating whether object supports random access.
- If False, seek(), tell() and truncate() will raise UnsupportedOperation.
+ If False, seek(), tell() and truncate() will raise OSError.
This method may need to do a test seek().
"""
return False
def readable(self):
"""Return a bool indicating whether object was opened for reading.
- If False, read() will raise UnsupportedOperation.
+ If False, read() will raise OSError.
"""
return False
def writable(self):
"""Return a bool indicating whether object was opened for writing.
- If False, write() and truncate() will raise UnsupportedOperation.
+ If False, write() and truncate() will raise OSError.
"""
return False
return self.__closed
def _checkClosed(self, msg=None):
- """Internal: raise an ValueError if file is closed
+ """Internal: raise a ValueError if file is closed
"""
if self.closed:
raise ValueError("I/O operation on closed file."
return data
def readinto(self, b):
- """Read up to len(b) bytes into bytearray b.
+ """Read bytes into a pre-allocated bytes-like object b.
Returns an int representing the number of bytes read (0 for EOF), or
None if the object is set not to block and has no data to read.
def write(self, b):
"""Write the given buffer to the IO stream.
- Returns the number of bytes written, which may be less than len(b).
+ Returns the number of bytes written, which may be less than the
+ length of b in bytes.
"""
self._unsupported("write")
self._unsupported("read1")
def readinto(self, b):
- """Read up to len(b) bytes into bytearray b.
+ """Read bytes into a pre-allocated bytes-like object b.
Like read(), this may issue multiple reads to the underlying raw
stream, unless the latter is 'interactive'.
return self._readinto(b, read1=False)
def readinto1(self, b):
- """Read up to len(b) bytes into *b*, using at most one system call
+ """Read bytes into buffer *b*, using at most one system call
Returns an int representing the number of bytes read (0 for EOF).
def write(self, b):
"""Write the given bytes buffer to the IO stream.
- Return the number of bytes written, which is never less than
- len(b).
+ Return the number of bytes written, which is always the length of b
+ in bytes.
Raises BlockingIOError if the buffer is full and the
underlying raw stream cannot accept more data at the moment.
def seekable(self):
return self.raw.seekable()
- def readable(self):
- return self.raw.readable()
-
- def writable(self):
- return self.raw.writable()
-
@property
def raw(self):
return self._raw
raise ValueError("write to closed file")
if isinstance(b, str):
raise TypeError("can't write str to binary stream")
- n = len(b)
+ with memoryview(b) as view:
+ n = view.nbytes # Size of any bytes-like object
if n == 0:
return 0
pos = self._pos
self._reset_read_buf()
self._read_lock = Lock()
+ def readable(self):
+ return self.raw.readable()
+
def _reset_read_buf(self):
self._read_buf = b""
self._read_pos = 0
break
avail += len(chunk)
chunks.append(chunk)
- # n is more then avail only when an EOF occurred or when
+ # n is more than avail only when an EOF occurred or when
# read() would have blocked.
n = min(n, avail)
out = b"".join(chunks)
def _readinto(self, buf, read1):
"""Read data into *buf* with at most one system call."""
- if len(buf) == 0:
- return 0
-
# Need to create a memoryview object of type 'b', otherwise
# we may not be able to assign bytes to it, and slicing it
# would create a new object.
if not isinstance(buf, memoryview):
buf = memoryview(buf)
+ if buf.nbytes == 0:
+ return 0
buf = buf.cast('B')
written = 0
self._write_buf = bytearray()
self._write_lock = Lock()
+ def writable(self):
+ return self.raw.writable()
+
def write(self, b):
if self.closed:
raise ValueError("write to closed file")
self.__calc_date_time()
if _getlang() != self.lang:
raise ValueError("locale changed during initialization")
+ if time.tzname != self.tzname or time.daylight != self.daylight:
+ raise ValueError("timezone changed during initialization")
def __pad(self, seq, front):
# Add '' to seq to either the front (is True), else the back.
def __calc_timezone(self):
# Set self.timezone by using time.tzname.
- # Do not worry about possibility of time.tzname[0] == timetzname[1]
- # and time.daylight; handle that in strptime .
+ # Do not worry about possibility of time.tzname[0] == time.tzname[1]
+ # and time.daylight; handle that in strptime.
try:
time.tzset()
except AttributeError:
pass
- no_saving = frozenset({"utc", "gmt", time.tzname[0].lower()})
- if time.daylight:
- has_saving = frozenset({time.tzname[1].lower()})
+ self.tzname = time.tzname
+ self.daylight = time.daylight
+ no_saving = frozenset({"utc", "gmt", self.tzname[0].lower()})
+ if self.daylight:
+ has_saving = frozenset({self.tzname[1].lower()})
else:
has_saving = frozenset()
self.timezone = (no_saving, has_saving)
global _TimeRE_cache, _regex_cache
with _cache_lock:
-
- if _getlang() != _TimeRE_cache.locale_time.lang:
+ locale_time = _TimeRE_cache.locale_time
+ if (_getlang() != locale_time.lang or
+ time.tzname != locale_time.tzname or
+ time.daylight != locale_time.daylight):
_TimeRE_cache = TimeRE()
_regex_cache.clear()
+ locale_time = _TimeRE_cache.locale_time
if len(_regex_cache) > _CACHE_MAX_SIZE:
_regex_cache.clear()
- locale_time = _TimeRE_cache.locale_time
format_regex = _regex_cache.get(format)
if not format_regex:
try:
week_starts_Mon = True if week_of_year_start == 0 else False
julian = _calc_julian_from_U_or_W(year, week_of_year, weekday,
week_starts_Mon)
+ if julian <= 0:
+ year -= 1
+ yday = 366 if calendar.isleap(year) else 365
+ julian += yday
# Cannot pre-calculate datetime_date() since can change in Julian
# calculation and thus could have different value for the day of the week
# calculation.
# before cleanup of cancelled handles is performed.
_MIN_CANCELLED_TIMER_HANDLES_FRACTION = 0.5
+# Exceptions which must not call the exception handler in fatal error
+# methods (_fatal_error())
+_FATAL_ERROR_IGNORE = (BrokenPipeError,
+ ConnectionResetError, ConnectionAbortedError)
+
+
def _format_handle(handle):
cb = handle._callback
if inspect.ismethod(cb) and isinstance(cb.__self__, tasks.Task):
return repr(fd)
-def _check_resolved_address(sock, address):
- # Ensure that the address is already resolved to avoid the trap of hanging
- # the entire event loop when the address requires doing a DNS lookup.
- #
- # getaddrinfo() is slow (around 10 us per call): this function should only
- # be called in debug mode
- family = sock.family
+# Linux's sock.type is a bitmask that can include extra info about socket.
+_SOCKET_TYPE_MASK = 0
+if hasattr(socket, 'SOCK_NONBLOCK'):
+ _SOCKET_TYPE_MASK |= socket.SOCK_NONBLOCK
+if hasattr(socket, 'SOCK_CLOEXEC'):
+ _SOCKET_TYPE_MASK |= socket.SOCK_CLOEXEC
- if family == socket.AF_INET:
- host, port = address
- elif family == socket.AF_INET6:
- host, port = address[:2]
- else:
+
+def _ipaddr_info(host, port, family, type, proto):
+ # Try to skip getaddrinfo if "host" is already an IP. Users might have
+ # handled name resolution in their own code and pass in resolved IPs.
+ if not hasattr(socket, 'inet_pton'):
return
- # On Windows, socket.inet_pton() is only available since Python 3.4
- if hasattr(socket, 'inet_pton'):
- # getaddrinfo() is slow and has known issue: prefer inet_pton()
- # if available
- try:
- socket.inet_pton(family, host)
- except OSError as exc:
- raise ValueError("address must be resolved (IP address), "
- "got host %r: %s"
- % (host, exc))
+ if proto not in {0, socket.IPPROTO_TCP, socket.IPPROTO_UDP} or \
+ host is None:
+ return None
+
+ type &= ~_SOCKET_TYPE_MASK
+ if type == socket.SOCK_STREAM:
+ proto = socket.IPPROTO_TCP
+ elif type == socket.SOCK_DGRAM:
+ proto = socket.IPPROTO_UDP
else:
- # Use getaddrinfo(flags=AI_NUMERICHOST) to ensure that the address is
- # already resolved.
- type_mask = 0
- if hasattr(socket, 'SOCK_NONBLOCK'):
- type_mask |= socket.SOCK_NONBLOCK
- if hasattr(socket, 'SOCK_CLOEXEC'):
- type_mask |= socket.SOCK_CLOEXEC
+ return None
+
+ if port is None:
+ port = 0
+ elif isinstance(port, bytes):
+ if port == b'':
+ port = 0
+ else:
+ try:
+ port = int(port)
+ except ValueError:
+ # Might be a service name like b"http".
+ port = socket.getservbyname(port.decode('ascii'))
+ elif isinstance(port, str):
+ if port == '':
+ port = 0
+ else:
+ try:
+ port = int(port)
+ except ValueError:
+ # Might be a service name like "http".
+ port = socket.getservbyname(port)
+
+ if family == socket.AF_UNSPEC:
+ afs = [socket.AF_INET, socket.AF_INET6]
+ else:
+ afs = [family]
+
+ if isinstance(host, bytes):
+ host = host.decode('idna')
+ if '%' in host:
+ # Linux's inet_pton doesn't accept an IPv6 zone index after host,
+ # like '::1%lo0'.
+ return None
+
+ for af in afs:
try:
- socket.getaddrinfo(host, port,
- family=family,
- type=(sock.type & ~type_mask),
- proto=sock.proto,
- flags=socket.AI_NUMERICHOST)
- except socket.gaierror as err:
- raise ValueError("address must be resolved (IP address), "
- "got host %r: %s"
- % (host, err))
+ socket.inet_pton(af, host)
+ # The host has already been resolved.
+ return af, type, proto, '', (host, port)
+ except OSError:
+ pass
+
+ # "host" is not an IP address.
+ return None
+
+
+def _ensure_resolved(address, *, family=0, type=socket.SOCK_STREAM, proto=0,
+ flags=0, loop):
+ host, port = address[:2]
+ info = _ipaddr_info(host, port, family, type, proto)
+ if info is not None:
+ # "host" is already a resolved IP.
+ fut = loop.create_future()
+ fut.set_result([info])
+ return fut
+ else:
+ return loop.getaddrinfo(host, port, family=family, type=type,
+ proto=proto, flags=flags)
def _run_until_complete_cb(fut):
def wait_closed(self):
if self.sockets is None or self._waiters is None:
return
- waiter = futures.Future(loop=self._loop)
+ waiter = self._loop.create_future()
self._waiters.append(waiter)
yield from waiter
% (self.__class__.__name__, self.is_running(),
self.is_closed(), self.get_debug()))
+ def create_future(self):
+ """Create a Future object attached to the loop."""
+ return futures.Future(loop=self)
+
def create_task(self, coro):
"""Schedule a coroutine object.
assert not args
assert not isinstance(func, events.TimerHandle)
if func._cancelled:
- f = futures.Future(loop=self)
+ f = self.create_future()
f.set_result(None)
return f
func, args = func._callback, func._args
raise ValueError(
'host/port and sock can not be specified at the same time')
- f1 = self.getaddrinfo(
- host, port, family=family,
- type=socket.SOCK_STREAM, proto=proto, flags=flags)
+ f1 = _ensure_resolved((host, port), family=family,
+ type=socket.SOCK_STREAM, proto=proto,
+ flags=flags, loop=self)
fs = [f1]
if local_addr is not None:
- f2 = self.getaddrinfo(
- *local_addr, family=family,
- type=socket.SOCK_STREAM, proto=proto, flags=flags)
+ f2 = _ensure_resolved(local_addr, family=family,
+ type=socket.SOCK_STREAM, proto=proto,
+ flags=flags, loop=self)
fs.append(f2)
else:
f2 = None
def _create_connection_transport(self, sock, protocol_factory, ssl,
server_hostname):
protocol = protocol_factory()
- waiter = futures.Future(loop=self)
+ waiter = self.create_future()
if ssl:
sslcontext = None if isinstance(ssl, bool) else ssl
transport = self._make_ssl_transport(
assert isinstance(addr, tuple) and len(addr) == 2, (
'2-tuple is expected')
- infos = yield from self.getaddrinfo(
- *addr, family=family, type=socket.SOCK_DGRAM,
- proto=proto, flags=flags)
+ infos = yield from _ensure_resolved(
+ addr, family=family, type=socket.SOCK_DGRAM,
+ proto=proto, flags=flags, loop=self)
if not infos:
raise OSError('getaddrinfo() returned empty list')
raise exceptions[0]
protocol = protocol_factory()
- waiter = futures.Future(loop=self)
+ waiter = self.create_future()
transport = self._make_datagram_transport(
sock, protocol, r_addr, waiter)
if self._debug:
@coroutine
def _create_server_getaddrinfo(self, host, port, family, flags):
- infos = yield from self.getaddrinfo(host, port, family=family,
+ infos = yield from _ensure_resolved((host, port), family=family,
type=socket.SOCK_STREAM,
- flags=flags)
+ flags=flags, loop=self)
if not infos:
raise OSError('getaddrinfo({!r}) returned empty list'.format(host))
return infos
to host and port.
The host parameter can also be a sequence of strings and in that case
- the TCP server is bound to all hosts of the sequence.
+ the TCP server is bound to all hosts of the sequence. If a host
+ appears multiple times (possibly indirectly e.g. when hostnames
+ resolve to the same IP address), the server is only bound once to that
+ host.
Return a Server object which can be used to stop the service.
flags=flags)
for host in hosts]
infos = yield from tasks.gather(*fs, loop=self)
- infos = itertools.chain.from_iterable(infos)
+ infos = set(itertools.chain.from_iterable(infos))
completed = False
try:
@coroutine
def connect_read_pipe(self, protocol_factory, pipe):
protocol = protocol_factory()
- waiter = futures.Future(loop=self)
+ waiter = self.create_future()
transport = self._make_read_pipe_transport(pipe, protocol, waiter)
try:
@coroutine
def connect_write_pipe(self, protocol_factory, pipe):
protocol = protocol_factory()
- waiter = futures.Future(loop=self)
+ waiter = self.create_future()
transport = self._make_write_pipe_transport(pipe, protocol, waiter)
try:
logger.info('%s: %r' % (debug_log, transport))
return transport, protocol
+ def get_exception_handler(self):
+ """Return an exception handler, or None if the default one is in use.
+ """
+ return self._exception_handler
+
def set_exception_handler(self, handler):
"""Set handler as the new event loop exception handler.
logger.info('%r exited with return code %r',
self, returncode)
self._returncode = returncode
+ if self._proc.returncode is None:
+ # asyncio uses a child watcher: copy the status into the Popen
+ # object. On Python 3.6, it is required to avoid a ResourceWarning.
+ self._proc.returncode = returncode
self._call(self._protocol.process_exited)
self._try_finish()
if self._returncode is not None:
return self._returncode
- waiter = futures.Future(loop=self._loop)
+ waiter = self._loop.create_future()
self._exit_waiters.append(waiter)
return (yield from waiter)
PY34 = sys.version_info >= (3, 4)
PY35 = sys.version_info >= (3, 5)
+PY352 = sys.version_info >= (3, 5, 2)
def flatten_list_bytes(list_of_data):
# before you define your coroutines. A downside of using this feature
# is that tracebacks show entries for the CoroWrapper.__next__ method
# when _DEBUG is true.
-_DEBUG = (not sys.flags.ignore_environment
- and bool(os.environ.get('PYTHONASYNCIODEBUG')))
+_DEBUG = (not sys.flags.ignore_environment and
+ bool(os.environ.get('PYTHONASYNCIODEBUG')))
try:
def __init__(self, gen, func=None):
assert inspect.isgenerator(gen) or inspect.iscoroutine(gen), gen
self.gen = gen
- self.func = func # Used to unwrap @coroutine decorator
+ self.func = func # Used to unwrap @coroutine decorator
self._source_traceback = traceback.extract_stack(sys._getframe(1))
self.__name__ = getattr(gen, '__name__', None)
self.__qualname__ = getattr(gen, '__qualname__', None)
@functools.wraps(func)
def coro(*args, **kw):
res = func(*args, **kw)
- if isinstance(res, futures.Future) or inspect.isgenerator(res):
+ if isinstance(res, futures.Future) or inspect.isgenerator(res) or \
+ isinstance(res, CoroWrapper):
res = yield from res
elif _AwaitableABC is not None:
# If 'func' returns an Awaitable (new in 3.5) we
coro_frame = coro.cr_frame
filename = coro_code.co_filename
- if (isinstance(coro, CoroWrapper)
- and not inspect.isgeneratorfunction(coro.func)
- and coro.func is not None):
- filename, lineno = events._get_function_source(coro.func)
+ lineno = 0
+ if (isinstance(coro, CoroWrapper) and
+ not inspect.isgeneratorfunction(coro.func) and
+ coro.func is not None):
+ source = events._get_function_source(coro.func)
+ if source is not None:
+ filename, lineno = source
if coro_frame is None:
coro_repr = ('%s done, defined at %s:%s'
% (coro_name, filename, lineno))
def time(self):
raise NotImplementedError
+ def create_future(self):
+ raise NotImplementedError
+
# Method scheduling a coroutine object: create a task.
def create_task(self, coro):
# Error handlers.
+ def get_exception_handler(self):
+ raise NotImplementedError
+
def set_exception_handler(self, handler):
raise NotImplementedError
def __init__(self, *, loop=None):
"""Initialize the future.
- The optional event_loop argument allows to explicitly set the event
+ The optional event_loop argument allows explicitly setting the event
loop object used by the future. If it's not provided, the future uses
the default event loop.
"""
raise InvalidStateError('{}: {!r}'.format(self._state, self))
if isinstance(exception, type):
exception = exception()
+ if type(exception) is StopIteration:
+ raise TypeError("StopIteration interacts badly with generators "
+ "and cannot be raised into a Future")
self._exception = exception
self._state = _FINISHED
self._schedule_callbacks()
return future
assert isinstance(future, concurrent.futures.Future), \
'concurrent.futures.Future is expected, got {!r}'.format(future)
- new_future = Future(loop=loop)
+ if loop is None:
+ loop = events.get_event_loop()
+ new_future = loop.create_future()
_chain_future(future, new_future)
return new_future
acquire() is a coroutine and should be called with 'yield from'.
Locks also support the context management protocol. '(yield from lock)'
- should be used as context manager expression.
+ should be used as the context manager expression.
Usage:
self._locked = True
return True
- fut = futures.Future(loop=self._loop)
+ fut = self._loop.create_future()
self._waiters.append(fut)
try:
yield from fut
if self._value:
return True
- fut = futures.Future(loop=self._loop)
+ fut = self._loop.create_future()
self._waiters.append(fut)
try:
yield from fut
self.release()
try:
- fut = futures.Future(loop=self._loop)
+ fut = self._loop.create_future()
self._waiters.append(fut)
try:
yield from fut
self._waiters.remove(fut)
finally:
- yield from self.acquire()
+ # Must reacquire lock even if wait is cancelled
+ while True:
+ try:
+ yield from self.acquire()
+ break
+ except futures.CancelledError:
+ pass
@coroutine
def wait_for(self, predicate):
True.
"""
while self._value <= 0:
- fut = futures.Future(loop=self._loop)
+ fut = self._loop.create_future()
self._waiters.append(fut)
try:
yield from fut
self.close()
def _fatal_error(self, exc, message='Fatal error on pipe transport'):
- if isinstance(exc, (BrokenPipeError, ConnectionResetError)):
+ if isinstance(exc, base_events._FATAL_ERROR_IGNORE):
if self._loop.get_debug():
logger.debug("%r: %s", self, message, exc_info=True)
else:
return self._proactor.send(sock, data)
def sock_connect(self, sock, address):
- try:
- if self._debug:
- base_events._check_resolved_address(sock, address)
- except ValueError as err:
- fut = futures.Future(loop=self)
- fut.set_exception(err)
- return fut
- else:
- return self._proactor.connect(sock, address)
+ return self._proactor.connect(sock, address)
def sock_accept(self, sock):
return self._proactor.accept(sock)
This method is a coroutine.
"""
while self.full():
- putter = futures.Future(loop=self._loop)
+ putter = self._loop.create_future()
self._putters.append(putter)
try:
yield from putter
This method is a coroutine.
"""
while self.empty():
- getter = futures.Future(loop=self._loop)
+ getter = self._loop.create_future()
self._getters.append(getter)
try:
yield from getter
transport = None
try:
protocol = protocol_factory()
- waiter = futures.Future(loop=self)
+ waiter = self.create_future()
if sslcontext:
transport = self._make_ssl_transport(
conn, protocol, sslcontext, waiter=waiter,
"""
if self._debug and sock.gettimeout() != 0:
raise ValueError("the socket must be non-blocking")
- fut = futures.Future(loop=self)
+ fut = self.create_future()
self._sock_recv(fut, False, sock, n)
return fut
"""
if self._debug and sock.gettimeout() != 0:
raise ValueError("the socket must be non-blocking")
- fut = futures.Future(loop=self)
+ fut = self.create_future()
if data:
self._sock_sendall(fut, False, sock, data)
else:
def sock_connect(self, sock, address):
"""Connect to a remote socket at address.
- The address must be already resolved to avoid the trap of hanging the
- entire event loop when the address requires doing a DNS lookup. For
- example, it must be an IP address, not an hostname, for AF_INET and
- AF_INET6 address families. Use getaddrinfo() to resolve the hostname
- asynchronously.
-
This method is a coroutine.
"""
if self._debug and sock.gettimeout() != 0:
raise ValueError("the socket must be non-blocking")
- fut = futures.Future(loop=self)
+
+ fut = self.create_future()
+ if hasattr(socket, 'AF_UNIX') and sock.family == socket.AF_UNIX:
+ self._sock_connect(fut, sock, address)
+ else:
+ resolved = base_events._ensure_resolved(address, loop=self)
+ resolved.add_done_callback(
+ lambda resolved: self._on_resolved(fut, sock, resolved))
+
+ return fut
+
+ def _on_resolved(self, fut, sock, resolved):
try:
- if self._debug:
- base_events._check_resolved_address(sock, address)
- except ValueError as err:
- fut.set_exception(err)
+ _, _, _, _, address = resolved.result()[0]
+ except Exception as exc:
+ fut.set_exception(exc)
else:
self._sock_connect(fut, sock, address)
- return fut
def _sock_connect(self, fut, sock, address):
fd = sock.fileno()
"""
if self._debug and sock.gettimeout() != 0:
raise ValueError("the socket must be non-blocking")
- fut = futures.Future(loop=self)
+ fut = self.create_future()
self._sock_accept(fut, False, sock)
return fut
self._loop.remove_reader(self._sock_fd)
if not self._buffer:
self._conn_lost += 1
+ self._loop.remove_writer(self._sock_fd)
self._loop.call_soon(self._call_connection_lost, None)
# On Python 3.3 and older, objects with a destructor part of a reference
def _fatal_error(self, exc, message='Fatal error on transport'):
# Should be called from exception handler only.
- if isinstance(exc, (BrokenPipeError,
- ConnectionResetError, ConnectionAbortedError)):
+ if isinstance(exc, base_events._FATAL_ERROR_IGNORE):
if self._loop.get_debug():
logger.debug("%r: %s", self, message, exc_info=True)
else:
logger.debug("%r resumes reading", self)
def _read_ready(self):
+ if self._conn_lost:
+ return
try:
data = self._sock.recv(self.max_size)
except (BlockingIOError, InterruptedError):
def write(self, data):
if not isinstance(data, (bytes, bytearray, memoryview)):
- raise TypeError('data argument must be byte-ish (%r)',
- type(data))
+ raise TypeError('data argument must be a bytes-like object, '
+ 'not %r' % type(data).__name__)
if self._eof:
raise RuntimeError('Cannot call write() after write_eof()')
if not data:
def _write_ready(self):
assert self._buffer, 'Data should not be empty'
+ if self._conn_lost:
+ return
try:
n = self._sock.send(self._buffer)
except (BlockingIOError, InterruptedError):
logger.debug("%r resumes reading", self)
def _read_ready(self):
+ if self._conn_lost:
+ return
if self._write_wants_read:
self._write_wants_read = False
self._write_ready()
self.close()
def _write_ready(self):
+ if self._conn_lost:
+ return
if self._read_wants_write:
self._read_wants_write = False
self._read_ready()
def write(self, data):
if not isinstance(data, (bytes, bytearray, memoryview)):
- raise TypeError('data argument must be byte-ish (%r)',
- type(data))
+ raise TypeError('data argument must be a bytes-like object, '
+ 'not %r' % type(data).__name__)
if not data:
return
return sum(len(data) for data, _ in self._buffer)
def _read_ready(self):
+ if self._conn_lost:
+ return
try:
data, addr = self._sock.recvfrom(self.max_size)
except (BlockingIOError, InterruptedError):
def sendto(self, data, addr=None):
if not isinstance(data, (bytes, bytearray, memoryview)):
- raise TypeError('data argument must be byte-ish (%r)',
- type(data))
+ raise TypeError('data argument must be a bytes-like object, '
+ 'not %r' % type(data).__name__)
if not data:
return
self._wakeup_waiter()
self._session_established = True
# In case transport.write() was already called. Don't call
- # immediatly _process_write_backlog(), but schedule it:
+ # immediately _process_write_backlog(), but schedule it:
# _on_handshake_complete() can be called indirectly from
# _process_write_backlog(), and _process_write_backlog() is not
# reentrant.
def _fatal_error(self, exc, message='Fatal error on transport'):
# Should be called from exception handler only.
- if isinstance(exc, (BrokenPipeError, ConnectionResetError)):
+ if isinstance(exc, base_events._FATAL_ERROR_IGNORE):
if self._loop.get_debug():
logger.debug("%r: %s", self, message, exc_info=True)
else:
__all__ = ['StreamReader', 'StreamWriter', 'StreamReaderProtocol',
'open_connection', 'start_server',
'IncompleteReadError',
+ 'LimitOverrunError',
]
import socket
from . import coroutines
from . import compat
from . import events
-from . import futures
from . import protocols
from .coroutines import coroutine
from .log import logger
-_DEFAULT_LIMIT = 2**16
+_DEFAULT_LIMIT = 2 ** 16
class IncompleteReadError(EOFError):
Incomplete read error. Attributes:
- partial: read bytes string before the end of stream was reached
- - expected: total number of expected bytes
+ - expected: total number of expected bytes (or None if unknown)
"""
def __init__(self, partial, expected):
- EOFError.__init__(self, "%s bytes read on a total of %s expected bytes"
- % (len(partial), expected))
+ super().__init__("%d bytes read on a total of %r expected bytes"
+ % (len(partial), expected))
self.partial = partial
self.expected = expected
+class LimitOverrunError(Exception):
+ """Reached the buffer limit while looking for a separator.
+
+ Attributes:
+ - consumed: total number of to be consumed bytes.
+ """
+ def __init__(self, message, consumed):
+ super().__init__(message)
+ self.consumed = consumed
+
+
@coroutine
def open_connection(host=None, port=None, *,
loop=None, limit=_DEFAULT_LIMIT, **kwds):
writer = StreamWriter(transport, protocol, reader, loop)
return reader, writer
-
@coroutine
def start_unix_server(client_connected_cb, path=None, *,
loop=None, limit=_DEFAULT_LIMIT, **kwds):
return
waiter = self._drain_waiter
assert waiter is None or waiter.cancelled()
- waiter = futures.Future(loop=self._loop)
+ waiter = self._loop.create_future()
self._drain_waiter = waiter
yield from waiter
self._stream_reader = stream_reader
self._stream_writer = None
self._client_connected_cb = client_connected_cb
+ self._over_ssl = False
def connection_made(self, transport):
self._stream_reader.set_transport(transport)
+ self._over_ssl = transport.get_extra_info('sslcontext') is not None
if self._client_connected_cb is not None:
self._stream_writer = StreamWriter(transport, self,
self._stream_reader,
self._loop.create_task(res)
def connection_lost(self, exc):
- if exc is None:
- self._stream_reader.feed_eof()
- else:
- self._stream_reader.set_exception(exc)
+ if self._stream_reader is not None:
+ if exc is None:
+ self._stream_reader.feed_eof()
+ else:
+ self._stream_reader.set_exception(exc)
super().connection_lost(exc)
+ self._stream_reader = None
+ self._stream_writer = None
def data_received(self, data):
self._stream_reader.feed_data(data)
def eof_received(self):
self._stream_reader.feed_eof()
+ if self._over_ssl:
+ # Prevent a warning in SSLProtocol.eof_received:
+ # "returning true from eof_received()
+ # has no effect when using ssl"
+ return False
return True
def __init__(self, limit=_DEFAULT_LIMIT, loop=None):
# The line length limit is a security feature;
# it also doubles as half the buffer limit.
+
+ if limit <= 0:
+ raise ValueError('Limit cannot be <= 0')
+
self._limit = limit
if loop is None:
self._loop = events.get_event_loop()
waiter.set_exception(exc)
def _wakeup_waiter(self):
- """Wakeup read() or readline() function waiting for data or EOF."""
+ """Wakeup read*() functions waiting for data or EOF."""
waiter = self._waiter
if waiter is not None:
self._waiter = None
self._wakeup_waiter()
if (self._transport is not None and
- not self._paused and
- len(self._buffer) > 2*self._limit):
+ not self._paused and
+ len(self._buffer) > 2 * self._limit):
try:
self._transport.pause_reading()
except NotImplementedError:
@coroutine
def _wait_for_data(self, func_name):
- """Wait until feed_data() or feed_eof() is called."""
+ """Wait until feed_data() or feed_eof() is called.
+
+ If stream was paused, automatically resume it.
+ """
# StreamReader uses a future to link the protocol feed_data() method
# to a read coroutine. Running two read coroutines at the same time
# would have an unexpected behaviour. It would not possible to know
raise RuntimeError('%s() called while another coroutine is '
'already waiting for incoming data' % func_name)
- self._waiter = futures.Future(loop=self._loop)
+ assert not self._eof, '_wait_for_data after EOF'
+
+ # Waiting for data while paused will make deadlock, so prevent it.
+ if self._paused:
+ self._paused = False
+ self._transport.resume_reading()
+
+ self._waiter = self._loop.create_future()
try:
yield from self._waiter
finally:
@coroutine
def readline(self):
+ """Read chunk of data from the stream until newline (b'\n') is found.
+
+ On success, return chunk that ends with newline. If only partial
+ line can be read due to EOF, return incomplete line without
+ terminating newline. When EOF was reached while no bytes read, empty
+ bytes object is returned.
+
+ If limit is reached, ValueError will be raised. In that case, if
+ newline was found, complete line including newline will be removed
+ from internal buffer. Else, internal buffer will be cleared. Limit is
+ compared against part of the line without newline.
+
+ If stream was paused, this function will automatically resume it if
+ needed.
+ """
+ sep = b'\n'
+ seplen = len(sep)
+ try:
+ line = yield from self.readuntil(sep)
+ except IncompleteReadError as e:
+ return e.partial
+ except LimitOverrunError as e:
+ if self._buffer.startswith(sep, e.consumed):
+ del self._buffer[:e.consumed + seplen]
+ else:
+ self._buffer.clear()
+ self._maybe_resume_transport()
+ raise ValueError(e.args[0])
+ return line
+
+ @coroutine
+ def readuntil(self, separator=b'\n'):
+ """Read data from the stream until ``separator`` is found.
+
+ On success, the data and separator will be removed from the
+ internal buffer (consumed). Returned data will include the
+ separator at the end.
+
+ Configured stream limit is used to check result. Limit sets the
+ maximal length of data that can be returned, not counting the
+ separator.
+
+ If an EOF occurs and the complete separator is still not found,
+ an IncompleteReadError exception will be raised, and the internal
+ buffer will be reset. The IncompleteReadError.partial attribute
+ may contain the separator partially.
+
+ If the data cannot be read because of over limit, a
+ LimitOverrunError exception will be raised, and the data
+ will be left in the internal buffer, so it can be read again.
+ """
+ seplen = len(separator)
+ if seplen == 0:
+ raise ValueError('Separator should be at least one-byte string')
+
if self._exception is not None:
raise self._exception
- line = bytearray()
- not_enough = True
-
- while not_enough:
- while self._buffer and not_enough:
- ichar = self._buffer.find(b'\n')
- if ichar < 0:
- line.extend(self._buffer)
- self._buffer.clear()
- else:
- ichar += 1
- line.extend(self._buffer[:ichar])
- del self._buffer[:ichar]
- not_enough = False
-
- if len(line) > self._limit:
- self._maybe_resume_transport()
- raise ValueError('Line is too long')
+ # Consume whole buffer except last bytes, which length is
+ # one less than seplen. Let's check corner cases with
+ # separator='SEPARATOR':
+ # * we have received almost complete separator (without last
+ # byte). i.e buffer='some textSEPARATO'. In this case we
+ # can safely consume len(separator) - 1 bytes.
+ # * last byte of buffer is first byte of separator, i.e.
+ # buffer='abcdefghijklmnopqrS'. We may safely consume
+ # everything except that last byte, but this require to
+ # analyze bytes of buffer that match partial separator.
+ # This is slow and/or require FSM. For this case our
+ # implementation is not optimal, since require rescanning
+ # of data that is known to not belong to separator. In
+ # real world, separator will not be so long to notice
+ # performance problems. Even when reading MIME-encoded
+ # messages :)
+
+ # `offset` is the number of bytes from the beginning of the buffer
+ # where there is no occurrence of `separator`.
+ offset = 0
+
+ # Loop until we find `separator` in the buffer, exceed the buffer size,
+ # or an EOF has happened.
+ while True:
+ buflen = len(self._buffer)
+
+ # Check if we now have enough data in the buffer for `separator` to
+ # fit.
+ if buflen - offset >= seplen:
+ isep = self._buffer.find(separator, offset)
+
+ if isep != -1:
+ # `separator` is in the buffer. `isep` will be used later
+ # to retrieve the data.
+ break
+ # see upper comment for explanation.
+ offset = buflen + 1 - seplen
+ if offset > self._limit:
+ raise LimitOverrunError(
+ 'Separator is not found, and chunk exceed the limit',
+ offset)
+
+ # Complete message (with full separator) may be present in buffer
+ # even when EOF flag is set. This may happen when the last chunk
+ # adds data which makes separator be found. That's why we check for
+ # EOF *ater* inspecting the buffer.
if self._eof:
- break
+ chunk = bytes(self._buffer)
+ self._buffer.clear()
+ raise IncompleteReadError(chunk, None)
- if not_enough:
- yield from self._wait_for_data('readline')
+ # _wait_for_data() will resume reading if stream was paused.
+ yield from self._wait_for_data('readuntil')
+ if isep > self._limit:
+ raise LimitOverrunError(
+ 'Separator is found, but chunk is longer than limit', isep)
+
+ chunk = self._buffer[:isep + seplen]
+ del self._buffer[:isep + seplen]
self._maybe_resume_transport()
- return bytes(line)
+ return bytes(chunk)
@coroutine
def read(self, n=-1):
+ """Read up to `n` bytes from the stream.
+
+ If n is not provided, or set to -1, read until EOF and return all read
+ bytes. If the EOF was received and the internal buffer is empty, return
+ an empty bytes object.
+
+ If n is zero, return empty bytes object immediatelly.
+
+ If n is positive, this function try to read `n` bytes, and may return
+ less or equal bytes than requested, but at least one byte. If EOF was
+ received before any byte is read, this function returns empty byte
+ object.
+
+ Returned value is not limited with limit, configured at stream
+ creation.
+
+ If stream was paused, this function will automatically resume it if
+ needed.
+ """
+
if self._exception is not None:
raise self._exception
- if not n:
+ if n == 0:
return b''
if n < 0:
break
blocks.append(block)
return b''.join(blocks)
- else:
- if not self._buffer and not self._eof:
- yield from self._wait_for_data('read')
- if n < 0 or len(self._buffer) <= n:
- data = bytes(self._buffer)
- self._buffer.clear()
- else:
- # n > 0 and len(self._buffer) > n
- data = bytes(self._buffer[:n])
- del self._buffer[:n]
+ if not self._buffer and not self._eof:
+ yield from self._wait_for_data('read')
+
+ # This will work right even if buffer is less than n bytes
+ data = bytes(self._buffer[:n])
+ del self._buffer[:n]
self._maybe_resume_transport()
return data
@coroutine
def readexactly(self, n):
+ """Read exactly `n` bytes.
+
+ Raise an IncompleteReadError if EOF is reached before `n` bytes can be
+ read. The IncompleteReadError.partial attribute of the exception will
+ contain the partial read bytes.
+
+ if n is zero, return empty bytes object.
+
+ Returned value is not limited with limit, configured at stream
+ creation.
+
+ If stream was paused, this function will automatically resume it if
+ needed.
+ """
+ if n < 0:
+ raise ValueError('readexactly size can not be less than zero')
+
if self._exception is not None:
raise self._exception
+ if n == 0:
+ return b''
+
# There used to be "optimized" code here. It created its own
# Future and waited until self._buffer had at least the n
# bytes, then called read(n). Unfortunately, this could pause
blocks.append(block)
n -= len(block)
+ assert n == 0
+
return b''.join(blocks)
if compat.PY35:
if val == b'':
raise StopAsyncIteration
return val
+
+ if compat.PY352:
+ # In Python 3.5.2 and greater, __aiter__ should return
+ # the asynchronous iterator directly.
+ def __aiter__(self):
+ return self
@coroutine
def communicate(self, input=None):
- if input:
+ if input is not None:
stdin = self._feed_stdin(input)
else:
stdin = self._noop()
else:
if isinstance(result, futures.Future):
# Yielded Future must come from Future.__iter__().
- if result._blocking:
+ if result._loop is not self._loop:
+ self._loop.call_soon(
+ self._step,
+ RuntimeError(
+ 'Task {!r} got Future {!r} attached to a '
+ 'different loop'.format(self, result)))
+ elif result._blocking:
result._blocking = False
result.add_done_callback(self._wakeup)
self._fut_waiter = result
if timeout is None:
return (yield from fut)
- waiter = futures.Future(loop=loop)
+ waiter = loop.create_future()
timeout_handle = loop.call_later(timeout, _release_waiter, waiter)
cb = functools.partial(_release_waiter, waiter)
@coroutine
def _wait(fs, timeout, return_when, loop):
- """Internal helper for wait() and _wait_for().
+ """Internal helper for wait() and wait_for().
The fs argument must be a collection of Futures.
"""
assert fs, 'Set of Futures is empty.'
- waiter = futures.Future(loop=loop)
+ waiter = loop.create_future()
timeout_handle = None
if timeout is not None:
timeout_handle = loop.call_later(timeout, _release_waiter, waiter)
yield
return result
- future = futures.Future(loop=loop)
+ if loop is None:
+ loop = events.get_event_loop()
+ future = loop.create_future()
h = future._loop.call_later(delay,
futures._set_result_unless_cancelled,
future, result)
be cancelled.)
"""
if not coros_or_futures:
- outer = futures.Future(loop=loop)
+ if loop is None:
+ loop = events.get_event_loop()
+ outer = loop.create_future()
outer.set_result([])
return outer
# Shortcut.
return inner
loop = inner._loop
- outer = futures.Future(loop=loop)
+ outer = loop.create_future()
def _done_callback(inner):
if outer.cancelled():
finally:
logger.setLevel(old_level)
-def mock_nonblocking_socket():
+
+def mock_nonblocking_socket(proto=socket.IPPROTO_TCP, type=socket.SOCK_STREAM,
+ family=socket.AF_INET):
"""Create a mock of a non-blocking socket."""
- sock = mock.Mock(socket.socket)
+ sock = mock.MagicMock(socket.socket)
+ sock.proto = proto
+ sock.type = type
+ sock.family = family
sock.gettimeout.return_value = 0.0
return sock
stdin, stdout, stderr, bufsize,
extra=None, **kwargs):
with events.get_child_watcher() as watcher:
- waiter = futures.Future(loop=self)
+ waiter = self.create_future()
transp = _UnixSubprocessTransport(self, protocol, args, shell,
stdin, stdout, stderr, bufsize,
waiter=waiter, extra=extra,
elif self._closing:
info.append('closing')
info.append('fd=%s' % self._fileno)
- if self._pipe is not None:
+ selector = getattr(self._loop, '_selector', None)
+ if self._pipe is not None and selector is not None:
polling = selector_events._test_selector_event(
- self._loop._selector,
+ selector,
self._fileno, selectors.EVENT_READ)
if polling:
info.append('polling')
else:
info.append('idle')
+ elif self._pipe is not None:
+ info.append('open')
else:
info.append('closed')
return '<%s>' % ' '.join(info)
elif self._closing:
info.append('closing')
info.append('fd=%s' % self._fileno)
- if self._pipe is not None:
+ selector = getattr(self._loop, '_selector', None)
+ if self._pipe is not None and selector is not None:
polling = selector_events._test_selector_event(
- self._loop._selector,
+ selector,
self._fileno, selectors.EVENT_WRITE)
if polling:
info.append('polling')
bufsize = self.get_write_buffer_size()
info.append('bufsize=%s' % bufsize)
+ elif self._pipe is not None:
+ info.append('open')
else:
info.append('closed')
return '<%s>' % ' '.join(info)
def _fatal_error(self, exc, message='Fatal error on pipe transport'):
# should be called by exception handler only
- if isinstance(exc, (BrokenPipeError, ConnectionResetError)):
+ if isinstance(exc, base_events._FATAL_ERROR_IGNORE):
if self._loop.get_debug():
logger.debug("%r: %s", self, message, exc_info=True)
else:
#
# If the IocpProactor already received the event, it's safe to call
# _unregister() because we kept a reference to the Overlapped object
- # which is used as an unique key.
+ # which is used as a unique key.
self._proactor._unregister(self._ov)
self._proactor = None
def _make_subprocess_transport(self, protocol, args, shell,
stdin, stdout, stderr, bufsize,
extra=None, **kwargs):
- waiter = futures.Future(loop=self)
+ waiter = self.create_future()
transp = _WindowsSubprocessTransport(self, protocol, args, shell,
stdin, stdout, stderr, bufsize,
waiter=waiter, extra=extra,
return tmp
def _result(self, value):
- fut = futures.Future(loop=self._loop)
+ fut = self._loop.create_future()
fut.set_result(value)
return fut
__all__ = [
- # Legacy interface exports traditional RFC 1521 Base64 encodings
+ # Legacy interface exports traditional RFC 2045 Base64 encodings
'encode', 'decode', 'encodebytes', 'decodebytes',
# Generalized interface for other encodings
'b64encode', 'b64decode', 'b32encode', 'b32decode',
# Base64 encoding/decoding uses binascii
def b64encode(s, altchars=None):
- """Encode a byte string using Base64.
+ """Encode the bytes-like object s using Base64 and return a bytes object.
- s is the byte string to encode. Optional altchars must be a byte
- string of length 2 which specifies an alternative alphabet for the
- '+' and '/' characters. This allows an application to
- e.g. generate url or filesystem safe Base64 strings.
-
- The encoded byte string is returned.
+ Optional altchars should be a byte string of length 2 which specifies an
+ alternative alphabet for the '+' and '/' characters. This allows an
+ application to e.g. generate url or filesystem safe Base64 strings.
"""
# Strip off the trailing newline
encoded = binascii.b2a_base64(s)[:-1]
def b64decode(s, altchars=None, validate=False):
- """Decode a Base64 encoded byte string.
+ """Decode the Base64 encoded bytes-like object or ASCII string s.
- s is the byte string to decode. Optional altchars must be a
- string of length 2 which specifies the alternative alphabet used
- instead of the '+' and '/' characters.
+ Optional altchars must be a bytes-like object or ASCII string of length 2
+ which specifies the alternative alphabet used instead of the '+' and '/'
+ characters.
- The decoded string is returned. A binascii.Error is raised if s is
- incorrectly padded.
+ The result is returned as a bytes object. A binascii.Error is raised if
+ s is incorrectly padded.
- If validate is False (the default), non-base64-alphabet characters are
- discarded prior to the padding check. If validate is True,
- non-base64-alphabet characters in the input result in a binascii.Error.
+ If validate is False (the default), characters that are neither in the
+ normal base-64 alphabet nor the alternative alphabet are discarded prior
+ to the padding check. If validate is True, these non-alphabet characters
+ in the input result in a binascii.Error.
"""
s = _bytes_from_decode_data(s)
if altchars is not None:
def standard_b64encode(s):
- """Encode a byte string using the standard Base64 alphabet.
+ """Encode bytes-like object s using the standard Base64 alphabet.
- s is the byte string to encode. The encoded byte string is returned.
+ The result is returned as a bytes object.
"""
return b64encode(s)
def standard_b64decode(s):
- """Decode a byte string encoded with the standard Base64 alphabet.
+ """Decode bytes encoded with the standard Base64 alphabet.
- s is the byte string to decode. The decoded byte string is
- returned. binascii.Error is raised if the input is incorrectly
- padded or if there are non-alphabet characters present in the
- input.
+ Argument s is a bytes-like object or ASCII string to decode. The result
+ is returned as a bytes object. A binascii.Error is raised if the input
+ is incorrectly padded. Characters that are not in the standard alphabet
+ are discarded prior to the padding check.
"""
return b64decode(s)
_urlsafe_decode_translation = bytes.maketrans(b'-_', b'+/')
def urlsafe_b64encode(s):
- """Encode a byte string using a url-safe Base64 alphabet.
+ """Encode bytes using the URL- and filesystem-safe Base64 alphabet.
- s is the byte string to encode. The encoded byte string is
- returned. The alphabet uses '-' instead of '+' and '_' instead of
+ Argument s is a bytes-like object to encode. The result is returned as a
+ bytes object. The alphabet uses '-' instead of '+' and '_' instead of
'/'.
"""
return b64encode(s).translate(_urlsafe_encode_translation)
def urlsafe_b64decode(s):
- """Decode a byte string encoded with the standard Base64 alphabet.
+ """Decode bytes using the URL- and filesystem-safe Base64 alphabet.
- s is the byte string to decode. The decoded byte string is
- returned. binascii.Error is raised if the input is incorrectly
- padded or if there are non-alphabet characters present in the
- input.
+ Argument s is a bytes-like object or ASCII string to decode. The result
+ is returned as a bytes object. A binascii.Error is raised if the input
+ is incorrectly padded. Characters that are not in the URL-safe base-64
+ alphabet, and are not a plus '+' or slash '/', are discarded prior to the
+ padding check.
The alphabet uses '-' instead of '+' and '_' instead of '/'.
"""
_b32rev = None
def b32encode(s):
- """Encode a byte string using Base32.
-
- s is the byte string to encode. The encoded byte string is returned.
+ """Encode the bytes-like object s using Base32 and return a bytes object.
"""
global _b32tab2
# Delay the initialization of the table to not waste memory
return bytes(encoded)
def b32decode(s, casefold=False, map01=None):
- """Decode a Base32 encoded byte string.
+ """Decode the Base32 encoded bytes-like object or ASCII string s.
- s is the byte string to decode. Optional casefold is a flag
- specifying whether a lowercase alphabet is acceptable as input.
- For security purposes, the default is False.
+ Optional casefold is a flag specifying whether a lowercase alphabet is
+ acceptable as input. For security purposes, the default is False.
RFC 3548 allows for optional mapping of the digit 0 (zero) to the
letter O (oh), and for optional mapping of the digit 1 (one) to
the letter O). For security purposes the default is None, so that
0 and 1 are not allowed in the input.
- The decoded byte string is returned. binascii.Error is raised if
+ The result is returned as a bytes object. A binascii.Error is raised if
the input is incorrectly padded or if there are non-alphabet
characters present in the input.
"""
# lowercase. The RFC also recommends against accepting input case
# insensitively.
def b16encode(s):
- """Encode a byte string using Base16.
-
- s is the byte string to encode. The encoded byte string is returned.
+ """Encode the bytes-like object s using Base16 and return a bytes object.
"""
return binascii.hexlify(s).upper()
def b16decode(s, casefold=False):
- """Decode a Base16 encoded byte string.
+ """Decode the Base16 encoded bytes-like object or ASCII string s.
- s is the byte string to decode. Optional casefold is a flag
- specifying whether a lowercase alphabet is acceptable as input.
- For security purposes, the default is False.
+ Optional casefold is a flag specifying whether a lowercase alphabet is
+ acceptable as input. For security purposes, the default is False.
- The decoded byte string is returned. binascii.Error is raised if
- s were incorrectly padded or if there are non-alphabet characters
- present in the string.
+ The result is returned as a bytes object. A binascii.Error is raised if
+ s is incorrectly padded or if there are non-alphabet characters present
+ in the input.
"""
s = _bytes_from_decode_data(s)
if casefold:
return b''.join(chunks)
def a85encode(b, *, foldspaces=False, wrapcol=0, pad=False, adobe=False):
- """Encode a byte string using Ascii85.
-
- b is the byte string to encode. The encoded byte string is returned.
+ """Encode bytes-like object b using Ascii85 and return a bytes object.
foldspaces is an optional flag that uses the special short sequence 'y'
instead of 4 consecutive spaces (ASCII 0x20) as supported by 'btoa'. This
feature is not supported by the "standard" Adobe encoding.
- wrapcol controls whether the output should have newline ('\\n') characters
+ wrapcol controls whether the output should have newline (b'\\n') characters
added to it. If this is non-zero, each output line will be at most this
many characters long.
- pad controls whether the input string is padded to a multiple of 4 before
+ pad controls whether the input is padded to a multiple of 4 before
encoding. Note that the btoa implementation always pads.
adobe controls whether the encoded byte sequence is framed with <~ and ~>,
return result
def a85decode(b, *, foldspaces=False, adobe=False, ignorechars=b' \t\n\r\v'):
- """Decode an Ascii85 encoded byte string.
-
- s is the byte string to decode.
+ """Decode the Ascii85 encoded bytes-like object or ASCII string b.
foldspaces is a flag that specifies whether the 'y' short sequence should be
accepted as shorthand for 4 consecutive spaces (ASCII 0x20). This feature is
ignorechars should be a byte string containing characters to ignore from the
input. This should only contain whitespace characters, and by default
contains all whitespace characters in ASCII.
+
+ The result is returned as a bytes object.
"""
b = _bytes_from_decode_data(b)
if adobe:
- if not (b.startswith(_A85START) and b.endswith(_A85END)):
- raise ValueError("Ascii85 encoded byte sequences must be bracketed "
- "by {!r} and {!r}".format(_A85START, _A85END))
- b = b[2:-2] # Strip off start/end markers
+ if not b.endswith(_A85END):
+ raise ValueError(
+ "Ascii85 encoded byte sequences must end "
+ "with {!r}".format(_A85END)
+ )
+ if b.startswith(_A85START):
+ b = b[2:-2] # Strip off start/end markers
+ else:
+ b = b[:-2]
#
# We have to go through this stepwise, so as to ignore spaces and handle
# special short sequences
_b85dec = None
def b85encode(b, pad=False):
- """Encode an ASCII-encoded byte array in base85 format.
+ """Encode bytes-like object b in base85 format and return a bytes object.
- If pad is true, the input is padded with "\\0" so its length is a multiple of
- 4 characters before encoding.
+ If pad is true, the input is padded with b'\\0' so its length is a multiple of
+ 4 bytes before encoding.
"""
global _b85chars, _b85chars2
# Delay the initialization of tables to not waste memory
return _85encode(b, _b85chars, _b85chars2, pad)
def b85decode(b):
- """Decode base85-encoded byte array"""
+ """Decode the base85-encoded bytes-like object or ASCII string b
+
+ The result is returned as a bytes object.
+ """
global _b85dec
# Delay the initialization of tables to not waste memory
# if the function is never called
def encodebytes(s):
- """Encode a bytestring into a bytestring containing multiple lines
+ """Encode a bytestring into a bytes object containing multiple lines
of base-64 data."""
_input_type_check(s)
pieces = []
def decodebytes(s):
- """Decode a bytestring of base-64 data into a bytestring."""
+ """Decode a bytestring of base-64 data into a bytes object."""
_input_type_check(s)
return binascii.a2b_base64(s)
# parse query string function called from urlparse,
-# this is done in order to maintain backward compatiblity.
+# this is done in order to maintain backward compatibility.
def parse_qs(qs, keep_blank_values=0, strict_parsing=0):
"""Parse a query given as a string argument."""
+'''This module implements specialized container datatypes providing
+alternatives to Python's general purpose built-in containers, dict,
+list, set, and tuple.
+
+* namedtuple factory function for creating tuple subclasses with named fields
+* deque list-like container with fast appends and pops on either end
+* ChainMap dict-like class for creating a single view of multiple mappings
+* Counter dict subclass for counting hashable objects
+* OrderedDict dict subclass that remembers the order entries were added
+* defaultdict dict subclass that calls a factory function to supply missing values
+* UserDict wrapper around dictionary objects for easier dict subclassing
+* UserList wrapper around list objects for easier list subclassing
+* UserString wrapper around string objects for easier string subclassing
+
+'''
+
__all__ = ['deque', 'defaultdict', 'namedtuple', 'UserDict', 'UserList',
'UserString', 'Counter', 'OrderedDict', 'ChainMap']
>>> x, y = p # unpack like a regular tuple
>>> x, y
(11, 22)
- >>> p.x + p.y # fields also accessable by name
+ >>> p.x + p.y # fields also accessible by name
33
>>> d = p._asdict() # convert to a dictionary
>>> d['x']
to create a single, updateable view.
The underlying mappings are stored in a list. That list is public and can
- accessed or updated using the *maps* attribute. There is no other state.
+ be accessed or updated using the *maps* attribute. There is no other
+ state.
Lookups search the underlying mappings successively until a key is found.
In contrast, writes, updates, and deletions only operate on the first
args = parser.parse_args()
compile_dests = args.compile_dest
- if (args.ddir and (len(compile_dests) != 1
- or not os.path.isdir(compile_dests[0]))):
- parser.exit('-d destdir requires exactly one directory argument')
if args.rx:
import re
args.rx = re.compile(args.rx)
except AttributeError:
pass
d[type] = _deepcopy_atomic
-d[range] = _deepcopy_atomic
d[types.BuiltinFunctionType] = _deepcopy_atomic
d[types.FunctionType] = _deepcopy_atomic
d[weakref.ref] = _deepcopy_atomic
if n > 2:
state = info[2]
else:
- state = {}
+ state = None
if n > 3:
listiter = info[3]
else:
y = callable(*args)
memo[id(x)] = y
- if state:
+ if state is not None:
if deep:
state = deepcopy(state, memo)
if hasattr(y, '__setstate__'):
def create_string_buffer(init, size=None):
"""create_string_buffer(aBytes) -> character array
create_string_buffer(anInteger) -> character array
- create_string_buffer(aString, anInteger) -> character array
+ create_string_buffer(aBytes, anInteger) -> character array
"""
if isinstance(init, bytes):
if size is None:
return func
class PyDLL(CDLL):
- """This class represents the Python library itself. It allows to
- access Python API functions. The GIL is not released, and
+ """This class represents the Python library itself. It allows
+ accessing Python API functions. The GIL is not released, and
Python exceptions are handled correctly.
"""
_func_flags_ = _FUNCFLAG_CDECL | _FUNCFLAG_PYTHONAPI
-Files in this directory from from Bob Ippolito's py2app.
+Files in this directory come from Bob Ippolito's py2app.
License: Any components of the py2app suite may be distributed under
the MIT or PSF open source licenses.
self.assertEqual(len(ia), alen)
# slot values ok?
- values = [ia[i] for i in range(len(init))]
+ values = [ia[i] for i in range(alen)]
self.assertEqual(values, init)
+ # out-of-bounds accesses should be caught
+ with self.assertRaises(IndexError): ia[alen]
+ with self.assertRaises(IndexError): ia[-alen-1]
+
# change the items
from operator import setitem
new_values = list(range(42, 42+alen))
[setitem(ia, n, new_values[n]) for n in range(alen)]
- values = [ia[i] for i in range(len(init))]
+ values = [ia[i] for i in range(alen)]
self.assertEqual(values, new_values)
# are the items initialized to 0?
ia = int_array()
- values = [ia[i] for i in range(len(init))]
- self.assertEqual(values, [0] * len(init))
+ values = [ia[i] for i in range(alen)]
+ self.assertEqual(values, [0] * alen)
# Too many initializers should be caught
self.assertRaises(IndexError, int_array, *range(alen*2))
# C code:
# int x = 12321;
# res = &x
- res.contents = c_int(12321)
+ x = c_int(12321)
+ res.contents = x
self.assertEqual(i.value, 54345)
+ x.value = -99
+ self.assertEqual(res.contents.value, -99)
+
def test_callbacks_with_pointers(self):
# a function type receiving a pointer
PROTOTYPE = CFUNCTYPE(c_int, POINTER(c_int))
def test_basic(self):
p = pointer(c_int(42))
- # Although a pointer can be indexed, it ha no length
+ # Although a pointer can be indexed, it has no length
self.assertRaises(TypeError, len, p)
self.assertEqual(p[0], 42)
+ self.assertEqual(p[0:1], [42])
self.assertEqual(p.contents.value, 42)
def test_charpp(self):
ctdll = CDLL(_ctypes_test.__file__)
self.assertRaises(ValueError, c_int.in_dll, ctdll, "Undefined_Symbol")
-@unittest.skipUnless(sys.platform == 'win32', 'Windows-specific test')
-class Win_ValuesTestCase(unittest.TestCase):
+class PythonValuesTestCase(unittest.TestCase):
"""This test only works when python itself is a dll/shared library"""
def test_optimizeflag(self):
if entry.name in bootstrap_expected:
bootstrap_seen.append(entry.name)
self.assertTrue(entry.size,
- "{} was reported as having no size".format(entry.name))
+ "{!r} was reported as having no size".format(entry.name))
continue
- items.append((entry.name, entry.size))
+ items.append((entry.name.decode("ascii"), entry.size))
- expected = [(b"__hello__", 161),
- (b"__phello__", -161),
- (b"__phello__.spam", 161),
+ expected = [("__hello__", 161),
+ ("__phello__", -161),
+ ("__phello__.spam", 161),
]
- self.assertEqual(items, expected)
+ self.assertEqual(items, expected, "PyImport_FrozenModules example "
+ "in Doc/library/ctypes.rst may be out of date")
self.assertEqual(sorted(bootstrap_seen), bootstrap_expected,
"frozen bootstrap modules did not match PyImport_FrozenModules")
else:
cmd = 'env LC_ALL=C /usr/bin/crle 2>/dev/null'
+ paths = None
with contextlib.closing(os.popen(cmd)) as f:
for line in f.readlines():
line = line.strip()
ISO calendar algorithm taken from
http://www.phys.uu.nl/~vgent/calendar/isocalendar.htm
+ (used with permission)
"""
year = self._year
week1monday = _isoweek1monday(year)
"get_instructions", "Instruction", "Bytecode"] + _opcodes_all
del _opcodes_all
-_have_code = (types.MethodType, types.FunctionType, types.CodeType, type)
+_have_code = (types.MethodType, types.FunctionType, types.CodeType,
+ classmethod, staticmethod, type)
def _try_compile(source, name):
"""Attempts to compile the given source, first as an expression and
"""
labels = findlabels(code)
- extended_arg = 0
starts_line = None
free = None
- # enumerate() is not an option, since we sometimes process
- # multiple elements on a single pass through the loop
- n = len(code)
- i = 0
- while i < n:
- op = code[i]
- offset = i
+ for offset, op, arg in _unpack_opargs(code):
if linestarts is not None:
- starts_line = linestarts.get(i, None)
+ starts_line = linestarts.get(offset, None)
if starts_line is not None:
starts_line += line_offset
- is_jump_target = i in labels
- i = i+1
- arg = None
+ is_jump_target = offset in labels
argval = None
argrepr = ''
- if op >= HAVE_ARGUMENT:
- arg = code[i] + code[i+1]*256 + extended_arg
- extended_arg = 0
- i = i+2
- if op == EXTENDED_ARG:
- extended_arg = arg*65536
+ if arg is not None:
# Set argval to the dereferenced value of the argument when
- # availabe, and argrepr to the string representation of argval.
+ # available, and argrepr to the string representation of argval.
# _disassemble_bytes needs the string repr of the
# raw name index for LOAD_GLOBAL, LOAD_CONST, etc.
argval = arg
elif op in hasname:
argval, argrepr = _get_name_info(arg, names)
elif op in hasjrel:
- argval = i + arg
+ argval = offset + 3 + arg
argrepr = "to " + repr(argval)
elif op in haslocal:
argval, argrepr = _get_name_info(arg, varnames)
elif op in hasfree:
argval, argrepr = _get_name_info(arg, cells)
elif op in hasnargs:
- argrepr = "%d positional, %d keyword pair" % (code[i-2], code[i-1])
+ argrepr = "%d positional, %d keyword pair" % (arg%256, arg//256)
yield Instruction(opname[op], op,
arg, argval, argrepr,
offset, starts_line, is_jump_target)
disco = disassemble # XXX For backwards compatibility
-def findlabels(code):
- """Detect all offsets in a byte code which are jump targets.
-
- Return the list of offsets.
-
- """
- labels = []
+def _unpack_opargs(code):
# enumerate() is not an option, since we sometimes process
# multiple elements on a single pass through the loop
+ extended_arg = 0
n = len(code)
i = 0
while i < n:
op = code[i]
+ offset = i
i = i+1
+ arg = None
if op >= HAVE_ARGUMENT:
- arg = code[i] + code[i+1]*256
+ arg = code[i] + code[i+1]*256 + extended_arg
+ extended_arg = 0
i = i+2
+ if op == EXTENDED_ARG:
+ extended_arg = arg*65536
+ yield (offset, op, arg)
+
+def findlabels(code):
+ """Detect all offsets in a byte code which are jump targets.
+
+ Return the list of offsets.
+
+ """
+ labels = []
+ for offset, op, arg in _unpack_opargs(code):
+ if arg is not None:
label = -1
if op in hasjrel:
- label = i+arg
+ label = offset + 3 + arg
elif op in hasjabs:
label = arg
if label >= 0:
return exe
# A map keyed by get_platform() return values to values accepted by
-# 'vcvarsall.bat'. Note a cross-compile may combine these (eg, 'x86_amd64' is
-# the param to cross-compile on x86 targetting amd64.)
+# 'vcvarsall.bat'. Always cross-compile from x86 to work with the
+# lighter-weight MSVC installs that do not include native 64-bit tools.
PLAT_TO_VCVARS = {
'win32' : 'x86',
- 'win-amd64' : 'amd64',
+ 'win-amd64' : 'x86_amd64',
}
# A map keyed by get_platform() return values to the file under
raise DistutilsPlatformError("--plat-name must be one of {}"
.format(tuple(PLAT_TO_VCVARS)))
- # On x86, 'vcvarsall.bat amd64' creates an env that doesn't work;
- # to cross compile, you use 'x86_amd64'.
- # On AMD64, 'vcvarsall.bat amd64' is a native build env; to cross
- # compile use 'x86' (ie, it runs the x86 compiler directly)
- if plat_name == get_platform() or plat_name == 'win32':
- # native build or cross-compile to win32
- plat_spec = PLAT_TO_VCVARS[plat_name]
- else:
- # cross compile from win32 -> some 64bit
- plat_spec = '{}_{}'.format(
- PLAT_TO_VCVARS[get_platform()],
- PLAT_TO_VCVARS[plat_name]
- )
+ # Get the vcvarsall.bat spec for the requested platform.
+ plat_spec = PLAT_TO_VCVARS[plat_name]
vc_env = _get_vc_env(plat_spec)
if not vc_env:
def library_filename(self, libname, lib_type='static', # or 'shared'
strip_dir=0, output_dir=''):
assert output_dir is not None
- if lib_type not in ("static", "shared", "dylib"):
+ if lib_type not in ("static", "shared", "dylib", "xcode_stub"):
raise ValueError(
- "'lib_type' must be \"static\", \"shared\" or \"dylib\"")
+ "'lib_type' must be \"static\", \"shared\", \"dylib\", or \"xcode_stub\"")
fmt = getattr(self, lib_type + "_lib_format")
ext = getattr(self, lib_type + "_lib_extension")
if sysconfig.get_config_var('Py_ENABLE_SHARED'):
pythonlib = 'python{}.{}{}'.format(
sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff,
- sys.abiflags)
+ sysconfig.get_config_var('ABIFLAGS'))
return ext.libraries + [pythonlib]
else:
return ext.libraries
result = 500, str(e)
else:
if self.show_response:
- data = result.read()
+ data = self._read_pypi_response(result)
result = 200, 'OK'
if self.show_response:
- dashes = '-' * 75
- self.announce('%s%r%s' % (dashes, data, dashes))
+ msg = '\n'.join(('-' * 75, data, '-' * 75))
+ self.announce(msg, log.INFO)
return result
result = urlopen(request)
status = result.getcode()
reason = result.msg
- except OSError as e:
- self.announce(str(e), log.ERROR)
- raise
except HTTPError as e:
status = e.code
reason = e.msg
+ except OSError as e:
+ self.announce(str(e), log.ERROR)
+ raise
if status == 200:
self.announce('Server response (%s): %s' % (status, reason),
log.INFO)
+ if self.show_response:
+ text = self._read_pypi_response(result)
+ msg = '\n'.join(('-' * 75, text, '-' * 75))
+ self.announce(msg, log.INFO)
else:
msg = 'Upload failed (%s): %s' % (status, reason)
self.announce(msg, log.ERROR)
raise DistutilsError(msg)
- if self.show_response:
- text = self._read_pypi_response(result)
- msg = '\n'.join(('-' * 75, text, '-' * 75))
- self.announce(msg, log.INFO)
that uses .pypirc in the distutils.command package.
"""
import os
-from configparser import ConfigParser
+from configparser import RawConfigParser
from distutils.cmd import Command
repository = self.repository or self.DEFAULT_REPOSITORY
realm = self.realm or self.DEFAULT_REALM
- config = ConfigParser()
+ config = RawConfigParser()
config.read(rc)
sections = config.sections()
if 'distutils' in sections:
# A map keyed by get_platform() return values to values accepted by
# 'vcvarsall.bat'. Note a cross-compile may combine these (eg, 'x86_amd64' is
-# the param to cross-compile on x86 targetting amd64.)
+# the param to cross-compile on x86 targeting amd64.)
PLAT_TO_VCVARS = {
'win32' : 'x86',
'win-amd64' : 'amd64',
def test_compiler_option(self):
# cmd.compiler is an option and
- # should not be overriden by a compiler instance
+ # should not be overridden by a compiler instance
# when the command is run
dist = Distribution()
cmd = self.build_ext(dist)
results = self.get_logs(INFO)
self.assertEqual(results, ['running check', 'xxx'])
+ def test_show_response(self):
+ # test that the --show-response option return a well formatted response
+ cmd = self._get_cmd()
+ inputs = Inputs('1', 'tarek', 'y')
+ register_module.input = inputs.__call__
+ cmd.show_response = 1
+ try:
+ cmd.run()
+ finally:
+ del register_module.input
+
+ results = self.get_logs(INFO)
+ self.assertEqual(results[3], 75 * '-' + '\nxxx\n' + 75 * '-')
+
def test_suite():
return unittest.makeSuite(RegisterTestCase)
self.assertEqual(self.cc.linker_so[0], 'my_cc')
@unittest.skipUnless(sys.platform == 'darwin', 'test only relevant for OS X')
- def test_osx_explict_ldshared(self):
+ def test_osx_explicit_ldshared(self):
# Issue #18080:
# ensure that setting CC env variable does not change
# explicit LDSHARED setting for linker
"""Tests for distutils.command.upload."""
import os
import unittest
+import unittest.mock as mock
+from urllib.request import HTTPError
+
from test.support import run_unittest
from distutils.command import upload as upload_mod
from distutils.command.upload import upload
from distutils.core import Distribution
from distutils.errors import DistutilsError
-from distutils.log import INFO
+from distutils.log import ERROR, INFO
from distutils.tests.test_config import PYPIRC, PyPIRCCommandTestCase
# The PyPI response body was echoed
results = self.get_logs(INFO)
- self.assertIn('xyzzy\n', results[-1])
+ self.assertEqual(results[-1], 75 * '-' + '\nxyzzy\n' + 75 * '-')
def test_upload_fails(self):
self.next_msg = "Not Found"
self.next_code = 404
self.assertRaises(DistutilsError, self.test_upload)
+ def test_wrong_exception_order(self):
+ tmp = self.mkdtemp()
+ path = os.path.join(tmp, 'xxx')
+ self.write_file(path)
+ dist_files = [('xxx', '2.6', path)] # command, pyversion, filename
+ self.write_file(self.rc, PYPIRC_LONG_PASSWORD)
+
+ pkg_dir, dist = self.create_dist(dist_files=dist_files)
+ tests = [
+ (OSError('oserror'), 'oserror', OSError),
+ (HTTPError('url', 400, 'httperror', {}, None),
+ 'Upload failed (400): httperror', DistutilsError),
+ ]
+ for exception, expected, raised_exception in tests:
+ with self.subTest(exception=type(exception).__name__):
+ with mock.patch('distutils.command.upload.urlopen',
+ new=mock.Mock(side_effect=exception)):
+ with self.assertRaises(raised_exception):
+ cmd = upload(dist)
+ cmd.ensure_finalized()
+ cmd.run()
+ results = self.get_logs(ERROR)
+ self.assertIn(expected, results[-1])
+ self.clear_logs()
+
+
def test_suite():
return unittest.makeSuite(uploadTestCase)
static_lib_extension = ".a"
shared_lib_extension = ".so"
dylib_lib_extension = ".dylib"
+ xcode_stub_lib_extension = ".tbd"
static_lib_format = shared_lib_format = dylib_lib_format = "lib%s%s"
+ xcode_stub_lib_format = dylib_lib_format
if sys.platform == "cygwin":
exe_extension = ".exe"
def find_library_file(self, dirs, lib, debug=0):
shared_f = self.library_filename(lib, lib_type='shared')
dylib_f = self.library_filename(lib, lib_type='dylib')
+ xcode_stub_f = self.library_filename(lib, lib_type='xcode_stub')
static_f = self.library_filename(lib, lib_type='static')
if sys.platform == 'darwin':
# On OSX users can specify an alternate SDK using
# '-isysroot', calculate the SDK root if it is specified
# (and use it further on)
+ #
+ # Note that, as of Xcode 7, Apple SDKs may contain textual stub
+ # libraries with .tbd extensions rather than the normal .dylib
+ # shared libraries installed in /. The Apple compiler tool
+ # chain handles this transparently but it can cause problems
+ # for programs that are being built with an SDK and searching
+ # for specific libraries. Callers of find_library_file need to
+ # keep in mind that the base filename of the returned SDK library
+ # file might have a different extension from that of the library
+ # file installed on the running system, for example:
+ # /Applications/Xcode.app/Contents/Developer/Platforms/
+ # MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/
+ # usr/lib/libedit.tbd
+ # vs
+ # /usr/lib/libedit.dylib
cflags = sysconfig.get_config_var('CFLAGS')
m = re.search(r'-isysroot\s+(\S+)', cflags)
if m is None:
shared = os.path.join(dir, shared_f)
dylib = os.path.join(dir, dylib_f)
static = os.path.join(dir, static_f)
+ xcode_stub = os.path.join(dir, xcode_stub_f)
if sys.platform == 'darwin' and (
dir.startswith('/System/') or (
shared = os.path.join(sysroot, dir[1:], shared_f)
dylib = os.path.join(sysroot, dir[1:], dylib_f)
static = os.path.join(sysroot, dir[1:], static_f)
+ xcode_stub = os.path.join(sysroot, dir[1:], xcode_stub_f)
# We're second-guessing the linker here, with not much hard
# data to go on: GCC seems to prefer the shared library, so I'm
# ignoring even GCC's "-static" option. So sue me.
if os.path.exists(dylib):
return dylib
+ elif os.path.exists(xcode_stub):
+ return xcode_stub
elif os.path.exists(shared):
return shared
elif os.path.exists(static):
basedir = os.curdir
else:
# A module w/o __file__ (this includes builtins)
- raise ValueError("Can't resolve paths relative to the module " +
- module + " (it has no __file__)")
+ raise ValueError("Can't resolve paths relative to the module "
+ "%r (it has no __file__)"
+ % module.__name__)
# Combine the base directory and the path.
return os.path.join(basedir, *(path.split('/')))
This is not the RFC ctext, since we are handling nested comments in comment
and unquoting quoted-pairs here. We allow anything except the '()'
characters, but if we find any ASCII other than the RFC defined printable
- ASCII an NonPrintableDefect is added to the token's defects list. Since
+ ASCII, a NonPrintableDefect is added to the token's defects list. Since
quoted pairs are converted to their unquoted values, what is returned is
a 'ptext' token. In this case it is a WhiteSpaceTerminal, so it's value
is ' '.
"""qcontent = qtext / quoted-pair
We allow anything except the DQUOTE character, but if we find any ASCII
- other than the RFC defined printable ASCII an NonPrintableDefect is
+ other than the RFC defined printable ASCII, a NonPrintableDefect is
added to the token's defects list. Any quoted pairs are converted to their
unquoted values, so what is returned is a 'ptext' token. In this case it
is a ValueTerminal.
obs-dtext = obs-NO-WS-CTL / quoted-pair
We allow anything except the excluded characters, but if we find any
- ASCII other than the RFC defined printable ASCII an NonPrintableDefect is
+ ASCII other than the RFC defined printable ASCII, a NonPrintableDefect is
added to the token's defects list. Quoted pairs are converted to their
unquoted values, so what is returned is a ptext token, in this case a
ValueTerminal. If there were quoted-printables, an ObsoleteHeaderDefect is
_find_mime_parameters(ctype, value)
return ctype
ctype.append(token)
- # XXX: If we really want to follow the formal grammer we should make
+ # XXX: If we really want to follow the formal grammar we should make
# mantype and subtype specialized TokenLists here. Probably not worth it.
if not value or value[0] != '/':
ctype.defects.append(errors.InvalidHeaderDefect(
class Address:
def __init__(self, display_name='', username='', domain='', addr_spec=None):
- """Create an object represeting a full email address.
+ """Create an object representing a full email address.
An address can have a 'display_name', a 'username', and a 'domain'. In
addition to specifying the username and domain separately, they may be
def __init__(self, display_name=None, addresses=None):
"""Create an object representing an address group.
- An address group consists of a display_name followed by colon and an
+ An address group consists of a display_name followed by colon and a
list of addresses (see Address) terminated by a semi-colon. The Group
is created by specifying a display_name and a possibly empty list of
Address objects. A Group can also be used to represent a single
message, it will be set to "text/plain" and the new parameter and
value will be appended as per RFC 2045.
- An alternate header can specified in the header argument, and all
+ An alternate header can be specified in the header argument, and all
parameters will be quoted as necessary unless requote is False.
If charset is specified, the parameter will be encoded according to RFC
textual representation of the message.
The string must be formatted as a block of RFC 2822 headers and header
- continuation lines, optionally preceeded by a `Unix-from' header. The
+ continuation lines, optionally preceded by a `Unix-from' header. The
header block is terminated either by the end of the string or by a
blank line.
textual representation of the message.
The input must be formatted as a block of RFC 2822 headers and header
- continuation lines, optionally preceeded by a `Unix-from' header. The
+ continuation lines, optionally preceded by a `Unix-from' header. The
header block is terminated either by the end of the input or by a
blank line.
'utf-8'.
"""
name, address = pair
- # The address MUST (per RFC) be ascii, so raise an UnicodeError if it isn't.
+ # The address MUST (per RFC) be ascii, so raise a UnicodeError if it isn't.
address.encode('ascii')
if name:
try:
Original source: LaserJet IIP Printer User's Manual HP part no
33471-90901, Hewlet-Packard, June 1989.
+ (Used with permission)
+
"""#"
import codecs
self.decoder = None
def getstate(self):
- # additonal state info from the base class must be None here,
+ # additional state info from the base class must be None here,
# as it isn't passed along to the caller
state = codecs.BufferedIncrementalDecoder.getstate(self)[0]
# additional state info we pass to the caller:
self.decoder = None
def getstate(self):
- # additonal state info from the base class must be None here,
+ # additional state info from the base class must be None here,
# as it isn't passed along to the caller
state = codecs.BufferedIncrementalDecoder.getstate(self)[0]
# additional state info we pass to the caller:
__all__ = ["version", "bootstrap"]
-_SETUPTOOLS_VERSION = "18.2"
+_SETUPTOOLS_VERSION = "20.10.1"
-_PIP_VERSION = "7.1.2"
+_PIP_VERSION = "8.1.1"
# pip currently requires ssl support, so we try to provide a nicer
# error message when that is missing (http://bugs.python.org/issue19744)
# save attributes from super classes so we know if we can take
# the shortcut of storing members in the class dict
- base_attributes = {a for b in bases for a in b.__dict__}
+ base_attributes = {a for b in enum_class.mro() for a in b.__dict__}
# Reverse value->name map for hashable values.
enum_class._value2member_map_ = {}
enum_class.__new__ = Enum.__new__
return enum_class
+ def __bool__(self):
+ """
+ classes/types should always be True.
+ """
+ return True
+
def __call__(cls, value, names=None, *, module=None, qualname=None, type=None, start=1):
"""Either returns an existing member, or creates a new enum class.
disabled when standard input is read. XXX The current implementation
does not work for MS-DOS 8+3 filesystems.
-Performance: this module is unfortunately one of the slower ways of
-processing large numbers of input lines. Nevertheless, a significant
-speed-up has been obtained by using readlines(bufsize) instead of
-readline(). A new keyword argument, bufsize=N, is present on the
-input() function and the FileInput() class to override the default
-buffer size.
-
XXX Possible additions:
- optional getopt argument processing
_state = None
+# No longer used
DEFAULT_BUFSIZE = 8*1024
def input(files=None, inplace=False, backup="", bufsize=0,
self._files = files
self._inplace = inplace
self._backup = backup
- self._bufsize = bufsize or DEFAULT_BUFSIZE
self._savestdout = None
self._output = None
self._filename = None
- self._lineno = 0
+ self._startlineno = 0
self._filelineno = 0
self._file = None
self._isstdin = False
self._backupfilename = None
- self._buffer = []
- self._bufindex = 0
# restrict mode argument to reading modes
if mode not in ('r', 'rU', 'U', 'rb'):
raise ValueError("FileInput opening mode must be one of "
return self
def __next__(self):
- try:
- line = self._buffer[self._bufindex]
- except IndexError:
- pass
- else:
- self._bufindex += 1
- self._lineno += 1
- self._filelineno += 1
- return line
- line = self.readline()
- if not line:
- raise StopIteration
- return line
+ while True:
+ line = self._readline()
+ if line:
+ self._filelineno += 1
+ return line
+ if not self._file:
+ raise StopIteration
+ self.nextfile()
+ # repeat with next file
def __getitem__(self, i):
- if i != self._lineno:
+ if i != self.lineno():
raise RuntimeError("accessing lines out of order")
try:
return self.__next__()
file = self._file
self._file = None
try:
+ del self._readline # restore FileInput._readline
+ except AttributeError:
+ pass
+ try:
if file and not self._isstdin:
file.close()
finally:
except OSError: pass
self._isstdin = False
- self._buffer = []
- self._bufindex = 0
def readline(self):
- try:
- line = self._buffer[self._bufindex]
- except IndexError:
- pass
+ while True:
+ line = self._readline()
+ if line:
+ self._filelineno += 1
+ return line
+ if not self._file:
+ return line
+ self.nextfile()
+ # repeat with next file
+
+ def _readline(self):
+ if not self._files:
+ if 'b' in self._mode:
+ return b''
+ else:
+ return ''
+ self._filename = self._files[0]
+ self._files = self._files[1:]
+ self._startlineno = self.lineno()
+ self._filelineno = 0
+ self._file = None
+ self._isstdin = False
+ self._backupfilename = 0
+ if self._filename == '-':
+ self._filename = '<stdin>'
+ if 'b' in self._mode:
+ self._file = getattr(sys.stdin, 'buffer', sys.stdin)
+ else:
+ self._file = sys.stdin
+ self._isstdin = True
else:
- self._bufindex += 1
- self._lineno += 1
- self._filelineno += 1
- return line
- if not self._file:
- if not self._files:
- if 'b' in self._mode:
- return b''
+ if self._inplace:
+ self._backupfilename = (
+ self._filename + (self._backup or ".bak"))
+ try:
+ os.unlink(self._backupfilename)
+ except OSError:
+ pass
+ # The next few lines may raise OSError
+ os.rename(self._filename, self._backupfilename)
+ self._file = open(self._backupfilename, self._mode)
+ try:
+ perm = os.fstat(self._file.fileno()).st_mode
+ except OSError:
+ self._output = open(self._filename, "w")
else:
- return ''
- self._filename = self._files[0]
- self._files = self._files[1:]
- self._filelineno = 0
- self._file = None
- self._isstdin = False
- self._backupfilename = 0
- if self._filename == '-':
- self._filename = '<stdin>'
- if 'b' in self._mode:
- self._file = sys.stdin.buffer
- else:
- self._file = sys.stdin
- self._isstdin = True
- else:
- if self._inplace:
- self._backupfilename = (
- self._filename + (self._backup or ".bak"))
+ mode = os.O_CREAT | os.O_WRONLY | os.O_TRUNC
+ if hasattr(os, 'O_BINARY'):
+ mode |= os.O_BINARY
+
+ fd = os.open(self._filename, mode, perm)
+ self._output = os.fdopen(fd, "w")
try:
- os.unlink(self._backupfilename)
+ if hasattr(os, 'chmod'):
+ os.chmod(self._filename, perm)
except OSError:
pass
- # The next few lines may raise OSError
- os.rename(self._filename, self._backupfilename)
- self._file = open(self._backupfilename, self._mode)
- try:
- perm = os.fstat(self._file.fileno()).st_mode
- except OSError:
- self._output = open(self._filename, "w")
- else:
- mode = os.O_CREAT | os.O_WRONLY | os.O_TRUNC
- if hasattr(os, 'O_BINARY'):
- mode |= os.O_BINARY
-
- fd = os.open(self._filename, mode, perm)
- self._output = os.fdopen(fd, "w")
- try:
- if hasattr(os, 'chmod'):
- os.chmod(self._filename, perm)
- except OSError:
- pass
- self._savestdout = sys.stdout
- sys.stdout = self._output
+ self._savestdout = sys.stdout
+ sys.stdout = self._output
+ else:
+ # This may raise OSError
+ if self._openhook:
+ self._file = self._openhook(self._filename, self._mode)
else:
- # This may raise OSError
- if self._openhook:
- self._file = self._openhook(self._filename, self._mode)
- else:
- self._file = open(self._filename, self._mode)
- self._buffer = self._file.readlines(self._bufsize)
- self._bufindex = 0
- if not self._buffer:
- self.nextfile()
- # Recursive call
- return self.readline()
+ self._file = open(self._filename, self._mode)
+ self._readline = self._file.readline # hide FileInput._readline
+ return self._readline()
def filename(self):
return self._filename
def lineno(self):
- return self._lineno
+ return self._startlineno + self._filelineno
def filelineno(self):
return self._filelineno
a file object.
When fileobj is not None, the filename argument is only used to be
- included in the gzip file header, which may includes the original
+ included in the gzip file header, which may include the original
filename of the uncompressed file. It defaults to the filename of
fileobj, if discernible; otherwise, it defaults to the empty string,
and in this case the original filename is not included in the header.
def _init_write(self, filename):
self.name = filename
- self.crc = zlib.crc32(b"") & 0xffffffff
+ self.crc = zlib.crc32(b"")
self.size = 0
self.writebuf = []
self.bufsize = 0
if length > 0:
self.fileobj.write(self.compress.compress(data))
self.size += length
- self.crc = zlib.crc32(data, self.crc) & 0xffffffff
+ self.crc = zlib.crc32(data, self.crc)
self.offset += length
return length
self._last_mtime = None
def _init_read(self):
- self._crc = zlib.crc32(b"") & 0xffffffff
+ self._crc = zlib.crc32(b"")
self._stream_size = 0 # Decompressed size of unconcatenated stream
def _read_exact(self, n):
return uncompress
def _add_read_data(self, data):
- self._crc = zlib.crc32(data, self._crc) & 0xffffffff
+ self._crc = zlib.crc32(data, self._crc)
self._stream_size = self._stream_size + len(data)
def _read_eof(self):
In the tree above, each cell `k' is topping `2*k+1' and `2*k+2'. In
-an usual binary tournament we see in sports, each cell is the winner
+a usual binary tournament we see in sports, each cell is the winner
over the two cells it tops, and we can trace the winner down the tree
to see all opponents s/he had. However, in many computer applications
of such tournaments, we do not need to trace the history of a winner.
# or there's more text incoming. If the latter is True,
# we can't pass the text to handle_data in case we have
# a charref cut in half at end. Try to determine if
- # this is the case before proceding by looking for an
+ # this is the case before proceeding by looking for an
# & near the end and see if it's followed by a space or ;.
amppos = rawdata.rfind('&', max(i, n-34))
if (amppos >= 0 and
_METHODS_EXPECTING_BODY = {'PATCH', 'POST', 'PUT'}
+def _encode(data, name='data'):
+ """Call data.encode("latin-1") but show a better error message."""
+ try:
+ return data.encode("latin-1")
+ except UnicodeEncodeError as err:
+ raise UnicodeEncodeError(
+ err.encoding,
+ err.object,
+ err.start,
+ err.end,
+ "%s (%.20r) is not valid Latin-1. Use %s.encode('utf-8') "
+ "if you want to send it encoded in UTF-8." %
+ (name.title(), data[err.start:err.end], name)) from None
+
+
class HTTPMessage(email.message.Message):
# XXX The only usage of this method is in
# http.server.CGIHTTPRequestHandler. Maybe move the code there so
return b""
if self.chunked:
return self._read1_chunked(n)
+ if self.length is not None and (n < 0 or n > self.length):
+ n = self.length
try:
result = self.fp.read1(n)
except ValueError:
result = self.fp.read1(16*1024)
if not result and n:
self._close_conn()
+ elif self.length is not None:
+ self.length -= len(result)
return result
def peek(self, n=-1):
if self.chunked:
# Fallback to IOBase readline which uses peek() and read()
return super().readline(limit)
+ if self.length is not None and (limit < 0 or limit > self.length):
+ limit = self.length
result = self.fp.readline(limit)
if not result and limit:
self._close_conn()
+ elif self.length is not None:
+ self.length -= len(result)
return result
def _read1_chunked(self, n):
if isinstance(body, str):
# RFC 2616 Section 3.7.1 says that text default has a
# default charset of iso-8859-1.
- body = body.encode('iso-8859-1')
+ body = _encode(body, 'body')
self.endheaders(body)
def getresponse(self):
If the HTTPConnection is in the correct state, returns an
instance of HTTPResponse or of whatever object is returned by
- class the response_class variable.
+ the response_class variable.
If a request has not been sent or if a previous response has
not be handled, ResponseNotReady is raised. If the HTTP
return offset
def _str2time(day, mon, yr, hr, min, sec, tz):
+ yr = int(yr)
+ if yr > datetime.MAXYEAR:
+ return None
+
# translate month name to number
# month numbers start with 1 (January)
try:
if min is None: min = 0
if sec is None: sec = 0
- yr = int(yr)
day = int(day)
hr = int(hr)
min = int(min)
class LWPCookieJar(FileCookieJar):
"""
The LWPCookieJar saves a sequence of "Set-Cookie3" lines.
- "Set-Cookie3" is the format used by the libwww-perl libary, not known
+ "Set-Cookie3" is the format used by the libwww-perl library, not known
to be compatible with any browser, but which is easy to read and
doesn't lose information about RFC 2965 cookies.
# a two-way quoting algorithm. Any non-text character is translated
# into a 4 character sequence: a forward-slash followed by the
# three-digit octal equivalent of the character. Any '\' or '"' is
-# quoted with a preceeding '\' slash.
+# quoted with a preceding '\' slash.
# Because of the way browsers really handle cookies (as opposed to what
# the RFC says) we also encode "," and ";".
#
ord('\\'): '\\\\',
})
-_is_legal_key = re.compile('[%s]+' % _LegalChars).fullmatch
+_is_legal_key = re.compile('[%s]+' % re.escape(_LegalChars)).fullmatch
def _quote(str):
r"""Quote a string for use in a cookie header.
HTTPStatus.BAD_REQUEST,
"Line too long")
return False
+ except http.client.HTTPException as err:
+ self.send_error(
+ HTTPStatus.REQUEST_HEADER_FIELDS_TOO_LARGE,
+ "Too many headers",
+ str(err)
+ )
+ return False
conntype = self.headers.get('Connection', "")
if conntype.lower() == 'close':
if explain is None:
explain = longmsg
self.log_error("code %d, message %s", code, message)
- # using _quote_html to prevent Cross Site Scripting attacks (see bug #1100201)
- content = (self.error_message_format %
- {'code': code, 'message': _quote_html(message), 'explain': _quote_html(explain)})
- body = content.encode('UTF-8', 'replace')
self.send_response(code, message)
- self.send_header("Content-Type", self.error_content_type)
self.send_header('Connection', 'close')
- self.send_header('Content-Length', int(len(body)))
+
+ # Message body is omitted for cases described in:
+ # - RFC7230: 3.3. 1xx, 204(No Content), 304(Not Modified)
+ # - RFC7231: 6.3.6. 205(Reset Content)
+ body = None
+ if (code >= 200 and
+ code not in (HTTPStatus.NO_CONTENT,
+ HTTPStatus.RESET_CONTENT,
+ HTTPStatus.NOT_MODIFIED)):
+ # HTML encode to prevent Cross Site Scripting attacks
+ # (see bug #1100201)
+ content = (self.error_message_format % {
+ 'code': code,
+ 'message': _quote_html(message),
+ 'explain': _quote_html(explain)
+ })
+ body = content.encode('UTF-8', 'replace')
+ self.send_header("Content-Type", self.error_content_type)
+ self.send_header('Content-Length', int(len(body)))
self.end_headers()
- if (self.command != 'HEAD' and
- code >= 200 and
- code not in (
- HTTPStatus.NO_CONTENT, HTTPStatus.NOT_MODIFIED)):
+ if self.command != 'HEAD' and body:
self.wfile.write(body)
def send_response(self, code, message=None):
words = filter(None, words)
path = os.getcwd()
for word in words:
- drive, word = os.path.splitdrive(word)
- head, word = os.path.split(word)
- if word in (os.curdir, os.pardir): continue
+ if os.path.dirname(word) or word in (os.curdir, os.pardir):
+ # Ignore components that are not a simple file/directory name
+ continue
path = os.path.join(path, word)
if trailing_slash:
path += '/'
"""AutoComplete.py - An IDLE extension for automatically completing names.
-This extension can complete either attribute names of file names. It can pop
+This extension can complete either attribute names or file names. It can pop
a window with all available names, for the user to select from.
"""
import os
def try_open_completions_event(self, event):
"""Happens when it would be nice to open a completion list, but not
- really necessary, for example after an dot, so function
+ really necessary, for example after a dot, so function
calls won't be made.
"""
lastchar = self.text.get("insert-1c")
integration, debugger integration and persistent breakpoints).
Scott David Daniels, Tal Einat, Hernan Foffani, Christos Georgiou,
-Jim Jewett, Martin v. Löwis, Jason Orendorff, Guilherme Polo, Josh Robb,
+Jim Jewett, Martin v. Löwis, Jason Orendorff, Guilherme Polo, Josh Robb,
Nigel Rowe, Bruce Sherwood, Jeff Shute, and Weeble have submitted useful
patches. Thanks, guys!
* Attic/PopupMenu.py: Pass a root to the help window.
* SearchBinding.py:
- Add parent argument to 'to to line number' dialog box.
+ Add parent argument to 'go to line number' dialog box.
Sat Oct 10 19:15:32 1998 Guido van Rossum <guido@cnri.reston.va.us>
import re
import keyword
import builtins
+from tkinter import TkVersion
from idlelib.Delegator import Delegator
from idlelib.configHandler import idleConf
prog = re.compile(make_pat(), re.S)
idprog = re.compile(r"\s+(\w+)", re.S)
+def color_config(text): # Called from htest, Editor, and Turtle Demo.
+ '''Set color opitons of Text widget.
+
+ Should be called whenever ColorDelegator is called.
+ '''
+ # Not automatic because ColorDelegator does not know 'text'.
+ theme = idleConf.CurrentTheme()
+ normal_colors = idleConf.GetHighlight(theme, 'normal')
+ cursor_color = idleConf.GetHighlight(theme, 'cursor', fgBg='fg')
+ select_colors = idleConf.GetHighlight(theme, 'hilite')
+ text.config(
+ foreground=normal_colors['foreground'],
+ background=normal_colors['background'],
+ insertbackground=cursor_color,
+ selectforeground=select_colors['foreground'],
+ selectbackground=select_colors['background'],
+ )
+ if TkVersion >= 8.5:
+ text.config(
+ inactiveselectbackground=select_colors['background'])
+
+
class ColorDelegator(Delegator):
def __init__(self):
for tag in self.tagdefs:
self.tag_remove(tag, "1.0", "end")
+
def _color_delegator(parent): # htest #
from tkinter import Toplevel, Text
from idlelib.Percolator import Percolator
text.insert("insert", source)
text.focus_set()
+ color_config(text)
p = Percolator(text)
d = ColorDelegator()
p.insertfilter(d)
def __init__(self, master, flist, gui):
if macosxSupport.isAquaTk():
# At least on with the stock AquaTk version on OSX 10.4 you'll
- # get an shaking GUI that eventually kills IDLE if the width
+ # get a shaking GUI that eventually kills IDLE if the width
# argument is specified.
ScrolledList.__init__(self, master)
else:
class Delegator:
- # The cache is only used to be able to change delegates!
-
def __init__(self, delegate=None):
self.delegate = delegate
self.__cache = set()
+ # Cache is used to only remove added attributes
+ # when changing the delegate.
def __getattr__(self, name):
attr = getattr(self.delegate, name) # May raise AttributeError
return attr
def resetcache(self):
+ "Removes added attributes while leaving original attributes."
+ # Function is really about resetting delagator dict
+ # to original state. Cache is just a means
for key in self.__cache:
try:
delattr(self, key)
self.__cache.clear()
def setdelegate(self, delegate):
+ "Reset attributes and change delegate."
self.resetcache()
self.delegate = delegate
+
+if __name__ == '__main__':
+ from unittest import main
+ main('idlelib.idle_test.test_delegator', verbosity=2)
class EditorWindow(object):
from idlelib.Percolator import Percolator
- from idlelib.ColorDelegator import ColorDelegator
+ from idlelib.ColorDelegator import ColorDelegator, color_config
from idlelib.UndoDelegator import UndoDelegator
from idlelib.IOBinding import IOBinding, filesystemencoding, encoding
from idlelib import Bindings
# Called from self.filename_change_hook and from configDialog.py
self._rmcolorizer()
self._addcolorizer()
- theme = idleConf.CurrentTheme()
- normal_colors = idleConf.GetHighlight(theme, 'normal')
- cursor_color = idleConf.GetHighlight(theme, 'cursor', fgBg='fg')
- select_colors = idleConf.GetHighlight(theme, 'hilite')
- self.text.config(
- foreground=normal_colors['foreground'],
- background=normal_colors['background'],
- insertbackground=cursor_color,
- selectforeground=select_colors['foreground'],
- selectbackground=select_colors['background'],
- )
- if TkVersion >= 8.5:
- self.text.config(
- inactiveselectbackground=select_colors['background'])
+ EditorWindow.color_config(self.text)
IDENTCHARS = string.ascii_letters + string.digits + "_"
import tkinter.messagebox as tkMessageBox
from tkinter.simpledialog import askstring
+from idlelib.configHandler import idleConf
# Try setting the locale, so that we can find out
encoding = locale_encoding ### KBK 07Sep07 This is used all over IDLE, check!
### 'encoding' is used below in encode(), check!
-coding_re = re.compile(r'^[ \t\f]*#.*coding[:=][ \t]*([-\w.]+)', re.ASCII)
+coding_re = re.compile(r'^[ \t\f]*#.*?coding[:=][ \t]*([-\w.]+)', re.ASCII)
blank_re = re.compile(r'^[ \t\f]*(?:[#\r\n]|$)', re.ASCII)
def coding_spec(data):
def _io_binding(parent): # htest #
from tkinter import Toplevel, Text
- from idlelib.configHandler import idleConf
root = Toplevel(parent)
root.title("Test IOBinding")
self.text = text
self.flist = None
self.text.bind("<Control-o>", self.open)
+ self.text.bind('<Control-p>', self.print)
self.text.bind("<Control-s>", self.save)
+ self.text.bind("<Alt-s>", self.saveas)
+ self.text.bind('<Control-c>', self.savecopy)
def get_saved(self): return 0
def set_saved(self, flag): pass
def reset_undo(self): pass
def open(self, event):
self.text.event_generate("<<open-window-from-file>>")
+ def print(self, event):
+ self.text.event_generate("<<print-window>>")
def save(self, event):
self.text.event_generate("<<save-window>>")
+ def saveas(self, event):
+ self.text.event_generate("<<save-window-as-file>>")
+ def savecopy(self, event):
+ self.text.event_generate("<<save-copy-of-window-as-file>>")
text = Text(root)
text.pack()
raise
# An int in range(1 << len(_modifiers)) represents a combination of modifiers
-# (if the least significent bit is on, _modifiers[0] is on, and so on).
+# (if the least significant bit is on, _modifiers[0] is on, and so on).
# _state_subsets gives for each combination of modifiers, or *state*,
# a list of the states which are a subset of it. This list is ordered by the
# number of modifiers is the state - the most specific state comes first.
+What's New in IDLE 3.5.2?
+=========================
+*Release date: 2016-06-30?*
+
+- Issue #5124: Paste with text selected now replaces the selection on X11.
+ This matches how paste works on Windows, Mac, most modern Linux apps,
+ and ttk widgets. Original patch by Serhiy Storchaka.
+
+- Issue #24759: Make clear in idlelib.idle_test.__init__ that the directory
+ is a private implementation of test.test_idle and tool for maintainers.
+
+- Issue #27196: Stop 'ThemeChangef' warnings when running IDLE tests.
+ These persisted after other warnings were suppressed in #20567.
+ Apply Serhiy Storchaka's update_idletasks solution to four test files.
+ Record this additional advice in idle_test/README.txt
+
+- Issue #20567: Revise idle_test/README.txt with advice about avoiding
+ tk warning messages from tests. Apply advice to several IDLE tests.
+
+- Issue #27117: Make colorizer htest and turtledemo work with dark themes.
+ Move code for configuring text widget colors to a new function.
+
+- Issue #26673: When tk reports font size as 0, change to size 10.
+ Such fonts on Linux prevented the configuration dialog from opening.
+
+- Issue #21939: Add test for IDLE's percolator.
+ Original patch by Saimadhav Heblikar.
+
+- Issue #21676: Add test for IDLE's replace dialog.
+ Original patch by Saimadhav Heblikar.
+
+- Issue #18410: Add test for IDLE's search dialog.
+ Original patch by Westley Martínez.
+
+- Issue #21703: Add test for undo delegator.
+ Original patch by Saimadhav Heblikar .
+
+- Issue #27044: Add ConfigDialog.remove_var_callbacks to stop memory leaks.
+
+- Issue #23977: Add more asserts to test_delegator.
+
+- Issue #20640: Add tests for idlelib.configHelpSourceEdit.
+ Patch by Saimadhav Heblikar.
+
+- In the 'IDLE-console differences' section of the IDLE doc, clarify
+ how running with IDLE affects sys.modules and the standard streams.
+
+- Issue #25507: fix incorrect change in IOBinding that prevented printing.
+ Augment IOBinding htest to include all major IOBinding functions.
+
+- Issue #25905: Revert unwanted conversion of ' to ’ RIGHT SINGLE QUOTATION
+ MARK in README.txt and open this and NEWS.txt with 'ascii'.
+ Re-encode CREDITS.txt to utf-8 and open it with 'utf-8'.
+
+
What's New in IDLE 3.5.1?
=========================
*Release date: 2015-12-06*
move version to end.
- Issue #14105: Idle debugger breakpoints no longer disappear
- when inseting or deleting lines.
+ when inserting or deleting lines.
- Issue #17172: Turtledemo can now be run from Idle.
Currently, the entry is on the Help menu, but it may move to Run.
from idlelib.WidgetRedirector import WidgetRedirector
from idlelib.Delegator import Delegator
+
class Percolator:
def __init__(self, text):
while self.top is not self.bottom:
self.removefilter(self.top)
self.top = None
- self.bottom.setdelegate(None); self.bottom = None
- self.redir.close(); self.redir = None
+ self.bottom.setdelegate(None)
+ self.bottom = None
+ self.redir.close()
+ self.redir = None
self.text = None
def insert(self, index, chars, tags=None):
f.setdelegate(filter.delegate)
filter.setdelegate(None)
-def _percolator(parent):
+
+def _percolator(parent): # htest #
import tkinter as tk
import re
+
class Tracer(Delegator):
def __init__(self, name):
self.name = name
Delegator.__init__(self, None)
+
def insert(self, *args):
print(self.name, ": insert", args)
self.delegate.insert(*args)
+
def delete(self, *args):
print(self.name, ": delete", args)
self.delegate.delete(*args)
- root = tk.Tk()
- root.title("Test Percolator")
+
+ box = tk.Toplevel(parent)
+ box.title("Test Percolator")
width, height, x, y = list(map(int, re.split('[x+]', parent.geometry())))
- root.geometry("+%d+%d"%(x, y + 150))
- text = tk.Text(root)
+ box.geometry("+%d+%d" % (x, y + 150))
+ text = tk.Text(box)
p = Percolator(text)
+ pin = p.insertfilter
+ pout = p.removefilter
t1 = Tracer("t1")
t2 = Tracer("t2")
def toggle1():
- if var1.get() == 0:
- var1.set(1)
- p.insertfilter(t1)
- elif var1.get() == 1:
- var1.set(0)
- p.removefilter(t1)
-
+ (pin if var1.get() else pout)(t1)
def toggle2():
- if var2.get() == 0:
- var2.set(1)
- p.insertfilter(t2)
- elif var2.get() == 1:
- var2.set(0)
- p.removefilter(t2)
+ (pin if var2.get() else pout)(t2)
text.pack()
var1 = tk.IntVar()
- cb1 = tk.Checkbutton(root, text="Tracer1", command=toggle1, variable=var1)
+ cb1 = tk.Checkbutton(box, text="Tracer1", command=toggle1, variable=var1)
cb1.pack()
var2 = tk.IntVar()
- cb2 = tk.Checkbutton(root, text="Tracer2", command=toggle2, variable=var2)
+ cb2 = tk.Checkbutton(box, text="Tracer2", command=toggle2, variable=var2)
cb2.pack()
- root.mainloop()
-
if __name__ == "__main__":
+ import unittest
+ unittest.main('idlelib.idle_test.test_percolator', verbosity=2,
+ exit=False)
+
from idlelib.idle_test.htest import run
run(_percolator)
self.shell.close()
+def fix_x11_paste(root):
+ "Make paste replace selection on x11. See issue #5124."
+ if root._windowingsystem == 'x11':
+ for cls in 'Text', 'Entry', 'Spinbox':
+ root.bind_class(
+ cls,
+ '<<Paste>>',
+ 'catch {%W delete sel.first sel.last}\n' +
+ root.bind_class(cls, '<<Paste>>'))
+
+
usage_msg = """\
USAGE: idle [-deins] [-t title] [file]*
'editor-on-startup', type='bool')
enable_edit = enable_edit or edit_start
enable_shell = enable_shell or not enable_edit
+
# start editor and/or shell windows:
root = Tk(className="Idle")
+ root.withdraw()
# set application icon
icondir = os.path.join(os.path.dirname(__file__), 'Icons')
root.wm_iconphoto(True, *icons)
fixwordbreaks(root)
- root.withdraw()
+ fix_x11_paste(root)
flist = PyShellFileList(root)
macosxSupport.setupApp(root, flist)
README.txt: an index to idlelib files and the IDLE menu.
-IDLE is Python\92s Integrated Development and Learning
+IDLE is Python's Integrated Development and Learning
Environment. The user documentation is part of the Library Reference and
is available in IDLE by selecting Help => IDLE Help. This README documents
idlelib for IDLE developers and curious users.
+"""Replace dialog for IDLE. Inherits SearchDialogBase for GUI.
+Uses idlelib.SearchEngine for search capability.
+Defines various replace related functions like replace, replace all,
+replace+find.
+"""
from tkinter import *
from idlelib import SearchEngine
def replace(text):
+ """Returns a singleton ReplaceDialog instance.The single dialog
+ saves user entries and preferences across instances."""
root = text._root()
engine = SearchEngine.get(root)
if not hasattr(engine, "_replacedialog"):
self.replvar = StringVar(root)
def open(self, text):
+ """Display the replace dialog"""
SearchDialogBase.open(self, text)
try:
first = text.index("sel.first")
self.ok = 1
def create_entries(self):
+ """Create label and text entry widgets"""
SearchDialogBase.create_entries(self)
self.replent = self.make_entry("Replace with:", self.replvar)[0]
self.do_replace()
def default_command(self, event=None):
+ "Replace and find next."
if self.do_find(self.ok):
- if self.do_replace(): # Only find next match if replace succeeded.
- # A bad re can cause it to fail.
+ if self.do_replace(): # Only find next match if replace succeeded.
+ # A bad re can cause it to fail.
self.do_find(0)
def _replace_expand(self, m, repl):
return new
def replace_all(self, event=None):
+ """Replace all instances of patvar with replvar in text"""
prog = self.engine.getprog()
if not prog:
return
return True
def show_hit(self, first, last):
+ """Highlight text from 'first' to 'last'.
+ 'first', 'last' - Text indices"""
text = self.text
text.mark_set("insert", first)
text.tag_remove("sel", "1.0", "end")
SearchDialogBase.close(self, event)
self.text.tag_remove("hit", "1.0", "end")
-def _replace_dialog(parent):
- root = Tk()
- root.title("Test ReplaceDialog")
+
+def _replace_dialog(parent): # htest #
+ """htest wrapper function"""
+ box = Toplevel(parent)
+ box.title("Test ReplaceDialog")
width, height, x, y = list(map(int, re.split('[x+]', parent.geometry())))
- root.geometry("+%d+%d"%(x, y + 150))
+ box.geometry("+%d+%d"%(x, y + 150))
# mock undo delegator methods
def undo_block_start():
def undo_block_stop():
pass
- text = Text(root)
+ text = Text(box, inactiveselectbackground='gray')
text.undo_block_start = undo_block_start
text.undo_block_stop = undo_block_stop
text.pack()
- text.insert("insert","This is a sample string.\n"*10)
+ text.insert("insert","This is a sample sTring\nPlus MORE.")
+ text.focus_set()
def show_replace():
text.tag_add(SEL, "1.0", END)
replace(text)
text.tag_remove(SEL, "1.0", END)
- button = Button(root, text="Replace", command=show_replace)
+ button = Button(box, text="Replace", command=show_replace)
button.pack()
if __name__ == '__main__':
+ import unittest
+ unittest.main('idlelib.idle_test.test_replacedialog',
+ verbosity=2, exit=False)
+
from idlelib.idle_test.htest import run
run(_replace_dialog)
from idlelib.SearchDialogBase import SearchDialogBase
def _setup(text):
+ "Create or find the singleton SearchDialog instance."
root = text._root()
engine = SearchEngine.get(root)
if not hasattr(engine, "_searchdialog"):
return engine._searchdialog
def find(text):
+ "Handle the editor edit menu item and corresponding event."
pat = text.get("sel.first", "sel.last")
- return _setup(text).open(text,pat)
+ return _setup(text).open(text, pat) # Open is inherited from SDBase.
def find_again(text):
+ "Handle the editor edit menu item and corresponding event."
return _setup(text).find_again(text)
def find_selection(text):
+ "Handle the editor edit menu item and corresponding event."
return _setup(text).find_selection(text)
class SearchDialog(SearchDialogBase):
self.engine.setcookedpat(pat)
return self.find_again(text)
-def _search_dialog(parent):
- root = Tk()
- root.title("Test SearchDialog")
+
+def _search_dialog(parent): # htest #
+ '''Display search test box.'''
+ box = Toplevel(parent)
+ box.title("Test SearchDialog")
width, height, x, y = list(map(int, re.split('[x+]', parent.geometry())))
- root.geometry("+%d+%d"%(x, y + 150))
- text = Text(root)
+ box.geometry("+%d+%d"%(x, y + 150))
+ text = Text(box, inactiveselectbackground='gray')
text.pack()
- text.insert("insert","This is a sample string.\n"*10)
+ text.insert("insert","This is a sample string.\n"*5)
def show_find():
text.tag_add(SEL, "1.0", END)
- s = _setup(text)
- s.open(text)
+ _setup(text).open(text)
text.tag_remove(SEL, "1.0", END)
- button = Button(root, text="Search", command=show_find)
+ button = Button(box, text="Search (selection ignored)", command=show_find)
button.pack()
if __name__ == '__main__':
+ import unittest
+ unittest.main('idlelib.idle_test.test_searchdialog',
+ verbosity=2, exit=False)
from idlelib.idle_test.htest import run
run(_search_dialog)
self.depth = self.depth + incr
return self.depth
-def _undo_delegator(parent):
+
+def _undo_delegator(parent): # htest #
+ import re
+ import tkinter as tk
from idlelib.Percolator import Percolator
- root = Tk()
- root.title("Test UndoDelegator")
+ undowin = tk.Toplevel()
+ undowin.title("Test UndoDelegator")
width, height, x, y = list(map(int, re.split('[x+]', parent.geometry())))
- root.geometry("+%d+%d"%(x, y + 150))
+ undowin.geometry("+%d+%d"%(x, y + 150))
- text = Text(root)
- text.config(height=10)
+ text = Text(undowin, height=10)
text.pack()
text.focus_set()
p = Percolator(text)
d = UndoDelegator()
p.insertfilter(d)
- undo = Button(root, text="Undo", command=lambda:d.undo_event(None))
+ undo = Button(undowin, text="Undo", command=lambda:d.undo_event(None))
undo.pack(side='left')
- redo = Button(root, text="Redo", command=lambda:d.redo_event(None))
+ redo = Button(undowin, text="Redo", command=lambda:d.redo_event(None))
redo.pack(side='left')
- dump = Button(root, text="Dump", command=lambda:d.dump_event(None))
+ dump = Button(undowin, text="Dump", command=lambda:d.dump_event(None))
dump.pack(side='left')
- root.mainloop()
-
if __name__ == "__main__":
+ import unittest
+ unittest.main('idlelib.idle_test.test_undodelegator', verbosity=2,
+ exit=False)
from idlelib.idle_test.htest import run
run(_undo_delegator)
'''Return OriginalCommand(operation) after registering function.
Registration adds an operation: function pair to ._operations.
- It also adds an widget function attribute that masks the tkinter
+ It also adds a widget function attribute that masks the tkinter
class instance method. Method masking operates independently
from command dispatch.
command=self.ShowIDLECredits)
idle_credits_b.pack(side=LEFT, padx=10, pady=10)
+ # License, et all, are of type _sitebuiltins._Printer
def ShowLicense(self):
self.display_printer_text('About - License', license)
def ShowPythonCredits(self):
self.display_printer_text('About - Python Credits', credits)
+ # Encode CREDITS.txt to utf-8 for proper version of Loewis.
+ # Specify others as ascii until need utf-8, so catch errors.
def ShowIDLECredits(self):
- self.display_file_text('About - Credits', 'CREDITS.txt', 'iso-8859-1')
+ self.display_file_text('About - Credits', 'CREDITS.txt', 'utf-8')
def ShowIDLEAbout(self):
- self.display_file_text('About - Readme', 'README.txt')
+ self.display_file_text('About - Readme', 'README.txt', 'ascii')
def ShowIDLENEWS(self):
- self.display_file_text('About - NEWS', 'NEWS.txt')
+ self.display_file_text('About - NEWS', 'NEWS.txt', 'utf-8')
def display_printer_text(self, title, printer):
printer._Printer__setup()
self.autoSave.trace_variable('w', self.VarChanged_autoSave)
self.encoding.trace_variable('w', self.VarChanged_encoding)
+ def remove_var_callbacks(self):
+ "Remove callbacks to prevent memory leaks."
+ for var in (
+ self.fontSize, self.fontName, self.fontBold,
+ self.spaceNum, self.colour, self.builtinTheme,
+ self.customTheme, self.themeIsBuiltin, self.highlightTarget,
+ self.keyBinding, self.builtinKeys, self.customKeys,
+ self.keysAreBuiltin, self.winWidth, self.winHeight,
+ self.startupEdit, self.autoSave, self.encoding,):
+ var.trace_vdelete('w', var.trace_vinfo()[0][1])
+
def VarChanged_font(self, *params):
'''When one font attribute changes, save them all, as they are
not independent from each other. In particular, when we are
All values are treated as text, and it is up to the user to supply
reasonable values. The only exception to this are the 'enable*' options,
- which are boolean, and can be toggled with an True/False button.
+ which are boolean, and can be toggled with a True/False button.
"""
parent = self.parent
frame = self.tabPages.pages['Extensions'].frame
actualFont = Font.actual(f)
family = actualFont['family']
size = actualFont['size']
- if size < 0:
+ if size <= 0:
size = 10 # if font in pixels, ignore actual size
bold = actualFont['weight']=='bold'
return (family, size, 'bold' if bold else 'normal')
self.title(title)
self.transient(parent)
self.grab_set()
- self.protocol("WM_DELETE_WINDOW", self.Cancel)
+ self.protocol("WM_DELETE_WINDOW", self.cancel)
self.parent = parent
self.result = None
- self.CreateWidgets()
+ self.create_widgets()
self.menu.set(menuItem)
self.path.set(filePath)
self.withdraw() #hide while setting geometry
((parent.winfo_height()/2 - self.winfo_reqheight()/2)
if not _htest else 150)))
self.deiconify() #geometry set, unhide
- self.bind('<Return>', self.Ok)
+ self.bind('<Return>', self.ok)
self.wait_window()
- def CreateWidgets(self):
+ def create_widgets(self):
self.menu = StringVar(self)
self.path = StringVar(self)
self.fontSize = StringVar(self)
labelPath.pack(anchor=W, padx=5, pady=3)
self.entryPath.pack(anchor=W, padx=5, pady=3)
browseButton = Button(self.frameMain, text='Browse', width=8,
- command=self.browseFile)
+ command=self.browse_file)
browseButton.pack(pady=3)
frameButtons = Frame(self)
frameButtons.pack(side=BOTTOM, fill=X)
self.buttonOk = Button(frameButtons, text='OK',
- width=8, default=ACTIVE, command=self.Ok)
+ width=8, default=ACTIVE, command=self.ok)
self.buttonOk.grid(row=0, column=0, padx=5,pady=5)
self.buttonCancel = Button(frameButtons, text='Cancel',
- width=8, command=self.Cancel)
+ width=8, command=self.cancel)
self.buttonCancel.grid(row=0, column=1, padx=5, pady=5)
- def browseFile(self):
+ def browse_file(self):
filetypes = [
("HTML Files", "*.htm *.html", "TEXT"),
("PDF Files", "*.pdf", "TEXT"),
if file:
self.path.set(file)
- def MenuOk(self):
+ def menu_ok(self):
"Simple validity check for a sensible menu item name"
- menuOk = True
+ menu_ok = True
menu = self.menu.get()
menu.strip()
if not menu:
message='No menu item specified',
parent=self)
self.entryMenu.focus_set()
- menuOk = False
+ menu_ok = False
elif len(menu) > 30:
tkMessageBox.showerror(title='Menu Item Error',
message='Menu item too long:'
'\nLimit 30 characters.',
parent=self)
self.entryMenu.focus_set()
- menuOk = False
- return menuOk
+ menu_ok = False
+ return menu_ok
- def PathOk(self):
+ def path_ok(self):
"Simple validity check for menu file path"
- pathOk = True
+ path_ok = True
path = self.path.get()
path.strip()
if not path: #no path specified
message='No help file path specified.',
parent=self)
self.entryPath.focus_set()
- pathOk = False
+ path_ok = False
elif path.startswith(('www.', 'http')):
pass
else:
message='Help file path does not exist.',
parent=self)
self.entryPath.focus_set()
- pathOk = False
- return pathOk
+ path_ok = False
+ return path_ok
- def Ok(self, event=None):
- if self.MenuOk() and self.PathOk():
+ def ok(self, event=None):
+ if self.menu_ok() and self.path_ok():
self.result = (self.menu.get().strip(),
self.path.get().strip())
if sys.platform == 'darwin':
path = self.result[1]
- if path.startswith(('www', 'file:', 'http:')):
+ if path.startswith(('www', 'file:', 'http:', 'https:')):
pass
else:
# Mac Safari insists on using the URI form for local files
self.result[1] = "file://" + path
self.destroy()
- def Cancel(self, event=None):
+ def cancel(self, event=None):
self.result = None
self.destroy()
if __name__ == '__main__':
+ import unittest
+ unittest.main('idlelib.idle_test.test_config_help',
+ verbosity=2, exit=False)
+
from idlelib.idle_test.htest import run
run(GetHelpSourceDialog)
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <title>25.5. IDLE — Python 3.4.3 documentation</title>
+ <title>25.5. IDLE — Python 3.5.1 documentation</title>
<link rel="stylesheet" href="../_static/pydoctheme.css" type="text/css" />
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '../',
- VERSION: '3.4.3',
+ VERSION: '3.5.1',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
<script type="text/javascript" src="../_static/doctools.js"></script>
<script type="text/javascript" src="../_static/sidebar.js"></script>
<link rel="search" type="application/opensearchdescription+xml"
- title="Search within Python 3.4.3 documentation"
+ title="Search within Python 3.5.1 documentation"
href="../_static/opensearch.xml"/>
<link rel="author" title="About these documents" href="../about.html" />
<link rel="copyright" title="Copyright" href="../copyright.html" />
- <link rel="top" title="Python 3.4.3 documentation" href="../index.html" />
+ <link rel="top" title="Python 3.5.1 documentation" href="../contents.html" />
<link rel="up" title="25. Graphical User Interfaces with Tk" href="tk.html" />
<link rel="next" title="25.6. Other Graphical User Interface Packages" href="othergui.html" />
<link rel="prev" title="25.4. tkinter.scrolledtext — Scrolled Text Widget" href="tkinter.scrolledtext.html" />
</head>
- <body>
- <div class="related">
+ <body role="document">
+ <div class="related" role="navigation" aria-label="related navigation">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
style="vertical-align: middle; margin-top: -1px"/></li>
<li><a href="https://www.python.org/">Python</a> »</li>
<li>
- <a href="../index.html">3.4.3 Documentation</a> »
+ <a href="../index.html">3.5.1 Documentation</a> »
</li>
- <li><a href="index.html" >The Python Standard Library</a> »</li>
- <li><a href="tk.html" accesskey="U">25. Graphical User Interfaces with Tk</a> »</li>
+ <li class="nav-item nav-item-1"><a href="index.html" >The Python Standard Library</a> »</li>
+ <li class="nav-item nav-item-2"><a href="tk.html" accesskey="U">25. Graphical User Interfaces with Tk</a> »</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
- <div class="body">
+ <div class="body" role="main">
<div class="section" id="idle">
<span id="id1"></span><h1>25.5. IDLE<a class="headerlink" href="#idle" title="Permalink to this headline">¶</a></h1>
-<p id="index-0">IDLE is Python’s Integrated Development and Learning Environment.</p>
+<p><strong>Source code:</strong> <a class="reference external" href="https://hg.python.org/cpython/file/3.5/Lib/idlelib/">Lib/idlelib/</a></p>
+<hr class="docutils" id="index-0" />
+<p>IDLE is Python’s Integrated Development and Learning Environment.</p>
<p>IDLE has the following features:</p>
<ul class="simple">
-<li>coded in 100% pure Python, using the <a class="reference internal" href="tkinter.html#module-tkinter" title="tkinter: Interface to Tcl/Tk for graphical user interfaces"><tt class="xref py py-mod docutils literal"><span class="pre">tkinter</span></tt></a> GUI toolkit</li>
+<li>coded in 100% pure Python, using the <a class="reference internal" href="tkinter.html#module-tkinter" title="tkinter: Interface to Tcl/Tk for graphical user interfaces"><code class="xref py py-mod docutils literal"><span class="pre">tkinter</span></code></a> GUI toolkit</li>
<li>cross-platform: works mostly the same on Windows, Unix, and Mac OS X</li>
<li>Python shell window (interactive interpreter) with colorizing
of code input, output, and error messages</li>
<dt>Find Selection</dt>
<dd>Search for the currently selected string, if there is one.</dd>
<dt>Find in Files...</dt>
-<dd>Open a file search dialog. Put results in an new output window.</dd>
+<dd>Open a file search dialog. Put results in a new output window.</dd>
<dt>Replace...</dt>
<dd>Open a search-and-replace dialog.</dd>
<dt>Go to Line</dt>
<dt>Run Module</dt>
<dd>Do Check Module (above). If no error, restart the shell to clean the
environment, then execute the module. Output is displayed in the Shell
-window. Note that output requires use of <tt class="docutils literal"><span class="pre">print</span></tt> or <tt class="docutils literal"><span class="pre">write</span></tt>.
+window. Note that output requires use of <code class="docutils literal"><span class="pre">print</span></code> or <code class="docutils literal"><span class="pre">write</span></code>.
When execution is complete, the Shell retains focus and displays a prompt.
At this point, one may interactively explore the result of execution.
-This is similar to executing a file with <tt class="docutils literal"><span class="pre">python</span> <span class="pre">-i</span> <span class="pre">file</span></tt> at a command
+This is similar to executing a file with <code class="docutils literal"><span class="pre">python</span> <span class="pre">-i</span> <span class="pre">file</span></code> at a command
line.</dd>
</dl>
</div>
</div>
<div class="section" id="editing-and-navigation">
<h2>25.5.2. Editing and navigation<a class="headerlink" href="#editing-and-navigation" title="Permalink to this headline">¶</a></h2>
-<p>In this section, ‘C’ refers to the <tt class="kbd docutils literal"><span class="pre">Control</span></tt> key on Windows and Unix and
-the <tt class="kbd docutils literal"><span class="pre">Command</span></tt> key on Mac OSX.</p>
+<p>In this section, ‘C’ refers to the <code class="kbd docutils literal"><span class="pre">Control</span></code> key on Windows and Unix and
+the <code class="kbd docutils literal"><span class="pre">Command</span></code> key on Mac OSX.</p>
<ul>
-<li><p class="first"><tt class="kbd docutils literal"><span class="pre">Backspace</span></tt> deletes to the left; <tt class="kbd docutils literal"><span class="pre">Del</span></tt> deletes to the right</p>
+<li><p class="first"><code class="kbd docutils literal"><span class="pre">Backspace</span></code> deletes to the left; <code class="kbd docutils literal"><span class="pre">Del</span></code> deletes to the right</p>
</li>
-<li><p class="first"><tt class="kbd docutils literal"><span class="pre">C-Backspace</span></tt> delete word left; <tt class="kbd docutils literal"><span class="pre">C-Del</span></tt> delete word to the right</p>
+<li><p class="first"><code class="kbd docutils literal"><span class="pre">C-Backspace</span></code> delete word left; <code class="kbd docutils literal"><span class="pre">C-Del</span></code> delete word to the right</p>
</li>
-<li><p class="first">Arrow keys and <tt class="kbd docutils literal"><span class="pre">Page</span> <span class="pre">Up</span></tt>/<tt class="kbd docutils literal"><span class="pre">Page</span> <span class="pre">Down</span></tt> to move around</p>
+<li><p class="first">Arrow keys and <code class="kbd docutils literal"><span class="pre">Page</span> <span class="pre">Up</span></code>/<code class="kbd docutils literal"><span class="pre">Page</span> <span class="pre">Down</span></code> to move around</p>
</li>
-<li><p class="first"><tt class="kbd docutils literal"><span class="pre">C-LeftArrow</span></tt> and <tt class="kbd docutils literal"><span class="pre">C-RightArrow</span></tt> moves by words</p>
+<li><p class="first"><code class="kbd docutils literal"><span class="pre">C-LeftArrow</span></code> and <code class="kbd docutils literal"><span class="pre">C-RightArrow</span></code> moves by words</p>
</li>
-<li><p class="first"><tt class="kbd docutils literal"><span class="pre">Home</span></tt>/<tt class="kbd docutils literal"><span class="pre">End</span></tt> go to begin/end of line</p>
+<li><p class="first"><code class="kbd docutils literal"><span class="pre">Home</span></code>/<code class="kbd docutils literal"><span class="pre">End</span></code> go to begin/end of line</p>
</li>
-<li><p class="first"><tt class="kbd docutils literal"><span class="pre">C-Home</span></tt>/<tt class="kbd docutils literal"><span class="pre">C-End</span></tt> go to begin/end of file</p>
+<li><p class="first"><code class="kbd docutils literal"><span class="pre">C-Home</span></code>/<code class="kbd docutils literal"><span class="pre">C-End</span></code> go to begin/end of file</p>
</li>
<li><p class="first">Some useful Emacs bindings are inherited from Tcl/Tk:</p>
<blockquote>
<div><ul class="simple">
-<li><tt class="kbd docutils literal"><span class="pre">C-a</span></tt> beginning of line</li>
-<li><tt class="kbd docutils literal"><span class="pre">C-e</span></tt> end of line</li>
-<li><tt class="kbd docutils literal"><span class="pre">C-k</span></tt> kill line (but doesn’t put it in clipboard)</li>
-<li><tt class="kbd docutils literal"><span class="pre">C-l</span></tt> center window around the insertion point</li>
-<li><tt class="kbd docutils literal"><span class="pre">C-b</span></tt> go backwards one character without deleting (usually you can
+<li><code class="kbd docutils literal"><span class="pre">C-a</span></code> beginning of line</li>
+<li><code class="kbd docutils literal"><span class="pre">C-e</span></code> end of line</li>
+<li><code class="kbd docutils literal"><span class="pre">C-k</span></code> kill line (but doesn’t put it in clipboard)</li>
+<li><code class="kbd docutils literal"><span class="pre">C-l</span></code> center window around the insertion point</li>
+<li><code class="kbd docutils literal"><span class="pre">C-b</span></code> go backwards one character without deleting (usually you can
also use the cursor key for this)</li>
-<li><tt class="kbd docutils literal"><span class="pre">C-f</span></tt> go forward one character without deleting (usually you can
+<li><code class="kbd docutils literal"><span class="pre">C-f</span></code> go forward one character without deleting (usually you can
also use the cursor key for this)</li>
-<li><tt class="kbd docutils literal"><span class="pre">C-p</span></tt> go up one line (usually you can also use the cursor key for
+<li><code class="kbd docutils literal"><span class="pre">C-p</span></code> go up one line (usually you can also use the cursor key for
this)</li>
-<li><tt class="kbd docutils literal"><span class="pre">C-d</span></tt> delete next character</li>
+<li><code class="kbd docutils literal"><span class="pre">C-d</span></code> delete next character</li>
</ul>
</div></blockquote>
</li>
</ul>
-<p>Standard keybindings (like <tt class="kbd docutils literal"><span class="pre">C-c</span></tt> to copy and <tt class="kbd docutils literal"><span class="pre">C-v</span></tt> to paste)
+<p>Standard keybindings (like <code class="kbd docutils literal"><span class="pre">C-c</span></code> to copy and <code class="kbd docutils literal"><span class="pre">C-v</span></code> to paste)
may work. Keybindings are selected in the Configure IDLE dialog.</p>
<div class="section" id="automatic-indentation">
<h3>25.5.2.1. Automatic indentation<a class="headerlink" href="#automatic-indentation" title="Permalink to this headline">¶</a></h3>
<p>After a block-opening statement, the next line is indented by 4 spaces (in the
Python Shell window by one tab). After certain keywords (break, return etc.)
-the next line is dedented. In leading indentation, <tt class="kbd docutils literal"><span class="pre">Backspace</span></tt> deletes up
-to 4 spaces if they are there. <tt class="kbd docutils literal"><span class="pre">Tab</span></tt> inserts spaces (in the Python
+the next line is dedented. In leading indentation, <code class="kbd docutils literal"><span class="pre">Backspace</span></code> deletes up
+to 4 spaces if they are there. <code class="kbd docutils literal"><span class="pre">Tab</span></code> inserts spaces (in the Python
Shell window one tab), number depends on Indent width. Currently tabs
are restricted to four spaces due to Tcl/Tk limitations.</p>
<p>See also the indent/dedent region commands in the edit menu.</p>
of those characters (plus zero or more other characters) a tab is typed
the ACW will open immediately if a possible continuation is found.</p>
<p>If there is only one possible completion for the characters entered, a
-<tt class="kbd docutils literal"><span class="pre">Tab</span></tt> will supply that completion without opening the ACW.</p>
+<code class="kbd docutils literal"><span class="pre">Tab</span></code> will supply that completion without opening the ACW.</p>
<p>‘Show Completions’ will force open a completions window, by default the
-<tt class="kbd docutils literal"><span class="pre">C-space</span></tt> will open a completions window. In an empty
+<code class="kbd docutils literal"><span class="pre">C-space</span></code> will open a completions window. In an empty
string, this will contain the files in the current directory. On a
blank line, it will contain the built-in and user-defined functions and
classes in the current name spaces, plus any modules imported. If some
characters have been entered, the ACW will attempt to be more specific.</p>
<p>If a string of characters is typed, the ACW selection will jump to the
-entry most closely matching those characters. Entering a <tt class="kbd docutils literal"><span class="pre">tab</span></tt> will
+entry most closely matching those characters. Entering a <code class="kbd docutils literal"><span class="pre">tab</span></code> will
cause the longest non-ambiguous match to be entered in the Editor window or
-Shell. Two <tt class="kbd docutils literal"><span class="pre">tab</span></tt> in a row will supply the current ACW selection, as
+Shell. Two <code class="kbd docutils literal"><span class="pre">tab</span></code> in a row will supply the current ACW selection, as
will return or a double click. Cursor keys, Page Up/Down, mouse selection,
and the scroll wheel all operate on the ACW.</p>
<p>“Hidden” attributes can be accessed by typing the beginning of hidden
name after a ‘.’, e.g. ‘_’. This allows access to modules with
-<tt class="docutils literal"><span class="pre">__all__</span></tt> set, or to class-private attributes.</p>
+<code class="docutils literal"><span class="pre">__all__</span></code> set, or to class-private attributes.</p>
<p>Completions and the ‘Expand Word’ facility can save a lot of typing!</p>
<p>Completions are currently limited to those in the namespaces. Names in
-an Editor window which are not via <tt class="docutils literal"><span class="pre">__main__</span></tt> and <a class="reference internal" href="sys.html#sys.modules" title="sys.modules"><tt class="xref py py-data docutils literal"><span class="pre">sys.modules</span></tt></a> will
+an Editor window which are not via <code class="docutils literal"><span class="pre">__main__</span></code> and <a class="reference internal" href="sys.html#sys.modules" title="sys.modules"><code class="xref py py-data docutils literal"><span class="pre">sys.modules</span></code></a> will
not be found. Run the module once with your imports to correct this situation.
Note that IDLE itself places quite a few modules in sys.modules, so
much can be found by default, e.g. the re module.</p>
</div>
<div class="section" id="calltips">
<h3>25.5.2.3. Calltips<a class="headerlink" href="#calltips" title="Permalink to this headline">¶</a></h3>
-<p>A calltip is shown when one types <tt class="kbd docutils literal"><span class="pre">(</span></tt> after the name of an <em>acccessible</em>
+<p>A calltip is shown when one types <code class="kbd docutils literal"><span class="pre">(</span></code> after the name of an <em>acccessible</em>
function. A name expression may include dots and subscripts. A calltip
remains until it is clicked, the cursor is moved out of the argument area,
-or <tt class="kbd docutils literal"><span class="pre">)</span></tt> is typed. When the cursor is in the argument part of a definition,
+or <code class="kbd docutils literal"><span class="pre">)</span></code> is typed. When the cursor is in the argument part of a definition,
the menu or shortcut display a calltip.</p>
<p>A calltip consists of the function signature and the first line of the
docstring. For builtins without an accessible signature, the calltip
<p>The set of <em>accessible</em> functions depends on what modules have been imported
into the user process, including those imported by Idle itself,
and what definitions have been run, all since the last restart.</p>
-<p>For example, restart the Shell and enter <tt class="docutils literal"><span class="pre">itertools.count(</span></tt>. A calltip
+<p>For example, restart the Shell and enter <code class="docutils literal"><span class="pre">itertools.count(</span></code>. A calltip
appears because Idle imports itertools into the user process for its own use.
-(This could change.) Enter <tt class="docutils literal"><span class="pre">turtle.write(</span></tt> and nothing appears. Idle does
+(This could change.) Enter <code class="docutils literal"><span class="pre">turtle.write(</span></code> and nothing appears. Idle does
not import turtle. The menu or shortcut do nothing either. Enter
-<tt class="docutils literal"><span class="pre">import</span> <span class="pre">turtle</span></tt> and then <tt class="docutils literal"><span class="pre">turtle.write(</span></tt> will work.</p>
+<code class="docutils literal"><span class="pre">import</span> <span class="pre">turtle</span></code> and then <code class="docutils literal"><span class="pre">turtle.write(</span></code> will work.</p>
<p>In an editor, import statements have no effect until one runs the file. One
might want to run a file after writing the import statements at the top,
or immediately run an existing file before editing.</p>
<div class="section" id="python-shell-window">
<h3>25.5.2.4. Python Shell window<a class="headerlink" href="#python-shell-window" title="Permalink to this headline">¶</a></h3>
<ul>
-<li><p class="first"><tt class="kbd docutils literal"><span class="pre">C-c</span></tt> interrupts executing command</p>
+<li><p class="first"><code class="kbd docutils literal"><span class="pre">C-c</span></code> interrupts executing command</p>
</li>
-<li><p class="first"><tt class="kbd docutils literal"><span class="pre">C-d</span></tt> sends end-of-file; closes window if typed at a <tt class="docutils literal"><span class="pre">>>></span></tt> prompt</p>
+<li><p class="first"><code class="kbd docutils literal"><span class="pre">C-d</span></code> sends end-of-file; closes window if typed at a <code class="docutils literal"><span class="pre">>>></span></code> prompt</p>
</li>
-<li><p class="first"><tt class="kbd docutils literal"><span class="pre">Alt-/</span></tt> (Expand word) is also useful to reduce typing</p>
+<li><p class="first"><code class="kbd docutils literal"><span class="pre">Alt-/</span></code> (Expand word) is also useful to reduce typing</p>
<p>Command history</p>
<ul class="simple">
-<li><tt class="kbd docutils literal"><span class="pre">Alt-p</span></tt> retrieves previous command matching what you have typed. On
-OS X use <tt class="kbd docutils literal"><span class="pre">C-p</span></tt>.</li>
-<li><tt class="kbd docutils literal"><span class="pre">Alt-n</span></tt> retrieves next. On OS X use <tt class="kbd docutils literal"><span class="pre">C-n</span></tt>.</li>
-<li><tt class="kbd docutils literal"><span class="pre">Return</span></tt> while on any previous command retrieves that command</li>
+<li><code class="kbd docutils literal"><span class="pre">Alt-p</span></code> retrieves previous command matching what you have typed. On
+OS X use <code class="kbd docutils literal"><span class="pre">C-p</span></code>.</li>
+<li><code class="kbd docutils literal"><span class="pre">Alt-n</span></code> retrieves next. On OS X use <code class="kbd docutils literal"><span class="pre">C-n</span></code>.</li>
+<li><code class="kbd docutils literal"><span class="pre">Return</span></code> while on any previous command retrieves that command</li>
</ul>
</li>
</ul>
<p>Idle defaults to black on white text, but colors text with special meanings.
For the shell, these are shell output, shell error, user output, and
user error. For Python code, at the shell prompt or in an editor, these are
-keywords, builtin class and function names, names following <tt class="docutils literal"><span class="pre">class</span></tt> and
-<tt class="docutils literal"><span class="pre">def</span></tt>, strings, and comments. For any text window, these are the cursor (when
+keywords, builtin class and function names, names following <code class="docutils literal"><span class="pre">class</span></code> and
+<code class="docutils literal"><span class="pre">def</span></code>, strings, and comments. For any text window, these are the cursor (when
present), found text (when possible), and selected text.</p>
<p>Text coloring is done in the background, so uncolorized text is occasionally
visible. To change the color scheme, use the Configure IDLE dialog
</div>
<div class="section" id="startup-and-code-execution">
<h2>25.5.3. Startup and code execution<a class="headerlink" href="#startup-and-code-execution" title="Permalink to this headline">¶</a></h2>
-<p>Upon startup with the <tt class="docutils literal"><span class="pre">-s</span></tt> option, IDLE will execute the file referenced by
-the environment variables <span class="target" id="index-5"></span><tt class="xref std std-envvar docutils literal"><span class="pre">IDLESTARTUP</span></tt> or <span class="target" id="index-6"></span><a class="reference internal" href="../using/cmdline.html#envvar-PYTHONSTARTUP"><tt class="xref std std-envvar docutils literal"><span class="pre">PYTHONSTARTUP</span></tt></a>.
-IDLE first checks for <tt class="docutils literal"><span class="pre">IDLESTARTUP</span></tt>; if <tt class="docutils literal"><span class="pre">IDLESTARTUP</span></tt> is present the file
-referenced is run. If <tt class="docutils literal"><span class="pre">IDLESTARTUP</span></tt> is not present, IDLE checks for
-<tt class="docutils literal"><span class="pre">PYTHONSTARTUP</span></tt>. Files referenced by these environment variables are
+<p>Upon startup with the <code class="docutils literal"><span class="pre">-s</span></code> option, IDLE will execute the file referenced by
+the environment variables <span class="target" id="index-5"></span><code class="xref std std-envvar docutils literal"><span class="pre">IDLESTARTUP</span></code> or <span class="target" id="index-6"></span><a class="reference internal" href="../using/cmdline.html#envvar-PYTHONSTARTUP"><code class="xref std std-envvar docutils literal"><span class="pre">PYTHONSTARTUP</span></code></a>.
+IDLE first checks for <code class="docutils literal"><span class="pre">IDLESTARTUP</span></code>; if <code class="docutils literal"><span class="pre">IDLESTARTUP</span></code> is present the file
+referenced is run. If <code class="docutils literal"><span class="pre">IDLESTARTUP</span></code> is not present, IDLE checks for
+<code class="docutils literal"><span class="pre">PYTHONSTARTUP</span></code>. Files referenced by these environment variables are
convenient places to store functions that are used frequently from the IDLE
shell, or for executing import statements to import common modules.</p>
-<p>In addition, <tt class="docutils literal"><span class="pre">Tk</span></tt> also loads a startup file if it is present. Note that the
-Tk file is loaded unconditionally. This additional file is <tt class="docutils literal"><span class="pre">.Idle.py</span></tt> and is
+<p>In addition, <code class="docutils literal"><span class="pre">Tk</span></code> also loads a startup file if it is present. Note that the
+Tk file is loaded unconditionally. This additional file is <code class="docutils literal"><span class="pre">.Idle.py</span></code> and is
looked for in the user’s home directory. Statements in this file will be
executed in the Tk namespace, so this file is not useful for importing
functions to be used from IDLE’s Python shell.</p>
</div>
<p>If there are arguments:</p>
<ul class="simple">
-<li>If <tt class="docutils literal"><span class="pre">-</span></tt>, <tt class="docutils literal"><span class="pre">-c</span></tt>, or <tt class="docutils literal"><span class="pre">r</span></tt> is used, all arguments are placed in
-<tt class="docutils literal"><span class="pre">sys.argv[1:...]</span></tt> and <tt class="docutils literal"><span class="pre">sys.argv[0]</span></tt> is set to <tt class="docutils literal"><span class="pre">''</span></tt>, <tt class="docutils literal"><span class="pre">'-c'</span></tt>,
-or <tt class="docutils literal"><span class="pre">'-r'</span></tt>. No editor window is opened, even if that is the default
+<li>If <code class="docutils literal"><span class="pre">-</span></code>, <code class="docutils literal"><span class="pre">-c</span></code>, or <code class="docutils literal"><span class="pre">r</span></code> is used, all arguments are placed in
+<code class="docutils literal"><span class="pre">sys.argv[1:...]</span></code> and <code class="docutils literal"><span class="pre">sys.argv[0]</span></code> is set to <code class="docutils literal"><span class="pre">''</span></code>, <code class="docutils literal"><span class="pre">'-c'</span></code>,
+or <code class="docutils literal"><span class="pre">'-r'</span></code>. No editor window is opened, even if that is the default
set in the Options dialog.</li>
<li>Otherwise, arguments are files opened for editing and
-<tt class="docutils literal"><span class="pre">sys.argv</span></tt> reflects the arguments passed to IDLE itself.</li>
+<code class="docutils literal"><span class="pre">sys.argv</span></code> reflects the arguments passed to IDLE itself.</li>
</ul>
</div>
<div class="section" id="idle-console-differences">
<h3>25.5.3.2. IDLE-console differences<a class="headerlink" href="#idle-console-differences" title="Permalink to this headline">¶</a></h3>
<p>As much as possible, the result of executing Python code with IDLE is the
same as executing the same code in a console window. However, the different
-interface and operation occasionally affects results.</p>
-<p>For instance, IDLE normally executes user code in a separate process from
-the IDLE GUI itself. The IDLE versions of sys.stdin, .stdout, and .stderr in the
-execution process get input from and send output to the GUI process,
-which keeps control of the keyboard and screen. This is normally transparent,
-but code that access these object will see different attribute values.
-Also, functions that directly access the keyboard and screen will not work.</p>
+interface and operation occasionally affects visible results. For instance,
+<code class="docutils literal"><span class="pre">sys.modules</span></code> starts with more entries.</p>
+<p>IDLE also replaces <code class="docutils literal"><span class="pre">sys.stdin</span></code>, <code class="docutils literal"><span class="pre">sys.stdout</span></code>, and <code class="docutils literal"><span class="pre">sys.stderr</span></code> with
+objects that get input from and send output to the Shell window.
+When this window has the focus, it controls the keyboard and screen.
+This is normally transparent, but functions that directly access the keyboard
+and screen will not work. If <code class="docutils literal"><span class="pre">sys</span></code> is reset with <code class="docutils literal"><span class="pre">importlib.reload(sys)</span></code>,
+IDLE’s changes are lost and things li ke <code class="docutils literal"><span class="pre">input</span></code>, <code class="docutils literal"><span class="pre">raw_input</span></code>, and
+<code class="docutils literal"><span class="pre">print</span></code> will not work correctly.</p>
<p>With IDLE’s Shell, one enters, edits, and recalls complete statements.
Some consoles only work with a single physical line at a time.</p>
</div>
</div>
</div>
</div>
- <div class="sphinxsidebar">
+ <div class="sphinxsidebar" role="navigation" aria-label="main navigation">
<div class="sphinxsidebarwrapper">
<h3><a href="../contents.html">Table Of Contents</a></h3>
<ul>
<h4>Previous topic</h4>
<p class="topless"><a href="tkinter.scrolledtext.html"
- title="previous chapter">25.4. <tt class="docutils literal"><span class="pre">tkinter.scrolledtext</span></tt> — Scrolled Text Widget</a></p>
+ title="previous chapter">25.4. <code class="docutils literal"><span class="pre">tkinter.scrolledtext</span></code> — Scrolled Text Widget</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="othergui.html"
title="next chapter">25.6. Other Graphical User Interface Packages</a></p>
rel="nofollow">Show Source</a></li>
</ul>
-<div id="searchbox" style="display: none">
+<div id="searchbox" style="display: none" role="search">
<h3>Quick search</h3>
<form class="search" action="../search.html" method="get">
<input type="text" name="q" />
</div>
<div class="clearer"></div>
</div>
- <div class="related">
+ <div class="related" role="navigation" aria-label="related navigation">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
style="vertical-align: middle; margin-top: -1px"/></li>
<li><a href="https://www.python.org/">Python</a> »</li>
<li>
- <a href="../index.html">3.4.3 Documentation</a> »
+ <a href="../index.html">3.5.1 Documentation</a> »
</li>
- <li><a href="index.html" >The Python Standard Library</a> »</li>
- <li><a href="tk.html" >25. Graphical User Interfaces with Tk</a> »</li>
+ <li class="nav-item nav-item-1"><a href="index.html" >The Python Standard Library</a> »</li>
+ <li class="nav-item nav-item-2"><a href="tk.html" >25. Graphical User Interfaces with Tk</a> »</li>
</ul>
</div>
<div class="footer">
- © <a href="../copyright.html">Copyright</a> 1990-2015, Python Software Foundation.
+ © <a href="../copyright.html">Copyright</a> 2001-2016, Python Software Foundation.
<br />
The Python Software Foundation is a non-profit corporation.
<a href="https://www.python.org/psf/donations/">Please donate.</a>
<br />
- Last updated on Oct 13, 2015.
+ Last updated on Jun 11, 2016.
<a href="../bugs.html">Found a bug</a>?
<br />
- Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.2.3.
+ Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.3.3.
</div>
</body>
Doc/library/idle.rst (Sphinx)=> Doc/build/html/library/idle.html
(help.copy_strip)=> Lib/idlelib/help.html
-HelpParser - Parse help.html and and render to tk Text.
+HelpParser - Parse help.html and render to tk Text.
HelpText - Display formatted help.html.
The overridden handle_xyz methods handle a subset of html tags.
The supplied text should have the needed tag configurations.
The behavior for unsupported tags, such as table, is undefined.
+ If the tags generated by Sphinx change, this class, especially
+ the handle_starttag and handle_endtags methods, might have to also.
"""
def __init__(self, text):
HTMLParser.__init__(self, convert_charrefs=True)
def copy_strip():
- "Copy idle.html to idlelib/help.html, stripping trailing whitespace."
+ """Copy idle.html to idlelib/help.html, stripping trailing whitespace.
+
+ Files with trailing whitespace cannot be pushed to the hg cpython
+ repository. For 3.x (on Windows), help.html is generated, after
+ editing idle.rst in the earliest maintenance version, with
+ sphinx-build -bhtml . build/html
+ python_d.exe -c "from idlelib.help import copy_strip; copy_strip()"
+ After refreshing TortoiseHG workshop to generate a diff,
+ check both the diff and displayed text. Push the diff along with
+ the idle.rst change and merge both into default (or an intermediate
+ maintenance version).
+
+ When the 'earlist' version gets its final maintenance release,
+ do an update as described above, without editing idle.rst, to
+ rebase help.html on the next version of idle.rst. Do not worry
+ about version changes as version is not displayed. Examine other
+ changes and the result of Help -> IDLE Help.
+
+ If maintenance and default versions of idle.rst diverge, and
+ merging does not go smoothly, then consider generating
+ separate help.html files from separate idle.htmls.
+ """
src = join(abspath(dirname(dirname(dirname(__file__)))),
'Doc', 'build', 'html', 'library', 'idle.html')
dst = join(abspath(dirname(__file__)), 'help.html')
0. Quick Start
-Automated unit tests were added in 2.7 for Python 2.x and 3.3 for Python 3.x.
+Automated unit tests were added in 3.3 for Python 3.x.
To run the tests from a command line:
python -m test.test_idle
-Human-mediated tests were added later in 2.7 and in 3.4.
+Human-mediated tests were added later in 3.4.
python -m idlelib.idle_test.htest
1. Test Files
The idle directory, idlelib, has over 60 xyz.py files. The idle_test
-subdirectory should contain a test_xyz.py for each, where 'xyz' is lowercased
-even if xyz.py is not. Here is a possible template, with the blanks after after
-'.' and 'as', and before and after '_' to be filled in.
+subdirectory should contain a test_xyz.py for each, where 'xyz' is
+lowercased even if xyz.py is not. Here is a possible template, with the
+blanks after '.' and 'as', and before and after '_' to be filled in.
import unittest
from test.support import requires
if __name__ == '__main__':
unittest.main(verbosity=2)
-Add the following at the end of xyy.py, with the appropriate name added after
-'test_'. Some files already have something like this for htest. If so, insert
-the import and unittest.main lines before the htest lines.
+Add the following at the end of xyy.py, with the appropriate name added
+after 'test_'. Some files already have something like this for htest.
+If so, insert the import and unittest.main lines before the htest lines.
if __name__ == "__main__":
import unittest
2. GUI Tests
-When run as part of the Python test suite, Idle gui tests need to run
-test.support.requires('gui') (test.test_support in 2.7). A test is a gui test
-if it creates a Tk root or master object either directly or indirectly by
-instantiating a tkinter or idle class. For the benefit of test processes that
-either have no graphical environment available or are not allowed to use it, gui
-tests must be 'guarded' by "requires('gui')" in a setUp function or method.
-This will typically be setUpClass.
+When run as part of the Python test suite, Idle GUI tests need to run
+test.support.requires('gui'). A test is a GUI test if it creates a
+tkinter.Tk root or master object either directly or indirectly by
+instantiating a tkinter or idle class. GUI tests cannot run in test
+processes that either have no graphical environment available or are not
+allowed to use it.
-To avoid interfering with other gui tests, all gui objects must be destroyed and
-deleted by the end of the test. Widgets, such as a Tk root, created in a setUpX
-function, should be destroyed in the corresponding tearDownX. Module and class
-widget attributes should also be deleted..
+To guard a module consisting entirely of GUI tests, start with
+
+from test.support import requires
+requires('gui')
+
+To guard a test class, put "requires('gui')" in its setUpClass function.
+
+To avoid interfering with other GUI tests, all GUI objects must be destroyed and
+deleted by the end of the test. The Tk root created in a setUpX function should
+be destroyed in the corresponding tearDownX and the module or class attribute
+deleted. Others widgets should descend from the single root and the attributes
+deleted BEFORE root is destroyed. See https://bugs.python.org/issue20567.
@classmethod
def setUpClass(cls):
requires('gui')
cls.root = tk.Tk()
+ cls.text = tk.Text(root)
@classmethod
def tearDownClass(cls):
+ del cls.text
+ cls.root.update_idletasks()
cls.root.destroy()
del cls.root
+The update_idletasks call is sometimes needed to prevent the following warning
+either when running a test alone or as part of the test suite (#27196).
+ can't invoke "event" command: application has been destroyed
+ ...
+ "ttk::ThemeChanged"
Requires('gui') causes the test(s) it guards to be skipped if any of
-a few conditions are met:
-
- - The tests are being run by regrtest.py, and it was started without enabling
- the "gui" resource with the "-u" command line option.
-
- - The tests are being run on Windows by a service that is not allowed to
- interact with the graphical environment.
-
- - The tests are being run on Mac OSX in a process that cannot make a window
- manager connection.
-
+these conditions are met:
+
+ - The tests are being run by regrtest.py, and it was started without
+ enabling the "gui" resource with the "-u" command line option.
+
+ - The tests are being run on Windows by a service that is not allowed
+ to interact with the graphical environment.
+
+ - The tests are being run on Linux and X Windows is not available.
+
+ - The tests are being run on Mac OSX in a process that cannot make a
+ window manager connection.
+
- tkinter.Tk cannot be successfully instantiated for some reason.
-
+
- test.support.use_resources has been set by something other than
regrtest.py and does not contain "gui".
-
-Tests of non-gui operations should avoid creating tk widgets. Incidental uses of
-tk variables and messageboxes can be replaced by the mock classes in
-idle_test/mock_tk.py. The mock text handles some uses of the tk Text widget.
+
+Tests of non-GUI operations should avoid creating tk widgets. Incidental
+uses of tk variables and messageboxes can be replaced by the mock
+classes in idle_test/mock_tk.py. The mock text handles some uses of the
+tk Text widget.
3. Running Unit Tests
Assume that xyz.py and test_xyz.py both end with a unittest.main() call.
-Running either from an Idle editor runs all tests in the test_xyz file with the
-version of Python running Idle. Test output appears in the Shell window. The
-'verbosity=2' option lists all test methods in the file, which is appropriate
-when developing tests. The 'exit=False' option is needed in xyx.py files when an
-htest follows.
+Running either from an Idle editor runs all tests in the test_xyz file
+with the version of Python running Idle. Test output appears in the
+Shell window. The 'verbosity=2' option lists all test methods in the
+file, which is appropriate when developing tests. The 'exit=False'
+option is needed in xyx.py files when an htest follows.
The following command lines also run all test methods, including
-gui tests, in test_xyz.py. (Both '-m idlelib' and '-m idlelib.idle' start
-Idle and so cannot run tests.)
+GUI tests, in test_xyz.py. (Both '-m idlelib' and '-m idlelib.idle'
+start Idle and so cannot run tests.)
python -m idlelib.xyz
python -m idlelib.idle_test.test_xyz
>>> import unittest
>>> unittest.main('idlelib.idle_test', verbosity=2)
-The following run all Idle tests at a command line. Option '-v' is the same as
-'verbosity=2'. (For 2.7, replace 'test' in the second line with
-'test.regrtest'.)
+The following run all Idle tests at a command line. Option '-v' is the
+same as 'verbosity=2'.
python -m unittest -v idlelib.idle_test
python -m test -v -ugui test_idle
python -m test.test_idle
-The idle tests are 'discovered' by idlelib.idle_test.__init__.load_tests,
-which is also imported into test.test_idle. Normally, neither file should be
-changed when working on individual test modules. The third command runs
-unittest indirectly through regrtest. The same happens when the entire test
-suite is run with 'python -m test'. So that command must work for buildbots
-to stay green. Idle tests must not disturb the environment in a way that
-makes other tests fail (issue 18081).
+The idle tests are 'discovered' by
+idlelib.idle_test.__init__.load_tests, which is also imported into
+test.test_idle. Normally, neither file should be changed when working on
+individual test modules. The third command runs unittest indirectly
+through regrtest. The same happens when the entire test suite is run
+with 'python -m test'. So that command must work for buildbots to stay
+green. Idle tests must not disturb the environment in a way that makes
+other tests fail (issue 18081).
-To run an individual Testcase or test method, extend the dotted name given to
-unittest on the command line.
+To run an individual Testcase or test method, extend the dotted name
+given to unittest on the command line.
python -m unittest -v idlelib.idle_test.test_xyz.Test_case.test_meth
4. Human-mediated Tests
-Human-mediated tests are widget tests that cannot be automated but need human
-verification. They are contained in idlelib/idle_test/htest.py, which has
-instructions. (Some modules need an auxiliary function, identified with # htest
-# on the header line.) The set is about complete, though some tests need
-improvement. To run all htests, run the htest file from an editor or from the
-command line with:
+Human-mediated tests are widget tests that cannot be automated but need
+human verification. They are contained in idlelib/idle_test/htest.py,
+which has instructions. (Some modules need an auxiliary function,
+identified with "# htest # on the header line.) The set is about
+complete, though some tests need improvement. To run all htests, run the
+htest file from an editor or from the command line with:
python -m idlelib.idle_test.htest
+'''idlelib.idle_test is a private implementation of test.test_idle,
+which tests the IDLE application as part of the stdlib test suite.
+Run IDLE tests alone with "python -m test.test_idle".
+This package and its contained modules are subject to change and
+any direct use is at your own risk.
+'''
from os.path import dirname
def load_tests(loader, standard_tests, pattern):
'msg': "Test the following bindings.\n"
"<Control-o> to open file from dialog.\n"
"Edit the file.\n"
+ "<Control-p> to print the file.\n"
"<Control-s> to save the file.\n"
+ "<Alt-s> to save-as another file.\n"
+ "<Control-c> to save-copy-as another file.\n"
"Check that changes were saved by opening the file elsewhere."
}
def bind(sequence=None, func=None, add=None):
"Bind to this widget at event sequence a call to function func."
pass
+
+class Entry:
+ "Mock for tkinter.Entry."
+ def focus_set(self):
+ pass
@classmethod
def tearDownClass(cls):
+ del cls.editor, cls.text
cls.root.destroy()
- del cls.text
- del cls.editor
del cls.root
def setUp(self):
@classmethod
def tearDownClass(cls):
+ del cls.text, cls.auto_expand
if hasattr(cls, 'tk'):
cls.tk.destroy()
del cls.tk
- del cls.text, cls.auto_expand
def tearDown(self):
self.text.delete('1.0', 'end')
--- /dev/null
+"""Unittests for idlelib.configHelpSourceEdit"""
+import unittest
+from idlelib.idle_test.mock_tk import Var, Mbox, Entry
+from idlelib import configHelpSourceEdit as help_dialog_module
+
+help_dialog = help_dialog_module.GetHelpSourceDialog
+
+
+class Dummy_help_dialog:
+ # Mock for testing the following methods of help_dialog
+ menu_ok = help_dialog.menu_ok
+ path_ok = help_dialog.path_ok
+ ok = help_dialog.ok
+ cancel = help_dialog.cancel
+ # Attributes, constant or variable, needed for tests
+ menu = Var()
+ entryMenu = Entry()
+ path = Var()
+ entryPath = Entry()
+ result = None
+ destroyed = False
+
+ def destroy(self):
+ self.destroyed = True
+
+
+# menu_ok and path_ok call Mbox.showerror if menu and path are not ok.
+orig_mbox = help_dialog_module.tkMessageBox
+showerror = Mbox.showerror
+
+
+class ConfigHelpTest(unittest.TestCase):
+ dialog = Dummy_help_dialog()
+
+ @classmethod
+ def setUpClass(cls):
+ help_dialog_module.tkMessageBox = Mbox
+
+ @classmethod
+ def tearDownClass(cls):
+ help_dialog_module.tkMessageBox = orig_mbox
+
+ def test_blank_menu(self):
+ self.dialog.menu.set('')
+ self.assertFalse(self.dialog.menu_ok())
+ self.assertEqual(showerror.title, 'Menu Item Error')
+ self.assertIn('No', showerror.message)
+
+ def test_long_menu(self):
+ self.dialog.menu.set('hello' * 10)
+ self.assertFalse(self.dialog.menu_ok())
+ self.assertEqual(showerror.title, 'Menu Item Error')
+ self.assertIn('long', showerror.message)
+
+ def test_good_menu(self):
+ self.dialog.menu.set('help')
+ showerror.title = 'No Error' # should not be called
+ self.assertTrue(self.dialog.menu_ok())
+ self.assertEqual(showerror.title, 'No Error')
+
+ def test_blank_path(self):
+ self.dialog.path.set('')
+ self.assertFalse(self.dialog.path_ok())
+ self.assertEqual(showerror.title, 'File Path Error')
+ self.assertIn('No', showerror.message)
+
+ def test_invalid_file_path(self):
+ self.dialog.path.set('foobar' * 100)
+ self.assertFalse(self.dialog.path_ok())
+ self.assertEqual(showerror.title, 'File Path Error')
+ self.assertIn('not exist', showerror.message)
+
+ def test_invalid_url_path(self):
+ self.dialog.path.set('ww.foobar.com')
+ self.assertFalse(self.dialog.path_ok())
+ self.assertEqual(showerror.title, 'File Path Error')
+ self.assertIn('not exist', showerror.message)
+
+ self.dialog.path.set('htt.foobar.com')
+ self.assertFalse(self.dialog.path_ok())
+ self.assertEqual(showerror.title, 'File Path Error')
+ self.assertIn('not exist', showerror.message)
+
+ def test_good_path(self):
+ self.dialog.path.set('https://docs.python.org')
+ showerror.title = 'No Error' # should not be called
+ self.assertTrue(self.dialog.path_ok())
+ self.assertEqual(showerror.title, 'No Error')
+
+ def test_ok(self):
+ self.dialog.destroyed = False
+ self.dialog.menu.set('help')
+ self.dialog.path.set('https://docs.python.org')
+ self.dialog.ok()
+ self.assertEqual(self.dialog.result, ('help',
+ 'https://docs.python.org'))
+ self.assertTrue(self.dialog.destroyed)
+
+ def test_cancel(self):
+ self.dialog.destroyed = False
+ self.dialog.cancel()
+ self.assertEqual(self.dialog.result, None)
+ self.assertTrue(self.dialog.destroyed)
+
+if __name__ == '__main__':
+ unittest.main(verbosity=2, exit=False)
-'''Unittests for idlelib/configHandler.py
-
-Coverage: 46% just by creating dialog. The other half is change code.
+'''Test idlelib.configDialog.
+Coverage: 46% just by creating dialog.
+The other half is code for working with user customizations.
'''
-import unittest
+from idlelib.configDialog import ConfigDialog # always test import
from test.support import requires
+requires('gui')
from tkinter import Tk
-from idlelib.configDialog import ConfigDialog
-from idlelib.macosxSupport import _initializeTkVariantTests
-
+import unittest
+from idlelib import macosxSupport as macosx
class ConfigDialogTest(unittest.TestCase):
@classmethod
def setUpClass(cls):
- requires('gui')
cls.root = Tk()
- _initializeTkVariantTests(cls.root)
+ macosx._initializeTkVariantTests(cls.root)
@classmethod
def tearDownClass(cls):
+ cls.root.update_idletasks()
cls.root.destroy()
del cls.root
def test_dialog(self):
- d=ConfigDialog(self.root, 'Test', _utest=True)
- d.destroy()
+ d = ConfigDialog(self.root, 'Test', _utest=True)
+ d.remove_var_callbacks()
if __name__ == '__main__':
class DelegatorTest(unittest.TestCase):
def test_mydel(self):
- # test a simple use scenario
+ # Test a simple use scenario.
- # initialize
+ # Initialize an int delegator.
mydel = Delegator(int)
self.assertIs(mydel.delegate, int)
self.assertEqual(mydel._Delegator__cache, set())
-
- # add an attribute:
+ # Trying to access a non-attribute of int fails.
self.assertRaises(AttributeError, mydel.__getattr__, 'xyz')
+
+ # Add real int attribute 'bit_length' by accessing it.
bl = mydel.bit_length
self.assertIs(bl, int.bit_length)
self.assertIs(mydel.__dict__['bit_length'], int.bit_length)
self.assertEqual(mydel._Delegator__cache, {'bit_length'})
- # add a second attribute
+ # Add attribute 'numerator'.
mydel.numerator
self.assertEqual(mydel._Delegator__cache, {'bit_length', 'numerator'})
- # delete the second (which, however, leaves it in the name cache)
+ # Delete 'numerator'.
del mydel.numerator
self.assertNotIn('numerator', mydel.__dict__)
- self.assertIn('numerator', mydel._Delegator__cache)
+ # The current implementation leaves it in the name cache.
+ # self.assertIn('numerator', mydel._Delegator__cache)
+ # However, this is not required and not part of the specification
- # reset by calling .setdelegate, which calls .resetcache
- mydel.setdelegate(float)
- self.assertIs(mydel.delegate, float)
+ # Change delegate to float, first resetting the attributes.
+ mydel.setdelegate(float) # calls resetcache
self.assertNotIn('bit_length', mydel.__dict__)
self.assertEqual(mydel._Delegator__cache, set())
+ self.assertIs(mydel.delegate, float)
if __name__ == '__main__':
unittest.main(verbosity=2, exit=2)
--- /dev/null
+'''Test (selected) IDLE Edit menu items.
+
+Edit modules have their own test files files
+'''
+from test.support import requires
+requires('gui')
+import tkinter as tk
+import unittest
+from idlelib import PyShell
+
+class PasteTest(unittest.TestCase):
+ '''Test pasting into widgets that allow pasting.
+
+ On X11, replacing selections requires tk fix.
+ '''
+ @classmethod
+ def setUpClass(cls):
+ cls.root = root = tk.Tk()
+ PyShell.fix_x11_paste(root)
+ cls.text = tk.Text(root)
+ cls.entry = tk.Entry(root)
+ cls.spin = tk.Spinbox(root)
+ root.clipboard_clear()
+ root.clipboard_append('two')
+
+ @classmethod
+ def tearDownClass(cls):
+ del cls.text, cls.entry, cls.spin
+ cls.root.clipboard_clear()
+ cls.root.update_idletasks()
+ cls.root.destroy()
+ del cls.root
+
+ def test_paste_text(self):
+ "Test pasting into text with and without a selection."
+ text = self.text
+ for tag, ans in ('', 'onetwo\n'), ('sel', 'two\n'):
+ with self.subTest(tag=tag, ans=ans):
+ text.delete('1.0', 'end')
+ text.insert('1.0', 'one', tag)
+ text.event_generate('<<Paste>>')
+ self.assertEqual(text.get('1.0', 'end'), ans)
+
+ def test_paste_entry(self):
+ "Test pasting into an entry with and without a selection."
+ # On 3.6, generated <<Paste>> fails without empty select range
+ # for 'no selection'. Live widget works fine.
+ entry = self.entry
+ for end, ans in (0, 'onetwo'), ('end', 'two'):
+ with self.subTest(entry=entry, end=end, ans=ans):
+ entry.delete(0, 'end')
+ entry.insert(0, 'one')
+ entry.select_range(0, end) # see note
+ entry.event_generate('<<Paste>>')
+ self.assertEqual(entry.get(), ans)
+
+ def test_paste_spin(self):
+ "Test pasting into a spinbox with and without a selection."
+ # See note above for entry.
+ spin = self.spin
+ for end, ans in (0, 'onetwo'), ('end', 'two'):
+ with self.subTest(end=end, ans=ans):
+ spin.delete(0, 'end')
+ spin.insert(0, 'one')
+ spin.selection('range', 0, end) # see note
+ spin.event_generate('<<Paste>>')
+ self.assertEqual(spin.get(), ans)
+
+
+if __name__ == '__main__':
+ unittest.main(verbosity=2)
@classmethod
def tearDownClass(cls):
+ del cls.text, cls.formatter
cls.root.destroy()
del cls.root
- del cls.text
- del cls.formatter
def test_short_line(self):
self.text.insert('1.0', "Short line\n")
-"""Test idlelib.ParenMatch."""
-# This must currently be a gui test because ParenMatch methods use
-# several text methods not defined on idlelib.idle_test.mock_tk.Text.
+'''Test idlelib.ParenMatch.
+
+This must currently be a gui test because ParenMatch methods use
+several text methods not defined on idlelib.idle_test.mock_tk.Text.
+'''
+from test.support import requires
+requires('gui')
import unittest
from unittest.mock import Mock
-from test.support import requires
from tkinter import Tk, Text
from idlelib.ParenMatch import ParenMatch
@classmethod
def setUpClass(cls):
- requires('gui')
cls.root = Tk()
cls.text = Text(cls.root)
cls.editwin = DummyEditwin(cls.text)
@classmethod
def tearDownClass(cls):
del cls.text, cls.editwin
+ cls.root.update_idletasks()
cls.root.destroy()
del cls.root
--- /dev/null
+'''Test Percolator'''
+from test.support import requires
+requires('gui')
+
+import unittest
+from tkinter import Text, Tk, END
+from idlelib.Percolator import Percolator, Delegator
+
+
+class MyFilter(Delegator):
+ def __init__(self):
+ Delegator.__init__(self, None)
+
+ def insert(self, *args):
+ self.insert_called_with = args
+ self.delegate.insert(*args)
+
+ def delete(self, *args):
+ self.delete_called_with = args
+ self.delegate.delete(*args)
+
+ def uppercase_insert(self, index, chars, tags=None):
+ chars = chars.upper()
+ self.delegate.insert(index, chars)
+
+ def lowercase_insert(self, index, chars, tags=None):
+ chars = chars.lower()
+ self.delegate.insert(index, chars)
+
+ def dont_insert(self, index, chars, tags=None):
+ pass
+
+
+class PercolatorTest(unittest.TestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ cls.root = Tk()
+ cls.text = Text(cls.root)
+
+ @classmethod
+ def tearDownClass(cls):
+ del cls.text
+ cls.root.destroy()
+ del cls.root
+
+ def setUp(self):
+ self.percolator = Percolator(self.text)
+ self.filter_one = MyFilter()
+ self.filter_two = MyFilter()
+ self.percolator.insertfilter(self.filter_one)
+ self.percolator.insertfilter(self.filter_two)
+
+ def tearDown(self):
+ self.percolator.close()
+ self.text.delete('1.0', END)
+
+ def test_insertfilter(self):
+ self.assertIsNotNone(self.filter_one.delegate)
+ self.assertEqual(self.percolator.top, self.filter_two)
+ self.assertEqual(self.filter_two.delegate, self.filter_one)
+ self.assertEqual(self.filter_one.delegate, self.percolator.bottom)
+
+ def test_removefilter(self):
+ filter_three = MyFilter()
+ self.percolator.removefilter(self.filter_two)
+ self.assertEqual(self.percolator.top, self.filter_one)
+ self.assertIsNone(self.filter_two.delegate)
+
+ filter_three = MyFilter()
+ self.percolator.insertfilter(self.filter_two)
+ self.percolator.insertfilter(filter_three)
+ self.percolator.removefilter(self.filter_one)
+ self.assertEqual(self.percolator.top, filter_three)
+ self.assertEqual(filter_three.delegate, self.filter_two)
+ self.assertEqual(self.filter_two.delegate, self.percolator.bottom)
+ self.assertIsNone(self.filter_one.delegate)
+
+ def test_insert(self):
+ self.text.insert('insert', 'foo')
+ self.assertEqual(self.text.get('1.0', END), 'foo\n')
+ self.assertTupleEqual(self.filter_one.insert_called_with,
+ ('insert', 'foo', None))
+
+ def test_modify_insert(self):
+ self.filter_one.insert = self.filter_one.uppercase_insert
+ self.text.insert('insert', 'bAr')
+ self.assertEqual(self.text.get('1.0', END), 'BAR\n')
+
+ def test_modify_chain_insert(self):
+ filter_three = MyFilter()
+ self.percolator.insertfilter(filter_three)
+ self.filter_two.insert = self.filter_two.uppercase_insert
+ self.filter_one.insert = self.filter_one.lowercase_insert
+ self.text.insert('insert', 'BaR')
+ self.assertEqual(self.text.get('1.0', END), 'bar\n')
+
+ def test_dont_insert(self):
+ self.filter_one.insert = self.filter_one.dont_insert
+ self.text.insert('insert', 'foo bar')
+ self.assertEqual(self.text.get('1.0', END), '\n')
+ self.filter_one.insert = self.filter_one.dont_insert
+ self.text.insert('insert', 'foo bar')
+ self.assertEqual(self.text.get('1.0', END), '\n')
+
+ def test_without_filter(self):
+ self.text.insert('insert', 'hello')
+ self.assertEqual(self.text.get('1.0', 'end'), 'hello\n')
+
+ def test_delete(self):
+ self.text.insert('insert', 'foo')
+ self.text.delete('1.0', '1.2')
+ self.assertEqual(self.text.get('1.0', END), 'o\n')
+ self.assertTupleEqual(self.filter_one.delete_called_with,
+ ('1.0', '1.2'))
+
+if __name__ == '__main__':
+ unittest.main(verbosity=2)
--- /dev/null
+"""Unittest for idlelib.ReplaceDialog"""
+from test.support import requires
+requires('gui')
+
+import unittest
+from unittest.mock import Mock
+from tkinter import Tk, Text
+from idlelib.idle_test.mock_tk import Mbox
+import idlelib.SearchEngine as se
+import idlelib.ReplaceDialog as rd
+
+orig_mbox = se.tkMessageBox
+showerror = Mbox.showerror
+
+
+class ReplaceDialogTest(unittest.TestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ cls.root = Tk()
+ cls.root.withdraw()
+ se.tkMessageBox = Mbox
+ cls.engine = se.SearchEngine(cls.root)
+ cls.dialog = rd.ReplaceDialog(cls.root, cls.engine)
+ cls.dialog.ok = Mock()
+ cls.text = Text(cls.root)
+ cls.text.undo_block_start = Mock()
+ cls.text.undo_block_stop = Mock()
+ cls.dialog.text = cls.text
+
+ @classmethod
+ def tearDownClass(cls):
+ se.tkMessageBox = orig_mbox
+ del cls.text, cls.dialog, cls.engine
+ cls.root.destroy()
+ del cls.root
+
+ def setUp(self):
+ self.text.insert('insert', 'This is a sample sTring')
+
+ def tearDown(self):
+ self.engine.patvar.set('')
+ self.dialog.replvar.set('')
+ self.engine.wordvar.set(False)
+ self.engine.casevar.set(False)
+ self.engine.revar.set(False)
+ self.engine.wrapvar.set(True)
+ self.engine.backvar.set(False)
+ showerror.title = ''
+ showerror.message = ''
+ self.text.delete('1.0', 'end')
+
+ def test_replace_simple(self):
+ # Test replace function with all options at default setting.
+ # Wrap around - True
+ # Regular Expression - False
+ # Match case - False
+ # Match word - False
+ # Direction - Forwards
+ text = self.text
+ equal = self.assertEqual
+ pv = self.engine.patvar
+ rv = self.dialog.replvar
+ replace = self.dialog.replace_it
+
+ # test accessor method
+ self.engine.setpat('asdf')
+ equal(self.engine.getpat(), pv.get())
+
+ # text found and replaced
+ pv.set('a')
+ rv.set('asdf')
+ self.dialog.open(self.text)
+ replace()
+ equal(text.get('1.8', '1.12'), 'asdf')
+
+ # dont "match word" case
+ text.mark_set('insert', '1.0')
+ pv.set('is')
+ rv.set('hello')
+ replace()
+ equal(text.get('1.2', '1.7'), 'hello')
+
+ # dont "match case" case
+ pv.set('string')
+ rv.set('world')
+ replace()
+ equal(text.get('1.23', '1.28'), 'world')
+
+ # without "regular expression" case
+ text.mark_set('insert', 'end')
+ text.insert('insert', '\nline42:')
+ before_text = text.get('1.0', 'end')
+ pv.set('[a-z][\d]+')
+ replace()
+ after_text = text.get('1.0', 'end')
+ equal(before_text, after_text)
+
+ # test with wrap around selected and complete a cycle
+ text.mark_set('insert', '1.9')
+ pv.set('i')
+ rv.set('j')
+ replace()
+ equal(text.get('1.8'), 'i')
+ equal(text.get('2.1'), 'j')
+ replace()
+ equal(text.get('2.1'), 'j')
+ equal(text.get('1.8'), 'j')
+ before_text = text.get('1.0', 'end')
+ replace()
+ after_text = text.get('1.0', 'end')
+ equal(before_text, after_text)
+
+ # text not found
+ before_text = text.get('1.0', 'end')
+ pv.set('foobar')
+ replace()
+ after_text = text.get('1.0', 'end')
+ equal(before_text, after_text)
+
+ # test access method
+ self.dialog.find_it(0)
+
+ def test_replace_wrap_around(self):
+ text = self.text
+ equal = self.assertEqual
+ pv = self.engine.patvar
+ rv = self.dialog.replvar
+ replace = self.dialog.replace_it
+ self.engine.wrapvar.set(False)
+
+ # replace candidate found both after and before 'insert'
+ text.mark_set('insert', '1.4')
+ pv.set('i')
+ rv.set('j')
+ replace()
+ equal(text.get('1.2'), 'i')
+ equal(text.get('1.5'), 'j')
+ replace()
+ equal(text.get('1.2'), 'i')
+ equal(text.get('1.20'), 'j')
+ replace()
+ equal(text.get('1.2'), 'i')
+
+ # replace candidate found only before 'insert'
+ text.mark_set('insert', '1.8')
+ pv.set('is')
+ before_text = text.get('1.0', 'end')
+ replace()
+ after_text = text.get('1.0', 'end')
+ equal(before_text, after_text)
+
+ def test_replace_whole_word(self):
+ text = self.text
+ equal = self.assertEqual
+ pv = self.engine.patvar
+ rv = self.dialog.replvar
+ replace = self.dialog.replace_it
+ self.engine.wordvar.set(True)
+
+ pv.set('is')
+ rv.set('hello')
+ replace()
+ equal(text.get('1.0', '1.4'), 'This')
+ equal(text.get('1.5', '1.10'), 'hello')
+
+ def test_replace_match_case(self):
+ equal = self.assertEqual
+ text = self.text
+ pv = self.engine.patvar
+ rv = self.dialog.replvar
+ replace = self.dialog.replace_it
+ self.engine.casevar.set(True)
+
+ before_text = self.text.get('1.0', 'end')
+ pv.set('this')
+ rv.set('that')
+ replace()
+ after_text = self.text.get('1.0', 'end')
+ equal(before_text, after_text)
+
+ pv.set('This')
+ replace()
+ equal(text.get('1.0', '1.4'), 'that')
+
+ def test_replace_regex(self):
+ equal = self.assertEqual
+ text = self.text
+ pv = self.engine.patvar
+ rv = self.dialog.replvar
+ replace = self.dialog.replace_it
+ self.engine.revar.set(True)
+
+ before_text = text.get('1.0', 'end')
+ pv.set('[a-z][\d]+')
+ rv.set('hello')
+ replace()
+ after_text = text.get('1.0', 'end')
+ equal(before_text, after_text)
+
+ text.insert('insert', '\nline42')
+ replace()
+ equal(text.get('2.0', '2.8'), 'linhello')
+
+ pv.set('')
+ replace()
+ self.assertIn('error', showerror.title)
+ self.assertIn('Empty', showerror.message)
+
+ pv.set('[\d')
+ replace()
+ self.assertIn('error', showerror.title)
+ self.assertIn('Pattern', showerror.message)
+
+ showerror.title = ''
+ showerror.message = ''
+ pv.set('[a]')
+ rv.set('test\\')
+ replace()
+ self.assertIn('error', showerror.title)
+ self.assertIn('Invalid Replace Expression', showerror.message)
+
+ # test access method
+ self.engine.setcookedpat("\'")
+ equal(pv.get(), "\\'")
+
+ def test_replace_backwards(self):
+ equal = self.assertEqual
+ text = self.text
+ pv = self.engine.patvar
+ rv = self.dialog.replvar
+ replace = self.dialog.replace_it
+ self.engine.backvar.set(True)
+
+ text.insert('insert', '\nis as ')
+
+ pv.set('is')
+ rv.set('was')
+ replace()
+ equal(text.get('1.2', '1.4'), 'is')
+ equal(text.get('2.0', '2.3'), 'was')
+ replace()
+ equal(text.get('1.5', '1.8'), 'was')
+ replace()
+ equal(text.get('1.2', '1.5'), 'was')
+
+ def test_replace_all(self):
+ text = self.text
+ pv = self.engine.patvar
+ rv = self.dialog.replvar
+ replace_all = self.dialog.replace_all
+
+ text.insert('insert', '\n')
+ text.insert('insert', text.get('1.0', 'end')*100)
+ pv.set('is')
+ rv.set('was')
+ replace_all()
+ self.assertNotIn('is', text.get('1.0', 'end'))
+
+ self.engine.revar.set(True)
+ pv.set('')
+ replace_all()
+ self.assertIn('error', showerror.title)
+ self.assertIn('Empty', showerror.message)
+
+ pv.set('[s][T]')
+ rv.set('\\')
+ replace_all()
+
+ self.engine.revar.set(False)
+ pv.set('text which is not present')
+ rv.set('foobar')
+ replace_all()
+
+ def test_default_command(self):
+ text = self.text
+ pv = self.engine.patvar
+ rv = self.dialog.replvar
+ replace_find = self.dialog.default_command
+ equal = self.assertEqual
+
+ pv.set('This')
+ rv.set('was')
+ replace_find()
+ equal(text.get('sel.first', 'sel.last'), 'was')
+
+ self.engine.revar.set(True)
+ pv.set('')
+ replace_find()
+
+
+if __name__ == '__main__':
+ unittest.main(verbosity=2)
--- /dev/null
+"""Test SearchDialog class in SearchDialogue.py"""
+
+# Does not currently test the event handler wrappers.
+# A usage test should simulate clicks and check hilighting.
+# Tests need to be coordinated with SearchDialogBase tests
+# to avoid duplication.
+
+from test.support import requires
+requires('gui')
+
+import unittest
+import tkinter as tk
+from tkinter import BooleanVar
+import idlelib.SearchEngine as se
+import idlelib.SearchDialog as sd
+
+
+class SearchDialogTest(unittest.TestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ cls.root = tk.Tk()
+
+ @classmethod
+ def tearDownClass(cls):
+ cls.root.destroy()
+ del cls.root
+
+ def setUp(self):
+ self.engine = se.SearchEngine(self.root)
+ self.dialog = sd.SearchDialog(self.root, self.engine)
+ self.text = tk.Text(self.root)
+ self.text.insert('1.0', 'Hello World!')
+
+ def test_find_again(self):
+ # Search for various expressions
+ text = self.text
+
+ self.engine.setpat('')
+ self.assertFalse(self.dialog.find_again(text))
+
+ self.engine.setpat('Hello')
+ self.assertTrue(self.dialog.find_again(text))
+
+ self.engine.setpat('Goodbye')
+ self.assertFalse(self.dialog.find_again(text))
+
+ self.engine.setpat('World!')
+ self.assertTrue(self.dialog.find_again(text))
+
+ self.engine.setpat('Hello World!')
+ self.assertTrue(self.dialog.find_again(text))
+
+ # Regular expression
+ self.engine.revar = BooleanVar(self.root, True)
+ self.engine.setpat('W[aeiouy]r')
+ self.assertTrue(self.dialog.find_again(text))
+
+ def test_find_selection(self):
+ # Select some text and make sure it's found
+ text = self.text
+ # Add additional line to find
+ self.text.insert('2.0', 'Hello World!')
+
+ text.tag_add('sel', '1.0', '1.4') # Select 'Hello'
+ self.assertTrue(self.dialog.find_selection(text))
+
+ text.tag_remove('sel', '1.0', 'end')
+ text.tag_add('sel', '1.6', '1.11') # Select 'World!'
+ self.assertTrue(self.dialog.find_selection(text))
+
+ text.tag_remove('sel', '1.0', 'end')
+ text.tag_add('sel', '1.0', '1.11') # Select 'Hello World!'
+ self.assertTrue(self.dialog.find_selection(text))
+
+ # Remove additional line
+ text.delete('2.0', 'end')
+
+if __name__ == '__main__':
+ unittest.main(verbosity=2, exit=2)
-'''Test the functions and main class method of textView.py.
+'''Test idlelib.textView.
Since all methods and functions create (or destroy) a TextViewer, which
is a widget containing multiple widgets, all tests must be gui tests.
root = Tk()
def tearDownModule():
- global root
+ global root, TV
+ del TV
+ root.update_idletasks()
root.destroy() # pyflakes falsely sees root as undefined
del root
--- /dev/null
+"""Unittest for UndoDelegator in idlelib.UndoDelegator.
+
+Coverage about 80% (retest).
+"""
+from test.support import requires
+requires('gui')
+
+import unittest
+from unittest.mock import Mock
+from tkinter import Text, Tk
+from idlelib.UndoDelegator import UndoDelegator
+from idlelib.Percolator import Percolator
+
+
+class UndoDelegatorTest(unittest.TestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ cls.root = Tk()
+ cls.text = Text(cls.root)
+ cls.percolator = Percolator(cls.text)
+
+ @classmethod
+ def tearDownClass(cls):
+ cls.percolator.redir.close()
+ del cls.percolator, cls.text
+ cls.root.destroy()
+ del cls.root
+
+ def setUp(self):
+ self.delegator = UndoDelegator()
+ self.percolator.insertfilter(self.delegator)
+ self.delegator.bell = Mock(wraps=self.delegator.bell)
+
+ def tearDown(self):
+ self.percolator.removefilter(self.delegator)
+ self.text.delete('1.0', 'end')
+ self.delegator.resetcache()
+
+ def test_undo_event(self):
+ text = self.text
+
+ text.insert('insert', 'foobar')
+ text.insert('insert', 'h')
+ text.event_generate('<<undo>>')
+ self.assertEqual(text.get('1.0', 'end'), '\n')
+
+ text.insert('insert', 'foo')
+ text.insert('insert', 'bar')
+ text.delete('1.2', '1.4')
+ text.insert('insert', 'hello')
+ text.event_generate('<<undo>>')
+ self.assertEqual(text.get('1.0', '1.4'), 'foar')
+ text.event_generate('<<undo>>')
+ self.assertEqual(text.get('1.0', '1.6'), 'foobar')
+ text.event_generate('<<undo>>')
+ self.assertEqual(text.get('1.0', '1.3'), 'foo')
+ text.event_generate('<<undo>>')
+ self.delegator.undo_event('event')
+ self.assertTrue(self.delegator.bell.called)
+
+ def test_redo_event(self):
+ text = self.text
+
+ text.insert('insert', 'foo')
+ text.insert('insert', 'bar')
+ text.delete('1.0', '1.3')
+ text.event_generate('<<undo>>')
+ text.event_generate('<<redo>>')
+ self.assertEqual(text.get('1.0', '1.3'), 'bar')
+ text.event_generate('<<redo>>')
+ self.assertTrue(self.delegator.bell.called)
+
+ def test_dump_event(self):
+ """
+ Dump_event cannot be tested directly without changing
+ environment variables. So, test statements in dump_event
+ indirectly
+ """
+ text = self.text
+ d = self.delegator
+
+ text.insert('insert', 'foo')
+ text.insert('insert', 'bar')
+ text.delete('1.2', '1.4')
+ self.assertTupleEqual((d.pointer, d.can_merge), (3, True))
+ text.event_generate('<<undo>>')
+ self.assertTupleEqual((d.pointer, d.can_merge), (2, False))
+
+ def test_get_set_saved(self):
+ # test the getter method get_saved
+ # test the setter method set_saved
+ # indirectly test check_saved
+ d = self.delegator
+
+ self.assertTrue(d.get_saved())
+ self.text.insert('insert', 'a')
+ self.assertFalse(d.get_saved())
+ d.saved_change_hook = Mock()
+
+ d.set_saved(True)
+ self.assertEqual(d.pointer, d.saved)
+ self.assertTrue(d.saved_change_hook.called)
+
+ d.set_saved(False)
+ self.assertEqual(d.saved, -1)
+ self.assertTrue(d.saved_change_hook.called)
+
+ def test_undo_start_stop(self):
+ # test the undo_block_start and undo_block_stop methods
+ text = self.text
+
+ text.insert('insert', 'foo')
+ self.delegator.undo_block_start()
+ text.insert('insert', 'bar')
+ text.insert('insert', 'bar')
+ self.delegator.undo_block_stop()
+ self.assertEqual(text.get('1.0', '1.3'), 'foo')
+
+ # test another code path
+ self.delegator.undo_block_start()
+ text.insert('insert', 'bar')
+ self.delegator.undo_block_stop()
+ self.assertEqual(text.get('1.0', '1.3'), 'foo')
+
+ def test_addcmd(self):
+ text = self.text
+ # when number of undo operations exceeds max_undo
+ self.delegator.max_undo = max_undo = 10
+ for i in range(max_undo + 10):
+ text.insert('insert', 'foo')
+ self.assertLessEqual(len(self.delegator.undolist), max_undo)
+
+if __name__ == '__main__':
+ unittest.main(verbosity=2, exit=False)
'Test', UserWarning, 'test_warning.py', 99, f, 'Line of code')
self.assertEqual(shellmsg.splitlines(), f.getvalue().splitlines())
-class ImportWarnTest(unittest.TestCase):
- def test_idlever(self):
- with warnings.catch_warnings(record=True) as w:
- warnings.simplefilter("always")
- import idlelib.idlever
- self.assertEqual(len(w), 1)
- self.assertTrue(issubclass(w[-1].category, DeprecationWarning))
- self.assertIn("version", str(w[-1].message))
-
if __name__ == '__main__':
unittest.main(verbosity=2, exit=False)
-"""Unittest for idlelib.WidgetRedirector
+'''Test idlelib.WidgetRedirector.
100% coverage
-"""
+'''
from test.support import requires
import unittest
from idlelib.idle_test.mock_idle import Func
@classmethod
def setUpClass(cls):
requires('gui')
- cls.tk = Tk()
- cls.text = Text(cls.tk)
+ cls.root = Tk()
+ cls.text = Text(cls.root)
@classmethod
def tearDownClass(cls):
- cls.text.destroy()
- cls.tk.destroy()
- del cls.text, cls.tk
+ del cls.text
+ cls.root.destroy()
+ del cls.root
def test_init(self):
redir = WidgetRedirector(self.text)
@classmethod
def setUpClass(cls):
requires('gui')
- cls.tk = Tk()
- cls.text = Text(cls.tk)
+ cls.root = Tk()
+ cls.text = Text(cls.root)
@classmethod
def tearDownClass(cls):
- cls.text.destroy()
- cls.tk.destroy()
- del cls.text, cls.tk
+ del cls.text
+ cls.root.update_idletasks()
+ cls.root.destroy()
+ del cls.root
def setUp(self):
self.redir = WidgetRedirector(self.text)
def test_command_dispatch(self):
# Test that .__init__ causes redirection of tk calls
# through redir.dispatch
- self.tk.call(self.text._w, 'insert', 'hello')
+ self.root.call(self.text._w, 'insert', 'hello')
self.assertEqual(self.func.args, ('hello',))
self.assertEqual(self.text.get('1.0', 'end'), '\n')
# Ensure that called through redir .dispatch and not through
# self.text.insert by having mock raise TclError.
self.func.__init__(TclError())
- self.assertEqual(self.tk.call(self.text._w, 'insert', 'boo'), '')
+ self.assertEqual(self.root.call(self.text._w, 'insert', 'boo'), '')
-"""RPC Implemention, originally written for the Python Idle IDE
+"""RPC Implementation, originally written for the Python Idle IDE
For security reasons, GvR requested that Idle's Python execution server process
connect to the Idle process, which listens for the connection. Since Idle has
raise TypeError('module name must be str, not {}'.format(type(name)))
if level < 0:
raise ValueError('level must be >= 0')
- if package:
+ if level > 0:
if not isinstance(package, str):
raise TypeError('__package__ not set to a string')
elif package not in sys.modules:
def __import__(name, globals=None, locals=None, fromlist=(), level=0):
"""Import a module.
- The 'globals' argument is used to infer where the import is occuring from
+ The 'globals' argument is used to infer where the import is occurring from
to handle relative imports. The 'locals' argument is ignored. The
'fromlist' argument specifies what should exist as attributes on the module
being imported (e.g. ``from module import <fromlist>``). The 'level'
# MAGIC must change whenever the bytecode emitted by the compiler may no
# longer be understood by older implementations of the eval loop (usually
# due to the addition of new opcodes).
+#
+# Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array
+# in PC/launcher.c must also be updated.
MAGIC_NUMBER = (3350).to_bytes(2, 'little') + b'\r\n'
_RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c
submodule_search_locations=smsl)
def find_spec(self, fullname, target=None):
- """Try to find a loader for the specified module, or the namespace
- package portions. Returns (loader, list-of-portions)."""
+ """Try to find a spec for the specified module. Returns the
+ matching spec, or None if not found."""
is_namespace = False
tail_module = fullname.rpartition('.')[2]
try:
from . import machinery
try:
import _frozen_importlib
-# import _frozen_importlib_external
except ImportError as exc:
if exc.name != '_frozen_importlib':
raise
def __check_eager_loader(loader):
if not hasattr(loader, 'exec_module'):
raise TypeError('loader must define exec_module()')
- elif hasattr(loader.__class__, 'create_module'):
- if abc.Loader.create_module != loader.__class__.create_module:
- # Only care if create_module() is overridden in a subclass of
- # importlib.abc.Loader.
- raise TypeError('loader cannot define create_module()')
@classmethod
def factory(cls, loader):
empty dict.
"""
arguments = self.arguments
- if not arguments:
- return
new_arguments = []
for name, param in self._signature.parameters.items():
try:
addr1 = ip_network('192.0.2.0/28')
addr2 = ip_network('192.0.2.1/32')
- addr1.address_exclude(addr2) =
+ list(addr1.address_exclude(addr2)) =
[IPv4Network('192.0.2.0/32'), IPv4Network('192.0.2.2/31'),
- IPv4Network('192.0.2.4/30'), IPv4Network('192.0.2.8/29')]
+ IPv4Network('192.0.2.4/30'), IPv4Network('192.0.2.8/29')]
or IPv6:
addr1 = ip_network('2001:db8::1/32')
addr2 = ip_network('2001:db8::1/128')
- addr1.address_exclude(addr2) =
+ list(addr1.address_exclude(addr2)) =
[ip_network('2001:db8::1/128'),
- ip_network('2001:db8::2/127'),
- ip_network('2001:db8::4/126'),
- ip_network('2001:db8::8/125'),
- ...
- ip_network('2001:db8:8000::/33')]
+ ip_network('2001:db8::2/127'),
+ ip_network('2001:db8::4/126'),
+ ip_network('2001:db8::8/125'),
+ ...
+ ip_network('2001:db8:8000::/33')]
Args:
other: An IPv4Network or IPv6Network object of the same type.
new_prefixlen, self))
start = int(self.network_address)
- end = int(self.broadcast_address)
+ end = int(self.broadcast_address) + 1
step = (int(self.hostmask) + 1) >> prefixlen_diff
for new_addr in range(start, end, step):
current = self.__class__((new_addr, new_prefixlen))
return any(self in net for net in self._constants._private_networks)
@property
+ @functools.lru_cache()
+ def is_global(self):
+ return self not in self._constants._public_network and not self.is_private
+
+ @property
def is_multicast(self):
"""Test if the address is reserved for multicast use.
_multicast_network = IPv4Network('224.0.0.0/4')
+ _public_network = IPv4Network('100.64.0.0/10')
+
_private_networks = [
IPv4Network('0.0.0.0/8'),
IPv4Network('10.0.0.0/8'),
#ESCAPE_DCT.setdefault(chr(i), '\\u%04x' % (i,))
INFINITY = float('inf')
-FLOAT_REPR = repr
def py_encode_basestring(s):
"""Return a JSON representation of a Python string
_encoder = encode_basestring
def floatstr(o, allow_nan=self.allow_nan,
- _repr=FLOAT_REPR, _inf=INFINITY, _neginf=-INFINITY):
+ _repr=float.__repr__, _inf=INFINITY, _neginf=-INFINITY):
# Check for specials. Note that this type of test is processor
# and/or platform-specific, so do tests which don't depend on the
# internals.
list=list,
str=str,
tuple=tuple,
+ _intstr=int.__str__,
):
if _indent is not None and not isinstance(_indent, str):
# Subclasses of int/float may override __str__, but we still
# want to encode them as integers/floats in JSON. One example
# within the standard library is IntEnum.
- yield buf + str(int(value))
+ yield buf + _intstr(value)
elif isinstance(value, float):
# see comment above for int
- yield buf + _floatstr(float(value))
+ yield buf + _floatstr(value)
else:
yield buf
if isinstance(value, (list, tuple)):
# also allow them. Many encoders seem to do something like this.
elif isinstance(key, float):
# see comment for int/float in _make_iterencode
- key = _floatstr(float(key))
+ key = _floatstr(key)
elif key is True:
key = 'true'
elif key is False:
key = 'null'
elif isinstance(key, int):
# see comment for int/float in _make_iterencode
- key = str(int(key))
+ key = _intstr(key)
elif _skipkeys:
continue
else:
yield 'false'
elif isinstance(value, int):
# see comment for int/float in _make_iterencode
- yield str(int(value))
+ yield _intstr(value)
elif isinstance(value, float):
# see comment for int/float in _make_iterencode
- yield _floatstr(float(value))
+ yield _floatstr(value)
else:
if isinstance(value, (list, tuple)):
chunks = _iterencode_list(value, _current_indent_level)
yield 'false'
elif isinstance(o, int):
# see comment for int/float in _make_iterencode
- yield str(int(o))
+ yield _intstr(o)
elif isinstance(o, float):
# see comment for int/float in _make_iterencode
- yield _floatstr(float(o))
+ yield _floatstr(o)
elif isinstance(o, (list, tuple)):
yield from _iterencode_list(o, _current_indent_level)
elif isinstance(o, dict):
#reduce to None
new_node = None
elif repeater_node.children[0].value == '+':
- #reduce to a single occurence i.e. do nothing
+ #reduce to a single occurrence i.e. do nothing
pass
else:
#TODO: handle {min, max} repeaters
"""Initializer. Subclass may override.
Args:
- options: an dict containing the options passed to RefactoringTool
+ options: a dict containing the options passed to RefactoringTool
that could be used to customize the fixer through the command line.
log: a list to append warnings and other messages to.
"""
def has_metaclass(parent):
""" we have to check the cls_node without changing it.
- There are two possiblities:
+ There are two possibilities:
1) clsdef => suite => simple_stmt => expr_stmt => Leaf('__meta')
2) clsdef => simple_stmt => expr_stmt => Leaf('__meta')
"""
"""Pattern compiler.
-The grammer is taken from PatternGrammar.txt.
+The grammar is taken from PatternGrammar.txt.
The compiler compiles a pattern to a pytree.*Pattern instance.
"""
startline = False
toks_append(tokval)
-cookie_re = re.compile(r'^[ \t\f]*#.*coding[:=][ \t]*([-\w.]+)', re.ASCII)
+cookie_re = re.compile(r'^[ \t\f]*#.*?coding[:=][ \t]*([-\w.]+)', re.ASCII)
blank_re = re.compile(br'^[ \t\f]*(?:[#\r\n]|$)', re.ASCII)
def _get_normal_name(orig_enc):
Args:
fixer_names: a list of fixers to import
- options: an dict with configuration.
+ options: a dict with configuration.
explicit: a list of fixers to run even if they are explicit.
"""
self.fixers = fixer_names
# Local imports
from .. import pytree
-import pgen2
-from pgen2 import driver
+from .. import pgen2
+from ..pgen2 import driver
logging.basicConfig()
-""" Locale support.
+"""Locale support module.
- The module provides low-level access to the C lib's locale APIs
- and adds high level number formatting APIs as well as a locale
- aliasing engine to complement these.
+The module provides low-level access to the C lib's locale APIs and adds high
+level number formatting APIs as well as a locale aliasing engine to complement
+these.
- The aliasing engine includes support for many commonly used locale
- names and maps them to values suitable for passing to the C lib's
- setlocale() function. It also includes default encodings for all
- supported locale names.
+The aliasing engine includes support for many commonly used locale names and
+maps them to values suitable for passing to the C lib's setlocale() function. It
+also includes default encodings for all supported locale names.
"""
return s.replace('<', '').replace('>', '')
def str(val):
- """Convert float to integer, taking the locale into account."""
+ """Convert float to string, taking the locale into account."""
return format("%.12g", val)
def delocalize(string):
0x1809: "en_IE", # English - Ireland
0x1c09: "en_ZA", # English - South Africa
0x2009: "en_JA", # English - Jamaica
- 0x2409: "en_CB", # English - Carribbean
+ 0x2409: "en_CB", # English - Caribbean
0x2809: "en_BZ", # English - Belize
0x2c09: "en_TT", # English - Trinidad
0x3009: "en_ZW", # English - Zimbabwe
use one of %-formatting, :meth:`str.format` (``{}``) formatting or
:class:`string.Template` formatting in your format string.
- .. versionchanged: 3.2
+ .. versionchanged:: 3.2
Added the ``style`` parameter.
"""
if style not in _STYLES:
this and the record is then dropped. Returns a zero value if a record
is to be dropped, else non-zero.
- .. versionchanged: 3.2
+ .. versionchanged:: 3.2
Allow filters to be just callables.
"""
d['msg'] = record.getMessage()
d['args'] = None
d['exc_info'] = None
+ # Issue #25685: delete 'message' if present: redundant with 'msg'
+ d.pop('message', None)
s = pickle.dumps(d, 1)
slen = struct.pack(">L", len(s))
return slen + s
h.putheader("Content-length", str(len(data)))
if self.credentials:
import base64
- s = ('u%s:%s' % self.credentials).encode('utf-8')
- s = 'Basic ' + base64.b64encode(s).strip()
+ s = ('%s:%s' % self.credentials).encode('utf-8')
+ s = 'Basic ' + base64.b64encode(s).strip().decode('ascii')
h.putheader('Authorization', s)
h.endheaders()
if self.method == "POST":
constructor: LZMAFile(filename, mode, ...). In this case, the
encoding, errors and newline arguments must not be provided.
- For text mode, a LZMAFile object is created, and wrapped in an
+ For text mode, an LZMAFile object is created, and wrapped in an
io.TextIOWrapper instance with the specified encoding, error
handling behavior, and line ending(s).
_type_specific_attributes = ['_labels', '_visible']
def __init__(self, message=None):
- """Initialize an BabylMessage instance."""
+ """Initialize a BabylMessage instance."""
self._labels = []
self._visible = Message()
Message.__init__(self, message)
'.cpio' : 'application/x-cpio',
'.csh' : 'application/x-csh',
'.css' : 'text/css',
+ '.csv' : 'text/csv',
'.dll' : 'application/octet-stream',
'.doc' : 'application/msword',
'.dot' : 'application/msword',
'.ustar' : 'application/x-ustar',
'.vcf' : 'text/x-vcard',
'.wav' : 'audio/x-wav',
+ '.webm' : 'video/webm',
'.wiz' : 'application/msword',
'.wsdl' : 'application/xml',
'.xbm' : 'image/x-xbitmap',
warnings.simplefilter('ignore', PendingDeprecationWarning)
import imp
-# XXX Clean up once str8's cstor matches bytes.
-LOAD_CONST = bytes([dis.opname.index('LOAD_CONST')])
-IMPORT_NAME = bytes([dis.opname.index('IMPORT_NAME')])
-STORE_NAME = bytes([dis.opname.index('STORE_NAME')])
-STORE_GLOBAL = bytes([dis.opname.index('STORE_GLOBAL')])
-STORE_OPS = [STORE_NAME, STORE_GLOBAL]
-HAVE_ARGUMENT = bytes([dis.HAVE_ARGUMENT])
+LOAD_CONST = dis.opmap['LOAD_CONST']
+IMPORT_NAME = dis.opmap['IMPORT_NAME']
+STORE_NAME = dis.opmap['STORE_NAME']
+STORE_GLOBAL = dis.opmap['STORE_GLOBAL']
+STORE_OPS = STORE_NAME, STORE_GLOBAL
+EXTENDED_ARG = dis.EXTENDED_ARG
# Modulefinder does a good job at simulating Python's, but it can not
# handle __path__ modifications packages make at runtime. Therefore there
def scan_opcodes_25(self, co,
unpack = struct.unpack):
# Scan the code, and yield 'interesting' opcode combinations
- # Python 2.5 version (has absolute and relative imports)
code = co.co_code
names = co.co_names
consts = co.co_consts
- LOAD_LOAD_AND_IMPORT = LOAD_CONST + LOAD_CONST + IMPORT_NAME
- while code:
- c = bytes([code[0]])
- if c in STORE_OPS:
- oparg, = unpack('<H', code[1:3])
+ opargs = [(op, arg) for _, op, arg in dis._unpack_opargs(code)
+ if op != EXTENDED_ARG]
+ for i, (op, oparg) in enumerate(opargs):
+ if op in STORE_OPS:
yield "store", (names[oparg],)
- code = code[3:]
continue
- if code[:9:3] == LOAD_LOAD_AND_IMPORT:
- oparg_1, oparg_2, oparg_3 = unpack('<xHxHxH', code[:9])
- level = consts[oparg_1]
+ if (op == IMPORT_NAME and i >= 2
+ and opargs[i-1][0] == opargs[i-2][0] == LOAD_CONST):
+ level = consts[opargs[i-2][1]]
+ fromlist = consts[opargs[i-1][1]]
if level == 0: # absolute import
- yield "absolute_import", (consts[oparg_2], names[oparg_3])
+ yield "absolute_import", (fromlist, names[oparg])
else: # relative import
- yield "relative_import", (level, consts[oparg_2], names[oparg_3])
- code = code[9:]
+ yield "relative_import", (level, fromlist, names[oparg])
continue
- if c >= HAVE_ARGUMENT:
- code = code[3:]
- else:
- code = code[1:]
def scan_code(self, co, m):
code = co.co_code
# Copyright (C) 2005 Martin v. Löwis
# Licensed to PSF under a Contributor Agreement.
from _msi import *
-import os, string, re, sys
+import glob
+import os
+import re
+import string
+import sys
AMD64 = "AMD64" in sys.version
Itanium = "Itanium" in sys.version
('CustomAction','Type','N',1,16383,None, None, None, None, 'The numeric custom action type, consisting of source location, code type, entry, option flags.',),
('CustomAction','Action','N',None, None, None, None, 'Identifier',None, 'Primary key, name of action, normally appears in sequence table unless private use.',),
('CustomAction','Source','Y',None, None, None, None, 'CustomSource',None, 'The table reference of the source of the code.',),
-('CustomAction','Target','Y',None, None, None, None, 'Formatted',None, 'Excecution parameter, depends on the type of custom action',),
+('CustomAction','Target','Y',None, None, None, None, 'Formatted',None, 'Execution parameter, depends on the type of custom action',),
('DrLocator','Signature_','N',None, None, None, None, 'Identifier',None, 'The Signature_ represents a unique file signature and is also the foreign key in the Signature table.',),
('DrLocator','Path','Y',None, None, None, None, 'AnyPath',None, 'The path on the user system. This is either a subpath below the value of the Parent or a full path. The path may contain properties enclosed within [ ] that will be expanded.',),
('DrLocator','Depth','Y',0,32767,None, None, None, None, 'The depth below the path to which the Signature_ is recursively searched. If absent, the depth is assumed to be 0.',),
self._send(header)
self._send(buf)
else:
- # Issue # 20540: concatenate before sending, to avoid delays due
+ # Issue #20540: concatenate before sending, to avoid delays due
# to Nagle's algorithm on a TCP socket.
# Also note we want to avoid sending a 0-length buffer separately,
# to avoid "broken pipe" errors if the other end closed the pipe.
except ImportError:
pass
- # close sys.stdin
- if sys.stdin is not None:
- try:
- sys.stdin.close()
- sys.stdin = open(os.devnull)
- except (OSError, ValueError):
- pass
+ util._close_stdin()
# ignoring SIGCHLD means no need to reap zombie processes
handler = signal.signal(signal.SIGCHLD, signal.SIG_IGN)
def MakeProxyType(name, exposed, _cache={}):
'''
- Return an proxy type whose methods are given by `exposed`
+ Return a proxy type whose methods are given by `exposed`
'''
exposed = tuple(exposed)
try:
context._force_start_method(self._start_method)
_process_counter = itertools.count(1)
_children = set()
- if sys.stdin is not None:
- try:
- sys.stdin.close()
- sys.stdin = open(os.devnull)
- except (OSError, ValueError):
- pass
+ util._close_stdin()
old_process = _current_process
_current_process = self
try:
def spawn_main(pipe_handle, parent_pid=None, tracker_fd=None):
'''
- Run code specifed by data received over pipe
+ Run code specified by data received over pipe
'''
assert is_forking(sys.argv)
if sys.platform == 'win32':
import os
import itertools
+import sys
import weakref
import atexit
import threading # we want threading to install it's
assert fds[-1] == MAXFD, 'fd too large'
for i in range(len(fds) - 1):
os.closerange(fds[i]+1, fds[i+1])
+#
+# Close sys.stdin and replace stdin with os.devnull
+#
+
+def _close_stdin():
+ if sys.stdin is None:
+ return
+
+ try:
+ sys.stdin.close()
+ except (OSError, ValueError):
+ pass
+
+ try:
+ fd = os.open(os.devnull, os.O_RDONLY)
+ try:
+ sys.stdin = open(fd, closefd=False)
+ except:
+ os.close(fd)
+ raise
+ except (OSError, ValueError):
+ pass
#
# Start a program with only specified fds kept open
# Helper function(s)
def decode_header(header_str):
- """Takes an unicode string representing a munged header value
+ """Takes a unicode string representing a munged header value
and decodes it as a (possibly non-ASCII) readable value."""
parts = []
for v, enc in _email_decode_header(header_str):
def _putcmd(self, line):
"""Internal: send one command to the server (through _putline()).
- The `line` must be an unicode string."""
+ The `line` must be a unicode string."""
if self.debugging: print('*cmd*', repr(line))
line = line.encode(self.encoding, self.errors)
self._putline(line)
def _getresp(self):
"""Internal: get a response from the server.
Raise various errors if the response indicates an error.
- Returns an unicode string."""
+ Returns a unicode string."""
resp = self._getline()
if self.debugging: print('*resp*', repr(resp))
resp = resp.decode(self.encoding, self.errors)
"""Internal: get a response plus following text from the server.
Raise various errors if the response indicates an error.
- Returns a (response, lines) tuple where `response` is an unicode
+ Returns a (response, lines) tuple where `response` is a unicode
string and `lines` is a list of bytes objects.
If `file` is a file-like object, it must be open in binary mode.
"""
Return a 2-tuple (unc, rest); either part may be empty.
If unc is not empty, it has the form '//host/mount' (or similar
using backslashes). unc+rest is always the input path.
- Paths containing drive letters never have an UNC part.
+ Paths containing drive letters never have a UNC part.
"""
import warnings
warnings.warn("ntpath.splitunc is deprecated, use ntpath.splitdrive instead",
_short_opt : { string : Option }
dictionary mapping short option strings, eg. "-f" or "-X",
to the Option instances that implement them. If an Option
- has multiple short option strings, it will appears in this
+ has multiple short option strings, it will appear in this
dictionary multiple times. [1]
_long_opt : { string : Option }
dictionary mapping long option strings, eg. "--file" or
sys.argv[1:]). Any errors result in a call to 'error()', which
by default prints the usage message to stderr and calls
sys.exit() with an error message. On success returns a pair
- (values, args) where 'values' is an Values instance (with all
+ (values, args) where 'values' is a Values instance (with all
your option values) and 'args' is the list of arguments left
over after parsing options.
"""
# minor reason when (say) a thousand readable directories are still
# left to visit. That logic is copied here.
try:
- # Note that scandir is global in this module due
- # to earlier import-*.
- scandir_it = scandir(top)
+ if name == 'nt' and isinstance(top, bytes):
+ scandir_it = _dummy_scandir(top)
+ else:
+ # Note that scandir is global in this module due
+ # to earlier import-*.
+ scandir_it = scandir(top)
+ entries = list(scandir_it)
except OSError as error:
if onerror is not None:
onerror(error)
return
- while True:
- try:
- try:
- entry = next(scandir_it)
- except StopIteration:
- break
- except OSError as error:
- if onerror is not None:
- onerror(error)
- return
-
+ for entry in entries:
try:
is_dir = entry.is_dir()
except OSError:
# Recurse into sub-directories
islink, join = path.islink, path.join
- for name in dirs:
- new_path = join(top, name)
+ for dirname in dirs:
+ new_path = join(top, dirname)
# Issue #23605: os.path.islink() is used instead of caching
# entry.is_symlink() result during the loop on os.scandir() because
# the caller can replace the directory entry during the "yield"
# Yield after recursion if going bottom up
yield top, dirs, nondirs
+class _DummyDirEntry:
+ """Dummy implementation of DirEntry
+
+ Only used internally by os.walk(bytes). Since os.walk() doesn't need the
+ follow_symlinks parameter: don't implement it, always follow symbolic
+ links.
+ """
+
+ def __init__(self, dir, name):
+ self.name = name
+ self.path = path.join(dir, name)
+ # Mimick FindFirstFile/FindNextFile: we should get file attributes
+ # while iterating on a directory
+ self._stat = None
+ self._lstat = None
+ try:
+ self.stat(follow_symlinks=False)
+ except OSError:
+ pass
+
+ def stat(self, *, follow_symlinks=True):
+ if follow_symlinks:
+ if self._stat is None:
+ self._stat = stat(self.path)
+ return self._stat
+ else:
+ if self._lstat is None:
+ self._lstat = stat(self.path, follow_symlinks=False)
+ return self._lstat
+
+ def is_dir(self):
+ if self._lstat is not None and not self.is_symlink():
+ # use the cache lstat
+ stat = self.stat(follow_symlinks=False)
+ return st.S_ISDIR(stat.st_mode)
+
+ stat = self.stat()
+ return st.S_ISDIR(stat.st_mode)
+
+ def is_symlink(self):
+ stat = self.stat(follow_symlinks=False)
+ return st.S_ISLNK(stat.st_mode)
+
+def _dummy_scandir(dir):
+ # listdir-based implementation for bytes patches on Windows
+ for name in listdir(dir):
+ yield _DummyDirEntry(dir, name)
+
__all__.append("walk")
if {open, stat} <= supports_dir_fd and {listdir, stat} <= supports_fd:
except OSError as err:
if onerror is not None:
onerror(err)
- return
+ continue
try:
if follow_symlinks or path.samestat(orig_st, stat(dirfd)):
dirpath = path.join(toppath, name)
_Selector.__init__(self, child_parts)
def _select_from(self, parent_path, is_dir, exists, listdir):
- if not is_dir(parent_path):
+ try:
+ if not is_dir(parent_path):
+ return
+ path = parent_path._make_child_relpath(self.name)
+ if exists(path):
+ for p in self.successor._select_from(path, is_dir, exists, listdir):
+ yield p
+ except PermissionError:
return
- path = parent_path._make_child_relpath(self.name)
- if exists(path):
- for p in self.successor._select_from(path, is_dir, exists, listdir):
- yield p
class _WildcardSelector(_Selector):
_Selector.__init__(self, child_parts)
def _select_from(self, parent_path, is_dir, exists, listdir):
- if not is_dir(parent_path):
+ try:
+ if not is_dir(parent_path):
+ return
+ cf = parent_path._flavour.casefold
+ for name in listdir(parent_path):
+ casefolded = cf(name)
+ if self.pat.match(casefolded):
+ path = parent_path._make_child_relpath(name)
+ for p in self.successor._select_from(path, is_dir, exists, listdir):
+ yield p
+ except PermissionError:
return
- cf = parent_path._flavour.casefold
- for name in listdir(parent_path):
- casefolded = cf(name)
- if self.pat.match(casefolded):
- path = parent_path._make_child_relpath(name)
- for p in self.successor._select_from(path, is_dir, exists, listdir):
- yield p
+
class _RecursiveWildcardSelector(_Selector):
def _iterate_directories(self, parent_path, is_dir, listdir):
yield parent_path
- for name in listdir(parent_path):
- path = parent_path._make_child_relpath(name)
- if is_dir(path):
- for p in self._iterate_directories(path, is_dir, listdir):
- yield p
+ try:
+ for name in listdir(parent_path):
+ path = parent_path._make_child_relpath(name)
+ if is_dir(path) and not path.is_symlink():
+ for p in self._iterate_directories(path, is_dir, listdir):
+ yield p
+ except PermissionError:
+ return
def _select_from(self, parent_path, is_dir, exists, listdir):
- if not is_dir(parent_path):
+ try:
+ if not is_dir(parent_path):
+ return
+ with _cached(listdir) as listdir:
+ yielded = set()
+ try:
+ successor_select = self.successor._select_from
+ for starting_point in self._iterate_directories(parent_path, is_dir, listdir):
+ for p in successor_select(starting_point, is_dir, exists, listdir):
+ if p not in yielded:
+ yield p
+ yielded.add(p)
+ finally:
+ yielded.clear()
+ except PermissionError:
return
- with _cached(listdir) as listdir:
- yielded = set()
- try:
- successor_select = self.successor._select_from
- for starting_point in self._iterate_directories(parent_path, is_dir, listdir):
- for p in successor_select(starting_point, is_dir, exists, listdir):
- if p not in yielded:
- yield p
- yielded.add(p)
- finally:
- yielded.clear()
#
return cls._flavour.join(parts)
def _init(self):
- # Overriden in concrete Path
+ # Overridden in concrete Path
pass
def _make_child(self, args):
"""Iterate over this subtree and yield all existing files (of any
kind, including directories) matching the given pattern.
"""
+ if not pattern:
+ raise ValueError("Unacceptable pattern: {!r}".format(pattern))
pattern = self._flavour.casefold(pattern)
drv, root, pattern_parts = self._flavour.parse_parts((pattern,))
if drv or root:
class WindowsPath(Path, PureWindowsPath):
__slots__ = ()
+
+ def owner(self):
+ raise NotImplementedError("Path.owner() is unsupported on this system")
+
+ def group(self):
+ raise NotImplementedError("Path.group() is unsupported on this system")
directory, it is read in and executed as if it had been typed at the
debugger prompt. This is particularly useful for aliases. If both
files exist, the one in the home directory is read first and aliases
-defined there can be overriden by the local file.
+defined there can be overridden by the local file.
Aside from aliases, the debugger is not directly programmable; but it
is implemented as a class from which you can derive your own debugger
# An 'Internal StopIteration' exception is an exception debug event
# issued by the interpreter when handling a subgenerator run with
- # 'yield from' or a generator controled by a for loop. No exception has
+ # 'yield from' or a generator controlled by a for loop. No exception has
# actually occurred in this case. The debugger uses this debug event to
# stop when the debuggee is returning from such generators.
prefix = 'Internal ' if (not exc_traceback
meets this interface.
Optional keyword arguments are *fix_imports*, *encoding* and
- *errors*, which are used to control compatiblity support for
+ *errors*, which are used to control compatibility support for
pickle stream generated by Python 2. If *fix_imports* is True,
pickle will try to map the old Python 2 names to the new names
used in Python 3. The *encoding* and *errors* tell pickle how
stack = self.stack
args = stack.pop()
func = stack[-1]
- try:
- value = func(*args)
- except:
- print(sys.exc_info())
- print(func, args)
- raise
- stack[-1] = value
+ stack[-1] = func(*args)
dispatch[REDUCE[0]] = load_reduce
def load_pop(self):
reader=read_bytes8,
doc="""A counted bytes string.
- The first argument is a 8-byte little-endian unsigned int giving
+ The first argument is an 8-byte little-endian unsigned int giving
the number of bytes, and the second argument is that many bytes.
""")
reader=read_unicodestring8,
doc="""A counted Unicode string.
- The first argument is a 8-byte little-endian signed int
+ The first argument is an 8-byte little-endian signed int
giving the number of bytes in the string, and the second
argument-- the UTF-8 encoding of the Unicode string --
contains that many bytes.
proto=4,
doc="""Push a Python bytes object.
- There are two arguments: the first is a 8-byte unsigned int giving
+ There are two arguments: the first is an 8-byte unsigned int giving
the number of bytes in the string, and the second is that many bytes,
which are taken literally as the string content.
"""),
proto=4,
doc="""Push a Python Unicode string object.
- There are two arguments: the first is a 8-byte little-endian signed int
+ There are two arguments: the first is an 8-byte little-endian signed int
giving the number of bytes in the string. The second is that many
bytes, and is the UTF-8 encoding of the Unicode string.
"""),
if len(fn)==2 and fn[1].startswith('__init__.py'):
if fn[0] not in yielded:
yielded[fn[0]] = 1
- yield fn[0], True
+ yield prefix + fn[0], True
if len(fn)!=1:
continue
full_distribution_name=1):
import warnings
warnings.warn("dist() and linux_distribution() functions are deprecated "
- "in Python 3.5 and will be removed in Python 3.7",
- PendingDeprecationWarning, stacklevel=2)
+ "in Python 3.5", PendingDeprecationWarning, stacklevel=2)
return _linux_distribution(distname, version, id, supported_dists,
full_distribution_name)
"""
import warnings
warnings.warn("dist() and linux_distribution() functions are deprecated "
- "in Python 3.5 and will be removed in Python 3.7",
- PendingDeprecationWarning, stacklevel=2)
+ "in Python 3.5", PendingDeprecationWarning, stacklevel=2)
return _linux_distribution(distname, version, id,
supported_dists=supported_dists,
full_distribution_name=0)
csd = 'SP' + csd[13:]
# VER_NT_SERVER = 3
- if getattr(winver, 'product_type', None) == 3:
+ if getattr(winver, 'product', None) == 3:
release = (_WIN32_SERVER_RELEASES.get((maj, min)) or
_WIN32_SERVER_RELEASES.get((maj, None)) or
release)
### Various APIs for extracting information from sys.version
_sys_version_parser = re.compile(
- r'([\w.+]+)\s*'
- '\(#?([^,]+),\s*([\w ]+),\s*([\w :]+)\)\s*'
- '\[([^\]]+)\]?', re.ASCII)
+ r'([\w.+]+)\s*' # "version<space>"
+ r'\(#?([^,]+)' # "(#buildno"
+ r'(?:,\s*([\w ]*)' # ", builddate"
+ r'(?:,\s*([\w :]*))?)?\)\s*' # ", buildtime)<space>"
+ r'\[([^\]]+)\]?', re.ASCII) # "[compiler]"
_ironpython_sys_version_parser = re.compile(
r'IronPython\s*'
'failed to parse Jython sys.version: %s' %
repr(sys_version))
version, buildno, builddate, buildtime, _ = match.groups()
+ if builddate is None:
+ builddate = ''
compiler = sys.platform
elif "PyPy" in sys_version:
version, buildno, builddate, buildtime, compiler = \
match.groups()
name = 'CPython'
- builddate = builddate + ' ' + buildtime
+ if builddate is None:
+ builddate = ''
+ elif buildtime:
+ builddate = builddate + ' ' + buildtime
if hasattr(sys, '_mercurial'):
_, branch, revision = sys._mercurial
def __eq__(self, other):
if isinstance(other, self.__class__):
return self.data == other.data
- elif isinstance(other, str):
+ elif isinstance(other, bytes):
return self.data == other
else:
- return id(self) == id(other)
+ return NotImplemented
def __repr__(self):
return "%s(%s)" % (self.__class__.__name__, repr(self.data))
f = struct.unpack('>d', self._fp.read(8))[0]
# timestamp 0 of binary plists corresponds to 1/1/2001
# (year of Mac OS X 10.0), instead of 1/1/1970.
- return datetime.datetime.utcfromtimestamp(f + (31 * 365 + 8) * 86400)
+ return datetime.datetime(2001, 1, 1) + datetime.timedelta(seconds=f)
elif tokenH == 0x40: # data
s = self._get_size(tokenL)
path, ok = _joinrealpath(filename[:0], filename, {})
return abspath(path)
-# Join two paths, normalizing ang eliminating any symbolic links
+# Join two paths, normalizing and eliminating any symbolic links
# encountered in the second path.
def _joinrealpath(path, rest, seen):
if isinstance(path, bytes):
class _safe_key:
"""Helper function for key functions when sorting unorderable objects.
- The wrapped-object will fallback to an Py2.x style comparison for
+ The wrapped-object will fallback to a Py2.x style comparison for
unorderable types (sorting first comparing the type name and then by
the obj ids). Does not work recursively, so dict.items() must have
_safe_key applied to both the key and the value.
search_path = path + sys.path
# XXX This will change once issue19944 lands.
spec = importlib.util._find_spec_from_path(fullmodule, search_path)
- fname = spec.loader.get_filename(fullmodule)
_modules[fullmodule] = dict
- if spec.loader.is_package(fullmodule):
- dict['__path__'] = [os.path.dirname(fname)]
+ # is module a package?
+ if spec.submodule_search_locations is not None:
+ dict['__path__'] = spec.submodule_search_locations
try:
source = spec.loader.get_source(fullmodule)
if source is None:
# not Python source, can't do anything with this module
return dict
+ fname = spec.loader.get_filename(fullmodule)
+
f = io.StringIO(source)
stack = [] # stack of (class, indent) pairs
class Doc:
PYTHONDOCS = os.environ.get("PYTHONDOCS",
- "http://docs.python.org/%d.%d/library"
+ "https://docs.python.org/%d.%d/library"
% sys.version_info[:2])
def document(self, object, name=None, *args):
docmodule = docclass = docroutine = docother = docproperty = docdata = fail
- def getdocloc(self, object):
+ def getdocloc(self, object,
+ basedir=os.path.join(sys.base_exec_prefix, "lib",
+ "python%d.%d" % sys.version_info[:2])):
"""Return the location of module docs or None"""
try:
docloc = os.environ.get("PYTHONDOCS", self.PYTHONDOCS)
- basedir = os.path.join(sys.base_exec_prefix, "lib",
- "python%d.%d" % sys.version_info[:2])
if (isinstance(object, type(os)) and
(object.__name__ in ('errno', 'exceptions', 'gc', 'imp',
'marshal', 'posix', 'signal', 'sys',
not file.startswith(os.path.join(basedir, 'site-packages')))) and
object.__name__ not in ('xml.etree', 'test.pydoc_mod')):
if docloc.startswith("http://"):
- docloc = "%s/%s" % (docloc.rstrip("/"), object.__name__)
+ docloc = "%s/%s" % (docloc.rstrip("/"), object.__name__.lower())
else:
- docloc = os.path.join(docloc, object.__name__ + ".html")
+ docloc = os.path.join(docloc, object.__name__.lower() + ".html")
else:
docloc = None
return docloc
# -*- coding: utf-8 -*-
-# Autogenerated by Sphinx on Sat Dec 5 17:02:49 2015
-topics = {'assert': u'\nThe "assert" statement\n**********************\n\nAssert statements are a convenient way to insert debugging assertions\ninto a program:\n\n assert_stmt ::= "assert" expression ["," expression]\n\nThe simple form, "assert expression", is equivalent to\n\n if __debug__:\n if not expression: raise AssertionError\n\nThe extended form, "assert expression1, expression2", is equivalent to\n\n if __debug__:\n if not expression1: raise AssertionError(expression2)\n\nThese equivalences assume that "__debug__" and "AssertionError" refer\nto the built-in variables with those names. In the current\nimplementation, the built-in variable "__debug__" is "True" under\nnormal circumstances, "False" when optimization is requested (command\nline option -O). The current code generator emits no code for an\nassert statement when optimization is requested at compile time. Note\nthat it is unnecessary to include the source code for the expression\nthat failed in the error message; it will be displayed as part of the\nstack trace.\n\nAssignments to "__debug__" are illegal. The value for the built-in\nvariable is determined when the interpreter starts.\n',
- 'assignment': u'\nAssignment statements\n*********************\n\nAssignment statements are used to (re)bind names to values and to\nmodify attributes or items of mutable objects:\n\n assignment_stmt ::= (target_list "=")+ (expression_list | yield_expression)\n target_list ::= target ("," target)* [","]\n target ::= identifier\n | "(" target_list ")"\n | "[" target_list "]"\n | attributeref\n | subscription\n | slicing\n | "*" target\n\n(See section *Primaries* for the syntax definitions for\n*attributeref*, *subscription*, and *slicing*.)\n\nAn assignment statement evaluates the expression list (remember that\nthis can be a single expression or a comma-separated list, the latter\nyielding a tuple) and assigns the single resulting object to each of\nthe target lists, from left to right.\n\nAssignment is defined recursively depending on the form of the target\n(list). When a target is part of a mutable object (an attribute\nreference, subscription or slicing), the mutable object must\nultimately perform the assignment and decide about its validity, and\nmay raise an exception if the assignment is unacceptable. The rules\nobserved by various types and the exceptions raised are given with the\ndefinition of the object types (see section *The standard type\nhierarchy*).\n\nAssignment of an object to a target list, optionally enclosed in\nparentheses or square brackets, is recursively defined as follows.\n\n* If the target list is a single target: The object is assigned to\n that target.\n\n* If the target list is a comma-separated list of targets: The\n object must be an iterable with the same number of items as there\n are targets in the target list, and the items are assigned, from\n left to right, to the corresponding targets.\n\n * If the target list contains one target prefixed with an\n asterisk, called a "starred" target: The object must be a sequence\n with at least as many items as there are targets in the target\n list, minus one. The first items of the sequence are assigned,\n from left to right, to the targets before the starred target. The\n final items of the sequence are assigned to the targets after the\n starred target. A list of the remaining items in the sequence is\n then assigned to the starred target (the list can be empty).\n\n * Else: The object must be a sequence with the same number of\n items as there are targets in the target list, and the items are\n assigned, from left to right, to the corresponding targets.\n\nAssignment of an object to a single target is recursively defined as\nfollows.\n\n* If the target is an identifier (name):\n\n * If the name does not occur in a "global" or "nonlocal" statement\n in the current code block: the name is bound to the object in the\n current local namespace.\n\n * Otherwise: the name is bound to the object in the global\n namespace or the outer namespace determined by "nonlocal",\n respectively.\n\n The name is rebound if it was already bound. This may cause the\n reference count for the object previously bound to the name to reach\n zero, causing the object to be deallocated and its destructor (if it\n has one) to be called.\n\n* If the target is a target list enclosed in parentheses or in\n square brackets: The object must be an iterable with the same number\n of items as there are targets in the target list, and its items are\n assigned, from left to right, to the corresponding targets.\n\n* If the target is an attribute reference: The primary expression in\n the reference is evaluated. It should yield an object with\n assignable attributes; if this is not the case, "TypeError" is\n raised. That object is then asked to assign the assigned object to\n the given attribute; if it cannot perform the assignment, it raises\n an exception (usually but not necessarily "AttributeError").\n\n Note: If the object is a class instance and the attribute reference\n occurs on both sides of the assignment operator, the RHS expression,\n "a.x" can access either an instance attribute or (if no instance\n attribute exists) a class attribute. The LHS target "a.x" is always\n set as an instance attribute, creating it if necessary. Thus, the\n two occurrences of "a.x" do not necessarily refer to the same\n attribute: if the RHS expression refers to a class attribute, the\n LHS creates a new instance attribute as the target of the\n assignment:\n\n class Cls:\n x = 3 # class variable\n inst = Cls()\n inst.x = inst.x + 1 # writes inst.x as 4 leaving Cls.x as 3\n\n This description does not necessarily apply to descriptor\n attributes, such as properties created with "property()".\n\n* If the target is a subscription: The primary expression in the\n reference is evaluated. It should yield either a mutable sequence\n object (such as a list) or a mapping object (such as a dictionary).\n Next, the subscript expression is evaluated.\n\n If the primary is a mutable sequence object (such as a list), the\n subscript must yield an integer. If it is negative, the sequence\'s\n length is added to it. The resulting value must be a nonnegative\n integer less than the sequence\'s length, and the sequence is asked\n to assign the assigned object to its item with that index. If the\n index is out of range, "IndexError" is raised (assignment to a\n subscripted sequence cannot add new items to a list).\n\n If the primary is a mapping object (such as a dictionary), the\n subscript must have a type compatible with the mapping\'s key type,\n and the mapping is then asked to create a key/datum pair which maps\n the subscript to the assigned object. This can either replace an\n existing key/value pair with the same key value, or insert a new\n key/value pair (if no key with the same value existed).\n\n For user-defined objects, the "__setitem__()" method is called with\n appropriate arguments.\n\n* If the target is a slicing: The primary expression in the\n reference is evaluated. It should yield a mutable sequence object\n (such as a list). The assigned object should be a sequence object\n of the same type. Next, the lower and upper bound expressions are\n evaluated, insofar they are present; defaults are zero and the\n sequence\'s length. The bounds should evaluate to integers. If\n either bound is negative, the sequence\'s length is added to it. The\n resulting bounds are clipped to lie between zero and the sequence\'s\n length, inclusive. Finally, the sequence object is asked to replace\n the slice with the items of the assigned sequence. The length of\n the slice may be different from the length of the assigned sequence,\n thus changing the length of the target sequence, if the target\n sequence allows it.\n\n**CPython implementation detail:** In the current implementation, the\nsyntax for targets is taken to be the same as for expressions, and\ninvalid syntax is rejected during the code generation phase, causing\nless detailed error messages.\n\nAlthough the definition of assignment implies that overlaps between\nthe left-hand side and the right-hand side are \'simultanenous\' (for\nexample "a, b = b, a" swaps two variables), overlaps *within* the\ncollection of assigned-to variables occur left-to-right, sometimes\nresulting in confusion. For instance, the following program prints\n"[0, 2]":\n\n x = [0, 1]\n i = 0\n i, x[i] = 1, 2 # i is updated, then x[i] is updated\n print(x)\n\nSee also: **PEP 3132** - Extended Iterable Unpacking\n\n The specification for the "*target" feature.\n\n\nAugmented assignment statements\n===============================\n\nAugmented assignment is the combination, in a single statement, of a\nbinary operation and an assignment statement:\n\n augmented_assignment_stmt ::= augtarget augop (expression_list | yield_expression)\n augtarget ::= identifier | attributeref | subscription | slicing\n augop ::= "+=" | "-=" | "*=" | "@=" | "/=" | "//=" | "%=" | "**="\n | ">>=" | "<<=" | "&=" | "^=" | "|="\n\n(See section *Primaries* for the syntax definitions of the last three\nsymbols.)\n\nAn augmented assignment evaluates the target (which, unlike normal\nassignment statements, cannot be an unpacking) and the expression\nlist, performs the binary operation specific to the type of assignment\non the two operands, and assigns the result to the original target.\nThe target is only evaluated once.\n\nAn augmented assignment expression like "x += 1" can be rewritten as\n"x = x + 1" to achieve a similar, but not exactly equal effect. In the\naugmented version, "x" is only evaluated once. Also, when possible,\nthe actual operation is performed *in-place*, meaning that rather than\ncreating a new object and assigning that to the target, the old object\nis modified instead.\n\nUnlike normal assignments, augmented assignments evaluate the left-\nhand side *before* evaluating the right-hand side. For example, "a[i]\n+= f(x)" first looks-up "a[i]", then it evaluates "f(x)" and performs\nthe addition, and lastly, it writes the result back to "a[i]".\n\nWith the exception of assigning to tuples and multiple targets in a\nsingle statement, the assignment done by augmented assignment\nstatements is handled the same way as normal assignments. Similarly,\nwith the exception of the possible *in-place* behavior, the binary\noperation performed by augmented assignment is the same as the normal\nbinary operations.\n\nFor targets which are attribute references, the same *caveat about\nclass and instance attributes* applies as for regular assignments.\n',
+# Autogenerated by Sphinx on Sat Jun 25 14:08:44 2016
+topics = {'assert': u'\nThe "assert" statement\n**********************\n\nAssert statements are a convenient way to insert debugging assertions\ninto a program:\n\n assert_stmt ::= "assert" expression ["," expression]\n\nThe simple form, "assert expression", is equivalent to\n\n if __debug__:\n if not expression: raise AssertionError\n\nThe extended form, "assert expression1, expression2", is equivalent to\n\n if __debug__:\n if not expression1: raise AssertionError(expression2)\n\nThese equivalences assume that "__debug__" and "AssertionError" refer\nto the built-in variables with those names. In the current\nimplementation, the built-in variable "__debug__" is "True" under\nnormal circumstances, "False" when optimization is requested (command\nline option -O). The current code generator emits no code for an\nassert statement when optimization is requested at compile time. Note\nthat it is unnecessary to include the source code for the expression\nthat failed in the error message; it will be displayed as part of the\nstack trace.\n\nAssignments to "__debug__" are illegal. The value for the built-in\nvariable is determined when the interpreter starts.\n',
+ 'assignment': u'\nAssignment statements\n*********************\n\nAssignment statements are used to (re)bind names to values and to\nmodify attributes or items of mutable objects:\n\n assignment_stmt ::= (target_list "=")+ (starred_expression | yield_expression)\n target_list ::= target ("," target)* [","]\n target ::= identifier\n | "(" target_list ")"\n | "[" [target_list] "]"\n | attributeref\n | subscription\n | slicing\n | "*" target\n\n(See section *Primaries* for the syntax definitions for\n*attributeref*, *subscription*, and *slicing*.)\n\nAn assignment statement evaluates the expression list (remember that\nthis can be a single expression or a comma-separated list, the latter\nyielding a tuple) and assigns the single resulting object to each of\nthe target lists, from left to right.\n\nAssignment is defined recursively depending on the form of the target\n(list). When a target is part of a mutable object (an attribute\nreference, subscription or slicing), the mutable object must\nultimately perform the assignment and decide about its validity, and\nmay raise an exception if the assignment is unacceptable. The rules\nobserved by various types and the exceptions raised are given with the\ndefinition of the object types (see section *The standard type\nhierarchy*).\n\nAssignment of an object to a target list, optionally enclosed in\nparentheses or square brackets, is recursively defined as follows.\n\n* If the target list is empty: The object must also be an empty\n iterable.\n\n* If the target list is a single target in parentheses: The object\n is assigned to that target.\n\n* If the target list is a comma-separated list of targets, or a\n single target in square brackets: The object must be an iterable\n with the same number of items as there are targets in the target\n list, and the items are assigned, from left to right, to the\n corresponding targets.\n\n * If the target list contains one target prefixed with an\n asterisk, called a "starred" target: The object must be an\n iterable with at least as many items as there are targets in the\n target list, minus one. The first items of the iterable are\n assigned, from left to right, to the targets before the starred\n target. The final items of the iterable are assigned to the\n targets after the starred target. A list of the remaining items\n in the iterable is then assigned to the starred target (the list\n can be empty).\n\n * Else: The object must be an iterable with the same number of\n items as there are targets in the target list, and the items are\n assigned, from left to right, to the corresponding targets.\n\nAssignment of an object to a single target is recursively defined as\nfollows.\n\n* If the target is an identifier (name):\n\n * If the name does not occur in a "global" or "nonlocal" statement\n in the current code block: the name is bound to the object in the\n current local namespace.\n\n * Otherwise: the name is bound to the object in the global\n namespace or the outer namespace determined by "nonlocal",\n respectively.\n\n The name is rebound if it was already bound. This may cause the\n reference count for the object previously bound to the name to reach\n zero, causing the object to be deallocated and its destructor (if it\n has one) to be called.\n\n* If the target is an attribute reference: The primary expression in\n the reference is evaluated. It should yield an object with\n assignable attributes; if this is not the case, "TypeError" is\n raised. That object is then asked to assign the assigned object to\n the given attribute; if it cannot perform the assignment, it raises\n an exception (usually but not necessarily "AttributeError").\n\n Note: If the object is a class instance and the attribute reference\n occurs on both sides of the assignment operator, the RHS expression,\n "a.x" can access either an instance attribute or (if no instance\n attribute exists) a class attribute. The LHS target "a.x" is always\n set as an instance attribute, creating it if necessary. Thus, the\n two occurrences of "a.x" do not necessarily refer to the same\n attribute: if the RHS expression refers to a class attribute, the\n LHS creates a new instance attribute as the target of the\n assignment:\n\n class Cls:\n x = 3 # class variable\n inst = Cls()\n inst.x = inst.x + 1 # writes inst.x as 4 leaving Cls.x as 3\n\n This description does not necessarily apply to descriptor\n attributes, such as properties created with "property()".\n\n* If the target is a subscription: The primary expression in the\n reference is evaluated. It should yield either a mutable sequence\n object (such as a list) or a mapping object (such as a dictionary).\n Next, the subscript expression is evaluated.\n\n If the primary is a mutable sequence object (such as a list), the\n subscript must yield an integer. If it is negative, the sequence\'s\n length is added to it. The resulting value must be a nonnegative\n integer less than the sequence\'s length, and the sequence is asked\n to assign the assigned object to its item with that index. If the\n index is out of range, "IndexError" is raised (assignment to a\n subscripted sequence cannot add new items to a list).\n\n If the primary is a mapping object (such as a dictionary), the\n subscript must have a type compatible with the mapping\'s key type,\n and the mapping is then asked to create a key/datum pair which maps\n the subscript to the assigned object. This can either replace an\n existing key/value pair with the same key value, or insert a new\n key/value pair (if no key with the same value existed).\n\n For user-defined objects, the "__setitem__()" method is called with\n appropriate arguments.\n\n* If the target is a slicing: The primary expression in the\n reference is evaluated. It should yield a mutable sequence object\n (such as a list). The assigned object should be a sequence object\n of the same type. Next, the lower and upper bound expressions are\n evaluated, insofar they are present; defaults are zero and the\n sequence\'s length. The bounds should evaluate to integers. If\n either bound is negative, the sequence\'s length is added to it. The\n resulting bounds are clipped to lie between zero and the sequence\'s\n length, inclusive. Finally, the sequence object is asked to replace\n the slice with the items of the assigned sequence. The length of\n the slice may be different from the length of the assigned sequence,\n thus changing the length of the target sequence, if the target\n sequence allows it.\n\n**CPython implementation detail:** In the current implementation, the\nsyntax for targets is taken to be the same as for expressions, and\ninvalid syntax is rejected during the code generation phase, causing\nless detailed error messages.\n\nAlthough the definition of assignment implies that overlaps between\nthe left-hand side and the right-hand side are \'simultaneous\' (for\nexample "a, b = b, a" swaps two variables), overlaps *within* the\ncollection of assigned-to variables occur left-to-right, sometimes\nresulting in confusion. For instance, the following program prints\n"[0, 2]":\n\n x = [0, 1]\n i = 0\n i, x[i] = 1, 2 # i is updated, then x[i] is updated\n print(x)\n\nSee also: **PEP 3132** - Extended Iterable Unpacking\n\n The specification for the "*target" feature.\n\n\nAugmented assignment statements\n===============================\n\nAugmented assignment is the combination, in a single statement, of a\nbinary operation and an assignment statement:\n\n augmented_assignment_stmt ::= augtarget augop (expression_list | yield_expression)\n augtarget ::= identifier | attributeref | subscription | slicing\n augop ::= "+=" | "-=" | "*=" | "@=" | "/=" | "//=" | "%=" | "**="\n | ">>=" | "<<=" | "&=" | "^=" | "|="\n\n(See section *Primaries* for the syntax definitions of the last three\nsymbols.)\n\nAn augmented assignment evaluates the target (which, unlike normal\nassignment statements, cannot be an unpacking) and the expression\nlist, performs the binary operation specific to the type of assignment\non the two operands, and assigns the result to the original target.\nThe target is only evaluated once.\n\nAn augmented assignment expression like "x += 1" can be rewritten as\n"x = x + 1" to achieve a similar, but not exactly equal effect. In the\naugmented version, "x" is only evaluated once. Also, when possible,\nthe actual operation is performed *in-place*, meaning that rather than\ncreating a new object and assigning that to the target, the old object\nis modified instead.\n\nUnlike normal assignments, augmented assignments evaluate the left-\nhand side *before* evaluating the right-hand side. For example, "a[i]\n+= f(x)" first looks-up "a[i]", then it evaluates "f(x)" and performs\nthe addition, and lastly, it writes the result back to "a[i]".\n\nWith the exception of assigning to tuples and multiple targets in a\nsingle statement, the assignment done by augmented assignment\nstatements is handled the same way as normal assignments. Similarly,\nwith the exception of the possible *in-place* behavior, the binary\noperation performed by augmented assignment is the same as the normal\nbinary operations.\n\nFor targets which are attribute references, the same *caveat about\nclass and instance attributes* applies as for regular assignments.\n',
'atom-identifiers': u'\nIdentifiers (Names)\n*******************\n\nAn identifier occurring as an atom is a name. See section\n*Identifiers and keywords* for lexical definition and section *Naming\nand binding* for documentation of naming and binding.\n\nWhen the name is bound to an object, evaluation of the atom yields\nthat object. When a name is not bound, an attempt to evaluate it\nraises a "NameError" exception.\n\n**Private name mangling:** When an identifier that textually occurs in\na class definition begins with two or more underscore characters and\ndoes not end in two or more underscores, it is considered a *private\nname* of that class. Private names are transformed to a longer form\nbefore code is generated for them. The transformation inserts the\nclass name, with leading underscores removed and a single underscore\ninserted, in front of the name. For example, the identifier "__spam"\noccurring in a class named "Ham" will be transformed to "_Ham__spam".\nThis transformation is independent of the syntactical context in which\nthe identifier is used. If the transformed name is extremely long\n(longer than 255 characters), implementation defined truncation may\nhappen. If the class name consists only of underscores, no\ntransformation is done.\n',
'atom-literals': u"\nLiterals\n********\n\nPython supports string and bytes literals and various numeric\nliterals:\n\n literal ::= stringliteral | bytesliteral\n | integer | floatnumber | imagnumber\n\nEvaluation of a literal yields an object of the given type (string,\nbytes, integer, floating point number, complex number) with the given\nvalue. The value may be approximated in the case of floating point\nand imaginary (complex) literals. See section *Literals* for details.\n\nAll literals correspond to immutable data types, and hence the\nobject's identity is less important than its value. Multiple\nevaluations of literals with the same value (either the same\noccurrence in the program text or a different occurrence) may obtain\nthe same object or a different object with the same value.\n",
'attribute-access': u'\nCustomizing attribute access\n****************************\n\nThe following methods can be defined to customize the meaning of\nattribute access (use of, assignment to, or deletion of "x.name") for\nclass instances.\n\nobject.__getattr__(self, name)\n\n Called when an attribute lookup has not found the attribute in the\n usual places (i.e. it is not an instance attribute nor is it found\n in the class tree for "self"). "name" is the attribute name. This\n method should return the (computed) attribute value or raise an\n "AttributeError" exception.\n\n Note that if the attribute is found through the normal mechanism,\n "__getattr__()" is not called. (This is an intentional asymmetry\n between "__getattr__()" and "__setattr__()".) This is done both for\n efficiency reasons and because otherwise "__getattr__()" would have\n no way to access other attributes of the instance. Note that at\n least for instance variables, you can fake total control by not\n inserting any values in the instance attribute dictionary (but\n instead inserting them in another object). See the\n "__getattribute__()" method below for a way to actually get total\n control over attribute access.\n\nobject.__getattribute__(self, name)\n\n Called unconditionally to implement attribute accesses for\n instances of the class. If the class also defines "__getattr__()",\n the latter will not be called unless "__getattribute__()" either\n calls it explicitly or raises an "AttributeError". This method\n should return the (computed) attribute value or raise an\n "AttributeError" exception. In order to avoid infinite recursion in\n this method, its implementation should always call the base class\n method with the same name to access any attributes it needs, for\n example, "object.__getattribute__(self, name)".\n\n Note: This method may still be bypassed when looking up special\n methods as the result of implicit invocation via language syntax\n or built-in functions. See *Special method lookup*.\n\nobject.__setattr__(self, name, value)\n\n Called when an attribute assignment is attempted. This is called\n instead of the normal mechanism (i.e. store the value in the\n instance dictionary). *name* is the attribute name, *value* is the\n value to be assigned to it.\n\n If "__setattr__()" wants to assign to an instance attribute, it\n should call the base class method with the same name, for example,\n "object.__setattr__(self, name, value)".\n\nobject.__delattr__(self, name)\n\n Like "__setattr__()" but for attribute deletion instead of\n assignment. This should only be implemented if "del obj.name" is\n meaningful for the object.\n\nobject.__dir__(self)\n\n Called when "dir()" is called on the object. A sequence must be\n returned. "dir()" converts the returned sequence to a list and\n sorts it.\n\n\nImplementing Descriptors\n========================\n\nThe following methods only apply when an instance of the class\ncontaining the method (a so-called *descriptor* class) appears in an\n*owner* class (the descriptor must be in either the owner\'s class\ndictionary or in the class dictionary for one of its parents). In the\nexamples below, "the attribute" refers to the attribute whose name is\nthe key of the property in the owner class\' "__dict__".\n\nobject.__get__(self, instance, owner)\n\n Called to get the attribute of the owner class (class attribute\n access) or of an instance of that class (instance attribute\n access). *owner* is always the owner class, while *instance* is the\n instance that the attribute was accessed through, or "None" when\n the attribute is accessed through the *owner*. This method should\n return the (computed) attribute value or raise an "AttributeError"\n exception.\n\nobject.__set__(self, instance, value)\n\n Called to set the attribute on an instance *instance* of the owner\n class to a new value, *value*.\n\nobject.__delete__(self, instance)\n\n Called to delete the attribute on an instance *instance* of the\n owner class.\n\nThe attribute "__objclass__" is interpreted by the "inspect" module as\nspecifying the class where this object was defined (setting this\nappropriately can assist in runtime introspection of dynamic class\nattributes). For callables, it may indicate that an instance of the\ngiven type (or a subclass) is expected or required as the first\npositional argument (for example, CPython sets this attribute for\nunbound methods that are implemented in C).\n\n\nInvoking Descriptors\n====================\n\nIn general, a descriptor is an object attribute with "binding\nbehavior", one whose attribute access has been overridden by methods\nin the descriptor protocol: "__get__()", "__set__()", and\n"__delete__()". If any of those methods are defined for an object, it\nis said to be a descriptor.\n\nThe default behavior for attribute access is to get, set, or delete\nthe attribute from an object\'s dictionary. For instance, "a.x" has a\nlookup chain starting with "a.__dict__[\'x\']", then\n"type(a).__dict__[\'x\']", and continuing through the base classes of\n"type(a)" excluding metaclasses.\n\nHowever, if the looked-up value is an object defining one of the\ndescriptor methods, then Python may override the default behavior and\ninvoke the descriptor method instead. Where this occurs in the\nprecedence chain depends on which descriptor methods were defined and\nhow they were called.\n\nThe starting point for descriptor invocation is a binding, "a.x". How\nthe arguments are assembled depends on "a":\n\nDirect Call\n The simplest and least common call is when user code directly\n invokes a descriptor method: "x.__get__(a)".\n\nInstance Binding\n If binding to an object instance, "a.x" is transformed into the\n call: "type(a).__dict__[\'x\'].__get__(a, type(a))".\n\nClass Binding\n If binding to a class, "A.x" is transformed into the call:\n "A.__dict__[\'x\'].__get__(None, A)".\n\nSuper Binding\n If "a" is an instance of "super", then the binding "super(B,\n obj).m()" searches "obj.__class__.__mro__" for the base class "A"\n immediately preceding "B" and then invokes the descriptor with the\n call: "A.__dict__[\'m\'].__get__(obj, obj.__class__)".\n\nFor instance bindings, the precedence of descriptor invocation depends\non the which descriptor methods are defined. A descriptor can define\nany combination of "__get__()", "__set__()" and "__delete__()". If it\ndoes not define "__get__()", then accessing the attribute will return\nthe descriptor object itself unless there is a value in the object\'s\ninstance dictionary. If the descriptor defines "__set__()" and/or\n"__delete__()", it is a data descriptor; if it defines neither, it is\na non-data descriptor. Normally, data descriptors define both\n"__get__()" and "__set__()", while non-data descriptors have just the\n"__get__()" method. Data descriptors with "__set__()" and "__get__()"\ndefined always override a redefinition in an instance dictionary. In\ncontrast, non-data descriptors can be overridden by instances.\n\nPython methods (including "staticmethod()" and "classmethod()") are\nimplemented as non-data descriptors. Accordingly, instances can\nredefine and override methods. This allows individual instances to\nacquire behaviors that differ from other instances of the same class.\n\nThe "property()" function is implemented as a data descriptor.\nAccordingly, instances cannot override the behavior of a property.\n\n\n__slots__\n=========\n\nBy default, instances of classes have a dictionary for attribute\nstorage. This wastes space for objects having very few instance\nvariables. The space consumption can become acute when creating large\nnumbers of instances.\n\nThe default can be overridden by defining *__slots__* in a class\ndefinition. The *__slots__* declaration takes a sequence of instance\nvariables and reserves just enough space in each instance to hold a\nvalue for each variable. Space is saved because *__dict__* is not\ncreated for each instance.\n\nobject.__slots__\n\n This class variable can be assigned a string, iterable, or sequence\n of strings with variable names used by instances. *__slots__*\n reserves space for the declared variables and prevents the\n automatic creation of *__dict__* and *__weakref__* for each\n instance.\n\n\nNotes on using *__slots__*\n--------------------------\n\n* When inheriting from a class without *__slots__*, the *__dict__*\n attribute of that class will always be accessible, so a *__slots__*\n definition in the subclass is meaningless.\n\n* Without a *__dict__* variable, instances cannot be assigned new\n variables not listed in the *__slots__* definition. Attempts to\n assign to an unlisted variable name raises "AttributeError". If\n dynamic assignment of new variables is desired, then add\n "\'__dict__\'" to the sequence of strings in the *__slots__*\n declaration.\n\n* Without a *__weakref__* variable for each instance, classes\n defining *__slots__* do not support weak references to its\n instances. If weak reference support is needed, then add\n "\'__weakref__\'" to the sequence of strings in the *__slots__*\n declaration.\n\n* *__slots__* are implemented at the class level by creating\n descriptors (*Implementing Descriptors*) for each variable name. As\n a result, class attributes cannot be used to set default values for\n instance variables defined by *__slots__*; otherwise, the class\n attribute would overwrite the descriptor assignment.\n\n* The action of a *__slots__* declaration is limited to the class\n where it is defined. As a result, subclasses will have a *__dict__*\n unless they also define *__slots__* (which must only contain names\n of any *additional* slots).\n\n* If a class defines a slot also defined in a base class, the\n instance variable defined by the base class slot is inaccessible\n (except by retrieving its descriptor directly from the base class).\n This renders the meaning of the program undefined. In the future, a\n check may be added to prevent this.\n\n* Nonempty *__slots__* does not work for classes derived from\n "variable-length" built-in types such as "int", "bytes" and "tuple".\n\n* Any non-string iterable may be assigned to *__slots__*. Mappings\n may also be used; however, in the future, special meaning may be\n assigned to the values corresponding to each key.\n\n* *__class__* assignment works only if both classes have the same\n *__slots__*.\n',
'booleans': u'\nBoolean operations\n******************\n\n or_test ::= and_test | or_test "or" and_test\n and_test ::= not_test | and_test "and" not_test\n not_test ::= comparison | "not" not_test\n\nIn the context of Boolean operations, and also when expressions are\nused by control flow statements, the following values are interpreted\nas false: "False", "None", numeric zero of all types, and empty\nstrings and containers (including strings, tuples, lists,\ndictionaries, sets and frozensets). All other values are interpreted\nas true. User-defined objects can customize their truth value by\nproviding a "__bool__()" method.\n\nThe operator "not" yields "True" if its argument is false, "False"\notherwise.\n\nThe expression "x and y" first evaluates *x*; if *x* is false, its\nvalue is returned; otherwise, *y* is evaluated and the resulting value\nis returned.\n\nThe expression "x or y" first evaluates *x*; if *x* is true, its value\nis returned; otherwise, *y* is evaluated and the resulting value is\nreturned.\n\n(Note that neither "and" nor "or" restrict the value and type they\nreturn to "False" and "True", but rather return the last evaluated\nargument. This is sometimes useful, e.g., if "s" is a string that\nshould be replaced by a default value if it is empty, the expression\n"s or \'foo\'" yields the desired value. Because "not" has to create a\nnew value, it returns a boolean value regardless of the type of its\nargument (for example, "not \'foo\'" produces "False" rather than "\'\'".)\n',
'break': u'\nThe "break" statement\n*********************\n\n break_stmt ::= "break"\n\n"break" may only occur syntactically nested in a "for" or "while"\nloop, but not nested in a function or class definition within that\nloop.\n\nIt terminates the nearest enclosing loop, skipping the optional "else"\nclause if the loop has one.\n\nIf a "for" loop is terminated by "break", the loop control target\nkeeps its current value.\n\nWhen "break" passes control out of a "try" statement with a "finally"\nclause, that "finally" clause is executed before really leaving the\nloop.\n',
'callable-types': u'\nEmulating callable objects\n**************************\n\nobject.__call__(self[, args...])\n\n Called when the instance is "called" as a function; if this method\n is defined, "x(arg1, arg2, ...)" is a shorthand for\n "x.__call__(arg1, arg2, ...)".\n',
- 'calls': u'\nCalls\n*****\n\nA call calls a callable object (e.g., a *function*) with a possibly\nempty series of *arguments*:\n\n call ::= primary "(" [argument_list [","] | comprehension] ")"\n argument_list ::= positional_arguments ["," keyword_arguments]\n ["," "*" expression] ["," keyword_arguments]\n ["," "**" expression]\n | keyword_arguments ["," "*" expression]\n ["," keyword_arguments] ["," "**" expression]\n | "*" expression ["," keyword_arguments] ["," "**" expression]\n | "**" expression\n positional_arguments ::= expression ("," expression)*\n keyword_arguments ::= keyword_item ("," keyword_item)*\n keyword_item ::= identifier "=" expression\n\nAn optional trailing comma may be present after the positional and\nkeyword arguments but does not affect the semantics.\n\nThe primary must evaluate to a callable object (user-defined\nfunctions, built-in functions, methods of built-in objects, class\nobjects, methods of class instances, and all objects having a\n"__call__()" method are callable). All argument expressions are\nevaluated before the call is attempted. Please refer to section\n*Function definitions* for the syntax of formal *parameter* lists.\n\nIf keyword arguments are present, they are first converted to\npositional arguments, as follows. First, a list of unfilled slots is\ncreated for the formal parameters. If there are N positional\narguments, they are placed in the first N slots. Next, for each\nkeyword argument, the identifier is used to determine the\ncorresponding slot (if the identifier is the same as the first formal\nparameter name, the first slot is used, and so on). If the slot is\nalready filled, a "TypeError" exception is raised. Otherwise, the\nvalue of the argument is placed in the slot, filling it (even if the\nexpression is "None", it fills the slot). When all arguments have\nbeen processed, the slots that are still unfilled are filled with the\ncorresponding default value from the function definition. (Default\nvalues are calculated, once, when the function is defined; thus, a\nmutable object such as a list or dictionary used as default value will\nbe shared by all calls that don\'t specify an argument value for the\ncorresponding slot; this should usually be avoided.) If there are any\nunfilled slots for which no default value is specified, a "TypeError"\nexception is raised. Otherwise, the list of filled slots is used as\nthe argument list for the call.\n\n**CPython implementation detail:** An implementation may provide\nbuilt-in functions whose positional parameters do not have names, even\nif they are \'named\' for the purpose of documentation, and which\ntherefore cannot be supplied by keyword. In CPython, this is the case\nfor functions implemented in C that use "PyArg_ParseTuple()" to parse\ntheir arguments.\n\nIf there are more positional arguments than there are formal parameter\nslots, a "TypeError" exception is raised, unless a formal parameter\nusing the syntax "*identifier" is present; in this case, that formal\nparameter receives a tuple containing the excess positional arguments\n(or an empty tuple if there were no excess positional arguments).\n\nIf any keyword argument does not correspond to a formal parameter\nname, a "TypeError" exception is raised, unless a formal parameter\nusing the syntax "**identifier" is present; in this case, that formal\nparameter receives a dictionary containing the excess keyword\narguments (using the keywords as keys and the argument values as\ncorresponding values), or a (new) empty dictionary if there were no\nexcess keyword arguments.\n\nIf the syntax "*expression" appears in the function call, "expression"\nmust evaluate to an iterable. Elements from this iterable are treated\nas if they were additional positional arguments; if there are\npositional arguments *x1*, ..., *xN*, and "expression" evaluates to a\nsequence *y1*, ..., *yM*, this is equivalent to a call with M+N\npositional arguments *x1*, ..., *xN*, *y1*, ..., *yM*.\n\nA consequence of this is that although the "*expression" syntax may\nappear *after* some keyword arguments, it is processed *before* the\nkeyword arguments (and the "**expression" argument, if any -- see\nbelow). So:\n\n >>> def f(a, b):\n ... print(a, b)\n ...\n >>> f(b=1, *(2,))\n 2 1\n >>> f(a=1, *(2,))\n Traceback (most recent call last):\n File "<stdin>", line 1, in ?\n TypeError: f() got multiple values for keyword argument \'a\'\n >>> f(1, *(2,))\n 1 2\n\nIt is unusual for both keyword arguments and the "*expression" syntax\nto be used in the same call, so in practice this confusion does not\narise.\n\nIf the syntax "**expression" appears in the function call,\n"expression" must evaluate to a mapping, the contents of which are\ntreated as additional keyword arguments. In the case of a keyword\nappearing in both "expression" and as an explicit keyword argument, a\n"TypeError" exception is raised.\n\nFormal parameters using the syntax "*identifier" or "**identifier"\ncannot be used as positional argument slots or as keyword argument\nnames.\n\nA call always returns some value, possibly "None", unless it raises an\nexception. How this value is computed depends on the type of the\ncallable object.\n\nIf it is---\n\na user-defined function:\n The code block for the function is executed, passing it the\n argument list. The first thing the code block will do is bind the\n formal parameters to the arguments; this is described in section\n *Function definitions*. When the code block executes a "return"\n statement, this specifies the return value of the function call.\n\na built-in function or method:\n The result is up to the interpreter; see *Built-in Functions* for\n the descriptions of built-in functions and methods.\n\na class object:\n A new instance of that class is returned.\n\na class instance method:\n The corresponding user-defined function is called, with an argument\n list that is one longer than the argument list of the call: the\n instance becomes the first argument.\n\na class instance:\n The class must define a "__call__()" method; the effect is then the\n same as if that method was called.\n',
- 'class': u'\nClass definitions\n*****************\n\nA class definition defines a class object (see section *The standard\ntype hierarchy*):\n\n classdef ::= [decorators] "class" classname [inheritance] ":" suite\n inheritance ::= "(" [parameter_list] ")"\n classname ::= identifier\n\nA class definition is an executable statement. The inheritance list\nusually gives a list of base classes (see *Customizing class creation*\nfor more advanced uses), so each item in the list should evaluate to a\nclass object which allows subclassing. Classes without an inheritance\nlist inherit, by default, from the base class "object"; hence,\n\n class Foo:\n pass\n\nis equivalent to\n\n class Foo(object):\n pass\n\nThe class\'s suite is then executed in a new execution frame (see\n*Naming and binding*), using a newly created local namespace and the\noriginal global namespace. (Usually, the suite contains mostly\nfunction definitions.) When the class\'s suite finishes execution, its\nexecution frame is discarded but its local namespace is saved. [4] A\nclass object is then created using the inheritance list for the base\nclasses and the saved local namespace for the attribute dictionary.\nThe class name is bound to this class object in the original local\nnamespace.\n\nClass creation can be customized heavily using *metaclasses*.\n\nClasses can also be decorated: just like when decorating functions,\n\n @f1(arg)\n @f2\n class Foo: pass\n\nis equivalent to\n\n class Foo: pass\n Foo = f1(arg)(f2(Foo))\n\nThe evaluation rules for the decorator expressions are the same as for\nfunction decorators. The result must be a class object, which is then\nbound to the class name.\n\n**Programmer\'s note:** Variables defined in the class definition are\nclass attributes; they are shared by instances. Instance attributes\ncan be set in a method with "self.name = value". Both class and\ninstance attributes are accessible through the notation ""self.name"",\nand an instance attribute hides a class attribute with the same name\nwhen accessed in this way. Class attributes can be used as defaults\nfor instance attributes, but using mutable values there can lead to\nunexpected results. *Descriptors* can be used to create instance\nvariables with different implementation details.\n\nSee also: **PEP 3115** - Metaclasses in Python 3 **PEP 3129** -\n Class Decorators\n',
+ 'calls': u'\nCalls\n*****\n\nA call calls a callable object (e.g., a *function*) with a possibly\nempty series of *arguments*:\n\n call ::= primary "(" [argument_list [","] | comprehension] ")"\n argument_list ::= positional_arguments ["," starred_and_keywords]\n ["," keywords_arguments]\n | starred_and_keywords ["," keywords_arguments]\n | keywords_arguments\n positional_arguments ::= ["*"] expression ("," ["*"] expression)*\n starred_and_keywords ::= ("*" expression | keyword_item)\n ("," "*" expression | "," keyword_item)*\n keywords_arguments ::= (keyword_item | "**" expression)\n ("," keyword_item | "**" expression)*\n keyword_item ::= identifier "=" expression\n\nAn optional trailing comma may be present after the positional and\nkeyword arguments but does not affect the semantics.\n\nThe primary must evaluate to a callable object (user-defined\nfunctions, built-in functions, methods of built-in objects, class\nobjects, methods of class instances, and all objects having a\n"__call__()" method are callable). All argument expressions are\nevaluated before the call is attempted. Please refer to section\n*Function definitions* for the syntax of formal *parameter* lists.\n\nIf keyword arguments are present, they are first converted to\npositional arguments, as follows. First, a list of unfilled slots is\ncreated for the formal parameters. If there are N positional\narguments, they are placed in the first N slots. Next, for each\nkeyword argument, the identifier is used to determine the\ncorresponding slot (if the identifier is the same as the first formal\nparameter name, the first slot is used, and so on). If the slot is\nalready filled, a "TypeError" exception is raised. Otherwise, the\nvalue of the argument is placed in the slot, filling it (even if the\nexpression is "None", it fills the slot). When all arguments have\nbeen processed, the slots that are still unfilled are filled with the\ncorresponding default value from the function definition. (Default\nvalues are calculated, once, when the function is defined; thus, a\nmutable object such as a list or dictionary used as default value will\nbe shared by all calls that don\'t specify an argument value for the\ncorresponding slot; this should usually be avoided.) If there are any\nunfilled slots for which no default value is specified, a "TypeError"\nexception is raised. Otherwise, the list of filled slots is used as\nthe argument list for the call.\n\n**CPython implementation detail:** An implementation may provide\nbuilt-in functions whose positional parameters do not have names, even\nif they are \'named\' for the purpose of documentation, and which\ntherefore cannot be supplied by keyword. In CPython, this is the case\nfor functions implemented in C that use "PyArg_ParseTuple()" to parse\ntheir arguments.\n\nIf there are more positional arguments than there are formal parameter\nslots, a "TypeError" exception is raised, unless a formal parameter\nusing the syntax "*identifier" is present; in this case, that formal\nparameter receives a tuple containing the excess positional arguments\n(or an empty tuple if there were no excess positional arguments).\n\nIf any keyword argument does not correspond to a formal parameter\nname, a "TypeError" exception is raised, unless a formal parameter\nusing the syntax "**identifier" is present; in this case, that formal\nparameter receives a dictionary containing the excess keyword\narguments (using the keywords as keys and the argument values as\ncorresponding values), or a (new) empty dictionary if there were no\nexcess keyword arguments.\n\nIf the syntax "*expression" appears in the function call, "expression"\nmust evaluate to an *iterable*. Elements from these iterables are\ntreated as if they were additional positional arguments. For the call\n"f(x1, x2, *y, x3, x4)", if *y* evaluates to a sequence *y1*, ...,\n*yM*, this is equivalent to a call with M+4 positional arguments *x1*,\n*x2*, *y1*, ..., *yM*, *x3*, *x4*.\n\nA consequence of this is that although the "*expression" syntax may\nappear *after* explicit keyword arguments, it is processed *before*\nthe keyword arguments (and any "**expression" arguments -- see below).\nSo:\n\n >>> def f(a, b):\n ... print(a, b)\n ...\n >>> f(b=1, *(2,))\n 2 1\n >>> f(a=1, *(2,))\n Traceback (most recent call last):\n File "<stdin>", line 1, in ?\n TypeError: f() got multiple values for keyword argument \'a\'\n >>> f(1, *(2,))\n 1 2\n\nIt is unusual for both keyword arguments and the "*expression" syntax\nto be used in the same call, so in practice this confusion does not\narise.\n\nIf the syntax "**expression" appears in the function call,\n"expression" must evaluate to a *mapping*, the contents of which are\ntreated as additional keyword arguments. If a keyword is already\npresent (as an explicit keyword argument, or from another unpacking),\na "TypeError" exception is raised.\n\nFormal parameters using the syntax "*identifier" or "**identifier"\ncannot be used as positional argument slots or as keyword argument\nnames.\n\nChanged in version 3.5: Function calls accept any number of "*" and\n"**" unpackings, positional arguments may follow iterable unpackings\n("*"), and keyword arguments may follow dictionary unpackings ("**").\nOriginally proposed by **PEP 448**.\n\nA call always returns some value, possibly "None", unless it raises an\nexception. How this value is computed depends on the type of the\ncallable object.\n\nIf it is---\n\na user-defined function:\n The code block for the function is executed, passing it the\n argument list. The first thing the code block will do is bind the\n formal parameters to the arguments; this is described in section\n *Function definitions*. When the code block executes a "return"\n statement, this specifies the return value of the function call.\n\na built-in function or method:\n The result is up to the interpreter; see *Built-in Functions* for\n the descriptions of built-in functions and methods.\n\na class object:\n A new instance of that class is returned.\n\na class instance method:\n The corresponding user-defined function is called, with an argument\n list that is one longer than the argument list of the call: the\n instance becomes the first argument.\n\na class instance:\n The class must define a "__call__()" method; the effect is then the\n same as if that method was called.\n',
+ 'class': u'\nClass definitions\n*****************\n\nA class definition defines a class object (see section *The standard\ntype hierarchy*):\n\n classdef ::= [decorators] "class" classname [inheritance] ":" suite\n inheritance ::= "(" [argument_list] ")"\n classname ::= identifier\n\nA class definition is an executable statement. The inheritance list\nusually gives a list of base classes (see *Customizing class creation*\nfor more advanced uses), so each item in the list should evaluate to a\nclass object which allows subclassing. Classes without an inheritance\nlist inherit, by default, from the base class "object"; hence,\n\n class Foo:\n pass\n\nis equivalent to\n\n class Foo(object):\n pass\n\nThe class\'s suite is then executed in a new execution frame (see\n*Naming and binding*), using a newly created local namespace and the\noriginal global namespace. (Usually, the suite contains mostly\nfunction definitions.) When the class\'s suite finishes execution, its\nexecution frame is discarded but its local namespace is saved. [4] A\nclass object is then created using the inheritance list for the base\nclasses and the saved local namespace for the attribute dictionary.\nThe class name is bound to this class object in the original local\nnamespace.\n\nClass creation can be customized heavily using *metaclasses*.\n\nClasses can also be decorated: just like when decorating functions,\n\n @f1(arg)\n @f2\n class Foo: pass\n\nis equivalent to\n\n class Foo: pass\n Foo = f1(arg)(f2(Foo))\n\nThe evaluation rules for the decorator expressions are the same as for\nfunction decorators. The result must be a class object, which is then\nbound to the class name.\n\n**Programmer\'s note:** Variables defined in the class definition are\nclass attributes; they are shared by instances. Instance attributes\ncan be set in a method with "self.name = value". Both class and\ninstance attributes are accessible through the notation ""self.name"",\nand an instance attribute hides a class attribute with the same name\nwhen accessed in this way. Class attributes can be used as defaults\nfor instance attributes, but using mutable values there can lead to\nunexpected results. *Descriptors* can be used to create instance\nvariables with different implementation details.\n\nSee also: **PEP 3115** - Metaclasses in Python 3 **PEP 3129** -\n Class Decorators\n',
'comparisons': u'\nComparisons\n***********\n\nUnlike C, all comparison operations in Python have the same priority,\nwhich is lower than that of any arithmetic, shifting or bitwise\noperation. Also unlike C, expressions like "a < b < c" have the\ninterpretation that is conventional in mathematics:\n\n comparison ::= or_expr ( comp_operator or_expr )*\n comp_operator ::= "<" | ">" | "==" | ">=" | "<=" | "!="\n | "is" ["not"] | ["not"] "in"\n\nComparisons yield boolean values: "True" or "False".\n\nComparisons can be chained arbitrarily, e.g., "x < y <= z" is\nequivalent to "x < y and y <= z", except that "y" is evaluated only\nonce (but in both cases "z" is not evaluated at all when "x < y" is\nfound to be false).\n\nFormally, if *a*, *b*, *c*, ..., *y*, *z* are expressions and *op1*,\n*op2*, ..., *opN* are comparison operators, then "a op1 b op2 c ... y\nopN z" is equivalent to "a op1 b and b op2 c and ... y opN z", except\nthat each expression is evaluated at most once.\n\nNote that "a op1 b op2 c" doesn\'t imply any kind of comparison between\n*a* and *c*, so that, e.g., "x < y > z" is perfectly legal (though\nperhaps not pretty).\n\n\nValue comparisons\n=================\n\nThe operators "<", ">", "==", ">=", "<=", and "!=" compare the values\nof two objects. The objects do not need to have the same type.\n\nChapter *Objects, values and types* states that objects have a value\n(in addition to type and identity). The value of an object is a\nrather abstract notion in Python: For example, there is no canonical\naccess method for an object\'s value. Also, there is no requirement\nthat the value of an object should be constructed in a particular way,\ne.g. comprised of all its data attributes. Comparison operators\nimplement a particular notion of what the value of an object is. One\ncan think of them as defining the value of an object indirectly, by\nmeans of their comparison implementation.\n\nBecause all types are (direct or indirect) subtypes of "object", they\ninherit the default comparison behavior from "object". Types can\ncustomize their comparison behavior by implementing *rich comparison\nmethods* like "__lt__()", described in *Basic customization*.\n\nThe default behavior for equality comparison ("==" and "!=") is based\non the identity of the objects. Hence, equality comparison of\ninstances with the same identity results in equality, and equality\ncomparison of instances with different identities results in\ninequality. A motivation for this default behavior is the desire that\nall objects should be reflexive (i.e. "x is y" implies "x == y").\n\nA default order comparison ("<", ">", "<=", and ">=") is not provided;\nan attempt raises "TypeError". A motivation for this default behavior\nis the lack of a similar invariant as for equality.\n\nThe behavior of the default equality comparison, that instances with\ndifferent identities are always unequal, may be in contrast to what\ntypes will need that have a sensible definition of object value and\nvalue-based equality. Such types will need to customize their\ncomparison behavior, and in fact, a number of built-in types have done\nthat.\n\nThe following list describes the comparison behavior of the most\nimportant built-in types.\n\n* Numbers of built-in numeric types (*Numeric Types --- int, float,\n complex*) and of the standard library types "fractions.Fraction" and\n "decimal.Decimal" can be compared within and across their types,\n with the restriction that complex numbers do not support order\n comparison. Within the limits of the types involved, they compare\n mathematically (algorithmically) correct without loss of precision.\n\n The not-a-number values "float(\'NaN\')" and "Decimal(\'NaN\')" are\n special. They are identical to themselves ("x is x" is true) but\n are not equal to themselves ("x == x" is false). Additionally,\n comparing any number to a not-a-number value will return "False".\n For example, both "3 < float(\'NaN\')" and "float(\'NaN\') < 3" will\n return "False".\n\n* Binary sequences (instances of "bytes" or "bytearray") can be\n compared within and across their types. They compare\n lexicographically using the numeric values of their elements.\n\n* Strings (instances of "str") compare lexicographically using the\n numerical Unicode code points (the result of the built-in function\n "ord()") of their characters. [3]\n\n Strings and binary sequences cannot be directly compared.\n\n* Sequences (instances of "tuple", "list", or "range") can be\n compared only within each of their types, with the restriction that\n ranges do not support order comparison. Equality comparison across\n these types results in unequality, and ordering comparison across\n these types raises "TypeError".\n\n Sequences compare lexicographically using comparison of\n corresponding elements, whereby reflexivity of the elements is\n enforced.\n\n In enforcing reflexivity of elements, the comparison of collections\n assumes that for a collection element "x", "x == x" is always true.\n Based on that assumption, element identity is compared first, and\n element comparison is performed only for distinct elements. This\n approach yields the same result as a strict element comparison\n would, if the compared elements are reflexive. For non-reflexive\n elements, the result is different than for strict element\n comparison, and may be surprising: The non-reflexive not-a-number\n values for example result in the following comparison behavior when\n used in a list:\n\n >>> nan = float(\'NaN\')\n >>> nan is nan\n True\n >>> nan == nan\n False <-- the defined non-reflexive behavior of NaN\n >>> [nan] == [nan]\n True <-- list enforces reflexivity and tests identity first\n\n Lexicographical comparison between built-in collections works as\n follows:\n\n * For two collections to compare equal, they must be of the same\n type, have the same length, and each pair of corresponding\n elements must compare equal (for example, "[1,2] == (1,2)" is\n false because the type is not the same).\n\n * Collections that support order comparison are ordered the same\n as their first unequal elements (for example, "[1,2,x] <= [1,2,y]"\n has the same value as "x <= y"). If a corresponding element does\n not exist, the shorter collection is ordered first (for example,\n "[1,2] < [1,2,3]" is true).\n\n* Mappings (instances of "dict") compare equal if and only if they\n have equal *(key, value)* pairs. Equality comparison of the keys and\n elements enforces reflexivity.\n\n Order comparisons ("<", ">", "<=", and ">=") raise "TypeError".\n\n* Sets (instances of "set" or "frozenset") can be compared within\n and across their types.\n\n They define order comparison operators to mean subset and superset\n tests. Those relations do not define total orderings (for example,\n the two sets "{1,2}" and "{2,3}" are not equal, nor subsets of one\n another, nor supersets of one another). Accordingly, sets are not\n appropriate arguments for functions which depend on total ordering\n (for example, "min()", "max()", and "sorted()" produce undefined\n results given a list of sets as inputs).\n\n Comparison of sets enforces reflexivity of its elements.\n\n* Most other built-in types have no comparison methods implemented,\n so they inherit the default comparison behavior.\n\nUser-defined classes that customize their comparison behavior should\nfollow some consistency rules, if possible:\n\n* Equality comparison should be reflexive. In other words, identical\n objects should compare equal:\n\n "x is y" implies "x == y"\n\n* Comparison should be symmetric. In other words, the following\n expressions should have the same result:\n\n "x == y" and "y == x"\n\n "x != y" and "y != x"\n\n "x < y" and "y > x"\n\n "x <= y" and "y >= x"\n\n* Comparison should be transitive. The following (non-exhaustive)\n examples illustrate that:\n\n "x > y and y > z" implies "x > z"\n\n "x < y and y <= z" implies "x < z"\n\n* Inverse comparison should result in the boolean negation. In other\n words, the following expressions should have the same result:\n\n "x == y" and "not x != y"\n\n "x < y" and "not x >= y" (for total ordering)\n\n "x > y" and "not x <= y" (for total ordering)\n\n The last two expressions apply to totally ordered collections (e.g.\n to sequences, but not to sets or mappings). See also the\n "total_ordering()" decorator.\n\nPython does not enforce these consistency rules. In fact, the\nnot-a-number values are an example for not following these rules.\n\n\nMembership test operations\n==========================\n\nThe operators "in" and "not in" test for membership. "x in s"\nevaluates to true if *x* is a member of *s*, and false otherwise. "x\nnot in s" returns the negation of "x in s". All built-in sequences\nand set types support this as well as dictionary, for which "in" tests\nwhether the dictionary has a given key. For container types such as\nlist, tuple, set, frozenset, dict, or collections.deque, the\nexpression "x in y" is equivalent to "any(x is e or x == e for e in\ny)".\n\nFor the string and bytes types, "x in y" is true if and only if *x* is\na substring of *y*. An equivalent test is "y.find(x) != -1". Empty\nstrings are always considered to be a substring of any other string,\nso """ in "abc"" will return "True".\n\nFor user-defined classes which define the "__contains__()" method, "x\nin y" is true if and only if "y.__contains__(x)" is true.\n\nFor user-defined classes which do not define "__contains__()" but do\ndefine "__iter__()", "x in y" is true if some value "z" with "x == z"\nis produced while iterating over "y". If an exception is raised\nduring the iteration, it is as if "in" raised that exception.\n\nLastly, the old-style iteration protocol is tried: if a class defines\n"__getitem__()", "x in y" is true if and only if there is a non-\nnegative integer index *i* such that "x == y[i]", and all lower\ninteger indices do not raise "IndexError" exception. (If any other\nexception is raised, it is as if "in" raised that exception).\n\nThe operator "not in" is defined to have the inverse true value of\n"in".\n\n\nIdentity comparisons\n====================\n\nThe operators "is" and "is not" test for object identity: "x is y" is\ntrue if and only if *x* and *y* are the same object. "x is not y"\nyields the inverse truth value. [4]\n',
- 'compound': u'\nCompound statements\n*******************\n\nCompound statements contain (groups of) other statements; they affect\nor control the execution of those other statements in some way. In\ngeneral, compound statements span multiple lines, although in simple\nincarnations a whole compound statement may be contained in one line.\n\nThe "if", "while" and "for" statements implement traditional control\nflow constructs. "try" specifies exception handlers and/or cleanup\ncode for a group of statements, while the "with" statement allows the\nexecution of initialization and finalization code around a block of\ncode. Function and class definitions are also syntactically compound\nstatements.\n\nA compound statement consists of one or more \'clauses.\' A clause\nconsists of a header and a \'suite.\' The clause headers of a\nparticular compound statement are all at the same indentation level.\nEach clause header begins with a uniquely identifying keyword and ends\nwith a colon. A suite is a group of statements controlled by a\nclause. A suite can be one or more semicolon-separated simple\nstatements on the same line as the header, following the header\'s\ncolon, or it can be one or more indented statements on subsequent\nlines. Only the latter form of a suite can contain nested compound\nstatements; the following is illegal, mostly because it wouldn\'t be\nclear to which "if" clause a following "else" clause would belong:\n\n if test1: if test2: print(x)\n\nAlso note that the semicolon binds tighter than the colon in this\ncontext, so that in the following example, either all or none of the\n"print()" calls are executed:\n\n if x < y < z: print(x); print(y); print(z)\n\nSummarizing:\n\n compound_stmt ::= if_stmt\n | while_stmt\n | for_stmt\n | try_stmt\n | with_stmt\n | funcdef\n | classdef\n | async_with_stmt\n | async_for_stmt\n | async_funcdef\n suite ::= stmt_list NEWLINE | NEWLINE INDENT statement+ DEDENT\n statement ::= stmt_list NEWLINE | compound_stmt\n stmt_list ::= simple_stmt (";" simple_stmt)* [";"]\n\nNote that statements always end in a "NEWLINE" possibly followed by a\n"DEDENT". Also note that optional continuation clauses always begin\nwith a keyword that cannot start a statement, thus there are no\nambiguities (the \'dangling "else"\' problem is solved in Python by\nrequiring nested "if" statements to be indented).\n\nThe formatting of the grammar rules in the following sections places\neach clause on a separate line for clarity.\n\n\nThe "if" statement\n==================\n\nThe "if" statement is used for conditional execution:\n\n if_stmt ::= "if" expression ":" suite\n ( "elif" expression ":" suite )*\n ["else" ":" suite]\n\nIt selects exactly one of the suites by evaluating the expressions one\nby one until one is found to be true (see section *Boolean operations*\nfor the definition of true and false); then that suite is executed\n(and no other part of the "if" statement is executed or evaluated).\nIf all expressions are false, the suite of the "else" clause, if\npresent, is executed.\n\n\nThe "while" statement\n=====================\n\nThe "while" statement is used for repeated execution as long as an\nexpression is true:\n\n while_stmt ::= "while" expression ":" suite\n ["else" ":" suite]\n\nThis repeatedly tests the expression and, if it is true, executes the\nfirst suite; if the expression is false (which may be the first time\nit is tested) the suite of the "else" clause, if present, is executed\nand the loop terminates.\n\nA "break" statement executed in the first suite terminates the loop\nwithout executing the "else" clause\'s suite. A "continue" statement\nexecuted in the first suite skips the rest of the suite and goes back\nto testing the expression.\n\n\nThe "for" statement\n===================\n\nThe "for" statement is used to iterate over the elements of a sequence\n(such as a string, tuple or list) or other iterable object:\n\n for_stmt ::= "for" target_list "in" expression_list ":" suite\n ["else" ":" suite]\n\nThe expression list is evaluated once; it should yield an iterable\nobject. An iterator is created for the result of the\n"expression_list". The suite is then executed once for each item\nprovided by the iterator, in the order returned by the iterator. Each\nitem in turn is assigned to the target list using the standard rules\nfor assignments (see *Assignment statements*), and then the suite is\nexecuted. When the items are exhausted (which is immediately when the\nsequence is empty or an iterator raises a "StopIteration" exception),\nthe suite in the "else" clause, if present, is executed, and the loop\nterminates.\n\nA "break" statement executed in the first suite terminates the loop\nwithout executing the "else" clause\'s suite. A "continue" statement\nexecuted in the first suite skips the rest of the suite and continues\nwith the next item, or with the "else" clause if there is no next\nitem.\n\nThe for-loop makes assignments to the variables(s) in the target list.\nThis overwrites all previous assignments to those variables including\nthose made in the suite of the for-loop:\n\n for i in range(10):\n print(i)\n i = 5 # this will not affect the for-loop\n # because i will be overwritten with the next\n # index in the range\n\nNames in the target list are not deleted when the loop is finished,\nbut if the sequence is empty, they will not have been assigned to at\nall by the loop. Hint: the built-in function "range()" returns an\niterator of integers suitable to emulate the effect of Pascal\'s "for i\n:= a to b do"; e.g., "list(range(3))" returns the list "[0, 1, 2]".\n\nNote: There is a subtlety when the sequence is being modified by the\n loop (this can only occur for mutable sequences, i.e. lists). An\n internal counter is used to keep track of which item is used next,\n and this is incremented on each iteration. When this counter has\n reached the length of the sequence the loop terminates. This means\n that if the suite deletes the current (or a previous) item from the\n sequence, the next item will be skipped (since it gets the index of\n the current item which has already been treated). Likewise, if the\n suite inserts an item in the sequence before the current item, the\n current item will be treated again the next time through the loop.\n This can lead to nasty bugs that can be avoided by making a\n temporary copy using a slice of the whole sequence, e.g.,\n\n for x in a[:]:\n if x < 0: a.remove(x)\n\n\nThe "try" statement\n===================\n\nThe "try" statement specifies exception handlers and/or cleanup code\nfor a group of statements:\n\n try_stmt ::= try1_stmt | try2_stmt\n try1_stmt ::= "try" ":" suite\n ("except" [expression ["as" identifier]] ":" suite)+\n ["else" ":" suite]\n ["finally" ":" suite]\n try2_stmt ::= "try" ":" suite\n "finally" ":" suite\n\nThe "except" clause(s) specify one or more exception handlers. When no\nexception occurs in the "try" clause, no exception handler is\nexecuted. When an exception occurs in the "try" suite, a search for an\nexception handler is started. This search inspects the except clauses\nin turn until one is found that matches the exception. An expression-\nless except clause, if present, must be last; it matches any\nexception. For an except clause with an expression, that expression\nis evaluated, and the clause matches the exception if the resulting\nobject is "compatible" with the exception. An object is compatible\nwith an exception if it is the class or a base class of the exception\nobject or a tuple containing an item compatible with the exception.\n\nIf no except clause matches the exception, the search for an exception\nhandler continues in the surrounding code and on the invocation stack.\n[1]\n\nIf the evaluation of an expression in the header of an except clause\nraises an exception, the original search for a handler is canceled and\na search starts for the new exception in the surrounding code and on\nthe call stack (it is treated as if the entire "try" statement raised\nthe exception).\n\nWhen a matching except clause is found, the exception is assigned to\nthe target specified after the "as" keyword in that except clause, if\npresent, and the except clause\'s suite is executed. All except\nclauses must have an executable block. When the end of this block is\nreached, execution continues normally after the entire try statement.\n(This means that if two nested handlers exist for the same exception,\nand the exception occurs in the try clause of the inner handler, the\nouter handler will not handle the exception.)\n\nWhen an exception has been assigned using "as target", it is cleared\nat the end of the except clause. This is as if\n\n except E as N:\n foo\n\nwas translated to\n\n except E as N:\n try:\n foo\n finally:\n del N\n\nThis means the exception must be assigned to a different name to be\nable to refer to it after the except clause. Exceptions are cleared\nbecause with the traceback attached to them, they form a reference\ncycle with the stack frame, keeping all locals in that frame alive\nuntil the next garbage collection occurs.\n\nBefore an except clause\'s suite is executed, details about the\nexception are stored in the "sys" module and can be accessed via\n"sys.exc_info()". "sys.exc_info()" returns a 3-tuple consisting of the\nexception class, the exception instance and a traceback object (see\nsection *The standard type hierarchy*) identifying the point in the\nprogram where the exception occurred. "sys.exc_info()" values are\nrestored to their previous values (before the call) when returning\nfrom a function that handled an exception.\n\nThe optional "else" clause is executed if and when control flows off\nthe end of the "try" clause. [2] Exceptions in the "else" clause are\nnot handled by the preceding "except" clauses.\n\nIf "finally" is present, it specifies a \'cleanup\' handler. The "try"\nclause is executed, including any "except" and "else" clauses. If an\nexception occurs in any of the clauses and is not handled, the\nexception is temporarily saved. The "finally" clause is executed. If\nthere is a saved exception it is re-raised at the end of the "finally"\nclause. If the "finally" clause raises another exception, the saved\nexception is set as the context of the new exception. If the "finally"\nclause executes a "return" or "break" statement, the saved exception\nis discarded:\n\n >>> def f():\n ... try:\n ... 1/0\n ... finally:\n ... return 42\n ...\n >>> f()\n 42\n\nThe exception information is not available to the program during\nexecution of the "finally" clause.\n\nWhen a "return", "break" or "continue" statement is executed in the\n"try" suite of a "try"..."finally" statement, the "finally" clause is\nalso executed \'on the way out.\' A "continue" statement is illegal in\nthe "finally" clause. (The reason is a problem with the current\nimplementation --- this restriction may be lifted in the future).\n\nThe return value of a function is determined by the last "return"\nstatement executed. Since the "finally" clause always executes, a\n"return" statement executed in the "finally" clause will always be the\nlast one executed:\n\n >>> def foo():\n ... try:\n ... return \'try\'\n ... finally:\n ... return \'finally\'\n ...\n >>> foo()\n \'finally\'\n\nAdditional information on exceptions can be found in section\n*Exceptions*, and information on using the "raise" statement to\ngenerate exceptions may be found in section *The raise statement*.\n\n\nThe "with" statement\n====================\n\nThe "with" statement is used to wrap the execution of a block with\nmethods defined by a context manager (see section *With Statement\nContext Managers*). This allows common "try"..."except"..."finally"\nusage patterns to be encapsulated for convenient reuse.\n\n with_stmt ::= "with" with_item ("," with_item)* ":" suite\n with_item ::= expression ["as" target]\n\nThe execution of the "with" statement with one "item" proceeds as\nfollows:\n\n1. The context expression (the expression given in the "with_item")\n is evaluated to obtain a context manager.\n\n2. The context manager\'s "__exit__()" is loaded for later use.\n\n3. The context manager\'s "__enter__()" method is invoked.\n\n4. If a target was included in the "with" statement, the return\n value from "__enter__()" is assigned to it.\n\n Note: The "with" statement guarantees that if the "__enter__()"\n method returns without an error, then "__exit__()" will always be\n called. Thus, if an error occurs during the assignment to the\n target list, it will be treated the same as an error occurring\n within the suite would be. See step 6 below.\n\n5. The suite is executed.\n\n6. The context manager\'s "__exit__()" method is invoked. If an\n exception caused the suite to be exited, its type, value, and\n traceback are passed as arguments to "__exit__()". Otherwise, three\n "None" arguments are supplied.\n\n If the suite was exited due to an exception, and the return value\n from the "__exit__()" method was false, the exception is reraised.\n If the return value was true, the exception is suppressed, and\n execution continues with the statement following the "with"\n statement.\n\n If the suite was exited for any reason other than an exception, the\n return value from "__exit__()" is ignored, and execution proceeds\n at the normal location for the kind of exit that was taken.\n\nWith more than one item, the context managers are processed as if\nmultiple "with" statements were nested:\n\n with A() as a, B() as b:\n suite\n\nis equivalent to\n\n with A() as a:\n with B() as b:\n suite\n\nChanged in version 3.1: Support for multiple context expressions.\n\nSee also: **PEP 0343** - The "with" statement\n\n The specification, background, and examples for the Python "with"\n statement.\n\n\nFunction definitions\n====================\n\nA function definition defines a user-defined function object (see\nsection *The standard type hierarchy*):\n\n funcdef ::= [decorators] "def" funcname "(" [parameter_list] ")" ["->" expression] ":" suite\n decorators ::= decorator+\n decorator ::= "@" dotted_name ["(" [parameter_list [","]] ")"] NEWLINE\n dotted_name ::= identifier ("." identifier)*\n parameter_list ::= (defparameter ",")*\n | "*" [parameter] ("," defparameter)* ["," "**" parameter]\n | "**" parameter\n | defparameter [","] )\n parameter ::= identifier [":" expression]\n defparameter ::= parameter ["=" expression]\n funcname ::= identifier\n\nA function definition is an executable statement. Its execution binds\nthe function name in the current local namespace to a function object\n(a wrapper around the executable code for the function). This\nfunction object contains a reference to the current global namespace\nas the global namespace to be used when the function is called.\n\nThe function definition does not execute the function body; this gets\nexecuted only when the function is called. [3]\n\nA function definition may be wrapped by one or more *decorator*\nexpressions. Decorator expressions are evaluated when the function is\ndefined, in the scope that contains the function definition. The\nresult must be a callable, which is invoked with the function object\nas the only argument. The returned value is bound to the function name\ninstead of the function object. Multiple decorators are applied in\nnested fashion. For example, the following code\n\n @f1(arg)\n @f2\n def func(): pass\n\nis equivalent to\n\n def func(): pass\n func = f1(arg)(f2(func))\n\nWhen one or more *parameters* have the form *parameter* "="\n*expression*, the function is said to have "default parameter values."\nFor a parameter with a default value, the corresponding *argument* may\nbe omitted from a call, in which case the parameter\'s default value is\nsubstituted. If a parameter has a default value, all following\nparameters up until the ""*"" must also have a default value --- this\nis a syntactic restriction that is not expressed by the grammar.\n\n**Default parameter values are evaluated from left to right when the\nfunction definition is executed.** This means that the expression is\nevaluated once, when the function is defined, and that the same "pre-\ncomputed" value is used for each call. This is especially important\nto understand when a default parameter is a mutable object, such as a\nlist or a dictionary: if the function modifies the object (e.g. by\nappending an item to a list), the default value is in effect modified.\nThis is generally not what was intended. A way around this is to use\n"None" as the default, and explicitly test for it in the body of the\nfunction, e.g.:\n\n def whats_on_the_telly(penguin=None):\n if penguin is None:\n penguin = []\n penguin.append("property of the zoo")\n return penguin\n\nFunction call semantics are described in more detail in section\n*Calls*. A function call always assigns values to all parameters\nmentioned in the parameter list, either from position arguments, from\nkeyword arguments, or from default values. If the form\n""*identifier"" is present, it is initialized to a tuple receiving any\nexcess positional parameters, defaulting to the empty tuple. If the\nform ""**identifier"" is present, it is initialized to a new\ndictionary receiving any excess keyword arguments, defaulting to a new\nempty dictionary. Parameters after ""*"" or ""*identifier"" are\nkeyword-only parameters and may only be passed used keyword arguments.\n\nParameters may have annotations of the form "": expression"" following\nthe parameter name. Any parameter may have an annotation even those\nof the form "*identifier" or "**identifier". Functions may have\n"return" annotation of the form ""-> expression"" after the parameter\nlist. These annotations can be any valid Python expression and are\nevaluated when the function definition is executed. Annotations may\nbe evaluated in a different order than they appear in the source code.\nThe presence of annotations does not change the semantics of a\nfunction. The annotation values are available as values of a\ndictionary keyed by the parameters\' names in the "__annotations__"\nattribute of the function object.\n\nIt is also possible to create anonymous functions (functions not bound\nto a name), for immediate use in expressions. This uses lambda\nexpressions, described in section *Lambdas*. Note that the lambda\nexpression is merely a shorthand for a simplified function definition;\na function defined in a ""def"" statement can be passed around or\nassigned to another name just like a function defined by a lambda\nexpression. The ""def"" form is actually more powerful since it\nallows the execution of multiple statements and annotations.\n\n**Programmer\'s note:** Functions are first-class objects. A ""def""\nstatement executed inside a function definition defines a local\nfunction that can be returned or passed around. Free variables used\nin the nested function can access the local variables of the function\ncontaining the def. See section *Naming and binding* for details.\n\nSee also: **PEP 3107** - Function Annotations\n\n The original specification for function annotations.\n\n\nClass definitions\n=================\n\nA class definition defines a class object (see section *The standard\ntype hierarchy*):\n\n classdef ::= [decorators] "class" classname [inheritance] ":" suite\n inheritance ::= "(" [parameter_list] ")"\n classname ::= identifier\n\nA class definition is an executable statement. The inheritance list\nusually gives a list of base classes (see *Customizing class creation*\nfor more advanced uses), so each item in the list should evaluate to a\nclass object which allows subclassing. Classes without an inheritance\nlist inherit, by default, from the base class "object"; hence,\n\n class Foo:\n pass\n\nis equivalent to\n\n class Foo(object):\n pass\n\nThe class\'s suite is then executed in a new execution frame (see\n*Naming and binding*), using a newly created local namespace and the\noriginal global namespace. (Usually, the suite contains mostly\nfunction definitions.) When the class\'s suite finishes execution, its\nexecution frame is discarded but its local namespace is saved. [4] A\nclass object is then created using the inheritance list for the base\nclasses and the saved local namespace for the attribute dictionary.\nThe class name is bound to this class object in the original local\nnamespace.\n\nClass creation can be customized heavily using *metaclasses*.\n\nClasses can also be decorated: just like when decorating functions,\n\n @f1(arg)\n @f2\n class Foo: pass\n\nis equivalent to\n\n class Foo: pass\n Foo = f1(arg)(f2(Foo))\n\nThe evaluation rules for the decorator expressions are the same as for\nfunction decorators. The result must be a class object, which is then\nbound to the class name.\n\n**Programmer\'s note:** Variables defined in the class definition are\nclass attributes; they are shared by instances. Instance attributes\ncan be set in a method with "self.name = value". Both class and\ninstance attributes are accessible through the notation ""self.name"",\nand an instance attribute hides a class attribute with the same name\nwhen accessed in this way. Class attributes can be used as defaults\nfor instance attributes, but using mutable values there can lead to\nunexpected results. *Descriptors* can be used to create instance\nvariables with different implementation details.\n\nSee also: **PEP 3115** - Metaclasses in Python 3 **PEP 3129** -\n Class Decorators\n\n\nCoroutines\n==========\n\nNew in version 3.5.\n\n\nCoroutine function definition\n-----------------------------\n\n async_funcdef ::= [decorators] "async" "def" funcname "(" [parameter_list] ")" ["->" expression] ":" suite\n\nExecution of Python coroutines can be suspended and resumed at many\npoints (see *coroutine*). In the body of a coroutine, any "await" and\n"async" identifiers become reserved keywords; "await" expressions,\n"async for" and "async with" can only be used in coroutine bodies.\n\nFunctions defined with "async def" syntax are always coroutine\nfunctions, even if they do not contain "await" or "async" keywords.\n\nIt is a "SyntaxError" to use "yield" expressions in "async def"\ncoroutines.\n\nAn example of a coroutine function:\n\n async def func(param1, param2):\n do_stuff()\n await some_coroutine()\n\n\nThe "async for" statement\n-------------------------\n\n async_for_stmt ::= "async" for_stmt\n\nAn *asynchronous iterable* is able to call asynchronous code in its\n*iter* implementation, and *asynchronous iterator* can call\nasynchronous code in its *next* method.\n\nThe "async for" statement allows convenient iteration over\nasynchronous iterators.\n\nThe following code:\n\n async for TARGET in ITER:\n BLOCK\n else:\n BLOCK2\n\nIs semantically equivalent to:\n\n iter = (ITER)\n iter = await type(iter).__aiter__(iter)\n running = True\n while running:\n try:\n TARGET = await type(iter).__anext__(iter)\n except StopAsyncIteration:\n running = False\n else:\n BLOCK\n else:\n BLOCK2\n\nSee also "__aiter__()" and "__anext__()" for details.\n\nIt is a "SyntaxError" to use "async for" statement outside of an\n"async def" function.\n\n\nThe "async with" statement\n--------------------------\n\n async_with_stmt ::= "async" with_stmt\n\nAn *asynchronous context manager* is a *context manager* that is able\nto suspend execution in its *enter* and *exit* methods.\n\nThe following code:\n\n async with EXPR as VAR:\n BLOCK\n\nIs semantically equivalent to:\n\n mgr = (EXPR)\n aexit = type(mgr).__aexit__\n aenter = type(mgr).__aenter__(mgr)\n exc = True\n\n VAR = await aenter\n try:\n BLOCK\n except:\n if not await aexit(mgr, *sys.exc_info()):\n raise\n else:\n await aexit(mgr, None, None, None)\n\nSee also "__aenter__()" and "__aexit__()" for details.\n\nIt is a "SyntaxError" to use "async with" statement outside of an\n"async def" function.\n\nSee also: **PEP 492** - Coroutines with async and await syntax\n\n-[ Footnotes ]-\n\n[1] The exception is propagated to the invocation stack unless\n there is a "finally" clause which happens to raise another\n exception. That new exception causes the old one to be lost.\n\n[2] Currently, control "flows off the end" except in the case of\n an exception or the execution of a "return", "continue", or\n "break" statement.\n\n[3] A string literal appearing as the first statement in the\n function body is transformed into the function\'s "__doc__"\n attribute and therefore the function\'s *docstring*.\n\n[4] A string literal appearing as the first statement in the class\n body is transformed into the namespace\'s "__doc__" item and\n therefore the class\'s *docstring*.\n',
- 'context-managers': u'\nWith Statement Context Managers\n*******************************\n\nA *context manager* is an object that defines the runtime context to\nbe established when executing a "with" statement. The context manager\nhandles the entry into, and the exit from, the desired runtime context\nfor the execution of the block of code. Context managers are normally\ninvoked using the "with" statement (described in section *The with\nstatement*), but can also be used by directly invoking their methods.\n\nTypical uses of context managers include saving and restoring various\nkinds of global state, locking and unlocking resources, closing opened\nfiles, etc.\n\nFor more information on context managers, see *Context Manager Types*.\n\nobject.__enter__(self)\n\n Enter the runtime context related to this object. The "with"\n statement will bind this method\'s return value to the target(s)\n specified in the "as" clause of the statement, if any.\n\nobject.__exit__(self, exc_type, exc_value, traceback)\n\n Exit the runtime context related to this object. The parameters\n describe the exception that caused the context to be exited. If the\n context was exited without an exception, all three arguments will\n be "None".\n\n If an exception is supplied, and the method wishes to suppress the\n exception (i.e., prevent it from being propagated), it should\n return a true value. Otherwise, the exception will be processed\n normally upon exit from this method.\n\n Note that "__exit__()" methods should not reraise the passed-in\n exception; this is the caller\'s responsibility.\n\nSee also: **PEP 0343** - The "with" statement\n\n The specification, background, and examples for the Python "with"\n statement.\n',
+ 'compound': u'\nCompound statements\n*******************\n\nCompound statements contain (groups of) other statements; they affect\nor control the execution of those other statements in some way. In\ngeneral, compound statements span multiple lines, although in simple\nincarnations a whole compound statement may be contained in one line.\n\nThe "if", "while" and "for" statements implement traditional control\nflow constructs. "try" specifies exception handlers and/or cleanup\ncode for a group of statements, while the "with" statement allows the\nexecution of initialization and finalization code around a block of\ncode. Function and class definitions are also syntactically compound\nstatements.\n\nA compound statement consists of one or more \'clauses.\' A clause\nconsists of a header and a \'suite.\' The clause headers of a\nparticular compound statement are all at the same indentation level.\nEach clause header begins with a uniquely identifying keyword and ends\nwith a colon. A suite is a group of statements controlled by a\nclause. A suite can be one or more semicolon-separated simple\nstatements on the same line as the header, following the header\'s\ncolon, or it can be one or more indented statements on subsequent\nlines. Only the latter form of a suite can contain nested compound\nstatements; the following is illegal, mostly because it wouldn\'t be\nclear to which "if" clause a following "else" clause would belong:\n\n if test1: if test2: print(x)\n\nAlso note that the semicolon binds tighter than the colon in this\ncontext, so that in the following example, either all or none of the\n"print()" calls are executed:\n\n if x < y < z: print(x); print(y); print(z)\n\nSummarizing:\n\n compound_stmt ::= if_stmt\n | while_stmt\n | for_stmt\n | try_stmt\n | with_stmt\n | funcdef\n | classdef\n | async_with_stmt\n | async_for_stmt\n | async_funcdef\n suite ::= stmt_list NEWLINE | NEWLINE INDENT statement+ DEDENT\n statement ::= stmt_list NEWLINE | compound_stmt\n stmt_list ::= simple_stmt (";" simple_stmt)* [";"]\n\nNote that statements always end in a "NEWLINE" possibly followed by a\n"DEDENT". Also note that optional continuation clauses always begin\nwith a keyword that cannot start a statement, thus there are no\nambiguities (the \'dangling "else"\' problem is solved in Python by\nrequiring nested "if" statements to be indented).\n\nThe formatting of the grammar rules in the following sections places\neach clause on a separate line for clarity.\n\n\nThe "if" statement\n==================\n\nThe "if" statement is used for conditional execution:\n\n if_stmt ::= "if" expression ":" suite\n ( "elif" expression ":" suite )*\n ["else" ":" suite]\n\nIt selects exactly one of the suites by evaluating the expressions one\nby one until one is found to be true (see section *Boolean operations*\nfor the definition of true and false); then that suite is executed\n(and no other part of the "if" statement is executed or evaluated).\nIf all expressions are false, the suite of the "else" clause, if\npresent, is executed.\n\n\nThe "while" statement\n=====================\n\nThe "while" statement is used for repeated execution as long as an\nexpression is true:\n\n while_stmt ::= "while" expression ":" suite\n ["else" ":" suite]\n\nThis repeatedly tests the expression and, if it is true, executes the\nfirst suite; if the expression is false (which may be the first time\nit is tested) the suite of the "else" clause, if present, is executed\nand the loop terminates.\n\nA "break" statement executed in the first suite terminates the loop\nwithout executing the "else" clause\'s suite. A "continue" statement\nexecuted in the first suite skips the rest of the suite and goes back\nto testing the expression.\n\n\nThe "for" statement\n===================\n\nThe "for" statement is used to iterate over the elements of a sequence\n(such as a string, tuple or list) or other iterable object:\n\n for_stmt ::= "for" target_list "in" expression_list ":" suite\n ["else" ":" suite]\n\nThe expression list is evaluated once; it should yield an iterable\nobject. An iterator is created for the result of the\n"expression_list". The suite is then executed once for each item\nprovided by the iterator, in the order returned by the iterator. Each\nitem in turn is assigned to the target list using the standard rules\nfor assignments (see *Assignment statements*), and then the suite is\nexecuted. When the items are exhausted (which is immediately when the\nsequence is empty or an iterator raises a "StopIteration" exception),\nthe suite in the "else" clause, if present, is executed, and the loop\nterminates.\n\nA "break" statement executed in the first suite terminates the loop\nwithout executing the "else" clause\'s suite. A "continue" statement\nexecuted in the first suite skips the rest of the suite and continues\nwith the next item, or with the "else" clause if there is no next\nitem.\n\nThe for-loop makes assignments to the variables(s) in the target list.\nThis overwrites all previous assignments to those variables including\nthose made in the suite of the for-loop:\n\n for i in range(10):\n print(i)\n i = 5 # this will not affect the for-loop\n # because i will be overwritten with the next\n # index in the range\n\nNames in the target list are not deleted when the loop is finished,\nbut if the sequence is empty, they will not have been assigned to at\nall by the loop. Hint: the built-in function "range()" returns an\niterator of integers suitable to emulate the effect of Pascal\'s "for i\n:= a to b do"; e.g., "list(range(3))" returns the list "[0, 1, 2]".\n\nNote: There is a subtlety when the sequence is being modified by the\n loop (this can only occur for mutable sequences, i.e. lists). An\n internal counter is used to keep track of which item is used next,\n and this is incremented on each iteration. When this counter has\n reached the length of the sequence the loop terminates. This means\n that if the suite deletes the current (or a previous) item from the\n sequence, the next item will be skipped (since it gets the index of\n the current item which has already been treated). Likewise, if the\n suite inserts an item in the sequence before the current item, the\n current item will be treated again the next time through the loop.\n This can lead to nasty bugs that can be avoided by making a\n temporary copy using a slice of the whole sequence, e.g.,\n\n for x in a[:]:\n if x < 0: a.remove(x)\n\n\nThe "try" statement\n===================\n\nThe "try" statement specifies exception handlers and/or cleanup code\nfor a group of statements:\n\n try_stmt ::= try1_stmt | try2_stmt\n try1_stmt ::= "try" ":" suite\n ("except" [expression ["as" identifier]] ":" suite)+\n ["else" ":" suite]\n ["finally" ":" suite]\n try2_stmt ::= "try" ":" suite\n "finally" ":" suite\n\nThe "except" clause(s) specify one or more exception handlers. When no\nexception occurs in the "try" clause, no exception handler is\nexecuted. When an exception occurs in the "try" suite, a search for an\nexception handler is started. This search inspects the except clauses\nin turn until one is found that matches the exception. An expression-\nless except clause, if present, must be last; it matches any\nexception. For an except clause with an expression, that expression\nis evaluated, and the clause matches the exception if the resulting\nobject is "compatible" with the exception. An object is compatible\nwith an exception if it is the class or a base class of the exception\nobject or a tuple containing an item compatible with the exception.\n\nIf no except clause matches the exception, the search for an exception\nhandler continues in the surrounding code and on the invocation stack.\n[1]\n\nIf the evaluation of an expression in the header of an except clause\nraises an exception, the original search for a handler is canceled and\na search starts for the new exception in the surrounding code and on\nthe call stack (it is treated as if the entire "try" statement raised\nthe exception).\n\nWhen a matching except clause is found, the exception is assigned to\nthe target specified after the "as" keyword in that except clause, if\npresent, and the except clause\'s suite is executed. All except\nclauses must have an executable block. When the end of this block is\nreached, execution continues normally after the entire try statement.\n(This means that if two nested handlers exist for the same exception,\nand the exception occurs in the try clause of the inner handler, the\nouter handler will not handle the exception.)\n\nWhen an exception has been assigned using "as target", it is cleared\nat the end of the except clause. This is as if\n\n except E as N:\n foo\n\nwas translated to\n\n except E as N:\n try:\n foo\n finally:\n del N\n\nThis means the exception must be assigned to a different name to be\nable to refer to it after the except clause. Exceptions are cleared\nbecause with the traceback attached to them, they form a reference\ncycle with the stack frame, keeping all locals in that frame alive\nuntil the next garbage collection occurs.\n\nBefore an except clause\'s suite is executed, details about the\nexception are stored in the "sys" module and can be accessed via\n"sys.exc_info()". "sys.exc_info()" returns a 3-tuple consisting of the\nexception class, the exception instance and a traceback object (see\nsection *The standard type hierarchy*) identifying the point in the\nprogram where the exception occurred. "sys.exc_info()" values are\nrestored to their previous values (before the call) when returning\nfrom a function that handled an exception.\n\nThe optional "else" clause is executed if and when control flows off\nthe end of the "try" clause. [2] Exceptions in the "else" clause are\nnot handled by the preceding "except" clauses.\n\nIf "finally" is present, it specifies a \'cleanup\' handler. The "try"\nclause is executed, including any "except" and "else" clauses. If an\nexception occurs in any of the clauses and is not handled, the\nexception is temporarily saved. The "finally" clause is executed. If\nthere is a saved exception it is re-raised at the end of the "finally"\nclause. If the "finally" clause raises another exception, the saved\nexception is set as the context of the new exception. If the "finally"\nclause executes a "return" or "break" statement, the saved exception\nis discarded:\n\n >>> def f():\n ... try:\n ... 1/0\n ... finally:\n ... return 42\n ...\n >>> f()\n 42\n\nThe exception information is not available to the program during\nexecution of the "finally" clause.\n\nWhen a "return", "break" or "continue" statement is executed in the\n"try" suite of a "try"..."finally" statement, the "finally" clause is\nalso executed \'on the way out.\' A "continue" statement is illegal in\nthe "finally" clause. (The reason is a problem with the current\nimplementation --- this restriction may be lifted in the future).\n\nThe return value of a function is determined by the last "return"\nstatement executed. Since the "finally" clause always executes, a\n"return" statement executed in the "finally" clause will always be the\nlast one executed:\n\n >>> def foo():\n ... try:\n ... return \'try\'\n ... finally:\n ... return \'finally\'\n ...\n >>> foo()\n \'finally\'\n\nAdditional information on exceptions can be found in section\n*Exceptions*, and information on using the "raise" statement to\ngenerate exceptions may be found in section *The raise statement*.\n\n\nThe "with" statement\n====================\n\nThe "with" statement is used to wrap the execution of a block with\nmethods defined by a context manager (see section *With Statement\nContext Managers*). This allows common "try"..."except"..."finally"\nusage patterns to be encapsulated for convenient reuse.\n\n with_stmt ::= "with" with_item ("," with_item)* ":" suite\n with_item ::= expression ["as" target]\n\nThe execution of the "with" statement with one "item" proceeds as\nfollows:\n\n1. The context expression (the expression given in the "with_item")\n is evaluated to obtain a context manager.\n\n2. The context manager\'s "__exit__()" is loaded for later use.\n\n3. The context manager\'s "__enter__()" method is invoked.\n\n4. If a target was included in the "with" statement, the return\n value from "__enter__()" is assigned to it.\n\n Note: The "with" statement guarantees that if the "__enter__()"\n method returns without an error, then "__exit__()" will always be\n called. Thus, if an error occurs during the assignment to the\n target list, it will be treated the same as an error occurring\n within the suite would be. See step 6 below.\n\n5. The suite is executed.\n\n6. The context manager\'s "__exit__()" method is invoked. If an\n exception caused the suite to be exited, its type, value, and\n traceback are passed as arguments to "__exit__()". Otherwise, three\n "None" arguments are supplied.\n\n If the suite was exited due to an exception, and the return value\n from the "__exit__()" method was false, the exception is reraised.\n If the return value was true, the exception is suppressed, and\n execution continues with the statement following the "with"\n statement.\n\n If the suite was exited for any reason other than an exception, the\n return value from "__exit__()" is ignored, and execution proceeds\n at the normal location for the kind of exit that was taken.\n\nWith more than one item, the context managers are processed as if\nmultiple "with" statements were nested:\n\n with A() as a, B() as b:\n suite\n\nis equivalent to\n\n with A() as a:\n with B() as b:\n suite\n\nChanged in version 3.1: Support for multiple context expressions.\n\nSee also: **PEP 343** - The "with" statement\n\n The specification, background, and examples for the Python "with"\n statement.\n\n\nFunction definitions\n====================\n\nA function definition defines a user-defined function object (see\nsection *The standard type hierarchy*):\n\n funcdef ::= [decorators] "def" funcname "(" [parameter_list] ")" ["->" expression] ":" suite\n decorators ::= decorator+\n decorator ::= "@" dotted_name ["(" [argument_list [","]] ")"] NEWLINE\n dotted_name ::= identifier ("." identifier)*\n parameter_list ::= (defparameter ",")*\n | "*" [parameter] ("," defparameter)* ["," "**" parameter]\n | "**" parameter\n | defparameter [","] )\n parameter ::= identifier [":" expression]\n defparameter ::= parameter ["=" expression]\n funcname ::= identifier\n\nA function definition is an executable statement. Its execution binds\nthe function name in the current local namespace to a function object\n(a wrapper around the executable code for the function). This\nfunction object contains a reference to the current global namespace\nas the global namespace to be used when the function is called.\n\nThe function definition does not execute the function body; this gets\nexecuted only when the function is called. [3]\n\nA function definition may be wrapped by one or more *decorator*\nexpressions. Decorator expressions are evaluated when the function is\ndefined, in the scope that contains the function definition. The\nresult must be a callable, which is invoked with the function object\nas the only argument. The returned value is bound to the function name\ninstead of the function object. Multiple decorators are applied in\nnested fashion. For example, the following code\n\n @f1(arg)\n @f2\n def func(): pass\n\nis equivalent to\n\n def func(): pass\n func = f1(arg)(f2(func))\n\nWhen one or more *parameters* have the form *parameter* "="\n*expression*, the function is said to have "default parameter values."\nFor a parameter with a default value, the corresponding *argument* may\nbe omitted from a call, in which case the parameter\'s default value is\nsubstituted. If a parameter has a default value, all following\nparameters up until the ""*"" must also have a default value --- this\nis a syntactic restriction that is not expressed by the grammar.\n\n**Default parameter values are evaluated from left to right when the\nfunction definition is executed.** This means that the expression is\nevaluated once, when the function is defined, and that the same "pre-\ncomputed" value is used for each call. This is especially important\nto understand when a default parameter is a mutable object, such as a\nlist or a dictionary: if the function modifies the object (e.g. by\nappending an item to a list), the default value is in effect modified.\nThis is generally not what was intended. A way around this is to use\n"None" as the default, and explicitly test for it in the body of the\nfunction, e.g.:\n\n def whats_on_the_telly(penguin=None):\n if penguin is None:\n penguin = []\n penguin.append("property of the zoo")\n return penguin\n\nFunction call semantics are described in more detail in section\n*Calls*. A function call always assigns values to all parameters\nmentioned in the parameter list, either from position arguments, from\nkeyword arguments, or from default values. If the form\n""*identifier"" is present, it is initialized to a tuple receiving any\nexcess positional parameters, defaulting to the empty tuple. If the\nform ""**identifier"" is present, it is initialized to a new\ndictionary receiving any excess keyword arguments, defaulting to a new\nempty dictionary. Parameters after ""*"" or ""*identifier"" are\nkeyword-only parameters and may only be passed used keyword arguments.\n\nParameters may have annotations of the form "": expression"" following\nthe parameter name. Any parameter may have an annotation even those\nof the form "*identifier" or "**identifier". Functions may have\n"return" annotation of the form ""-> expression"" after the parameter\nlist. These annotations can be any valid Python expression and are\nevaluated when the function definition is executed. Annotations may\nbe evaluated in a different order than they appear in the source code.\nThe presence of annotations does not change the semantics of a\nfunction. The annotation values are available as values of a\ndictionary keyed by the parameters\' names in the "__annotations__"\nattribute of the function object.\n\nIt is also possible to create anonymous functions (functions not bound\nto a name), for immediate use in expressions. This uses lambda\nexpressions, described in section *Lambdas*. Note that the lambda\nexpression is merely a shorthand for a simplified function definition;\na function defined in a ""def"" statement can be passed around or\nassigned to another name just like a function defined by a lambda\nexpression. The ""def"" form is actually more powerful since it\nallows the execution of multiple statements and annotations.\n\n**Programmer\'s note:** Functions are first-class objects. A ""def""\nstatement executed inside a function definition defines a local\nfunction that can be returned or passed around. Free variables used\nin the nested function can access the local variables of the function\ncontaining the def. See section *Naming and binding* for details.\n\nSee also: **PEP 3107** - Function Annotations\n\n The original specification for function annotations.\n\n\nClass definitions\n=================\n\nA class definition defines a class object (see section *The standard\ntype hierarchy*):\n\n classdef ::= [decorators] "class" classname [inheritance] ":" suite\n inheritance ::= "(" [argument_list] ")"\n classname ::= identifier\n\nA class definition is an executable statement. The inheritance list\nusually gives a list of base classes (see *Customizing class creation*\nfor more advanced uses), so each item in the list should evaluate to a\nclass object which allows subclassing. Classes without an inheritance\nlist inherit, by default, from the base class "object"; hence,\n\n class Foo:\n pass\n\nis equivalent to\n\n class Foo(object):\n pass\n\nThe class\'s suite is then executed in a new execution frame (see\n*Naming and binding*), using a newly created local namespace and the\noriginal global namespace. (Usually, the suite contains mostly\nfunction definitions.) When the class\'s suite finishes execution, its\nexecution frame is discarded but its local namespace is saved. [4] A\nclass object is then created using the inheritance list for the base\nclasses and the saved local namespace for the attribute dictionary.\nThe class name is bound to this class object in the original local\nnamespace.\n\nClass creation can be customized heavily using *metaclasses*.\n\nClasses can also be decorated: just like when decorating functions,\n\n @f1(arg)\n @f2\n class Foo: pass\n\nis equivalent to\n\n class Foo: pass\n Foo = f1(arg)(f2(Foo))\n\nThe evaluation rules for the decorator expressions are the same as for\nfunction decorators. The result must be a class object, which is then\nbound to the class name.\n\n**Programmer\'s note:** Variables defined in the class definition are\nclass attributes; they are shared by instances. Instance attributes\ncan be set in a method with "self.name = value". Both class and\ninstance attributes are accessible through the notation ""self.name"",\nand an instance attribute hides a class attribute with the same name\nwhen accessed in this way. Class attributes can be used as defaults\nfor instance attributes, but using mutable values there can lead to\nunexpected results. *Descriptors* can be used to create instance\nvariables with different implementation details.\n\nSee also: **PEP 3115** - Metaclasses in Python 3 **PEP 3129** -\n Class Decorators\n\n\nCoroutines\n==========\n\nNew in version 3.5.\n\n\nCoroutine function definition\n-----------------------------\n\n async_funcdef ::= [decorators] "async" "def" funcname "(" [parameter_list] ")" ["->" expression] ":" suite\n\nExecution of Python coroutines can be suspended and resumed at many\npoints (see *coroutine*). In the body of a coroutine, any "await" and\n"async" identifiers become reserved keywords; "await" expressions,\n"async for" and "async with" can only be used in coroutine bodies.\n\nFunctions defined with "async def" syntax are always coroutine\nfunctions, even if they do not contain "await" or "async" keywords.\n\nIt is a "SyntaxError" to use "yield" expressions in "async def"\ncoroutines.\n\nAn example of a coroutine function:\n\n async def func(param1, param2):\n do_stuff()\n await some_coroutine()\n\n\nThe "async for" statement\n-------------------------\n\n async_for_stmt ::= "async" for_stmt\n\nAn *asynchronous iterable* is able to call asynchronous code in its\n*iter* implementation, and *asynchronous iterator* can call\nasynchronous code in its *next* method.\n\nThe "async for" statement allows convenient iteration over\nasynchronous iterators.\n\nThe following code:\n\n async for TARGET in ITER:\n BLOCK\n else:\n BLOCK2\n\nIs semantically equivalent to:\n\n iter = (ITER)\n iter = type(iter).__aiter__(iter)\n running = True\n while running:\n try:\n TARGET = await type(iter).__anext__(iter)\n except StopAsyncIteration:\n running = False\n else:\n BLOCK\n else:\n BLOCK2\n\nSee also "__aiter__()" and "__anext__()" for details.\n\nIt is a "SyntaxError" to use "async for" statement outside of an\n"async def" function.\n\n\nThe "async with" statement\n--------------------------\n\n async_with_stmt ::= "async" with_stmt\n\nAn *asynchronous context manager* is a *context manager* that is able\nto suspend execution in its *enter* and *exit* methods.\n\nThe following code:\n\n async with EXPR as VAR:\n BLOCK\n\nIs semantically equivalent to:\n\n mgr = (EXPR)\n aexit = type(mgr).__aexit__\n aenter = type(mgr).__aenter__(mgr)\n exc = True\n\n VAR = await aenter\n try:\n BLOCK\n except:\n if not await aexit(mgr, *sys.exc_info()):\n raise\n else:\n await aexit(mgr, None, None, None)\n\nSee also "__aenter__()" and "__aexit__()" for details.\n\nIt is a "SyntaxError" to use "async with" statement outside of an\n"async def" function.\n\nSee also: **PEP 492** - Coroutines with async and await syntax\n\n-[ Footnotes ]-\n\n[1] The exception is propagated to the invocation stack unless\n there is a "finally" clause which happens to raise another\n exception. That new exception causes the old one to be lost.\n\n[2] Currently, control "flows off the end" except in the case of\n an exception or the execution of a "return", "continue", or\n "break" statement.\n\n[3] A string literal appearing as the first statement in the\n function body is transformed into the function\'s "__doc__"\n attribute and therefore the function\'s *docstring*.\n\n[4] A string literal appearing as the first statement in the class\n body is transformed into the namespace\'s "__doc__" item and\n therefore the class\'s *docstring*.\n',
+ 'context-managers': u'\nWith Statement Context Managers\n*******************************\n\nA *context manager* is an object that defines the runtime context to\nbe established when executing a "with" statement. The context manager\nhandles the entry into, and the exit from, the desired runtime context\nfor the execution of the block of code. Context managers are normally\ninvoked using the "with" statement (described in section *The with\nstatement*), but can also be used by directly invoking their methods.\n\nTypical uses of context managers include saving and restoring various\nkinds of global state, locking and unlocking resources, closing opened\nfiles, etc.\n\nFor more information on context managers, see *Context Manager Types*.\n\nobject.__enter__(self)\n\n Enter the runtime context related to this object. The "with"\n statement will bind this method\'s return value to the target(s)\n specified in the "as" clause of the statement, if any.\n\nobject.__exit__(self, exc_type, exc_value, traceback)\n\n Exit the runtime context related to this object. The parameters\n describe the exception that caused the context to be exited. If the\n context was exited without an exception, all three arguments will\n be "None".\n\n If an exception is supplied, and the method wishes to suppress the\n exception (i.e., prevent it from being propagated), it should\n return a true value. Otherwise, the exception will be processed\n normally upon exit from this method.\n\n Note that "__exit__()" methods should not reraise the passed-in\n exception; this is the caller\'s responsibility.\n\nSee also: **PEP 343** - The "with" statement\n\n The specification, background, and examples for the Python "with"\n statement.\n',
'continue': u'\nThe "continue" statement\n************************\n\n continue_stmt ::= "continue"\n\n"continue" may only occur syntactically nested in a "for" or "while"\nloop, but not nested in a function or class definition or "finally"\nclause within that loop. It continues with the next cycle of the\nnearest enclosing loop.\n\nWhen "continue" passes control out of a "try" statement with a\n"finally" clause, that "finally" clause is executed before really\nstarting the next loop cycle.\n',
'conversions': u'\nArithmetic conversions\n**********************\n\nWhen a description of an arithmetic operator below uses the phrase\n"the numeric arguments are converted to a common type," this means\nthat the operator implementation for built-in types works as follows:\n\n* If either argument is a complex number, the other is converted to\n complex;\n\n* otherwise, if either argument is a floating point number, the\n other is converted to floating point;\n\n* otherwise, both must be integers and no conversion is necessary.\n\nSome additional rules apply for certain operators (e.g., a string as a\nleft argument to the \'%\' operator). Extensions must define their own\nconversion behavior.\n',
'customization': u'\nBasic customization\n*******************\n\nobject.__new__(cls[, ...])\n\n Called to create a new instance of class *cls*. "__new__()" is a\n static method (special-cased so you need not declare it as such)\n that takes the class of which an instance was requested as its\n first argument. The remaining arguments are those passed to the\n object constructor expression (the call to the class). The return\n value of "__new__()" should be the new object instance (usually an\n instance of *cls*).\n\n Typical implementations create a new instance of the class by\n invoking the superclass\'s "__new__()" method using\n "super(currentclass, cls).__new__(cls[, ...])" with appropriate\n arguments and then modifying the newly-created instance as\n necessary before returning it.\n\n If "__new__()" returns an instance of *cls*, then the new\n instance\'s "__init__()" method will be invoked like\n "__init__(self[, ...])", where *self* is the new instance and the\n remaining arguments are the same as were passed to "__new__()".\n\n If "__new__()" does not return an instance of *cls*, then the new\n instance\'s "__init__()" method will not be invoked.\n\n "__new__()" is intended mainly to allow subclasses of immutable\n types (like int, str, or tuple) to customize instance creation. It\n is also commonly overridden in custom metaclasses in order to\n customize class creation.\n\nobject.__init__(self[, ...])\n\n Called after the instance has been created (by "__new__()"), but\n before it is returned to the caller. The arguments are those\n passed to the class constructor expression. If a base class has an\n "__init__()" method, the derived class\'s "__init__()" method, if\n any, must explicitly call it to ensure proper initialization of the\n base class part of the instance; for example:\n "BaseClass.__init__(self, [args...])".\n\n Because "__new__()" and "__init__()" work together in constructing\n objects ("__new__()" to create it, and "__init__()" to customise\n it), no non-"None" value may be returned by "__init__()"; doing so\n will cause a "TypeError" to be raised at runtime.\n\nobject.__del__(self)\n\n Called when the instance is about to be destroyed. This is also\n called a destructor. If a base class has a "__del__()" method, the\n derived class\'s "__del__()" method, if any, must explicitly call it\n to ensure proper deletion of the base class part of the instance.\n Note that it is possible (though not recommended!) for the\n "__del__()" method to postpone destruction of the instance by\n creating a new reference to it. It may then be called at a later\n time when this new reference is deleted. It is not guaranteed that\n "__del__()" methods are called for objects that still exist when\n the interpreter exits.\n\n Note: "del x" doesn\'t directly call "x.__del__()" --- the former\n decrements the reference count for "x" by one, and the latter is\n only called when "x"\'s reference count reaches zero. Some common\n situations that may prevent the reference count of an object from\n going to zero include: circular references between objects (e.g.,\n a doubly-linked list or a tree data structure with parent and\n child pointers); a reference to the object on the stack frame of\n a function that caught an exception (the traceback stored in\n "sys.exc_info()[2]" keeps the stack frame alive); or a reference\n to the object on the stack frame that raised an unhandled\n exception in interactive mode (the traceback stored in\n "sys.last_traceback" keeps the stack frame alive). The first\n situation can only be remedied by explicitly breaking the cycles;\n the second can be resolved by freeing the reference to the\n traceback object when it is no longer useful, and the third can\n be resolved by storing "None" in "sys.last_traceback". Circular\n references which are garbage are detected and cleaned up when the\n cyclic garbage collector is enabled (it\'s on by default). Refer\n to the documentation for the "gc" module for more information\n about this topic.\n\n Warning: Due to the precarious circumstances under which\n "__del__()" methods are invoked, exceptions that occur during\n their execution are ignored, and a warning is printed to\n "sys.stderr" instead. Also, when "__del__()" is invoked in\n response to a module being deleted (e.g., when execution of the\n program is done), other globals referenced by the "__del__()"\n method may already have been deleted or in the process of being\n torn down (e.g. the import machinery shutting down). For this\n reason, "__del__()" methods should do the absolute minimum needed\n to maintain external invariants. Starting with version 1.5,\n Python guarantees that globals whose name begins with a single\n underscore are deleted from their module before other globals are\n deleted; if no other references to such globals exist, this may\n help in assuring that imported modules are still available at the\n time when the "__del__()" method is called.\n\nobject.__repr__(self)\n\n Called by the "repr()" built-in function to compute the "official"\n string representation of an object. If at all possible, this\n should look like a valid Python expression that could be used to\n recreate an object with the same value (given an appropriate\n environment). If this is not possible, a string of the form\n "<...some useful description...>" should be returned. The return\n value must be a string object. If a class defines "__repr__()" but\n not "__str__()", then "__repr__()" is also used when an "informal"\n string representation of instances of that class is required.\n\n This is typically used for debugging, so it is important that the\n representation is information-rich and unambiguous.\n\nobject.__str__(self)\n\n Called by "str(object)" and the built-in functions "format()" and\n "print()" to compute the "informal" or nicely printable string\n representation of an object. The return value must be a *string*\n object.\n\n This method differs from "object.__repr__()" in that there is no\n expectation that "__str__()" return a valid Python expression: a\n more convenient or concise representation can be used.\n\n The default implementation defined by the built-in type "object"\n calls "object.__repr__()".\n\nobject.__bytes__(self)\n\n Called by "bytes()" to compute a byte-string representation of an\n object. This should return a "bytes" object.\n\nobject.__format__(self, format_spec)\n\n Called by the "format()" built-in function (and by extension, the\n "str.format()" method of class "str") to produce a "formatted"\n string representation of an object. The "format_spec" argument is a\n string that contains a description of the formatting options\n desired. The interpretation of the "format_spec" argument is up to\n the type implementing "__format__()", however most classes will\n either delegate formatting to one of the built-in types, or use a\n similar formatting option syntax.\n\n See *Format Specification Mini-Language* for a description of the\n standard formatting syntax.\n\n The return value must be a string object.\n\n Changed in version 3.4: The __format__ method of "object" itself\n raises a "TypeError" if passed any non-empty string.\n\nobject.__lt__(self, other)\nobject.__le__(self, other)\nobject.__eq__(self, other)\nobject.__ne__(self, other)\nobject.__gt__(self, other)\nobject.__ge__(self, other)\n\n These are the so-called "rich comparison" methods. The\n correspondence between operator symbols and method names is as\n follows: "x<y" calls "x.__lt__(y)", "x<=y" calls "x.__le__(y)",\n "x==y" calls "x.__eq__(y)", "x!=y" calls "x.__ne__(y)", "x>y" calls\n "x.__gt__(y)", and "x>=y" calls "x.__ge__(y)".\n\n A rich comparison method may return the singleton "NotImplemented"\n if it does not implement the operation for a given pair of\n arguments. By convention, "False" and "True" are returned for a\n successful comparison. However, these methods can return any value,\n so if the comparison operator is used in a Boolean context (e.g.,\n in the condition of an "if" statement), Python will call "bool()"\n on the value to determine if the result is true or false.\n\n By default, "__ne__()" delegates to "__eq__()" and inverts the\n result unless it is "NotImplemented". There are no other implied\n relationships among the comparison operators, for example, the\n truth of "(x<y or x==y)" does not imply "x<=y". To automatically\n generate ordering operations from a single root operation, see\n "functools.total_ordering()".\n\n See the paragraph on "__hash__()" for some important notes on\n creating *hashable* objects which support custom comparison\n operations and are usable as dictionary keys.\n\n There are no swapped-argument versions of these methods (to be used\n when the left argument does not support the operation but the right\n argument does); rather, "__lt__()" and "__gt__()" are each other\'s\n reflection, "__le__()" and "__ge__()" are each other\'s reflection,\n and "__eq__()" and "__ne__()" are their own reflection. If the\n operands are of different types, and right operand\'s type is a\n direct or indirect subclass of the left operand\'s type, the\n reflected method of the right operand has priority, otherwise the\n left operand\'s method has priority. Virtual subclassing is not\n considered.\n\nobject.__hash__(self)\n\n Called by built-in function "hash()" and for operations on members\n of hashed collections including "set", "frozenset", and "dict".\n "__hash__()" should return an integer. The only required property\n is that objects which compare equal have the same hash value; it is\n advised to somehow mix together (e.g. using exclusive or) the hash\n values for the components of the object that also play a part in\n comparison of objects.\n\n Note: "hash()" truncates the value returned from an object\'s\n custom "__hash__()" method to the size of a "Py_ssize_t". This\n is typically 8 bytes on 64-bit builds and 4 bytes on 32-bit\n builds. If an object\'s "__hash__()" must interoperate on builds\n of different bit sizes, be sure to check the width on all\n supported builds. An easy way to do this is with "python -c\n "import sys; print(sys.hash_info.width)"".\n\n If a class does not define an "__eq__()" method it should not\n define a "__hash__()" operation either; if it defines "__eq__()"\n but not "__hash__()", its instances will not be usable as items in\n hashable collections. If a class defines mutable objects and\n implements an "__eq__()" method, it should not implement\n "__hash__()", since the implementation of hashable collections\n requires that a key\'s hash value is immutable (if the object\'s hash\n value changes, it will be in the wrong hash bucket).\n\n User-defined classes have "__eq__()" and "__hash__()" methods by\n default; with them, all objects compare unequal (except with\n themselves) and "x.__hash__()" returns an appropriate value such\n that "x == y" implies both that "x is y" and "hash(x) == hash(y)".\n\n A class that overrides "__eq__()" and does not define "__hash__()"\n will have its "__hash__()" implicitly set to "None". When the\n "__hash__()" method of a class is "None", instances of the class\n will raise an appropriate "TypeError" when a program attempts to\n retrieve their hash value, and will also be correctly identified as\n unhashable when checking "isinstance(obj, collections.Hashable)".\n\n If a class that overrides "__eq__()" needs to retain the\n implementation of "__hash__()" from a parent class, the interpreter\n must be told this explicitly by setting "__hash__ =\n <ParentClass>.__hash__".\n\n If a class that does not override "__eq__()" wishes to suppress\n hash support, it should include "__hash__ = None" in the class\n definition. A class which defines its own "__hash__()" that\n explicitly raises a "TypeError" would be incorrectly identified as\n hashable by an "isinstance(obj, collections.Hashable)" call.\n\n Note: By default, the "__hash__()" values of str, bytes and\n datetime objects are "salted" with an unpredictable random value.\n Although they remain constant within an individual Python\n process, they are not predictable between repeated invocations of\n Python.This is intended to provide protection against a denial-\n of-service caused by carefully-chosen inputs that exploit the\n worst case performance of a dict insertion, O(n^2) complexity.\n See http://www.ocert.org/advisories/ocert-2011-003.html for\n details.Changing hash values affects the iteration order of\n dicts, sets and other mappings. Python has never made guarantees\n about this ordering (and it typically varies between 32-bit and\n 64-bit builds).See also "PYTHONHASHSEED".\n\n Changed in version 3.3: Hash randomization is enabled by default.\n\nobject.__bool__(self)\n\n Called to implement truth value testing and the built-in operation\n "bool()"; should return "False" or "True". When this method is not\n defined, "__len__()" is called, if it is defined, and the object is\n considered true if its result is nonzero. If a class defines\n neither "__len__()" nor "__bool__()", all its instances are\n considered true.\n',
'debugger': u'\n"pdb" --- The Python Debugger\n*****************************\n\n**Source code:** Lib/pdb.py\n\n======================================================================\n\nThe module "pdb" defines an interactive source code debugger for\nPython programs. It supports setting (conditional) breakpoints and\nsingle stepping at the source line level, inspection of stack frames,\nsource code listing, and evaluation of arbitrary Python code in the\ncontext of any stack frame. It also supports post-mortem debugging\nand can be called under program control.\n\nThe debugger is extensible -- it is actually defined as the class\n"Pdb". This is currently undocumented but easily understood by reading\nthe source. The extension interface uses the modules "bdb" and "cmd".\n\nThe debugger\'s prompt is "(Pdb)". Typical usage to run a program under\ncontrol of the debugger is:\n\n >>> import pdb\n >>> import mymodule\n >>> pdb.run(\'mymodule.test()\')\n > <string>(0)?()\n (Pdb) continue\n > <string>(1)?()\n (Pdb) continue\n NameError: \'spam\'\n > <string>(1)?()\n (Pdb)\n\nChanged in version 3.3: Tab-completion via the "readline" module is\navailable for commands and command arguments, e.g. the current global\nand local names are offered as arguments of the "p" command.\n\n"pdb.py" can also be invoked as a script to debug other scripts. For\nexample:\n\n python3 -m pdb myscript.py\n\nWhen invoked as a script, pdb will automatically enter post-mortem\ndebugging if the program being debugged exits abnormally. After post-\nmortem debugging (or after normal exit of the program), pdb will\nrestart the program. Automatic restarting preserves pdb\'s state (such\nas breakpoints) and in most cases is more useful than quitting the\ndebugger upon program\'s exit.\n\nNew in version 3.2: "pdb.py" now accepts a "-c" option that executes\ncommands as if given in a ".pdbrc" file, see *Debugger Commands*.\n\nThe typical usage to break into the debugger from a running program is\nto insert\n\n import pdb; pdb.set_trace()\n\nat the location you want to break into the debugger. You can then\nstep through the code following this statement, and continue running\nwithout the debugger using the "continue" command.\n\nThe typical usage to inspect a crashed program is:\n\n >>> import pdb\n >>> import mymodule\n >>> mymodule.test()\n Traceback (most recent call last):\n File "<stdin>", line 1, in ?\n File "./mymodule.py", line 4, in test\n test2()\n File "./mymodule.py", line 3, in test2\n print(spam)\n NameError: spam\n >>> pdb.pm()\n > ./mymodule.py(3)test2()\n -> print(spam)\n (Pdb)\n\nThe module defines the following functions; each enters the debugger\nin a slightly different way:\n\npdb.run(statement, globals=None, locals=None)\n\n Execute the *statement* (given as a string or a code object) under\n debugger control. The debugger prompt appears before any code is\n executed; you can set breakpoints and type "continue", or you can\n step through the statement using "step" or "next" (all these\n commands are explained below). The optional *globals* and *locals*\n arguments specify the environment in which the code is executed; by\n default the dictionary of the module "__main__" is used. (See the\n explanation of the built-in "exec()" or "eval()" functions.)\n\npdb.runeval(expression, globals=None, locals=None)\n\n Evaluate the *expression* (given as a string or a code object)\n under debugger control. When "runeval()" returns, it returns the\n value of the expression. Otherwise this function is similar to\n "run()".\n\npdb.runcall(function, *args, **kwds)\n\n Call the *function* (a function or method object, not a string)\n with the given arguments. When "runcall()" returns, it returns\n whatever the function call returned. The debugger prompt appears\n as soon as the function is entered.\n\npdb.set_trace()\n\n Enter the debugger at the calling stack frame. This is useful to\n hard-code a breakpoint at a given point in a program, even if the\n code is not otherwise being debugged (e.g. when an assertion\n fails).\n\npdb.post_mortem(traceback=None)\n\n Enter post-mortem debugging of the given *traceback* object. If no\n *traceback* is given, it uses the one of the exception that is\n currently being handled (an exception must be being handled if the\n default is to be used).\n\npdb.pm()\n\n Enter post-mortem debugging of the traceback found in\n "sys.last_traceback".\n\nThe "run*" functions and "set_trace()" are aliases for instantiating\nthe "Pdb" class and calling the method of the same name. If you want\nto access further features, you have to do this yourself:\n\nclass class pdb.Pdb(completekey=\'tab\', stdin=None, stdout=None, skip=None, nosigint=False)\n\n "Pdb" is the debugger class.\n\n The *completekey*, *stdin* and *stdout* arguments are passed to the\n underlying "cmd.Cmd" class; see the description there.\n\n The *skip* argument, if given, must be an iterable of glob-style\n module name patterns. The debugger will not step into frames that\n originate in a module that matches one of these patterns. [1]\n\n By default, Pdb sets a handler for the SIGINT signal (which is sent\n when the user presses "Ctrl-C" on the console) when you give a\n "continue" command. This allows you to break into the debugger\n again by pressing "Ctrl-C". If you want Pdb not to touch the\n SIGINT handler, set *nosigint* tot true.\n\n Example call to enable tracing with *skip*:\n\n import pdb; pdb.Pdb(skip=[\'django.*\']).set_trace()\n\n New in version 3.1: The *skip* argument.\n\n New in version 3.2: The *nosigint* argument. Previously, a SIGINT\n handler was never set by Pdb.\n\n run(statement, globals=None, locals=None)\n runeval(expression, globals=None, locals=None)\n runcall(function, *args, **kwds)\n set_trace()\n\n See the documentation for the functions explained above.\n\n\nDebugger Commands\n=================\n\nThe commands recognized by the debugger are listed below. Most\ncommands can be abbreviated to one or two letters as indicated; e.g.\n"h(elp)" means that either "h" or "help" can be used to enter the help\ncommand (but not "he" or "hel", nor "H" or "Help" or "HELP").\nArguments to commands must be separated by whitespace (spaces or\ntabs). Optional arguments are enclosed in square brackets ("[]") in\nthe command syntax; the square brackets must not be typed.\nAlternatives in the command syntax are separated by a vertical bar\n("|").\n\nEntering a blank line repeats the last command entered. Exception: if\nthe last command was a "list" command, the next 11 lines are listed.\n\nCommands that the debugger doesn\'t recognize are assumed to be Python\nstatements and are executed in the context of the program being\ndebugged. Python statements can also be prefixed with an exclamation\npoint ("!"). This is a powerful way to inspect the program being\ndebugged; it is even possible to change a variable or call a function.\nWhen an exception occurs in such a statement, the exception name is\nprinted but the debugger\'s state is not changed.\n\nThe debugger supports *aliases*. Aliases can have parameters which\nallows one a certain level of adaptability to the context under\nexamination.\n\nMultiple commands may be entered on a single line, separated by ";;".\n(A single ";" is not used as it is the separator for multiple commands\nin a line that is passed to the Python parser.) No intelligence is\napplied to separating the commands; the input is split at the first\n";;" pair, even if it is in the middle of a quoted string.\n\nIf a file ".pdbrc" exists in the user\'s home directory or in the\ncurrent directory, it is read in and executed as if it had been typed\nat the debugger prompt. This is particularly useful for aliases. If\nboth files exist, the one in the home directory is read first and\naliases defined there can be overridden by the local file.\n\nChanged in version 3.2: ".pdbrc" can now contain commands that\ncontinue debugging, such as "continue" or "next". Previously, these\ncommands had no effect.\n\nh(elp) [command]\n\n Without argument, print the list of available commands. With a\n *command* as argument, print help about that command. "help pdb"\n displays the full documentation (the docstring of the "pdb"\n module). Since the *command* argument must be an identifier, "help\n exec" must be entered to get help on the "!" command.\n\nw(here)\n\n Print a stack trace, with the most recent frame at the bottom. An\n arrow indicates the current frame, which determines the context of\n most commands.\n\nd(own) [count]\n\n Move the current frame *count* (default one) levels down in the\n stack trace (to a newer frame).\n\nu(p) [count]\n\n Move the current frame *count* (default one) levels up in the stack\n trace (to an older frame).\n\nb(reak) [([filename:]lineno | function) [, condition]]\n\n With a *lineno* argument, set a break there in the current file.\n With a *function* argument, set a break at the first executable\n statement within that function. The line number may be prefixed\n with a filename and a colon, to specify a breakpoint in another\n file (probably one that hasn\'t been loaded yet). The file is\n searched on "sys.path". Note that each breakpoint is assigned a\n number to which all the other breakpoint commands refer.\n\n If a second argument is present, it is an expression which must\n evaluate to true before the breakpoint is honored.\n\n Without argument, list all breaks, including for each breakpoint,\n the number of times that breakpoint has been hit, the current\n ignore count, and the associated condition if any.\n\ntbreak [([filename:]lineno | function) [, condition]]\n\n Temporary breakpoint, which is removed automatically when it is\n first hit. The arguments are the same as for "break".\n\ncl(ear) [filename:lineno | bpnumber [bpnumber ...]]\n\n With a *filename:lineno* argument, clear all the breakpoints at\n this line. With a space separated list of breakpoint numbers, clear\n those breakpoints. Without argument, clear all breaks (but first\n ask confirmation).\n\ndisable [bpnumber [bpnumber ...]]\n\n Disable the breakpoints given as a space separated list of\n breakpoint numbers. Disabling a breakpoint means it cannot cause\n the program to stop execution, but unlike clearing a breakpoint, it\n remains in the list of breakpoints and can be (re-)enabled.\n\nenable [bpnumber [bpnumber ...]]\n\n Enable the breakpoints specified.\n\nignore bpnumber [count]\n\n Set the ignore count for the given breakpoint number. If count is\n omitted, the ignore count is set to 0. A breakpoint becomes active\n when the ignore count is zero. When non-zero, the count is\n decremented each time the breakpoint is reached and the breakpoint\n is not disabled and any associated condition evaluates to true.\n\ncondition bpnumber [condition]\n\n Set a new *condition* for the breakpoint, an expression which must\n evaluate to true before the breakpoint is honored. If *condition*\n is absent, any existing condition is removed; i.e., the breakpoint\n is made unconditional.\n\ncommands [bpnumber]\n\n Specify a list of commands for breakpoint number *bpnumber*. The\n commands themselves appear on the following lines. Type a line\n containing just "end" to terminate the commands. An example:\n\n (Pdb) commands 1\n (com) p some_variable\n (com) end\n (Pdb)\n\n To remove all commands from a breakpoint, type commands and follow\n it immediately with "end"; that is, give no commands.\n\n With no *bpnumber* argument, commands refers to the last breakpoint\n set.\n\n You can use breakpoint commands to start your program up again.\n Simply use the continue command, or step, or any other command that\n resumes execution.\n\n Specifying any command resuming execution (currently continue,\n step, next, return, jump, quit and their abbreviations) terminates\n the command list (as if that command was immediately followed by\n end). This is because any time you resume execution (even with a\n simple next or step), you may encounter another breakpoint--which\n could have its own command list, leading to ambiguities about which\n list to execute.\n\n If you use the \'silent\' command in the command list, the usual\n message about stopping at a breakpoint is not printed. This may be\n desirable for breakpoints that are to print a specific message and\n then continue. If none of the other commands print anything, you\n see no sign that the breakpoint was reached.\n\ns(tep)\n\n Execute the current line, stop at the first possible occasion\n (either in a function that is called or on the next line in the\n current function).\n\nn(ext)\n\n Continue execution until the next line in the current function is\n reached or it returns. (The difference between "next" and "step"\n is that "step" stops inside a called function, while "next"\n executes called functions at (nearly) full speed, only stopping at\n the next line in the current function.)\n\nunt(il) [lineno]\n\n Without argument, continue execution until the line with a number\n greater than the current one is reached.\n\n With a line number, continue execution until a line with a number\n greater or equal to that is reached. In both cases, also stop when\n the current frame returns.\n\n Changed in version 3.2: Allow giving an explicit line number.\n\nr(eturn)\n\n Continue execution until the current function returns.\n\nc(ont(inue))\n\n Continue execution, only stop when a breakpoint is encountered.\n\nj(ump) lineno\n\n Set the next line that will be executed. Only available in the\n bottom-most frame. This lets you jump back and execute code again,\n or jump forward to skip code that you don\'t want to run.\n\n It should be noted that not all jumps are allowed -- for instance\n it is not possible to jump into the middle of a "for" loop or out\n of a "finally" clause.\n\nl(ist) [first[, last]]\n\n List source code for the current file. Without arguments, list 11\n lines around the current line or continue the previous listing.\n With "." as argument, list 11 lines around the current line. With\n one argument, list 11 lines around at that line. With two\n arguments, list the given range; if the second argument is less\n than the first, it is interpreted as a count.\n\n The current line in the current frame is indicated by "->". If an\n exception is being debugged, the line where the exception was\n originally raised or propagated is indicated by ">>", if it differs\n from the current line.\n\n New in version 3.2: The ">>" marker.\n\nll | longlist\n\n List all source code for the current function or frame.\n Interesting lines are marked as for "list".\n\n New in version 3.2.\n\na(rgs)\n\n Print the argument list of the current function.\n\np expression\n\n Evaluate the *expression* in the current context and print its\n value.\n\n Note: "print()" can also be used, but is not a debugger command\n --- this executes the Python "print()" function.\n\npp expression\n\n Like the "p" command, except the value of the expression is pretty-\n printed using the "pprint" module.\n\nwhatis expression\n\n Print the type of the *expression*.\n\nsource expression\n\n Try to get source code for the given object and display it.\n\n New in version 3.2.\n\ndisplay [expression]\n\n Display the value of the expression if it changed, each time\n execution stops in the current frame.\n\n Without expression, list all display expressions for the current\n frame.\n\n New in version 3.2.\n\nundisplay [expression]\n\n Do not display the expression any more in the current frame.\n Without expression, clear all display expressions for the current\n frame.\n\n New in version 3.2.\n\ninteract\n\n Start an interative interpreter (using the "code" module) whose\n global namespace contains all the (global and local) names found in\n the current scope.\n\n New in version 3.2.\n\nalias [name [command]]\n\n Create an alias called *name* that executes *command*. The command\n must *not* be enclosed in quotes. Replaceable parameters can be\n indicated by "%1", "%2", and so on, while "%*" is replaced by all\n the parameters. If no command is given, the current alias for\n *name* is shown. If no arguments are given, all aliases are listed.\n\n Aliases may be nested and can contain anything that can be legally\n typed at the pdb prompt. Note that internal pdb commands *can* be\n overridden by aliases. Such a command is then hidden until the\n alias is removed. Aliasing is recursively applied to the first\n word of the command line; all other words in the line are left\n alone.\n\n As an example, here are two useful aliases (especially when placed\n in the ".pdbrc" file):\n\n # Print instance variables (usage "pi classInst")\n alias pi for k in %1.__dict__.keys(): print("%1.",k,"=",%1.__dict__[k])\n # Print instance variables in self\n alias ps pi self\n\nunalias name\n\n Delete the specified alias.\n\n! statement\n\n Execute the (one-line) *statement* in the context of the current\n stack frame. The exclamation point can be omitted unless the first\n word of the statement resembles a debugger command. To set a\n global variable, you can prefix the assignment command with a\n "global" statement on the same line, e.g.:\n\n (Pdb) global list_options; list_options = [\'-l\']\n (Pdb)\n\nrun [args ...]\nrestart [args ...]\n\n Restart the debugged Python program. If an argument is supplied,\n it is split with "shlex" and the result is used as the new\n "sys.argv". History, breakpoints, actions and debugger options are\n preserved. "restart" is an alias for "run".\n\nq(uit)\n\n Quit from the debugger. The program being executed is aborted.\n\n-[ Footnotes ]-\n\n[1] Whether a frame is considered to originate in a certain module\n is determined by the "__name__" in the frame globals.\n',
'del': u'\nThe "del" statement\n*******************\n\n del_stmt ::= "del" target_list\n\nDeletion is recursively defined very similar to the way assignment is\ndefined. Rather than spelling it out in full details, here are some\nhints.\n\nDeletion of a target list recursively deletes each target, from left\nto right.\n\nDeletion of a name removes the binding of that name from the local or\nglobal namespace, depending on whether the name occurs in a "global"\nstatement in the same code block. If the name is unbound, a\n"NameError" exception will be raised.\n\nDeletion of attribute references, subscriptions and slicings is passed\nto the primary object involved; deletion of a slicing is in general\nequivalent to assignment of an empty slice of the right type (but even\nthis is determined by the sliced object).\n\nChanged in version 3.2: Previously it was illegal to delete a name\nfrom the local namespace if it occurs as a free variable in a nested\nblock.\n',
- 'dict': u'\nDictionary displays\n*******************\n\nA dictionary display is a possibly empty series of key/datum pairs\nenclosed in curly braces:\n\n dict_display ::= "{" [key_datum_list | dict_comprehension] "}"\n key_datum_list ::= key_datum ("," key_datum)* [","]\n key_datum ::= expression ":" expression\n dict_comprehension ::= expression ":" expression comp_for\n\nA dictionary display yields a new dictionary object.\n\nIf a comma-separated sequence of key/datum pairs is given, they are\nevaluated from left to right to define the entries of the dictionary:\neach key object is used as a key into the dictionary to store the\ncorresponding datum. This means that you can specify the same key\nmultiple times in the key/datum list, and the final dictionary\'s value\nfor that key will be the last one given.\n\nA dict comprehension, in contrast to list and set comprehensions,\nneeds two expressions separated with a colon followed by the usual\n"for" and "if" clauses. When the comprehension is run, the resulting\nkey and value elements are inserted in the new dictionary in the order\nthey are produced.\n\nRestrictions on the types of the key values are listed earlier in\nsection *The standard type hierarchy*. (To summarize, the key type\nshould be *hashable*, which excludes all mutable objects.) Clashes\nbetween duplicate keys are not detected; the last datum (textually\nrightmost in the display) stored for a given key value prevails.\n',
+ 'dict': u'\nDictionary displays\n*******************\n\nA dictionary display is a possibly empty series of key/datum pairs\nenclosed in curly braces:\n\n dict_display ::= "{" [key_datum_list | dict_comprehension] "}"\n key_datum_list ::= key_datum ("," key_datum)* [","]\n key_datum ::= expression ":" expression | "**" or_expr\n dict_comprehension ::= expression ":" expression comp_for\n\nA dictionary display yields a new dictionary object.\n\nIf a comma-separated sequence of key/datum pairs is given, they are\nevaluated from left to right to define the entries of the dictionary:\neach key object is used as a key into the dictionary to store the\ncorresponding datum. This means that you can specify the same key\nmultiple times in the key/datum list, and the final dictionary\'s value\nfor that key will be the last one given.\n\nA double asterisk "**" denotes *dictionary unpacking*. Its operand\nmust be a *mapping*. Each mapping item is added to the new\ndictionary. Later values replace values already set by earlier\nkey/datum pairs and earlier dictionary unpackings.\n\nNew in version 3.5: Unpacking into dictionary displays, originally\nproposed by **PEP 448**.\n\nA dict comprehension, in contrast to list and set comprehensions,\nneeds two expressions separated with a colon followed by the usual\n"for" and "if" clauses. When the comprehension is run, the resulting\nkey and value elements are inserted in the new dictionary in the order\nthey are produced.\n\nRestrictions on the types of the key values are listed earlier in\nsection *The standard type hierarchy*. (To summarize, the key type\nshould be *hashable*, which excludes all mutable objects.) Clashes\nbetween duplicate keys are not detected; the last datum (textually\nrightmost in the display) stored for a given key value prevails.\n',
'dynamic-features': u'\nInteraction with dynamic features\n*********************************\n\nName resolution of free variables occurs at runtime, not at compile\ntime. This means that the following code will print 42:\n\n i = 10\n def f():\n print(i)\n i = 42\n f()\n\nThere are several cases where Python statements are illegal when used\nin conjunction with nested scopes that contain free variables.\n\nIf a variable is referenced in an enclosing scope, it is illegal to\ndelete the name. An error will be reported at compile time.\n\nThe "eval()" and "exec()" functions do not have access to the full\nenvironment for resolving names. Names may be resolved in the local\nand global namespaces of the caller. Free variables are not resolved\nin the nearest enclosing namespace, but in the global namespace. [1]\nThe "exec()" and "eval()" functions have optional arguments to\noverride the global and local namespace. If only one namespace is\nspecified, it is used for both.\n',
'else': u'\nThe "if" statement\n******************\n\nThe "if" statement is used for conditional execution:\n\n if_stmt ::= "if" expression ":" suite\n ( "elif" expression ":" suite )*\n ["else" ":" suite]\n\nIt selects exactly one of the suites by evaluating the expressions one\nby one until one is found to be true (see section *Boolean operations*\nfor the definition of true and false); then that suite is executed\n(and no other part of the "if" statement is executed or evaluated).\nIf all expressions are false, the suite of the "else" clause, if\npresent, is executed.\n',
'exceptions': u'\nExceptions\n**********\n\nExceptions are a means of breaking out of the normal flow of control\nof a code block in order to handle errors or other exceptional\nconditions. An exception is *raised* at the point where the error is\ndetected; it may be *handled* by the surrounding code block or by any\ncode block that directly or indirectly invoked the code block where\nthe error occurred.\n\nThe Python interpreter raises an exception when it detects a run-time\nerror (such as division by zero). A Python program can also\nexplicitly raise an exception with the "raise" statement. Exception\nhandlers are specified with the "try" ... "except" statement. The\n"finally" clause of such a statement can be used to specify cleanup\ncode which does not handle the exception, but is executed whether an\nexception occurred or not in the preceding code.\n\nPython uses the "termination" model of error handling: an exception\nhandler can find out what happened and continue execution at an outer\nlevel, but it cannot repair the cause of the error and retry the\nfailing operation (except by re-entering the offending piece of code\nfrom the top).\n\nWhen an exception is not handled at all, the interpreter terminates\nexecution of the program, or returns to its interactive main loop. In\neither case, it prints a stack backtrace, except when the exception is\n"SystemExit".\n\nExceptions are identified by class instances. The "except" clause is\nselected depending on the class of the instance: it must reference the\nclass of the instance or a base class thereof. The instance can be\nreceived by the handler and can carry additional information about the\nexceptional condition.\n\nNote: Exception messages are not part of the Python API. Their\n contents may change from one version of Python to the next without\n warning and should not be relied on by code which will run under\n multiple versions of the interpreter.\n\nSee also the description of the "try" statement in section *The try\nstatement* and "raise" statement in section *The raise statement*.\n\n-[ Footnotes ]-\n\n[1] This limitation occurs because the code that is executed by\n these operations is not available at the time the module is\n compiled.\n',
'execmodel': u'\nExecution model\n***************\n\n\nStructure of a program\n======================\n\nA Python program is constructed from code blocks. A *block* is a piece\nof Python program text that is executed as a unit. The following are\nblocks: a module, a function body, and a class definition. Each\ncommand typed interactively is a block. A script file (a file given\nas standard input to the interpreter or specified as a command line\nargument to the interpreter) is a code block. A script command (a\ncommand specified on the interpreter command line with the \'**-c**\'\noption) is a code block. The string argument passed to the built-in\nfunctions "eval()" and "exec()" is a code block.\n\nA code block is executed in an *execution frame*. A frame contains\nsome administrative information (used for debugging) and determines\nwhere and how execution continues after the code block\'s execution has\ncompleted.\n\n\nNaming and binding\n==================\n\n\nBinding of names\n----------------\n\n*Names* refer to objects. Names are introduced by name binding\noperations.\n\nThe following constructs bind names: formal parameters to functions,\n"import" statements, class and function definitions (these bind the\nclass or function name in the defining block), and targets that are\nidentifiers if occurring in an assignment, "for" loop header, or after\n"as" in a "with" statement or "except" clause. The "import" statement\nof the form "from ... import *" binds all names defined in the\nimported module, except those beginning with an underscore. This form\nmay only be used at the module level.\n\nA target occurring in a "del" statement is also considered bound for\nthis purpose (though the actual semantics are to unbind the name).\n\nEach assignment or import statement occurs within a block defined by a\nclass or function definition or at the module level (the top-level\ncode block).\n\nIf a name is bound in a block, it is a local variable of that block,\nunless declared as "nonlocal" or "global". If a name is bound at the\nmodule level, it is a global variable. (The variables of the module\ncode block are local and global.) If a variable is used in a code\nblock but not defined there, it is a *free variable*.\n\nEach occurrence of a name in the program text refers to the *binding*\nof that name established by the following name resolution rules.\n\n\nResolution of names\n-------------------\n\nA *scope* defines the visibility of a name within a block. If a local\nvariable is defined in a block, its scope includes that block. If the\ndefinition occurs in a function block, the scope extends to any blocks\ncontained within the defining one, unless a contained block introduces\na different binding for the name.\n\nWhen a name is used in a code block, it is resolved using the nearest\nenclosing scope. The set of all such scopes visible to a code block\nis called the block\'s *environment*.\n\nWhen a name is not found at all, a "NameError" exception is raised. If\nthe current scope is a function scope, and the name refers to a local\nvariable that has not yet been bound to a value at the point where the\nname is used, an "UnboundLocalError" exception is raised.\n"UnboundLocalError" is a subclass of "NameError".\n\nIf a name binding operation occurs anywhere within a code block, all\nuses of the name within the block are treated as references to the\ncurrent block. This can lead to errors when a name is used within a\nblock before it is bound. This rule is subtle. Python lacks\ndeclarations and allows name binding operations to occur anywhere\nwithin a code block. The local variables of a code block can be\ndetermined by scanning the entire text of the block for name binding\noperations.\n\nIf the "global" statement occurs within a block, all uses of the name\nspecified in the statement refer to the binding of that name in the\ntop-level namespace. Names are resolved in the top-level namespace by\nsearching the global namespace, i.e. the namespace of the module\ncontaining the code block, and the builtins namespace, the namespace\nof the module "builtins". The global namespace is searched first. If\nthe name is not found there, the builtins namespace is searched. The\n"global" statement must precede all uses of the name.\n\nThe "global" statement has the same scope as a name binding operation\nin the same block. If the nearest enclosing scope for a free variable\ncontains a global statement, the free variable is treated as a global.\n\nThe "nonlocal" statement causes corresponding names to refer to\npreviously bound variables in the nearest enclosing function scope.\n"SyntaxError" is raised at compile time if the given name does not\nexist in any enclosing function scope.\n\nThe namespace for a module is automatically created the first time a\nmodule is imported. The main module for a script is always called\n"__main__".\n\nClass definition blocks and arguments to "exec()" and "eval()" are\nspecial in the context of name resolution. A class definition is an\nexecutable statement that may use and define names. These references\nfollow the normal rules for name resolution with an exception that\nunbound local variables are looked up in the global namespace. The\nnamespace of the class definition becomes the attribute dictionary of\nthe class. The scope of names defined in a class block is limited to\nthe class block; it does not extend to the code blocks of methods --\nthis includes comprehensions and generator expressions since they are\nimplemented using a function scope. This means that the following\nwill fail:\n\n class A:\n a = 42\n b = list(a + i for i in range(10))\n\n\nBuiltins and restricted execution\n---------------------------------\n\nThe builtins namespace associated with the execution of a code block\nis actually found by looking up the name "__builtins__" in its global\nnamespace; this should be a dictionary or a module (in the latter case\nthe module\'s dictionary is used). By default, when in the "__main__"\nmodule, "__builtins__" is the built-in module "builtins"; when in any\nother module, "__builtins__" is an alias for the dictionary of the\n"builtins" module itself. "__builtins__" can be set to a user-created\ndictionary to create a weak form of restricted execution.\n\n**CPython implementation detail:** Users should not touch\n"__builtins__"; it is strictly an implementation detail. Users\nwanting to override values in the builtins namespace should "import"\nthe "builtins" module and modify its attributes appropriately.\n\n\nInteraction with dynamic features\n---------------------------------\n\nName resolution of free variables occurs at runtime, not at compile\ntime. This means that the following code will print 42:\n\n i = 10\n def f():\n print(i)\n i = 42\n f()\n\nThere are several cases where Python statements are illegal when used\nin conjunction with nested scopes that contain free variables.\n\nIf a variable is referenced in an enclosing scope, it is illegal to\ndelete the name. An error will be reported at compile time.\n\nThe "eval()" and "exec()" functions do not have access to the full\nenvironment for resolving names. Names may be resolved in the local\nand global namespaces of the caller. Free variables are not resolved\nin the nearest enclosing namespace, but in the global namespace. [1]\nThe "exec()" and "eval()" functions have optional arguments to\noverride the global and local namespace. If only one namespace is\nspecified, it is used for both.\n\n\nExceptions\n==========\n\nExceptions are a means of breaking out of the normal flow of control\nof a code block in order to handle errors or other exceptional\nconditions. An exception is *raised* at the point where the error is\ndetected; it may be *handled* by the surrounding code block or by any\ncode block that directly or indirectly invoked the code block where\nthe error occurred.\n\nThe Python interpreter raises an exception when it detects a run-time\nerror (such as division by zero). A Python program can also\nexplicitly raise an exception with the "raise" statement. Exception\nhandlers are specified with the "try" ... "except" statement. The\n"finally" clause of such a statement can be used to specify cleanup\ncode which does not handle the exception, but is executed whether an\nexception occurred or not in the preceding code.\n\nPython uses the "termination" model of error handling: an exception\nhandler can find out what happened and continue execution at an outer\nlevel, but it cannot repair the cause of the error and retry the\nfailing operation (except by re-entering the offending piece of code\nfrom the top).\n\nWhen an exception is not handled at all, the interpreter terminates\nexecution of the program, or returns to its interactive main loop. In\neither case, it prints a stack backtrace, except when the exception is\n"SystemExit".\n\nExceptions are identified by class instances. The "except" clause is\nselected depending on the class of the instance: it must reference the\nclass of the instance or a base class thereof. The instance can be\nreceived by the handler and can carry additional information about the\nexceptional condition.\n\nNote: Exception messages are not part of the Python API. Their\n contents may change from one version of Python to the next without\n warning and should not be relied on by code which will run under\n multiple versions of the interpreter.\n\nSee also the description of the "try" statement in section *The try\nstatement* and "raise" statement in section *The raise statement*.\n\n-[ Footnotes ]-\n\n[1] This limitation occurs because the code that is executed by\n these operations is not available at the time the module is\n compiled.\n',
- 'exprlists': u'\nExpression lists\n****************\n\n expression_list ::= expression ( "," expression )* [","]\n\nAn expression list containing at least one comma yields a tuple. The\nlength of the tuple is the number of expressions in the list. The\nexpressions are evaluated from left to right.\n\nThe trailing comma is required only to create a single tuple (a.k.a. a\n*singleton*); it is optional in all other cases. A single expression\nwithout a trailing comma doesn\'t create a tuple, but rather yields the\nvalue of that expression. (To create an empty tuple, use an empty pair\nof parentheses: "()".)\n',
+ 'exprlists': u'\nExpression lists\n****************\n\n expression_list ::= expression ( "," expression )* [","]\n starred_list ::= starred_item ( "," starred_item )* [","]\n starred_expression ::= expression | ( starred_item "," )* [starred_item]\n starred_item ::= expression | "*" or_expr\n\nExcept when part of a list or set display, an expression list\ncontaining at least one comma yields a tuple. The length of the tuple\nis the number of expressions in the list. The expressions are\nevaluated from left to right.\n\nAn asterisk "*" denotes *iterable unpacking*. Its operand must be an\n*iterable*. The iterable is expanded into a sequence of items, which\nare included in the new tuple, list, or set, at the site of the\nunpacking.\n\nNew in version 3.5: Iterable unpacking in expression lists, originally\nproposed by **PEP 448**.\n\nThe trailing comma is required only to create a single tuple (a.k.a. a\n*singleton*); it is optional in all other cases. A single expression\nwithout a trailing comma doesn\'t create a tuple, but rather yields the\nvalue of that expression. (To create an empty tuple, use an empty pair\nof parentheses: "()".)\n',
'floating': u'\nFloating point literals\n***********************\n\nFloating point literals are described by the following lexical\ndefinitions:\n\n floatnumber ::= pointfloat | exponentfloat\n pointfloat ::= [intpart] fraction | intpart "."\n exponentfloat ::= (intpart | pointfloat) exponent\n intpart ::= digit+\n fraction ::= "." digit+\n exponent ::= ("e" | "E") ["+" | "-"] digit+\n\nNote that the integer and exponent parts are always interpreted using\nradix 10. For example, "077e010" is legal, and denotes the same number\nas "77e10". The allowed range of floating point literals is\nimplementation-dependent. Some examples of floating point literals:\n\n 3.14 10. .001 1e100 3.14e-10 0e0\n\nNote that numeric literals do not include a sign; a phrase like "-1"\nis actually an expression composed of the unary operator "-" and the\nliteral "1".\n',
'for': u'\nThe "for" statement\n*******************\n\nThe "for" statement is used to iterate over the elements of a sequence\n(such as a string, tuple or list) or other iterable object:\n\n for_stmt ::= "for" target_list "in" expression_list ":" suite\n ["else" ":" suite]\n\nThe expression list is evaluated once; it should yield an iterable\nobject. An iterator is created for the result of the\n"expression_list". The suite is then executed once for each item\nprovided by the iterator, in the order returned by the iterator. Each\nitem in turn is assigned to the target list using the standard rules\nfor assignments (see *Assignment statements*), and then the suite is\nexecuted. When the items are exhausted (which is immediately when the\nsequence is empty or an iterator raises a "StopIteration" exception),\nthe suite in the "else" clause, if present, is executed, and the loop\nterminates.\n\nA "break" statement executed in the first suite terminates the loop\nwithout executing the "else" clause\'s suite. A "continue" statement\nexecuted in the first suite skips the rest of the suite and continues\nwith the next item, or with the "else" clause if there is no next\nitem.\n\nThe for-loop makes assignments to the variables(s) in the target list.\nThis overwrites all previous assignments to those variables including\nthose made in the suite of the for-loop:\n\n for i in range(10):\n print(i)\n i = 5 # this will not affect the for-loop\n # because i will be overwritten with the next\n # index in the range\n\nNames in the target list are not deleted when the loop is finished,\nbut if the sequence is empty, they will not have been assigned to at\nall by the loop. Hint: the built-in function "range()" returns an\niterator of integers suitable to emulate the effect of Pascal\'s "for i\n:= a to b do"; e.g., "list(range(3))" returns the list "[0, 1, 2]".\n\nNote: There is a subtlety when the sequence is being modified by the\n loop (this can only occur for mutable sequences, i.e. lists). An\n internal counter is used to keep track of which item is used next,\n and this is incremented on each iteration. When this counter has\n reached the length of the sequence the loop terminates. This means\n that if the suite deletes the current (or a previous) item from the\n sequence, the next item will be skipped (since it gets the index of\n the current item which has already been treated). Likewise, if the\n suite inserts an item in the sequence before the current item, the\n current item will be treated again the next time through the loop.\n This can lead to nasty bugs that can be avoided by making a\n temporary copy using a slice of the whole sequence, e.g.,\n\n for x in a[:]:\n if x < 0: a.remove(x)\n',
- 'formatstrings': u'\nFormat String Syntax\n********************\n\nThe "str.format()" method and the "Formatter" class share the same\nsyntax for format strings (although in the case of "Formatter",\nsubclasses can define their own format string syntax).\n\nFormat strings contain "replacement fields" surrounded by curly braces\n"{}". Anything that is not contained in braces is considered literal\ntext, which is copied unchanged to the output. If you need to include\na brace character in the literal text, it can be escaped by doubling:\n"{{" and "}}".\n\nThe grammar for a replacement field is as follows:\n\n replacement_field ::= "{" [field_name] ["!" conversion] [":" format_spec] "}"\n field_name ::= arg_name ("." attribute_name | "[" element_index "]")*\n arg_name ::= [identifier | integer]\n attribute_name ::= identifier\n element_index ::= integer | index_string\n index_string ::= <any source character except "]"> +\n conversion ::= "r" | "s" | "a"\n format_spec ::= <described in the next section>\n\nIn less formal terms, the replacement field can start with a\n*field_name* that specifies the object whose value is to be formatted\nand inserted into the output instead of the replacement field. The\n*field_name* is optionally followed by a *conversion* field, which is\npreceded by an exclamation point "\'!\'", and a *format_spec*, which is\npreceded by a colon "\':\'". These specify a non-default format for the\nreplacement value.\n\nSee also the *Format Specification Mini-Language* section.\n\nThe *field_name* itself begins with an *arg_name* that is either a\nnumber or a keyword. If it\'s a number, it refers to a positional\nargument, and if it\'s a keyword, it refers to a named keyword\nargument. If the numerical arg_names in a format string are 0, 1, 2,\n... in sequence, they can all be omitted (not just some) and the\nnumbers 0, 1, 2, ... will be automatically inserted in that order.\nBecause *arg_name* is not quote-delimited, it is not possible to\nspecify arbitrary dictionary keys (e.g., the strings "\'10\'" or\n"\':-]\'") within a format string. The *arg_name* can be followed by any\nnumber of index or attribute expressions. An expression of the form\n"\'.name\'" selects the named attribute using "getattr()", while an\nexpression of the form "\'[index]\'" does an index lookup using\n"__getitem__()".\n\nChanged in version 3.1: The positional argument specifiers can be\nomitted, so "\'{} {}\'" is equivalent to "\'{0} {1}\'".\n\nSome simple format string examples:\n\n "First, thou shalt count to {0}" # References first positional argument\n "Bring me a {}" # Implicitly references the first positional argument\n "From {} to {}" # Same as "From {0} to {1}"\n "My quest is {name}" # References keyword argument \'name\'\n "Weight in tons {0.weight}" # \'weight\' attribute of first positional arg\n "Units destroyed: {players[0]}" # First element of keyword argument \'players\'.\n\nThe *conversion* field causes a type coercion before formatting.\nNormally, the job of formatting a value is done by the "__format__()"\nmethod of the value itself. However, in some cases it is desirable to\nforce a type to be formatted as a string, overriding its own\ndefinition of formatting. By converting the value to a string before\ncalling "__format__()", the normal formatting logic is bypassed.\n\nThree conversion flags are currently supported: "\'!s\'" which calls\n"str()" on the value, "\'!r\'" which calls "repr()" and "\'!a\'" which\ncalls "ascii()".\n\nSome examples:\n\n "Harold\'s a clever {0!s}" # Calls str() on the argument first\n "Bring out the holy {name!r}" # Calls repr() on the argument first\n "More {!a}" # Calls ascii() on the argument first\n\nThe *format_spec* field contains a specification of how the value\nshould be presented, including such details as field width, alignment,\npadding, decimal precision and so on. Each value type can define its\nown "formatting mini-language" or interpretation of the *format_spec*.\n\nMost built-in types support a common formatting mini-language, which\nis described in the next section.\n\nA *format_spec* field can also include nested replacement fields\nwithin it. These nested replacement fields can contain only a field\nname; conversion flags and format specifications are not allowed. The\nreplacement fields within the format_spec are substituted before the\n*format_spec* string is interpreted. This allows the formatting of a\nvalue to be dynamically specified.\n\nSee the *Format examples* section for some examples.\n\n\nFormat Specification Mini-Language\n==================================\n\n"Format specifications" are used within replacement fields contained\nwithin a format string to define how individual values are presented\n(see *Format String Syntax*). They can also be passed directly to the\nbuilt-in "format()" function. Each formattable type may define how\nthe format specification is to be interpreted.\n\nMost built-in types implement the following options for format\nspecifications, although some of the formatting options are only\nsupported by the numeric types.\n\nA general convention is that an empty format string ("""") produces\nthe same result as if you had called "str()" on the value. A non-empty\nformat string typically modifies the result.\n\nThe general form of a *standard format specifier* is:\n\n format_spec ::= [[fill]align][sign][#][0][width][,][.precision][type]\n fill ::= <any character>\n align ::= "<" | ">" | "=" | "^"\n sign ::= "+" | "-" | " "\n width ::= integer\n precision ::= integer\n type ::= "b" | "c" | "d" | "e" | "E" | "f" | "F" | "g" | "G" | "n" | "o" | "s" | "x" | "X" | "%"\n\nIf a valid *align* value is specified, it can be preceded by a *fill*\ncharacter that can be any character and defaults to a space if\nomitted. Note that it is not possible to use "{" and "}" as *fill*\nchar while using the "str.format()" method; this limitation however\ndoesn\'t affect the "format()" function.\n\nThe meaning of the various alignment options is as follows:\n\n +-----------+------------------------------------------------------------+\n | Option | Meaning |\n +===========+============================================================+\n | "\'<\'" | Forces the field to be left-aligned within the available |\n | | space (this is the default for most objects). |\n +-----------+------------------------------------------------------------+\n | "\'>\'" | Forces the field to be right-aligned within the available |\n | | space (this is the default for numbers). |\n +-----------+------------------------------------------------------------+\n | "\'=\'" | Forces the padding to be placed after the sign (if any) |\n | | but before the digits. This is used for printing fields |\n | | in the form \'+000000120\'. This alignment option is only |\n | | valid for numeric types. |\n +-----------+------------------------------------------------------------+\n | "\'^\'" | Forces the field to be centered within the available |\n | | space. |\n +-----------+------------------------------------------------------------+\n\nNote that unless a minimum field width is defined, the field width\nwill always be the same size as the data to fill it, so that the\nalignment option has no meaning in this case.\n\nThe *sign* option is only valid for number types, and can be one of\nthe following:\n\n +-----------+------------------------------------------------------------+\n | Option | Meaning |\n +===========+============================================================+\n | "\'+\'" | indicates that a sign should be used for both positive as |\n | | well as negative numbers. |\n +-----------+------------------------------------------------------------+\n | "\'-\'" | indicates that a sign should be used only for negative |\n | | numbers (this is the default behavior). |\n +-----------+------------------------------------------------------------+\n | space | indicates that a leading space should be used on positive |\n | | numbers, and a minus sign on negative numbers. |\n +-----------+------------------------------------------------------------+\n\nThe "\'#\'" option causes the "alternate form" to be used for the\nconversion. The alternate form is defined differently for different\ntypes. This option is only valid for integer, float, complex and\nDecimal types. For integers, when binary, octal, or hexadecimal output\nis used, this option adds the prefix respective "\'0b\'", "\'0o\'", or\n"\'0x\'" to the output value. For floats, complex and Decimal the\nalternate form causes the result of the conversion to always contain a\ndecimal-point character, even if no digits follow it. Normally, a\ndecimal-point character appears in the result of these conversions\nonly if a digit follows it. In addition, for "\'g\'" and "\'G\'"\nconversions, trailing zeros are not removed from the result.\n\nThe "\',\'" option signals the use of a comma for a thousands separator.\nFor a locale aware separator, use the "\'n\'" integer presentation type\ninstead.\n\nChanged in version 3.1: Added the "\',\'" option (see also **PEP 378**).\n\n*width* is a decimal integer defining the minimum field width. If not\nspecified, then the field width will be determined by the content.\n\nPreceding the *width* field by a zero ("\'0\'") character enables sign-\naware zero-padding for numeric types. This is equivalent to a *fill*\ncharacter of "\'0\'" with an *alignment* type of "\'=\'".\n\nThe *precision* is a decimal number indicating how many digits should\nbe displayed after the decimal point for a floating point value\nformatted with "\'f\'" and "\'F\'", or before and after the decimal point\nfor a floating point value formatted with "\'g\'" or "\'G\'". For non-\nnumber types the field indicates the maximum field size - in other\nwords, how many characters will be used from the field content. The\n*precision* is not allowed for integer values.\n\nFinally, the *type* determines how the data should be presented.\n\nThe available string presentation types are:\n\n +-----------+------------------------------------------------------------+\n | Type | Meaning |\n +===========+============================================================+\n | "\'s\'" | String format. This is the default type for strings and |\n | | may be omitted. |\n +-----------+------------------------------------------------------------+\n | None | The same as "\'s\'". |\n +-----------+------------------------------------------------------------+\n\nThe available integer presentation types are:\n\n +-----------+------------------------------------------------------------+\n | Type | Meaning |\n +===========+============================================================+\n | "\'b\'" | Binary format. Outputs the number in base 2. |\n +-----------+------------------------------------------------------------+\n | "\'c\'" | Character. Converts the integer to the corresponding |\n | | unicode character before printing. |\n +-----------+------------------------------------------------------------+\n | "\'d\'" | Decimal Integer. Outputs the number in base 10. |\n +-----------+------------------------------------------------------------+\n | "\'o\'" | Octal format. Outputs the number in base 8. |\n +-----------+------------------------------------------------------------+\n | "\'x\'" | Hex format. Outputs the number in base 16, using lower- |\n | | case letters for the digits above 9. |\n +-----------+------------------------------------------------------------+\n | "\'X\'" | Hex format. Outputs the number in base 16, using upper- |\n | | case letters for the digits above 9. |\n +-----------+------------------------------------------------------------+\n | "\'n\'" | Number. This is the same as "\'d\'", except that it uses the |\n | | current locale setting to insert the appropriate number |\n | | separator characters. |\n +-----------+------------------------------------------------------------+\n | None | The same as "\'d\'". |\n +-----------+------------------------------------------------------------+\n\nIn addition to the above presentation types, integers can be formatted\nwith the floating point presentation types listed below (except "\'n\'"\nand None). When doing so, "float()" is used to convert the integer to\na floating point number before formatting.\n\nThe available presentation types for floating point and decimal values\nare:\n\n +-----------+------------------------------------------------------------+\n | Type | Meaning |\n +===========+============================================================+\n | "\'e\'" | Exponent notation. Prints the number in scientific |\n | | notation using the letter \'e\' to indicate the exponent. |\n | | The default precision is "6". |\n +-----------+------------------------------------------------------------+\n | "\'E\'" | Exponent notation. Same as "\'e\'" except it uses an upper |\n | | case \'E\' as the separator character. |\n +-----------+------------------------------------------------------------+\n | "\'f\'" | Fixed point. Displays the number as a fixed-point number. |\n | | The default precision is "6". |\n +-----------+------------------------------------------------------------+\n | "\'F\'" | Fixed point. Same as "\'f\'", but converts "nan" to "NAN" |\n | | and "inf" to "INF". |\n +-----------+------------------------------------------------------------+\n | "\'g\'" | General format. For a given precision "p >= 1", this |\n | | rounds the number to "p" significant digits and then |\n | | formats the result in either fixed-point format or in |\n | | scientific notation, depending on its magnitude. The |\n | | precise rules are as follows: suppose that the result |\n | | formatted with presentation type "\'e\'" and precision "p-1" |\n | | would have exponent "exp". Then if "-4 <= exp < p", the |\n | | number is formatted with presentation type "\'f\'" and |\n | | precision "p-1-exp". Otherwise, the number is formatted |\n | | with presentation type "\'e\'" and precision "p-1". In both |\n | | cases insignificant trailing zeros are removed from the |\n | | significand, and the decimal point is also removed if |\n | | there are no remaining digits following it. Positive and |\n | | negative infinity, positive and negative zero, and nans, |\n | | are formatted as "inf", "-inf", "0", "-0" and "nan" |\n | | respectively, regardless of the precision. A precision of |\n | | "0" is treated as equivalent to a precision of "1". The |\n | | default precision is "6". |\n +-----------+------------------------------------------------------------+\n | "\'G\'" | General format. Same as "\'g\'" except switches to "\'E\'" if |\n | | the number gets too large. The representations of infinity |\n | | and NaN are uppercased, too. |\n +-----------+------------------------------------------------------------+\n | "\'n\'" | Number. This is the same as "\'g\'", except that it uses the |\n | | current locale setting to insert the appropriate number |\n | | separator characters. |\n +-----------+------------------------------------------------------------+\n | "\'%\'" | Percentage. Multiplies the number by 100 and displays in |\n | | fixed ("\'f\'") format, followed by a percent sign. |\n +-----------+------------------------------------------------------------+\n | None | Similar to "\'g\'", except that fixed-point notation, when |\n | | used, has at least one digit past the decimal point. The |\n | | default precision is as high as needed to represent the |\n | | particular value. The overall effect is to match the |\n | | output of "str()" as altered by the other format |\n | | modifiers. |\n +-----------+------------------------------------------------------------+\n\n\nFormat examples\n===============\n\nThis section contains examples of the new format syntax and comparison\nwith the old "%"-formatting.\n\nIn most of the cases the syntax is similar to the old "%"-formatting,\nwith the addition of the "{}" and with ":" used instead of "%". For\nexample, "\'%03.2f\'" can be translated to "\'{:03.2f}\'".\n\nThe new format syntax also supports new and different options, shown\nin the follow examples.\n\nAccessing arguments by position:\n\n >>> \'{0}, {1}, {2}\'.format(\'a\', \'b\', \'c\')\n \'a, b, c\'\n >>> \'{}, {}, {}\'.format(\'a\', \'b\', \'c\') # 3.1+ only\n \'a, b, c\'\n >>> \'{2}, {1}, {0}\'.format(\'a\', \'b\', \'c\')\n \'c, b, a\'\n >>> \'{2}, {1}, {0}\'.format(*\'abc\') # unpacking argument sequence\n \'c, b, a\'\n >>> \'{0}{1}{0}\'.format(\'abra\', \'cad\') # arguments\' indices can be repeated\n \'abracadabra\'\n\nAccessing arguments by name:\n\n >>> \'Coordinates: {latitude}, {longitude}\'.format(latitude=\'37.24N\', longitude=\'-115.81W\')\n \'Coordinates: 37.24N, -115.81W\'\n >>> coord = {\'latitude\': \'37.24N\', \'longitude\': \'-115.81W\'}\n >>> \'Coordinates: {latitude}, {longitude}\'.format(**coord)\n \'Coordinates: 37.24N, -115.81W\'\n\nAccessing arguments\' attributes:\n\n >>> c = 3-5j\n >>> (\'The complex number {0} is formed from the real part {0.real} \'\n ... \'and the imaginary part {0.imag}.\').format(c)\n \'The complex number (3-5j) is formed from the real part 3.0 and the imaginary part -5.0.\'\n >>> class Point:\n ... def __init__(self, x, y):\n ... self.x, self.y = x, y\n ... def __str__(self):\n ... return \'Point({self.x}, {self.y})\'.format(self=self)\n ...\n >>> str(Point(4, 2))\n \'Point(4, 2)\'\n\nAccessing arguments\' items:\n\n >>> coord = (3, 5)\n >>> \'X: {0[0]}; Y: {0[1]}\'.format(coord)\n \'X: 3; Y: 5\'\n\nReplacing "%s" and "%r":\n\n >>> "repr() shows quotes: {!r}; str() doesn\'t: {!s}".format(\'test1\', \'test2\')\n "repr() shows quotes: \'test1\'; str() doesn\'t: test2"\n\nAligning the text and specifying a width:\n\n >>> \'{:<30}\'.format(\'left aligned\')\n \'left aligned \'\n >>> \'{:>30}\'.format(\'right aligned\')\n \' right aligned\'\n >>> \'{:^30}\'.format(\'centered\')\n \' centered \'\n >>> \'{:*^30}\'.format(\'centered\') # use \'*\' as a fill char\n \'***********centered***********\'\n\nReplacing "%+f", "%-f", and "% f" and specifying a sign:\n\n >>> \'{:+f}; {:+f}\'.format(3.14, -3.14) # show it always\n \'+3.140000; -3.140000\'\n >>> \'{: f}; {: f}\'.format(3.14, -3.14) # show a space for positive numbers\n \' 3.140000; -3.140000\'\n >>> \'{:-f}; {:-f}\'.format(3.14, -3.14) # show only the minus -- same as \'{:f}; {:f}\'\n \'3.140000; -3.140000\'\n\nReplacing "%x" and "%o" and converting the value to different bases:\n\n >>> # format also supports binary numbers\n >>> "int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}".format(42)\n \'int: 42; hex: 2a; oct: 52; bin: 101010\'\n >>> # with 0x, 0o, or 0b as prefix:\n >>> "int: {0:d}; hex: {0:#x}; oct: {0:#o}; bin: {0:#b}".format(42)\n \'int: 42; hex: 0x2a; oct: 0o52; bin: 0b101010\'\n\nUsing the comma as a thousands separator:\n\n >>> \'{:,}\'.format(1234567890)\n \'1,234,567,890\'\n\nExpressing a percentage:\n\n >>> points = 19\n >>> total = 22\n >>> \'Correct answers: {:.2%}\'.format(points/total)\n \'Correct answers: 86.36%\'\n\nUsing type-specific formatting:\n\n >>> import datetime\n >>> d = datetime.datetime(2010, 7, 4, 12, 15, 58)\n >>> \'{:%Y-%m-%d %H:%M:%S}\'.format(d)\n \'2010-07-04 12:15:58\'\n\nNesting arguments and more complex examples:\n\n >>> for align, text in zip(\'<^>\', [\'left\', \'center\', \'right\']):\n ... \'{0:{fill}{align}16}\'.format(text, fill=align, align=align)\n ...\n \'left<<<<<<<<<<<<\'\n \'^^^^^center^^^^^\'\n \'>>>>>>>>>>>right\'\n >>>\n >>> octets = [192, 168, 0, 1]\n >>> \'{:02X}{:02X}{:02X}{:02X}\'.format(*octets)\n \'C0A80001\'\n >>> int(_, 16)\n 3232235521\n >>>\n >>> width = 5\n >>> for num in range(5,12): #doctest: +NORMALIZE_WHITESPACE\n ... for base in \'dXob\':\n ... print(\'{0:{width}{base}}\'.format(num, base=base, width=width), end=\' \')\n ... print()\n ...\n 5 5 5 101\n 6 6 6 110\n 7 7 7 111\n 8 8 10 1000\n 9 9 11 1001\n 10 A 12 1010\n 11 B 13 1011\n',
- 'function': u'\nFunction definitions\n********************\n\nA function definition defines a user-defined function object (see\nsection *The standard type hierarchy*):\n\n funcdef ::= [decorators] "def" funcname "(" [parameter_list] ")" ["->" expression] ":" suite\n decorators ::= decorator+\n decorator ::= "@" dotted_name ["(" [parameter_list [","]] ")"] NEWLINE\n dotted_name ::= identifier ("." identifier)*\n parameter_list ::= (defparameter ",")*\n | "*" [parameter] ("," defparameter)* ["," "**" parameter]\n | "**" parameter\n | defparameter [","] )\n parameter ::= identifier [":" expression]\n defparameter ::= parameter ["=" expression]\n funcname ::= identifier\n\nA function definition is an executable statement. Its execution binds\nthe function name in the current local namespace to a function object\n(a wrapper around the executable code for the function). This\nfunction object contains a reference to the current global namespace\nas the global namespace to be used when the function is called.\n\nThe function definition does not execute the function body; this gets\nexecuted only when the function is called. [3]\n\nA function definition may be wrapped by one or more *decorator*\nexpressions. Decorator expressions are evaluated when the function is\ndefined, in the scope that contains the function definition. The\nresult must be a callable, which is invoked with the function object\nas the only argument. The returned value is bound to the function name\ninstead of the function object. Multiple decorators are applied in\nnested fashion. For example, the following code\n\n @f1(arg)\n @f2\n def func(): pass\n\nis equivalent to\n\n def func(): pass\n func = f1(arg)(f2(func))\n\nWhen one or more *parameters* have the form *parameter* "="\n*expression*, the function is said to have "default parameter values."\nFor a parameter with a default value, the corresponding *argument* may\nbe omitted from a call, in which case the parameter\'s default value is\nsubstituted. If a parameter has a default value, all following\nparameters up until the ""*"" must also have a default value --- this\nis a syntactic restriction that is not expressed by the grammar.\n\n**Default parameter values are evaluated from left to right when the\nfunction definition is executed.** This means that the expression is\nevaluated once, when the function is defined, and that the same "pre-\ncomputed" value is used for each call. This is especially important\nto understand when a default parameter is a mutable object, such as a\nlist or a dictionary: if the function modifies the object (e.g. by\nappending an item to a list), the default value is in effect modified.\nThis is generally not what was intended. A way around this is to use\n"None" as the default, and explicitly test for it in the body of the\nfunction, e.g.:\n\n def whats_on_the_telly(penguin=None):\n if penguin is None:\n penguin = []\n penguin.append("property of the zoo")\n return penguin\n\nFunction call semantics are described in more detail in section\n*Calls*. A function call always assigns values to all parameters\nmentioned in the parameter list, either from position arguments, from\nkeyword arguments, or from default values. If the form\n""*identifier"" is present, it is initialized to a tuple receiving any\nexcess positional parameters, defaulting to the empty tuple. If the\nform ""**identifier"" is present, it is initialized to a new\ndictionary receiving any excess keyword arguments, defaulting to a new\nempty dictionary. Parameters after ""*"" or ""*identifier"" are\nkeyword-only parameters and may only be passed used keyword arguments.\n\nParameters may have annotations of the form "": expression"" following\nthe parameter name. Any parameter may have an annotation even those\nof the form "*identifier" or "**identifier". Functions may have\n"return" annotation of the form ""-> expression"" after the parameter\nlist. These annotations can be any valid Python expression and are\nevaluated when the function definition is executed. Annotations may\nbe evaluated in a different order than they appear in the source code.\nThe presence of annotations does not change the semantics of a\nfunction. The annotation values are available as values of a\ndictionary keyed by the parameters\' names in the "__annotations__"\nattribute of the function object.\n\nIt is also possible to create anonymous functions (functions not bound\nto a name), for immediate use in expressions. This uses lambda\nexpressions, described in section *Lambdas*. Note that the lambda\nexpression is merely a shorthand for a simplified function definition;\na function defined in a ""def"" statement can be passed around or\nassigned to another name just like a function defined by a lambda\nexpression. The ""def"" form is actually more powerful since it\nallows the execution of multiple statements and annotations.\n\n**Programmer\'s note:** Functions are first-class objects. A ""def""\nstatement executed inside a function definition defines a local\nfunction that can be returned or passed around. Free variables used\nin the nested function can access the local variables of the function\ncontaining the def. See section *Naming and binding* for details.\n\nSee also: **PEP 3107** - Function Annotations\n\n The original specification for function annotations.\n',
+ 'formatstrings': u'\nFormat String Syntax\n********************\n\nThe "str.format()" method and the "Formatter" class share the same\nsyntax for format strings (although in the case of "Formatter",\nsubclasses can define their own format string syntax).\n\nFormat strings contain "replacement fields" surrounded by curly braces\n"{}". Anything that is not contained in braces is considered literal\ntext, which is copied unchanged to the output. If you need to include\na brace character in the literal text, it can be escaped by doubling:\n"{{" and "}}".\n\nThe grammar for a replacement field is as follows:\n\n replacement_field ::= "{" [field_name] ["!" conversion] [":" format_spec] "}"\n field_name ::= arg_name ("." attribute_name | "[" element_index "]")*\n arg_name ::= [identifier | integer]\n attribute_name ::= identifier\n element_index ::= integer | index_string\n index_string ::= <any source character except "]"> +\n conversion ::= "r" | "s" | "a"\n format_spec ::= <described in the next section>\n\nIn less formal terms, the replacement field can start with a\n*field_name* that specifies the object whose value is to be formatted\nand inserted into the output instead of the replacement field. The\n*field_name* is optionally followed by a *conversion* field, which is\npreceded by an exclamation point "\'!\'", and a *format_spec*, which is\npreceded by a colon "\':\'". These specify a non-default format for the\nreplacement value.\n\nSee also the *Format Specification Mini-Language* section.\n\nThe *field_name* itself begins with an *arg_name* that is either a\nnumber or a keyword. If it\'s a number, it refers to a positional\nargument, and if it\'s a keyword, it refers to a named keyword\nargument. If the numerical arg_names in a format string are 0, 1, 2,\n... in sequence, they can all be omitted (not just some) and the\nnumbers 0, 1, 2, ... will be automatically inserted in that order.\nBecause *arg_name* is not quote-delimited, it is not possible to\nspecify arbitrary dictionary keys (e.g., the strings "\'10\'" or\n"\':-]\'") within a format string. The *arg_name* can be followed by any\nnumber of index or attribute expressions. An expression of the form\n"\'.name\'" selects the named attribute using "getattr()", while an\nexpression of the form "\'[index]\'" does an index lookup using\n"__getitem__()".\n\nChanged in version 3.1: The positional argument specifiers can be\nomitted, so "\'{} {}\'" is equivalent to "\'{0} {1}\'".\n\nSome simple format string examples:\n\n "First, thou shalt count to {0}" # References first positional argument\n "Bring me a {}" # Implicitly references the first positional argument\n "From {} to {}" # Same as "From {0} to {1}"\n "My quest is {name}" # References keyword argument \'name\'\n "Weight in tons {0.weight}" # \'weight\' attribute of first positional arg\n "Units destroyed: {players[0]}" # First element of keyword argument \'players\'.\n\nThe *conversion* field causes a type coercion before formatting.\nNormally, the job of formatting a value is done by the "__format__()"\nmethod of the value itself. However, in some cases it is desirable to\nforce a type to be formatted as a string, overriding its own\ndefinition of formatting. By converting the value to a string before\ncalling "__format__()", the normal formatting logic is bypassed.\n\nThree conversion flags are currently supported: "\'!s\'" which calls\n"str()" on the value, "\'!r\'" which calls "repr()" and "\'!a\'" which\ncalls "ascii()".\n\nSome examples:\n\n "Harold\'s a clever {0!s}" # Calls str() on the argument first\n "Bring out the holy {name!r}" # Calls repr() on the argument first\n "More {!a}" # Calls ascii() on the argument first\n\nThe *format_spec* field contains a specification of how the value\nshould be presented, including such details as field width, alignment,\npadding, decimal precision and so on. Each value type can define its\nown "formatting mini-language" or interpretation of the *format_spec*.\n\nMost built-in types support a common formatting mini-language, which\nis described in the next section.\n\nA *format_spec* field can also include nested replacement fields\nwithin it. These nested replacement fields may contain a field name,\nconversion flag and format specification, but deeper nesting is not\nallowed. The replacement fields within the format_spec are\nsubstituted before the *format_spec* string is interpreted. This\nallows the formatting of a value to be dynamically specified.\n\nSee the *Format examples* section for some examples.\n\n\nFormat Specification Mini-Language\n==================================\n\n"Format specifications" are used within replacement fields contained\nwithin a format string to define how individual values are presented\n(see *Format String Syntax*). They can also be passed directly to the\nbuilt-in "format()" function. Each formattable type may define how\nthe format specification is to be interpreted.\n\nMost built-in types implement the following options for format\nspecifications, although some of the formatting options are only\nsupported by the numeric types.\n\nA general convention is that an empty format string ("""") produces\nthe same result as if you had called "str()" on the value. A non-empty\nformat string typically modifies the result.\n\nThe general form of a *standard format specifier* is:\n\n format_spec ::= [[fill]align][sign][#][0][width][,][.precision][type]\n fill ::= <any character>\n align ::= "<" | ">" | "=" | "^"\n sign ::= "+" | "-" | " "\n width ::= integer\n precision ::= integer\n type ::= "b" | "c" | "d" | "e" | "E" | "f" | "F" | "g" | "G" | "n" | "o" | "s" | "x" | "X" | "%"\n\nIf a valid *align* value is specified, it can be preceded by a *fill*\ncharacter that can be any character and defaults to a space if\nomitted. It is not possible to use a literal curly brace (""{"" or\n""}"") as the *fill* character when using the "str.format()" method.\nHowever, it is possible to insert a curly brace with a nested\nreplacement field. This limitation doesn\'t affect the "format()"\nfunction.\n\nThe meaning of the various alignment options is as follows:\n\n +-----------+------------------------------------------------------------+\n | Option | Meaning |\n +===========+============================================================+\n | "\'<\'" | Forces the field to be left-aligned within the available |\n | | space (this is the default for most objects). |\n +-----------+------------------------------------------------------------+\n | "\'>\'" | Forces the field to be right-aligned within the available |\n | | space (this is the default for numbers). |\n +-----------+------------------------------------------------------------+\n | "\'=\'" | Forces the padding to be placed after the sign (if any) |\n | | but before the digits. This is used for printing fields |\n | | in the form \'+000000120\'. This alignment option is only |\n | | valid for numeric types. It becomes the default when \'0\' |\n | | immediately precedes the field width. |\n +-----------+------------------------------------------------------------+\n | "\'^\'" | Forces the field to be centered within the available |\n | | space. |\n +-----------+------------------------------------------------------------+\n\nNote that unless a minimum field width is defined, the field width\nwill always be the same size as the data to fill it, so that the\nalignment option has no meaning in this case.\n\nThe *sign* option is only valid for number types, and can be one of\nthe following:\n\n +-----------+------------------------------------------------------------+\n | Option | Meaning |\n +===========+============================================================+\n | "\'+\'" | indicates that a sign should be used for both positive as |\n | | well as negative numbers. |\n +-----------+------------------------------------------------------------+\n | "\'-\'" | indicates that a sign should be used only for negative |\n | | numbers (this is the default behavior). |\n +-----------+------------------------------------------------------------+\n | space | indicates that a leading space should be used on positive |\n | | numbers, and a minus sign on negative numbers. |\n +-----------+------------------------------------------------------------+\n\nThe "\'#\'" option causes the "alternate form" to be used for the\nconversion. The alternate form is defined differently for different\ntypes. This option is only valid for integer, float, complex and\nDecimal types. For integers, when binary, octal, or hexadecimal output\nis used, this option adds the prefix respective "\'0b\'", "\'0o\'", or\n"\'0x\'" to the output value. For floats, complex and Decimal the\nalternate form causes the result of the conversion to always contain a\ndecimal-point character, even if no digits follow it. Normally, a\ndecimal-point character appears in the result of these conversions\nonly if a digit follows it. In addition, for "\'g\'" and "\'G\'"\nconversions, trailing zeros are not removed from the result.\n\nThe "\',\'" option signals the use of a comma for a thousands separator.\nFor a locale aware separator, use the "\'n\'" integer presentation type\ninstead.\n\nChanged in version 3.1: Added the "\',\'" option (see also **PEP 378**).\n\n*width* is a decimal integer defining the minimum field width. If not\nspecified, then the field width will be determined by the content.\n\nWhen no explicit alignment is given, preceding the *width* field by a\nzero ("\'0\'") character enables sign-aware zero-padding for numeric\ntypes. This is equivalent to a *fill* character of "\'0\'" with an\n*alignment* type of "\'=\'".\n\nThe *precision* is a decimal number indicating how many digits should\nbe displayed after the decimal point for a floating point value\nformatted with "\'f\'" and "\'F\'", or before and after the decimal point\nfor a floating point value formatted with "\'g\'" or "\'G\'". For non-\nnumber types the field indicates the maximum field size - in other\nwords, how many characters will be used from the field content. The\n*precision* is not allowed for integer values.\n\nFinally, the *type* determines how the data should be presented.\n\nThe available string presentation types are:\n\n +-----------+------------------------------------------------------------+\n | Type | Meaning |\n +===========+============================================================+\n | "\'s\'" | String format. This is the default type for strings and |\n | | may be omitted. |\n +-----------+------------------------------------------------------------+\n | None | The same as "\'s\'". |\n +-----------+------------------------------------------------------------+\n\nThe available integer presentation types are:\n\n +-----------+------------------------------------------------------------+\n | Type | Meaning |\n +===========+============================================================+\n | "\'b\'" | Binary format. Outputs the number in base 2. |\n +-----------+------------------------------------------------------------+\n | "\'c\'" | Character. Converts the integer to the corresponding |\n | | unicode character before printing. |\n +-----------+------------------------------------------------------------+\n | "\'d\'" | Decimal Integer. Outputs the number in base 10. |\n +-----------+------------------------------------------------------------+\n | "\'o\'" | Octal format. Outputs the number in base 8. |\n +-----------+------------------------------------------------------------+\n | "\'x\'" | Hex format. Outputs the number in base 16, using lower- |\n | | case letters for the digits above 9. |\n +-----------+------------------------------------------------------------+\n | "\'X\'" | Hex format. Outputs the number in base 16, using upper- |\n | | case letters for the digits above 9. |\n +-----------+------------------------------------------------------------+\n | "\'n\'" | Number. This is the same as "\'d\'", except that it uses the |\n | | current locale setting to insert the appropriate number |\n | | separator characters. |\n +-----------+------------------------------------------------------------+\n | None | The same as "\'d\'". |\n +-----------+------------------------------------------------------------+\n\nIn addition to the above presentation types, integers can be formatted\nwith the floating point presentation types listed below (except "\'n\'"\nand None). When doing so, "float()" is used to convert the integer to\na floating point number before formatting.\n\nThe available presentation types for floating point and decimal values\nare:\n\n +-----------+------------------------------------------------------------+\n | Type | Meaning |\n +===========+============================================================+\n | "\'e\'" | Exponent notation. Prints the number in scientific |\n | | notation using the letter \'e\' to indicate the exponent. |\n | | The default precision is "6". |\n +-----------+------------------------------------------------------------+\n | "\'E\'" | Exponent notation. Same as "\'e\'" except it uses an upper |\n | | case \'E\' as the separator character. |\n +-----------+------------------------------------------------------------+\n | "\'f\'" | Fixed point. Displays the number as a fixed-point number. |\n | | The default precision is "6". |\n +-----------+------------------------------------------------------------+\n | "\'F\'" | Fixed point. Same as "\'f\'", but converts "nan" to "NAN" |\n | | and "inf" to "INF". |\n +-----------+------------------------------------------------------------+\n | "\'g\'" | General format. For a given precision "p >= 1", this |\n | | rounds the number to "p" significant digits and then |\n | | formats the result in either fixed-point format or in |\n | | scientific notation, depending on its magnitude. The |\n | | precise rules are as follows: suppose that the result |\n | | formatted with presentation type "\'e\'" and precision "p-1" |\n | | would have exponent "exp". Then if "-4 <= exp < p", the |\n | | number is formatted with presentation type "\'f\'" and |\n | | precision "p-1-exp". Otherwise, the number is formatted |\n | | with presentation type "\'e\'" and precision "p-1". In both |\n | | cases insignificant trailing zeros are removed from the |\n | | significand, and the decimal point is also removed if |\n | | there are no remaining digits following it. Positive and |\n | | negative infinity, positive and negative zero, and nans, |\n | | are formatted as "inf", "-inf", "0", "-0" and "nan" |\n | | respectively, regardless of the precision. A precision of |\n | | "0" is treated as equivalent to a precision of "1". The |\n | | default precision is "6". |\n +-----------+------------------------------------------------------------+\n | "\'G\'" | General format. Same as "\'g\'" except switches to "\'E\'" if |\n | | the number gets too large. The representations of infinity |\n | | and NaN are uppercased, too. |\n +-----------+------------------------------------------------------------+\n | "\'n\'" | Number. This is the same as "\'g\'", except that it uses the |\n | | current locale setting to insert the appropriate number |\n | | separator characters. |\n +-----------+------------------------------------------------------------+\n | "\'%\'" | Percentage. Multiplies the number by 100 and displays in |\n | | fixed ("\'f\'") format, followed by a percent sign. |\n +-----------+------------------------------------------------------------+\n | None | Similar to "\'g\'", except that fixed-point notation, when |\n | | used, has at least one digit past the decimal point. The |\n | | default precision is as high as needed to represent the |\n | | particular value. The overall effect is to match the |\n | | output of "str()" as altered by the other format |\n | | modifiers. |\n +-----------+------------------------------------------------------------+\n\n\nFormat examples\n===============\n\nThis section contains examples of the "str.format()" syntax and\ncomparison with the old "%"-formatting.\n\nIn most of the cases the syntax is similar to the old "%"-formatting,\nwith the addition of the "{}" and with ":" used instead of "%". For\nexample, "\'%03.2f\'" can be translated to "\'{:03.2f}\'".\n\nThe new format syntax also supports new and different options, shown\nin the follow examples.\n\nAccessing arguments by position:\n\n >>> \'{0}, {1}, {2}\'.format(\'a\', \'b\', \'c\')\n \'a, b, c\'\n >>> \'{}, {}, {}\'.format(\'a\', \'b\', \'c\') # 3.1+ only\n \'a, b, c\'\n >>> \'{2}, {1}, {0}\'.format(\'a\', \'b\', \'c\')\n \'c, b, a\'\n >>> \'{2}, {1}, {0}\'.format(*\'abc\') # unpacking argument sequence\n \'c, b, a\'\n >>> \'{0}{1}{0}\'.format(\'abra\', \'cad\') # arguments\' indices can be repeated\n \'abracadabra\'\n\nAccessing arguments by name:\n\n >>> \'Coordinates: {latitude}, {longitude}\'.format(latitude=\'37.24N\', longitude=\'-115.81W\')\n \'Coordinates: 37.24N, -115.81W\'\n >>> coord = {\'latitude\': \'37.24N\', \'longitude\': \'-115.81W\'}\n >>> \'Coordinates: {latitude}, {longitude}\'.format(**coord)\n \'Coordinates: 37.24N, -115.81W\'\n\nAccessing arguments\' attributes:\n\n >>> c = 3-5j\n >>> (\'The complex number {0} is formed from the real part {0.real} \'\n ... \'and the imaginary part {0.imag}.\').format(c)\n \'The complex number (3-5j) is formed from the real part 3.0 and the imaginary part -5.0.\'\n >>> class Point:\n ... def __init__(self, x, y):\n ... self.x, self.y = x, y\n ... def __str__(self):\n ... return \'Point({self.x}, {self.y})\'.format(self=self)\n ...\n >>> str(Point(4, 2))\n \'Point(4, 2)\'\n\nAccessing arguments\' items:\n\n >>> coord = (3, 5)\n >>> \'X: {0[0]}; Y: {0[1]}\'.format(coord)\n \'X: 3; Y: 5\'\n\nReplacing "%s" and "%r":\n\n >>> "repr() shows quotes: {!r}; str() doesn\'t: {!s}".format(\'test1\', \'test2\')\n "repr() shows quotes: \'test1\'; str() doesn\'t: test2"\n\nAligning the text and specifying a width:\n\n >>> \'{:<30}\'.format(\'left aligned\')\n \'left aligned \'\n >>> \'{:>30}\'.format(\'right aligned\')\n \' right aligned\'\n >>> \'{:^30}\'.format(\'centered\')\n \' centered \'\n >>> \'{:*^30}\'.format(\'centered\') # use \'*\' as a fill char\n \'***********centered***********\'\n\nReplacing "%+f", "%-f", and "% f" and specifying a sign:\n\n >>> \'{:+f}; {:+f}\'.format(3.14, -3.14) # show it always\n \'+3.140000; -3.140000\'\n >>> \'{: f}; {: f}\'.format(3.14, -3.14) # show a space for positive numbers\n \' 3.140000; -3.140000\'\n >>> \'{:-f}; {:-f}\'.format(3.14, -3.14) # show only the minus -- same as \'{:f}; {:f}\'\n \'3.140000; -3.140000\'\n\nReplacing "%x" and "%o" and converting the value to different bases:\n\n >>> # format also supports binary numbers\n >>> "int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}".format(42)\n \'int: 42; hex: 2a; oct: 52; bin: 101010\'\n >>> # with 0x, 0o, or 0b as prefix:\n >>> "int: {0:d}; hex: {0:#x}; oct: {0:#o}; bin: {0:#b}".format(42)\n \'int: 42; hex: 0x2a; oct: 0o52; bin: 0b101010\'\n\nUsing the comma as a thousands separator:\n\n >>> \'{:,}\'.format(1234567890)\n \'1,234,567,890\'\n\nExpressing a percentage:\n\n >>> points = 19\n >>> total = 22\n >>> \'Correct answers: {:.2%}\'.format(points/total)\n \'Correct answers: 86.36%\'\n\nUsing type-specific formatting:\n\n >>> import datetime\n >>> d = datetime.datetime(2010, 7, 4, 12, 15, 58)\n >>> \'{:%Y-%m-%d %H:%M:%S}\'.format(d)\n \'2010-07-04 12:15:58\'\n\nNesting arguments and more complex examples:\n\n >>> for align, text in zip(\'<^>\', [\'left\', \'center\', \'right\']):\n ... \'{0:{fill}{align}16}\'.format(text, fill=align, align=align)\n ...\n \'left<<<<<<<<<<<<\'\n \'^^^^^center^^^^^\'\n \'>>>>>>>>>>>right\'\n >>>\n >>> octets = [192, 168, 0, 1]\n >>> \'{:02X}{:02X}{:02X}{:02X}\'.format(*octets)\n \'C0A80001\'\n >>> int(_, 16)\n 3232235521\n >>>\n >>> width = 5\n >>> for num in range(5,12): #doctest: +NORMALIZE_WHITESPACE\n ... for base in \'dXob\':\n ... print(\'{0:{width}{base}}\'.format(num, base=base, width=width), end=\' \')\n ... print()\n ...\n 5 5 5 101\n 6 6 6 110\n 7 7 7 111\n 8 8 10 1000\n 9 9 11 1001\n 10 A 12 1010\n 11 B 13 1011\n',
+ 'function': u'\nFunction definitions\n********************\n\nA function definition defines a user-defined function object (see\nsection *The standard type hierarchy*):\n\n funcdef ::= [decorators] "def" funcname "(" [parameter_list] ")" ["->" expression] ":" suite\n decorators ::= decorator+\n decorator ::= "@" dotted_name ["(" [argument_list [","]] ")"] NEWLINE\n dotted_name ::= identifier ("." identifier)*\n parameter_list ::= (defparameter ",")*\n | "*" [parameter] ("," defparameter)* ["," "**" parameter]\n | "**" parameter\n | defparameter [","] )\n parameter ::= identifier [":" expression]\n defparameter ::= parameter ["=" expression]\n funcname ::= identifier\n\nA function definition is an executable statement. Its execution binds\nthe function name in the current local namespace to a function object\n(a wrapper around the executable code for the function). This\nfunction object contains a reference to the current global namespace\nas the global namespace to be used when the function is called.\n\nThe function definition does not execute the function body; this gets\nexecuted only when the function is called. [3]\n\nA function definition may be wrapped by one or more *decorator*\nexpressions. Decorator expressions are evaluated when the function is\ndefined, in the scope that contains the function definition. The\nresult must be a callable, which is invoked with the function object\nas the only argument. The returned value is bound to the function name\ninstead of the function object. Multiple decorators are applied in\nnested fashion. For example, the following code\n\n @f1(arg)\n @f2\n def func(): pass\n\nis equivalent to\n\n def func(): pass\n func = f1(arg)(f2(func))\n\nWhen one or more *parameters* have the form *parameter* "="\n*expression*, the function is said to have "default parameter values."\nFor a parameter with a default value, the corresponding *argument* may\nbe omitted from a call, in which case the parameter\'s default value is\nsubstituted. If a parameter has a default value, all following\nparameters up until the ""*"" must also have a default value --- this\nis a syntactic restriction that is not expressed by the grammar.\n\n**Default parameter values are evaluated from left to right when the\nfunction definition is executed.** This means that the expression is\nevaluated once, when the function is defined, and that the same "pre-\ncomputed" value is used for each call. This is especially important\nto understand when a default parameter is a mutable object, such as a\nlist or a dictionary: if the function modifies the object (e.g. by\nappending an item to a list), the default value is in effect modified.\nThis is generally not what was intended. A way around this is to use\n"None" as the default, and explicitly test for it in the body of the\nfunction, e.g.:\n\n def whats_on_the_telly(penguin=None):\n if penguin is None:\n penguin = []\n penguin.append("property of the zoo")\n return penguin\n\nFunction call semantics are described in more detail in section\n*Calls*. A function call always assigns values to all parameters\nmentioned in the parameter list, either from position arguments, from\nkeyword arguments, or from default values. If the form\n""*identifier"" is present, it is initialized to a tuple receiving any\nexcess positional parameters, defaulting to the empty tuple. If the\nform ""**identifier"" is present, it is initialized to a new\ndictionary receiving any excess keyword arguments, defaulting to a new\nempty dictionary. Parameters after ""*"" or ""*identifier"" are\nkeyword-only parameters and may only be passed used keyword arguments.\n\nParameters may have annotations of the form "": expression"" following\nthe parameter name. Any parameter may have an annotation even those\nof the form "*identifier" or "**identifier". Functions may have\n"return" annotation of the form ""-> expression"" after the parameter\nlist. These annotations can be any valid Python expression and are\nevaluated when the function definition is executed. Annotations may\nbe evaluated in a different order than they appear in the source code.\nThe presence of annotations does not change the semantics of a\nfunction. The annotation values are available as values of a\ndictionary keyed by the parameters\' names in the "__annotations__"\nattribute of the function object.\n\nIt is also possible to create anonymous functions (functions not bound\nto a name), for immediate use in expressions. This uses lambda\nexpressions, described in section *Lambdas*. Note that the lambda\nexpression is merely a shorthand for a simplified function definition;\na function defined in a ""def"" statement can be passed around or\nassigned to another name just like a function defined by a lambda\nexpression. The ""def"" form is actually more powerful since it\nallows the execution of multiple statements and annotations.\n\n**Programmer\'s note:** Functions are first-class objects. A ""def""\nstatement executed inside a function definition defines a local\nfunction that can be returned or passed around. Free variables used\nin the nested function can access the local variables of the function\ncontaining the def. See section *Naming and binding* for details.\n\nSee also: **PEP 3107** - Function Annotations\n\n The original specification for function annotations.\n',
'global': u'\nThe "global" statement\n**********************\n\n global_stmt ::= "global" identifier ("," identifier)*\n\nThe "global" statement is a declaration which holds for the entire\ncurrent code block. It means that the listed identifiers are to be\ninterpreted as globals. It would be impossible to assign to a global\nvariable without "global", although free variables may refer to\nglobals without being declared global.\n\nNames listed in a "global" statement must not be used in the same code\nblock textually preceding that "global" statement.\n\nNames listed in a "global" statement must not be defined as formal\nparameters or in a "for" loop control target, "class" definition,\nfunction definition, or "import" statement.\n\n**CPython implementation detail:** The current implementation does not\nenforce the two restrictions, but programs should not abuse this\nfreedom, as future implementations may enforce them or silently change\nthe meaning of the program.\n\n**Programmer\'s note:** the "global" is a directive to the parser. It\napplies only to code parsed at the same time as the "global"\nstatement. In particular, a "global" statement contained in a string\nor code object supplied to the built-in "exec()" function does not\naffect the code block *containing* the function call, and code\ncontained in such a string is unaffected by "global" statements in the\ncode containing the function call. The same applies to the "eval()"\nand "compile()" functions.\n',
'id-classes': u'\nReserved classes of identifiers\n*******************************\n\nCertain classes of identifiers (besides keywords) have special\nmeanings. These classes are identified by the patterns of leading and\ntrailing underscore characters:\n\n"_*"\n Not imported by "from module import *". The special identifier "_"\n is used in the interactive interpreter to store the result of the\n last evaluation; it is stored in the "builtins" module. When not\n in interactive mode, "_" has no special meaning and is not defined.\n See section *The import statement*.\n\n Note: The name "_" is often used in conjunction with\n internationalization; refer to the documentation for the\n "gettext" module for more information on this convention.\n\n"__*__"\n System-defined names. These names are defined by the interpreter\n and its implementation (including the standard library). Current\n system names are discussed in the *Special method names* section\n and elsewhere. More will likely be defined in future versions of\n Python. *Any* use of "__*__" names, in any context, that does not\n follow explicitly documented use, is subject to breakage without\n warning.\n\n"__*"\n Class-private names. Names in this category, when used within the\n context of a class definition, are re-written to use a mangled form\n to help avoid name clashes between "private" attributes of base and\n derived classes. See section *Identifiers (Names)*.\n',
- 'identifiers': u'\nIdentifiers and keywords\n************************\n\nIdentifiers (also referred to as *names*) are described by the\nfollowing lexical definitions.\n\nThe syntax of identifiers in Python is based on the Unicode standard\nannex UAX-31, with elaboration and changes as defined below; see also\n**PEP 3131** for further details.\n\nWithin the ASCII range (U+0001..U+007F), the valid characters for\nidentifiers are the same as in Python 2.x: the uppercase and lowercase\nletters "A" through "Z", the underscore "_" and, except for the first\ncharacter, the digits "0" through "9".\n\nPython 3.0 introduces additional characters from outside the ASCII\nrange (see **PEP 3131**). For these characters, the classification\nuses the version of the Unicode Character Database as included in the\n"unicodedata" module.\n\nIdentifiers are unlimited in length. Case is significant.\n\n identifier ::= xid_start xid_continue*\n id_start ::= <all characters in general categories Lu, Ll, Lt, Lm, Lo, Nl, the underscore, and characters with the Other_ID_Start property>\n id_continue ::= <all characters in id_start, plus characters in the categories Mn, Mc, Nd, Pc and others with the Other_ID_Continue property>\n xid_start ::= <all characters in id_start whose NFKC normalization is in "id_start xid_continue*">\n xid_continue ::= <all characters in id_continue whose NFKC normalization is in "id_continue*">\n\nThe Unicode category codes mentioned above stand for:\n\n* *Lu* - uppercase letters\n\n* *Ll* - lowercase letters\n\n* *Lt* - titlecase letters\n\n* *Lm* - modifier letters\n\n* *Lo* - other letters\n\n* *Nl* - letter numbers\n\n* *Mn* - nonspacing marks\n\n* *Mc* - spacing combining marks\n\n* *Nd* - decimal numbers\n\n* *Pc* - connector punctuations\n\n* *Other_ID_Start* - explicit list of characters in PropList.txt to\n support backwards compatibility\n\n* *Other_ID_Continue* - likewise\n\nAll identifiers are converted into the normal form NFKC while parsing;\ncomparison of identifiers is based on NFKC.\n\nA non-normative HTML file listing all valid identifier characters for\nUnicode 4.1 can be found at http://www.dcl.hpi.uni-\npotsdam.de/home/loewis/table-3131.html.\n\n\nKeywords\n========\n\nThe following identifiers are used as reserved words, or *keywords* of\nthe language, and cannot be used as ordinary identifiers. They must\nbe spelled exactly as written here:\n\n False class finally is return\n None continue for lambda try\n True def from nonlocal while\n and del global not with\n as elif if or yield\n assert else import pass\n break except in raise\n\n\nReserved classes of identifiers\n===============================\n\nCertain classes of identifiers (besides keywords) have special\nmeanings. These classes are identified by the patterns of leading and\ntrailing underscore characters:\n\n"_*"\n Not imported by "from module import *". The special identifier "_"\n is used in the interactive interpreter to store the result of the\n last evaluation; it is stored in the "builtins" module. When not\n in interactive mode, "_" has no special meaning and is not defined.\n See section *The import statement*.\n\n Note: The name "_" is often used in conjunction with\n internationalization; refer to the documentation for the\n "gettext" module for more information on this convention.\n\n"__*__"\n System-defined names. These names are defined by the interpreter\n and its implementation (including the standard library). Current\n system names are discussed in the *Special method names* section\n and elsewhere. More will likely be defined in future versions of\n Python. *Any* use of "__*__" names, in any context, that does not\n follow explicitly documented use, is subject to breakage without\n warning.\n\n"__*"\n Class-private names. Names in this category, when used within the\n context of a class definition, are re-written to use a mangled form\n to help avoid name clashes between "private" attributes of base and\n derived classes. See section *Identifiers (Names)*.\n',
+ 'identifiers': u'\nIdentifiers and keywords\n************************\n\nIdentifiers (also referred to as *names*) are described by the\nfollowing lexical definitions.\n\nThe syntax of identifiers in Python is based on the Unicode standard\nannex UAX-31, with elaboration and changes as defined below; see also\n**PEP 3131** for further details.\n\nWithin the ASCII range (U+0001..U+007F), the valid characters for\nidentifiers are the same as in Python 2.x: the uppercase and lowercase\nletters "A" through "Z", the underscore "_" and, except for the first\ncharacter, the digits "0" through "9".\n\nPython 3.0 introduces additional characters from outside the ASCII\nrange (see **PEP 3131**). For these characters, the classification\nuses the version of the Unicode Character Database as included in the\n"unicodedata" module.\n\nIdentifiers are unlimited in length. Case is significant.\n\n identifier ::= xid_start xid_continue*\n id_start ::= <all characters in general categories Lu, Ll, Lt, Lm, Lo, Nl, the underscore, and characters with the Other_ID_Start property>\n id_continue ::= <all characters in id_start, plus characters in the categories Mn, Mc, Nd, Pc and others with the Other_ID_Continue property>\n xid_start ::= <all characters in id_start whose NFKC normalization is in "id_start xid_continue*">\n xid_continue ::= <all characters in id_continue whose NFKC normalization is in "id_continue*">\n\nThe Unicode category codes mentioned above stand for:\n\n* *Lu* - uppercase letters\n\n* *Ll* - lowercase letters\n\n* *Lt* - titlecase letters\n\n* *Lm* - modifier letters\n\n* *Lo* - other letters\n\n* *Nl* - letter numbers\n\n* *Mn* - nonspacing marks\n\n* *Mc* - spacing combining marks\n\n* *Nd* - decimal numbers\n\n* *Pc* - connector punctuations\n\n* *Other_ID_Start* - explicit list of characters in PropList.txt to\n support backwards compatibility\n\n* *Other_ID_Continue* - likewise\n\nAll identifiers are converted into the normal form NFKC while parsing;\ncomparison of identifiers is based on NFKC.\n\nA non-normative HTML file listing all valid identifier characters for\nUnicode 4.1 can be found at https://www.dcl.hpi.uni-\npotsdam.de/home/loewis/table-3131.html.\n\n\nKeywords\n========\n\nThe following identifiers are used as reserved words, or *keywords* of\nthe language, and cannot be used as ordinary identifiers. They must\nbe spelled exactly as written here:\n\n False class finally is return\n None continue for lambda try\n True def from nonlocal while\n and del global not with\n as elif if or yield\n assert else import pass\n break except in raise\n\n\nReserved classes of identifiers\n===============================\n\nCertain classes of identifiers (besides keywords) have special\nmeanings. These classes are identified by the patterns of leading and\ntrailing underscore characters:\n\n"_*"\n Not imported by "from module import *". The special identifier "_"\n is used in the interactive interpreter to store the result of the\n last evaluation; it is stored in the "builtins" module. When not\n in interactive mode, "_" has no special meaning and is not defined.\n See section *The import statement*.\n\n Note: The name "_" is often used in conjunction with\n internationalization; refer to the documentation for the\n "gettext" module for more information on this convention.\n\n"__*__"\n System-defined names. These names are defined by the interpreter\n and its implementation (including the standard library). Current\n system names are discussed in the *Special method names* section\n and elsewhere. More will likely be defined in future versions of\n Python. *Any* use of "__*__" names, in any context, that does not\n follow explicitly documented use, is subject to breakage without\n warning.\n\n"__*"\n Class-private names. Names in this category, when used within the\n context of a class definition, are re-written to use a mangled form\n to help avoid name clashes between "private" attributes of base and\n derived classes. See section *Identifiers (Names)*.\n',
'if': u'\nThe "if" statement\n******************\n\nThe "if" statement is used for conditional execution:\n\n if_stmt ::= "if" expression ":" suite\n ( "elif" expression ":" suite )*\n ["else" ":" suite]\n\nIt selects exactly one of the suites by evaluating the expressions one\nby one until one is found to be true (see section *Boolean operations*\nfor the definition of true and false); then that suite is executed\n(and no other part of the "if" statement is executed or evaluated).\nIf all expressions are false, the suite of the "else" clause, if\npresent, is executed.\n',
'imaginary': u'\nImaginary literals\n******************\n\nImaginary literals are described by the following lexical definitions:\n\n imagnumber ::= (floatnumber | intpart) ("j" | "J")\n\nAn imaginary literal yields a complex number with a real part of 0.0.\nComplex numbers are represented as a pair of floating point numbers\nand have the same restrictions on their range. To create a complex\nnumber with a nonzero real part, add a floating point number to it,\ne.g., "(3+4j)". Some examples of imaginary literals:\n\n 3.14j 10.j 10j .001j 1e100j 3.14e-10j\n',
- 'import': u'\nThe "import" statement\n**********************\n\n import_stmt ::= "import" module ["as" name] ( "," module ["as" name] )*\n | "from" relative_module "import" identifier ["as" name]\n ( "," identifier ["as" name] )*\n | "from" relative_module "import" "(" identifier ["as" name]\n ( "," identifier ["as" name] )* [","] ")"\n | "from" module "import" "*"\n module ::= (identifier ".")* identifier\n relative_module ::= "."* module | "."+\n name ::= identifier\n\nThe basic import statement (no "from" clause) is executed in two\nsteps:\n\n1. find a module, loading and initializing it if necessary\n\n2. define a name or names in the local namespace for the scope\n where the "import" statement occurs.\n\nWhen the statement contains multiple clauses (separated by commas) the\ntwo steps are carried out separately for each clause, just as though\nthe clauses had been separated out into individiual import statements.\n\nThe details of the first step, finding and loading modules are\ndescribed in greater detail in the section on the *import system*,\nwhich also describes the various types of packages and modules that\ncan be imported, as well as all the hooks that can be used to\ncustomize the import system. Note that failures in this step may\nindicate either that the module could not be located, *or* that an\nerror occurred while initializing the module, which includes execution\nof the module\'s code.\n\nIf the requested module is retrieved successfully, it will be made\navailable in the local namespace in one of three ways:\n\n* If the module name is followed by "as", then the name following\n "as" is bound directly to the imported module.\n\n* If no other name is specified, and the module being imported is a\n top level module, the module\'s name is bound in the local namespace\n as a reference to the imported module\n\n* If the module being imported is *not* a top level module, then the\n name of the top level package that contains the module is bound in\n the local namespace as a reference to the top level package. The\n imported module must be accessed using its full qualified name\n rather than directly\n\nThe "from" form uses a slightly more complex process:\n\n1. find the module specified in the "from" clause, loading and\n initializing it if necessary;\n\n2. for each of the identifiers specified in the "import" clauses:\n\n 1. check if the imported module has an attribute by that name\n\n 2. if not, attempt to import a submodule with that name and then\n check the imported module again for that attribute\n\n 3. if the attribute is not found, "ImportError" is raised.\n\n 4. otherwise, a reference to that value is stored in the local\n namespace, using the name in the "as" clause if it is present,\n otherwise using the attribute name\n\nExamples:\n\n import foo # foo imported and bound locally\n import foo.bar.baz # foo.bar.baz imported, foo bound locally\n import foo.bar.baz as fbb # foo.bar.baz imported and bound as fbb\n from foo.bar import baz # foo.bar.baz imported and bound as baz\n from foo import attr # foo imported and foo.attr bound as attr\n\nIf the list of identifiers is replaced by a star ("\'*\'"), all public\nnames defined in the module are bound in the local namespace for the\nscope where the "import" statement occurs.\n\nThe *public names* defined by a module are determined by checking the\nmodule\'s namespace for a variable named "__all__"; if defined, it must\nbe a sequence of strings which are names defined or imported by that\nmodule. The names given in "__all__" are all considered public and\nare required to exist. If "__all__" is not defined, the set of public\nnames includes all names found in the module\'s namespace which do not\nbegin with an underscore character ("\'_\'"). "__all__" should contain\nthe entire public API. It is intended to avoid accidentally exporting\nitems that are not part of the API (such as library modules which were\nimported and used within the module).\n\nThe wild card form of import --- "from module import *" --- is only\nallowed at the module level. Attempting to use it in class or\nfunction definitions will raise a "SyntaxError".\n\nWhen specifying what module to import you do not have to specify the\nabsolute name of the module. When a module or package is contained\nwithin another package it is possible to make a relative import within\nthe same top package without having to mention the package name. By\nusing leading dots in the specified module or package after "from" you\ncan specify how high to traverse up the current package hierarchy\nwithout specifying exact names. One leading dot means the current\npackage where the module making the import exists. Two dots means up\none package level. Three dots is up two levels, etc. So if you execute\n"from . import mod" from a module in the "pkg" package then you will\nend up importing "pkg.mod". If you execute "from ..subpkg2 import mod"\nfrom within "pkg.subpkg1" you will import "pkg.subpkg2.mod". The\nspecification for relative imports is contained within **PEP 328**.\n\n"importlib.import_module()" is provided to support applications that\ndetermine dynamically the modules to be loaded.\n\n\nFuture statements\n=================\n\nA *future statement* is a directive to the compiler that a particular\nmodule should be compiled using syntax or semantics that will be\navailable in a specified future release of Python where the feature\nbecomes standard.\n\nThe future statement is intended to ease migration to future versions\nof Python that introduce incompatible changes to the language. It\nallows use of the new features on a per-module basis before the\nrelease in which the feature becomes standard.\n\n future_statement ::= "from" "__future__" "import" feature ["as" name]\n ("," feature ["as" name])*\n | "from" "__future__" "import" "(" feature ["as" name]\n ("," feature ["as" name])* [","] ")"\n feature ::= identifier\n name ::= identifier\n\nA future statement must appear near the top of the module. The only\nlines that can appear before a future statement are:\n\n* the module docstring (if any),\n\n* comments,\n\n* blank lines, and\n\n* other future statements.\n\nThe features recognized by Python 3.0 are "absolute_import",\n"division", "generators", "unicode_literals", "print_function",\n"nested_scopes" and "with_statement". They are all redundant because\nthey are always enabled, and only kept for backwards compatibility.\n\nA future statement is recognized and treated specially at compile\ntime: Changes to the semantics of core constructs are often\nimplemented by generating different code. It may even be the case\nthat a new feature introduces new incompatible syntax (such as a new\nreserved word), in which case the compiler may need to parse the\nmodule differently. Such decisions cannot be pushed off until\nruntime.\n\nFor any given release, the compiler knows which feature names have\nbeen defined, and raises a compile-time error if a future statement\ncontains a feature not known to it.\n\nThe direct runtime semantics are the same as for any import statement:\nthere is a standard module "__future__", described later, and it will\nbe imported in the usual way at the time the future statement is\nexecuted.\n\nThe interesting runtime semantics depend on the specific feature\nenabled by the future statement.\n\nNote that there is nothing special about the statement:\n\n import __future__ [as name]\n\nThat is not a future statement; it\'s an ordinary import statement with\nno special semantics or syntax restrictions.\n\nCode compiled by calls to the built-in functions "exec()" and\n"compile()" that occur in a module "M" containing a future statement\nwill, by default, use the new syntax or semantics associated with the\nfuture statement. This can be controlled by optional arguments to\n"compile()" --- see the documentation of that function for details.\n\nA future statement typed at an interactive interpreter prompt will\ntake effect for the rest of the interpreter session. If an\ninterpreter is started with the *-i* option, is passed a script name\nto execute, and the script includes a future statement, it will be in\neffect in the interactive session started after the script is\nexecuted.\n\nSee also: **PEP 236** - Back to the __future__\n\n The original proposal for the __future__ mechanism.\n',
+ 'import': u'\nThe "import" statement\n**********************\n\n import_stmt ::= "import" module ["as" name] ( "," module ["as" name] )*\n | "from" relative_module "import" identifier ["as" name]\n ( "," identifier ["as" name] )*\n | "from" relative_module "import" "(" identifier ["as" name]\n ( "," identifier ["as" name] )* [","] ")"\n | "from" module "import" "*"\n module ::= (identifier ".")* identifier\n relative_module ::= "."* module | "."+\n name ::= identifier\n\nThe basic import statement (no "from" clause) is executed in two\nsteps:\n\n1. find a module, loading and initializing it if necessary\n\n2. define a name or names in the local namespace for the scope\n where the "import" statement occurs.\n\nWhen the statement contains multiple clauses (separated by commas) the\ntwo steps are carried out separately for each clause, just as though\nthe clauses had been separated out into individual import statements.\n\nThe details of the first step, finding and loading modules are\ndescribed in greater detail in the section on the *import system*,\nwhich also describes the various types of packages and modules that\ncan be imported, as well as all the hooks that can be used to\ncustomize the import system. Note that failures in this step may\nindicate either that the module could not be located, *or* that an\nerror occurred while initializing the module, which includes execution\nof the module\'s code.\n\nIf the requested module is retrieved successfully, it will be made\navailable in the local namespace in one of three ways:\n\n* If the module name is followed by "as", then the name following\n "as" is bound directly to the imported module.\n\n* If no other name is specified, and the module being imported is a\n top level module, the module\'s name is bound in the local namespace\n as a reference to the imported module\n\n* If the module being imported is *not* a top level module, then the\n name of the top level package that contains the module is bound in\n the local namespace as a reference to the top level package. The\n imported module must be accessed using its full qualified name\n rather than directly\n\nThe "from" form uses a slightly more complex process:\n\n1. find the module specified in the "from" clause, loading and\n initializing it if necessary;\n\n2. for each of the identifiers specified in the "import" clauses:\n\n 1. check if the imported module has an attribute by that name\n\n 2. if not, attempt to import a submodule with that name and then\n check the imported module again for that attribute\n\n 3. if the attribute is not found, "ImportError" is raised.\n\n 4. otherwise, a reference to that value is stored in the local\n namespace, using the name in the "as" clause if it is present,\n otherwise using the attribute name\n\nExamples:\n\n import foo # foo imported and bound locally\n import foo.bar.baz # foo.bar.baz imported, foo bound locally\n import foo.bar.baz as fbb # foo.bar.baz imported and bound as fbb\n from foo.bar import baz # foo.bar.baz imported and bound as baz\n from foo import attr # foo imported and foo.attr bound as attr\n\nIf the list of identifiers is replaced by a star ("\'*\'"), all public\nnames defined in the module are bound in the local namespace for the\nscope where the "import" statement occurs.\n\nThe *public names* defined by a module are determined by checking the\nmodule\'s namespace for a variable named "__all__"; if defined, it must\nbe a sequence of strings which are names defined or imported by that\nmodule. The names given in "__all__" are all considered public and\nare required to exist. If "__all__" is not defined, the set of public\nnames includes all names found in the module\'s namespace which do not\nbegin with an underscore character ("\'_\'"). "__all__" should contain\nthe entire public API. It is intended to avoid accidentally exporting\nitems that are not part of the API (such as library modules which were\nimported and used within the module).\n\nThe wild card form of import --- "from module import *" --- is only\nallowed at the module level. Attempting to use it in class or\nfunction definitions will raise a "SyntaxError".\n\nWhen specifying what module to import you do not have to specify the\nabsolute name of the module. When a module or package is contained\nwithin another package it is possible to make a relative import within\nthe same top package without having to mention the package name. By\nusing leading dots in the specified module or package after "from" you\ncan specify how high to traverse up the current package hierarchy\nwithout specifying exact names. One leading dot means the current\npackage where the module making the import exists. Two dots means up\none package level. Three dots is up two levels, etc. So if you execute\n"from . import mod" from a module in the "pkg" package then you will\nend up importing "pkg.mod". If you execute "from ..subpkg2 import mod"\nfrom within "pkg.subpkg1" you will import "pkg.subpkg2.mod". The\nspecification for relative imports is contained within **PEP 328**.\n\n"importlib.import_module()" is provided to support applications that\ndetermine dynamically the modules to be loaded.\n\n\nFuture statements\n=================\n\nA *future statement* is a directive to the compiler that a particular\nmodule should be compiled using syntax or semantics that will be\navailable in a specified future release of Python where the feature\nbecomes standard.\n\nThe future statement is intended to ease migration to future versions\nof Python that introduce incompatible changes to the language. It\nallows use of the new features on a per-module basis before the\nrelease in which the feature becomes standard.\n\n future_statement ::= "from" "__future__" "import" feature ["as" name]\n ("," feature ["as" name])*\n | "from" "__future__" "import" "(" feature ["as" name]\n ("," feature ["as" name])* [","] ")"\n feature ::= identifier\n name ::= identifier\n\nA future statement must appear near the top of the module. The only\nlines that can appear before a future statement are:\n\n* the module docstring (if any),\n\n* comments,\n\n* blank lines, and\n\n* other future statements.\n\nThe features recognized by Python 3.0 are "absolute_import",\n"division", "generators", "unicode_literals", "print_function",\n"nested_scopes" and "with_statement". They are all redundant because\nthey are always enabled, and only kept for backwards compatibility.\n\nA future statement is recognized and treated specially at compile\ntime: Changes to the semantics of core constructs are often\nimplemented by generating different code. It may even be the case\nthat a new feature introduces new incompatible syntax (such as a new\nreserved word), in which case the compiler may need to parse the\nmodule differently. Such decisions cannot be pushed off until\nruntime.\n\nFor any given release, the compiler knows which feature names have\nbeen defined, and raises a compile-time error if a future statement\ncontains a feature not known to it.\n\nThe direct runtime semantics are the same as for any import statement:\nthere is a standard module "__future__", described later, and it will\nbe imported in the usual way at the time the future statement is\nexecuted.\n\nThe interesting runtime semantics depend on the specific feature\nenabled by the future statement.\n\nNote that there is nothing special about the statement:\n\n import __future__ [as name]\n\nThat is not a future statement; it\'s an ordinary import statement with\nno special semantics or syntax restrictions.\n\nCode compiled by calls to the built-in functions "exec()" and\n"compile()" that occur in a module "M" containing a future statement\nwill, by default, use the new syntax or semantics associated with the\nfuture statement. This can be controlled by optional arguments to\n"compile()" --- see the documentation of that function for details.\n\nA future statement typed at an interactive interpreter prompt will\ntake effect for the rest of the interpreter session. If an\ninterpreter is started with the *-i* option, is passed a script name\nto execute, and the script includes a future statement, it will be in\neffect in the interactive session started after the script is\nexecuted.\n\nSee also: **PEP 236** - Back to the __future__\n\n The original proposal for the __future__ mechanism.\n',
'in': u'\nMembership test operations\n**************************\n\nThe operators "in" and "not in" test for membership. "x in s"\nevaluates to true if *x* is a member of *s*, and false otherwise. "x\nnot in s" returns the negation of "x in s". All built-in sequences\nand set types support this as well as dictionary, for which "in" tests\nwhether the dictionary has a given key. For container types such as\nlist, tuple, set, frozenset, dict, or collections.deque, the\nexpression "x in y" is equivalent to "any(x is e or x == e for e in\ny)".\n\nFor the string and bytes types, "x in y" is true if and only if *x* is\na substring of *y*. An equivalent test is "y.find(x) != -1". Empty\nstrings are always considered to be a substring of any other string,\nso """ in "abc"" will return "True".\n\nFor user-defined classes which define the "__contains__()" method, "x\nin y" is true if and only if "y.__contains__(x)" is true.\n\nFor user-defined classes which do not define "__contains__()" but do\ndefine "__iter__()", "x in y" is true if some value "z" with "x == z"\nis produced while iterating over "y". If an exception is raised\nduring the iteration, it is as if "in" raised that exception.\n\nLastly, the old-style iteration protocol is tried: if a class defines\n"__getitem__()", "x in y" is true if and only if there is a non-\nnegative integer index *i* such that "x == y[i]", and all lower\ninteger indices do not raise "IndexError" exception. (If any other\nexception is raised, it is as if "in" raised that exception).\n\nThe operator "not in" is defined to have the inverse true value of\n"in".\n',
'integers': u'\nInteger literals\n****************\n\nInteger literals are described by the following lexical definitions:\n\n integer ::= decimalinteger | octinteger | hexinteger | bininteger\n decimalinteger ::= nonzerodigit digit* | "0"+\n nonzerodigit ::= "1"..."9"\n digit ::= "0"..."9"\n octinteger ::= "0" ("o" | "O") octdigit+\n hexinteger ::= "0" ("x" | "X") hexdigit+\n bininteger ::= "0" ("b" | "B") bindigit+\n octdigit ::= "0"..."7"\n hexdigit ::= digit | "a"..."f" | "A"..."F"\n bindigit ::= "0" | "1"\n\nThere is no limit for the length of integer literals apart from what\ncan be stored in available memory.\n\nNote that leading zeros in a non-zero decimal number are not allowed.\nThis is for disambiguation with C-style octal literals, which Python\nused before version 3.0.\n\nSome examples of integer literals:\n\n 7 2147483647 0o177 0b100110111\n 3 79228162514264337593543950336 0o377 0xdeadbeef\n',
'lambda': u'\nLambdas\n*******\n\n lambda_expr ::= "lambda" [parameter_list]: expression\n lambda_expr_nocond ::= "lambda" [parameter_list]: expression_nocond\n\nLambda expressions (sometimes called lambda forms) are used to create\nanonymous functions. The expression "lambda arguments: expression"\nyields a function object. The unnamed object behaves like a function\nobject defined with\n\n def <lambda>(arguments):\n return expression\n\nSee section *Function definitions* for the syntax of parameter lists.\nNote that functions created with lambda expressions cannot contain\nstatements or annotations.\n',
- 'lists': u'\nList displays\n*************\n\nA list display is a possibly empty series of expressions enclosed in\nsquare brackets:\n\n list_display ::= "[" [expression_list | comprehension] "]"\n\nA list display yields a new list object, the contents being specified\nby either a list of expressions or a comprehension. When a comma-\nseparated list of expressions is supplied, its elements are evaluated\nfrom left to right and placed into the list object in that order.\nWhen a comprehension is supplied, the list is constructed from the\nelements resulting from the comprehension.\n',
+ 'lists': u'\nList displays\n*************\n\nA list display is a possibly empty series of expressions enclosed in\nsquare brackets:\n\n list_display ::= "[" [starred_list | comprehension] "]"\n\nA list display yields a new list object, the contents being specified\nby either a list of expressions or a comprehension. When a comma-\nseparated list of expressions is supplied, its elements are evaluated\nfrom left to right and placed into the list object in that order.\nWhen a comprehension is supplied, the list is constructed from the\nelements resulting from the comprehension.\n',
'naming': u'\nNaming and binding\n******************\n\n\nBinding of names\n================\n\n*Names* refer to objects. Names are introduced by name binding\noperations.\n\nThe following constructs bind names: formal parameters to functions,\n"import" statements, class and function definitions (these bind the\nclass or function name in the defining block), and targets that are\nidentifiers if occurring in an assignment, "for" loop header, or after\n"as" in a "with" statement or "except" clause. The "import" statement\nof the form "from ... import *" binds all names defined in the\nimported module, except those beginning with an underscore. This form\nmay only be used at the module level.\n\nA target occurring in a "del" statement is also considered bound for\nthis purpose (though the actual semantics are to unbind the name).\n\nEach assignment or import statement occurs within a block defined by a\nclass or function definition or at the module level (the top-level\ncode block).\n\nIf a name is bound in a block, it is a local variable of that block,\nunless declared as "nonlocal" or "global". If a name is bound at the\nmodule level, it is a global variable. (The variables of the module\ncode block are local and global.) If a variable is used in a code\nblock but not defined there, it is a *free variable*.\n\nEach occurrence of a name in the program text refers to the *binding*\nof that name established by the following name resolution rules.\n\n\nResolution of names\n===================\n\nA *scope* defines the visibility of a name within a block. If a local\nvariable is defined in a block, its scope includes that block. If the\ndefinition occurs in a function block, the scope extends to any blocks\ncontained within the defining one, unless a contained block introduces\na different binding for the name.\n\nWhen a name is used in a code block, it is resolved using the nearest\nenclosing scope. The set of all such scopes visible to a code block\nis called the block\'s *environment*.\n\nWhen a name is not found at all, a "NameError" exception is raised. If\nthe current scope is a function scope, and the name refers to a local\nvariable that has not yet been bound to a value at the point where the\nname is used, an "UnboundLocalError" exception is raised.\n"UnboundLocalError" is a subclass of "NameError".\n\nIf a name binding operation occurs anywhere within a code block, all\nuses of the name within the block are treated as references to the\ncurrent block. This can lead to errors when a name is used within a\nblock before it is bound. This rule is subtle. Python lacks\ndeclarations and allows name binding operations to occur anywhere\nwithin a code block. The local variables of a code block can be\ndetermined by scanning the entire text of the block for name binding\noperations.\n\nIf the "global" statement occurs within a block, all uses of the name\nspecified in the statement refer to the binding of that name in the\ntop-level namespace. Names are resolved in the top-level namespace by\nsearching the global namespace, i.e. the namespace of the module\ncontaining the code block, and the builtins namespace, the namespace\nof the module "builtins". The global namespace is searched first. If\nthe name is not found there, the builtins namespace is searched. The\n"global" statement must precede all uses of the name.\n\nThe "global" statement has the same scope as a name binding operation\nin the same block. If the nearest enclosing scope for a free variable\ncontains a global statement, the free variable is treated as a global.\n\nThe "nonlocal" statement causes corresponding names to refer to\npreviously bound variables in the nearest enclosing function scope.\n"SyntaxError" is raised at compile time if the given name does not\nexist in any enclosing function scope.\n\nThe namespace for a module is automatically created the first time a\nmodule is imported. The main module for a script is always called\n"__main__".\n\nClass definition blocks and arguments to "exec()" and "eval()" are\nspecial in the context of name resolution. A class definition is an\nexecutable statement that may use and define names. These references\nfollow the normal rules for name resolution with an exception that\nunbound local variables are looked up in the global namespace. The\nnamespace of the class definition becomes the attribute dictionary of\nthe class. The scope of names defined in a class block is limited to\nthe class block; it does not extend to the code blocks of methods --\nthis includes comprehensions and generator expressions since they are\nimplemented using a function scope. This means that the following\nwill fail:\n\n class A:\n a = 42\n b = list(a + i for i in range(10))\n\n\nBuiltins and restricted execution\n=================================\n\nThe builtins namespace associated with the execution of a code block\nis actually found by looking up the name "__builtins__" in its global\nnamespace; this should be a dictionary or a module (in the latter case\nthe module\'s dictionary is used). By default, when in the "__main__"\nmodule, "__builtins__" is the built-in module "builtins"; when in any\nother module, "__builtins__" is an alias for the dictionary of the\n"builtins" module itself. "__builtins__" can be set to a user-created\ndictionary to create a weak form of restricted execution.\n\n**CPython implementation detail:** Users should not touch\n"__builtins__"; it is strictly an implementation detail. Users\nwanting to override values in the builtins namespace should "import"\nthe "builtins" module and modify its attributes appropriately.\n\n\nInteraction with dynamic features\n=================================\n\nName resolution of free variables occurs at runtime, not at compile\ntime. This means that the following code will print 42:\n\n i = 10\n def f():\n print(i)\n i = 42\n f()\n\nThere are several cases where Python statements are illegal when used\nin conjunction with nested scopes that contain free variables.\n\nIf a variable is referenced in an enclosing scope, it is illegal to\ndelete the name. An error will be reported at compile time.\n\nThe "eval()" and "exec()" functions do not have access to the full\nenvironment for resolving names. Names may be resolved in the local\nand global namespaces of the caller. Free variables are not resolved\nin the nearest enclosing namespace, but in the global namespace. [1]\nThe "exec()" and "eval()" functions have optional arguments to\noverride the global and local namespace. If only one namespace is\nspecified, it is used for both.\n',
'nonlocal': u'\nThe "nonlocal" statement\n************************\n\n nonlocal_stmt ::= "nonlocal" identifier ("," identifier)*\n\nThe "nonlocal" statement causes the listed identifiers to refer to\npreviously bound variables in the nearest enclosing scope excluding\nglobals. This is important because the default behavior for binding is\nto search the local namespace first. The statement allows\nencapsulated code to rebind variables outside of the local scope\nbesides the global (module) scope.\n\nNames listed in a "nonlocal" statement, unlike those listed in a\n"global" statement, must refer to pre-existing bindings in an\nenclosing scope (the scope in which a new binding should be created\ncannot be determined unambiguously).\n\nNames listed in a "nonlocal" statement must not collide with pre-\nexisting bindings in the local scope.\n\nSee also: **PEP 3104** - Access to Names in Outer Scopes\n\n The specification for the "nonlocal" statement.\n',
'numbers': u'\nNumeric literals\n****************\n\nThere are three types of numeric literals: integers, floating point\nnumbers, and imaginary numbers. There are no complex literals\n(complex numbers can be formed by adding a real number and an\nimaginary number).\n\nNote that numeric literals do not include a sign; a phrase like "-1"\nis actually an expression composed of the unary operator \'"-"\' and the\nliteral "1".\n',
'objects': u'\nObjects, values and types\n*************************\n\n*Objects* are Python\'s abstraction for data. All data in a Python\nprogram is represented by objects or by relations between objects. (In\na sense, and in conformance to Von Neumann\'s model of a "stored\nprogram computer," code is also represented by objects.)\n\nEvery object has an identity, a type and a value. An object\'s\n*identity* never changes once it has been created; you may think of it\nas the object\'s address in memory. The \'"is"\' operator compares the\nidentity of two objects; the "id()" function returns an integer\nrepresenting its identity.\n\n**CPython implementation detail:** For CPython, "id(x)" is the memory\naddress where "x" is stored.\n\nAn object\'s type determines the operations that the object supports\n(e.g., "does it have a length?") and also defines the possible values\nfor objects of that type. The "type()" function returns an object\'s\ntype (which is an object itself). Like its identity, an object\'s\n*type* is also unchangeable. [1]\n\nThe *value* of some objects can change. Objects whose value can\nchange are said to be *mutable*; objects whose value is unchangeable\nonce they are created are called *immutable*. (The value of an\nimmutable container object that contains a reference to a mutable\nobject can change when the latter\'s value is changed; however the\ncontainer is still considered immutable, because the collection of\nobjects it contains cannot be changed. So, immutability is not\nstrictly the same as having an unchangeable value, it is more subtle.)\nAn object\'s mutability is determined by its type; for instance,\nnumbers, strings and tuples are immutable, while dictionaries and\nlists are mutable.\n\nObjects are never explicitly destroyed; however, when they become\nunreachable they may be garbage-collected. An implementation is\nallowed to postpone garbage collection or omit it altogether --- it is\na matter of implementation quality how garbage collection is\nimplemented, as long as no objects are collected that are still\nreachable.\n\n**CPython implementation detail:** CPython currently uses a reference-\ncounting scheme with (optional) delayed detection of cyclically linked\ngarbage, which collects most objects as soon as they become\nunreachable, but is not guaranteed to collect garbage containing\ncircular references. See the documentation of the "gc" module for\ninformation on controlling the collection of cyclic garbage. Other\nimplementations act differently and CPython may change. Do not depend\non immediate finalization of objects when they become unreachable (so\nyou should always close files explicitly).\n\nNote that the use of the implementation\'s tracing or debugging\nfacilities may keep objects alive that would normally be collectable.\nAlso note that catching an exception with a \'"try"..."except"\'\nstatement may keep objects alive.\n\nSome objects contain references to "external" resources such as open\nfiles or windows. It is understood that these resources are freed\nwhen the object is garbage-collected, but since garbage collection is\nnot guaranteed to happen, such objects also provide an explicit way to\nrelease the external resource, usually a "close()" method. Programs\nare strongly recommended to explicitly close such objects. The\n\'"try"..."finally"\' statement and the \'"with"\' statement provide\nconvenient ways to do this.\n\nSome objects contain references to other objects; these are called\n*containers*. Examples of containers are tuples, lists and\ndictionaries. The references are part of a container\'s value. In\nmost cases, when we talk about the value of a container, we imply the\nvalues, not the identities of the contained objects; however, when we\ntalk about the mutability of a container, only the identities of the\nimmediately contained objects are implied. So, if an immutable\ncontainer (like a tuple) contains a reference to a mutable object, its\nvalue changes if that mutable object is changed.\n\nTypes affect almost all aspects of object behavior. Even the\nimportance of object identity is affected in some sense: for immutable\ntypes, operations that compute new values may actually return a\nreference to any existing object with the same type and value, while\nfor mutable objects this is not allowed. E.g., after "a = 1; b = 1",\n"a" and "b" may or may not refer to the same object with the value\none, depending on the implementation, but after "c = []; d = []", "c"\nand "d" are guaranteed to refer to two different, unique, newly\ncreated empty lists. (Note that "c = d = []" assigns the same object\nto both "c" and "d".)\n',
'operator-summary': u'\nOperator precedence\n*******************\n\nThe following table summarizes the operator precedence in Python, from\nlowest precedence (least binding) to highest precedence (most\nbinding). Operators in the same box have the same precedence. Unless\nthe syntax is explicitly given, operators are binary. Operators in\nthe same box group left to right (except for exponentiation, which\ngroups from right to left).\n\nNote that comparisons, membership tests, and identity tests, all have\nthe same precedence and have a left-to-right chaining feature as\ndescribed in the *Comparisons* section.\n\n+-------------------------------------------------+---------------------------------------+\n| Operator | Description |\n+=================================================+=======================================+\n| "lambda" | Lambda expression |\n+-------------------------------------------------+---------------------------------------+\n| "if" -- "else" | Conditional expression |\n+-------------------------------------------------+---------------------------------------+\n| "or" | Boolean OR |\n+-------------------------------------------------+---------------------------------------+\n| "and" | Boolean AND |\n+-------------------------------------------------+---------------------------------------+\n| "not" "x" | Boolean NOT |\n+-------------------------------------------------+---------------------------------------+\n| "in", "not in", "is", "is not", "<", "<=", ">", | Comparisons, including membership |\n| ">=", "!=", "==" | tests and identity tests |\n+-------------------------------------------------+---------------------------------------+\n| "|" | Bitwise OR |\n+-------------------------------------------------+---------------------------------------+\n| "^" | Bitwise XOR |\n+-------------------------------------------------+---------------------------------------+\n| "&" | Bitwise AND |\n+-------------------------------------------------+---------------------------------------+\n| "<<", ">>" | Shifts |\n+-------------------------------------------------+---------------------------------------+\n| "+", "-" | Addition and subtraction |\n+-------------------------------------------------+---------------------------------------+\n| "*", "@", "/", "//", "%" | Multiplication, matrix multiplication |\n| | division, remainder [5] |\n+-------------------------------------------------+---------------------------------------+\n| "+x", "-x", "~x" | Positive, negative, bitwise NOT |\n+-------------------------------------------------+---------------------------------------+\n| "**" | Exponentiation [6] |\n+-------------------------------------------------+---------------------------------------+\n| "await" "x" | Await expression |\n+-------------------------------------------------+---------------------------------------+\n| "x[index]", "x[index:index]", | Subscription, slicing, call, |\n| "x(arguments...)", "x.attribute" | attribute reference |\n+-------------------------------------------------+---------------------------------------+\n| "(expressions...)", "[expressions...]", "{key: | Binding or tuple display, list |\n| value...}", "{expressions...}" | display, dictionary display, set |\n| | display |\n+-------------------------------------------------+---------------------------------------+\n\n-[ Footnotes ]-\n\n[1] While "abs(x%y) < abs(y)" is true mathematically, for floats\n it may not be true numerically due to roundoff. For example, and\n assuming a platform on which a Python float is an IEEE 754 double-\n precision number, in order that "-1e-100 % 1e100" have the same\n sign as "1e100", the computed result is "-1e-100 + 1e100", which\n is numerically exactly equal to "1e100". The function\n "math.fmod()" returns a result whose sign matches the sign of the\n first argument instead, and so returns "-1e-100" in this case.\n Which approach is more appropriate depends on the application.\n\n[2] If x is very close to an exact integer multiple of y, it\'s\n possible for "x//y" to be one larger than "(x-x%y)//y" due to\n rounding. In such cases, Python returns the latter result, in\n order to preserve that "divmod(x,y)[0] * y + x % y" be very close\n to "x".\n\n[3] The Unicode standard distinguishes between *code points* (e.g.\n U+0041) and *abstract characters* (e.g. "LATIN CAPITAL LETTER A").\n While most abstract characters in Unicode are only represented\n using one code point, there is a number of abstract characters\n that can in addition be represented using a sequence of more than\n one code point. For example, the abstract character "LATIN\n CAPITAL LETTER C WITH CEDILLA" can be represented as a single\n *precomposed character* at code position U+00C7, or as a sequence\n of a *base character* at code position U+0043 (LATIN CAPITAL\n LETTER C), followed by a *combining character* at code position\n U+0327 (COMBINING CEDILLA).\n\n The comparison operators on strings compare at the level of\n Unicode code points. This may be counter-intuitive to humans. For\n example, ""\\u00C7" == "\\u0043\\u0327"" is "False", even though both\n strings represent the same abstract character "LATIN CAPITAL\n LETTER C WITH CEDILLA".\n\n To compare strings at the level of abstract characters (that is,\n in a way intuitive to humans), use "unicodedata.normalize()".\n\n[4] Due to automatic garbage-collection, free lists, and the\n dynamic nature of descriptors, you may notice seemingly unusual\n behaviour in certain uses of the "is" operator, like those\n involving comparisons between instance methods, or constants.\n Check their documentation for more info.\n\n[5] The "%" operator is also used for string formatting; the same\n precedence applies.\n\n[6] The power operator "**" binds less tightly than an arithmetic\n or bitwise unary operator on its right, that is, "2**-1" is "0.5".\n',
'pass': u'\nThe "pass" statement\n********************\n\n pass_stmt ::= "pass"\n\n"pass" is a null operation --- when it is executed, nothing happens.\nIt is useful as a placeholder when a statement is required\nsyntactically, but no code needs to be executed, for example:\n\n def f(arg): pass # a function that does nothing (yet)\n\n class C: pass # a class with no methods (yet)\n',
- 'power': u'\nThe power operator\n******************\n\nThe power operator binds more tightly than unary operators on its\nleft; it binds less tightly than unary operators on its right. The\nsyntax is:\n\n power ::= await ["**" u_expr]\n\nThus, in an unparenthesized sequence of power and unary operators, the\noperators are evaluated from right to left (this does not constrain\nthe evaluation order for the operands): "-1**2" results in "-1".\n\nThe power operator has the same semantics as the built-in "pow()"\nfunction, when called with two arguments: it yields its left argument\nraised to the power of its right argument. The numeric arguments are\nfirst converted to a common type, and the result is of that type.\n\nFor int operands, the result has the same type as the operands unless\nthe second argument is negative; in that case, all arguments are\nconverted to float and a float result is delivered. For example,\n"10**2" returns "100", but "10**-2" returns "0.01".\n\nRaising "0.0" to a negative power results in a "ZeroDivisionError".\nRaising a negative number to a fractional power results in a "complex"\nnumber. (In earlier versions it raised a "ValueError".)\n',
+ 'power': u'\nThe power operator\n******************\n\nThe power operator binds more tightly than unary operators on its\nleft; it binds less tightly than unary operators on its right. The\nsyntax is:\n\n power ::= ( await_expr | primary ) ["**" u_expr]\n\nThus, in an unparenthesized sequence of power and unary operators, the\noperators are evaluated from right to left (this does not constrain\nthe evaluation order for the operands): "-1**2" results in "-1".\n\nThe power operator has the same semantics as the built-in "pow()"\nfunction, when called with two arguments: it yields its left argument\nraised to the power of its right argument. The numeric arguments are\nfirst converted to a common type, and the result is of that type.\n\nFor int operands, the result has the same type as the operands unless\nthe second argument is negative; in that case, all arguments are\nconverted to float and a float result is delivered. For example,\n"10**2" returns "100", but "10**-2" returns "0.01".\n\nRaising "0.0" to a negative power results in a "ZeroDivisionError".\nRaising a negative number to a fractional power results in a "complex"\nnumber. (In earlier versions it raised a "ValueError".)\n',
'raise': u'\nThe "raise" statement\n*********************\n\n raise_stmt ::= "raise" [expression ["from" expression]]\n\nIf no expressions are present, "raise" re-raises the last exception\nthat was active in the current scope. If no exception is active in\nthe current scope, a "RuntimeError" exception is raised indicating\nthat this is an error.\n\nOtherwise, "raise" evaluates the first expression as the exception\nobject. It must be either a subclass or an instance of\n"BaseException". If it is a class, the exception instance will be\nobtained when needed by instantiating the class with no arguments.\n\nThe *type* of the exception is the exception instance\'s class, the\n*value* is the instance itself.\n\nA traceback object is normally created automatically when an exception\nis raised and attached to it as the "__traceback__" attribute, which\nis writable. You can create an exception and set your own traceback in\none step using the "with_traceback()" exception method (which returns\nthe same exception instance, with its traceback set to its argument),\nlike so:\n\n raise Exception("foo occurred").with_traceback(tracebackobj)\n\nThe "from" clause is used for exception chaining: if given, the second\n*expression* must be another exception class or instance, which will\nthen be attached to the raised exception as the "__cause__" attribute\n(which is writable). If the raised exception is not handled, both\nexceptions will be printed:\n\n >>> try:\n ... print(1 / 0)\n ... except Exception as exc:\n ... raise RuntimeError("Something bad happened") from exc\n ...\n Traceback (most recent call last):\n File "<stdin>", line 2, in <module>\n ZeroDivisionError: int division or modulo by zero\n\n The above exception was the direct cause of the following exception:\n\n Traceback (most recent call last):\n File "<stdin>", line 4, in <module>\n RuntimeError: Something bad happened\n\nA similar mechanism works implicitly if an exception is raised inside\nan exception handler or a "finally" clause: the previous exception is\nthen attached as the new exception\'s "__context__" attribute:\n\n >>> try:\n ... print(1 / 0)\n ... except:\n ... raise RuntimeError("Something bad happened")\n ...\n Traceback (most recent call last):\n File "<stdin>", line 2, in <module>\n ZeroDivisionError: int division or modulo by zero\n\n During handling of the above exception, another exception occurred:\n\n Traceback (most recent call last):\n File "<stdin>", line 4, in <module>\n RuntimeError: Something bad happened\n\nAdditional information on exceptions can be found in section\n*Exceptions*, and information about handling exceptions is in section\n*The try statement*.\n',
'return': u'\nThe "return" statement\n**********************\n\n return_stmt ::= "return" [expression_list]\n\n"return" may only occur syntactically nested in a function definition,\nnot within a nested class definition.\n\nIf an expression list is present, it is evaluated, else "None" is\nsubstituted.\n\n"return" leaves the current function call with the expression list (or\n"None") as return value.\n\nWhen "return" passes control out of a "try" statement with a "finally"\nclause, that "finally" clause is executed before really leaving the\nfunction.\n\nIn a generator function, the "return" statement indicates that the\ngenerator is done and will cause "StopIteration" to be raised. The\nreturned value (if any) is used as an argument to construct\n"StopIteration" and becomes the "StopIteration.value" attribute.\n',
'sequence-types': u'\nEmulating container types\n*************************\n\nThe following methods can be defined to implement container objects.\nContainers usually are sequences (such as lists or tuples) or mappings\n(like dictionaries), but can represent other containers as well. The\nfirst set of methods is used either to emulate a sequence or to\nemulate a mapping; the difference is that for a sequence, the\nallowable keys should be the integers *k* for which "0 <= k < N" where\n*N* is the length of the sequence, or slice objects, which define a\nrange of items. It is also recommended that mappings provide the\nmethods "keys()", "values()", "items()", "get()", "clear()",\n"setdefault()", "pop()", "popitem()", "copy()", and "update()"\nbehaving similar to those for Python\'s standard dictionary objects.\nThe "collections" module provides a "MutableMapping" abstract base\nclass to help create those methods from a base set of "__getitem__()",\n"__setitem__()", "__delitem__()", and "keys()". Mutable sequences\nshould provide methods "append()", "count()", "index()", "extend()",\n"insert()", "pop()", "remove()", "reverse()" and "sort()", like Python\nstandard list objects. Finally, sequence types should implement\naddition (meaning concatenation) and multiplication (meaning\nrepetition) by defining the methods "__add__()", "__radd__()",\n"__iadd__()", "__mul__()", "__rmul__()" and "__imul__()" described\nbelow; they should not define other numerical operators. It is\nrecommended that both mappings and sequences implement the\n"__contains__()" method to allow efficient use of the "in" operator;\nfor mappings, "in" should search the mapping\'s keys; for sequences, it\nshould search through the values. It is further recommended that both\nmappings and sequences implement the "__iter__()" method to allow\nefficient iteration through the container; for mappings, "__iter__()"\nshould be the same as "keys()"; for sequences, it should iterate\nthrough the values.\n\nobject.__len__(self)\n\n Called to implement the built-in function "len()". Should return\n the length of the object, an integer ">=" 0. Also, an object that\n doesn\'t define a "__bool__()" method and whose "__len__()" method\n returns zero is considered to be false in a Boolean context.\n\nobject.__length_hint__(self)\n\n Called to implement "operator.length_hint()". Should return an\n estimated length for the object (which may be greater or less than\n the actual length). The length must be an integer ">=" 0. This\n method is purely an optimization and is never required for\n correctness.\n\n New in version 3.4.\n\nNote: Slicing is done exclusively with the following three methods.\n A call like\n\n a[1:2] = b\n\n is translated to\n\n a[slice(1, 2, None)] = b\n\n and so forth. Missing slice items are always filled in with "None".\n\nobject.__getitem__(self, key)\n\n Called to implement evaluation of "self[key]". For sequence types,\n the accepted keys should be integers and slice objects. Note that\n the special interpretation of negative indexes (if the class wishes\n to emulate a sequence type) is up to the "__getitem__()" method. If\n *key* is of an inappropriate type, "TypeError" may be raised; if of\n a value outside the set of indexes for the sequence (after any\n special interpretation of negative values), "IndexError" should be\n raised. For mapping types, if *key* is missing (not in the\n container), "KeyError" should be raised.\n\n Note: "for" loops expect that an "IndexError" will be raised for\n illegal indexes to allow proper detection of the end of the\n sequence.\n\nobject.__missing__(self, key)\n\n Called by "dict"."__getitem__()" to implement "self[key]" for dict\n subclasses when key is not in the dictionary.\n\nobject.__setitem__(self, key, value)\n\n Called to implement assignment to "self[key]". Same note as for\n "__getitem__()". This should only be implemented for mappings if\n the objects support changes to the values for keys, or if new keys\n can be added, or for sequences if elements can be replaced. The\n same exceptions should be raised for improper *key* values as for\n the "__getitem__()" method.\n\nobject.__delitem__(self, key)\n\n Called to implement deletion of "self[key]". Same note as for\n "__getitem__()". This should only be implemented for mappings if\n the objects support removal of keys, or for sequences if elements\n can be removed from the sequence. The same exceptions should be\n raised for improper *key* values as for the "__getitem__()" method.\n\nobject.__iter__(self)\n\n This method is called when an iterator is required for a container.\n This method should return a new iterator object that can iterate\n over all the objects in the container. For mappings, it should\n iterate over the keys of the container.\n\n Iterator objects also need to implement this method; they are\n required to return themselves. For more information on iterator\n objects, see *Iterator Types*.\n\nobject.__reversed__(self)\n\n Called (if present) by the "reversed()" built-in to implement\n reverse iteration. It should return a new iterator object that\n iterates over all the objects in the container in reverse order.\n\n If the "__reversed__()" method is not provided, the "reversed()"\n built-in will fall back to using the sequence protocol ("__len__()"\n and "__getitem__()"). Objects that support the sequence protocol\n should only provide "__reversed__()" if they can provide an\n implementation that is more efficient than the one provided by\n "reversed()".\n\nThe membership test operators ("in" and "not in") are normally\nimplemented as an iteration through a sequence. However, container\nobjects can supply the following special method with a more efficient\nimplementation, which also does not require the object be a sequence.\n\nobject.__contains__(self, item)\n\n Called to implement membership test operators. Should return true\n if *item* is in *self*, false otherwise. For mapping objects, this\n should consider the keys of the mapping rather than the values or\n the key-item pairs.\n\n For objects that don\'t define "__contains__()", the membership test\n first tries iteration via "__iter__()", then the old sequence\n iteration protocol via "__getitem__()", see *this section in the\n language reference*.\n',
'shifting': u'\nShifting operations\n*******************\n\nThe shifting operations have lower priority than the arithmetic\noperations:\n\n shift_expr ::= a_expr | shift_expr ( "<<" | ">>" ) a_expr\n\nThese operators accept integers as arguments. They shift the first\nargument to the left or right by the number of bits given by the\nsecond argument.\n\nA right shift by *n* bits is defined as floor division by "pow(2,n)".\nA left shift by *n* bits is defined as multiplication with "pow(2,n)".\n\nNote: In the current implementation, the right-hand operand is\n required to be at most "sys.maxsize". If the right-hand operand is\n larger than "sys.maxsize" an "OverflowError" exception is raised.\n',
'slicings': u'\nSlicings\n********\n\nA slicing selects a range of items in a sequence object (e.g., a\nstring, tuple or list). Slicings may be used as expressions or as\ntargets in assignment or "del" statements. The syntax for a slicing:\n\n slicing ::= primary "[" slice_list "]"\n slice_list ::= slice_item ("," slice_item)* [","]\n slice_item ::= expression | proper_slice\n proper_slice ::= [lower_bound] ":" [upper_bound] [ ":" [stride] ]\n lower_bound ::= expression\n upper_bound ::= expression\n stride ::= expression\n\nThere is ambiguity in the formal syntax here: anything that looks like\nan expression list also looks like a slice list, so any subscription\ncan be interpreted as a slicing. Rather than further complicating the\nsyntax, this is disambiguated by defining that in this case the\ninterpretation as a subscription takes priority over the\ninterpretation as a slicing (this is the case if the slice list\ncontains no proper slice).\n\nThe semantics for a slicing are as follows. The primary is indexed\n(using the same "__getitem__()" method as normal subscription) with a\nkey that is constructed from the slice list, as follows. If the slice\nlist contains at least one comma, the key is a tuple containing the\nconversion of the slice items; otherwise, the conversion of the lone\nslice item is the key. The conversion of a slice item that is an\nexpression is that expression. The conversion of a proper slice is a\nslice object (see section *The standard type hierarchy*) whose\n"start", "stop" and "step" attributes are the values of the\nexpressions given as lower bound, upper bound and stride,\nrespectively, substituting "None" for missing expressions.\n',
'specialattrs': u'\nSpecial Attributes\n******************\n\nThe implementation adds a few special read-only attributes to several\nobject types, where they are relevant. Some of these are not reported\nby the "dir()" built-in function.\n\nobject.__dict__\n\n A dictionary or other mapping object used to store an object\'s\n (writable) attributes.\n\ninstance.__class__\n\n The class to which a class instance belongs.\n\nclass.__bases__\n\n The tuple of base classes of a class object.\n\nclass.__name__\n\n The name of the class or type.\n\nclass.__qualname__\n\n The *qualified name* of the class or type.\n\n New in version 3.3.\n\nclass.__mro__\n\n This attribute is a tuple of classes that are considered when\n looking for base classes during method resolution.\n\nclass.mro()\n\n This method can be overridden by a metaclass to customize the\n method resolution order for its instances. It is called at class\n instantiation, and its result is stored in "__mro__".\n\nclass.__subclasses__()\n\n Each class keeps a list of weak references to its immediate\n subclasses. This method returns a list of all those references\n still alive. Example:\n\n >>> int.__subclasses__()\n [<class \'bool\'>]\n\n-[ Footnotes ]-\n\n[1] Additional information on these special methods may be found\n in the Python Reference Manual (*Basic customization*).\n\n[2] As a consequence, the list "[1, 2]" is considered equal to\n "[1.0, 2.0]", and similarly for tuples.\n\n[3] They must have since the parser can\'t tell the type of the\n operands.\n\n[4] Cased characters are those with general category property\n being one of "Lu" (Letter, uppercase), "Ll" (Letter, lowercase),\n or "Lt" (Letter, titlecase).\n\n[5] To format only a tuple you should therefore provide a\n singleton tuple whose only element is the tuple to be formatted.\n',
- 'specialnames': u'\nSpecial method names\n********************\n\nA class can implement certain operations that are invoked by special\nsyntax (such as arithmetic operations or subscripting and slicing) by\ndefining methods with special names. This is Python\'s approach to\n*operator overloading*, allowing classes to define their own behavior\nwith respect to language operators. For instance, if a class defines\na method named "__getitem__()", and "x" is an instance of this class,\nthen "x[i]" is roughly equivalent to "type(x).__getitem__(x, i)".\nExcept where mentioned, attempts to execute an operation raise an\nexception when no appropriate method is defined (typically\n"AttributeError" or "TypeError").\n\nWhen implementing a class that emulates any built-in type, it is\nimportant that the emulation only be implemented to the degree that it\nmakes sense for the object being modelled. For example, some\nsequences may work well with retrieval of individual elements, but\nextracting a slice may not make sense. (One example of this is the\n"NodeList" interface in the W3C\'s Document Object Model.)\n\n\nBasic customization\n===================\n\nobject.__new__(cls[, ...])\n\n Called to create a new instance of class *cls*. "__new__()" is a\n static method (special-cased so you need not declare it as such)\n that takes the class of which an instance was requested as its\n first argument. The remaining arguments are those passed to the\n object constructor expression (the call to the class). The return\n value of "__new__()" should be the new object instance (usually an\n instance of *cls*).\n\n Typical implementations create a new instance of the class by\n invoking the superclass\'s "__new__()" method using\n "super(currentclass, cls).__new__(cls[, ...])" with appropriate\n arguments and then modifying the newly-created instance as\n necessary before returning it.\n\n If "__new__()" returns an instance of *cls*, then the new\n instance\'s "__init__()" method will be invoked like\n "__init__(self[, ...])", where *self* is the new instance and the\n remaining arguments are the same as were passed to "__new__()".\n\n If "__new__()" does not return an instance of *cls*, then the new\n instance\'s "__init__()" method will not be invoked.\n\n "__new__()" is intended mainly to allow subclasses of immutable\n types (like int, str, or tuple) to customize instance creation. It\n is also commonly overridden in custom metaclasses in order to\n customize class creation.\n\nobject.__init__(self[, ...])\n\n Called after the instance has been created (by "__new__()"), but\n before it is returned to the caller. The arguments are those\n passed to the class constructor expression. If a base class has an\n "__init__()" method, the derived class\'s "__init__()" method, if\n any, must explicitly call it to ensure proper initialization of the\n base class part of the instance; for example:\n "BaseClass.__init__(self, [args...])".\n\n Because "__new__()" and "__init__()" work together in constructing\n objects ("__new__()" to create it, and "__init__()" to customise\n it), no non-"None" value may be returned by "__init__()"; doing so\n will cause a "TypeError" to be raised at runtime.\n\nobject.__del__(self)\n\n Called when the instance is about to be destroyed. This is also\n called a destructor. If a base class has a "__del__()" method, the\n derived class\'s "__del__()" method, if any, must explicitly call it\n to ensure proper deletion of the base class part of the instance.\n Note that it is possible (though not recommended!) for the\n "__del__()" method to postpone destruction of the instance by\n creating a new reference to it. It may then be called at a later\n time when this new reference is deleted. It is not guaranteed that\n "__del__()" methods are called for objects that still exist when\n the interpreter exits.\n\n Note: "del x" doesn\'t directly call "x.__del__()" --- the former\n decrements the reference count for "x" by one, and the latter is\n only called when "x"\'s reference count reaches zero. Some common\n situations that may prevent the reference count of an object from\n going to zero include: circular references between objects (e.g.,\n a doubly-linked list or a tree data structure with parent and\n child pointers); a reference to the object on the stack frame of\n a function that caught an exception (the traceback stored in\n "sys.exc_info()[2]" keeps the stack frame alive); or a reference\n to the object on the stack frame that raised an unhandled\n exception in interactive mode (the traceback stored in\n "sys.last_traceback" keeps the stack frame alive). The first\n situation can only be remedied by explicitly breaking the cycles;\n the second can be resolved by freeing the reference to the\n traceback object when it is no longer useful, and the third can\n be resolved by storing "None" in "sys.last_traceback". Circular\n references which are garbage are detected and cleaned up when the\n cyclic garbage collector is enabled (it\'s on by default). Refer\n to the documentation for the "gc" module for more information\n about this topic.\n\n Warning: Due to the precarious circumstances under which\n "__del__()" methods are invoked, exceptions that occur during\n their execution are ignored, and a warning is printed to\n "sys.stderr" instead. Also, when "__del__()" is invoked in\n response to a module being deleted (e.g., when execution of the\n program is done), other globals referenced by the "__del__()"\n method may already have been deleted or in the process of being\n torn down (e.g. the import machinery shutting down). For this\n reason, "__del__()" methods should do the absolute minimum needed\n to maintain external invariants. Starting with version 1.5,\n Python guarantees that globals whose name begins with a single\n underscore are deleted from their module before other globals are\n deleted; if no other references to such globals exist, this may\n help in assuring that imported modules are still available at the\n time when the "__del__()" method is called.\n\nobject.__repr__(self)\n\n Called by the "repr()" built-in function to compute the "official"\n string representation of an object. If at all possible, this\n should look like a valid Python expression that could be used to\n recreate an object with the same value (given an appropriate\n environment). If this is not possible, a string of the form\n "<...some useful description...>" should be returned. The return\n value must be a string object. If a class defines "__repr__()" but\n not "__str__()", then "__repr__()" is also used when an "informal"\n string representation of instances of that class is required.\n\n This is typically used for debugging, so it is important that the\n representation is information-rich and unambiguous.\n\nobject.__str__(self)\n\n Called by "str(object)" and the built-in functions "format()" and\n "print()" to compute the "informal" or nicely printable string\n representation of an object. The return value must be a *string*\n object.\n\n This method differs from "object.__repr__()" in that there is no\n expectation that "__str__()" return a valid Python expression: a\n more convenient or concise representation can be used.\n\n The default implementation defined by the built-in type "object"\n calls "object.__repr__()".\n\nobject.__bytes__(self)\n\n Called by "bytes()" to compute a byte-string representation of an\n object. This should return a "bytes" object.\n\nobject.__format__(self, format_spec)\n\n Called by the "format()" built-in function (and by extension, the\n "str.format()" method of class "str") to produce a "formatted"\n string representation of an object. The "format_spec" argument is a\n string that contains a description of the formatting options\n desired. The interpretation of the "format_spec" argument is up to\n the type implementing "__format__()", however most classes will\n either delegate formatting to one of the built-in types, or use a\n similar formatting option syntax.\n\n See *Format Specification Mini-Language* for a description of the\n standard formatting syntax.\n\n The return value must be a string object.\n\n Changed in version 3.4: The __format__ method of "object" itself\n raises a "TypeError" if passed any non-empty string.\n\nobject.__lt__(self, other)\nobject.__le__(self, other)\nobject.__eq__(self, other)\nobject.__ne__(self, other)\nobject.__gt__(self, other)\nobject.__ge__(self, other)\n\n These are the so-called "rich comparison" methods. The\n correspondence between operator symbols and method names is as\n follows: "x<y" calls "x.__lt__(y)", "x<=y" calls "x.__le__(y)",\n "x==y" calls "x.__eq__(y)", "x!=y" calls "x.__ne__(y)", "x>y" calls\n "x.__gt__(y)", and "x>=y" calls "x.__ge__(y)".\n\n A rich comparison method may return the singleton "NotImplemented"\n if it does not implement the operation for a given pair of\n arguments. By convention, "False" and "True" are returned for a\n successful comparison. However, these methods can return any value,\n so if the comparison operator is used in a Boolean context (e.g.,\n in the condition of an "if" statement), Python will call "bool()"\n on the value to determine if the result is true or false.\n\n By default, "__ne__()" delegates to "__eq__()" and inverts the\n result unless it is "NotImplemented". There are no other implied\n relationships among the comparison operators, for example, the\n truth of "(x<y or x==y)" does not imply "x<=y". To automatically\n generate ordering operations from a single root operation, see\n "functools.total_ordering()".\n\n See the paragraph on "__hash__()" for some important notes on\n creating *hashable* objects which support custom comparison\n operations and are usable as dictionary keys.\n\n There are no swapped-argument versions of these methods (to be used\n when the left argument does not support the operation but the right\n argument does); rather, "__lt__()" and "__gt__()" are each other\'s\n reflection, "__le__()" and "__ge__()" are each other\'s reflection,\n and "__eq__()" and "__ne__()" are their own reflection. If the\n operands are of different types, and right operand\'s type is a\n direct or indirect subclass of the left operand\'s type, the\n reflected method of the right operand has priority, otherwise the\n left operand\'s method has priority. Virtual subclassing is not\n considered.\n\nobject.__hash__(self)\n\n Called by built-in function "hash()" and for operations on members\n of hashed collections including "set", "frozenset", and "dict".\n "__hash__()" should return an integer. The only required property\n is that objects which compare equal have the same hash value; it is\n advised to somehow mix together (e.g. using exclusive or) the hash\n values for the components of the object that also play a part in\n comparison of objects.\n\n Note: "hash()" truncates the value returned from an object\'s\n custom "__hash__()" method to the size of a "Py_ssize_t". This\n is typically 8 bytes on 64-bit builds and 4 bytes on 32-bit\n builds. If an object\'s "__hash__()" must interoperate on builds\n of different bit sizes, be sure to check the width on all\n supported builds. An easy way to do this is with "python -c\n "import sys; print(sys.hash_info.width)"".\n\n If a class does not define an "__eq__()" method it should not\n define a "__hash__()" operation either; if it defines "__eq__()"\n but not "__hash__()", its instances will not be usable as items in\n hashable collections. If a class defines mutable objects and\n implements an "__eq__()" method, it should not implement\n "__hash__()", since the implementation of hashable collections\n requires that a key\'s hash value is immutable (if the object\'s hash\n value changes, it will be in the wrong hash bucket).\n\n User-defined classes have "__eq__()" and "__hash__()" methods by\n default; with them, all objects compare unequal (except with\n themselves) and "x.__hash__()" returns an appropriate value such\n that "x == y" implies both that "x is y" and "hash(x) == hash(y)".\n\n A class that overrides "__eq__()" and does not define "__hash__()"\n will have its "__hash__()" implicitly set to "None". When the\n "__hash__()" method of a class is "None", instances of the class\n will raise an appropriate "TypeError" when a program attempts to\n retrieve their hash value, and will also be correctly identified as\n unhashable when checking "isinstance(obj, collections.Hashable)".\n\n If a class that overrides "__eq__()" needs to retain the\n implementation of "__hash__()" from a parent class, the interpreter\n must be told this explicitly by setting "__hash__ =\n <ParentClass>.__hash__".\n\n If a class that does not override "__eq__()" wishes to suppress\n hash support, it should include "__hash__ = None" in the class\n definition. A class which defines its own "__hash__()" that\n explicitly raises a "TypeError" would be incorrectly identified as\n hashable by an "isinstance(obj, collections.Hashable)" call.\n\n Note: By default, the "__hash__()" values of str, bytes and\n datetime objects are "salted" with an unpredictable random value.\n Although they remain constant within an individual Python\n process, they are not predictable between repeated invocations of\n Python.This is intended to provide protection against a denial-\n of-service caused by carefully-chosen inputs that exploit the\n worst case performance of a dict insertion, O(n^2) complexity.\n See http://www.ocert.org/advisories/ocert-2011-003.html for\n details.Changing hash values affects the iteration order of\n dicts, sets and other mappings. Python has never made guarantees\n about this ordering (and it typically varies between 32-bit and\n 64-bit builds).See also "PYTHONHASHSEED".\n\n Changed in version 3.3: Hash randomization is enabled by default.\n\nobject.__bool__(self)\n\n Called to implement truth value testing and the built-in operation\n "bool()"; should return "False" or "True". When this method is not\n defined, "__len__()" is called, if it is defined, and the object is\n considered true if its result is nonzero. If a class defines\n neither "__len__()" nor "__bool__()", all its instances are\n considered true.\n\n\nCustomizing attribute access\n============================\n\nThe following methods can be defined to customize the meaning of\nattribute access (use of, assignment to, or deletion of "x.name") for\nclass instances.\n\nobject.__getattr__(self, name)\n\n Called when an attribute lookup has not found the attribute in the\n usual places (i.e. it is not an instance attribute nor is it found\n in the class tree for "self"). "name" is the attribute name. This\n method should return the (computed) attribute value or raise an\n "AttributeError" exception.\n\n Note that if the attribute is found through the normal mechanism,\n "__getattr__()" is not called. (This is an intentional asymmetry\n between "__getattr__()" and "__setattr__()".) This is done both for\n efficiency reasons and because otherwise "__getattr__()" would have\n no way to access other attributes of the instance. Note that at\n least for instance variables, you can fake total control by not\n inserting any values in the instance attribute dictionary (but\n instead inserting them in another object). See the\n "__getattribute__()" method below for a way to actually get total\n control over attribute access.\n\nobject.__getattribute__(self, name)\n\n Called unconditionally to implement attribute accesses for\n instances of the class. If the class also defines "__getattr__()",\n the latter will not be called unless "__getattribute__()" either\n calls it explicitly or raises an "AttributeError". This method\n should return the (computed) attribute value or raise an\n "AttributeError" exception. In order to avoid infinite recursion in\n this method, its implementation should always call the base class\n method with the same name to access any attributes it needs, for\n example, "object.__getattribute__(self, name)".\n\n Note: This method may still be bypassed when looking up special\n methods as the result of implicit invocation via language syntax\n or built-in functions. See *Special method lookup*.\n\nobject.__setattr__(self, name, value)\n\n Called when an attribute assignment is attempted. This is called\n instead of the normal mechanism (i.e. store the value in the\n instance dictionary). *name* is the attribute name, *value* is the\n value to be assigned to it.\n\n If "__setattr__()" wants to assign to an instance attribute, it\n should call the base class method with the same name, for example,\n "object.__setattr__(self, name, value)".\n\nobject.__delattr__(self, name)\n\n Like "__setattr__()" but for attribute deletion instead of\n assignment. This should only be implemented if "del obj.name" is\n meaningful for the object.\n\nobject.__dir__(self)\n\n Called when "dir()" is called on the object. A sequence must be\n returned. "dir()" converts the returned sequence to a list and\n sorts it.\n\n\nImplementing Descriptors\n------------------------\n\nThe following methods only apply when an instance of the class\ncontaining the method (a so-called *descriptor* class) appears in an\n*owner* class (the descriptor must be in either the owner\'s class\ndictionary or in the class dictionary for one of its parents). In the\nexamples below, "the attribute" refers to the attribute whose name is\nthe key of the property in the owner class\' "__dict__".\n\nobject.__get__(self, instance, owner)\n\n Called to get the attribute of the owner class (class attribute\n access) or of an instance of that class (instance attribute\n access). *owner* is always the owner class, while *instance* is the\n instance that the attribute was accessed through, or "None" when\n the attribute is accessed through the *owner*. This method should\n return the (computed) attribute value or raise an "AttributeError"\n exception.\n\nobject.__set__(self, instance, value)\n\n Called to set the attribute on an instance *instance* of the owner\n class to a new value, *value*.\n\nobject.__delete__(self, instance)\n\n Called to delete the attribute on an instance *instance* of the\n owner class.\n\nThe attribute "__objclass__" is interpreted by the "inspect" module as\nspecifying the class where this object was defined (setting this\nappropriately can assist in runtime introspection of dynamic class\nattributes). For callables, it may indicate that an instance of the\ngiven type (or a subclass) is expected or required as the first\npositional argument (for example, CPython sets this attribute for\nunbound methods that are implemented in C).\n\n\nInvoking Descriptors\n--------------------\n\nIn general, a descriptor is an object attribute with "binding\nbehavior", one whose attribute access has been overridden by methods\nin the descriptor protocol: "__get__()", "__set__()", and\n"__delete__()". If any of those methods are defined for an object, it\nis said to be a descriptor.\n\nThe default behavior for attribute access is to get, set, or delete\nthe attribute from an object\'s dictionary. For instance, "a.x" has a\nlookup chain starting with "a.__dict__[\'x\']", then\n"type(a).__dict__[\'x\']", and continuing through the base classes of\n"type(a)" excluding metaclasses.\n\nHowever, if the looked-up value is an object defining one of the\ndescriptor methods, then Python may override the default behavior and\ninvoke the descriptor method instead. Where this occurs in the\nprecedence chain depends on which descriptor methods were defined and\nhow they were called.\n\nThe starting point for descriptor invocation is a binding, "a.x". How\nthe arguments are assembled depends on "a":\n\nDirect Call\n The simplest and least common call is when user code directly\n invokes a descriptor method: "x.__get__(a)".\n\nInstance Binding\n If binding to an object instance, "a.x" is transformed into the\n call: "type(a).__dict__[\'x\'].__get__(a, type(a))".\n\nClass Binding\n If binding to a class, "A.x" is transformed into the call:\n "A.__dict__[\'x\'].__get__(None, A)".\n\nSuper Binding\n If "a" is an instance of "super", then the binding "super(B,\n obj).m()" searches "obj.__class__.__mro__" for the base class "A"\n immediately preceding "B" and then invokes the descriptor with the\n call: "A.__dict__[\'m\'].__get__(obj, obj.__class__)".\n\nFor instance bindings, the precedence of descriptor invocation depends\non the which descriptor methods are defined. A descriptor can define\nany combination of "__get__()", "__set__()" and "__delete__()". If it\ndoes not define "__get__()", then accessing the attribute will return\nthe descriptor object itself unless there is a value in the object\'s\ninstance dictionary. If the descriptor defines "__set__()" and/or\n"__delete__()", it is a data descriptor; if it defines neither, it is\na non-data descriptor. Normally, data descriptors define both\n"__get__()" and "__set__()", while non-data descriptors have just the\n"__get__()" method. Data descriptors with "__set__()" and "__get__()"\ndefined always override a redefinition in an instance dictionary. In\ncontrast, non-data descriptors can be overridden by instances.\n\nPython methods (including "staticmethod()" and "classmethod()") are\nimplemented as non-data descriptors. Accordingly, instances can\nredefine and override methods. This allows individual instances to\nacquire behaviors that differ from other instances of the same class.\n\nThe "property()" function is implemented as a data descriptor.\nAccordingly, instances cannot override the behavior of a property.\n\n\n__slots__\n---------\n\nBy default, instances of classes have a dictionary for attribute\nstorage. This wastes space for objects having very few instance\nvariables. The space consumption can become acute when creating large\nnumbers of instances.\n\nThe default can be overridden by defining *__slots__* in a class\ndefinition. The *__slots__* declaration takes a sequence of instance\nvariables and reserves just enough space in each instance to hold a\nvalue for each variable. Space is saved because *__dict__* is not\ncreated for each instance.\n\nobject.__slots__\n\n This class variable can be assigned a string, iterable, or sequence\n of strings with variable names used by instances. *__slots__*\n reserves space for the declared variables and prevents the\n automatic creation of *__dict__* and *__weakref__* for each\n instance.\n\n\nNotes on using *__slots__*\n~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n* When inheriting from a class without *__slots__*, the *__dict__*\n attribute of that class will always be accessible, so a *__slots__*\n definition in the subclass is meaningless.\n\n* Without a *__dict__* variable, instances cannot be assigned new\n variables not listed in the *__slots__* definition. Attempts to\n assign to an unlisted variable name raises "AttributeError". If\n dynamic assignment of new variables is desired, then add\n "\'__dict__\'" to the sequence of strings in the *__slots__*\n declaration.\n\n* Without a *__weakref__* variable for each instance, classes\n defining *__slots__* do not support weak references to its\n instances. If weak reference support is needed, then add\n "\'__weakref__\'" to the sequence of strings in the *__slots__*\n declaration.\n\n* *__slots__* are implemented at the class level by creating\n descriptors (*Implementing Descriptors*) for each variable name. As\n a result, class attributes cannot be used to set default values for\n instance variables defined by *__slots__*; otherwise, the class\n attribute would overwrite the descriptor assignment.\n\n* The action of a *__slots__* declaration is limited to the class\n where it is defined. As a result, subclasses will have a *__dict__*\n unless they also define *__slots__* (which must only contain names\n of any *additional* slots).\n\n* If a class defines a slot also defined in a base class, the\n instance variable defined by the base class slot is inaccessible\n (except by retrieving its descriptor directly from the base class).\n This renders the meaning of the program undefined. In the future, a\n check may be added to prevent this.\n\n* Nonempty *__slots__* does not work for classes derived from\n "variable-length" built-in types such as "int", "bytes" and "tuple".\n\n* Any non-string iterable may be assigned to *__slots__*. Mappings\n may also be used; however, in the future, special meaning may be\n assigned to the values corresponding to each key.\n\n* *__class__* assignment works only if both classes have the same\n *__slots__*.\n\n\nCustomizing class creation\n==========================\n\nBy default, classes are constructed using "type()". The class body is\nexecuted in a new namespace and the class name is bound locally to the\nresult of "type(name, bases, namespace)".\n\nThe class creation process can be customised by passing the\n"metaclass" keyword argument in the class definition line, or by\ninheriting from an existing class that included such an argument. In\nthe following example, both "MyClass" and "MySubclass" are instances\nof "Meta":\n\n class Meta(type):\n pass\n\n class MyClass(metaclass=Meta):\n pass\n\n class MySubclass(MyClass):\n pass\n\nAny other keyword arguments that are specified in the class definition\nare passed through to all metaclass operations described below.\n\nWhen a class definition is executed, the following steps occur:\n\n* the appropriate metaclass is determined\n\n* the class namespace is prepared\n\n* the class body is executed\n\n* the class object is created\n\n\nDetermining the appropriate metaclass\n-------------------------------------\n\nThe appropriate metaclass for a class definition is determined as\nfollows:\n\n* if no bases and no explicit metaclass are given, then "type()" is\n used\n\n* if an explicit metaclass is given and it is *not* an instance of\n "type()", then it is used directly as the metaclass\n\n* if an instance of "type()" is given as the explicit metaclass, or\n bases are defined, then the most derived metaclass is used\n\nThe most derived metaclass is selected from the explicitly specified\nmetaclass (if any) and the metaclasses (i.e. "type(cls)") of all\nspecified base classes. The most derived metaclass is one which is a\nsubtype of *all* of these candidate metaclasses. If none of the\ncandidate metaclasses meets that criterion, then the class definition\nwill fail with "TypeError".\n\n\nPreparing the class namespace\n-----------------------------\n\nOnce the appropriate metaclass has been identified, then the class\nnamespace is prepared. If the metaclass has a "__prepare__" attribute,\nit is called as "namespace = metaclass.__prepare__(name, bases,\n**kwds)" (where the additional keyword arguments, if any, come from\nthe class definition).\n\nIf the metaclass has no "__prepare__" attribute, then the class\nnamespace is initialised as an empty "dict()" instance.\n\nSee also: **PEP 3115** - Metaclasses in Python 3000\n\n Introduced the "__prepare__" namespace hook\n\n\nExecuting the class body\n------------------------\n\nThe class body is executed (approximately) as "exec(body, globals(),\nnamespace)". The key difference from a normal call to "exec()" is that\nlexical scoping allows the class body (including any methods) to\nreference names from the current and outer scopes when the class\ndefinition occurs inside a function.\n\nHowever, even when the class definition occurs inside the function,\nmethods defined inside the class still cannot see names defined at the\nclass scope. Class variables must be accessed through the first\nparameter of instance or class methods, and cannot be accessed at all\nfrom static methods.\n\n\nCreating the class object\n-------------------------\n\nOnce the class namespace has been populated by executing the class\nbody, the class object is created by calling "metaclass(name, bases,\nnamespace, **kwds)" (the additional keywords passed here are the same\nas those passed to "__prepare__").\n\nThis class object is the one that will be referenced by the zero-\nargument form of "super()". "__class__" is an implicit closure\nreference created by the compiler if any methods in a class body refer\nto either "__class__" or "super". This allows the zero argument form\nof "super()" to correctly identify the class being defined based on\nlexical scoping, while the class or instance that was used to make the\ncurrent call is identified based on the first argument passed to the\nmethod.\n\nAfter the class object is created, it is passed to the class\ndecorators included in the class definition (if any) and the resulting\nobject is bound in the local namespace as the defined class.\n\nSee also: **PEP 3135** - New super\n\n Describes the implicit "__class__" closure reference\n\n\nMetaclass example\n-----------------\n\nThe potential uses for metaclasses are boundless. Some ideas that have\nbeen explored include logging, interface checking, automatic\ndelegation, automatic property creation, proxies, frameworks, and\nautomatic resource locking/synchronization.\n\nHere is an example of a metaclass that uses an\n"collections.OrderedDict" to remember the order that class variables\nare defined:\n\n class OrderedClass(type):\n\n @classmethod\n def __prepare__(metacls, name, bases, **kwds):\n return collections.OrderedDict()\n\n def __new__(cls, name, bases, namespace, **kwds):\n result = type.__new__(cls, name, bases, dict(namespace))\n result.members = tuple(namespace)\n return result\n\n class A(metaclass=OrderedClass):\n def one(self): pass\n def two(self): pass\n def three(self): pass\n def four(self): pass\n\n >>> A.members\n (\'__module__\', \'one\', \'two\', \'three\', \'four\')\n\nWhen the class definition for *A* gets executed, the process begins\nwith calling the metaclass\'s "__prepare__()" method which returns an\nempty "collections.OrderedDict". That mapping records the methods and\nattributes of *A* as they are defined within the body of the class\nstatement. Once those definitions are executed, the ordered dictionary\nis fully populated and the metaclass\'s "__new__()" method gets\ninvoked. That method builds the new type and it saves the ordered\ndictionary keys in an attribute called "members".\n\n\nCustomizing instance and subclass checks\n========================================\n\nThe following methods are used to override the default behavior of the\n"isinstance()" and "issubclass()" built-in functions.\n\nIn particular, the metaclass "abc.ABCMeta" implements these methods in\norder to allow the addition of Abstract Base Classes (ABCs) as\n"virtual base classes" to any class or type (including built-in\ntypes), including other ABCs.\n\nclass.__instancecheck__(self, instance)\n\n Return true if *instance* should be considered a (direct or\n indirect) instance of *class*. If defined, called to implement\n "isinstance(instance, class)".\n\nclass.__subclasscheck__(self, subclass)\n\n Return true if *subclass* should be considered a (direct or\n indirect) subclass of *class*. If defined, called to implement\n "issubclass(subclass, class)".\n\nNote that these methods are looked up on the type (metaclass) of a\nclass. They cannot be defined as class methods in the actual class.\nThis is consistent with the lookup of special methods that are called\non instances, only in this case the instance is itself a class.\n\nSee also: **PEP 3119** - Introducing Abstract Base Classes\n\n Includes the specification for customizing "isinstance()" and\n "issubclass()" behavior through "__instancecheck__()" and\n "__subclasscheck__()", with motivation for this functionality in\n the context of adding Abstract Base Classes (see the "abc"\n module) to the language.\n\n\nEmulating callable objects\n==========================\n\nobject.__call__(self[, args...])\n\n Called when the instance is "called" as a function; if this method\n is defined, "x(arg1, arg2, ...)" is a shorthand for\n "x.__call__(arg1, arg2, ...)".\n\n\nEmulating container types\n=========================\n\nThe following methods can be defined to implement container objects.\nContainers usually are sequences (such as lists or tuples) or mappings\n(like dictionaries), but can represent other containers as well. The\nfirst set of methods is used either to emulate a sequence or to\nemulate a mapping; the difference is that for a sequence, the\nallowable keys should be the integers *k* for which "0 <= k < N" where\n*N* is the length of the sequence, or slice objects, which define a\nrange of items. It is also recommended that mappings provide the\nmethods "keys()", "values()", "items()", "get()", "clear()",\n"setdefault()", "pop()", "popitem()", "copy()", and "update()"\nbehaving similar to those for Python\'s standard dictionary objects.\nThe "collections" module provides a "MutableMapping" abstract base\nclass to help create those methods from a base set of "__getitem__()",\n"__setitem__()", "__delitem__()", and "keys()". Mutable sequences\nshould provide methods "append()", "count()", "index()", "extend()",\n"insert()", "pop()", "remove()", "reverse()" and "sort()", like Python\nstandard list objects. Finally, sequence types should implement\naddition (meaning concatenation) and multiplication (meaning\nrepetition) by defining the methods "__add__()", "__radd__()",\n"__iadd__()", "__mul__()", "__rmul__()" and "__imul__()" described\nbelow; they should not define other numerical operators. It is\nrecommended that both mappings and sequences implement the\n"__contains__()" method to allow efficient use of the "in" operator;\nfor mappings, "in" should search the mapping\'s keys; for sequences, it\nshould search through the values. It is further recommended that both\nmappings and sequences implement the "__iter__()" method to allow\nefficient iteration through the container; for mappings, "__iter__()"\nshould be the same as "keys()"; for sequences, it should iterate\nthrough the values.\n\nobject.__len__(self)\n\n Called to implement the built-in function "len()". Should return\n the length of the object, an integer ">=" 0. Also, an object that\n doesn\'t define a "__bool__()" method and whose "__len__()" method\n returns zero is considered to be false in a Boolean context.\n\nobject.__length_hint__(self)\n\n Called to implement "operator.length_hint()". Should return an\n estimated length for the object (which may be greater or less than\n the actual length). The length must be an integer ">=" 0. This\n method is purely an optimization and is never required for\n correctness.\n\n New in version 3.4.\n\nNote: Slicing is done exclusively with the following three methods.\n A call like\n\n a[1:2] = b\n\n is translated to\n\n a[slice(1, 2, None)] = b\n\n and so forth. Missing slice items are always filled in with "None".\n\nobject.__getitem__(self, key)\n\n Called to implement evaluation of "self[key]". For sequence types,\n the accepted keys should be integers and slice objects. Note that\n the special interpretation of negative indexes (if the class wishes\n to emulate a sequence type) is up to the "__getitem__()" method. If\n *key* is of an inappropriate type, "TypeError" may be raised; if of\n a value outside the set of indexes for the sequence (after any\n special interpretation of negative values), "IndexError" should be\n raised. For mapping types, if *key* is missing (not in the\n container), "KeyError" should be raised.\n\n Note: "for" loops expect that an "IndexError" will be raised for\n illegal indexes to allow proper detection of the end of the\n sequence.\n\nobject.__missing__(self, key)\n\n Called by "dict"."__getitem__()" to implement "self[key]" for dict\n subclasses when key is not in the dictionary.\n\nobject.__setitem__(self, key, value)\n\n Called to implement assignment to "self[key]". Same note as for\n "__getitem__()". This should only be implemented for mappings if\n the objects support changes to the values for keys, or if new keys\n can be added, or for sequences if elements can be replaced. The\n same exceptions should be raised for improper *key* values as for\n the "__getitem__()" method.\n\nobject.__delitem__(self, key)\n\n Called to implement deletion of "self[key]". Same note as for\n "__getitem__()". This should only be implemented for mappings if\n the objects support removal of keys, or for sequences if elements\n can be removed from the sequence. The same exceptions should be\n raised for improper *key* values as for the "__getitem__()" method.\n\nobject.__iter__(self)\n\n This method is called when an iterator is required for a container.\n This method should return a new iterator object that can iterate\n over all the objects in the container. For mappings, it should\n iterate over the keys of the container.\n\n Iterator objects also need to implement this method; they are\n required to return themselves. For more information on iterator\n objects, see *Iterator Types*.\n\nobject.__reversed__(self)\n\n Called (if present) by the "reversed()" built-in to implement\n reverse iteration. It should return a new iterator object that\n iterates over all the objects in the container in reverse order.\n\n If the "__reversed__()" method is not provided, the "reversed()"\n built-in will fall back to using the sequence protocol ("__len__()"\n and "__getitem__()"). Objects that support the sequence protocol\n should only provide "__reversed__()" if they can provide an\n implementation that is more efficient than the one provided by\n "reversed()".\n\nThe membership test operators ("in" and "not in") are normally\nimplemented as an iteration through a sequence. However, container\nobjects can supply the following special method with a more efficient\nimplementation, which also does not require the object be a sequence.\n\nobject.__contains__(self, item)\n\n Called to implement membership test operators. Should return true\n if *item* is in *self*, false otherwise. For mapping objects, this\n should consider the keys of the mapping rather than the values or\n the key-item pairs.\n\n For objects that don\'t define "__contains__()", the membership test\n first tries iteration via "__iter__()", then the old sequence\n iteration protocol via "__getitem__()", see *this section in the\n language reference*.\n\n\nEmulating numeric types\n=======================\n\nThe following methods can be defined to emulate numeric objects.\nMethods corresponding to operations that are not supported by the\nparticular kind of number implemented (e.g., bitwise operations for\nnon-integral numbers) should be left undefined.\n\nobject.__add__(self, other)\nobject.__sub__(self, other)\nobject.__mul__(self, other)\nobject.__matmul__(self, other)\nobject.__truediv__(self, other)\nobject.__floordiv__(self, other)\nobject.__mod__(self, other)\nobject.__divmod__(self, other)\nobject.__pow__(self, other[, modulo])\nobject.__lshift__(self, other)\nobject.__rshift__(self, other)\nobject.__and__(self, other)\nobject.__xor__(self, other)\nobject.__or__(self, other)\n\n These methods are called to implement the binary arithmetic\n operations ("+", "-", "*", "@", "/", "//", "%", "divmod()",\n "pow()", "**", "<<", ">>", "&", "^", "|"). For instance, to\n evaluate the expression "x + y", where *x* is an instance of a\n class that has an "__add__()" method, "x.__add__(y)" is called.\n The "__divmod__()" method should be the equivalent to using\n "__floordiv__()" and "__mod__()"; it should not be related to\n "__truediv__()". Note that "__pow__()" should be defined to accept\n an optional third argument if the ternary version of the built-in\n "pow()" function is to be supported.\n\n If one of those methods does not support the operation with the\n supplied arguments, it should return "NotImplemented".\n\nobject.__radd__(self, other)\nobject.__rsub__(self, other)\nobject.__rmul__(self, other)\nobject.__rmatmul__(self, other)\nobject.__rtruediv__(self, other)\nobject.__rfloordiv__(self, other)\nobject.__rmod__(self, other)\nobject.__rdivmod__(self, other)\nobject.__rpow__(self, other)\nobject.__rlshift__(self, other)\nobject.__rrshift__(self, other)\nobject.__rand__(self, other)\nobject.__rxor__(self, other)\nobject.__ror__(self, other)\n\n These methods are called to implement the binary arithmetic\n operations ("+", "-", "*", "@", "/", "//", "%", "divmod()",\n "pow()", "**", "<<", ">>", "&", "^", "|") with reflected (swapped)\n operands. These functions are only called if the left operand does\n not support the corresponding operation and the operands are of\n different types. [2] For instance, to evaluate the expression "x -\n y", where *y* is an instance of a class that has an "__rsub__()"\n method, "y.__rsub__(x)" is called if "x.__sub__(y)" returns\n *NotImplemented*.\n\n Note that ternary "pow()" will not try calling "__rpow__()" (the\n coercion rules would become too complicated).\n\n Note: If the right operand\'s type is a subclass of the left\n operand\'s type and that subclass provides the reflected method\n for the operation, this method will be called before the left\n operand\'s non-reflected method. This behavior allows subclasses\n to override their ancestors\' operations.\n\nobject.__iadd__(self, other)\nobject.__isub__(self, other)\nobject.__imul__(self, other)\nobject.__imatmul__(self, other)\nobject.__itruediv__(self, other)\nobject.__ifloordiv__(self, other)\nobject.__imod__(self, other)\nobject.__ipow__(self, other[, modulo])\nobject.__ilshift__(self, other)\nobject.__irshift__(self, other)\nobject.__iand__(self, other)\nobject.__ixor__(self, other)\nobject.__ior__(self, other)\n\n These methods are called to implement the augmented arithmetic\n assignments ("+=", "-=", "*=", "@=", "/=", "//=", "%=", "**=",\n "<<=", ">>=", "&=", "^=", "|="). These methods should attempt to\n do the operation in-place (modifying *self*) and return the result\n (which could be, but does not have to be, *self*). If a specific\n method is not defined, the augmented assignment falls back to the\n normal methods. For instance, if *x* is an instance of a class\n with an "__iadd__()" method, "x += y" is equivalent to "x =\n x.__iadd__(y)" . Otherwise, "x.__add__(y)" and "y.__radd__(x)" are\n considered, as with the evaluation of "x + y". In certain\n situations, augmented assignment can result in unexpected errors\n (see *Why does a_tuple[i] += [\'item\'] raise an exception when the\n addition works?*), but this behavior is in fact part of the data\n model.\n\nobject.__neg__(self)\nobject.__pos__(self)\nobject.__abs__(self)\nobject.__invert__(self)\n\n Called to implement the unary arithmetic operations ("-", "+",\n "abs()" and "~").\n\nobject.__complex__(self)\nobject.__int__(self)\nobject.__float__(self)\nobject.__round__(self[, n])\n\n Called to implement the built-in functions "complex()", "int()",\n "float()" and "round()". Should return a value of the appropriate\n type.\n\nobject.__index__(self)\n\n Called to implement "operator.index()", and whenever Python needs\n to losslessly convert the numeric object to an integer object (such\n as in slicing, or in the built-in "bin()", "hex()" and "oct()"\n functions). Presence of this method indicates that the numeric\n object is an integer type. Must return an integer.\n\n Note: In order to have a coherent integer type class, when\n "__index__()" is defined "__int__()" should also be defined, and\n both should return the same value.\n\n\nWith Statement Context Managers\n===============================\n\nA *context manager* is an object that defines the runtime context to\nbe established when executing a "with" statement. The context manager\nhandles the entry into, and the exit from, the desired runtime context\nfor the execution of the block of code. Context managers are normally\ninvoked using the "with" statement (described in section *The with\nstatement*), but can also be used by directly invoking their methods.\n\nTypical uses of context managers include saving and restoring various\nkinds of global state, locking and unlocking resources, closing opened\nfiles, etc.\n\nFor more information on context managers, see *Context Manager Types*.\n\nobject.__enter__(self)\n\n Enter the runtime context related to this object. The "with"\n statement will bind this method\'s return value to the target(s)\n specified in the "as" clause of the statement, if any.\n\nobject.__exit__(self, exc_type, exc_value, traceback)\n\n Exit the runtime context related to this object. The parameters\n describe the exception that caused the context to be exited. If the\n context was exited without an exception, all three arguments will\n be "None".\n\n If an exception is supplied, and the method wishes to suppress the\n exception (i.e., prevent it from being propagated), it should\n return a true value. Otherwise, the exception will be processed\n normally upon exit from this method.\n\n Note that "__exit__()" methods should not reraise the passed-in\n exception; this is the caller\'s responsibility.\n\nSee also: **PEP 0343** - The "with" statement\n\n The specification, background, and examples for the Python "with"\n statement.\n\n\nSpecial method lookup\n=====================\n\nFor custom classes, implicit invocations of special methods are only\nguaranteed to work correctly if defined on an object\'s type, not in\nthe object\'s instance dictionary. That behaviour is the reason why\nthe following code raises an exception:\n\n >>> class C:\n ... pass\n ...\n >>> c = C()\n >>> c.__len__ = lambda: 5\n >>> len(c)\n Traceback (most recent call last):\n File "<stdin>", line 1, in <module>\n TypeError: object of type \'C\' has no len()\n\nThe rationale behind this behaviour lies with a number of special\nmethods such as "__hash__()" and "__repr__()" that are implemented by\nall objects, including type objects. If the implicit lookup of these\nmethods used the conventional lookup process, they would fail when\ninvoked on the type object itself:\n\n >>> 1 .__hash__() == hash(1)\n True\n >>> int.__hash__() == hash(int)\n Traceback (most recent call last):\n File "<stdin>", line 1, in <module>\n TypeError: descriptor \'__hash__\' of \'int\' object needs an argument\n\nIncorrectly attempting to invoke an unbound method of a class in this\nway is sometimes referred to as \'metaclass confusion\', and is avoided\nby bypassing the instance when looking up special methods:\n\n >>> type(1).__hash__(1) == hash(1)\n True\n >>> type(int).__hash__(int) == hash(int)\n True\n\nIn addition to bypassing any instance attributes in the interest of\ncorrectness, implicit special method lookup generally also bypasses\nthe "__getattribute__()" method even of the object\'s metaclass:\n\n >>> class Meta(type):\n ... def __getattribute__(*args):\n ... print("Metaclass getattribute invoked")\n ... return type.__getattribute__(*args)\n ...\n >>> class C(object, metaclass=Meta):\n ... def __len__(self):\n ... return 10\n ... def __getattribute__(*args):\n ... print("Class getattribute invoked")\n ... return object.__getattribute__(*args)\n ...\n >>> c = C()\n >>> c.__len__() # Explicit lookup via instance\n Class getattribute invoked\n 10\n >>> type(c).__len__(c) # Explicit lookup via type\n Metaclass getattribute invoked\n 10\n >>> len(c) # Implicit lookup\n 10\n\nBypassing the "__getattribute__()" machinery in this fashion provides\nsignificant scope for speed optimisations within the interpreter, at\nthe cost of some flexibility in the handling of special methods (the\nspecial method *must* be set on the class object itself in order to be\nconsistently invoked by the interpreter).\n',
- 'string-methods': u'\nString Methods\n**************\n\nStrings implement all of the *common* sequence operations, along with\nthe additional methods described below.\n\nStrings also support two styles of string formatting, one providing a\nlarge degree of flexibility and customization (see "str.format()",\n*Format String Syntax* and *String Formatting*) and the other based on\nC "printf" style formatting that handles a narrower range of types and\nis slightly harder to use correctly, but is often faster for the cases\nit can handle (*printf-style String Formatting*).\n\nThe *Text Processing Services* section of the standard library covers\na number of other modules that provide various text related utilities\n(including regular expression support in the "re" module).\n\nstr.capitalize()\n\n Return a copy of the string with its first character capitalized\n and the rest lowercased.\n\nstr.casefold()\n\n Return a casefolded copy of the string. Casefolded strings may be\n used for caseless matching.\n\n Casefolding is similar to lowercasing but more aggressive because\n it is intended to remove all case distinctions in a string. For\n example, the German lowercase letter "\'\xdf\'" is equivalent to ""ss"".\n Since it is already lowercase, "lower()" would do nothing to "\'\xdf\'";\n "casefold()" converts it to ""ss"".\n\n The casefolding algorithm is described in section 3.13 of the\n Unicode Standard.\n\n New in version 3.3.\n\nstr.center(width[, fillchar])\n\n Return centered in a string of length *width*. Padding is done\n using the specified *fillchar* (default is an ASCII space). The\n original string is returned if *width* is less than or equal to\n "len(s)".\n\nstr.count(sub[, start[, end]])\n\n Return the number of non-overlapping occurrences of substring *sub*\n in the range [*start*, *end*]. Optional arguments *start* and\n *end* are interpreted as in slice notation.\n\nstr.encode(encoding="utf-8", errors="strict")\n\n Return an encoded version of the string as a bytes object. Default\n encoding is "\'utf-8\'". *errors* may be given to set a different\n error handling scheme. The default for *errors* is "\'strict\'",\n meaning that encoding errors raise a "UnicodeError". Other possible\n values are "\'ignore\'", "\'replace\'", "\'xmlcharrefreplace\'",\n "\'backslashreplace\'" and any other name registered via\n "codecs.register_error()", see section *Error Handlers*. For a list\n of possible encodings, see section *Standard Encodings*.\n\n Changed in version 3.1: Support for keyword arguments added.\n\nstr.endswith(suffix[, start[, end]])\n\n Return "True" if the string ends with the specified *suffix*,\n otherwise return "False". *suffix* can also be a tuple of suffixes\n to look for. With optional *start*, test beginning at that\n position. With optional *end*, stop comparing at that position.\n\nstr.expandtabs(tabsize=8)\n\n Return a copy of the string where all tab characters are replaced\n by one or more spaces, depending on the current column and the\n given tab size. Tab positions occur every *tabsize* characters\n (default is 8, giving tab positions at columns 0, 8, 16 and so on).\n To expand the string, the current column is set to zero and the\n string is examined character by character. If the character is a\n tab ("\\t"), one or more space characters are inserted in the result\n until the current column is equal to the next tab position. (The\n tab character itself is not copied.) If the character is a newline\n ("\\n") or return ("\\r"), it is copied and the current column is\n reset to zero. Any other character is copied unchanged and the\n current column is incremented by one regardless of how the\n character is represented when printed.\n\n >>> \'01\\t012\\t0123\\t01234\'.expandtabs()\n \'01 012 0123 01234\'\n >>> \'01\\t012\\t0123\\t01234\'.expandtabs(4)\n \'01 012 0123 01234\'\n\nstr.find(sub[, start[, end]])\n\n Return the lowest index in the string where substring *sub* is\n found, such that *sub* is contained in the slice "s[start:end]".\n Optional arguments *start* and *end* are interpreted as in slice\n notation. Return "-1" if *sub* is not found.\n\n Note: The "find()" method should be used only if you need to know\n the position of *sub*. To check if *sub* is a substring or not,\n use the "in" operator:\n\n >>> \'Py\' in \'Python\'\n True\n\nstr.format(*args, **kwargs)\n\n Perform a string formatting operation. The string on which this\n method is called can contain literal text or replacement fields\n delimited by braces "{}". Each replacement field contains either\n the numeric index of a positional argument, or the name of a\n keyword argument. Returns a copy of the string where each\n replacement field is replaced with the string value of the\n corresponding argument.\n\n >>> "The sum of 1 + 2 is {0}".format(1+2)\n \'The sum of 1 + 2 is 3\'\n\n See *Format String Syntax* for a description of the various\n formatting options that can be specified in format strings.\n\nstr.format_map(mapping)\n\n Similar to "str.format(**mapping)", except that "mapping" is used\n directly and not copied to a "dict". This is useful if for example\n "mapping" is a dict subclass:\n\n >>> class Default(dict):\n ... def __missing__(self, key):\n ... return key\n ...\n >>> \'{name} was born in {country}\'.format_map(Default(name=\'Guido\'))\n \'Guido was born in country\'\n\n New in version 3.2.\n\nstr.index(sub[, start[, end]])\n\n Like "find()", but raise "ValueError" when the substring is not\n found.\n\nstr.isalnum()\n\n Return true if all characters in the string are alphanumeric and\n there is at least one character, false otherwise. A character "c"\n is alphanumeric if one of the following returns "True":\n "c.isalpha()", "c.isdecimal()", "c.isdigit()", or "c.isnumeric()".\n\nstr.isalpha()\n\n Return true if all characters in the string are alphabetic and\n there is at least one character, false otherwise. Alphabetic\n characters are those characters defined in the Unicode character\n database as "Letter", i.e., those with general category property\n being one of "Lm", "Lt", "Lu", "Ll", or "Lo". Note that this is\n different from the "Alphabetic" property defined in the Unicode\n Standard.\n\nstr.isdecimal()\n\n Return true if all characters in the string are decimal characters\n and there is at least one character, false otherwise. Decimal\n characters are those from general category "Nd". This category\n includes digit characters, and all characters that can be used to\n form decimal-radix numbers, e.g. U+0660, ARABIC-INDIC DIGIT ZERO.\n\nstr.isdigit()\n\n Return true if all characters in the string are digits and there is\n at least one character, false otherwise. Digits include decimal\n characters and digits that need special handling, such as the\n compatibility superscript digits. Formally, a digit is a character\n that has the property value Numeric_Type=Digit or\n Numeric_Type=Decimal.\n\nstr.isidentifier()\n\n Return true if the string is a valid identifier according to the\n language definition, section *Identifiers and keywords*.\n\n Use "keyword.iskeyword()" to test for reserved identifiers such as\n "def" and "class".\n\nstr.islower()\n\n Return true if all cased characters [4] in the string are lowercase\n and there is at least one cased character, false otherwise.\n\nstr.isnumeric()\n\n Return true if all characters in the string are numeric characters,\n and there is at least one character, false otherwise. Numeric\n characters include digit characters, and all characters that have\n the Unicode numeric value property, e.g. U+2155, VULGAR FRACTION\n ONE FIFTH. Formally, numeric characters are those with the\n property value Numeric_Type=Digit, Numeric_Type=Decimal or\n Numeric_Type=Numeric.\n\nstr.isprintable()\n\n Return true if all characters in the string are printable or the\n string is empty, false otherwise. Nonprintable characters are\n those characters defined in the Unicode character database as\n "Other" or "Separator", excepting the ASCII space (0x20) which is\n considered printable. (Note that printable characters in this\n context are those which should not be escaped when "repr()" is\n invoked on a string. It has no bearing on the handling of strings\n written to "sys.stdout" or "sys.stderr".)\n\nstr.isspace()\n\n Return true if there are only whitespace characters in the string\n and there is at least one character, false otherwise. Whitespace\n characters are those characters defined in the Unicode character\n database as "Other" or "Separator" and those with bidirectional\n property being one of "WS", "B", or "S".\n\nstr.istitle()\n\n Return true if the string is a titlecased string and there is at\n least one character, for example uppercase characters may only\n follow uncased characters and lowercase characters only cased ones.\n Return false otherwise.\n\nstr.isupper()\n\n Return true if all cased characters [4] in the string are uppercase\n and there is at least one cased character, false otherwise.\n\nstr.join(iterable)\n\n Return a string which is the concatenation of the strings in the\n *iterable* *iterable*. A "TypeError" will be raised if there are\n any non-string values in *iterable*, including "bytes" objects.\n The separator between elements is the string providing this method.\n\nstr.ljust(width[, fillchar])\n\n Return the string left justified in a string of length *width*.\n Padding is done using the specified *fillchar* (default is an ASCII\n space). The original string is returned if *width* is less than or\n equal to "len(s)".\n\nstr.lower()\n\n Return a copy of the string with all the cased characters [4]\n converted to lowercase.\n\n The lowercasing algorithm used is described in section 3.13 of the\n Unicode Standard.\n\nstr.lstrip([chars])\n\n Return a copy of the string with leading characters removed. The\n *chars* argument is a string specifying the set of characters to be\n removed. If omitted or "None", the *chars* argument defaults to\n removing whitespace. The *chars* argument is not a prefix; rather,\n all combinations of its values are stripped:\n\n >>> \' spacious \'.lstrip()\n \'spacious \'\n >>> \'www.example.com\'.lstrip(\'cmowz.\')\n \'example.com\'\n\nstatic str.maketrans(x[, y[, z]])\n\n This static method returns a translation table usable for\n "str.translate()".\n\n If there is only one argument, it must be a dictionary mapping\n Unicode ordinals (integers) or characters (strings of length 1) to\n Unicode ordinals, strings (of arbitrary lengths) or None.\n Character keys will then be converted to ordinals.\n\n If there are two arguments, they must be strings of equal length,\n and in the resulting dictionary, each character in x will be mapped\n to the character at the same position in y. If there is a third\n argument, it must be a string, whose characters will be mapped to\n None in the result.\n\nstr.partition(sep)\n\n Split the string at the first occurrence of *sep*, and return a\n 3-tuple containing the part before the separator, the separator\n itself, and the part after the separator. If the separator is not\n found, return a 3-tuple containing the string itself, followed by\n two empty strings.\n\nstr.replace(old, new[, count])\n\n Return a copy of the string with all occurrences of substring *old*\n replaced by *new*. If the optional argument *count* is given, only\n the first *count* occurrences are replaced.\n\nstr.rfind(sub[, start[, end]])\n\n Return the highest index in the string where substring *sub* is\n found, such that *sub* is contained within "s[start:end]".\n Optional arguments *start* and *end* are interpreted as in slice\n notation. Return "-1" on failure.\n\nstr.rindex(sub[, start[, end]])\n\n Like "rfind()" but raises "ValueError" when the substring *sub* is\n not found.\n\nstr.rjust(width[, fillchar])\n\n Return the string right justified in a string of length *width*.\n Padding is done using the specified *fillchar* (default is an ASCII\n space). The original string is returned if *width* is less than or\n equal to "len(s)".\n\nstr.rpartition(sep)\n\n Split the string at the last occurrence of *sep*, and return a\n 3-tuple containing the part before the separator, the separator\n itself, and the part after the separator. If the separator is not\n found, return a 3-tuple containing two empty strings, followed by\n the string itself.\n\nstr.rsplit(sep=None, maxsplit=-1)\n\n Return a list of the words in the string, using *sep* as the\n delimiter string. If *maxsplit* is given, at most *maxsplit* splits\n are done, the *rightmost* ones. If *sep* is not specified or\n "None", any whitespace string is a separator. Except for splitting\n from the right, "rsplit()" behaves like "split()" which is\n described in detail below.\n\nstr.rstrip([chars])\n\n Return a copy of the string with trailing characters removed. The\n *chars* argument is a string specifying the set of characters to be\n removed. If omitted or "None", the *chars* argument defaults to\n removing whitespace. The *chars* argument is not a suffix; rather,\n all combinations of its values are stripped:\n\n >>> \' spacious \'.rstrip()\n \' spacious\'\n >>> \'mississippi\'.rstrip(\'ipz\')\n \'mississ\'\n\nstr.split(sep=None, maxsplit=-1)\n\n Return a list of the words in the string, using *sep* as the\n delimiter string. If *maxsplit* is given, at most *maxsplit*\n splits are done (thus, the list will have at most "maxsplit+1"\n elements). If *maxsplit* is not specified or "-1", then there is\n no limit on the number of splits (all possible splits are made).\n\n If *sep* is given, consecutive delimiters are not grouped together\n and are deemed to delimit empty strings (for example,\n "\'1,,2\'.split(\',\')" returns "[\'1\', \'\', \'2\']"). The *sep* argument\n may consist of multiple characters (for example,\n "\'1<>2<>3\'.split(\'<>\')" returns "[\'1\', \'2\', \'3\']"). Splitting an\n empty string with a specified separator returns "[\'\']".\n\n For example:\n\n >>> \'1,2,3\'.split(\',\')\n [\'1\', \'2\', \'3\']\n >>> \'1,2,3\'.split(\',\', maxsplit=1)\n [\'1\', \'2,3\']\n >>> \'1,2,,3,\'.split(\',\')\n [\'1\', \'2\', \'\', \'3\', \'\']\n\n If *sep* is not specified or is "None", a different splitting\n algorithm is applied: runs of consecutive whitespace are regarded\n as a single separator, and the result will contain no empty strings\n at the start or end if the string has leading or trailing\n whitespace. Consequently, splitting an empty string or a string\n consisting of just whitespace with a "None" separator returns "[]".\n\n For example:\n\n >>> \'1 2 3\'.split()\n [\'1\', \'2\', \'3\']\n >>> \'1 2 3\'.split(maxsplit=1)\n [\'1\', \'2 3\']\n >>> \' 1 2 3 \'.split()\n [\'1\', \'2\', \'3\']\n\nstr.splitlines([keepends])\n\n Return a list of the lines in the string, breaking at line\n boundaries. Line breaks are not included in the resulting list\n unless *keepends* is given and true.\n\n This method splits on the following line boundaries. In\n particular, the boundaries are a superset of *universal newlines*.\n\n +-------------------------+-------------------------------+\n | Representation | Description |\n +=========================+===============================+\n | "\\n" | Line Feed |\n +-------------------------+-------------------------------+\n | "\\r" | Carriage Return |\n +-------------------------+-------------------------------+\n | "\\r\\n" | Carriage Return + Line Feed |\n +-------------------------+-------------------------------+\n | "\\v" or "\\x0b" | Line Tabulation |\n +-------------------------+-------------------------------+\n | "\\f" or "\\x0c" | Form Feed |\n +-------------------------+-------------------------------+\n | "\\x1c" | File Separator |\n +-------------------------+-------------------------------+\n | "\\x1d" | Group Separator |\n +-------------------------+-------------------------------+\n | "\\x1e" | Record Separator |\n +-------------------------+-------------------------------+\n | "\\x85" | Next Line (C1 Control Code) |\n +-------------------------+-------------------------------+\n | "\\u2028" | Line Separator |\n +-------------------------+-------------------------------+\n | "\\u2029" | Paragraph Separator |\n +-------------------------+-------------------------------+\n\n Changed in version 3.2: "\\v" and "\\f" added to list of line\n boundaries.\n\n For example:\n\n >>> \'ab c\\n\\nde fg\\rkl\\r\\n\'.splitlines()\n [\'ab c\', \'\', \'de fg\', \'kl\']\n >>> \'ab c\\n\\nde fg\\rkl\\r\\n\'.splitlines(keepends=True)\n [\'ab c\\n\', \'\\n\', \'de fg\\r\', \'kl\\r\\n\']\n\n Unlike "split()" when a delimiter string *sep* is given, this\n method returns an empty list for the empty string, and a terminal\n line break does not result in an extra line:\n\n >>> "".splitlines()\n []\n >>> "One line\\n".splitlines()\n [\'One line\']\n\n For comparison, "split(\'\\n\')" gives:\n\n >>> \'\'.split(\'\\n\')\n [\'\']\n >>> \'Two lines\\n\'.split(\'\\n\')\n [\'Two lines\', \'\']\n\nstr.startswith(prefix[, start[, end]])\n\n Return "True" if string starts with the *prefix*, otherwise return\n "False". *prefix* can also be a tuple of prefixes to look for.\n With optional *start*, test string beginning at that position.\n With optional *end*, stop comparing string at that position.\n\nstr.strip([chars])\n\n Return a copy of the string with the leading and trailing\n characters removed. The *chars* argument is a string specifying the\n set of characters to be removed. If omitted or "None", the *chars*\n argument defaults to removing whitespace. The *chars* argument is\n not a prefix or suffix; rather, all combinations of its values are\n stripped:\n\n >>> \' spacious \'.strip()\n \'spacious\'\n >>> \'www.example.com\'.strip(\'cmowz.\')\n \'example\'\n\n The outermost leading and trailing *chars* argument values are\n stripped from the string. Characters are removed from the leading\n end until reaching a string character that is not contained in the\n set of characters in *chars*. A similar action takes place on the\n trailing end. For example:\n\n >>> comment_string = \'#....... Section 3.2.1 Issue #32 .......\'\n >>> comment_string.strip(\'.#! \')\n \'Section 3.2.1 Issue #32\'\n\nstr.swapcase()\n\n Return a copy of the string with uppercase characters converted to\n lowercase and vice versa. Note that it is not necessarily true that\n "s.swapcase().swapcase() == s".\n\nstr.title()\n\n Return a titlecased version of the string where words start with an\n uppercase character and the remaining characters are lowercase.\n\n For example:\n\n >>> \'Hello world\'.title()\n \'Hello World\'\n\n The algorithm uses a simple language-independent definition of a\n word as groups of consecutive letters. The definition works in\n many contexts but it means that apostrophes in contractions and\n possessives form word boundaries, which may not be the desired\n result:\n\n >>> "they\'re bill\'s friends from the UK".title()\n "They\'Re Bill\'S Friends From The Uk"\n\n A workaround for apostrophes can be constructed using regular\n expressions:\n\n >>> import re\n >>> def titlecase(s):\n ... return re.sub(r"[A-Za-z]+(\'[A-Za-z]+)?",\n ... lambda mo: mo.group(0)[0].upper() +\n ... mo.group(0)[1:].lower(),\n ... s)\n ...\n >>> titlecase("they\'re bill\'s friends.")\n "They\'re Bill\'s Friends."\n\nstr.translate(table)\n\n Return a copy of the string in which each character has been mapped\n through the given translation table. The table must be an object\n that implements indexing via "__getitem__()", typically a *mapping*\n or *sequence*. When indexed by a Unicode ordinal (an integer), the\n table object can do any of the following: return a Unicode ordinal\n or a string, to map the character to one or more other characters;\n return "None", to delete the character from the return string; or\n raise a "LookupError" exception, to map the character to itself.\n\n You can use "str.maketrans()" to create a translation map from\n character-to-character mappings in different formats.\n\n See also the "codecs" module for a more flexible approach to custom\n character mappings.\n\nstr.upper()\n\n Return a copy of the string with all the cased characters [4]\n converted to uppercase. Note that "str.upper().isupper()" might be\n "False" if "s" contains uncased characters or if the Unicode\n category of the resulting character(s) is not "Lu" (Letter,\n uppercase), but e.g. "Lt" (Letter, titlecase).\n\n The uppercasing algorithm used is described in section 3.13 of the\n Unicode Standard.\n\nstr.zfill(width)\n\n Return a copy of the string left filled with ASCII "\'0\'" digits to\n make a string of length *width*. A leading sign prefix\n ("\'+\'"/"\'-\'") is handled by inserting the padding *after* the sign\n character rather than before. The original string is returned if\n *width* is less than or equal to "len(s)".\n\n For example:\n\n >>> "42".zfill(5)\n \'00042\'\n >>> "-42".zfill(5)\n \'-0042\'\n',
- 'strings': u'\nString and Bytes literals\n*************************\n\nString literals are described by the following lexical definitions:\n\n stringliteral ::= [stringprefix](shortstring | longstring)\n stringprefix ::= "r" | "u" | "R" | "U"\n shortstring ::= "\'" shortstringitem* "\'" | \'"\' shortstringitem* \'"\'\n longstring ::= "\'\'\'" longstringitem* "\'\'\'" | \'"""\' longstringitem* \'"""\'\n shortstringitem ::= shortstringchar | stringescapeseq\n longstringitem ::= longstringchar | stringescapeseq\n shortstringchar ::= <any source character except "\\" or newline or the quote>\n longstringchar ::= <any source character except "\\">\n stringescapeseq ::= "\\" <any source character>\n\n bytesliteral ::= bytesprefix(shortbytes | longbytes)\n bytesprefix ::= "b" | "B" | "br" | "Br" | "bR" | "BR" | "rb" | "rB" | "Rb" | "RB"\n shortbytes ::= "\'" shortbytesitem* "\'" | \'"\' shortbytesitem* \'"\'\n longbytes ::= "\'\'\'" longbytesitem* "\'\'\'" | \'"""\' longbytesitem* \'"""\'\n shortbytesitem ::= shortbyteschar | bytesescapeseq\n longbytesitem ::= longbyteschar | bytesescapeseq\n shortbyteschar ::= <any ASCII character except "\\" or newline or the quote>\n longbyteschar ::= <any ASCII character except "\\">\n bytesescapeseq ::= "\\" <any ASCII character>\n\nOne syntactic restriction not indicated by these productions is that\nwhitespace is not allowed between the "stringprefix" or "bytesprefix"\nand the rest of the literal. The source character set is defined by\nthe encoding declaration; it is UTF-8 if no encoding declaration is\ngiven in the source file; see section *Encoding declarations*.\n\nIn plain English: Both types of literals can be enclosed in matching\nsingle quotes ("\'") or double quotes ("""). They can also be enclosed\nin matching groups of three single or double quotes (these are\ngenerally referred to as *triple-quoted strings*). The backslash\n("\\") character is used to escape characters that otherwise have a\nspecial meaning, such as newline, backslash itself, or the quote\ncharacter.\n\nBytes literals are always prefixed with "\'b\'" or "\'B\'"; they produce\nan instance of the "bytes" type instead of the "str" type. They may\nonly contain ASCII characters; bytes with a numeric value of 128 or\ngreater must be expressed with escapes.\n\nAs of Python 3.3 it is possible again to prefix string literals with a\n"u" prefix to simplify maintenance of dual 2.x and 3.x codebases.\n\nBoth string and bytes literals may optionally be prefixed with a\nletter "\'r\'" or "\'R\'"; such strings are called *raw strings* and treat\nbackslashes as literal characters. As a result, in string literals,\n"\'\\U\'" and "\'\\u\'" escapes in raw strings are not treated specially.\nGiven that Python 2.x\'s raw unicode literals behave differently than\nPython 3.x\'s the "\'ur\'" syntax is not supported.\n\nNew in version 3.3: The "\'rb\'" prefix of raw bytes literals has been\nadded as a synonym of "\'br\'".\n\nNew in version 3.3: Support for the unicode legacy literal\n("u\'value\'") was reintroduced to simplify the maintenance of dual\nPython 2.x and 3.x codebases. See **PEP 414** for more information.\n\nIn triple-quoted literals, unescaped newlines and quotes are allowed\n(and are retained), except that three unescaped quotes in a row\nterminate the literal. (A "quote" is the character used to open the\nliteral, i.e. either "\'" or """.)\n\nUnless an "\'r\'" or "\'R\'" prefix is present, escape sequences in string\nand bytes literals are interpreted according to rules similar to those\nused by Standard C. The recognized escape sequences are:\n\n+-------------------+-----------------------------------+---------+\n| Escape Sequence | Meaning | Notes |\n+===================+===================================+=========+\n| "\\newline" | Backslash and newline ignored | |\n+-------------------+-----------------------------------+---------+\n| "\\\\" | Backslash ("\\") | |\n+-------------------+-----------------------------------+---------+\n| "\\\'" | Single quote ("\'") | |\n+-------------------+-----------------------------------+---------+\n| "\\"" | Double quote (""") | |\n+-------------------+-----------------------------------+---------+\n| "\\a" | ASCII Bell (BEL) | |\n+-------------------+-----------------------------------+---------+\n| "\\b" | ASCII Backspace (BS) | |\n+-------------------+-----------------------------------+---------+\n| "\\f" | ASCII Formfeed (FF) | |\n+-------------------+-----------------------------------+---------+\n| "\\n" | ASCII Linefeed (LF) | |\n+-------------------+-----------------------------------+---------+\n| "\\r" | ASCII Carriage Return (CR) | |\n+-------------------+-----------------------------------+---------+\n| "\\t" | ASCII Horizontal Tab (TAB) | |\n+-------------------+-----------------------------------+---------+\n| "\\v" | ASCII Vertical Tab (VT) | |\n+-------------------+-----------------------------------+---------+\n| "\\ooo" | Character with octal value *ooo* | (1,3) |\n+-------------------+-----------------------------------+---------+\n| "\\xhh" | Character with hex value *hh* | (2,3) |\n+-------------------+-----------------------------------+---------+\n\nEscape sequences only recognized in string literals are:\n\n+-------------------+-----------------------------------+---------+\n| Escape Sequence | Meaning | Notes |\n+===================+===================================+=========+\n| "\\N{name}" | Character named *name* in the | (4) |\n| | Unicode database | |\n+-------------------+-----------------------------------+---------+\n| "\\uxxxx" | Character with 16-bit hex value | (5) |\n| | *xxxx* | |\n+-------------------+-----------------------------------+---------+\n| "\\Uxxxxxxxx" | Character with 32-bit hex value | (6) |\n| | *xxxxxxxx* | |\n+-------------------+-----------------------------------+---------+\n\nNotes:\n\n1. As in Standard C, up to three octal digits are accepted.\n\n2. Unlike in Standard C, exactly two hex digits are required.\n\n3. In a bytes literal, hexadecimal and octal escapes denote the\n byte with the given value. In a string literal, these escapes\n denote a Unicode character with the given value.\n\n4. Changed in version 3.3: Support for name aliases [1] has been\n added.\n\n5. Individual code units which form parts of a surrogate pair can\n be encoded using this escape sequence. Exactly four hex digits are\n required.\n\n6. Any Unicode character can be encoded this way. Exactly eight\n hex digits are required.\n\nUnlike Standard C, all unrecognized escape sequences are left in the\nstring unchanged, i.e., *the backslash is left in the result*. (This\nbehavior is useful when debugging: if an escape sequence is mistyped,\nthe resulting output is more easily recognized as broken.) It is also\nimportant to note that the escape sequences only recognized in string\nliterals fall into the category of unrecognized escapes for bytes\nliterals.\n\nEven in a raw literal, quotes can be escaped with a backslash, but the\nbackslash remains in the result; for example, "r"\\""" is a valid\nstring literal consisting of two characters: a backslash and a double\nquote; "r"\\"" is not a valid string literal (even a raw string cannot\nend in an odd number of backslashes). Specifically, *a raw literal\ncannot end in a single backslash* (since the backslash would escape\nthe following quote character). Note also that a single backslash\nfollowed by a newline is interpreted as those two characters as part\nof the literal, *not* as a line continuation.\n',
+ 'specialnames': u'\nSpecial method names\n********************\n\nA class can implement certain operations that are invoked by special\nsyntax (such as arithmetic operations or subscripting and slicing) by\ndefining methods with special names. This is Python\'s approach to\n*operator overloading*, allowing classes to define their own behavior\nwith respect to language operators. For instance, if a class defines\na method named "__getitem__()", and "x" is an instance of this class,\nthen "x[i]" is roughly equivalent to "type(x).__getitem__(x, i)".\nExcept where mentioned, attempts to execute an operation raise an\nexception when no appropriate method is defined (typically\n"AttributeError" or "TypeError").\n\nWhen implementing a class that emulates any built-in type, it is\nimportant that the emulation only be implemented to the degree that it\nmakes sense for the object being modelled. For example, some\nsequences may work well with retrieval of individual elements, but\nextracting a slice may not make sense. (One example of this is the\n"NodeList" interface in the W3C\'s Document Object Model.)\n\n\nBasic customization\n===================\n\nobject.__new__(cls[, ...])\n\n Called to create a new instance of class *cls*. "__new__()" is a\n static method (special-cased so you need not declare it as such)\n that takes the class of which an instance was requested as its\n first argument. The remaining arguments are those passed to the\n object constructor expression (the call to the class). The return\n value of "__new__()" should be the new object instance (usually an\n instance of *cls*).\n\n Typical implementations create a new instance of the class by\n invoking the superclass\'s "__new__()" method using\n "super(currentclass, cls).__new__(cls[, ...])" with appropriate\n arguments and then modifying the newly-created instance as\n necessary before returning it.\n\n If "__new__()" returns an instance of *cls*, then the new\n instance\'s "__init__()" method will be invoked like\n "__init__(self[, ...])", where *self* is the new instance and the\n remaining arguments are the same as were passed to "__new__()".\n\n If "__new__()" does not return an instance of *cls*, then the new\n instance\'s "__init__()" method will not be invoked.\n\n "__new__()" is intended mainly to allow subclasses of immutable\n types (like int, str, or tuple) to customize instance creation. It\n is also commonly overridden in custom metaclasses in order to\n customize class creation.\n\nobject.__init__(self[, ...])\n\n Called after the instance has been created (by "__new__()"), but\n before it is returned to the caller. The arguments are those\n passed to the class constructor expression. If a base class has an\n "__init__()" method, the derived class\'s "__init__()" method, if\n any, must explicitly call it to ensure proper initialization of the\n base class part of the instance; for example:\n "BaseClass.__init__(self, [args...])".\n\n Because "__new__()" and "__init__()" work together in constructing\n objects ("__new__()" to create it, and "__init__()" to customise\n it), no non-"None" value may be returned by "__init__()"; doing so\n will cause a "TypeError" to be raised at runtime.\n\nobject.__del__(self)\n\n Called when the instance is about to be destroyed. This is also\n called a destructor. If a base class has a "__del__()" method, the\n derived class\'s "__del__()" method, if any, must explicitly call it\n to ensure proper deletion of the base class part of the instance.\n Note that it is possible (though not recommended!) for the\n "__del__()" method to postpone destruction of the instance by\n creating a new reference to it. It may then be called at a later\n time when this new reference is deleted. It is not guaranteed that\n "__del__()" methods are called for objects that still exist when\n the interpreter exits.\n\n Note: "del x" doesn\'t directly call "x.__del__()" --- the former\n decrements the reference count for "x" by one, and the latter is\n only called when "x"\'s reference count reaches zero. Some common\n situations that may prevent the reference count of an object from\n going to zero include: circular references between objects (e.g.,\n a doubly-linked list or a tree data structure with parent and\n child pointers); a reference to the object on the stack frame of\n a function that caught an exception (the traceback stored in\n "sys.exc_info()[2]" keeps the stack frame alive); or a reference\n to the object on the stack frame that raised an unhandled\n exception in interactive mode (the traceback stored in\n "sys.last_traceback" keeps the stack frame alive). The first\n situation can only be remedied by explicitly breaking the cycles;\n the second can be resolved by freeing the reference to the\n traceback object when it is no longer useful, and the third can\n be resolved by storing "None" in "sys.last_traceback". Circular\n references which are garbage are detected and cleaned up when the\n cyclic garbage collector is enabled (it\'s on by default). Refer\n to the documentation for the "gc" module for more information\n about this topic.\n\n Warning: Due to the precarious circumstances under which\n "__del__()" methods are invoked, exceptions that occur during\n their execution are ignored, and a warning is printed to\n "sys.stderr" instead. Also, when "__del__()" is invoked in\n response to a module being deleted (e.g., when execution of the\n program is done), other globals referenced by the "__del__()"\n method may already have been deleted or in the process of being\n torn down (e.g. the import machinery shutting down). For this\n reason, "__del__()" methods should do the absolute minimum needed\n to maintain external invariants. Starting with version 1.5,\n Python guarantees that globals whose name begins with a single\n underscore are deleted from their module before other globals are\n deleted; if no other references to such globals exist, this may\n help in assuring that imported modules are still available at the\n time when the "__del__()" method is called.\n\nobject.__repr__(self)\n\n Called by the "repr()" built-in function to compute the "official"\n string representation of an object. If at all possible, this\n should look like a valid Python expression that could be used to\n recreate an object with the same value (given an appropriate\n environment). If this is not possible, a string of the form\n "<...some useful description...>" should be returned. The return\n value must be a string object. If a class defines "__repr__()" but\n not "__str__()", then "__repr__()" is also used when an "informal"\n string representation of instances of that class is required.\n\n This is typically used for debugging, so it is important that the\n representation is information-rich and unambiguous.\n\nobject.__str__(self)\n\n Called by "str(object)" and the built-in functions "format()" and\n "print()" to compute the "informal" or nicely printable string\n representation of an object. The return value must be a *string*\n object.\n\n This method differs from "object.__repr__()" in that there is no\n expectation that "__str__()" return a valid Python expression: a\n more convenient or concise representation can be used.\n\n The default implementation defined by the built-in type "object"\n calls "object.__repr__()".\n\nobject.__bytes__(self)\n\n Called by "bytes()" to compute a byte-string representation of an\n object. This should return a "bytes" object.\n\nobject.__format__(self, format_spec)\n\n Called by the "format()" built-in function (and by extension, the\n "str.format()" method of class "str") to produce a "formatted"\n string representation of an object. The "format_spec" argument is a\n string that contains a description of the formatting options\n desired. The interpretation of the "format_spec" argument is up to\n the type implementing "__format__()", however most classes will\n either delegate formatting to one of the built-in types, or use a\n similar formatting option syntax.\n\n See *Format Specification Mini-Language* for a description of the\n standard formatting syntax.\n\n The return value must be a string object.\n\n Changed in version 3.4: The __format__ method of "object" itself\n raises a "TypeError" if passed any non-empty string.\n\nobject.__lt__(self, other)\nobject.__le__(self, other)\nobject.__eq__(self, other)\nobject.__ne__(self, other)\nobject.__gt__(self, other)\nobject.__ge__(self, other)\n\n These are the so-called "rich comparison" methods. The\n correspondence between operator symbols and method names is as\n follows: "x<y" calls "x.__lt__(y)", "x<=y" calls "x.__le__(y)",\n "x==y" calls "x.__eq__(y)", "x!=y" calls "x.__ne__(y)", "x>y" calls\n "x.__gt__(y)", and "x>=y" calls "x.__ge__(y)".\n\n A rich comparison method may return the singleton "NotImplemented"\n if it does not implement the operation for a given pair of\n arguments. By convention, "False" and "True" are returned for a\n successful comparison. However, these methods can return any value,\n so if the comparison operator is used in a Boolean context (e.g.,\n in the condition of an "if" statement), Python will call "bool()"\n on the value to determine if the result is true or false.\n\n By default, "__ne__()" delegates to "__eq__()" and inverts the\n result unless it is "NotImplemented". There are no other implied\n relationships among the comparison operators, for example, the\n truth of "(x<y or x==y)" does not imply "x<=y". To automatically\n generate ordering operations from a single root operation, see\n "functools.total_ordering()".\n\n See the paragraph on "__hash__()" for some important notes on\n creating *hashable* objects which support custom comparison\n operations and are usable as dictionary keys.\n\n There are no swapped-argument versions of these methods (to be used\n when the left argument does not support the operation but the right\n argument does); rather, "__lt__()" and "__gt__()" are each other\'s\n reflection, "__le__()" and "__ge__()" are each other\'s reflection,\n and "__eq__()" and "__ne__()" are their own reflection. If the\n operands are of different types, and right operand\'s type is a\n direct or indirect subclass of the left operand\'s type, the\n reflected method of the right operand has priority, otherwise the\n left operand\'s method has priority. Virtual subclassing is not\n considered.\n\nobject.__hash__(self)\n\n Called by built-in function "hash()" and for operations on members\n of hashed collections including "set", "frozenset", and "dict".\n "__hash__()" should return an integer. The only required property\n is that objects which compare equal have the same hash value; it is\n advised to somehow mix together (e.g. using exclusive or) the hash\n values for the components of the object that also play a part in\n comparison of objects.\n\n Note: "hash()" truncates the value returned from an object\'s\n custom "__hash__()" method to the size of a "Py_ssize_t". This\n is typically 8 bytes on 64-bit builds and 4 bytes on 32-bit\n builds. If an object\'s "__hash__()" must interoperate on builds\n of different bit sizes, be sure to check the width on all\n supported builds. An easy way to do this is with "python -c\n "import sys; print(sys.hash_info.width)"".\n\n If a class does not define an "__eq__()" method it should not\n define a "__hash__()" operation either; if it defines "__eq__()"\n but not "__hash__()", its instances will not be usable as items in\n hashable collections. If a class defines mutable objects and\n implements an "__eq__()" method, it should not implement\n "__hash__()", since the implementation of hashable collections\n requires that a key\'s hash value is immutable (if the object\'s hash\n value changes, it will be in the wrong hash bucket).\n\n User-defined classes have "__eq__()" and "__hash__()" methods by\n default; with them, all objects compare unequal (except with\n themselves) and "x.__hash__()" returns an appropriate value such\n that "x == y" implies both that "x is y" and "hash(x) == hash(y)".\n\n A class that overrides "__eq__()" and does not define "__hash__()"\n will have its "__hash__()" implicitly set to "None". When the\n "__hash__()" method of a class is "None", instances of the class\n will raise an appropriate "TypeError" when a program attempts to\n retrieve their hash value, and will also be correctly identified as\n unhashable when checking "isinstance(obj, collections.Hashable)".\n\n If a class that overrides "__eq__()" needs to retain the\n implementation of "__hash__()" from a parent class, the interpreter\n must be told this explicitly by setting "__hash__ =\n <ParentClass>.__hash__".\n\n If a class that does not override "__eq__()" wishes to suppress\n hash support, it should include "__hash__ = None" in the class\n definition. A class which defines its own "__hash__()" that\n explicitly raises a "TypeError" would be incorrectly identified as\n hashable by an "isinstance(obj, collections.Hashable)" call.\n\n Note: By default, the "__hash__()" values of str, bytes and\n datetime objects are "salted" with an unpredictable random value.\n Although they remain constant within an individual Python\n process, they are not predictable between repeated invocations of\n Python.This is intended to provide protection against a denial-\n of-service caused by carefully-chosen inputs that exploit the\n worst case performance of a dict insertion, O(n^2) complexity.\n See http://www.ocert.org/advisories/ocert-2011-003.html for\n details.Changing hash values affects the iteration order of\n dicts, sets and other mappings. Python has never made guarantees\n about this ordering (and it typically varies between 32-bit and\n 64-bit builds).See also "PYTHONHASHSEED".\n\n Changed in version 3.3: Hash randomization is enabled by default.\n\nobject.__bool__(self)\n\n Called to implement truth value testing and the built-in operation\n "bool()"; should return "False" or "True". When this method is not\n defined, "__len__()" is called, if it is defined, and the object is\n considered true if its result is nonzero. If a class defines\n neither "__len__()" nor "__bool__()", all its instances are\n considered true.\n\n\nCustomizing attribute access\n============================\n\nThe following methods can be defined to customize the meaning of\nattribute access (use of, assignment to, or deletion of "x.name") for\nclass instances.\n\nobject.__getattr__(self, name)\n\n Called when an attribute lookup has not found the attribute in the\n usual places (i.e. it is not an instance attribute nor is it found\n in the class tree for "self"). "name" is the attribute name. This\n method should return the (computed) attribute value or raise an\n "AttributeError" exception.\n\n Note that if the attribute is found through the normal mechanism,\n "__getattr__()" is not called. (This is an intentional asymmetry\n between "__getattr__()" and "__setattr__()".) This is done both for\n efficiency reasons and because otherwise "__getattr__()" would have\n no way to access other attributes of the instance. Note that at\n least for instance variables, you can fake total control by not\n inserting any values in the instance attribute dictionary (but\n instead inserting them in another object). See the\n "__getattribute__()" method below for a way to actually get total\n control over attribute access.\n\nobject.__getattribute__(self, name)\n\n Called unconditionally to implement attribute accesses for\n instances of the class. If the class also defines "__getattr__()",\n the latter will not be called unless "__getattribute__()" either\n calls it explicitly or raises an "AttributeError". This method\n should return the (computed) attribute value or raise an\n "AttributeError" exception. In order to avoid infinite recursion in\n this method, its implementation should always call the base class\n method with the same name to access any attributes it needs, for\n example, "object.__getattribute__(self, name)".\n\n Note: This method may still be bypassed when looking up special\n methods as the result of implicit invocation via language syntax\n or built-in functions. See *Special method lookup*.\n\nobject.__setattr__(self, name, value)\n\n Called when an attribute assignment is attempted. This is called\n instead of the normal mechanism (i.e. store the value in the\n instance dictionary). *name* is the attribute name, *value* is the\n value to be assigned to it.\n\n If "__setattr__()" wants to assign to an instance attribute, it\n should call the base class method with the same name, for example,\n "object.__setattr__(self, name, value)".\n\nobject.__delattr__(self, name)\n\n Like "__setattr__()" but for attribute deletion instead of\n assignment. This should only be implemented if "del obj.name" is\n meaningful for the object.\n\nobject.__dir__(self)\n\n Called when "dir()" is called on the object. A sequence must be\n returned. "dir()" converts the returned sequence to a list and\n sorts it.\n\n\nImplementing Descriptors\n------------------------\n\nThe following methods only apply when an instance of the class\ncontaining the method (a so-called *descriptor* class) appears in an\n*owner* class (the descriptor must be in either the owner\'s class\ndictionary or in the class dictionary for one of its parents). In the\nexamples below, "the attribute" refers to the attribute whose name is\nthe key of the property in the owner class\' "__dict__".\n\nobject.__get__(self, instance, owner)\n\n Called to get the attribute of the owner class (class attribute\n access) or of an instance of that class (instance attribute\n access). *owner* is always the owner class, while *instance* is the\n instance that the attribute was accessed through, or "None" when\n the attribute is accessed through the *owner*. This method should\n return the (computed) attribute value or raise an "AttributeError"\n exception.\n\nobject.__set__(self, instance, value)\n\n Called to set the attribute on an instance *instance* of the owner\n class to a new value, *value*.\n\nobject.__delete__(self, instance)\n\n Called to delete the attribute on an instance *instance* of the\n owner class.\n\nThe attribute "__objclass__" is interpreted by the "inspect" module as\nspecifying the class where this object was defined (setting this\nappropriately can assist in runtime introspection of dynamic class\nattributes). For callables, it may indicate that an instance of the\ngiven type (or a subclass) is expected or required as the first\npositional argument (for example, CPython sets this attribute for\nunbound methods that are implemented in C).\n\n\nInvoking Descriptors\n--------------------\n\nIn general, a descriptor is an object attribute with "binding\nbehavior", one whose attribute access has been overridden by methods\nin the descriptor protocol: "__get__()", "__set__()", and\n"__delete__()". If any of those methods are defined for an object, it\nis said to be a descriptor.\n\nThe default behavior for attribute access is to get, set, or delete\nthe attribute from an object\'s dictionary. For instance, "a.x" has a\nlookup chain starting with "a.__dict__[\'x\']", then\n"type(a).__dict__[\'x\']", and continuing through the base classes of\n"type(a)" excluding metaclasses.\n\nHowever, if the looked-up value is an object defining one of the\ndescriptor methods, then Python may override the default behavior and\ninvoke the descriptor method instead. Where this occurs in the\nprecedence chain depends on which descriptor methods were defined and\nhow they were called.\n\nThe starting point for descriptor invocation is a binding, "a.x". How\nthe arguments are assembled depends on "a":\n\nDirect Call\n The simplest and least common call is when user code directly\n invokes a descriptor method: "x.__get__(a)".\n\nInstance Binding\n If binding to an object instance, "a.x" is transformed into the\n call: "type(a).__dict__[\'x\'].__get__(a, type(a))".\n\nClass Binding\n If binding to a class, "A.x" is transformed into the call:\n "A.__dict__[\'x\'].__get__(None, A)".\n\nSuper Binding\n If "a" is an instance of "super", then the binding "super(B,\n obj).m()" searches "obj.__class__.__mro__" for the base class "A"\n immediately preceding "B" and then invokes the descriptor with the\n call: "A.__dict__[\'m\'].__get__(obj, obj.__class__)".\n\nFor instance bindings, the precedence of descriptor invocation depends\non the which descriptor methods are defined. A descriptor can define\nany combination of "__get__()", "__set__()" and "__delete__()". If it\ndoes not define "__get__()", then accessing the attribute will return\nthe descriptor object itself unless there is a value in the object\'s\ninstance dictionary. If the descriptor defines "__set__()" and/or\n"__delete__()", it is a data descriptor; if it defines neither, it is\na non-data descriptor. Normally, data descriptors define both\n"__get__()" and "__set__()", while non-data descriptors have just the\n"__get__()" method. Data descriptors with "__set__()" and "__get__()"\ndefined always override a redefinition in an instance dictionary. In\ncontrast, non-data descriptors can be overridden by instances.\n\nPython methods (including "staticmethod()" and "classmethod()") are\nimplemented as non-data descriptors. Accordingly, instances can\nredefine and override methods. This allows individual instances to\nacquire behaviors that differ from other instances of the same class.\n\nThe "property()" function is implemented as a data descriptor.\nAccordingly, instances cannot override the behavior of a property.\n\n\n__slots__\n---------\n\nBy default, instances of classes have a dictionary for attribute\nstorage. This wastes space for objects having very few instance\nvariables. The space consumption can become acute when creating large\nnumbers of instances.\n\nThe default can be overridden by defining *__slots__* in a class\ndefinition. The *__slots__* declaration takes a sequence of instance\nvariables and reserves just enough space in each instance to hold a\nvalue for each variable. Space is saved because *__dict__* is not\ncreated for each instance.\n\nobject.__slots__\n\n This class variable can be assigned a string, iterable, or sequence\n of strings with variable names used by instances. *__slots__*\n reserves space for the declared variables and prevents the\n automatic creation of *__dict__* and *__weakref__* for each\n instance.\n\n\nNotes on using *__slots__*\n~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n* When inheriting from a class without *__slots__*, the *__dict__*\n attribute of that class will always be accessible, so a *__slots__*\n definition in the subclass is meaningless.\n\n* Without a *__dict__* variable, instances cannot be assigned new\n variables not listed in the *__slots__* definition. Attempts to\n assign to an unlisted variable name raises "AttributeError". If\n dynamic assignment of new variables is desired, then add\n "\'__dict__\'" to the sequence of strings in the *__slots__*\n declaration.\n\n* Without a *__weakref__* variable for each instance, classes\n defining *__slots__* do not support weak references to its\n instances. If weak reference support is needed, then add\n "\'__weakref__\'" to the sequence of strings in the *__slots__*\n declaration.\n\n* *__slots__* are implemented at the class level by creating\n descriptors (*Implementing Descriptors*) for each variable name. As\n a result, class attributes cannot be used to set default values for\n instance variables defined by *__slots__*; otherwise, the class\n attribute would overwrite the descriptor assignment.\n\n* The action of a *__slots__* declaration is limited to the class\n where it is defined. As a result, subclasses will have a *__dict__*\n unless they also define *__slots__* (which must only contain names\n of any *additional* slots).\n\n* If a class defines a slot also defined in a base class, the\n instance variable defined by the base class slot is inaccessible\n (except by retrieving its descriptor directly from the base class).\n This renders the meaning of the program undefined. In the future, a\n check may be added to prevent this.\n\n* Nonempty *__slots__* does not work for classes derived from\n "variable-length" built-in types such as "int", "bytes" and "tuple".\n\n* Any non-string iterable may be assigned to *__slots__*. Mappings\n may also be used; however, in the future, special meaning may be\n assigned to the values corresponding to each key.\n\n* *__class__* assignment works only if both classes have the same\n *__slots__*.\n\n\nCustomizing class creation\n==========================\n\nBy default, classes are constructed using "type()". The class body is\nexecuted in a new namespace and the class name is bound locally to the\nresult of "type(name, bases, namespace)".\n\nThe class creation process can be customised by passing the\n"metaclass" keyword argument in the class definition line, or by\ninheriting from an existing class that included such an argument. In\nthe following example, both "MyClass" and "MySubclass" are instances\nof "Meta":\n\n class Meta(type):\n pass\n\n class MyClass(metaclass=Meta):\n pass\n\n class MySubclass(MyClass):\n pass\n\nAny other keyword arguments that are specified in the class definition\nare passed through to all metaclass operations described below.\n\nWhen a class definition is executed, the following steps occur:\n\n* the appropriate metaclass is determined\n\n* the class namespace is prepared\n\n* the class body is executed\n\n* the class object is created\n\n\nDetermining the appropriate metaclass\n-------------------------------------\n\nThe appropriate metaclass for a class definition is determined as\nfollows:\n\n* if no bases and no explicit metaclass are given, then "type()" is\n used\n\n* if an explicit metaclass is given and it is *not* an instance of\n "type()", then it is used directly as the metaclass\n\n* if an instance of "type()" is given as the explicit metaclass, or\n bases are defined, then the most derived metaclass is used\n\nThe most derived metaclass is selected from the explicitly specified\nmetaclass (if any) and the metaclasses (i.e. "type(cls)") of all\nspecified base classes. The most derived metaclass is one which is a\nsubtype of *all* of these candidate metaclasses. If none of the\ncandidate metaclasses meets that criterion, then the class definition\nwill fail with "TypeError".\n\n\nPreparing the class namespace\n-----------------------------\n\nOnce the appropriate metaclass has been identified, then the class\nnamespace is prepared. If the metaclass has a "__prepare__" attribute,\nit is called as "namespace = metaclass.__prepare__(name, bases,\n**kwds)" (where the additional keyword arguments, if any, come from\nthe class definition).\n\nIf the metaclass has no "__prepare__" attribute, then the class\nnamespace is initialised as an empty "dict()" instance.\n\nSee also: **PEP 3115** - Metaclasses in Python 3000\n\n Introduced the "__prepare__" namespace hook\n\n\nExecuting the class body\n------------------------\n\nThe class body is executed (approximately) as "exec(body, globals(),\nnamespace)". The key difference from a normal call to "exec()" is that\nlexical scoping allows the class body (including any methods) to\nreference names from the current and outer scopes when the class\ndefinition occurs inside a function.\n\nHowever, even when the class definition occurs inside the function,\nmethods defined inside the class still cannot see names defined at the\nclass scope. Class variables must be accessed through the first\nparameter of instance or class methods, and cannot be accessed at all\nfrom static methods.\n\n\nCreating the class object\n-------------------------\n\nOnce the class namespace has been populated by executing the class\nbody, the class object is created by calling "metaclass(name, bases,\nnamespace, **kwds)" (the additional keywords passed here are the same\nas those passed to "__prepare__").\n\nThis class object is the one that will be referenced by the zero-\nargument form of "super()". "__class__" is an implicit closure\nreference created by the compiler if any methods in a class body refer\nto either "__class__" or "super". This allows the zero argument form\nof "super()" to correctly identify the class being defined based on\nlexical scoping, while the class or instance that was used to make the\ncurrent call is identified based on the first argument passed to the\nmethod.\n\nAfter the class object is created, it is passed to the class\ndecorators included in the class definition (if any) and the resulting\nobject is bound in the local namespace as the defined class.\n\nWhen a new class is created by "type.__new__", the object provided as\nthe namespace parameter is copied to a standard Python dictionary and\nthe original object is discarded. The new copy becomes the "__dict__"\nattribute of the class object.\n\nSee also: **PEP 3135** - New super\n\n Describes the implicit "__class__" closure reference\n\n\nMetaclass example\n-----------------\n\nThe potential uses for metaclasses are boundless. Some ideas that have\nbeen explored include logging, interface checking, automatic\ndelegation, automatic property creation, proxies, frameworks, and\nautomatic resource locking/synchronization.\n\nHere is an example of a metaclass that uses an\n"collections.OrderedDict" to remember the order that class variables\nare defined:\n\n class OrderedClass(type):\n\n @classmethod\n def __prepare__(metacls, name, bases, **kwds):\n return collections.OrderedDict()\n\n def __new__(cls, name, bases, namespace, **kwds):\n result = type.__new__(cls, name, bases, dict(namespace))\n result.members = tuple(namespace)\n return result\n\n class A(metaclass=OrderedClass):\n def one(self): pass\n def two(self): pass\n def three(self): pass\n def four(self): pass\n\n >>> A.members\n (\'__module__\', \'one\', \'two\', \'three\', \'four\')\n\nWhen the class definition for *A* gets executed, the process begins\nwith calling the metaclass\'s "__prepare__()" method which returns an\nempty "collections.OrderedDict". That mapping records the methods and\nattributes of *A* as they are defined within the body of the class\nstatement. Once those definitions are executed, the ordered dictionary\nis fully populated and the metaclass\'s "__new__()" method gets\ninvoked. That method builds the new type and it saves the ordered\ndictionary keys in an attribute called "members".\n\n\nCustomizing instance and subclass checks\n========================================\n\nThe following methods are used to override the default behavior of the\n"isinstance()" and "issubclass()" built-in functions.\n\nIn particular, the metaclass "abc.ABCMeta" implements these methods in\norder to allow the addition of Abstract Base Classes (ABCs) as\n"virtual base classes" to any class or type (including built-in\ntypes), including other ABCs.\n\nclass.__instancecheck__(self, instance)\n\n Return true if *instance* should be considered a (direct or\n indirect) instance of *class*. If defined, called to implement\n "isinstance(instance, class)".\n\nclass.__subclasscheck__(self, subclass)\n\n Return true if *subclass* should be considered a (direct or\n indirect) subclass of *class*. If defined, called to implement\n "issubclass(subclass, class)".\n\nNote that these methods are looked up on the type (metaclass) of a\nclass. They cannot be defined as class methods in the actual class.\nThis is consistent with the lookup of special methods that are called\non instances, only in this case the instance is itself a class.\n\nSee also: **PEP 3119** - Introducing Abstract Base Classes\n\n Includes the specification for customizing "isinstance()" and\n "issubclass()" behavior through "__instancecheck__()" and\n "__subclasscheck__()", with motivation for this functionality in\n the context of adding Abstract Base Classes (see the "abc"\n module) to the language.\n\n\nEmulating callable objects\n==========================\n\nobject.__call__(self[, args...])\n\n Called when the instance is "called" as a function; if this method\n is defined, "x(arg1, arg2, ...)" is a shorthand for\n "x.__call__(arg1, arg2, ...)".\n\n\nEmulating container types\n=========================\n\nThe following methods can be defined to implement container objects.\nContainers usually are sequences (such as lists or tuples) or mappings\n(like dictionaries), but can represent other containers as well. The\nfirst set of methods is used either to emulate a sequence or to\nemulate a mapping; the difference is that for a sequence, the\nallowable keys should be the integers *k* for which "0 <= k < N" where\n*N* is the length of the sequence, or slice objects, which define a\nrange of items. It is also recommended that mappings provide the\nmethods "keys()", "values()", "items()", "get()", "clear()",\n"setdefault()", "pop()", "popitem()", "copy()", and "update()"\nbehaving similar to those for Python\'s standard dictionary objects.\nThe "collections" module provides a "MutableMapping" abstract base\nclass to help create those methods from a base set of "__getitem__()",\n"__setitem__()", "__delitem__()", and "keys()". Mutable sequences\nshould provide methods "append()", "count()", "index()", "extend()",\n"insert()", "pop()", "remove()", "reverse()" and "sort()", like Python\nstandard list objects. Finally, sequence types should implement\naddition (meaning concatenation) and multiplication (meaning\nrepetition) by defining the methods "__add__()", "__radd__()",\n"__iadd__()", "__mul__()", "__rmul__()" and "__imul__()" described\nbelow; they should not define other numerical operators. It is\nrecommended that both mappings and sequences implement the\n"__contains__()" method to allow efficient use of the "in" operator;\nfor mappings, "in" should search the mapping\'s keys; for sequences, it\nshould search through the values. It is further recommended that both\nmappings and sequences implement the "__iter__()" method to allow\nefficient iteration through the container; for mappings, "__iter__()"\nshould be the same as "keys()"; for sequences, it should iterate\nthrough the values.\n\nobject.__len__(self)\n\n Called to implement the built-in function "len()". Should return\n the length of the object, an integer ">=" 0. Also, an object that\n doesn\'t define a "__bool__()" method and whose "__len__()" method\n returns zero is considered to be false in a Boolean context.\n\nobject.__length_hint__(self)\n\n Called to implement "operator.length_hint()". Should return an\n estimated length for the object (which may be greater or less than\n the actual length). The length must be an integer ">=" 0. This\n method is purely an optimization and is never required for\n correctness.\n\n New in version 3.4.\n\nNote: Slicing is done exclusively with the following three methods.\n A call like\n\n a[1:2] = b\n\n is translated to\n\n a[slice(1, 2, None)] = b\n\n and so forth. Missing slice items are always filled in with "None".\n\nobject.__getitem__(self, key)\n\n Called to implement evaluation of "self[key]". For sequence types,\n the accepted keys should be integers and slice objects. Note that\n the special interpretation of negative indexes (if the class wishes\n to emulate a sequence type) is up to the "__getitem__()" method. If\n *key* is of an inappropriate type, "TypeError" may be raised; if of\n a value outside the set of indexes for the sequence (after any\n special interpretation of negative values), "IndexError" should be\n raised. For mapping types, if *key* is missing (not in the\n container), "KeyError" should be raised.\n\n Note: "for" loops expect that an "IndexError" will be raised for\n illegal indexes to allow proper detection of the end of the\n sequence.\n\nobject.__missing__(self, key)\n\n Called by "dict"."__getitem__()" to implement "self[key]" for dict\n subclasses when key is not in the dictionary.\n\nobject.__setitem__(self, key, value)\n\n Called to implement assignment to "self[key]". Same note as for\n "__getitem__()". This should only be implemented for mappings if\n the objects support changes to the values for keys, or if new keys\n can be added, or for sequences if elements can be replaced. The\n same exceptions should be raised for improper *key* values as for\n the "__getitem__()" method.\n\nobject.__delitem__(self, key)\n\n Called to implement deletion of "self[key]". Same note as for\n "__getitem__()". This should only be implemented for mappings if\n the objects support removal of keys, or for sequences if elements\n can be removed from the sequence. The same exceptions should be\n raised for improper *key* values as for the "__getitem__()" method.\n\nobject.__iter__(self)\n\n This method is called when an iterator is required for a container.\n This method should return a new iterator object that can iterate\n over all the objects in the container. For mappings, it should\n iterate over the keys of the container.\n\n Iterator objects also need to implement this method; they are\n required to return themselves. For more information on iterator\n objects, see *Iterator Types*.\n\nobject.__reversed__(self)\n\n Called (if present) by the "reversed()" built-in to implement\n reverse iteration. It should return a new iterator object that\n iterates over all the objects in the container in reverse order.\n\n If the "__reversed__()" method is not provided, the "reversed()"\n built-in will fall back to using the sequence protocol ("__len__()"\n and "__getitem__()"). Objects that support the sequence protocol\n should only provide "__reversed__()" if they can provide an\n implementation that is more efficient than the one provided by\n "reversed()".\n\nThe membership test operators ("in" and "not in") are normally\nimplemented as an iteration through a sequence. However, container\nobjects can supply the following special method with a more efficient\nimplementation, which also does not require the object be a sequence.\n\nobject.__contains__(self, item)\n\n Called to implement membership test operators. Should return true\n if *item* is in *self*, false otherwise. For mapping objects, this\n should consider the keys of the mapping rather than the values or\n the key-item pairs.\n\n For objects that don\'t define "__contains__()", the membership test\n first tries iteration via "__iter__()", then the old sequence\n iteration protocol via "__getitem__()", see *this section in the\n language reference*.\n\n\nEmulating numeric types\n=======================\n\nThe following methods can be defined to emulate numeric objects.\nMethods corresponding to operations that are not supported by the\nparticular kind of number implemented (e.g., bitwise operations for\nnon-integral numbers) should be left undefined.\n\nobject.__add__(self, other)\nobject.__sub__(self, other)\nobject.__mul__(self, other)\nobject.__matmul__(self, other)\nobject.__truediv__(self, other)\nobject.__floordiv__(self, other)\nobject.__mod__(self, other)\nobject.__divmod__(self, other)\nobject.__pow__(self, other[, modulo])\nobject.__lshift__(self, other)\nobject.__rshift__(self, other)\nobject.__and__(self, other)\nobject.__xor__(self, other)\nobject.__or__(self, other)\n\n These methods are called to implement the binary arithmetic\n operations ("+", "-", "*", "@", "/", "//", "%", "divmod()",\n "pow()", "**", "<<", ">>", "&", "^", "|"). For instance, to\n evaluate the expression "x + y", where *x* is an instance of a\n class that has an "__add__()" method, "x.__add__(y)" is called.\n The "__divmod__()" method should be the equivalent to using\n "__floordiv__()" and "__mod__()"; it should not be related to\n "__truediv__()". Note that "__pow__()" should be defined to accept\n an optional third argument if the ternary version of the built-in\n "pow()" function is to be supported.\n\n If one of those methods does not support the operation with the\n supplied arguments, it should return "NotImplemented".\n\nobject.__radd__(self, other)\nobject.__rsub__(self, other)\nobject.__rmul__(self, other)\nobject.__rmatmul__(self, other)\nobject.__rtruediv__(self, other)\nobject.__rfloordiv__(self, other)\nobject.__rmod__(self, other)\nobject.__rdivmod__(self, other)\nobject.__rpow__(self, other)\nobject.__rlshift__(self, other)\nobject.__rrshift__(self, other)\nobject.__rand__(self, other)\nobject.__rxor__(self, other)\nobject.__ror__(self, other)\n\n These methods are called to implement the binary arithmetic\n operations ("+", "-", "*", "@", "/", "//", "%", "divmod()",\n "pow()", "**", "<<", ">>", "&", "^", "|") with reflected (swapped)\n operands. These functions are only called if the left operand does\n not support the corresponding operation and the operands are of\n different types. [2] For instance, to evaluate the expression "x -\n y", where *y* is an instance of a class that has an "__rsub__()"\n method, "y.__rsub__(x)" is called if "x.__sub__(y)" returns\n *NotImplemented*.\n\n Note that ternary "pow()" will not try calling "__rpow__()" (the\n coercion rules would become too complicated).\n\n Note: If the right operand\'s type is a subclass of the left\n operand\'s type and that subclass provides the reflected method\n for the operation, this method will be called before the left\n operand\'s non-reflected method. This behavior allows subclasses\n to override their ancestors\' operations.\n\nobject.__iadd__(self, other)\nobject.__isub__(self, other)\nobject.__imul__(self, other)\nobject.__imatmul__(self, other)\nobject.__itruediv__(self, other)\nobject.__ifloordiv__(self, other)\nobject.__imod__(self, other)\nobject.__ipow__(self, other[, modulo])\nobject.__ilshift__(self, other)\nobject.__irshift__(self, other)\nobject.__iand__(self, other)\nobject.__ixor__(self, other)\nobject.__ior__(self, other)\n\n These methods are called to implement the augmented arithmetic\n assignments ("+=", "-=", "*=", "@=", "/=", "//=", "%=", "**=",\n "<<=", ">>=", "&=", "^=", "|="). These methods should attempt to\n do the operation in-place (modifying *self*) and return the result\n (which could be, but does not have to be, *self*). If a specific\n method is not defined, the augmented assignment falls back to the\n normal methods. For instance, if *x* is an instance of a class\n with an "__iadd__()" method, "x += y" is equivalent to "x =\n x.__iadd__(y)" . Otherwise, "x.__add__(y)" and "y.__radd__(x)" are\n considered, as with the evaluation of "x + y". In certain\n situations, augmented assignment can result in unexpected errors\n (see *Why does a_tuple[i] += [\'item\'] raise an exception when the\n addition works?*), but this behavior is in fact part of the data\n model.\n\nobject.__neg__(self)\nobject.__pos__(self)\nobject.__abs__(self)\nobject.__invert__(self)\n\n Called to implement the unary arithmetic operations ("-", "+",\n "abs()" and "~").\n\nobject.__complex__(self)\nobject.__int__(self)\nobject.__float__(self)\nobject.__round__(self[, n])\n\n Called to implement the built-in functions "complex()", "int()",\n "float()" and "round()". Should return a value of the appropriate\n type.\n\nobject.__index__(self)\n\n Called to implement "operator.index()", and whenever Python needs\n to losslessly convert the numeric object to an integer object (such\n as in slicing, or in the built-in "bin()", "hex()" and "oct()"\n functions). Presence of this method indicates that the numeric\n object is an integer type. Must return an integer.\n\n Note: In order to have a coherent integer type class, when\n "__index__()" is defined "__int__()" should also be defined, and\n both should return the same value.\n\n\nWith Statement Context Managers\n===============================\n\nA *context manager* is an object that defines the runtime context to\nbe established when executing a "with" statement. The context manager\nhandles the entry into, and the exit from, the desired runtime context\nfor the execution of the block of code. Context managers are normally\ninvoked using the "with" statement (described in section *The with\nstatement*), but can also be used by directly invoking their methods.\n\nTypical uses of context managers include saving and restoring various\nkinds of global state, locking and unlocking resources, closing opened\nfiles, etc.\n\nFor more information on context managers, see *Context Manager Types*.\n\nobject.__enter__(self)\n\n Enter the runtime context related to this object. The "with"\n statement will bind this method\'s return value to the target(s)\n specified in the "as" clause of the statement, if any.\n\nobject.__exit__(self, exc_type, exc_value, traceback)\n\n Exit the runtime context related to this object. The parameters\n describe the exception that caused the context to be exited. If the\n context was exited without an exception, all three arguments will\n be "None".\n\n If an exception is supplied, and the method wishes to suppress the\n exception (i.e., prevent it from being propagated), it should\n return a true value. Otherwise, the exception will be processed\n normally upon exit from this method.\n\n Note that "__exit__()" methods should not reraise the passed-in\n exception; this is the caller\'s responsibility.\n\nSee also: **PEP 343** - The "with" statement\n\n The specification, background, and examples for the Python "with"\n statement.\n\n\nSpecial method lookup\n=====================\n\nFor custom classes, implicit invocations of special methods are only\nguaranteed to work correctly if defined on an object\'s type, not in\nthe object\'s instance dictionary. That behaviour is the reason why\nthe following code raises an exception:\n\n >>> class C:\n ... pass\n ...\n >>> c = C()\n >>> c.__len__ = lambda: 5\n >>> len(c)\n Traceback (most recent call last):\n File "<stdin>", line 1, in <module>\n TypeError: object of type \'C\' has no len()\n\nThe rationale behind this behaviour lies with a number of special\nmethods such as "__hash__()" and "__repr__()" that are implemented by\nall objects, including type objects. If the implicit lookup of these\nmethods used the conventional lookup process, they would fail when\ninvoked on the type object itself:\n\n >>> 1 .__hash__() == hash(1)\n True\n >>> int.__hash__() == hash(int)\n Traceback (most recent call last):\n File "<stdin>", line 1, in <module>\n TypeError: descriptor \'__hash__\' of \'int\' object needs an argument\n\nIncorrectly attempting to invoke an unbound method of a class in this\nway is sometimes referred to as \'metaclass confusion\', and is avoided\nby bypassing the instance when looking up special methods:\n\n >>> type(1).__hash__(1) == hash(1)\n True\n >>> type(int).__hash__(int) == hash(int)\n True\n\nIn addition to bypassing any instance attributes in the interest of\ncorrectness, implicit special method lookup generally also bypasses\nthe "__getattribute__()" method even of the object\'s metaclass:\n\n >>> class Meta(type):\n ... def __getattribute__(*args):\n ... print("Metaclass getattribute invoked")\n ... return type.__getattribute__(*args)\n ...\n >>> class C(object, metaclass=Meta):\n ... def __len__(self):\n ... return 10\n ... def __getattribute__(*args):\n ... print("Class getattribute invoked")\n ... return object.__getattribute__(*args)\n ...\n >>> c = C()\n >>> c.__len__() # Explicit lookup via instance\n Class getattribute invoked\n 10\n >>> type(c).__len__(c) # Explicit lookup via type\n Metaclass getattribute invoked\n 10\n >>> len(c) # Implicit lookup\n 10\n\nBypassing the "__getattribute__()" machinery in this fashion provides\nsignificant scope for speed optimisations within the interpreter, at\nthe cost of some flexibility in the handling of special methods (the\nspecial method *must* be set on the class object itself in order to be\nconsistently invoked by the interpreter).\n',
+ 'string-methods': u'\nString Methods\n**************\n\nStrings implement all of the *common* sequence operations, along with\nthe additional methods described below.\n\nStrings also support two styles of string formatting, one providing a\nlarge degree of flexibility and customization (see "str.format()",\n*Format String Syntax* and *Custom String Formatting*) and the other\nbased on C "printf" style formatting that handles a narrower range of\ntypes and is slightly harder to use correctly, but is often faster for\nthe cases it can handle (*printf-style String Formatting*).\n\nThe *Text Processing Services* section of the standard library covers\na number of other modules that provide various text related utilities\n(including regular expression support in the "re" module).\n\nstr.capitalize()\n\n Return a copy of the string with its first character capitalized\n and the rest lowercased.\n\nstr.casefold()\n\n Return a casefolded copy of the string. Casefolded strings may be\n used for caseless matching.\n\n Casefolding is similar to lowercasing but more aggressive because\n it is intended to remove all case distinctions in a string. For\n example, the German lowercase letter "\'\xdf\'" is equivalent to ""ss"".\n Since it is already lowercase, "lower()" would do nothing to "\'\xdf\'";\n "casefold()" converts it to ""ss"".\n\n The casefolding algorithm is described in section 3.13 of the\n Unicode Standard.\n\n New in version 3.3.\n\nstr.center(width[, fillchar])\n\n Return centered in a string of length *width*. Padding is done\n using the specified *fillchar* (default is an ASCII space). The\n original string is returned if *width* is less than or equal to\n "len(s)".\n\nstr.count(sub[, start[, end]])\n\n Return the number of non-overlapping occurrences of substring *sub*\n in the range [*start*, *end*]. Optional arguments *start* and\n *end* are interpreted as in slice notation.\n\nstr.encode(encoding="utf-8", errors="strict")\n\n Return an encoded version of the string as a bytes object. Default\n encoding is "\'utf-8\'". *errors* may be given to set a different\n error handling scheme. The default for *errors* is "\'strict\'",\n meaning that encoding errors raise a "UnicodeError". Other possible\n values are "\'ignore\'", "\'replace\'", "\'xmlcharrefreplace\'",\n "\'backslashreplace\'" and any other name registered via\n "codecs.register_error()", see section *Error Handlers*. For a list\n of possible encodings, see section *Standard Encodings*.\n\n Changed in version 3.1: Support for keyword arguments added.\n\nstr.endswith(suffix[, start[, end]])\n\n Return "True" if the string ends with the specified *suffix*,\n otherwise return "False". *suffix* can also be a tuple of suffixes\n to look for. With optional *start*, test beginning at that\n position. With optional *end*, stop comparing at that position.\n\nstr.expandtabs(tabsize=8)\n\n Return a copy of the string where all tab characters are replaced\n by one or more spaces, depending on the current column and the\n given tab size. Tab positions occur every *tabsize* characters\n (default is 8, giving tab positions at columns 0, 8, 16 and so on).\n To expand the string, the current column is set to zero and the\n string is examined character by character. If the character is a\n tab ("\\t"), one or more space characters are inserted in the result\n until the current column is equal to the next tab position. (The\n tab character itself is not copied.) If the character is a newline\n ("\\n") or return ("\\r"), it is copied and the current column is\n reset to zero. Any other character is copied unchanged and the\n current column is incremented by one regardless of how the\n character is represented when printed.\n\n >>> \'01\\t012\\t0123\\t01234\'.expandtabs()\n \'01 012 0123 01234\'\n >>> \'01\\t012\\t0123\\t01234\'.expandtabs(4)\n \'01 012 0123 01234\'\n\nstr.find(sub[, start[, end]])\n\n Return the lowest index in the string where substring *sub* is\n found within the slice "s[start:end]". Optional arguments *start*\n and *end* are interpreted as in slice notation. Return "-1" if\n *sub* is not found.\n\n Note: The "find()" method should be used only if you need to know\n the position of *sub*. To check if *sub* is a substring or not,\n use the "in" operator:\n\n >>> \'Py\' in \'Python\'\n True\n\nstr.format(*args, **kwargs)\n\n Perform a string formatting operation. The string on which this\n method is called can contain literal text or replacement fields\n delimited by braces "{}". Each replacement field contains either\n the numeric index of a positional argument, or the name of a\n keyword argument. Returns a copy of the string where each\n replacement field is replaced with the string value of the\n corresponding argument.\n\n >>> "The sum of 1 + 2 is {0}".format(1+2)\n \'The sum of 1 + 2 is 3\'\n\n See *Format String Syntax* for a description of the various\n formatting options that can be specified in format strings.\n\nstr.format_map(mapping)\n\n Similar to "str.format(**mapping)", except that "mapping" is used\n directly and not copied to a "dict". This is useful if for example\n "mapping" is a dict subclass:\n\n >>> class Default(dict):\n ... def __missing__(self, key):\n ... return key\n ...\n >>> \'{name} was born in {country}\'.format_map(Default(name=\'Guido\'))\n \'Guido was born in country\'\n\n New in version 3.2.\n\nstr.index(sub[, start[, end]])\n\n Like "find()", but raise "ValueError" when the substring is not\n found.\n\nstr.isalnum()\n\n Return true if all characters in the string are alphanumeric and\n there is at least one character, false otherwise. A character "c"\n is alphanumeric if one of the following returns "True":\n "c.isalpha()", "c.isdecimal()", "c.isdigit()", or "c.isnumeric()".\n\nstr.isalpha()\n\n Return true if all characters in the string are alphabetic and\n there is at least one character, false otherwise. Alphabetic\n characters are those characters defined in the Unicode character\n database as "Letter", i.e., those with general category property\n being one of "Lm", "Lt", "Lu", "Ll", or "Lo". Note that this is\n different from the "Alphabetic" property defined in the Unicode\n Standard.\n\nstr.isdecimal()\n\n Return true if all characters in the string are decimal characters\n and there is at least one character, false otherwise. Decimal\n characters are those from general category "Nd". This category\n includes digit characters, and all characters that can be used to\n form decimal-radix numbers, e.g. U+0660, ARABIC-INDIC DIGIT ZERO.\n\nstr.isdigit()\n\n Return true if all characters in the string are digits and there is\n at least one character, false otherwise. Digits include decimal\n characters and digits that need special handling, such as the\n compatibility superscript digits. Formally, a digit is a character\n that has the property value Numeric_Type=Digit or\n Numeric_Type=Decimal.\n\nstr.isidentifier()\n\n Return true if the string is a valid identifier according to the\n language definition, section *Identifiers and keywords*.\n\n Use "keyword.iskeyword()" to test for reserved identifiers such as\n "def" and "class".\n\nstr.islower()\n\n Return true if all cased characters [4] in the string are lowercase\n and there is at least one cased character, false otherwise.\n\nstr.isnumeric()\n\n Return true if all characters in the string are numeric characters,\n and there is at least one character, false otherwise. Numeric\n characters include digit characters, and all characters that have\n the Unicode numeric value property, e.g. U+2155, VULGAR FRACTION\n ONE FIFTH. Formally, numeric characters are those with the\n property value Numeric_Type=Digit, Numeric_Type=Decimal or\n Numeric_Type=Numeric.\n\nstr.isprintable()\n\n Return true if all characters in the string are printable or the\n string is empty, false otherwise. Nonprintable characters are\n those characters defined in the Unicode character database as\n "Other" or "Separator", excepting the ASCII space (0x20) which is\n considered printable. (Note that printable characters in this\n context are those which should not be escaped when "repr()" is\n invoked on a string. It has no bearing on the handling of strings\n written to "sys.stdout" or "sys.stderr".)\n\nstr.isspace()\n\n Return true if there are only whitespace characters in the string\n and there is at least one character, false otherwise. Whitespace\n characters are those characters defined in the Unicode character\n database as "Other" or "Separator" and those with bidirectional\n property being one of "WS", "B", or "S".\n\nstr.istitle()\n\n Return true if the string is a titlecased string and there is at\n least one character, for example uppercase characters may only\n follow uncased characters and lowercase characters only cased ones.\n Return false otherwise.\n\nstr.isupper()\n\n Return true if all cased characters [4] in the string are uppercase\n and there is at least one cased character, false otherwise.\n\nstr.join(iterable)\n\n Return a string which is the concatenation of the strings in the\n *iterable* *iterable*. A "TypeError" will be raised if there are\n any non-string values in *iterable*, including "bytes" objects.\n The separator between elements is the string providing this method.\n\nstr.ljust(width[, fillchar])\n\n Return the string left justified in a string of length *width*.\n Padding is done using the specified *fillchar* (default is an ASCII\n space). The original string is returned if *width* is less than or\n equal to "len(s)".\n\nstr.lower()\n\n Return a copy of the string with all the cased characters [4]\n converted to lowercase.\n\n The lowercasing algorithm used is described in section 3.13 of the\n Unicode Standard.\n\nstr.lstrip([chars])\n\n Return a copy of the string with leading characters removed. The\n *chars* argument is a string specifying the set of characters to be\n removed. If omitted or "None", the *chars* argument defaults to\n removing whitespace. The *chars* argument is not a prefix; rather,\n all combinations of its values are stripped:\n\n >>> \' spacious \'.lstrip()\n \'spacious \'\n >>> \'www.example.com\'.lstrip(\'cmowz.\')\n \'example.com\'\n\nstatic str.maketrans(x[, y[, z]])\n\n This static method returns a translation table usable for\n "str.translate()".\n\n If there is only one argument, it must be a dictionary mapping\n Unicode ordinals (integers) or characters (strings of length 1) to\n Unicode ordinals, strings (of arbitrary lengths) or None.\n Character keys will then be converted to ordinals.\n\n If there are two arguments, they must be strings of equal length,\n and in the resulting dictionary, each character in x will be mapped\n to the character at the same position in y. If there is a third\n argument, it must be a string, whose characters will be mapped to\n None in the result.\n\nstr.partition(sep)\n\n Split the string at the first occurrence of *sep*, and return a\n 3-tuple containing the part before the separator, the separator\n itself, and the part after the separator. If the separator is not\n found, return a 3-tuple containing the string itself, followed by\n two empty strings.\n\nstr.replace(old, new[, count])\n\n Return a copy of the string with all occurrences of substring *old*\n replaced by *new*. If the optional argument *count* is given, only\n the first *count* occurrences are replaced.\n\nstr.rfind(sub[, start[, end]])\n\n Return the highest index in the string where substring *sub* is\n found, such that *sub* is contained within "s[start:end]".\n Optional arguments *start* and *end* are interpreted as in slice\n notation. Return "-1" on failure.\n\nstr.rindex(sub[, start[, end]])\n\n Like "rfind()" but raises "ValueError" when the substring *sub* is\n not found.\n\nstr.rjust(width[, fillchar])\n\n Return the string right justified in a string of length *width*.\n Padding is done using the specified *fillchar* (default is an ASCII\n space). The original string is returned if *width* is less than or\n equal to "len(s)".\n\nstr.rpartition(sep)\n\n Split the string at the last occurrence of *sep*, and return a\n 3-tuple containing the part before the separator, the separator\n itself, and the part after the separator. If the separator is not\n found, return a 3-tuple containing two empty strings, followed by\n the string itself.\n\nstr.rsplit(sep=None, maxsplit=-1)\n\n Return a list of the words in the string, using *sep* as the\n delimiter string. If *maxsplit* is given, at most *maxsplit* splits\n are done, the *rightmost* ones. If *sep* is not specified or\n "None", any whitespace string is a separator. Except for splitting\n from the right, "rsplit()" behaves like "split()" which is\n described in detail below.\n\nstr.rstrip([chars])\n\n Return a copy of the string with trailing characters removed. The\n *chars* argument is a string specifying the set of characters to be\n removed. If omitted or "None", the *chars* argument defaults to\n removing whitespace. The *chars* argument is not a suffix; rather,\n all combinations of its values are stripped:\n\n >>> \' spacious \'.rstrip()\n \' spacious\'\n >>> \'mississippi\'.rstrip(\'ipz\')\n \'mississ\'\n\nstr.split(sep=None, maxsplit=-1)\n\n Return a list of the words in the string, using *sep* as the\n delimiter string. If *maxsplit* is given, at most *maxsplit*\n splits are done (thus, the list will have at most "maxsplit+1"\n elements). If *maxsplit* is not specified or "-1", then there is\n no limit on the number of splits (all possible splits are made).\n\n If *sep* is given, consecutive delimiters are not grouped together\n and are deemed to delimit empty strings (for example,\n "\'1,,2\'.split(\',\')" returns "[\'1\', \'\', \'2\']"). The *sep* argument\n may consist of multiple characters (for example,\n "\'1<>2<>3\'.split(\'<>\')" returns "[\'1\', \'2\', \'3\']"). Splitting an\n empty string with a specified separator returns "[\'\']".\n\n For example:\n\n >>> \'1,2,3\'.split(\',\')\n [\'1\', \'2\', \'3\']\n >>> \'1,2,3\'.split(\',\', maxsplit=1)\n [\'1\', \'2,3\']\n >>> \'1,2,,3,\'.split(\',\')\n [\'1\', \'2\', \'\', \'3\', \'\']\n\n If *sep* is not specified or is "None", a different splitting\n algorithm is applied: runs of consecutive whitespace are regarded\n as a single separator, and the result will contain no empty strings\n at the start or end if the string has leading or trailing\n whitespace. Consequently, splitting an empty string or a string\n consisting of just whitespace with a "None" separator returns "[]".\n\n For example:\n\n >>> \'1 2 3\'.split()\n [\'1\', \'2\', \'3\']\n >>> \'1 2 3\'.split(maxsplit=1)\n [\'1\', \'2 3\']\n >>> \' 1 2 3 \'.split()\n [\'1\', \'2\', \'3\']\n\nstr.splitlines([keepends])\n\n Return a list of the lines in the string, breaking at line\n boundaries. Line breaks are not included in the resulting list\n unless *keepends* is given and true.\n\n This method splits on the following line boundaries. In\n particular, the boundaries are a superset of *universal newlines*.\n\n +-------------------------+-------------------------------+\n | Representation | Description |\n +=========================+===============================+\n | "\\n" | Line Feed |\n +-------------------------+-------------------------------+\n | "\\r" | Carriage Return |\n +-------------------------+-------------------------------+\n | "\\r\\n" | Carriage Return + Line Feed |\n +-------------------------+-------------------------------+\n | "\\v" or "\\x0b" | Line Tabulation |\n +-------------------------+-------------------------------+\n | "\\f" or "\\x0c" | Form Feed |\n +-------------------------+-------------------------------+\n | "\\x1c" | File Separator |\n +-------------------------+-------------------------------+\n | "\\x1d" | Group Separator |\n +-------------------------+-------------------------------+\n | "\\x1e" | Record Separator |\n +-------------------------+-------------------------------+\n | "\\x85" | Next Line (C1 Control Code) |\n +-------------------------+-------------------------------+\n | "\\u2028" | Line Separator |\n +-------------------------+-------------------------------+\n | "\\u2029" | Paragraph Separator |\n +-------------------------+-------------------------------+\n\n Changed in version 3.2: "\\v" and "\\f" added to list of line\n boundaries.\n\n For example:\n\n >>> \'ab c\\n\\nde fg\\rkl\\r\\n\'.splitlines()\n [\'ab c\', \'\', \'de fg\', \'kl\']\n >>> \'ab c\\n\\nde fg\\rkl\\r\\n\'.splitlines(keepends=True)\n [\'ab c\\n\', \'\\n\', \'de fg\\r\', \'kl\\r\\n\']\n\n Unlike "split()" when a delimiter string *sep* is given, this\n method returns an empty list for the empty string, and a terminal\n line break does not result in an extra line:\n\n >>> "".splitlines()\n []\n >>> "One line\\n".splitlines()\n [\'One line\']\n\n For comparison, "split(\'\\n\')" gives:\n\n >>> \'\'.split(\'\\n\')\n [\'\']\n >>> \'Two lines\\n\'.split(\'\\n\')\n [\'Two lines\', \'\']\n\nstr.startswith(prefix[, start[, end]])\n\n Return "True" if string starts with the *prefix*, otherwise return\n "False". *prefix* can also be a tuple of prefixes to look for.\n With optional *start*, test string beginning at that position.\n With optional *end*, stop comparing string at that position.\n\nstr.strip([chars])\n\n Return a copy of the string with the leading and trailing\n characters removed. The *chars* argument is a string specifying the\n set of characters to be removed. If omitted or "None", the *chars*\n argument defaults to removing whitespace. The *chars* argument is\n not a prefix or suffix; rather, all combinations of its values are\n stripped:\n\n >>> \' spacious \'.strip()\n \'spacious\'\n >>> \'www.example.com\'.strip(\'cmowz.\')\n \'example\'\n\n The outermost leading and trailing *chars* argument values are\n stripped from the string. Characters are removed from the leading\n end until reaching a string character that is not contained in the\n set of characters in *chars*. A similar action takes place on the\n trailing end. For example:\n\n >>> comment_string = \'#....... Section 3.2.1 Issue #32 .......\'\n >>> comment_string.strip(\'.#! \')\n \'Section 3.2.1 Issue #32\'\n\nstr.swapcase()\n\n Return a copy of the string with uppercase characters converted to\n lowercase and vice versa. Note that it is not necessarily true that\n "s.swapcase().swapcase() == s".\n\nstr.title()\n\n Return a titlecased version of the string where words start with an\n uppercase character and the remaining characters are lowercase.\n\n For example:\n\n >>> \'Hello world\'.title()\n \'Hello World\'\n\n The algorithm uses a simple language-independent definition of a\n word as groups of consecutive letters. The definition works in\n many contexts but it means that apostrophes in contractions and\n possessives form word boundaries, which may not be the desired\n result:\n\n >>> "they\'re bill\'s friends from the UK".title()\n "They\'Re Bill\'S Friends From The Uk"\n\n A workaround for apostrophes can be constructed using regular\n expressions:\n\n >>> import re\n >>> def titlecase(s):\n ... return re.sub(r"[A-Za-z]+(\'[A-Za-z]+)?",\n ... lambda mo: mo.group(0)[0].upper() +\n ... mo.group(0)[1:].lower(),\n ... s)\n ...\n >>> titlecase("they\'re bill\'s friends.")\n "They\'re Bill\'s Friends."\n\nstr.translate(table)\n\n Return a copy of the string in which each character has been mapped\n through the given translation table. The table must be an object\n that implements indexing via "__getitem__()", typically a *mapping*\n or *sequence*. When indexed by a Unicode ordinal (an integer), the\n table object can do any of the following: return a Unicode ordinal\n or a string, to map the character to one or more other characters;\n return "None", to delete the character from the return string; or\n raise a "LookupError" exception, to map the character to itself.\n\n You can use "str.maketrans()" to create a translation map from\n character-to-character mappings in different formats.\n\n See also the "codecs" module for a more flexible approach to custom\n character mappings.\n\nstr.upper()\n\n Return a copy of the string with all the cased characters [4]\n converted to uppercase. Note that "str.upper().isupper()" might be\n "False" if "s" contains uncased characters or if the Unicode\n category of the resulting character(s) is not "Lu" (Letter,\n uppercase), but e.g. "Lt" (Letter, titlecase).\n\n The uppercasing algorithm used is described in section 3.13 of the\n Unicode Standard.\n\nstr.zfill(width)\n\n Return a copy of the string left filled with ASCII "\'0\'" digits to\n make a string of length *width*. A leading sign prefix\n ("\'+\'"/"\'-\'") is handled by inserting the padding *after* the sign\n character rather than before. The original string is returned if\n *width* is less than or equal to "len(s)".\n\n For example:\n\n >>> "42".zfill(5)\n \'00042\'\n >>> "-42".zfill(5)\n \'-0042\'\n',
+ 'strings': u'\nString and Bytes literals\n*************************\n\nString literals are described by the following lexical definitions:\n\n stringliteral ::= [stringprefix](shortstring | longstring)\n stringprefix ::= "r" | "u" | "R" | "U"\n shortstring ::= "\'" shortstringitem* "\'" | \'"\' shortstringitem* \'"\'\n longstring ::= "\'\'\'" longstringitem* "\'\'\'" | \'"""\' longstringitem* \'"""\'\n shortstringitem ::= shortstringchar | stringescapeseq\n longstringitem ::= longstringchar | stringescapeseq\n shortstringchar ::= <any source character except "\\" or newline or the quote>\n longstringchar ::= <any source character except "\\">\n stringescapeseq ::= "\\" <any source character>\n\n bytesliteral ::= bytesprefix(shortbytes | longbytes)\n bytesprefix ::= "b" | "B" | "br" | "Br" | "bR" | "BR" | "rb" | "rB" | "Rb" | "RB"\n shortbytes ::= "\'" shortbytesitem* "\'" | \'"\' shortbytesitem* \'"\'\n longbytes ::= "\'\'\'" longbytesitem* "\'\'\'" | \'"""\' longbytesitem* \'"""\'\n shortbytesitem ::= shortbyteschar | bytesescapeseq\n longbytesitem ::= longbyteschar | bytesescapeseq\n shortbyteschar ::= <any ASCII character except "\\" or newline or the quote>\n longbyteschar ::= <any ASCII character except "\\">\n bytesescapeseq ::= "\\" <any ASCII character>\n\nOne syntactic restriction not indicated by these productions is that\nwhitespace is not allowed between the "stringprefix" or "bytesprefix"\nand the rest of the literal. The source character set is defined by\nthe encoding declaration; it is UTF-8 if no encoding declaration is\ngiven in the source file; see section *Encoding declarations*.\n\nIn plain English: Both types of literals can be enclosed in matching\nsingle quotes ("\'") or double quotes ("""). They can also be enclosed\nin matching groups of three single or double quotes (these are\ngenerally referred to as *triple-quoted strings*). The backslash\n("\\") character is used to escape characters that otherwise have a\nspecial meaning, such as newline, backslash itself, or the quote\ncharacter.\n\nBytes literals are always prefixed with "\'b\'" or "\'B\'"; they produce\nan instance of the "bytes" type instead of the "str" type. They may\nonly contain ASCII characters; bytes with a numeric value of 128 or\ngreater must be expressed with escapes.\n\nAs of Python 3.3 it is possible again to prefix string literals with a\n"u" prefix to simplify maintenance of dual 2.x and 3.x codebases.\n\nBoth string and bytes literals may optionally be prefixed with a\nletter "\'r\'" or "\'R\'"; such strings are called *raw strings* and treat\nbackslashes as literal characters. As a result, in string literals,\n"\'\\U\'" and "\'\\u\'" escapes in raw strings are not treated specially.\nGiven that Python 2.x\'s raw unicode literals behave differently than\nPython 3.x\'s the "\'ur\'" syntax is not supported.\n\nNew in version 3.3: The "\'rb\'" prefix of raw bytes literals has been\nadded as a synonym of "\'br\'".\n\nNew in version 3.3: Support for the unicode legacy literal\n("u\'value\'") was reintroduced to simplify the maintenance of dual\nPython 2.x and 3.x codebases. See **PEP 414** for more information.\n\nIn triple-quoted literals, unescaped newlines and quotes are allowed\n(and are retained), except that three unescaped quotes in a row\nterminate the literal. (A "quote" is the character used to open the\nliteral, i.e. either "\'" or """.)\n\nUnless an "\'r\'" or "\'R\'" prefix is present, escape sequences in string\nand bytes literals are interpreted according to rules similar to those\nused by Standard C. The recognized escape sequences are:\n\n+-------------------+-----------------------------------+---------+\n| Escape Sequence | Meaning | Notes |\n+===================+===================================+=========+\n| "\\newline" | Backslash and newline ignored | |\n+-------------------+-----------------------------------+---------+\n| "\\\\" | Backslash ("\\") | |\n+-------------------+-----------------------------------+---------+\n| "\\\'" | Single quote ("\'") | |\n+-------------------+-----------------------------------+---------+\n| "\\"" | Double quote (""") | |\n+-------------------+-----------------------------------+---------+\n| "\\a" | ASCII Bell (BEL) | |\n+-------------------+-----------------------------------+---------+\n| "\\b" | ASCII Backspace (BS) | |\n+-------------------+-----------------------------------+---------+\n| "\\f" | ASCII Formfeed (FF) | |\n+-------------------+-----------------------------------+---------+\n| "\\n" | ASCII Linefeed (LF) | |\n+-------------------+-----------------------------------+---------+\n| "\\r" | ASCII Carriage Return (CR) | |\n+-------------------+-----------------------------------+---------+\n| "\\t" | ASCII Horizontal Tab (TAB) | |\n+-------------------+-----------------------------------+---------+\n| "\\v" | ASCII Vertical Tab (VT) | |\n+-------------------+-----------------------------------+---------+\n| "\\ooo" | Character with octal value *ooo* | (1,3) |\n+-------------------+-----------------------------------+---------+\n| "\\xhh" | Character with hex value *hh* | (2,3) |\n+-------------------+-----------------------------------+---------+\n\nEscape sequences only recognized in string literals are:\n\n+-------------------+-----------------------------------+---------+\n| Escape Sequence | Meaning | Notes |\n+===================+===================================+=========+\n| "\\N{name}" | Character named *name* in the | (4) |\n| | Unicode database | |\n+-------------------+-----------------------------------+---------+\n| "\\uxxxx" | Character with 16-bit hex value | (5) |\n| | *xxxx* | |\n+-------------------+-----------------------------------+---------+\n| "\\Uxxxxxxxx" | Character with 32-bit hex value | (6) |\n| | *xxxxxxxx* | |\n+-------------------+-----------------------------------+---------+\n\nNotes:\n\n1. As in Standard C, up to three octal digits are accepted.\n\n2. Unlike in Standard C, exactly two hex digits are required.\n\n3. In a bytes literal, hexadecimal and octal escapes denote the\n byte with the given value. In a string literal, these escapes\n denote a Unicode character with the given value.\n\n4. Changed in version 3.3: Support for name aliases [1] has been\n added.\n\n5. Exactly four hex digits are required.\n\n6. Any Unicode character can be encoded this way. Exactly eight\n hex digits are required.\n\nUnlike Standard C, all unrecognized escape sequences are left in the\nstring unchanged, i.e., *the backslash is left in the result*. (This\nbehavior is useful when debugging: if an escape sequence is mistyped,\nthe resulting output is more easily recognized as broken.) It is also\nimportant to note that the escape sequences only recognized in string\nliterals fall into the category of unrecognized escapes for bytes\nliterals.\n\nEven in a raw literal, quotes can be escaped with a backslash, but the\nbackslash remains in the result; for example, "r"\\""" is a valid\nstring literal consisting of two characters: a backslash and a double\nquote; "r"\\"" is not a valid string literal (even a raw string cannot\nend in an odd number of backslashes). Specifically, *a raw literal\ncannot end in a single backslash* (since the backslash would escape\nthe following quote character). Note also that a single backslash\nfollowed by a newline is interpreted as those two characters as part\nof the literal, *not* as a line continuation.\n',
'subscriptions': u'\nSubscriptions\n*************\n\nA subscription selects an item of a sequence (string, tuple or list)\nor mapping (dictionary) object:\n\n subscription ::= primary "[" expression_list "]"\n\nThe primary must evaluate to an object that supports subscription\n(lists or dictionaries for example). User-defined objects can support\nsubscription by defining a "__getitem__()" method.\n\nFor built-in objects, there are two types of objects that support\nsubscription:\n\nIf the primary is a mapping, the expression list must evaluate to an\nobject whose value is one of the keys of the mapping, and the\nsubscription selects the value in the mapping that corresponds to that\nkey. (The expression list is a tuple except if it has exactly one\nitem.)\n\nIf the primary is a sequence, the expression (list) must evaluate to\nan integer or a slice (as discussed in the following section).\n\nThe formal syntax makes no special provision for negative indices in\nsequences; however, built-in sequences all provide a "__getitem__()"\nmethod that interprets negative indices by adding the length of the\nsequence to the index (so that "x[-1]" selects the last item of "x").\nThe resulting value must be a nonnegative integer less than the number\nof items in the sequence, and the subscription selects the item whose\nindex is that value (counting from zero). Since the support for\nnegative indices and slicing occurs in the object\'s "__getitem__()"\nmethod, subclasses overriding this method will need to explicitly add\nthat support.\n\nA string\'s items are characters. A character is not a separate data\ntype but a string of exactly one character.\n',
'truth': u'\nTruth Value Testing\n*******************\n\nAny object can be tested for truth value, for use in an "if" or\n"while" condition or as operand of the Boolean operations below. The\nfollowing values are considered false:\n\n* "None"\n\n* "False"\n\n* zero of any numeric type, for example, "0", "0.0", "0j".\n\n* any empty sequence, for example, "\'\'", "()", "[]".\n\n* any empty mapping, for example, "{}".\n\n* instances of user-defined classes, if the class defines a\n "__bool__()" or "__len__()" method, when that method returns the\n integer zero or "bool" value "False". [1]\n\nAll other values are considered true --- so objects of many types are\nalways true.\n\nOperations and built-in functions that have a Boolean result always\nreturn "0" or "False" for false and "1" or "True" for true, unless\notherwise stated. (Important exception: the Boolean operations "or"\nand "and" always return one of their operands.)\n',
'try': u'\nThe "try" statement\n*******************\n\nThe "try" statement specifies exception handlers and/or cleanup code\nfor a group of statements:\n\n try_stmt ::= try1_stmt | try2_stmt\n try1_stmt ::= "try" ":" suite\n ("except" [expression ["as" identifier]] ":" suite)+\n ["else" ":" suite]\n ["finally" ":" suite]\n try2_stmt ::= "try" ":" suite\n "finally" ":" suite\n\nThe "except" clause(s) specify one or more exception handlers. When no\nexception occurs in the "try" clause, no exception handler is\nexecuted. When an exception occurs in the "try" suite, a search for an\nexception handler is started. This search inspects the except clauses\nin turn until one is found that matches the exception. An expression-\nless except clause, if present, must be last; it matches any\nexception. For an except clause with an expression, that expression\nis evaluated, and the clause matches the exception if the resulting\nobject is "compatible" with the exception. An object is compatible\nwith an exception if it is the class or a base class of the exception\nobject or a tuple containing an item compatible with the exception.\n\nIf no except clause matches the exception, the search for an exception\nhandler continues in the surrounding code and on the invocation stack.\n[1]\n\nIf the evaluation of an expression in the header of an except clause\nraises an exception, the original search for a handler is canceled and\na search starts for the new exception in the surrounding code and on\nthe call stack (it is treated as if the entire "try" statement raised\nthe exception).\n\nWhen a matching except clause is found, the exception is assigned to\nthe target specified after the "as" keyword in that except clause, if\npresent, and the except clause\'s suite is executed. All except\nclauses must have an executable block. When the end of this block is\nreached, execution continues normally after the entire try statement.\n(This means that if two nested handlers exist for the same exception,\nand the exception occurs in the try clause of the inner handler, the\nouter handler will not handle the exception.)\n\nWhen an exception has been assigned using "as target", it is cleared\nat the end of the except clause. This is as if\n\n except E as N:\n foo\n\nwas translated to\n\n except E as N:\n try:\n foo\n finally:\n del N\n\nThis means the exception must be assigned to a different name to be\nable to refer to it after the except clause. Exceptions are cleared\nbecause with the traceback attached to them, they form a reference\ncycle with the stack frame, keeping all locals in that frame alive\nuntil the next garbage collection occurs.\n\nBefore an except clause\'s suite is executed, details about the\nexception are stored in the "sys" module and can be accessed via\n"sys.exc_info()". "sys.exc_info()" returns a 3-tuple consisting of the\nexception class, the exception instance and a traceback object (see\nsection *The standard type hierarchy*) identifying the point in the\nprogram where the exception occurred. "sys.exc_info()" values are\nrestored to their previous values (before the call) when returning\nfrom a function that handled an exception.\n\nThe optional "else" clause is executed if and when control flows off\nthe end of the "try" clause. [2] Exceptions in the "else" clause are\nnot handled by the preceding "except" clauses.\n\nIf "finally" is present, it specifies a \'cleanup\' handler. The "try"\nclause is executed, including any "except" and "else" clauses. If an\nexception occurs in any of the clauses and is not handled, the\nexception is temporarily saved. The "finally" clause is executed. If\nthere is a saved exception it is re-raised at the end of the "finally"\nclause. If the "finally" clause raises another exception, the saved\nexception is set as the context of the new exception. If the "finally"\nclause executes a "return" or "break" statement, the saved exception\nis discarded:\n\n >>> def f():\n ... try:\n ... 1/0\n ... finally:\n ... return 42\n ...\n >>> f()\n 42\n\nThe exception information is not available to the program during\nexecution of the "finally" clause.\n\nWhen a "return", "break" or "continue" statement is executed in the\n"try" suite of a "try"..."finally" statement, the "finally" clause is\nalso executed \'on the way out.\' A "continue" statement is illegal in\nthe "finally" clause. (The reason is a problem with the current\nimplementation --- this restriction may be lifted in the future).\n\nThe return value of a function is determined by the last "return"\nstatement executed. Since the "finally" clause always executes, a\n"return" statement executed in the "finally" clause will always be the\nlast one executed:\n\n >>> def foo():\n ... try:\n ... return \'try\'\n ... finally:\n ... return \'finally\'\n ...\n >>> foo()\n \'finally\'\n\nAdditional information on exceptions can be found in section\n*Exceptions*, and information on using the "raise" statement to\ngenerate exceptions may be found in section *The raise statement*.\n',
'typesmapping': u'\nMapping Types --- "dict"\n************************\n\nA *mapping* object maps *hashable* values to arbitrary objects.\nMappings are mutable objects. There is currently only one standard\nmapping type, the *dictionary*. (For other containers see the built-\nin "list", "set", and "tuple" classes, and the "collections" module.)\n\nA dictionary\'s keys are *almost* arbitrary values. Values that are\nnot *hashable*, that is, values containing lists, dictionaries or\nother mutable types (that are compared by value rather than by object\nidentity) may not be used as keys. Numeric types used for keys obey\nthe normal rules for numeric comparison: if two numbers compare equal\n(such as "1" and "1.0") then they can be used interchangeably to index\nthe same dictionary entry. (Note however, that since computers store\nfloating-point numbers as approximations it is usually unwise to use\nthem as dictionary keys.)\n\nDictionaries can be created by placing a comma-separated list of "key:\nvalue" pairs within braces, for example: "{\'jack\': 4098, \'sjoerd\':\n4127}" or "{4098: \'jack\', 4127: \'sjoerd\'}", or by the "dict"\nconstructor.\n\nclass class dict(**kwarg)\nclass class dict(mapping, **kwarg)\nclass class dict(iterable, **kwarg)\n\n Return a new dictionary initialized from an optional positional\n argument and a possibly empty set of keyword arguments.\n\n If no positional argument is given, an empty dictionary is created.\n If a positional argument is given and it is a mapping object, a\n dictionary is created with the same key-value pairs as the mapping\n object. Otherwise, the positional argument must be an *iterable*\n object. Each item in the iterable must itself be an iterable with\n exactly two objects. The first object of each item becomes a key\n in the new dictionary, and the second object the corresponding\n value. If a key occurs more than once, the last value for that key\n becomes the corresponding value in the new dictionary.\n\n If keyword arguments are given, the keyword arguments and their\n values are added to the dictionary created from the positional\n argument. If a key being added is already present, the value from\n the keyword argument replaces the value from the positional\n argument.\n\n To illustrate, the following examples all return a dictionary equal\n to "{"one": 1, "two": 2, "three": 3}":\n\n >>> a = dict(one=1, two=2, three=3)\n >>> b = {\'one\': 1, \'two\': 2, \'three\': 3}\n >>> c = dict(zip([\'one\', \'two\', \'three\'], [1, 2, 3]))\n >>> d = dict([(\'two\', 2), (\'one\', 1), (\'three\', 3)])\n >>> e = dict({\'three\': 3, \'one\': 1, \'two\': 2})\n >>> a == b == c == d == e\n True\n\n Providing keyword arguments as in the first example only works for\n keys that are valid Python identifiers. Otherwise, any valid keys\n can be used.\n\n These are the operations that dictionaries support (and therefore,\n custom mapping types should support too):\n\n len(d)\n\n Return the number of items in the dictionary *d*.\n\n d[key]\n\n Return the item of *d* with key *key*. Raises a "KeyError" if\n *key* is not in the map.\n\n If a subclass of dict defines a method "__missing__()" and *key*\n is not present, the "d[key]" operation calls that method with\n the key *key* as argument. The "d[key]" operation then returns\n or raises whatever is returned or raised by the\n "__missing__(key)" call. No other operations or methods invoke\n "__missing__()". If "__missing__()" is not defined, "KeyError"\n is raised. "__missing__()" must be a method; it cannot be an\n instance variable:\n\n >>> class Counter(dict):\n ... def __missing__(self, key):\n ... return 0\n >>> c = Counter()\n >>> c[\'red\']\n 0\n >>> c[\'red\'] += 1\n >>> c[\'red\']\n 1\n\n The example above shows part of the implementation of\n "collections.Counter". A different "__missing__" method is used\n by "collections.defaultdict".\n\n d[key] = value\n\n Set "d[key]" to *value*.\n\n del d[key]\n\n Remove "d[key]" from *d*. Raises a "KeyError" if *key* is not\n in the map.\n\n key in d\n\n Return "True" if *d* has a key *key*, else "False".\n\n key not in d\n\n Equivalent to "not key in d".\n\n iter(d)\n\n Return an iterator over the keys of the dictionary. This is a\n shortcut for "iter(d.keys())".\n\n clear()\n\n Remove all items from the dictionary.\n\n copy()\n\n Return a shallow copy of the dictionary.\n\n classmethod fromkeys(seq[, value])\n\n Create a new dictionary with keys from *seq* and values set to\n *value*.\n\n "fromkeys()" is a class method that returns a new dictionary.\n *value* defaults to "None".\n\n get(key[, default])\n\n Return the value for *key* if *key* is in the dictionary, else\n *default*. If *default* is not given, it defaults to "None", so\n that this method never raises a "KeyError".\n\n items()\n\n Return a new view of the dictionary\'s items ("(key, value)"\n pairs). See the *documentation of view objects*.\n\n keys()\n\n Return a new view of the dictionary\'s keys. See the\n *documentation of view objects*.\n\n pop(key[, default])\n\n If *key* is in the dictionary, remove it and return its value,\n else return *default*. If *default* is not given and *key* is\n not in the dictionary, a "KeyError" is raised.\n\n popitem()\n\n Remove and return an arbitrary "(key, value)" pair from the\n dictionary.\n\n "popitem()" is useful to destructively iterate over a\n dictionary, as often used in set algorithms. If the dictionary\n is empty, calling "popitem()" raises a "KeyError".\n\n setdefault(key[, default])\n\n If *key* is in the dictionary, return its value. If not, insert\n *key* with a value of *default* and return *default*. *default*\n defaults to "None".\n\n update([other])\n\n Update the dictionary with the key/value pairs from *other*,\n overwriting existing keys. Return "None".\n\n "update()" accepts either another dictionary object or an\n iterable of key/value pairs (as tuples or other iterables of\n length two). If keyword arguments are specified, the dictionary\n is then updated with those key/value pairs: "d.update(red=1,\n blue=2)".\n\n values()\n\n Return a new view of the dictionary\'s values. See the\n *documentation of view objects*.\n\n Dictionaries compare equal if and only if they have the same "(key,\n value)" pairs. Order comparisons (\'<\', \'<=\', \'>=\', \'>\') raise\n "TypeError".\n\nSee also: "types.MappingProxyType" can be used to create a read-only\n view of a "dict".\n\n\nDictionary view objects\n=======================\n\nThe objects returned by "dict.keys()", "dict.values()" and\n"dict.items()" are *view objects*. They provide a dynamic view on the\ndictionary\'s entries, which means that when the dictionary changes,\nthe view reflects these changes.\n\nDictionary views can be iterated over to yield their respective data,\nand support membership tests:\n\nlen(dictview)\n\n Return the number of entries in the dictionary.\n\niter(dictview)\n\n Return an iterator over the keys, values or items (represented as\n tuples of "(key, value)") in the dictionary.\n\n Keys and values are iterated over in an arbitrary order which is\n non-random, varies across Python implementations, and depends on\n the dictionary\'s history of insertions and deletions. If keys,\n values and items views are iterated over with no intervening\n modifications to the dictionary, the order of items will directly\n correspond. This allows the creation of "(value, key)" pairs using\n "zip()": "pairs = zip(d.values(), d.keys())". Another way to\n create the same list is "pairs = [(v, k) for (k, v) in d.items()]".\n\n Iterating views while adding or deleting entries in the dictionary\n may raise a "RuntimeError" or fail to iterate over all entries.\n\nx in dictview\n\n Return "True" if *x* is in the underlying dictionary\'s keys, values\n or items (in the latter case, *x* should be a "(key, value)"\n tuple).\n\nKeys views are set-like since their entries are unique and hashable.\nIf all values are hashable, so that "(key, value)" pairs are unique\nand hashable, then the items view is also set-like. (Values views are\nnot treated as set-like since the entries are generally not unique.)\nFor set-like views, all of the operations defined for the abstract\nbase class "collections.abc.Set" are available (for example, "==",\n"<", or "^").\n\nAn example of dictionary view usage:\n\n >>> dishes = {\'eggs\': 2, \'sausage\': 1, \'bacon\': 1, \'spam\': 500}\n >>> keys = dishes.keys()\n >>> values = dishes.values()\n\n >>> # iteration\n >>> n = 0\n >>> for val in values:\n ... n += val\n >>> print(n)\n 504\n\n >>> # keys and values are iterated over in the same order\n >>> list(keys)\n [\'eggs\', \'bacon\', \'sausage\', \'spam\']\n >>> list(values)\n [2, 1, 1, 500]\n\n >>> # view objects are dynamic and reflect dict changes\n >>> del dishes[\'eggs\']\n >>> del dishes[\'sausage\']\n >>> list(keys)\n [\'spam\', \'bacon\']\n\n >>> # set operations\n >>> keys & {\'eggs\', \'bacon\', \'salad\'}\n {\'bacon\'}\n >>> keys ^ {\'sausage\', \'juice\'}\n {\'juice\', \'sausage\', \'bacon\', \'spam\'}\n',
'typesmethods': u'\nMethods\n*******\n\nMethods are functions that are called using the attribute notation.\nThere are two flavors: built-in methods (such as "append()" on lists)\nand class instance methods. Built-in methods are described with the\ntypes that support them.\n\nIf you access a method (a function defined in a class namespace)\nthrough an instance, you get a special object: a *bound method* (also\ncalled *instance method*) object. When called, it will add the "self"\nargument to the argument list. Bound methods have two special read-\nonly attributes: "m.__self__" is the object on which the method\noperates, and "m.__func__" is the function implementing the method.\nCalling "m(arg-1, arg-2, ..., arg-n)" is completely equivalent to\ncalling "m.__func__(m.__self__, arg-1, arg-2, ..., arg-n)".\n\nLike function objects, bound method objects support getting arbitrary\nattributes. However, since method attributes are actually stored on\nthe underlying function object ("meth.__func__"), setting method\nattributes on bound methods is disallowed. Attempting to set an\nattribute on a method results in an "AttributeError" being raised. In\norder to set a method attribute, you need to explicitly set it on the\nunderlying function object:\n\n >>> class C:\n ... def method(self):\n ... pass\n ...\n >>> c = C()\n >>> c.method.whoami = \'my name is method\' # can\'t set on the method\n Traceback (most recent call last):\n File "<stdin>", line 1, in <module>\n AttributeError: \'method\' object has no attribute \'whoami\'\n >>> c.method.__func__.whoami = \'my name is method\'\n >>> c.method.whoami\n \'my name is method\'\n\nSee *The standard type hierarchy* for more information.\n',
'typesmodules': u'\nModules\n*******\n\nThe only special operation on a module is attribute access: "m.name",\nwhere *m* is a module and *name* accesses a name defined in *m*\'s\nsymbol table. Module attributes can be assigned to. (Note that the\n"import" statement is not, strictly speaking, an operation on a module\nobject; "import foo" does not require a module object named *foo* to\nexist, rather it requires an (external) *definition* for a module\nnamed *foo* somewhere.)\n\nA special attribute of every module is "__dict__". This is the\ndictionary containing the module\'s symbol table. Modifying this\ndictionary will actually change the module\'s symbol table, but direct\nassignment to the "__dict__" attribute is not possible (you can write\n"m.__dict__[\'a\'] = 1", which defines "m.a" to be "1", but you can\'t\nwrite "m.__dict__ = {}"). Modifying "__dict__" directly is not\nrecommended.\n\nModules built into the interpreter are written like this: "<module\n\'sys\' (built-in)>". If loaded from a file, they are written as\n"<module \'os\' from \'/usr/local/lib/pythonX.Y/os.pyc\'>".\n',
- 'typesseq': u'\nSequence Types --- "list", "tuple", "range"\n*******************************************\n\nThere are three basic sequence types: lists, tuples, and range\nobjects. Additional sequence types tailored for processing of *binary\ndata* and *text strings* are described in dedicated sections.\n\n\nCommon Sequence Operations\n==========================\n\nThe operations in the following table are supported by most sequence\ntypes, both mutable and immutable. The "collections.abc.Sequence" ABC\nis provided to make it easier to correctly implement these operations\non custom sequence types.\n\nThis table lists the sequence operations sorted in ascending priority.\nIn the table, *s* and *t* are sequences of the same type, *n*, *i*,\n*j* and *k* are integers and *x* is an arbitrary object that meets any\ntype and value restrictions imposed by *s*.\n\nThe "in" and "not in" operations have the same priorities as the\ncomparison operations. The "+" (concatenation) and "*" (repetition)\noperations have the same priority as the corresponding numeric\noperations.\n\n+----------------------------+----------------------------------+------------+\n| Operation | Result | Notes |\n+============================+==================================+============+\n| "x in s" | "True" if an item of *s* is | (1) |\n| | equal to *x*, else "False" | |\n+----------------------------+----------------------------------+------------+\n| "x not in s" | "False" if an item of *s* is | (1) |\n| | equal to *x*, else "True" | |\n+----------------------------+----------------------------------+------------+\n| "s + t" | the concatenation of *s* and *t* | (6)(7) |\n+----------------------------+----------------------------------+------------+\n| "s * n" or "n * s" | equivalent to adding *s* to | (2)(7) |\n| | itself *n* times | |\n+----------------------------+----------------------------------+------------+\n| "s[i]" | *i*th item of *s*, origin 0 | (3) |\n+----------------------------+----------------------------------+------------+\n| "s[i:j]" | slice of *s* from *i* to *j* | (3)(4) |\n+----------------------------+----------------------------------+------------+\n| "s[i:j:k]" | slice of *s* from *i* to *j* | (3)(5) |\n| | with step *k* | |\n+----------------------------+----------------------------------+------------+\n| "len(s)" | length of *s* | |\n+----------------------------+----------------------------------+------------+\n| "min(s)" | smallest item of *s* | |\n+----------------------------+----------------------------------+------------+\n| "max(s)" | largest item of *s* | |\n+----------------------------+----------------------------------+------------+\n| "s.index(x[, i[, j]])" | index of the first occurrence of | (8) |\n| | *x* in *s* (at or after index | |\n| | *i* and before index *j*) | |\n+----------------------------+----------------------------------+------------+\n| "s.count(x)" | total number of occurrences of | |\n| | *x* in *s* | |\n+----------------------------+----------------------------------+------------+\n\nSequences of the same type also support comparisons. In particular,\ntuples and lists are compared lexicographically by comparing\ncorresponding elements. This means that to compare equal, every\nelement must compare equal and the two sequences must be of the same\ntype and have the same length. (For full details see *Comparisons* in\nthe language reference.)\n\nNotes:\n\n1. While the "in" and "not in" operations are used only for simple\n containment testing in the general case, some specialised sequences\n (such as "str", "bytes" and "bytearray") also use them for\n subsequence testing:\n\n >>> "gg" in "eggs"\n True\n\n2. Values of *n* less than "0" are treated as "0" (which yields an\n empty sequence of the same type as *s*). Note that items in the\n sequence *s* are not copied; they are referenced multiple times.\n This often haunts new Python programmers; consider:\n\n >>> lists = [[]] * 3\n >>> lists\n [[], [], []]\n >>> lists[0].append(3)\n >>> lists\n [[3], [3], [3]]\n\n What has happened is that "[[]]" is a one-element list containing\n an empty list, so all three elements of "[[]] * 3" are references\n to this single empty list. Modifying any of the elements of\n "lists" modifies this single list. You can create a list of\n different lists this way:\n\n >>> lists = [[] for i in range(3)]\n >>> lists[0].append(3)\n >>> lists[1].append(5)\n >>> lists[2].append(7)\n >>> lists\n [[3], [5], [7]]\n\n Further explanation is available in the FAQ entry *How do I create\n a multidimensional list?*.\n\n3. If *i* or *j* is negative, the index is relative to the end of\n the string: "len(s) + i" or "len(s) + j" is substituted. But note\n that "-0" is still "0".\n\n4. The slice of *s* from *i* to *j* is defined as the sequence of\n items with index *k* such that "i <= k < j". If *i* or *j* is\n greater than "len(s)", use "len(s)". If *i* is omitted or "None",\n use "0". If *j* is omitted or "None", use "len(s)". If *i* is\n greater than or equal to *j*, the slice is empty.\n\n5. The slice of *s* from *i* to *j* with step *k* is defined as the\n sequence of items with index "x = i + n*k" such that "0 <= n <\n (j-i)/k". In other words, the indices are "i", "i+k", "i+2*k",\n "i+3*k" and so on, stopping when *j* is reached (but never\n including *j*). If *i* or *j* is greater than "len(s)", use\n "len(s)". If *i* or *j* are omitted or "None", they become "end"\n values (which end depends on the sign of *k*). Note, *k* cannot be\n zero. If *k* is "None", it is treated like "1".\n\n6. Concatenating immutable sequences always results in a new\n object. This means that building up a sequence by repeated\n concatenation will have a quadratic runtime cost in the total\n sequence length. To get a linear runtime cost, you must switch to\n one of the alternatives below:\n\n * if concatenating "str" objects, you can build a list and use\n "str.join()" at the end or else write to an "io.StringIO"\n instance and retrieve its value when complete\n\n * if concatenating "bytes" objects, you can similarly use\n "bytes.join()" or "io.BytesIO", or you can do in-place\n concatenation with a "bytearray" object. "bytearray" objects are\n mutable and have an efficient overallocation mechanism\n\n * if concatenating "tuple" objects, extend a "list" instead\n\n * for other types, investigate the relevant class documentation\n\n7. Some sequence types (such as "range") only support item\n sequences that follow specific patterns, and hence don\'t support\n sequence concatenation or repetition.\n\n8. "index" raises "ValueError" when *x* is not found in *s*. When\n supported, the additional arguments to the index method allow\n efficient searching of subsections of the sequence. Passing the\n extra arguments is roughly equivalent to using "s[i:j].index(x)",\n only without copying any data and with the returned index being\n relative to the start of the sequence rather than the start of the\n slice.\n\n\nImmutable Sequence Types\n========================\n\nThe only operation that immutable sequence types generally implement\nthat is not also implemented by mutable sequence types is support for\nthe "hash()" built-in.\n\nThis support allows immutable sequences, such as "tuple" instances, to\nbe used as "dict" keys and stored in "set" and "frozenset" instances.\n\nAttempting to hash an immutable sequence that contains unhashable\nvalues will result in "TypeError".\n\n\nMutable Sequence Types\n======================\n\nThe operations in the following table are defined on mutable sequence\ntypes. The "collections.abc.MutableSequence" ABC is provided to make\nit easier to correctly implement these operations on custom sequence\ntypes.\n\nIn the table *s* is an instance of a mutable sequence type, *t* is any\niterable object and *x* is an arbitrary object that meets any type and\nvalue restrictions imposed by *s* (for example, "bytearray" only\naccepts integers that meet the value restriction "0 <= x <= 255").\n\n+--------------------------------+----------------------------------+-----------------------+\n| Operation | Result | Notes |\n+================================+==================================+=======================+\n| "s[i] = x" | item *i* of *s* is replaced by | |\n| | *x* | |\n+--------------------------------+----------------------------------+-----------------------+\n| "s[i:j] = t" | slice of *s* from *i* to *j* is | |\n| | replaced by the contents of the | |\n| | iterable *t* | |\n+--------------------------------+----------------------------------+-----------------------+\n| "del s[i:j]" | same as "s[i:j] = []" | |\n+--------------------------------+----------------------------------+-----------------------+\n| "s[i:j:k] = t" | the elements of "s[i:j:k]" are | (1) |\n| | replaced by those of *t* | |\n+--------------------------------+----------------------------------+-----------------------+\n| "del s[i:j:k]" | removes the elements of | |\n| | "s[i:j:k]" from the list | |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.append(x)" | appends *x* to the end of the | |\n| | sequence (same as | |\n| | "s[len(s):len(s)] = [x]") | |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.clear()" | removes all items from "s" (same | (5) |\n| | as "del s[:]") | |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.copy()" | creates a shallow copy of "s" | (5) |\n| | (same as "s[:]") | |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.extend(t)" or "s += t" | extends *s* with the contents of | |\n| | *t* (for the most part the same | |\n| | as "s[len(s):len(s)] = t") | |\n+--------------------------------+----------------------------------+-----------------------+\n| "s *= n" | updates *s* with its contents | (6) |\n| | repeated *n* times | |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.insert(i, x)" | inserts *x* into *s* at the | |\n| | index given by *i* (same as | |\n| | "s[i:i] = [x]") | |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.pop([i])" | retrieves the item at *i* and | (2) |\n| | also removes it from *s* | |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.remove(x)" | remove the first item from *s* | (3) |\n| | where "s[i] == x" | |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.reverse()" | reverses the items of *s* in | (4) |\n| | place | |\n+--------------------------------+----------------------------------+-----------------------+\n\nNotes:\n\n1. *t* must have the same length as the slice it is replacing.\n\n2. The optional argument *i* defaults to "-1", so that by default\n the last item is removed and returned.\n\n3. "remove" raises "ValueError" when *x* is not found in *s*.\n\n4. The "reverse()" method modifies the sequence in place for\n economy of space when reversing a large sequence. To remind users\n that it operates by side effect, it does not return the reversed\n sequence.\n\n5. "clear()" and "copy()" are included for consistency with the\n interfaces of mutable containers that don\'t support slicing\n operations (such as "dict" and "set")\n\n New in version 3.3: "clear()" and "copy()" methods.\n\n6. The value *n* is an integer, or an object implementing\n "__index__()". Zero and negative values of *n* clear the sequence.\n Items in the sequence are not copied; they are referenced multiple\n times, as explained for "s * n" under *Common Sequence Operations*.\n\n\nLists\n=====\n\nLists are mutable sequences, typically used to store collections of\nhomogeneous items (where the precise degree of similarity will vary by\napplication).\n\nclass class list([iterable])\n\n Lists may be constructed in several ways:\n\n * Using a pair of square brackets to denote the empty list: "[]"\n\n * Using square brackets, separating items with commas: "[a]",\n "[a, b, c]"\n\n * Using a list comprehension: "[x for x in iterable]"\n\n * Using the type constructor: "list()" or "list(iterable)"\n\n The constructor builds a list whose items are the same and in the\n same order as *iterable*\'s items. *iterable* may be either a\n sequence, a container that supports iteration, or an iterator\n object. If *iterable* is already a list, a copy is made and\n returned, similar to "iterable[:]". For example, "list(\'abc\')"\n returns "[\'a\', \'b\', \'c\']" and "list( (1, 2, 3) )" returns "[1, 2,\n 3]". If no argument is given, the constructor creates a new empty\n list, "[]".\n\n Many other operations also produce lists, including the "sorted()"\n built-in.\n\n Lists implement all of the *common* and *mutable* sequence\n operations. Lists also provide the following additional method:\n\n sort(*, key=None, reverse=None)\n\n This method sorts the list in place, using only "<" comparisons\n between items. Exceptions are not suppressed - if any comparison\n operations fail, the entire sort operation will fail (and the\n list will likely be left in a partially modified state).\n\n "sort()" accepts two arguments that can only be passed by\n keyword (*keyword-only arguments*):\n\n *key* specifies a function of one argument that is used to\n extract a comparison key from each list element (for example,\n "key=str.lower"). The key corresponding to each item in the list\n is calculated once and then used for the entire sorting process.\n The default value of "None" means that list items are sorted\n directly without calculating a separate key value.\n\n The "functools.cmp_to_key()" utility is available to convert a\n 2.x style *cmp* function to a *key* function.\n\n *reverse* is a boolean value. If set to "True", then the list\n elements are sorted as if each comparison were reversed.\n\n This method modifies the sequence in place for economy of space\n when sorting a large sequence. To remind users that it operates\n by side effect, it does not return the sorted sequence (use\n "sorted()" to explicitly request a new sorted list instance).\n\n The "sort()" method is guaranteed to be stable. A sort is\n stable if it guarantees not to change the relative order of\n elements that compare equal --- this is helpful for sorting in\n multiple passes (for example, sort by department, then by salary\n grade).\n\n **CPython implementation detail:** While a list is being sorted,\n the effect of attempting to mutate, or even inspect, the list is\n undefined. The C implementation of Python makes the list appear\n empty for the duration, and raises "ValueError" if it can detect\n that the list has been mutated during a sort.\n\n\nTuples\n======\n\nTuples are immutable sequences, typically used to store collections of\nheterogeneous data (such as the 2-tuples produced by the "enumerate()"\nbuilt-in). Tuples are also used for cases where an immutable sequence\nof homogeneous data is needed (such as allowing storage in a "set" or\n"dict" instance).\n\nclass class tuple([iterable])\n\n Tuples may be constructed in a number of ways:\n\n * Using a pair of parentheses to denote the empty tuple: "()"\n\n * Using a trailing comma for a singleton tuple: "a," or "(a,)"\n\n * Separating items with commas: "a, b, c" or "(a, b, c)"\n\n * Using the "tuple()" built-in: "tuple()" or "tuple(iterable)"\n\n The constructor builds a tuple whose items are the same and in the\n same order as *iterable*\'s items. *iterable* may be either a\n sequence, a container that supports iteration, or an iterator\n object. If *iterable* is already a tuple, it is returned\n unchanged. For example, "tuple(\'abc\')" returns "(\'a\', \'b\', \'c\')"\n and "tuple( [1, 2, 3] )" returns "(1, 2, 3)". If no argument is\n given, the constructor creates a new empty tuple, "()".\n\n Note that it is actually the comma which makes a tuple, not the\n parentheses. The parentheses are optional, except in the empty\n tuple case, or when they are needed to avoid syntactic ambiguity.\n For example, "f(a, b, c)" is a function call with three arguments,\n while "f((a, b, c))" is a function call with a 3-tuple as the sole\n argument.\n\n Tuples implement all of the *common* sequence operations.\n\nFor heterogeneous collections of data where access by name is clearer\nthan access by index, "collections.namedtuple()" may be a more\nappropriate choice than a simple tuple object.\n\n\nRanges\n======\n\nThe "range" type represents an immutable sequence of numbers and is\ncommonly used for looping a specific number of times in "for" loops.\n\nclass class range(stop)\nclass class range(start, stop[, step])\n\n The arguments to the range constructor must be integers (either\n built-in "int" or any object that implements the "__index__"\n special method). If the *step* argument is omitted, it defaults to\n "1". If the *start* argument is omitted, it defaults to "0". If\n *step* is zero, "ValueError" is raised.\n\n For a positive *step*, the contents of a range "r" are determined\n by the formula "r[i] = start + step*i" where "i >= 0" and "r[i] <\n stop".\n\n For a negative *step*, the contents of the range are still\n determined by the formula "r[i] = start + step*i", but the\n constraints are "i >= 0" and "r[i] > stop".\n\n A range object will be empty if "r[0]" does not meet the value\n constraint. Ranges do support negative indices, but these are\n interpreted as indexing from the end of the sequence determined by\n the positive indices.\n\n Ranges containing absolute values larger than "sys.maxsize" are\n permitted but some features (such as "len()") may raise\n "OverflowError".\n\n Range examples:\n\n >>> list(range(10))\n [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n >>> list(range(1, 11))\n [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n >>> list(range(0, 30, 5))\n [0, 5, 10, 15, 20, 25]\n >>> list(range(0, 10, 3))\n [0, 3, 6, 9]\n >>> list(range(0, -10, -1))\n [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]\n >>> list(range(0))\n []\n >>> list(range(1, 0))\n []\n\n Ranges implement all of the *common* sequence operations except\n concatenation and repetition (due to the fact that range objects\n can only represent sequences that follow a strict pattern and\n repetition and concatenation will usually violate that pattern).\n\nThe advantage of the "range" type over a regular "list" or "tuple" is\nthat a "range" object will always take the same (small) amount of\nmemory, no matter the size of the range it represents (as it only\nstores the "start", "stop" and "step" values, calculating individual\nitems and subranges as needed).\n\nRange objects implement the "collections.abc.Sequence" ABC, and\nprovide features such as containment tests, element index lookup,\nslicing and support for negative indices (see *Sequence Types ---\nlist, tuple, range*):\n\n>>> r = range(0, 20, 2)\n>>> r\nrange(0, 20, 2)\n>>> 11 in r\nFalse\n>>> 10 in r\nTrue\n>>> r.index(10)\n5\n>>> r[5]\n10\n>>> r[:5]\nrange(0, 10, 2)\n>>> r[-1]\n18\n\nTesting range objects for equality with "==" and "!=" compares them as\nsequences. That is, two range objects are considered equal if they\nrepresent the same sequence of values. (Note that two range objects\nthat compare equal might have different "start", "stop" and "step"\nattributes, for example "range(0) == range(2, 1, 3)" or "range(0, 3,\n2) == range(0, 4, 2)".)\n\nChanged in version 3.2: Implement the Sequence ABC. Support slicing\nand negative indices. Test "int" objects for membership in constant\ntime instead of iterating through all items.\n\nChanged in version 3.3: Define \'==\' and \'!=\' to compare range objects\nbased on the sequence of values they define (instead of comparing\nbased on object identity).\n\nNew in version 3.3: The "start", "stop" and "step" attributes.\n',
+ 'typesseq': u'\nSequence Types --- "list", "tuple", "range"\n*******************************************\n\nThere are three basic sequence types: lists, tuples, and range\nobjects. Additional sequence types tailored for processing of *binary\ndata* and *text strings* are described in dedicated sections.\n\n\nCommon Sequence Operations\n==========================\n\nThe operations in the following table are supported by most sequence\ntypes, both mutable and immutable. The "collections.abc.Sequence" ABC\nis provided to make it easier to correctly implement these operations\non custom sequence types.\n\nThis table lists the sequence operations sorted in ascending priority.\nIn the table, *s* and *t* are sequences of the same type, *n*, *i*,\n*j* and *k* are integers and *x* is an arbitrary object that meets any\ntype and value restrictions imposed by *s*.\n\nThe "in" and "not in" operations have the same priorities as the\ncomparison operations. The "+" (concatenation) and "*" (repetition)\noperations have the same priority as the corresponding numeric\noperations.\n\n+----------------------------+----------------------------------+------------+\n| Operation | Result | Notes |\n+============================+==================================+============+\n| "x in s" | "True" if an item of *s* is | (1) |\n| | equal to *x*, else "False" | |\n+----------------------------+----------------------------------+------------+\n| "x not in s" | "False" if an item of *s* is | (1) |\n| | equal to *x*, else "True" | |\n+----------------------------+----------------------------------+------------+\n| "s + t" | the concatenation of *s* and *t* | (6)(7) |\n+----------------------------+----------------------------------+------------+\n| "s * n" or "n * s" | equivalent to adding *s* to | (2)(7) |\n| | itself *n* times | |\n+----------------------------+----------------------------------+------------+\n| "s[i]" | *i*th item of *s*, origin 0 | (3) |\n+----------------------------+----------------------------------+------------+\n| "s[i:j]" | slice of *s* from *i* to *j* | (3)(4) |\n+----------------------------+----------------------------------+------------+\n| "s[i:j:k]" | slice of *s* from *i* to *j* | (3)(5) |\n| | with step *k* | |\n+----------------------------+----------------------------------+------------+\n| "len(s)" | length of *s* | |\n+----------------------------+----------------------------------+------------+\n| "min(s)" | smallest item of *s* | |\n+----------------------------+----------------------------------+------------+\n| "max(s)" | largest item of *s* | |\n+----------------------------+----------------------------------+------------+\n| "s.index(x[, i[, j]])" | index of the first occurrence of | (8) |\n| | *x* in *s* (at or after index | |\n| | *i* and before index *j*) | |\n+----------------------------+----------------------------------+------------+\n| "s.count(x)" | total number of occurrences of | |\n| | *x* in *s* | |\n+----------------------------+----------------------------------+------------+\n\nSequences of the same type also support comparisons. In particular,\ntuples and lists are compared lexicographically by comparing\ncorresponding elements. This means that to compare equal, every\nelement must compare equal and the two sequences must be of the same\ntype and have the same length. (For full details see *Comparisons* in\nthe language reference.)\n\nNotes:\n\n1. While the "in" and "not in" operations are used only for simple\n containment testing in the general case, some specialised sequences\n (such as "str", "bytes" and "bytearray") also use them for\n subsequence testing:\n\n >>> "gg" in "eggs"\n True\n\n2. Values of *n* less than "0" are treated as "0" (which yields an\n empty sequence of the same type as *s*). Note that items in the\n sequence *s* are not copied; they are referenced multiple times.\n This often haunts new Python programmers; consider:\n\n >>> lists = [[]] * 3\n >>> lists\n [[], [], []]\n >>> lists[0].append(3)\n >>> lists\n [[3], [3], [3]]\n\n What has happened is that "[[]]" is a one-element list containing\n an empty list, so all three elements of "[[]] * 3" are references\n to this single empty list. Modifying any of the elements of\n "lists" modifies this single list. You can create a list of\n different lists this way:\n\n >>> lists = [[] for i in range(3)]\n >>> lists[0].append(3)\n >>> lists[1].append(5)\n >>> lists[2].append(7)\n >>> lists\n [[3], [5], [7]]\n\n Further explanation is available in the FAQ entry *How do I create\n a multidimensional list?*.\n\n3. If *i* or *j* is negative, the index is relative to the end of\n the string: "len(s) + i" or "len(s) + j" is substituted. But note\n that "-0" is still "0".\n\n4. The slice of *s* from *i* to *j* is defined as the sequence of\n items with index *k* such that "i <= k < j". If *i* or *j* is\n greater than "len(s)", use "len(s)". If *i* is omitted or "None",\n use "0". If *j* is omitted or "None", use "len(s)". If *i* is\n greater than or equal to *j*, the slice is empty.\n\n5. The slice of *s* from *i* to *j* with step *k* is defined as the\n sequence of items with index "x = i + n*k" such that "0 <= n <\n (j-i)/k". In other words, the indices are "i", "i+k", "i+2*k",\n "i+3*k" and so on, stopping when *j* is reached (but never\n including *j*). If *i* or *j* is greater than "len(s)", use\n "len(s)". If *i* or *j* are omitted or "None", they become "end"\n values (which end depends on the sign of *k*). Note, *k* cannot be\n zero. If *k* is "None", it is treated like "1".\n\n6. Concatenating immutable sequences always results in a new\n object. This means that building up a sequence by repeated\n concatenation will have a quadratic runtime cost in the total\n sequence length. To get a linear runtime cost, you must switch to\n one of the alternatives below:\n\n * if concatenating "str" objects, you can build a list and use\n "str.join()" at the end or else write to an "io.StringIO"\n instance and retrieve its value when complete\n\n * if concatenating "bytes" objects, you can similarly use\n "bytes.join()" or "io.BytesIO", or you can do in-place\n concatenation with a "bytearray" object. "bytearray" objects are\n mutable and have an efficient overallocation mechanism\n\n * if concatenating "tuple" objects, extend a "list" instead\n\n * for other types, investigate the relevant class documentation\n\n7. Some sequence types (such as "range") only support item\n sequences that follow specific patterns, and hence don\'t support\n sequence concatenation or repetition.\n\n8. "index" raises "ValueError" when *x* is not found in *s*. When\n supported, the additional arguments to the index method allow\n efficient searching of subsections of the sequence. Passing the\n extra arguments is roughly equivalent to using "s[i:j].index(x)",\n only without copying any data and with the returned index being\n relative to the start of the sequence rather than the start of the\n slice.\n\n\nImmutable Sequence Types\n========================\n\nThe only operation that immutable sequence types generally implement\nthat is not also implemented by mutable sequence types is support for\nthe "hash()" built-in.\n\nThis support allows immutable sequences, such as "tuple" instances, to\nbe used as "dict" keys and stored in "set" and "frozenset" instances.\n\nAttempting to hash an immutable sequence that contains unhashable\nvalues will result in "TypeError".\n\n\nMutable Sequence Types\n======================\n\nThe operations in the following table are defined on mutable sequence\ntypes. The "collections.abc.MutableSequence" ABC is provided to make\nit easier to correctly implement these operations on custom sequence\ntypes.\n\nIn the table *s* is an instance of a mutable sequence type, *t* is any\niterable object and *x* is an arbitrary object that meets any type and\nvalue restrictions imposed by *s* (for example, "bytearray" only\naccepts integers that meet the value restriction "0 <= x <= 255").\n\n+--------------------------------+----------------------------------+-----------------------+\n| Operation | Result | Notes |\n+================================+==================================+=======================+\n| "s[i] = x" | item *i* of *s* is replaced by | |\n| | *x* | |\n+--------------------------------+----------------------------------+-----------------------+\n| "s[i:j] = t" | slice of *s* from *i* to *j* is | |\n| | replaced by the contents of the | |\n| | iterable *t* | |\n+--------------------------------+----------------------------------+-----------------------+\n| "del s[i:j]" | same as "s[i:j] = []" | |\n+--------------------------------+----------------------------------+-----------------------+\n| "s[i:j:k] = t" | the elements of "s[i:j:k]" are | (1) |\n| | replaced by those of *t* | |\n+--------------------------------+----------------------------------+-----------------------+\n| "del s[i:j:k]" | removes the elements of | |\n| | "s[i:j:k]" from the list | |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.append(x)" | appends *x* to the end of the | |\n| | sequence (same as | |\n| | "s[len(s):len(s)] = [x]") | |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.clear()" | removes all items from "s" (same | (5) |\n| | as "del s[:]") | |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.copy()" | creates a shallow copy of "s" | (5) |\n| | (same as "s[:]") | |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.extend(t)" or "s += t" | extends *s* with the contents of | |\n| | *t* (for the most part the same | |\n| | as "s[len(s):len(s)] = t") | |\n+--------------------------------+----------------------------------+-----------------------+\n| "s *= n" | updates *s* with its contents | (6) |\n| | repeated *n* times | |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.insert(i, x)" | inserts *x* into *s* at the | |\n| | index given by *i* (same as | |\n| | "s[i:i] = [x]") | |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.pop([i])" | retrieves the item at *i* and | (2) |\n| | also removes it from *s* | |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.remove(x)" | remove the first item from *s* | (3) |\n| | where "s[i] == x" | |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.reverse()" | reverses the items of *s* in | (4) |\n| | place | |\n+--------------------------------+----------------------------------+-----------------------+\n\nNotes:\n\n1. *t* must have the same length as the slice it is replacing.\n\n2. The optional argument *i* defaults to "-1", so that by default\n the last item is removed and returned.\n\n3. "remove" raises "ValueError" when *x* is not found in *s*.\n\n4. The "reverse()" method modifies the sequence in place for\n economy of space when reversing a large sequence. To remind users\n that it operates by side effect, it does not return the reversed\n sequence.\n\n5. "clear()" and "copy()" are included for consistency with the\n interfaces of mutable containers that don\'t support slicing\n operations (such as "dict" and "set")\n\n New in version 3.3: "clear()" and "copy()" methods.\n\n6. The value *n* is an integer, or an object implementing\n "__index__()". Zero and negative values of *n* clear the sequence.\n Items in the sequence are not copied; they are referenced multiple\n times, as explained for "s * n" under *Common Sequence Operations*.\n\n\nLists\n=====\n\nLists are mutable sequences, typically used to store collections of\nhomogeneous items (where the precise degree of similarity will vary by\napplication).\n\nclass class list([iterable])\n\n Lists may be constructed in several ways:\n\n * Using a pair of square brackets to denote the empty list: "[]"\n\n * Using square brackets, separating items with commas: "[a]",\n "[a, b, c]"\n\n * Using a list comprehension: "[x for x in iterable]"\n\n * Using the type constructor: "list()" or "list(iterable)"\n\n The constructor builds a list whose items are the same and in the\n same order as *iterable*\'s items. *iterable* may be either a\n sequence, a container that supports iteration, or an iterator\n object. If *iterable* is already a list, a copy is made and\n returned, similar to "iterable[:]". For example, "list(\'abc\')"\n returns "[\'a\', \'b\', \'c\']" and "list( (1, 2, 3) )" returns "[1, 2,\n 3]". If no argument is given, the constructor creates a new empty\n list, "[]".\n\n Many other operations also produce lists, including the "sorted()"\n built-in.\n\n Lists implement all of the *common* and *mutable* sequence\n operations. Lists also provide the following additional method:\n\n sort(*, key=None, reverse=None)\n\n This method sorts the list in place, using only "<" comparisons\n between items. Exceptions are not suppressed - if any comparison\n operations fail, the entire sort operation will fail (and the\n list will likely be left in a partially modified state).\n\n "sort()" accepts two arguments that can only be passed by\n keyword (*keyword-only arguments*):\n\n *key* specifies a function of one argument that is used to\n extract a comparison key from each list element (for example,\n "key=str.lower"). The key corresponding to each item in the list\n is calculated once and then used for the entire sorting process.\n The default value of "None" means that list items are sorted\n directly without calculating a separate key value.\n\n The "functools.cmp_to_key()" utility is available to convert a\n 2.x style *cmp* function to a *key* function.\n\n *reverse* is a boolean value. If set to "True", then the list\n elements are sorted as if each comparison were reversed.\n\n This method modifies the sequence in place for economy of space\n when sorting a large sequence. To remind users that it operates\n by side effect, it does not return the sorted sequence (use\n "sorted()" to explicitly request a new sorted list instance).\n\n The "sort()" method is guaranteed to be stable. A sort is\n stable if it guarantees not to change the relative order of\n elements that compare equal --- this is helpful for sorting in\n multiple passes (for example, sort by department, then by salary\n grade).\n\n **CPython implementation detail:** While a list is being sorted,\n the effect of attempting to mutate, or even inspect, the list is\n undefined. The C implementation of Python makes the list appear\n empty for the duration, and raises "ValueError" if it can detect\n that the list has been mutated during a sort.\n\n\nTuples\n======\n\nTuples are immutable sequences, typically used to store collections of\nheterogeneous data (such as the 2-tuples produced by the "enumerate()"\nbuilt-in). Tuples are also used for cases where an immutable sequence\nof homogeneous data is needed (such as allowing storage in a "set" or\n"dict" instance).\n\nclass class tuple([iterable])\n\n Tuples may be constructed in a number of ways:\n\n * Using a pair of parentheses to denote the empty tuple: "()"\n\n * Using a trailing comma for a singleton tuple: "a," or "(a,)"\n\n * Separating items with commas: "a, b, c" or "(a, b, c)"\n\n * Using the "tuple()" built-in: "tuple()" or "tuple(iterable)"\n\n The constructor builds a tuple whose items are the same and in the\n same order as *iterable*\'s items. *iterable* may be either a\n sequence, a container that supports iteration, or an iterator\n object. If *iterable* is already a tuple, it is returned\n unchanged. For example, "tuple(\'abc\')" returns "(\'a\', \'b\', \'c\')"\n and "tuple( [1, 2, 3] )" returns "(1, 2, 3)". If no argument is\n given, the constructor creates a new empty tuple, "()".\n\n Note that it is actually the comma which makes a tuple, not the\n parentheses. The parentheses are optional, except in the empty\n tuple case, or when they are needed to avoid syntactic ambiguity.\n For example, "f(a, b, c)" is a function call with three arguments,\n while "f((a, b, c))" is a function call with a 3-tuple as the sole\n argument.\n\n Tuples implement all of the *common* sequence operations.\n\nFor heterogeneous collections of data where access by name is clearer\nthan access by index, "collections.namedtuple()" may be a more\nappropriate choice than a simple tuple object.\n\n\nRanges\n======\n\nThe "range" type represents an immutable sequence of numbers and is\ncommonly used for looping a specific number of times in "for" loops.\n\nclass class range(stop)\nclass class range(start, stop[, step])\n\n The arguments to the range constructor must be integers (either\n built-in "int" or any object that implements the "__index__"\n special method). If the *step* argument is omitted, it defaults to\n "1". If the *start* argument is omitted, it defaults to "0". If\n *step* is zero, "ValueError" is raised.\n\n For a positive *step*, the contents of a range "r" are determined\n by the formula "r[i] = start + step*i" where "i >= 0" and "r[i] <\n stop".\n\n For a negative *step*, the contents of the range are still\n determined by the formula "r[i] = start + step*i", but the\n constraints are "i >= 0" and "r[i] > stop".\n\n A range object will be empty if "r[0]" does not meet the value\n constraint. Ranges do support negative indices, but these are\n interpreted as indexing from the end of the sequence determined by\n the positive indices.\n\n Ranges containing absolute values larger than "sys.maxsize" are\n permitted but some features (such as "len()") may raise\n "OverflowError".\n\n Range examples:\n\n >>> list(range(10))\n [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n >>> list(range(1, 11))\n [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n >>> list(range(0, 30, 5))\n [0, 5, 10, 15, 20, 25]\n >>> list(range(0, 10, 3))\n [0, 3, 6, 9]\n >>> list(range(0, -10, -1))\n [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]\n >>> list(range(0))\n []\n >>> list(range(1, 0))\n []\n\n Ranges implement all of the *common* sequence operations except\n concatenation and repetition (due to the fact that range objects\n can only represent sequences that follow a strict pattern and\n repetition and concatenation will usually violate that pattern).\n\n start\n\n The value of the *start* parameter (or "0" if the parameter was\n not supplied)\n\n stop\n\n The value of the *stop* parameter\n\n step\n\n The value of the *step* parameter (or "1" if the parameter was\n not supplied)\n\nThe advantage of the "range" type over a regular "list" or "tuple" is\nthat a "range" object will always take the same (small) amount of\nmemory, no matter the size of the range it represents (as it only\nstores the "start", "stop" and "step" values, calculating individual\nitems and subranges as needed).\n\nRange objects implement the "collections.abc.Sequence" ABC, and\nprovide features such as containment tests, element index lookup,\nslicing and support for negative indices (see *Sequence Types ---\nlist, tuple, range*):\n\n>>> r = range(0, 20, 2)\n>>> r\nrange(0, 20, 2)\n>>> 11 in r\nFalse\n>>> 10 in r\nTrue\n>>> r.index(10)\n5\n>>> r[5]\n10\n>>> r[:5]\nrange(0, 10, 2)\n>>> r[-1]\n18\n\nTesting range objects for equality with "==" and "!=" compares them as\nsequences. That is, two range objects are considered equal if they\nrepresent the same sequence of values. (Note that two range objects\nthat compare equal might have different "start", "stop" and "step"\nattributes, for example "range(0) == range(2, 1, 3)" or "range(0, 3,\n2) == range(0, 4, 2)".)\n\nChanged in version 3.2: Implement the Sequence ABC. Support slicing\nand negative indices. Test "int" objects for membership in constant\ntime instead of iterating through all items.\n\nChanged in version 3.3: Define \'==\' and \'!=\' to compare range objects\nbased on the sequence of values they define (instead of comparing\nbased on object identity).\n\nNew in version 3.3: The "start", "stop" and "step" attributes.\n',
'typesseq-mutable': u'\nMutable Sequence Types\n**********************\n\nThe operations in the following table are defined on mutable sequence\ntypes. The "collections.abc.MutableSequence" ABC is provided to make\nit easier to correctly implement these operations on custom sequence\ntypes.\n\nIn the table *s* is an instance of a mutable sequence type, *t* is any\niterable object and *x* is an arbitrary object that meets any type and\nvalue restrictions imposed by *s* (for example, "bytearray" only\naccepts integers that meet the value restriction "0 <= x <= 255").\n\n+--------------------------------+----------------------------------+-----------------------+\n| Operation | Result | Notes |\n+================================+==================================+=======================+\n| "s[i] = x" | item *i* of *s* is replaced by | |\n| | *x* | |\n+--------------------------------+----------------------------------+-----------------------+\n| "s[i:j] = t" | slice of *s* from *i* to *j* is | |\n| | replaced by the contents of the | |\n| | iterable *t* | |\n+--------------------------------+----------------------------------+-----------------------+\n| "del s[i:j]" | same as "s[i:j] = []" | |\n+--------------------------------+----------------------------------+-----------------------+\n| "s[i:j:k] = t" | the elements of "s[i:j:k]" are | (1) |\n| | replaced by those of *t* | |\n+--------------------------------+----------------------------------+-----------------------+\n| "del s[i:j:k]" | removes the elements of | |\n| | "s[i:j:k]" from the list | |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.append(x)" | appends *x* to the end of the | |\n| | sequence (same as | |\n| | "s[len(s):len(s)] = [x]") | |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.clear()" | removes all items from "s" (same | (5) |\n| | as "del s[:]") | |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.copy()" | creates a shallow copy of "s" | (5) |\n| | (same as "s[:]") | |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.extend(t)" or "s += t" | extends *s* with the contents of | |\n| | *t* (for the most part the same | |\n| | as "s[len(s):len(s)] = t") | |\n+--------------------------------+----------------------------------+-----------------------+\n| "s *= n" | updates *s* with its contents | (6) |\n| | repeated *n* times | |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.insert(i, x)" | inserts *x* into *s* at the | |\n| | index given by *i* (same as | |\n| | "s[i:i] = [x]") | |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.pop([i])" | retrieves the item at *i* and | (2) |\n| | also removes it from *s* | |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.remove(x)" | remove the first item from *s* | (3) |\n| | where "s[i] == x" | |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.reverse()" | reverses the items of *s* in | (4) |\n| | place | |\n+--------------------------------+----------------------------------+-----------------------+\n\nNotes:\n\n1. *t* must have the same length as the slice it is replacing.\n\n2. The optional argument *i* defaults to "-1", so that by default\n the last item is removed and returned.\n\n3. "remove" raises "ValueError" when *x* is not found in *s*.\n\n4. The "reverse()" method modifies the sequence in place for\n economy of space when reversing a large sequence. To remind users\n that it operates by side effect, it does not return the reversed\n sequence.\n\n5. "clear()" and "copy()" are included for consistency with the\n interfaces of mutable containers that don\'t support slicing\n operations (such as "dict" and "set")\n\n New in version 3.3: "clear()" and "copy()" methods.\n\n6. The value *n* is an integer, or an object implementing\n "__index__()". Zero and negative values of *n* clear the sequence.\n Items in the sequence are not copied; they are referenced multiple\n times, as explained for "s * n" under *Common Sequence Operations*.\n',
'unary': u'\nUnary arithmetic and bitwise operations\n***************************************\n\nAll unary arithmetic and bitwise operations have the same priority:\n\n u_expr ::= power | "-" u_expr | "+" u_expr | "~" u_expr\n\nThe unary "-" (minus) operator yields the negation of its numeric\nargument.\n\nThe unary "+" (plus) operator yields its numeric argument unchanged.\n\nThe unary "~" (invert) operator yields the bitwise inversion of its\ninteger argument. The bitwise inversion of "x" is defined as\n"-(x+1)". It only applies to integral numbers.\n\nIn all three cases, if the argument does not have the proper type, a\n"TypeError" exception is raised.\n',
'while': u'\nThe "while" statement\n*********************\n\nThe "while" statement is used for repeated execution as long as an\nexpression is true:\n\n while_stmt ::= "while" expression ":" suite\n ["else" ":" suite]\n\nThis repeatedly tests the expression and, if it is true, executes the\nfirst suite; if the expression is false (which may be the first time\nit is tested) the suite of the "else" clause, if present, is executed\nand the loop terminates.\n\nA "break" statement executed in the first suite terminates the loop\nwithout executing the "else" clause\'s suite. A "continue" statement\nexecuted in the first suite skips the rest of the suite and goes back\nto testing the expression.\n',
- 'with': u'\nThe "with" statement\n********************\n\nThe "with" statement is used to wrap the execution of a block with\nmethods defined by a context manager (see section *With Statement\nContext Managers*). This allows common "try"..."except"..."finally"\nusage patterns to be encapsulated for convenient reuse.\n\n with_stmt ::= "with" with_item ("," with_item)* ":" suite\n with_item ::= expression ["as" target]\n\nThe execution of the "with" statement with one "item" proceeds as\nfollows:\n\n1. The context expression (the expression given in the "with_item")\n is evaluated to obtain a context manager.\n\n2. The context manager\'s "__exit__()" is loaded for later use.\n\n3. The context manager\'s "__enter__()" method is invoked.\n\n4. If a target was included in the "with" statement, the return\n value from "__enter__()" is assigned to it.\n\n Note: The "with" statement guarantees that if the "__enter__()"\n method returns without an error, then "__exit__()" will always be\n called. Thus, if an error occurs during the assignment to the\n target list, it will be treated the same as an error occurring\n within the suite would be. See step 6 below.\n\n5. The suite is executed.\n\n6. The context manager\'s "__exit__()" method is invoked. If an\n exception caused the suite to be exited, its type, value, and\n traceback are passed as arguments to "__exit__()". Otherwise, three\n "None" arguments are supplied.\n\n If the suite was exited due to an exception, and the return value\n from the "__exit__()" method was false, the exception is reraised.\n If the return value was true, the exception is suppressed, and\n execution continues with the statement following the "with"\n statement.\n\n If the suite was exited for any reason other than an exception, the\n return value from "__exit__()" is ignored, and execution proceeds\n at the normal location for the kind of exit that was taken.\n\nWith more than one item, the context managers are processed as if\nmultiple "with" statements were nested:\n\n with A() as a, B() as b:\n suite\n\nis equivalent to\n\n with A() as a:\n with B() as b:\n suite\n\nChanged in version 3.1: Support for multiple context expressions.\n\nSee also: **PEP 0343** - The "with" statement\n\n The specification, background, and examples for the Python "with"\n statement.\n',
+ 'with': u'\nThe "with" statement\n********************\n\nThe "with" statement is used to wrap the execution of a block with\nmethods defined by a context manager (see section *With Statement\nContext Managers*). This allows common "try"..."except"..."finally"\nusage patterns to be encapsulated for convenient reuse.\n\n with_stmt ::= "with" with_item ("," with_item)* ":" suite\n with_item ::= expression ["as" target]\n\nThe execution of the "with" statement with one "item" proceeds as\nfollows:\n\n1. The context expression (the expression given in the "with_item")\n is evaluated to obtain a context manager.\n\n2. The context manager\'s "__exit__()" is loaded for later use.\n\n3. The context manager\'s "__enter__()" method is invoked.\n\n4. If a target was included in the "with" statement, the return\n value from "__enter__()" is assigned to it.\n\n Note: The "with" statement guarantees that if the "__enter__()"\n method returns without an error, then "__exit__()" will always be\n called. Thus, if an error occurs during the assignment to the\n target list, it will be treated the same as an error occurring\n within the suite would be. See step 6 below.\n\n5. The suite is executed.\n\n6. The context manager\'s "__exit__()" method is invoked. If an\n exception caused the suite to be exited, its type, value, and\n traceback are passed as arguments to "__exit__()". Otherwise, three\n "None" arguments are supplied.\n\n If the suite was exited due to an exception, and the return value\n from the "__exit__()" method was false, the exception is reraised.\n If the return value was true, the exception is suppressed, and\n execution continues with the statement following the "with"\n statement.\n\n If the suite was exited for any reason other than an exception, the\n return value from "__exit__()" is ignored, and execution proceeds\n at the normal location for the kind of exit that was taken.\n\nWith more than one item, the context managers are processed as if\nmultiple "with" statements were nested:\n\n with A() as a, B() as b:\n suite\n\nis equivalent to\n\n with A() as a:\n with B() as b:\n suite\n\nChanged in version 3.1: Support for multiple context expressions.\n\nSee also: **PEP 343** - The "with" statement\n\n The specification, background, and examples for the Python "with"\n statement.\n',
'yield': u'\nThe "yield" statement\n*********************\n\n yield_stmt ::= yield_expression\n\nA "yield" statement is semantically equivalent to a *yield\nexpression*. The yield statement can be used to omit the parentheses\nthat would otherwise be required in the equivalent yield expression\nstatement. For example, the yield statements\n\n yield <expr>\n yield from <expr>\n\nare equivalent to the yield expression statements\n\n (yield <expr>)\n (yield from <expr>)\n\nYield expressions and statements are only used when defining a\n*generator* function, and are only used in the body of the generator\nfunction. Using yield in a function definition is sufficient to cause\nthat definition to create a generator function instead of a normal\nfunction.\n\nFor full details of "yield" semantics, refer to the *Yield\nexpressions* section.\n'}
while r >= n:
r = getrandbits(k)
return r
- # There's an overriden random() method but no new getrandbits() method,
+ # There's an overridden random() method but no new getrandbits() method,
# so we can only use random() from here.
if n >= maxsize:
_warn("Underlying random() generator does not supply \n"
wrapper.__module__ = getattr(user_function, '__module__')
wrapper.__doc__ = getattr(user_function, '__doc__')
wrapper.__name__ = getattr(user_function, '__name__')
+ wrapper.__qualname__ = getattr(user_function, '__qualname__')
wrapper.__annotations__ = getattr(user_function, '__annotations__', {})
return wrapper
if not text.strip():
if state == 0:
- return '\t'
+ if _readline_available:
+ readline.insert_text('\t')
+ readline.redisplay()
+ return ''
+ else:
+ return '\t'
else:
return None
"""
import keyword
matches = []
+ seen = {"__builtins__"}
n = len(text)
for word in keyword.kwlist:
if word[:n] == text:
+ seen.add(word)
matches.append(word)
- for nspace in [builtins.__dict__, self.namespace]:
+ for nspace in [self.namespace, builtins.__dict__]:
for word, val in nspace.items():
- if word[:n] == text and word != "__builtins__":
+ if word[:n] == text and word not in seen:
+ seen.add(word)
matches.append(self._callable_postfix(val, word))
return matches
try:
import readline
except ImportError:
- pass
+ _readline_available = False
else:
readline.set_completer(Completer().complete)
# Release references early at shutdown (the readline module's
# contents are quasi-immortal, and the completer function holds a
# reference to globals).
atexit.register(lambda: readline.set_completer(None))
+ _readline_available = True
return mod_globals.copy()
# Helper to get the loader, code and filename for a module
-def _get_module_details(mod_name):
+def _get_module_details(mod_name, error=ImportError):
+ if mod_name.startswith("."):
+ raise error("Relative module names not supported")
+ pkg_name, _, _ = mod_name.rpartition(".")
+ if pkg_name:
+ # Try importing the parent to avoid catching initialization errors
+ try:
+ __import__(pkg_name)
+ except ImportError as e:
+ # If the parent or higher ancestor package is missing, let the
+ # error be raised by find_spec() below and then be caught. But do
+ # not allow other errors to be caught.
+ if e.name is None or (e.name != pkg_name and
+ not pkg_name.startswith(e.name + ".")):
+ raise
+
try:
spec = importlib.util.find_spec(mod_name)
except (ImportError, AttributeError, TypeError, ValueError) as ex:
# importlib, where the latter raises other errors for cases where
# pkgutil previously raised ImportError
msg = "Error while finding spec for {!r} ({}: {})"
- raise ImportError(msg.format(mod_name, type(ex), ex)) from ex
+ raise error(msg.format(mod_name, type(ex).__name__, ex)) from ex
if spec is None:
- raise ImportError("No module named %s" % mod_name)
+ raise error("No module named %s" % mod_name)
if spec.submodule_search_locations is not None:
if mod_name == "__main__" or mod_name.endswith(".__main__"):
- raise ImportError("Cannot use package as __main__ module")
+ raise error("Cannot use package as __main__ module")
try:
pkg_main_name = mod_name + ".__main__"
- return _get_module_details(pkg_main_name)
- except ImportError as e:
- raise ImportError(("%s; %r is a package and cannot " +
+ return _get_module_details(pkg_main_name, error)
+ except error as e:
+ if mod_name not in sys.modules:
+ raise # No module loaded; being a package is irrelevant
+ raise error(("%s; %r is a package and cannot " +
"be directly executed") %(e, mod_name))
loader = spec.loader
if loader is None:
- raise ImportError("%r is a namespace package and cannot be executed"
+ raise error("%r is a namespace package and cannot be executed"
% mod_name)
- code = loader.get_code(mod_name)
+ try:
+ code = loader.get_code(mod_name)
+ except ImportError as e:
+ raise error(format(e)) from e
if code is None:
- raise ImportError("No code object available for %s" % mod_name)
+ raise error("No code object available for %s" % mod_name)
return mod_name, spec, code
+class _Error(Exception):
+ """Error that _run_module_as_main() should report without a traceback"""
+
# XXX ncoghlan: Should this be documented and made public?
# (Current thoughts: don't repeat the mistake that lead to its
# creation when run_module() no longer met the needs of
"""
try:
if alter_argv or mod_name != "__main__": # i.e. -m switch
- mod_name, mod_spec, code = _get_module_details(mod_name)
+ mod_name, mod_spec, code = _get_module_details(mod_name, _Error)
else: # i.e. directory or zipfile execution
- mod_name, mod_spec, code = _get_main_module_details()
- except ImportError as exc:
- # Try to provide a good error message
- # for directories, zip files and the -m switch
- if alter_argv:
- # For -m switch, just display the exception
- info = str(exc)
- else:
- # For directories/zipfiles, let the user
- # know what the code was looking for
- info = "can't find '__main__' module in %r" % sys.argv[0]
- msg = "%s: %s" % (sys.executable, info)
+ mod_name, mod_spec, code = _get_main_module_details(_Error)
+ except _Error as exc:
+ msg = "%s: %s" % (sys.executable, exc)
sys.exit(msg)
main_globals = sys.modules["__main__"].__dict__
if alter_argv:
# Leave the sys module alone
return _run_code(code, {}, init_globals, run_name, mod_spec)
-def _get_main_module_details():
+def _get_main_module_details(error=ImportError):
# Helper that gives a nicer error message when attempting to
# execute a zipfile or directory by invoking __main__.py
# Also moves the standard __main__ out of the way so that the
return _get_module_details(main_name)
except ImportError as exc:
if main_name in str(exc):
- raise ImportError("can't find %r module in %r" %
+ raise error("can't find %r module in %r" %
(main_name, sys.path[0])) from exc
raise
finally:
SelectorKey = namedtuple('SelectorKey', ['fileobj', 'fd', 'events', 'data'])
-"""Object used to associate a file object to its backing file descriptor,
-selected event mask and attached data."""
+SelectorKey.__doc__ = """SelectorKey(fileobj, fd, events, data)
+
+ Object used to associate a file object to its backing
+ file descriptor, selected event mask, and attached data.
+"""
+if sys.version_info >= (3, 5):
+ SelectorKey.fileobj.__doc__ = 'File object registered.'
+ SelectorKey.fd.__doc__ = 'Underlying file descriptor.'
+ SelectorKey.events.__doc__ = 'Events that must be waited for on this file object.'
+ SelectorKey.data.__doc__ = ('''Optional opaque data associated to this file object.
+ For example, this could be used to store a per-client session ID.''')
class _SelectorMapping(Mapping):
"""Mapping of file objects to selector keys."""
if columns <= 0 or lines <= 0:
try:
size = os.get_terminal_size(sys.__stdout__.fileno())
- except (NameError, OSError):
+ except (AttributeError, ValueError, OSError):
+ # stdout is None, closed, detached, or not a terminal, or
+ # os.get_terminal_size() is unsupported
size = os.terminal_size(fallback)
if columns <= 0:
columns = size.columns
omitted because it is not mentioned in either path configuration file.
The readline module is also automatically configured to enable
-completion for systems that support it. This can be overriden in
+completion for systems that support it. This can be overridden in
sitecustomize, usercustomize or PYTHONSTARTUP.
After these operations, an attempt is made to import a module
If the readline module can be imported, the hook will set the Tab key
as completion key and register ~/.python_history as history file.
- This can be overriden in the sitecustomize or usercustomize module,
+ This can be overridden in the sitecustomize or usercustomize module,
or in a PYTHONSTARTUP file.
"""
def register_readline():
self.ehlo_resp = None
self.esmtp_features = {}
self.does_esmtp = 0
+ else:
+ # RFC 3207:
+ # 501 Syntax error (no parameters allowed)
+ # 454 TLS not available due to temporary reason
+ raise SMTPResponseException(resp, reply)
return (resp, reply)
def sendmail(self, from_addr, to_addrs, msg, mail_options=[],
encoding=None, errors=None, newline=None):
"""makefile(...) -> an I/O stream connected to the socket
- The arguments are as for io.open() after the filename,
- except the only mode characters supported are 'r', 'w' and 'b'.
- The semantics are similar too. (XXX refactor to share code?)
+ The arguments are as for io.open() after the filename, except the only
+ supported mode values are 'r' (default), 'w' and 'b'.
"""
+ # XXX refactor to share code?
if not set(mode) <= {"r", "w", "b"}:
raise ValueError("invalid mode %r (only r, w, b allowed)" % (mode,))
writing = "w" in mode
global default timeout setting returned by :func:`getdefaulttimeout`
is used. If *source_address* is set it must be a tuple of (host, port)
for the socket to bind as a source address before making the connection.
- An host of '' or port 0 tells the OS to use the default.
+ A host of '' or port 0 tells the OS to use the default.
"""
host, port = address
# Author of the BaseServer patch: Luke Kenneth Casson Leighton
-# XXX Warning!
-# There is a test suite for this module, but it cannot be run by the
-# standard regression test.
-# To run it manually, run Lib/test/test_socketserver.py.
-
__version__ = "0.4"
except:
self.handle_error(request, client_address)
self.shutdown_request(request)
+ else:
+ self.shutdown_request(request)
def handle_timeout(self):
"""Called if no new request arrives within self.timeout.
client address as self.client_address, and the server (in case it
needs access to per-server information) as self.server. Since a
separate instance is created for each request, the handle() method
- can define arbitrary other instance variariables.
+ can define other arbitrary instance variables.
"""
try:
self.wfile.flush()
except socket.error:
- # An final socket error may have occurred here, such as
+ # A final socket error may have occurred here, such as
# the local error ECONNABORTED.
pass
self.wfile.close()
class DatagramRequestHandler(BaseRequestHandler):
- # XXX Regrettably, I cannot get this working on Linux;
- # s.recvfrom() doesn't return a meaningful client address.
-
"""Define self.rfile and self.wfile for datagram sockets."""
def setup(self):
def CheckStatementFinalizationOnCloseDb(self):
# pysqlite versions <= 2.3.3 only finalized statements in the statement
# cache when closing the database. statements that were still
- # referenced in cursors weren't closed an could provoke "
+ # referenced in cursors weren't closed and could provoke "
# "OperationalError: Unable to close due to unfinalised statements".
con = sqlite.connect(":memory:")
cursors = []
def func_islonglong(v):
return isinstance(v, int) and v >= 1<<31
+def func(*args):
+ return len(args)
+
class AggrNoStep:
def __init__(self):
pass
def finalize(self):
return self.val
+class AggrCheckTypes:
+ def __init__(self):
+ self.val = 0
+
+ def step(self, whichType, *vals):
+ theType = {"str": str, "int": int, "float": float, "None": type(None),
+ "blob": bytes}
+ for val in vals:
+ self.val += int(theType[whichType] is type(val))
+
+ def finalize(self):
+ return self.val
+
class AggrSum:
def __init__(self):
self.val = 0.0
self.con.create_function("isnone", 1, func_isnone)
self.con.create_function("isblob", 1, func_isblob)
self.con.create_function("islonglong", 1, func_islonglong)
+ self.con.create_function("spam", -1, func)
def tearDown(self):
self.con.close()
val = cur.fetchone()[0]
self.assertEqual(val, 1)
+ def CheckAnyArguments(self):
+ cur = self.con.cursor()
+ cur.execute("select spam(?, ?)", (1, 2))
+ val = cur.fetchone()[0]
+ self.assertEqual(val, 2)
+
+
class AggregateTests(unittest.TestCase):
def setUp(self):
self.con = sqlite.connect(":memory:")
self.con.create_aggregate("excStep", 1, AggrExceptionInStep)
self.con.create_aggregate("excFinalize", 1, AggrExceptionInFinalize)
self.con.create_aggregate("checkType", 2, AggrCheckType)
+ self.con.create_aggregate("checkTypes", -1, AggrCheckTypes)
self.con.create_aggregate("mysum", 1, AggrSum)
def tearDown(self):
val = cur.fetchone()[0]
self.assertEqual(val, 1)
+ def CheckAggrCheckParamsInt(self):
+ cur = self.con.cursor()
+ cur.execute("select checkTypes('int', ?, ?)", (42, 24))
+ val = cur.fetchone()[0]
+ self.assertEqual(val, 2)
+
def CheckAggrCheckParamFloat(self):
cur = self.con.cursor()
cur.execute("select checkType('float', ?)", (3.14,))
assert source.next == ")"
raise source.error("unbalanced parenthesis")
- if flags & SRE_FLAG_DEBUG:
- p.dump()
-
if not (flags & SRE_FLAG_VERBOSE) and p.pattern.flags & SRE_FLAG_VERBOSE:
# the VERBOSE flag was switched on inside the pattern. to be
# on the safe side, we'll parse the whole thing again...
return parse(str, p.pattern.flags)
+ if flags & SRE_FLAG_DEBUG:
+ p.dump()
+
return p
def parse_template(source, pattern):
from socket import SOL_SOCKET, SO_TYPE
import base64 # for DER-to-PEM translation
import errno
+import warnings
socket_error = OSError # keep that public name in module namespace
def _load_windows_store_certs(self, storename, purpose):
certs = bytearray()
- for cert, encoding, trust in enum_certificates(storename):
- # CA certs are never PKCS#7 encoded
- if encoding == "x509_asn":
- if trust is True or purpose.oid in trust:
- certs.extend(cert)
- self.load_verify_locations(cadata=certs)
+ try:
+ for cert, encoding, trust in enum_certificates(storename):
+ # CA certs are never PKCS#7 encoded
+ if encoding == "x509_asn":
+ if trust is True or purpose.oid in trust:
+ certs.extend(cert)
+ except PermissionError:
+ warnings.warn("unable to enumerate Windows certificate store")
+ if certs:
+ self.load_verify_locations(cadata=certs)
return certs
def load_default_certs(self, purpose=Purpose.SERVER_AUTH):
server hostame is set."""
return self._sslobj.server_hostname
- def read(self, len=0, buffer=None):
+ def read(self, len=1024, buffer=None):
"""Read up to 'len' bytes from the SSL object and return them.
If 'buffer' is provided, read into this buffer and return the number of
if buffer is not None:
v = self._sslobj.read(len, buffer)
else:
- v = self._sslobj.read(len or 1024)
+ v = self._sslobj.read(len)
return v
def write(self, data):
# EAGAIN.
self.getpeername()
- def read(self, len=0, buffer=None):
+ def read(self, len=1024, buffer=None):
"""Read up to LEN bytes and return them.
Return zero-length string on EOF."""
from fractions import Fraction
from decimal import Decimal
+from itertools import groupby
+
# === Exceptions ===
# === Private utilities ===
def _sum(data, start=0):
- """_sum(data [, start]) -> value
+ """_sum(data [, start]) -> (type, sum, count)
+
+ Return a high-precision sum of the given numeric data as a fraction,
+ together with the type to be converted to and the count of items.
- Return a high-precision sum of the given numeric data. If optional
- argument ``start`` is given, it is added to the total. If ``data`` is
- empty, ``start`` (defaulting to 0) is returned.
+ If optional argument ``start`` is given, it is added to the total.
+ If ``data`` is empty, ``start`` (defaulting to 0) is returned.
Examples
--------
>>> _sum([3, 2.25, 4.5, -0.5, 1.0], 0.75)
- 11.0
+ (<class 'float'>, Fraction(11, 1), 5)
Some sources of round-off error will be avoided:
>>> _sum([1e50, 1, -1e50] * 1000) # Built-in sum returns zero.
- 1000.0
+ (<class 'float'>, Fraction(1000, 1), 3000)
Fractions and Decimals are also supported:
>>> from fractions import Fraction as F
>>> _sum([F(2, 3), F(7, 5), F(1, 4), F(5, 6)])
- Fraction(63, 20)
+ (<class 'fractions.Fraction'>, Fraction(63, 20), 4)
>>> from decimal import Decimal as D
>>> data = [D("0.1375"), D("0.2108"), D("0.3061"), D("0.0419")]
>>> _sum(data)
- Decimal('0.6963')
+ (<class 'decimal.Decimal'>, Fraction(6963, 10000), 4)
Mixed types are currently treated as an error, except that int is
allowed.
"""
- # We fail as soon as we reach a value that is not an int or the type of
- # the first value which is not an int. E.g. _sum([int, int, float, int])
- # is okay, but sum([int, int, float, Fraction]) is not.
- allowed_types = {int, type(start)}
+ count = 0
n, d = _exact_ratio(start)
- partials = {d: n} # map {denominator: sum of numerators}
- # Micro-optimizations.
- exact_ratio = _exact_ratio
+ partials = {d: n}
partials_get = partials.get
- # Add numerators for each denominator.
- for x in data:
- _check_type(type(x), allowed_types)
- n, d = exact_ratio(x)
- partials[d] = partials_get(d, 0) + n
- # Find the expected result type. If allowed_types has only one item, it
- # will be int; if it has two, use the one which isn't int.
- assert len(allowed_types) in (1, 2)
- if len(allowed_types) == 1:
- assert allowed_types.pop() is int
- T = int
- else:
- T = (allowed_types - {int}).pop()
+ T = _coerce(int, type(start))
+ for typ, values in groupby(data, type):
+ T = _coerce(T, typ) # or raise TypeError
+ for n,d in map(_exact_ratio, values):
+ count += 1
+ partials[d] = partials_get(d, 0) + n
if None in partials:
- assert issubclass(T, (float, Decimal))
- assert not math.isfinite(partials[None])
- return T(partials[None])
- total = Fraction()
- for d, n in sorted(partials.items()):
- total += Fraction(n, d)
- if issubclass(T, int):
- assert total.denominator == 1
- return T(total.numerator)
- if issubclass(T, Decimal):
- return T(total.numerator)/total.denominator
- return T(total)
-
-
-def _check_type(T, allowed):
- if T not in allowed:
- if len(allowed) == 1:
- allowed.add(T)
- else:
- types = ', '.join([t.__name__ for t in allowed] + [T.__name__])
- raise TypeError("unsupported mixed types: %s" % types)
+ # The sum will be a NAN or INF. We can ignore all the finite
+ # partials, and just look at this special one.
+ total = partials[None]
+ assert not _isfinite(total)
+ else:
+ # Sum all the partial sums using builtin sum.
+ # FIXME is this faster if we sum them in order of the denominator?
+ total = sum(Fraction(n, d) for d, n in sorted(partials.items()))
+ return (T, total, count)
+
+
+def _isfinite(x):
+ try:
+ return x.is_finite() # Likely a Decimal.
+ except AttributeError:
+ return math.isfinite(x) # Coerces to float first.
+
+
+def _coerce(T, S):
+ """Coerce types T and S to a common type, or raise TypeError.
+
+ Coercion rules are currently an implementation detail. See the CoerceTest
+ test class in test_statistics for details.
+ """
+ # See http://bugs.python.org/issue24068.
+ assert T is not bool, "initial type T is bool"
+ # If the types are the same, no need to coerce anything. Put this
+ # first, so that the usual case (no coercion needed) happens as soon
+ # as possible.
+ if T is S: return T
+ # Mixed int & other coerce to the other type.
+ if S is int or S is bool: return T
+ if T is int: return S
+ # If one is a (strict) subclass of the other, coerce to the subclass.
+ if issubclass(S, T): return S
+ if issubclass(T, S): return T
+ # Ints coerce to the other type.
+ if issubclass(T, int): return S
+ if issubclass(S, int): return T
+ # Mixed fraction & float coerces to float (or float subclass).
+ if issubclass(T, Fraction) and issubclass(S, float):
+ return S
+ if issubclass(T, float) and issubclass(S, Fraction):
+ return T
+ # Any other combination is disallowed.
+ msg = "don't know how to coerce %s and %s"
+ raise TypeError(msg % (T.__name__, S.__name__))
def _exact_ratio(x):
- """Convert Real number x exactly to (numerator, denominator) pair.
+ """Return Real number x to exact (numerator, denominator) pair.
>>> _exact_ratio(0.25)
(1, 4)
x is expected to be an int, Fraction, Decimal or float.
"""
try:
+ # Optimise the common case of floats. We expect that the most often
+ # used numeric type will be builtin floats, so try to make this as
+ # fast as possible.
+ if type(x) is float:
+ return x.as_integer_ratio()
try:
- # int, Fraction
+ # x may be an int, Fraction, or Integral ABC.
return (x.numerator, x.denominator)
except AttributeError:
- # float
try:
+ # x may be a float subclass.
return x.as_integer_ratio()
except AttributeError:
- # Decimal
try:
+ # x may be a Decimal.
return _decimal_to_ratio(x)
except AttributeError:
- msg = "can't convert type '{}' to numerator/denominator"
- raise TypeError(msg.format(type(x).__name__)) from None
+ # Just give up?
+ pass
except (OverflowError, ValueError):
- # INF or NAN
- if __debug__:
- # Decimal signalling NANs cannot be converted to float :-(
- if isinstance(x, Decimal):
- assert not x.is_finite()
- else:
- assert not math.isfinite(x)
+ # float NAN or INF.
+ assert not math.isfinite(x)
return (x, None)
+ msg = "can't convert type '{}' to numerator/denominator"
+ raise TypeError(msg.format(type(x).__name__))
# FIXME This is faster than Fraction.from_decimal, but still too slow.
sign, digits, exp = d.as_tuple()
if exp in ('F', 'n', 'N'): # INF, NAN, sNAN
assert not d.is_finite()
- raise ValueError
+ return (d, None)
num = 0
for digit in digits:
num = num*10 + digit
return (num, den)
+def _convert(value, T):
+ """Convert value to given numeric type T."""
+ if type(value) is T:
+ # This covers the cases where T is Fraction, or where value is
+ # a NAN or INF (Decimal or float).
+ return value
+ if issubclass(T, int) and value.denominator != 1:
+ T = float
+ try:
+ # FIXME: what do we do if this overflows?
+ return T(value)
+ except TypeError:
+ if issubclass(T, Decimal):
+ return T(value.numerator)/T(value.denominator)
+ else:
+ raise
+
+
def _counts(data):
# Generate a table of sorted (value, frequency) pairs.
table = collections.Counter(iter(data)).most_common()
n = len(data)
if n < 1:
raise StatisticsError('mean requires at least one data point')
- return _sum(data)/n
+ T, total, count = _sum(data)
+ assert count == n
+ return _convert(total/n, T)
# FIXME: investigate ways to calculate medians without sorting? Quickselect?
"""
if c is None:
c = mean(data)
- ss = _sum((x-c)**2 for x in data)
+ T, total, count = _sum((x-c)**2 for x in data)
# The following sum should mathematically equal zero, but due to rounding
# error may not.
- ss -= _sum((x-c) for x in data)**2/len(data)
- assert not ss < 0, 'negative sum of square deviations: %f' % ss
- return ss
+ U, total2, count2 = _sum((x-c) for x in data)
+ assert T == U and count == count2
+ total -= total2**2/len(data)
+ assert not total < 0, 'negative sum of square deviations: %f' % total
+ return (T, total)
def variance(data, xbar=None):
n = len(data)
if n < 2:
raise StatisticsError('variance requires at least two data points')
- ss = _ss(data, xbar)
- return ss/(n-1)
+ T, ss = _ss(data, xbar)
+ return _convert(ss/(n-1), T)
def pvariance(data, mu=None):
n = len(data)
if n < 1:
raise StatisticsError('pvariance requires at least one data point')
- ss = _ss(data, mu)
- return ss/n
+ T, ss = _ss(data, mu)
+ return _convert(ss/n, T)
def stdev(data, xbar=None):
"""
+__all__ = ["ascii_letters", "ascii_lowercase", "ascii_uppercase", "capwords",
+ "digits", "hexdigits", "octdigits", "printable", "punctuation",
+ "whitespace", "Formatter", "Template"]
+
import _string
# Some strings for ctype-style character classification
####################################################################
import re as _re
-from collections import ChainMap
+from collections import ChainMap as _ChainMap
class _TemplateMetaclass(type):
pattern = r"""
if not args:
mapping = kws
elif kws:
- mapping = ChainMap(kws, args[0])
+ mapping = _ChainMap(kws, args[0])
else:
mapping = args[0]
# Helper function for .sub()
if not args:
mapping = kws
elif kws:
- mapping = ChainMap(kws, args[0])
+ mapping = _ChainMap(kws, args[0])
else:
mapping = args[0]
# Helper function for .sub()
'verbose': 'v',
'bytes_warning': 'b',
'quiet': 'q',
- 'hash_randomization': 'R',
}
args = []
for flag, opt in flag_opt_map.items():
v = getattr(sys.flags, flag)
if v > 0:
- if flag == 'hash_randomization':
- v = 1 # Handle specification of an exact seed
args.append('-' + opt * v)
for opt in sys.warnoptions:
args.append('-W' + opt)
try:
self.stdin.write(input)
except BrokenPipeError:
- # communicate() must ignore broken pipe error
- pass
+ pass # communicate() must ignore broken pipe errors.
except OSError as e:
if e.errno == errno.EINVAL and self.poll() is not None:
# Issue #19612: On Windows, stdin.write() fails with EINVAL
pass
else:
raise
- self.stdin.close()
+ try:
+ self.stdin.close()
+ except BrokenPipeError:
+ pass # communicate() must ignore broken pipe errors.
+ except OSError as e:
+ if e.errno == errno.EINVAL and self.poll() is not None:
+ pass
+ else:
+ raise
def communicate(self, input=None, timeout=None):
"""Interact with process: Send data to stdin. Read data from
elif stderr == PIPE:
errread, errwrite = os.pipe()
elif stderr == STDOUT:
- errwrite = c2pwrite
+ if c2pwrite != -1:
+ errwrite = c2pwrite
+ else: # child's stdout is not set, use parent's stdout
+ errwrite = sys.__stdout__.fileno()
elif stderr == DEVNULL:
errwrite = self._get_devnull()
elif isinstance(stderr, int):
if self.stdin and not self._communication_started:
# Flush stdio buffer. This might block, if the user has
# been writing to .stdin in an uncontrolled fashion.
- self.stdin.flush()
+ try:
+ self.stdin.flush()
+ except BrokenPipeError:
+ pass # communicate() must ignore BrokenPipeError.
if not input:
- self.stdin.close()
+ try:
+ self.stdin.close()
+ except BrokenPipeError:
+ pass # communicate() must ignore BrokenPipeError.
stdout = None
stderr = None
while len(variables) > 0:
for name in tuple(variables):
value = notdone[name]
- m = _findvar1_rx.search(value) or _findvar2_rx.search(value)
+ m1 = _findvar1_rx.search(value)
+ m2 = _findvar2_rx.search(value)
+ if m1 and m2:
+ m = m1 if m1.start() < m2.start() else m2
+ else:
+ m = m1 if m1 else m2
if m is not None:
n = m.group(1)
found = True
self.fileobj.write(self.buf)
self.buf = b""
if self.comptype == "gz":
- # The native zlib crc is an unsigned 32-bit integer, but
- # the Python wrapper implicitly casts that to a signed C
- # long. So, on a 32-bit box self.crc may "look negative",
- # while the same crc on a 64-bit box may "look positive".
- # To avoid irksome warnings from the `struct` module, force
- # it to look positive on all boxes.
- self.fileobj.write(struct.pack("<L", self.crc & 0xffffffff))
+ self.fileobj.write(struct.pack("<L", self.crc))
self.fileobj.write(struct.pack("<L", self.pos & 0xffffFFFF))
finally:
if not self._extfileobj:
"""
info["magic"] = POSIX_MAGIC
- if len(info["linkname"]) > LENGTH_LINK:
+ if len(info["linkname"].encode(encoding, errors)) > LENGTH_LINK:
raise ValueError("linkname is too long")
- if len(info["name"]) > LENGTH_NAME:
- info["prefix"], info["name"] = self._posix_split_name(info["name"])
+ if len(info["name"].encode(encoding, errors)) > LENGTH_NAME:
+ info["prefix"], info["name"] = self._posix_split_name(info["name"], encoding, errors)
return self._create_header(info, USTAR_FORMAT, encoding, errors)
info["magic"] = GNU_MAGIC
buf = b""
- if len(info["linkname"]) > LENGTH_LINK:
+ if len(info["linkname"].encode(encoding, errors)) > LENGTH_LINK:
buf += self._create_gnu_long_header(info["linkname"], GNUTYPE_LONGLINK, encoding, errors)
- if len(info["name"]) > LENGTH_NAME:
+ if len(info["name"].encode(encoding, errors)) > LENGTH_NAME:
buf += self._create_gnu_long_header(info["name"], GNUTYPE_LONGNAME, encoding, errors)
return buf + self._create_header(info, GNU_FORMAT, encoding, errors)
"""
return cls._create_pax_generic_header(pax_headers, XGLTYPE, "utf-8")
- def _posix_split_name(self, name):
+ def _posix_split_name(self, name, encoding, errors):
"""Split a name longer than 100 chars into a prefix
and a name part.
"""
- prefix = name[:LENGTH_PREFIX + 1]
- while prefix and prefix[-1] != "/":
- prefix = prefix[:-1]
-
- name = name[len(prefix):]
- prefix = prefix[:-1]
-
- if not prefix or len(name) > LENGTH_NAME:
+ components = name.split("/")
+ for i in range(1, len(components)):
+ prefix = "/".join(components[:i])
+ name = "/".join(components[i:])
+ if len(prefix.encode(encoding, errors)) <= LENGTH_PREFIX and \
+ len(name.encode(encoding, errors)) <= LENGTH_NAME:
+ break
+ else:
raise ValueError("name is too long")
+
return prefix, name
@staticmethod
'x' or 'x:' create a tarfile exclusively without compression, raise
an exception if the file is already created
- 'x:gz' create an gzip compressed tarfile, raise an exception
+ 'x:gz' create a gzip compressed tarfile, raise an exception
if the file is already created
- 'x:bz2' create an bzip2 compressed tarfile, raise an exception
+ 'x:bz2' create a bzip2 compressed tarfile, raise an exception
if the file is already created
'x:xz' create an lzma compressed tarfile, raise an exception
if the file is already created
return [tarinfo.name for tarinfo in self.getmembers()]
def gettarinfo(self, name=None, arcname=None, fileobj=None):
- """Create a TarInfo object for either the file `name' or the file
- object `fileobj' (using os.fstat on its file descriptor). You can
- modify some of the TarInfo's attributes before you add it using
- addfile(). If given, `arcname' specifies an alternative name for the
- file in the archive.
+ """Create a TarInfo object from the result of os.stat or equivalent
+ on an existing file. The file is either named by `name', or
+ specified as a file object `fileobj' with a file descriptor. If
+ given, `arcname' specifies an alternative name for the file in the
+ archive, otherwise, the name is taken from the 'name' attribute of
+ 'fileobj', or the 'name' argument. The name should be a text
+ string.
"""
self._check("awx")
# Now, fill the TarInfo object with
# information specific for the file.
tarinfo = self.tarinfo()
- tarinfo.tarfile = self
+ tarinfo.tarfile = self # Not needed
# Use os.stat or os.lstat, depending on platform
# and if symlinks shall be resolved.
def addfile(self, tarinfo, fileobj=None):
"""Add the TarInfo object `tarinfo' to the archive. If `fileobj' is
- given, tarinfo.size bytes are read from it and added to the archive.
- You can create TarInfo objects using gettarinfo().
- On Windows platforms, `fileobj' should always be opened with mode
- 'rb' to avoid irritation about the file size.
+ given, it should be a binary file, and tarinfo.size bytes are read
+ from it and added to the archive. You can create TarInfo objects
+ directly, or by using gettarinfo().
"""
self._check("awx")
for offset, size in tarinfo.sparse:
target.seek(offset)
copyfileobj(source, target, size, ReadError)
+ target.seek(tarinfo.size)
+ target.truncate()
else:
copyfileobj(source, target, tarinfo.size, ReadError)
- target.seek(tarinfo.size)
- target.truncate()
def makeunknown(self, tarinfo, targetpath):
"""Make a file from a TarInfo object with an unknown type
The file is created as mkstemp() would do it.
Returns an object with a file-like interface; the name of the file
- is accessible as file.name. The file will be automatically deleted
- when it is closed unless the 'delete' argument is set to False.
+ is accessible as its 'name' attribute. The file will be automatically
+ deleted when it is closed unless the 'delete' argument is set to False.
"""
prefix, suffix, dir, output_type = _sanitize_params(prefix, suffix, dir)
newline=newline, encoding=encoding)
return _TemporaryFileWrapper(file, name, delete)
- except Exception:
+ except BaseException:
+ _os.unlink(name)
_os.close(fd)
raise
@classmethod
def _test_stderr_flush(cls, testfn):
- sys.stderr = open(testfn, 'w')
+ fd = os.open(testfn, os.O_WRONLY | os.O_CREAT | os.O_EXCL)
+ sys.stderr = open(fd, 'w', closefd=False)
1/0 # MARKER
@classmethod
def _test_sys_exit(cls, reason, testfn):
- sys.stderr = open(testfn, 'w')
+ fd = os.open(testfn, os.O_WRONLY | os.O_CREAT | os.O_EXCL)
+ sys.stderr = open(fd, 'w', closefd=False)
sys.exit(reason)
def test_sys_exit(self):
testfn = test.support.TESTFN
self.addCleanup(test.support.unlink, testfn)
- for reason, code in (([1, 2, 3], 1), ('ignore this', 1)):
+ for reason in (
+ [1, 2, 3],
+ 'ignore this',
+ ):
p = self.Process(target=self._test_sys_exit, args=(reason, testfn))
p.daemon = True
p.start()
p.join(5)
- self.assertEqual(p.exitcode, code)
+ self.assertEqual(p.exitcode, 1)
with open(testfn, 'r') as f:
- self.assertEqual(f.read().rstrip(), str(reason))
+ content = f.read()
+ self.assertEqual(content.rstrip(), str(reason))
+
+ os.unlink(testfn)
for reason in (True, False, 8):
p = self.Process(target=sys.exit, args=(reason,))
expected_values.remove(value)
def test_make_pool(self):
- self.assertRaises(ValueError, multiprocessing.Pool, -1)
- self.assertRaises(ValueError, multiprocessing.Pool, 0)
+ expected_error = (RemoteError if self.TYPE == 'manager'
+ else ValueError)
- p = multiprocessing.Pool(3)
- self.assertEqual(3, len(p._pool))
- p.close()
- p.join()
+ self.assertRaises(expected_error, self.Pool, -1)
+ self.assertRaises(expected_error, self.Pool, 0)
+
+ if self.TYPE != 'manager':
+ p = self.Pool(3)
+ try:
+ self.assertEqual(3, len(p._pool))
+ finally:
+ p.close()
+ p.join()
def test_terminate(self):
result = self.pool.map_async(
self.pool.terminate()
join = TimingWrapper(self.pool.join)
join()
- self.assertLess(join.elapsed, 0.5)
+ # Sanity check the pool didn't wait for all tasks to finish
+ self.assertLess(join.elapsed, 2.0)
def test_empty_iterable(self):
# See Issue 12157
if self.TYPE == 'processes':
L = list(range(10))
expected = [sqr(i) for i in L]
- with multiprocessing.Pool(2) as p:
+ with self.Pool(2) as p:
r = p.map_async(sqr, L)
self.assertEqual(r.get(), expected)
self.assertRaises(ValueError, p.map_async, sqr, L)
connection = multiprocessing.dummy.connection
current_process = staticmethod(multiprocessing.dummy.current_process)
active_children = staticmethod(multiprocessing.dummy.active_children)
- Pool = staticmethod(multiprocessing.Pool)
+ Pool = staticmethod(multiprocessing.dummy.Pool)
Pipe = staticmethod(multiprocessing.dummy.Pipe)
Queue = staticmethod(multiprocessing.dummy.Queue)
JoinableQueue = staticmethod(multiprocessing.dummy.JoinableQueue)
+++ /dev/null
-# Tests that work for both bytes and buffer objects.
-# See PEP 3137.
-
-import struct
-import sys
-
-class MixinBytesBufferCommonTests(object):
- """Tests that work for both bytes and buffer objects.
- See PEP 3137.
- """
-
- def marshal(self, x):
- """Convert x into the appropriate type for these tests."""
- raise RuntimeError('test class must provide a marshal method')
-
- def test_islower(self):
- self.assertFalse(self.marshal(b'').islower())
- self.assertTrue(self.marshal(b'a').islower())
- self.assertFalse(self.marshal(b'A').islower())
- self.assertFalse(self.marshal(b'\n').islower())
- self.assertTrue(self.marshal(b'abc').islower())
- self.assertFalse(self.marshal(b'aBc').islower())
- self.assertTrue(self.marshal(b'abc\n').islower())
- self.assertRaises(TypeError, self.marshal(b'abc').islower, 42)
-
- def test_isupper(self):
- self.assertFalse(self.marshal(b'').isupper())
- self.assertFalse(self.marshal(b'a').isupper())
- self.assertTrue(self.marshal(b'A').isupper())
- self.assertFalse(self.marshal(b'\n').isupper())
- self.assertTrue(self.marshal(b'ABC').isupper())
- self.assertFalse(self.marshal(b'AbC').isupper())
- self.assertTrue(self.marshal(b'ABC\n').isupper())
- self.assertRaises(TypeError, self.marshal(b'abc').isupper, 42)
-
- def test_istitle(self):
- self.assertFalse(self.marshal(b'').istitle())
- self.assertFalse(self.marshal(b'a').istitle())
- self.assertTrue(self.marshal(b'A').istitle())
- self.assertFalse(self.marshal(b'\n').istitle())
- self.assertTrue(self.marshal(b'A Titlecased Line').istitle())
- self.assertTrue(self.marshal(b'A\nTitlecased Line').istitle())
- self.assertTrue(self.marshal(b'A Titlecased, Line').istitle())
- self.assertFalse(self.marshal(b'Not a capitalized String').istitle())
- self.assertFalse(self.marshal(b'Not\ta Titlecase String').istitle())
- self.assertFalse(self.marshal(b'Not--a Titlecase String').istitle())
- self.assertFalse(self.marshal(b'NOT').istitle())
- self.assertRaises(TypeError, self.marshal(b'abc').istitle, 42)
-
- def test_isspace(self):
- self.assertFalse(self.marshal(b'').isspace())
- self.assertFalse(self.marshal(b'a').isspace())
- self.assertTrue(self.marshal(b' ').isspace())
- self.assertTrue(self.marshal(b'\t').isspace())
- self.assertTrue(self.marshal(b'\r').isspace())
- self.assertTrue(self.marshal(b'\n').isspace())
- self.assertTrue(self.marshal(b' \t\r\n').isspace())
- self.assertFalse(self.marshal(b' \t\r\na').isspace())
- self.assertRaises(TypeError, self.marshal(b'abc').isspace, 42)
-
- def test_isalpha(self):
- self.assertFalse(self.marshal(b'').isalpha())
- self.assertTrue(self.marshal(b'a').isalpha())
- self.assertTrue(self.marshal(b'A').isalpha())
- self.assertFalse(self.marshal(b'\n').isalpha())
- self.assertTrue(self.marshal(b'abc').isalpha())
- self.assertFalse(self.marshal(b'aBc123').isalpha())
- self.assertFalse(self.marshal(b'abc\n').isalpha())
- self.assertRaises(TypeError, self.marshal(b'abc').isalpha, 42)
-
- def test_isalnum(self):
- self.assertFalse(self.marshal(b'').isalnum())
- self.assertTrue(self.marshal(b'a').isalnum())
- self.assertTrue(self.marshal(b'A').isalnum())
- self.assertFalse(self.marshal(b'\n').isalnum())
- self.assertTrue(self.marshal(b'123abc456').isalnum())
- self.assertTrue(self.marshal(b'a1b3c').isalnum())
- self.assertFalse(self.marshal(b'aBc000 ').isalnum())
- self.assertFalse(self.marshal(b'abc\n').isalnum())
- self.assertRaises(TypeError, self.marshal(b'abc').isalnum, 42)
-
- def test_isdigit(self):
- self.assertFalse(self.marshal(b'').isdigit())
- self.assertFalse(self.marshal(b'a').isdigit())
- self.assertTrue(self.marshal(b'0').isdigit())
- self.assertTrue(self.marshal(b'0123456789').isdigit())
- self.assertFalse(self.marshal(b'0123456789a').isdigit())
-
- self.assertRaises(TypeError, self.marshal(b'abc').isdigit, 42)
-
- def test_lower(self):
- self.assertEqual(b'hello', self.marshal(b'HeLLo').lower())
- self.assertEqual(b'hello', self.marshal(b'hello').lower())
- self.assertRaises(TypeError, self.marshal(b'hello').lower, 42)
-
- def test_upper(self):
- self.assertEqual(b'HELLO', self.marshal(b'HeLLo').upper())
- self.assertEqual(b'HELLO', self.marshal(b'HELLO').upper())
- self.assertRaises(TypeError, self.marshal(b'hello').upper, 42)
-
- def test_capitalize(self):
- self.assertEqual(b' hello ', self.marshal(b' hello ').capitalize())
- self.assertEqual(b'Hello ', self.marshal(b'Hello ').capitalize())
- self.assertEqual(b'Hello ', self.marshal(b'hello ').capitalize())
- self.assertEqual(b'Aaaa', self.marshal(b'aaaa').capitalize())
- self.assertEqual(b'Aaaa', self.marshal(b'AaAa').capitalize())
-
- self.assertRaises(TypeError, self.marshal(b'hello').capitalize, 42)
-
- def test_ljust(self):
- self.assertEqual(b'abc ', self.marshal(b'abc').ljust(10))
- self.assertEqual(b'abc ', self.marshal(b'abc').ljust(6))
- self.assertEqual(b'abc', self.marshal(b'abc').ljust(3))
- self.assertEqual(b'abc', self.marshal(b'abc').ljust(2))
- self.assertEqual(b'abc*******', self.marshal(b'abc').ljust(10, b'*'))
- self.assertRaises(TypeError, self.marshal(b'abc').ljust)
-
- def test_rjust(self):
- self.assertEqual(b' abc', self.marshal(b'abc').rjust(10))
- self.assertEqual(b' abc', self.marshal(b'abc').rjust(6))
- self.assertEqual(b'abc', self.marshal(b'abc').rjust(3))
- self.assertEqual(b'abc', self.marshal(b'abc').rjust(2))
- self.assertEqual(b'*******abc', self.marshal(b'abc').rjust(10, b'*'))
- self.assertRaises(TypeError, self.marshal(b'abc').rjust)
-
- def test_center(self):
- self.assertEqual(b' abc ', self.marshal(b'abc').center(10))
- self.assertEqual(b' abc ', self.marshal(b'abc').center(6))
- self.assertEqual(b'abc', self.marshal(b'abc').center(3))
- self.assertEqual(b'abc', self.marshal(b'abc').center(2))
- self.assertEqual(b'***abc****', self.marshal(b'abc').center(10, b'*'))
- self.assertRaises(TypeError, self.marshal(b'abc').center)
-
- def test_swapcase(self):
- self.assertEqual(b'hEllO CoMPuTErS',
- self.marshal(b'HeLLo cOmpUteRs').swapcase())
-
- self.assertRaises(TypeError, self.marshal(b'hello').swapcase, 42)
-
- def test_zfill(self):
- self.assertEqual(b'123', self.marshal(b'123').zfill(2))
- self.assertEqual(b'123', self.marshal(b'123').zfill(3))
- self.assertEqual(b'0123', self.marshal(b'123').zfill(4))
- self.assertEqual(b'+123', self.marshal(b'+123').zfill(3))
- self.assertEqual(b'+123', self.marshal(b'+123').zfill(4))
- self.assertEqual(b'+0123', self.marshal(b'+123').zfill(5))
- self.assertEqual(b'-123', self.marshal(b'-123').zfill(3))
- self.assertEqual(b'-123', self.marshal(b'-123').zfill(4))
- self.assertEqual(b'-0123', self.marshal(b'-123').zfill(5))
- self.assertEqual(b'000', self.marshal(b'').zfill(3))
- self.assertEqual(b'34', self.marshal(b'34').zfill(1))
- self.assertEqual(b'0034', self.marshal(b'34').zfill(4))
-
- self.assertRaises(TypeError, self.marshal(b'123').zfill)
-
- def test_expandtabs(self):
- self.assertEqual(b'abc\rab def\ng hi',
- self.marshal(b'abc\rab\tdef\ng\thi').expandtabs())
- self.assertEqual(b'abc\rab def\ng hi',
- self.marshal(b'abc\rab\tdef\ng\thi').expandtabs(8))
- self.assertEqual(b'abc\rab def\ng hi',
- self.marshal(b'abc\rab\tdef\ng\thi').expandtabs(4))
- self.assertEqual(b'abc\r\nab def\ng hi',
- self.marshal(b'abc\r\nab\tdef\ng\thi').expandtabs())
- self.assertEqual(b'abc\r\nab def\ng hi',
- self.marshal(b'abc\r\nab\tdef\ng\thi').expandtabs(8))
- self.assertEqual(b'abc\r\nab def\ng hi',
- self.marshal(b'abc\r\nab\tdef\ng\thi').expandtabs(4))
- self.assertEqual(b'abc\r\nab\r\ndef\ng\r\nhi',
- self.marshal(b'abc\r\nab\r\ndef\ng\r\nhi').expandtabs(4))
- # check keyword args
- self.assertEqual(b'abc\rab def\ng hi',
- self.marshal(b'abc\rab\tdef\ng\thi').expandtabs(tabsize=8))
- self.assertEqual(b'abc\rab def\ng hi',
- self.marshal(b'abc\rab\tdef\ng\thi').expandtabs(tabsize=4))
-
- self.assertEqual(b' a\n b', self.marshal(b' \ta\n\tb').expandtabs(1))
-
- self.assertRaises(TypeError, self.marshal(b'hello').expandtabs, 42, 42)
- # This test is only valid when sizeof(int) == sizeof(void*) == 4.
- if sys.maxsize < (1 << 32) and struct.calcsize('P') == 4:
- self.assertRaises(OverflowError,
- self.marshal(b'\ta\n\tb').expandtabs, sys.maxsize)
-
- def test_title(self):
- self.assertEqual(b' Hello ', self.marshal(b' hello ').title())
- self.assertEqual(b'Hello ', self.marshal(b'hello ').title())
- self.assertEqual(b'Hello ', self.marshal(b'Hello ').title())
- self.assertEqual(b'Format This As Title String',
- self.marshal(b'fOrMaT thIs aS titLe String').title())
- self.assertEqual(b'Format,This-As*Title;String',
- self.marshal(b'fOrMaT,thIs-aS*titLe;String').title())
- self.assertEqual(b'Getint', self.marshal(b'getInt').title())
- self.assertRaises(TypeError, self.marshal(b'hello').title, 42)
-
- def test_splitlines(self):
- self.assertEqual([b'abc', b'def', b'', b'ghi'],
- self.marshal(b'abc\ndef\n\rghi').splitlines())
- self.assertEqual([b'abc', b'def', b'', b'ghi'],
- self.marshal(b'abc\ndef\n\r\nghi').splitlines())
- self.assertEqual([b'abc', b'def', b'ghi'],
- self.marshal(b'abc\ndef\r\nghi').splitlines())
- self.assertEqual([b'abc', b'def', b'ghi'],
- self.marshal(b'abc\ndef\r\nghi\n').splitlines())
- self.assertEqual([b'abc', b'def', b'ghi', b''],
- self.marshal(b'abc\ndef\r\nghi\n\r').splitlines())
- self.assertEqual([b'', b'abc', b'def', b'ghi', b''],
- self.marshal(b'\nabc\ndef\r\nghi\n\r').splitlines())
- self.assertEqual([b'', b'abc', b'def', b'ghi', b''],
- self.marshal(b'\nabc\ndef\r\nghi\n\r').splitlines(False))
- self.assertEqual([b'\n', b'abc\n', b'def\r\n', b'ghi\n', b'\r'],
- self.marshal(b'\nabc\ndef\r\nghi\n\r').splitlines(True))
- self.assertEqual([b'', b'abc', b'def', b'ghi', b''],
- self.marshal(b'\nabc\ndef\r\nghi\n\r').splitlines(keepends=False))
- self.assertEqual([b'\n', b'abc\n', b'def\r\n', b'ghi\n', b'\r'],
- self.marshal(b'\nabc\ndef\r\nghi\n\r').splitlines(keepends=True))
-
- self.assertRaises(TypeError, self.marshal(b'abc').splitlines, 42, 42)
"""Throws AssertionError if op is found"""
for instr in dis.get_instructions(x):
if instr.opname == opname:
- disassembly = self.get_disassembly_as_string(co)
- if opargval is _UNSPECIFIED:
+ disassembly = self.get_disassembly_as_string(x)
+ if argval is _UNSPECIFIED:
msg = '%s occurs in bytecode:\n%s' % (opname, disassembly)
elif instr.argval == argval:
msg = '(%s,%r) occurs in bytecode:\n%s'
--- /dev/null
+-----BEGIN CERTIFICATE-----
+MIIClTCCAf6gAwIBAgIJAKGU95wKR8pTMA0GCSqGSIb3DQEBBQUAMHAxCzAJBgNV
+BAYTAlhZMRcwFQYDVQQHDA5DYXN0bGUgQW50aHJheDEjMCEGA1UECgwaUHl0aG9u
+IFNvZnR3YXJlIEZvdW5kYXRpb24xIzAhBgNVBAMMGnNlbGYtc2lnbmVkLnB5dGhv
+bnRlc3QubmV0MB4XDTE0MTEwMjE4MDkyOVoXDTI0MTAzMDE4MDkyOVowcDELMAkG
+A1UEBhMCWFkxFzAVBgNVBAcMDkNhc3RsZSBBbnRocmF4MSMwIQYDVQQKDBpQeXRo
+b24gU29mdHdhcmUgRm91bmRhdGlvbjEjMCEGA1UEAwwac2VsZi1zaWduZWQucHl0
+aG9udGVzdC5uZXQwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANDXQXW9tjyZ
+Xt0Iv2tLL1+jinr4wGg36ioLDLFkMf+2Y1GL0v0BnKYG4N1OKlAU15LXGeGer8vm
+Sv/yIvmdrELvhAbbo3w4a9TMYQA4XkIVLdvu3mvNOAet+8PMJxn26dbDhG809ALv
+EHY57lQsBS3G59RZyBPVqAqmImWNJnVzAgMBAAGjNzA1MCUGA1UdEQQeMByCGnNl
+bGYtc2lnbmVkLnB5dGhvbnRlc3QubmV0MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcN
+AQEFBQADgYEAIuzAhgMouJpNdf3URCHIineyoSt6WK/9+eyUcjlKOrDoXNZaD72h
+TXMeKYoWvJyVcSLKL8ckPtDobgP2OTt0UkyAaj0n+ZHaqq1lH2yVfGUA1ILJv515
+C8BqbvVZuqm3i7ygmw3bqE/lYMgOrYtXXnqOrz6nvsE6Yc9V9rFflOM=
+-----END CERTIFICATE-----
--- /dev/null
+-----BEGIN CERTIFICATE-----
+MIIClTCCAf6gAwIBAgIJAKGU95wKR8pTMA0GCSqGSIb3DQEBBQUAMHAxCzAJBgNV
+BAYTAlhZMRcwFQYDVQQHDA5DYXN0bGUgQW50aHJheDEjMCEGA1UECgwaUHl0aG9u
+IFNvZnR3YXJlIEZvdW5kYXRpb24xIzAhBgNVBAMMGnNlbGYtc2lnbmVkLnB5dGhv
+bnRlc3QubmV0MB4XDTE0MTEwMjE4MDkyOVoXDTI0MTAzMDE4MDkyOVowcDELMAkG
+A1UEBhMCWFkxFzAVBgNVBAcMDkNhc3RsZSBBbnRocmF4MSMwIQYDVQQKDBpQeXRo
+b24gU29mdHdhcmUgRm91bmRhdGlvbjEjMCEGA1UEAwwac2VsZi1zaWduZWQucHl0
+aG9udGVzdC5uZXQwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANDXQXW9tjyZ
+Xt0Iv2tLL1+jinr4wGg36ioLDLFkMf+2Y1GL0v0BnKYG4N1OKlAU15LXGeGer8vm
+Sv/yIvmdrELvhAbbo3w4a9TMYQA4XkIVLdvu3mvNOAet+8PMJxn26dbDhG809ALv
+EHY57lQsBS3G59RZyBPVqAqmImWNJnVzAgMBAAGjNzA1MCUGA1UdEQQeMByCGnNl
+bGYtc2lnbmVkLnB5dGhvbnRlc3QubmV0MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcN
+AQEFBQADgYEAIuzAhgMouJpNdf3URCHIineyoSt6WK/9+eyUcjlKOrDoXNZaD72h
+TXMeKYoWvJyVcSLKL8ckPtDobgP2OTt0UkyAaj0n+ZHaqq1lH2yVfGUA1ILJv515
+C8BqbvVZuqm3i7ygmw3bqE/lYMgOrYtXXnqOrz6nvsE6Yc9V9rFflOM=
+-----END CERTIFICATE-----
# either /etc/hosts OR DNS or NIS depending on the settings of
# /etc/host.config, /etc/nsswitch.conf
# and the /etc/resolv.conf file. "host" therefore is system
-# configuration dependant. This parameter is most often of use to
+# configuration dependent. This parameter is most often of use to
# prevent DNS lookups
# in order to resolve NetBIOS names to IP Addresses. Use with care!
# The example below excludes use of name resolution for machines that
def __init__(self, offset=None, name=None, dstoffset=None):
FixedOffset.__init__(self, offset, name, dstoffset)
+ def __getstate__(self):
+ return self.__dict__
+
class _TZInfo(tzinfo):
def utcoffset(self, datetime_module):
return random.random()
#self.assertRaises(ValueError, t.strftime, "%#")
#oh well, some systems just ignore those invalid ones.
- #at least, excercise them to make sure that no crashes
+ #at least, exercise them to make sure that no crashes
#are generated
for f in ["%e", "%", "%#"]:
try:
dt = self.theclass(2007, 9, 10)
self.assertEqual(dt.__format__(''), str(dt))
- with self.assertRaisesRegex(TypeError, '^must be str, not int$'):
+ with self.assertRaisesRegex(TypeError, 'must be str, not int'):
dt.__format__(123)
# check that a derived class's __str__() gets called
dt = self.theclass(2007, 9, 10, 4, 5, 1, 123)
self.assertEqual(dt.__format__(''), str(dt))
- with self.assertRaisesRegex(TypeError, '^must be str, not int$'):
+ with self.assertRaisesRegex(TypeError, 'must be str, not int'):
dt.__format__(123)
# check that a derived class's __str__() gets called
t = self.theclass(1, 2, 3, 4)
self.assertEqual(t.__format__(''), str(t))
- with self.assertRaisesRegex(TypeError, '^must be str, not int$'):
+ with self.assertRaisesRegex(TypeError, 'must be str, not int'):
t.__format__(123)
# check that a derived class's __str__() gets called
self.theclass(bytes([1] * len(base)), 'EST')
# A mixin for classes with a tzinfo= argument. Subclasses must define
-# theclass as a class atribute, and theclass(1, 1, 1, tzinfo=whatever)
+# theclass as a class attribute, and theclass(1, 1, 1, tzinfo=whatever)
# must be legit (which is true for time and datetime).
class TZInfoBase:
self.assertEqual(dt, local)
self.assertEqual(local.strftime("%z %Z"), "-0400 EDT")
+ @support.run_with_tz('EST+05EDT,M3.2.0,M11.1.0')
+ def test_astimezone_default_near_fold(self):
+ # Issue #26616.
+ u = datetime(2015, 11, 1, 5, tzinfo=timezone.utc)
+ t = u.astimezone()
+ s = t.astimezone()
+ self.assertEqual(t.tzinfo, s.tzinfo)
+
def test_aware_subtract(self):
cls = self.theclass
self._test_open("fp = open(path, 'r')\nfp.close()",
self.python_open)
+ @unittest.skipIf(sys.platform == 'darwin', "hangs under OS X; see issue #25234")
def os_open(self, path):
fd = os.open(path, os.O_WRONLY)
os.close(fd)
+ @unittest.skipIf(sys.platform == "darwin", "hangs under OS X; see issue #25234")
def test_os_open(self):
self._test_open("fd = os.open(path, os.O_RDONLY)\nos.close(fd)",
self.os_open)
@unittest.skipUnless(hasattr(signal, 'sigwaitinfo'),
'need signal.sigwaitinfo()')
def test_sigwaitinfo(self):
- # Issue #25277: The sleep is a weak synchronization between the parent
- # and the child process. If the sleep is too low, the test hangs on
- # slow or highly loaded systems.
- self.sleep_time = 2.0
+ # Issue #25277, #25868: give a few miliseconds to the parent process
+ # between os.write() and signal.sigwaitinfo() to works around a race
+ # condition
+ self.sleep_time = 0.100
signum = signal.SIGUSR1
pid = os.getpid()
old_handler = signal.signal(signum, lambda *args: None)
self.addCleanup(signal.signal, signum, old_handler)
+ rpipe, wpipe = os.pipe()
+
code = '\n'.join((
'import os, time',
'pid = %s' % os.getpid(),
'signum = %s' % int(signum),
'sleep_time = %r' % self.sleep_time,
+ 'rpipe = %r' % rpipe,
+ 'os.read(rpipe, 1)',
+ 'os.close(rpipe)',
'time.sleep(sleep_time)',
'os.kill(pid, signum)',
))
t0 = time.monotonic()
- proc = self.subprocess(code)
+ proc = self.subprocess(code, pass_fds=(rpipe,))
+ os.close(rpipe)
with kill_on_error(proc):
+ # sync child-parent
+ os.write(wpipe, b'x')
+ os.close(wpipe)
+
# parent
signal.sigwaitinfo([signum])
dt = time.monotonic() - t0
+++ /dev/null
------BEGIN CERTIFICATE-----
-MIIHPTCCBSWgAwIBAgIBADANBgkqhkiG9w0BAQQFADB5MRAwDgYDVQQKEwdSb290
-IENBMR4wHAYDVQQLExVodHRwOi8vd3d3LmNhY2VydC5vcmcxIjAgBgNVBAMTGUNB
-IENlcnQgU2lnbmluZyBBdXRob3JpdHkxITAfBgkqhkiG9w0BCQEWEnN1cHBvcnRA
-Y2FjZXJ0Lm9yZzAeFw0wMzAzMzAxMjI5NDlaFw0zMzAzMjkxMjI5NDlaMHkxEDAO
-BgNVBAoTB1Jvb3QgQ0ExHjAcBgNVBAsTFWh0dHA6Ly93d3cuY2FjZXJ0Lm9yZzEi
-MCAGA1UEAxMZQ0EgQ2VydCBTaWduaW5nIEF1dGhvcml0eTEhMB8GCSqGSIb3DQEJ
-ARYSc3VwcG9ydEBjYWNlcnQub3JnMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC
-CgKCAgEAziLA4kZ97DYoB1CW8qAzQIxL8TtmPzHlawI229Z89vGIj053NgVBlfkJ
-8BLPRoZzYLdufujAWGSuzbCtRRcMY/pnCujW0r8+55jE8Ez64AO7NV1sId6eINm6
-zWYyN3L69wj1x81YyY7nDl7qPv4coRQKFWyGhFtkZip6qUtTefWIonvuLwphK42y
-fk1WpRPs6tqSnqxEQR5YYGUFZvjARL3LlPdCfgv3ZWiYUQXw8wWRBB0bF4LsyFe7
-w2t6iPGwcswlWyCR7BYCEo8y6RcYSNDHBS4CMEK4JZwFaz+qOqfrU0j36NK2B5jc
-G8Y0f3/JHIJ6BVgrCFvzOKKrF11myZjXnhCLotLddJr3cQxyYN/Nb5gznZY0dj4k
-epKwDpUeb+agRThHqtdB7Uq3EvbXG4OKDy7YCbZZ16oE/9KTfWgu3YtLq1i6L43q
-laegw1SJpfvbi1EinbLDvhG+LJGGi5Z4rSDTii8aP8bQUWWHIbEZAWV/RRyH9XzQ
-QUxPKZgh/TMfdQwEUfoZd9vUFBzugcMd9Zi3aQaRIt0AUMyBMawSB3s42mhb5ivU
-fslfrejrckzzAeVLIL+aplfKkQABi6F1ITe1Yw1nPkZPcCBnzsXWWdsC4PDSy826
-YreQQejdIOQpvGQpQsgi3Hia/0PsmBsJUUtaWsJx8cTLc6nloQsCAwEAAaOCAc4w
-ggHKMB0GA1UdDgQWBBQWtTIb1Mfz4OaO873SsDrusjkY0TCBowYDVR0jBIGbMIGY
-gBQWtTIb1Mfz4OaO873SsDrusjkY0aF9pHsweTEQMA4GA1UEChMHUm9vdCBDQTEe
-MBwGA1UECxMVaHR0cDovL3d3dy5jYWNlcnQub3JnMSIwIAYDVQQDExlDQSBDZXJ0
-IFNpZ25pbmcgQXV0aG9yaXR5MSEwHwYJKoZIhvcNAQkBFhJzdXBwb3J0QGNhY2Vy
-dC5vcmeCAQAwDwYDVR0TAQH/BAUwAwEB/zAyBgNVHR8EKzApMCegJaAjhiFodHRw
-czovL3d3dy5jYWNlcnQub3JnL3Jldm9rZS5jcmwwMAYJYIZIAYb4QgEEBCMWIWh0
-dHBzOi8vd3d3LmNhY2VydC5vcmcvcmV2b2tlLmNybDA0BglghkgBhvhCAQgEJxYl
-aHR0cDovL3d3dy5jYWNlcnQub3JnL2luZGV4LnBocD9pZD0xMDBWBglghkgBhvhC
-AQ0ESRZHVG8gZ2V0IHlvdXIgb3duIGNlcnRpZmljYXRlIGZvciBGUkVFIGhlYWQg
-b3ZlciB0byBodHRwOi8vd3d3LmNhY2VydC5vcmcwDQYJKoZIhvcNAQEEBQADggIB
-ACjH7pyCArpcgBLKNQodgW+JapnM8mgPf6fhjViVPr3yBsOQWqy1YPaZQwGjiHCc
-nWKdpIevZ1gNMDY75q1I08t0AoZxPuIrA2jxNGJARjtT6ij0rPtmlVOKTV39O9lg
-18p5aTuxZZKmxoGCXJzN600BiqXfEVWqFcofN8CCmHBh22p8lqOOLlQ+TyGpkO/c
-gr/c6EWtTZBzCDyUZbAEmXZ/4rzCahWqlwQ3JNgelE5tDlG+1sSPypZt90Pf6DBl
-Jzt7u0NDY8RD97LsaMzhGY4i+5jhe1o+ATc7iwiwovOVThrLm82asduycPAtStvY
-sONvRUgzEv/+PDIqVPfE94rwiCPCR/5kenHA0R6mY7AHfqQv0wGP3J8rtsYIqQ+T
-SCX8Ev2fQtzzxD72V7DX3WnRBnc0CkvSyqD/HMaMyRa+xMwyN2hzXwj7UfdJUzYF
-CpUCTPJ5GhD22Dp1nPMd8aINcGeGG7MW9S/lpOt5hvk9C8JzC6WZrG/8Z7jlLwum
-GCSNe9FINSkYQKyTYOGWhlC0elnYjyELn8+CkcY7v2vcB5G5l1YjqrZslMZIBjzk
-zk6q5PYvCdxTby78dOs6Y5nCpqyJvKeyRKANihDjbPIky/qbn3BHLt4Ui9SyIAmW
-omTxJBzcoTWcFbLUvFUufQb1nA5V9FrWk9p2rSVzTMVD
------END CERTIFICATE-----
def __iter__(self):
raise KeyboardInterrupt
self.assertRaises(KeyboardInterrupt, list, F())
+
+ def test_exhausted_iterator(self):
+ a = self.type2test([1, 2, 3])
+ exhit = iter(a)
+ empit = iter(a)
+ for x in exhit: # exhaust the iterator
+ next(empit) # not exhausted
+ a.append(9)
+ self.assertEqual(list(exhit), [])
+ self.assertEqual(list(empit), [9])
+ self.assertEqual(a, self.type2test([1, 2, 3, 9]))
self.assertEqual(results, [True] * N)
def test_reset_internal_locks(self):
+ # ensure that condition is still using a Lock after reset
evt = self.eventtype()
- old_lock = evt._cond._lock
+ with evt._cond:
+ self.assertFalse(evt._cond.acquire(False))
evt._reset_internal_locks()
- new_lock = evt._cond._lock
- self.assertIsNot(new_lock, old_lock)
- self.assertIs(type(new_lock), type(old_lock))
+ with evt._cond:
+ self.assertFalse(evt._cond.acquire(False))
class ConditionTests(BaseTestCase):
import weakref
from http.cookies import SimpleCookie
+from test import support
from test.support import (
TestFailed, TESTFN, run_with_locale, no_tracing,
_2G, _4G, bigmemtest,
self.assertEqual(getattr(obj, slot, None),
getattr(objcopy, slot, None), msg=msg)
+ def check_unpickling_error(self, errors, data):
+ with self.subTest(data=data), \
+ self.assertRaises(errors):
+ try:
+ self.loads(data)
+ except BaseException as exc:
+ if support.verbose > 1:
+ print('%-32r - %s: %s' %
+ (data, exc.__class__.__name__, exc))
+ raise
+
def test_load_from_data0(self):
self.assert_is_copy(self._testdata, self.loads(DATA0))
# Try too with a bogus literal.
data = b'I' + str(maxint64).encode("ascii") + b'JUNK\n.'
- self.assertRaises(ValueError, self.loads, data)
-
- def test_pop_empty_stack(self):
- # Test issue7455
- s = b'0'
- self.assertRaises((pickle.UnpicklingError, IndexError), self.loads, s)
+ self.check_unpickling_error(ValueError, data)
def test_unpickle_from_2x(self):
# Unpickle non-trivial data from Python 2.x.
def test_negative_32b_binbytes(self):
# On 32-bit builds, a BINBYTES of 2**31 or more is refused
dumped = b'\x80\x03B\xff\xff\xff\xffxyzq\x00.'
- with self.assertRaises((pickle.UnpicklingError, OverflowError)):
- self.loads(dumped)
+ self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
+ dumped)
@requires_32b
def test_negative_32b_binunicode(self):
# On 32-bit builds, a BINUNICODE of 2**31 or more is refused
dumped = b'\x80\x03X\xff\xff\xff\xffxyzq\x00.'
- with self.assertRaises((pickle.UnpicklingError, OverflowError)):
- self.loads(dumped)
+ self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
+ dumped)
def test_short_binunicode(self):
dumped = b'\x80\x04\x8c\x04\xe2\x82\xac\x00.'
self.assertEqual(self.loads(dumped), '\u20ac\x00')
def test_misc_get(self):
- self.assertRaises(KeyError, self.loads, b'g0\np0')
+ self.check_unpickling_error(KeyError, b'g0\np0')
self.assert_is_copy([(100,), (100,)],
self.loads(b'((Kdtp0\nh\x00l.))'))
@requires_32b
def test_large_32b_binbytes8(self):
dumped = b'\x80\x04\x8e\4\0\0\0\1\0\0\0\xe2\x82\xac\x00.'
- with self.assertRaises((pickle.UnpicklingError, OverflowError)):
- self.loads(dumped)
+ self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
+ dumped)
@requires_32b
def test_large_32b_binunicode8(self):
dumped = b'\x80\x04\x8d\4\0\0\0\1\0\0\0\xe2\x82\xac\x00.'
- with self.assertRaises((pickle.UnpicklingError, OverflowError)):
- self.loads(dumped)
+ self.check_unpickling_error((pickle.UnpicklingError, OverflowError),
+ dumped)
def test_get(self):
pickled = b'((lp100000\ng100000\nt.'
def test_negative_put(self):
# Issue #12847
dumped = b'Va\np-1\n.'
- self.assertRaises(ValueError, self.loads, dumped)
+ self.check_unpickling_error(ValueError, dumped)
@requires_32b
def test_negative_32b_binput(self):
# Issue #12847
dumped = b'\x80\x03X\x01\x00\x00\x00ar\xff\xff\xff\xff.'
- self.assertRaises(ValueError, self.loads, dumped)
+ self.check_unpickling_error(ValueError, dumped)
def test_badly_escaped_string(self):
- self.assertRaises(ValueError, self.loads, b"S'\\'\n.")
+ self.check_unpickling_error(ValueError, b"S'\\'\n.")
def test_badly_quoted_string(self):
# Issue #17710
b'S\n.',
b'S.']
for p in badpickles:
- self.assertRaises(pickle.UnpicklingError, self.loads, p)
+ self.check_unpickling_error(pickle.UnpicklingError, p)
def test_correctly_quoted_string(self):
goodpickles = [(b"S''\n.", ''),
self.assertIs(type(unpickled), collections.UserDict)
self.assertEqual(unpickled, collections.UserDict({1: 2}))
+ def test_bad_stack(self):
+ badpickles = [
+ b'.', # STOP
+ b'0', # POP
+ b'1', # POP_MARK
+ b'2', # DUP
+ # b'(2', # PyUnpickler doesn't raise
+ b'R', # REDUCE
+ b')R',
+ b'a', # APPEND
+ b'Na',
+ b'b', # BUILD
+ b'Nb',
+ b'd', # DICT
+ b'e', # APPENDS
+ # b'(e', # PyUnpickler raises AttributeError
+ b'ibuiltins\nlist\n', # INST
+ b'l', # LIST
+ b'o', # OBJ
+ b'(o',
+ b'p1\n', # PUT
+ b'q\x00', # BINPUT
+ b'r\x00\x00\x00\x00', # LONG_BINPUT
+ b's', # SETITEM
+ b'Ns',
+ b'NNs',
+ b't', # TUPLE
+ b'u', # SETITEMS
+ # b'(u', # PyUnpickler doesn't raise
+ b'}(Nu',
+ b'\x81', # NEWOBJ
+ b')\x81',
+ b'\x85', # TUPLE1
+ b'\x86', # TUPLE2
+ b'N\x86',
+ b'\x87', # TUPLE3
+ b'N\x87',
+ b'NN\x87',
+ b'\x90', # ADDITEMS
+ # b'(\x90', # PyUnpickler raises AttributeError
+ b'\x91', # FROZENSET
+ b'\x92', # NEWOBJ_EX
+ b')}\x92',
+ b'\x93', # STACK_GLOBAL
+ b'Vlist\n\x93',
+ b'\x94', # MEMOIZE
+ ]
+ for p in badpickles:
+ self.check_unpickling_error(self.bad_stack_errors, p)
+
+ def test_bad_mark(self):
+ badpickles = [
+ # b'N(.', # STOP
+ b'N(2', # DUP
+ b'cbuiltins\nlist\n)(R', # REDUCE
+ b'cbuiltins\nlist\n()R',
+ b']N(a', # APPEND
+ # BUILD
+ b'cbuiltins\nValueError\n)R}(b',
+ b'cbuiltins\nValueError\n)R(}b',
+ b'(Nd', # DICT
+ b'N(p1\n', # PUT
+ b'N(q\x00', # BINPUT
+ b'N(r\x00\x00\x00\x00', # LONG_BINPUT
+ b'}NN(s', # SETITEM
+ b'}N(Ns',
+ b'}(NNs',
+ b'}((u', # SETITEMS
+ b'cbuiltins\nlist\n)(\x81', # NEWOBJ
+ b'cbuiltins\nlist\n()\x81',
+ b'N(\x85', # TUPLE1
+ b'NN(\x86', # TUPLE2
+ b'N(N\x86',
+ b'NNN(\x87', # TUPLE3
+ b'NN(N\x87',
+ b'N(NN\x87',
+ b']((\x90', # ADDITEMS
+ # NEWOBJ_EX
+ b'cbuiltins\nlist\n)}(\x92',
+ b'cbuiltins\nlist\n)(}\x92',
+ b'cbuiltins\nlist\n()}\x92',
+ # STACK_GLOBAL
+ b'Vbuiltins\n(Vlist\n\x93',
+ b'Vbuiltins\nVlist\n(\x93',
+ b'N(\x94', # MEMOIZE
+ ]
+ for p in badpickles:
+ self.check_unpickling_error(self.bad_mark_errors, p)
+
+ def test_truncated_data(self):
+ self.check_unpickling_error(EOFError, b'')
+ self.check_unpickling_error(EOFError, b'N')
+ badpickles = [
+ b'B', # BINBYTES
+ b'B\x03\x00\x00',
+ b'B\x03\x00\x00\x00',
+ b'B\x03\x00\x00\x00ab',
+ b'C', # SHORT_BINBYTES
+ b'C\x03',
+ b'C\x03ab',
+ b'F', # FLOAT
+ b'F0.0',
+ b'F0.00',
+ b'G', # BINFLOAT
+ b'G\x00\x00\x00\x00\x00\x00\x00',
+ b'I', # INT
+ b'I0',
+ b'J', # BININT
+ b'J\x00\x00\x00',
+ b'K', # BININT1
+ b'L', # LONG
+ b'L0',
+ b'L10',
+ b'L0L',
+ b'L10L',
+ b'M', # BININT2
+ b'M\x00',
+ # b'P', # PERSID
+ # b'Pabc',
+ b'S', # STRING
+ b"S'abc'",
+ b'T', # BINSTRING
+ b'T\x03\x00\x00',
+ b'T\x03\x00\x00\x00',
+ b'T\x03\x00\x00\x00ab',
+ b'U', # SHORT_BINSTRING
+ b'U\x03',
+ b'U\x03ab',
+ b'V', # UNICODE
+ b'Vabc',
+ b'X', # BINUNICODE
+ b'X\x03\x00\x00',
+ b'X\x03\x00\x00\x00',
+ b'X\x03\x00\x00\x00ab',
+ b'(c', # GLOBAL
+ b'(cbuiltins',
+ b'(cbuiltins\n',
+ b'(cbuiltins\nlist',
+ b'Ng', # GET
+ b'Ng0',
+ b'(i', # INST
+ b'(ibuiltins',
+ b'(ibuiltins\n',
+ b'(ibuiltins\nlist',
+ b'Nh', # BINGET
+ b'Nj', # LONG_BINGET
+ b'Nj\x00\x00\x00',
+ b'Np', # PUT
+ b'Np0',
+ b'Nq', # BINPUT
+ b'Nr', # LONG_BINPUT
+ b'Nr\x00\x00\x00',
+ b'\x80', # PROTO
+ b'\x82', # EXT1
+ b'\x83', # EXT2
+ b'\x84\x01',
+ b'\x84', # EXT4
+ b'\x84\x01\x00\x00',
+ b'\x8a', # LONG1
+ b'\x8b', # LONG4
+ b'\x8b\x00\x00\x00',
+ b'\x8c', # SHORT_BINUNICODE
+ b'\x8c\x03',
+ b'\x8c\x03ab',
+ b'\x8d', # BINUNICODE8
+ b'\x8d\x03\x00\x00\x00\x00\x00\x00',
+ b'\x8d\x03\x00\x00\x00\x00\x00\x00\x00',
+ b'\x8d\x03\x00\x00\x00\x00\x00\x00\x00ab',
+ b'\x8e', # BINBYTES8
+ b'\x8e\x03\x00\x00\x00\x00\x00\x00',
+ b'\x8e\x03\x00\x00\x00\x00\x00\x00\x00',
+ b'\x8e\x03\x00\x00\x00\x00\x00\x00\x00ab',
+ b'\x95', # FRAME
+ b'\x95\x02\x00\x00\x00\x00\x00\x00',
+ b'\x95\x02\x00\x00\x00\x00\x00\x00\x00',
+ b'\x95\x02\x00\x00\x00\x00\x00\x00\x00N',
+ ]
+ for p in badpickles:
+ self.check_unpickling_error(self.truncated_errors, p)
+
class AbstractPickleTests(unittest.TestCase):
# Subclass must define self.dumps, self.loads.
# 5th item is not an iterator
return dict, (), None, None, []
- # Protocol 0 is less strict and also accept iterables.
+ # Python implementation is less strict and also accepts iterables.
for proto in protocols:
try:
self.dumps(C(), proto)
- except (pickle.PickleError):
+ except pickle.PicklingError:
pass
try:
self.dumps(D(), proto)
- except (pickle.PickleError):
+ except pickle.PicklingError:
pass
def test_many_puts_and_gets(self):
def __init__(self, items=None):
self.items = items if items is not None else []
def __eq__(self, other):
- return type(self) is type(other) and self.items == self.items
+ return type(self) is type(other) and self.items == other.items
def append(self, item):
self.items.append(item)
def __reduce__(self):
def __init__(self, table=None):
self.table = table if table is not None else {}
def __eq__(self, other):
- return type(self) is type(other) and self.table == self.table
+ return type(self) is type(other) and self.table == other.table
def __setitem__(self, key, value):
self.table[key] = value
def __reduce__(self):
'multiprocessing.process._dangling', 'threading._dangling',
'sysconfig._CONFIG_VARS', 'sysconfig._INSTALL_SCHEMES',
'files', 'locale', 'warnings.showwarning',
+ 'shutil_archive_formats', 'shutil_unpack_formats',
)
def get_sys_argv(self):
-----BEGIN CERTIFICATE-----
-MIIChzCCAfCgAwIBAgIJAKGU95wKR8pSMA0GCSqGSIb3DQEBBQUAMHAxCzAJBgNV
+MIIClTCCAf6gAwIBAgIJAKGU95wKR8pTMA0GCSqGSIb3DQEBBQUAMHAxCzAJBgNV
BAYTAlhZMRcwFQYDVQQHDA5DYXN0bGUgQW50aHJheDEjMCEGA1UECgwaUHl0aG9u
IFNvZnR3YXJlIEZvdW5kYXRpb24xIzAhBgNVBAMMGnNlbGYtc2lnbmVkLnB5dGhv
bnRlc3QubmV0MB4XDTE0MTEwMjE4MDkyOVoXDTI0MTAzMDE4MDkyOVowcDELMAkG
aG9udGVzdC5uZXQwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANDXQXW9tjyZ
Xt0Iv2tLL1+jinr4wGg36ioLDLFkMf+2Y1GL0v0BnKYG4N1OKlAU15LXGeGer8vm
Sv/yIvmdrELvhAbbo3w4a9TMYQA4XkIVLdvu3mvNOAet+8PMJxn26dbDhG809ALv
-EHY57lQsBS3G59RZyBPVqAqmImWNJnVzAgMBAAGjKTAnMCUGA1UdEQQeMByCGnNl
-bGYtc2lnbmVkLnB5dGhvbnRlc3QubmV0MA0GCSqGSIb3DQEBBQUAA4GBAIOXmdtM
-eG9qzP9TiXW/Gc/zI4cBfdCpC+Y4gOfC9bQUC7hefix4iO3+iZjgy3X/FaRxUUoV
-HKiXcXIaWqTSUWp45cSh0MbwZXudp6JIAptzdAhvvCrPKeC9i9GvxsPD4LtDAL97
-vSaxQBezA7hdxZd90/EeyMgVZgAnTCnvAWX9
+EHY57lQsBS3G59RZyBPVqAqmImWNJnVzAgMBAAGjNzA1MCUGA1UdEQQeMByCGnNl
+bGYtc2lnbmVkLnB5dGhvbnRlc3QubmV0MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcN
+AQEFBQADgYEAIuzAhgMouJpNdf3URCHIineyoSt6WK/9+eyUcjlKOrDoXNZaD72h
+TXMeKYoWvJyVcSLKL8ckPtDobgP2OTt0UkyAaj0n+ZHaqq1lH2yVfGUA1ILJv515
+C8BqbvVZuqm3i7ygmw3bqE/lYMgOrYtXXnqOrz6nvsE6Yc9V9rFflOM=
-----END CERTIFICATE-----
import unittest
import sys
import pickle
+from test import support
# Various iterables
# This is used for checking the constructor (here and in test_deque.py)
lst2 = pickle.loads(pickle.dumps(lst, proto))
self.assertEqual(lst2, lst)
self.assertNotEqual(id(lst2), id(lst))
+
+ def test_free_after_iterating(self):
+ support.check_free_after_iterating(self, iter, self.type2test)
+ support.check_free_after_iterating(self, reversed, self.type2test)
"""
-Common tests shared by test_unicode, test_userstring and test_string.
+Common tests shared by test_unicode, test_userstring and test_bytes.
"""
import unittest, string, sys, struct
else:
return obj
+ def test_fixtype(self):
+ self.assertIs(type(self.fixtype("123")), self.type2test)
+
# check that obj.method(*args) returns result
def checkequal(self, result, obj, methodname, *args, **kwargs):
result = self.fixtype(result)
sys.maxsize-2)
self.checkequal(['a|b|c|d'], 'a|b|c|d', 'split', '|', 0)
self.checkequal(['a', '', 'b||c||d'], 'a||b||c||d', 'split', '|', 2)
+ self.checkequal(['abcd'], 'abcd', 'split', '|')
+ self.checkequal([''], '', 'split', '|')
self.checkequal(['endcase ', ''], 'endcase |', 'split', '|')
self.checkequal(['', ' startcase'], '| startcase', 'split', '|')
self.checkequal(['', 'bothcase', ''], '|bothcase|', 'split', '|')
sys.maxsize-100)
self.checkequal(['a|b|c|d'], 'a|b|c|d', 'rsplit', '|', 0)
self.checkequal(['a||b||c', '', 'd'], 'a||b||c||d', 'rsplit', '|', 2)
+ self.checkequal(['abcd'], 'abcd', 'rsplit', '|')
+ self.checkequal([''], '', 'rsplit', '|')
self.checkequal(['', ' begincase'], '| begincase', 'rsplit', '|')
self.checkequal(['endcase ', ''], 'endcase |', 'rsplit', '|')
self.checkequal(['', 'bothcase', ''], '|bothcase|', 'rsplit', '|')
EQ("bobobXbobob", "bobobobXbobobob", "replace", "bobob", "bob")
EQ("BOBOBOB", "BOBOBOB", "replace", "bob", "bobby")
- # XXX Commented out. Is there any reason to support buffer objects
- # as arguments for str.replace()? GvR
-## ba = bytearray('a')
-## bb = bytearray('b')
-## EQ("bbc", "abc", "replace", ba, bb)
-## EQ("aac", "abc", "replace", bb, ba)
-
- #
self.checkequal('one@two!three!', 'one!two!three!', 'replace', '!', '@', 1)
self.checkequal('onetwothree', 'one!two!three!', 'replace', '!', '')
self.checkequal('one@two@three!', 'one!two!three!', 'replace', '!', '@', 2)
self.checkraises(OverflowError, A2_16, "replace", "A", A2_16)
self.checkraises(OverflowError, A2_16, "replace", "AA", A2_16+A2_16)
-
-
-class CommonTest(BaseTest):
- # This testcase contains test that can be used in all
- # stringlike classes. Currently this is str, unicode
- # UserString and the string module.
-
- def test_hash(self):
- # SF bug 1054139: += optimization was not invalidating cached hash value
- a = self.type2test('DNSSEC')
- b = self.type2test('')
- for c in a:
- b += c
- hash(b)
- self.assertEqual(hash(a), hash(b))
-
def test_capitalize(self):
self.checkequal(' hello ', ' hello ', 'capitalize')
self.checkequal('Hello ', 'Hello ','capitalize')
self.checkequal('Aaaa', 'aaaa', 'capitalize')
self.checkequal('Aaaa', 'AaAa', 'capitalize')
- # check that titlecased chars are lowered correctly
- # \u1ffc is the titlecased char
- self.checkequal('\u03a9\u0399\u1ff3\u1ff3\u1ff3',
- '\u1ff3\u1ff3\u1ffc\u1ffc', 'capitalize')
- # check with cased non-letter chars
- self.checkequal('\u24c5\u24e8\u24e3\u24d7\u24de\u24dd',
- '\u24c5\u24ce\u24c9\u24bd\u24c4\u24c3', 'capitalize')
- self.checkequal('\u24c5\u24e8\u24e3\u24d7\u24de\u24dd',
- '\u24df\u24e8\u24e3\u24d7\u24de\u24dd', 'capitalize')
- self.checkequal('\u2160\u2171\u2172',
- '\u2160\u2161\u2162', 'capitalize')
- self.checkequal('\u2160\u2171\u2172',
- '\u2170\u2171\u2172', 'capitalize')
- # check with Ll chars with no upper - nothing changes here
- self.checkequal('\u019b\u1d00\u1d86\u0221\u1fb7',
- '\u019b\u1d00\u1d86\u0221\u1fb7', 'capitalize')
-
self.checkraises(TypeError, 'hello', 'capitalize', 42)
def test_additional_split(self):
self.checkequal(['a'], ' a ', 'split')
self.checkequal(['a', 'b'], ' a b ', 'split')
self.checkequal(['a', 'b '], ' a b ', 'split', None, 1)
+ self.checkequal(['a b c '], ' a b c ', 'split', None, 0)
self.checkequal(['a', 'b c '], ' a b c ', 'split', None, 1)
self.checkequal(['a', 'b', 'c '], ' a b c ', 'split', None, 2)
+ self.checkequal(['a', 'b', 'c'], ' a b c ', 'split', None, 3)
self.checkequal(['a', 'b'], '\n\ta \t\r b \v ', 'split')
aaa = ' a '*20
self.checkequal(['a']*20, aaa, 'split')
self.checkequal(['a'] + [aaa[4:]], aaa, 'split', None, 1)
self.checkequal(['a']*19 + ['a '], aaa, 'split', None, 19)
- # mixed use of str and unicode
- self.checkequal(['a', 'b', 'c d'], 'a b c d', 'split', ' ', 2)
+ for b in ('arf\tbarf', 'arf\nbarf', 'arf\rbarf',
+ 'arf\fbarf', 'arf\vbarf'):
+ self.checkequal(['arf', 'barf'], b, 'split')
+ self.checkequal(['arf', 'barf'], b, 'split', None)
+ self.checkequal(['arf', 'barf'], b, 'split', None, 2)
def test_additional_rsplit(self):
self.checkequal(['this', 'is', 'the', 'rsplit', 'function'],
self.checkequal(['a'], ' a ', 'rsplit')
self.checkequal(['a', 'b'], ' a b ', 'rsplit')
self.checkequal([' a', 'b'], ' a b ', 'rsplit', None, 1)
+ self.checkequal([' a b c'], ' a b c ', 'rsplit',
+ None, 0)
self.checkequal([' a b','c'], ' a b c ', 'rsplit',
None, 1)
self.checkequal([' a', 'b', 'c'], ' a b c ', 'rsplit',
None, 2)
+ self.checkequal(['a', 'b', 'c'], ' a b c ', 'rsplit',
+ None, 3)
self.checkequal(['a', 'b'], '\n\ta \t\r b \v ', 'rsplit', None, 88)
aaa = ' a '*20
self.checkequal(['a']*20, aaa, 'rsplit')
self.checkequal([aaa[:-4]] + ['a'], aaa, 'rsplit', None, 1)
self.checkequal([' a a'] + ['a']*18, aaa, 'rsplit', None, 18)
- # mixed use of str and unicode
- self.checkequal(['a b', 'c', 'd'], 'a b c d', 'rsplit', ' ', 2)
+ for b in ('arf\tbarf', 'arf\nbarf', 'arf\rbarf',
+ 'arf\fbarf', 'arf\vbarf'):
+ self.checkequal(['arf', 'barf'], b, 'rsplit')
+ self.checkequal(['arf', 'barf'], b, 'rsplit', None)
+ self.checkequal(['arf', 'barf'], b, 'rsplit', None, 2)
- def test_strip(self):
+ def test_strip_whitespace(self):
self.checkequal('hello', ' hello ', 'strip')
self.checkequal('hello ', ' hello ', 'lstrip')
self.checkequal(' hello', ' hello ', 'rstrip')
self.checkequal('hello', 'hello', 'strip')
+ b = ' \t\n\r\f\vabc \t\n\r\f\v'
+ self.checkequal('abc', b, 'strip')
+ self.checkequal('abc \t\n\r\f\v', b, 'lstrip')
+ self.checkequal(' \t\n\r\f\vabc', b, 'rstrip')
+
# strip/lstrip/rstrip with None arg
self.checkequal('hello', ' hello ', 'strip', None)
self.checkequal('hello ', ' hello ', 'lstrip', None)
self.checkequal(' hello', ' hello ', 'rstrip', None)
self.checkequal('hello', 'hello', 'strip', None)
+ def test_strip(self):
# strip/lstrip/rstrip with str arg
self.checkequal('hello', 'xyzzyhelloxyzzy', 'strip', 'xyz')
self.checkequal('helloxyzzy', 'xyzzyhelloxyzzy', 'lstrip', 'xyz')
self.checkequal('xyzzyhello', 'xyzzyhelloxyzzy', 'rstrip', 'xyz')
self.checkequal('hello', 'hello', 'strip', 'xyz')
+ self.checkequal('', 'mississippi', 'strip', 'mississippi')
+
+ # only trim the start and end; does not strip internal characters
+ self.checkequal('mississipp', 'mississippi', 'strip', 'i')
self.checkraises(TypeError, 'hello', 'strip', 42, 42)
self.checkraises(TypeError, 'hello', 'lstrip', 42, 42)
self.checkraises(TypeError, '123', 'zfill')
-class MixinStrUnicodeUserStringTest:
- # additional tests that only work for
- # stringlike objects, i.e. str, unicode, UserString
- # (but not the string module)
-
def test_islower(self):
self.checkequal(False, '', 'islower')
self.checkequal(True, 'a', 'islower')
self.checkraises(TypeError, 'abc', 'splitlines', 42, 42)
+
+class CommonTest(BaseTest):
+ # This testcase contains tests that can be used in all
+ # stringlike classes. Currently this is str and UserString.
+
+ def test_hash(self):
+ # SF bug 1054139: += optimization was not invalidating cached hash value
+ a = self.type2test('DNSSEC')
+ b = self.type2test('')
+ for c in a:
+ b += c
+ hash(b)
+ self.assertEqual(hash(a), hash(b))
+
+ def test_capitalize_nonascii(self):
+ # check that titlecased chars are lowered correctly
+ # \u1ffc is the titlecased char
+ self.checkequal('\u03a9\u0399\u1ff3\u1ff3\u1ff3',
+ '\u1ff3\u1ff3\u1ffc\u1ffc', 'capitalize')
+ # check with cased non-letter chars
+ self.checkequal('\u24c5\u24e8\u24e3\u24d7\u24de\u24dd',
+ '\u24c5\u24ce\u24c9\u24bd\u24c4\u24c3', 'capitalize')
+ self.checkequal('\u24c5\u24e8\u24e3\u24d7\u24de\u24dd',
+ '\u24df\u24e8\u24e3\u24d7\u24de\u24dd', 'capitalize')
+ self.checkequal('\u2160\u2171\u2172',
+ '\u2160\u2161\u2162', 'capitalize')
+ self.checkequal('\u2160\u2171\u2172',
+ '\u2170\u2171\u2172', 'capitalize')
+ # check with Ll chars with no upper - nothing changes here
+ self.checkequal('\u019b\u1d00\u1d86\u0221\u1fb7',
+ '\u019b\u1d00\u1d86\u0221\u1fb7', 'capitalize')
+
+
+class MixinStrUnicodeUserStringTest:
+ # additional tests that only work for
+ # stringlike objects, i.e. str, UserString
+
def test_startswith(self):
self.checkequal(True, 'hello', 'startswith', 'he')
self.checkequal(True, 'hello', 'startswith', 'hello')
class MixinStrUnicodeTest:
- # Additional tests that only work with str and unicode.
+ # Additional tests that only work with str.
def test_bug1001011(self):
# Make sure join returns a NEW object for single item sequences
s1 = t("abcd")
s2 = t().join([s1])
self.assertIs(s1, s2)
-
- # Should also test mixed-type join.
- if t is str:
- s1 = subclass("abcd")
- s2 = "".join([s1])
- self.assertIsNot(s1, s2)
- self.assertIs(type(s2), t)
-
- s1 = t("abcd")
- s2 = "".join([s1])
- self.assertIs(s1, s2)
-
-## elif t is str8:
-## s1 = subclass("abcd")
-## s2 = "".join([s1])
-## self.assertIsNot(s1, s2)
-## self.assertIs(type(s2), str) # promotes!
-
-## s1 = t("abcd")
-## s2 = "".join([s1])
-## self.assertIsNot(s1, s2)
-## self.assertIs(type(s2), str) # promotes!
-
- else:
- self.fail("unexpected type for MixinStrUnicodeTest %r" % t)
# threads
"threading_setup", "threading_cleanup", "reap_threads", "start_threads",
# miscellaneous
- "check_warnings", "EnvironmentVarGuard", "run_with_locale", "swap_item",
+ "check_warnings", "check_no_resource_warning", "EnvironmentVarGuard",
+ "run_with_locale", "swap_item",
"swap_attr", "Matcher", "set_memlimit", "SuppressCrashReport", "sortdict",
"run_with_tz",
]
return _filterwarnings(filters, quiet)
+@contextlib.contextmanager
+def check_no_resource_warning(testcase):
+ """Context manager to check that no ResourceWarning is emitted.
+
+ Usage:
+
+ with check_no_resource_warning(self):
+ f = open(...)
+ ...
+ del f
+
+ You must remove the object which may emit ResourceWarning before
+ the end of the context manager.
+ """
+ with warnings.catch_warnings(record=True) as warns:
+ warnings.filterwarnings('always', category=ResourceWarning)
+ yield
+ gc_collect()
+ testcase.assertEqual(warns, [])
+
+
class CleanImport(object):
"""Context manager to force import to return a new module reference.
"memory allocations")
import _testcapi
return _testcapi.run_in_subinterp(code)
+
+
+def check_free_after_iterating(test, iter, cls, args=()):
+ class A(cls):
+ def __del__(self):
+ nonlocal done
+ done = True
+ try:
+ next(it)
+ except StopIteration:
+ pass
+
+ done = False
+ it = iter(A(*args))
+ # Issue 26494: Shouldn't crash
+ test.assertRaises(StopIteration, next, it)
+ # The sequence should be deallocated just after the end of iterating
+ gc_collect()
+ test.assertTrue(done)
variables `env_vars` succeeds (rc == 0) and return a (return code, stdout,
stderr) tuple.
- If the __cleanenv keyword is set, env_vars is used a fresh environment.
+ If the __cleanenv keyword is set, env_vars is used as a fresh environment.
Python is started in isolated mode (command line option -I),
except if the __isolated keyword is set to False.
known_numerics = {
'en_US': ('.', ','),
'de_DE' : (',', '.'),
- 'fr_FR.UTF-8' : (',', ' '),
+ # The French thousands separator may be a breaking or non-breaking space
+ # depending on the platform, so do not test it
+ 'fr_FR' : (',', ''),
'ps_AF': ('\u066b', '\u066c'),
}
class TestOptionalsNargs1(ParserTestCase):
- """Tests specifying the 1 arg for an Optional"""
+ """Tests specifying 1 arg for an Optional"""
argument_signatures = [Sig('-x', nargs=1)]
failures = ['a', '-x']
class TestOptionalsNargs3(ParserTestCase):
- """Tests specifying the 3 args for an Optional"""
+ """Tests specifying 3 args for an Optional"""
argument_signatures = [Sig('-x', nargs=3)]
failures = ['a', '-x', '-x a', '-x a b', 'a -x', 'a -x b']
class TestOptionalsNargsZeroOrMore(ParserTestCase):
- """Tests specifying an args for an Optional that accepts zero or more"""
+ """Tests specifying args for an Optional that accepts zero or more"""
argument_signatures = [
Sig('-x', nargs='*'),
class TestOptionalsNargsOneOrMore(ParserTestCase):
- """Tests specifying an args for an Optional that accepts one or more"""
+ """Tests specifying args for an Optional that accepts one or more"""
argument_signatures = [
Sig('-x', nargs='+'),
class TestNargsZeroOrMore(ParserTestCase):
- """Tests specifying an args for an Optional that accepts zero or more"""
+ """Tests specifying args for an Optional that accepts zero or more"""
argument_signatures = [Sig('-x', nargs='*'), Sig('y', nargs='*')]
failures = []
self.assertEqual(type(a), type(b))
def test_iterator_pickle(self):
- data = array.array(self.typecode, self.example)
+ orig = array.array(self.typecode, self.example)
+ data = list(orig)
+ data2 = data[::-1]
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
- orgit = iter(data)
- d = pickle.dumps(orgit, proto)
- it = pickle.loads(d)
- self.assertEqual(type(orgit), type(it))
- self.assertEqual(list(it), list(data))
-
- if len(data):
- it = pickle.loads(d)
- next(it)
- d = pickle.dumps(it, proto)
- self.assertEqual(list(it), list(data)[1:])
+ # initial iterator
+ itorig = iter(orig)
+ d = pickle.dumps((itorig, orig), proto)
+ it, a = pickle.loads(d)
+ a.fromlist(data2)
+ self.assertEqual(type(it), type(itorig))
+ self.assertEqual(list(it), data + data2)
+
+ # running iterator
+ next(itorig)
+ d = pickle.dumps((itorig, orig), proto)
+ it, a = pickle.loads(d)
+ a.fromlist(data2)
+ self.assertEqual(type(it), type(itorig))
+ self.assertEqual(list(it), data[1:] + data2)
+
+ # empty iterator
+ for i in range(1, len(data)):
+ next(itorig)
+ d = pickle.dumps((itorig, orig), proto)
+ it, a = pickle.loads(d)
+ a.fromlist(data2)
+ self.assertEqual(type(it), type(itorig))
+ self.assertEqual(list(it), data2)
+
+ # exhausted iterator
+ self.assertRaises(StopIteration, next, itorig)
+ d = pickle.dumps((itorig, orig), proto)
+ it, a = pickle.loads(d)
+ a.fromlist(data2)
+ self.assertEqual(type(it), type(itorig))
+ self.assertEqual(list(it), data2)
def test_insert(self):
a = array.array(self.typecode, self.example)
PY34 = sys.version_info >= (3, 4)
+def mock_socket_module():
+ m_socket = mock.MagicMock(spec=socket)
+ for name in (
+ 'AF_INET', 'AF_INET6', 'AF_UNSPEC', 'IPPROTO_TCP', 'IPPROTO_UDP',
+ 'SOCK_STREAM', 'SOCK_DGRAM', 'SOL_SOCKET', 'SO_REUSEADDR', 'inet_pton'
+ ):
+ if hasattr(socket, name):
+ setattr(m_socket, name, getattr(socket, name))
+ else:
+ delattr(m_socket, name)
+
+ m_socket.socket = mock.MagicMock()
+ m_socket.socket.return_value = test_utils.mock_nonblocking_socket()
+ m_socket.getaddrinfo._is_coroutine = False
+
+ return m_socket
+
+
+def patch_socket(f):
+ return mock.patch('asyncio.base_events.socket',
+ new_callable=mock_socket_module)(f)
+
+
+class BaseEventTests(test_utils.TestCase):
+
+ def test_ipaddr_info(self):
+ UNSPEC = socket.AF_UNSPEC
+ INET = socket.AF_INET
+ INET6 = socket.AF_INET6
+ STREAM = socket.SOCK_STREAM
+ DGRAM = socket.SOCK_DGRAM
+ TCP = socket.IPPROTO_TCP
+ UDP = socket.IPPROTO_UDP
+
+ self.assertEqual(
+ (INET, STREAM, TCP, '', ('1.2.3.4', 1)),
+ base_events._ipaddr_info('1.2.3.4', 1, INET, STREAM, TCP))
+
+ self.assertEqual(
+ (INET, STREAM, TCP, '', ('1.2.3.4', 1)),
+ base_events._ipaddr_info(b'1.2.3.4', 1, INET, STREAM, TCP))
+
+ self.assertEqual(
+ (INET, STREAM, TCP, '', ('1.2.3.4', 1)),
+ base_events._ipaddr_info('1.2.3.4', 1, UNSPEC, STREAM, TCP))
+
+ self.assertEqual(
+ (INET, DGRAM, UDP, '', ('1.2.3.4', 1)),
+ base_events._ipaddr_info('1.2.3.4', 1, UNSPEC, DGRAM, UDP))
+
+ # Socket type STREAM implies TCP protocol.
+ self.assertEqual(
+ (INET, STREAM, TCP, '', ('1.2.3.4', 1)),
+ base_events._ipaddr_info('1.2.3.4', 1, UNSPEC, STREAM, 0))
+
+ # Socket type DGRAM implies UDP protocol.
+ self.assertEqual(
+ (INET, DGRAM, UDP, '', ('1.2.3.4', 1)),
+ base_events._ipaddr_info('1.2.3.4', 1, UNSPEC, DGRAM, 0))
+
+ # No socket type.
+ self.assertIsNone(
+ base_events._ipaddr_info('1.2.3.4', 1, UNSPEC, 0, 0))
+
+ # IPv4 address with family IPv6.
+ self.assertIsNone(
+ base_events._ipaddr_info('1.2.3.4', 1, INET6, STREAM, TCP))
+
+ self.assertEqual(
+ (INET6, STREAM, TCP, '', ('::3', 1)),
+ base_events._ipaddr_info('::3', 1, INET6, STREAM, TCP))
+
+ self.assertEqual(
+ (INET6, STREAM, TCP, '', ('::3', 1)),
+ base_events._ipaddr_info('::3', 1, UNSPEC, STREAM, TCP))
+
+ # IPv6 address with family IPv4.
+ self.assertIsNone(
+ base_events._ipaddr_info('::3', 1, INET, STREAM, TCP))
+
+ # IPv6 address with zone index.
+ self.assertIsNone(
+ base_events._ipaddr_info('::3%lo0', 1, INET6, STREAM, TCP))
+
+ def test_port_parameter_types(self):
+ # Test obscure kinds of arguments for "port".
+ INET = socket.AF_INET
+ STREAM = socket.SOCK_STREAM
+ TCP = socket.IPPROTO_TCP
+
+ self.assertEqual(
+ (INET, STREAM, TCP, '', ('1.2.3.4', 0)),
+ base_events._ipaddr_info('1.2.3.4', None, INET, STREAM, TCP))
+
+ self.assertEqual(
+ (INET, STREAM, TCP, '', ('1.2.3.4', 0)),
+ base_events._ipaddr_info('1.2.3.4', b'', INET, STREAM, TCP))
+
+ self.assertEqual(
+ (INET, STREAM, TCP, '', ('1.2.3.4', 0)),
+ base_events._ipaddr_info('1.2.3.4', '', INET, STREAM, TCP))
+
+ self.assertEqual(
+ (INET, STREAM, TCP, '', ('1.2.3.4', 1)),
+ base_events._ipaddr_info('1.2.3.4', '1', INET, STREAM, TCP))
+
+ self.assertEqual(
+ (INET, STREAM, TCP, '', ('1.2.3.4', 1)),
+ base_events._ipaddr_info('1.2.3.4', b'1', INET, STREAM, TCP))
+
+ def test_getaddrinfo_servname(self):
+ INET = socket.AF_INET
+ STREAM = socket.SOCK_STREAM
+ TCP = socket.IPPROTO_TCP
+
+ self.assertEqual(
+ (INET, STREAM, TCP, '', ('1.2.3.4', 80)),
+ base_events._ipaddr_info('1.2.3.4', 'http', INET, STREAM, TCP))
+
+ self.assertEqual(
+ (INET, STREAM, TCP, '', ('1.2.3.4', 80)),
+ base_events._ipaddr_info('1.2.3.4', b'http', INET, STREAM, TCP))
+
+ # Raises "service/proto not found".
+ with self.assertRaises(OSError):
+ base_events._ipaddr_info('1.2.3.4', 'nonsense', INET, STREAM, TCP)
+
+ with self.assertRaises(OSError):
+ base_events._ipaddr_info('1.2.3.4', 'nonsense', INET, STREAM, TCP)
+
+ @patch_socket
+ def test_ipaddr_info_no_inet_pton(self, m_socket):
+ del m_socket.inet_pton
+ self.assertIsNone(base_events._ipaddr_info('1.2.3.4', 1,
+ socket.AF_INET,
+ socket.SOCK_STREAM,
+ socket.IPPROTO_TCP))
+
+
class BaseEventLoopTests(test_utils.TestCase):
def setUp(self):
fut.add_done_callback(lambda *args: self.loop.stop())
self.loop.run_forever()
fut = None # Trigger Future.__del__ or futures._TracebackLogger
+ support.gc_collect()
if PY34:
# Future.__del__ in Python 3.4 logs error with
# an actual exception context
self.loop.set_debug(True)
self.loop._process_events = mock.Mock()
+ self.assertIsNone(self.loop.get_exception_handler())
mock_handler = mock.Mock()
self.loop.set_exception_handler(mock_handler)
+ self.assertIs(self.loop.get_exception_handler(), mock_handler)
handle = run_loop()
mock_handler.assert_called_with(self.loop, {
'exception': MOCK_ANY,
self.loop = asyncio.new_event_loop()
self.set_event_loop(self.loop)
- @mock.patch('asyncio.base_events.socket')
+ @patch_socket
def test_create_connection_multiple_errors(self, m_socket):
class MyProto(asyncio.Protocol):
self.assertEqual(str(cm.exception), 'Multiple exceptions: err1, err2')
- @mock.patch('asyncio.base_events.socket')
+ @patch_socket
def test_create_connection_timeout(self, m_socket):
# Ensure that the socket is closed on timeout
sock = mock.Mock()
with self.assertRaises(OSError):
self.loop.run_until_complete(coro)
- @mock.patch('asyncio.base_events.socket')
+ @patch_socket
def test_create_connection_multiple_errors_local_addr(self, m_socket):
def bind(addr):
self.assertTrue(str(cm.exception).startswith('Multiple exceptions: '))
self.assertTrue(m_socket.socket.return_value.close.called)
+ def _test_create_connection_ip_addr(self, m_socket, allow_inet_pton):
+ # Test the fallback code, even if this system has inet_pton.
+ if not allow_inet_pton:
+ del m_socket.inet_pton
+
+ m_socket.getaddrinfo = socket.getaddrinfo
+ sock = m_socket.socket.return_value
+
+ self.loop.add_reader = mock.Mock()
+ self.loop.add_reader._is_coroutine = False
+ self.loop.add_writer = mock.Mock()
+ self.loop.add_writer._is_coroutine = False
+
+ coro = self.loop.create_connection(asyncio.Protocol, '1.2.3.4', 80)
+ t, p = self.loop.run_until_complete(coro)
+ try:
+ sock.connect.assert_called_with(('1.2.3.4', 80))
+ _, kwargs = m_socket.socket.call_args
+ self.assertEqual(kwargs['family'], m_socket.AF_INET)
+ self.assertEqual(kwargs['type'], m_socket.SOCK_STREAM)
+ finally:
+ t.close()
+ test_utils.run_briefly(self.loop) # allow transport to close
+
+ sock.family = socket.AF_INET6
+ coro = self.loop.create_connection(asyncio.Protocol, '::2', 80)
+ t, p = self.loop.run_until_complete(coro)
+ try:
+ # Without inet_pton we use getaddrinfo, which transforms ('::2', 80)
+ # to ('::0.0.0.2', 80, 0, 0). The last 0s are flow info, scope id.
+ [address] = sock.connect.call_args[0]
+ host, port = address[:2]
+ self.assertRegex(host, r'::(0\.)*2')
+ self.assertEqual(port, 80)
+ _, kwargs = m_socket.socket.call_args
+ self.assertEqual(kwargs['family'], m_socket.AF_INET6)
+ self.assertEqual(kwargs['type'], m_socket.SOCK_STREAM)
+ finally:
+ t.close()
+ test_utils.run_briefly(self.loop) # allow transport to close
+
+ @patch_socket
+ def test_create_connection_ip_addr(self, m_socket):
+ self._test_create_connection_ip_addr(m_socket, True)
+
+ @patch_socket
+ def test_create_connection_no_inet_pton(self, m_socket):
+ self._test_create_connection_ip_addr(m_socket, False)
+
def test_create_connection_no_local_addr(self):
@asyncio.coroutine
def getaddrinfo(host, *args, **kw):
self.assertRaises(
OSError, self.loop.run_until_complete, coro)
+ @patch_socket
+ def test_create_connection_bluetooth(self, m_socket):
+ # See http://bugs.python.org/issue27136, fallback to getaddrinfo when
+ # we can't recognize an address is resolved, e.g. a Bluetooth address.
+ addr = ('00:01:02:03:04:05', 1)
+
+ def getaddrinfo(host, port, *args, **kw):
+ assert (host, port) == addr
+ return [(999, 1, 999, '', (addr, 1))]
+
+ m_socket.getaddrinfo = getaddrinfo
+ sock = m_socket.socket()
+ coro = self.loop.sock_connect(sock, addr)
+ self.loop.run_until_complete(coro)
+
def test_create_connection_ssl_server_hostname_default(self):
self.loop.getaddrinfo = mock.Mock()
getaddrinfo = self.loop.getaddrinfo = mock.Mock()
getaddrinfo.return_value = []
- f = self.loop.create_server(MyProto, '0.0.0.0', 0)
+ f = self.loop.create_server(MyProto, 'python.org', 0)
self.assertRaises(OSError, self.loop.run_until_complete, f)
- @mock.patch('asyncio.base_events.socket')
+ @patch_socket
def test_create_server_nosoreuseport(self, m_socket):
m_socket.getaddrinfo = socket.getaddrinfo
- m_socket.SOCK_STREAM = socket.SOCK_STREAM
- m_socket.SOL_SOCKET = socket.SOL_SOCKET
del m_socket.SO_REUSEPORT
m_socket.socket.return_value = mock.Mock()
self.assertRaises(ValueError, self.loop.run_until_complete, f)
- @mock.patch('asyncio.base_events.socket')
+ @patch_socket
def test_create_server_cant_bind(self, m_socket):
class Err(OSError):
self.assertRaises(OSError, self.loop.run_until_complete, fut)
self.assertTrue(m_sock.close.called)
- @mock.patch('asyncio.base_events.socket')
+ @patch_socket
def test_create_datagram_endpoint_no_addrinfo(self, m_socket):
m_socket.getaddrinfo.return_value = []
m_socket.getaddrinfo._is_coroutine = False
self.assertRaises(
OSError, self.loop.run_until_complete, coro)
- @mock.patch('asyncio.base_events.socket')
+ @patch_socket
def test_create_datagram_endpoint_socket_err(self, m_socket):
m_socket.getaddrinfo = socket.getaddrinfo
m_socket.socket.side_effect = OSError
self.assertRaises(
ValueError, self.loop.run_until_complete, coro)
- @mock.patch('asyncio.base_events.socket')
+ @patch_socket
def test_create_datagram_endpoint_setblk_err(self, m_socket):
m_socket.socket.return_value.setblocking.side_effect = OSError
asyncio.DatagramProtocol)
self.assertRaises(ValueError, self.loop.run_until_complete, coro)
- @mock.patch('asyncio.base_events.socket')
+ @patch_socket
def test_create_datagram_endpoint_cant_bind(self, m_socket):
class Err(OSError):
pass
- m_socket.AF_INET6 = socket.AF_INET6
m_socket.getaddrinfo = socket.getaddrinfo
m_sock = m_socket.socket.return_value = mock.Mock()
m_sock.bind.side_effect = Err
self.loop.run_until_complete(protocol.done)
self.assertEqual('CLOSED', protocol.state)
- @mock.patch('asyncio.base_events.socket')
+ @patch_socket
def test_create_datagram_endpoint_nosoreuseport(self, m_socket):
- m_socket.getaddrinfo = socket.getaddrinfo
- m_socket.SOCK_DGRAM = socket.SOCK_DGRAM
- m_socket.SOL_SOCKET = socket.SOL_SOCKET
del m_socket.SO_REUSEPORT
m_socket.socket.return_value = mock.Mock()
self.assertRaises(ValueError, self.loop.run_until_complete, coro)
+ @patch_socket
+ def test_create_datagram_endpoint_ip_addr(self, m_socket):
+ def getaddrinfo(*args, **kw):
+ self.fail('should not have called getaddrinfo')
+
+ m_socket.getaddrinfo = getaddrinfo
+ m_socket.socket.return_value.bind = bind = mock.Mock()
+ self.loop.add_reader = mock.Mock()
+ self.loop.add_reader._is_coroutine = False
+
+ reuseport_supported = hasattr(socket, 'SO_REUSEPORT')
+ coro = self.loop.create_datagram_endpoint(
+ lambda: MyDatagramProto(loop=self.loop),
+ local_addr=('1.2.3.4', 0),
+ reuse_address=False,
+ reuse_port=reuseport_supported)
+
+ t, p = self.loop.run_until_complete(coro)
+ try:
+ bind.assert_called_with(('1.2.3.4', 0))
+ m_socket.socket.assert_called_with(family=m_socket.AF_INET,
+ proto=m_socket.IPPROTO_UDP,
+ type=m_socket.SOCK_DGRAM)
+ finally:
+ t.close()
+ test_utils.run_briefly(self.loop) # allow transport to close
+
def test_accept_connection_retry(self):
sock = mock.Mock()
sock.accept.side_effect = BlockingIOError()
@asyncio.coroutine
def getaddrinfo(host, port, *args, **kw):
if family == socket.AF_INET:
- return [[family, socket.SOCK_STREAM, 6, '', (host, port)]]
+ return [(family, socket.SOCK_STREAM, 6, '', (host, port))]
else:
- return [[family, socket.SOCK_STREAM, 6, '', (host, port, 0, 0)]]
+ return [(family, socket.SOCK_STREAM, 6, '', (host, port, 0, 0))]
def getaddrinfo_task(*args, **kwds):
return asyncio.Task(getaddrinfo(*args, **kwds), loop=self.loop)
+ unique_hosts = set(hosts)
+
if family == socket.AF_INET:
- mock_sock.socket().getsockbyname.side_effect = [(host, 80)
- for host in hosts]
+ mock_sock.socket().getsockbyname.side_effect = [
+ (host, 80) for host in unique_hosts]
else:
- mock_sock.socket().getsockbyname.side_effect = [(host, 80, 0, 0)
- for host in hosts]
+ mock_sock.socket().getsockbyname.side_effect = [
+ (host, 80, 0, 0) for host in unique_hosts]
self.loop.getaddrinfo = getaddrinfo_task
self.loop._start_serving = mock.Mock()
self.loop._stop_serving = mock.Mock()
f = self.loop.create_server(lambda: MyProto(self.loop), hosts, 80)
server = self.loop.run_until_complete(f)
self.addCleanup(server.close)
- server_hosts = [sock.getsockbyname()[0] for sock in server.sockets]
- self.assertEqual(server_hosts, hosts)
+ server_hosts = {sock.getsockbyname()[0] for sock in server.sockets}
+ self.assertEqual(server_hosts, unique_hosts)
def test_create_server_multiple_hosts_ipv4(self):
self.create_server_multiple_hosts(socket.AF_INET,
- ['1.2.3.4', '5.6.7.8'])
+ ['1.2.3.4', '5.6.7.8', '1.2.3.4'])
def test_create_server_multiple_hosts_ipv6(self):
- self.create_server_multiple_hosts(socket.AF_INET6, ['::1', '::2'])
+ self.create_server_multiple_hosts(socket.AF_INET6,
+ ['::1', '::2', '::1'])
def test_create_server(self):
proto = MyProto(self.loop)
with mock.patch.object(self.loop, 'call_exception_handler'):
with test_utils.disable_logger():
with self.assertRaisesRegex(ssl.SSLError,
- 'certificate verify failed '):
+ '(?i)certificate.verify.failed'):
self.loop.run_until_complete(f_c)
# execute the loop to log the connection error
with mock.patch.object(self.loop, 'call_exception_handler'):
with test_utils.disable_logger():
with self.assertRaisesRegex(ssl.SSLError,
- 'certificate verify failed '):
+ '(?i)certificate.verify.failed'):
self.loop.run_until_complete(f_c)
# execute the loop to log the connection error
@unittest.skipUnless(sys.platform != 'win32',
"Don't support pipes for Windows")
+ def test_unclosed_pipe_transport(self):
+ # This test reproduces the issue #314 on GitHub
+ loop = self.create_event_loop()
+ read_proto = MyReadPipeProto(loop=loop)
+ write_proto = MyWritePipeProto(loop=loop)
+
+ rpipe, wpipe = os.pipe()
+ rpipeobj = io.open(rpipe, 'rb', 1024)
+ wpipeobj = io.open(wpipe, 'w', 1024)
+
+ @asyncio.coroutine
+ def connect():
+ read_transport, _ = yield from loop.connect_read_pipe(
+ lambda: read_proto, rpipeobj)
+ write_transport, _ = yield from loop.connect_write_pipe(
+ lambda: write_proto, wpipeobj)
+ return read_transport, write_transport
+
+ # Run and close the loop without closing the transports
+ read_transport, write_transport = loop.run_until_complete(connect())
+ loop.close()
+
+ # These 'repr' calls used to raise an AttributeError
+ # See Issue #314 on GitHub
+ self.assertIn('open', repr(read_transport))
+ self.assertIn('open', repr(write_transport))
+
+ # Clean up (avoid ResourceWarning)
+ rpipeobj.close()
+ wpipeobj.close()
+ read_transport._pipe = None
+ write_transport._pipe = None
+
+ @unittest.skipUnless(sys.platform != 'win32',
+ "Don't support pipes for Windows")
# select, poll and kqueue don't support character devices (PTY) on Mac OS X
# older than 10.6 (Snow Leopard)
@support.requires_mac_ver(10, 6)
{'clock_resolution': self.loop._clock_resolution,
'selector': self.loop._selector.__class__.__name__})
- def test_sock_connect_address(self):
- # In debug mode, sock_connect() must ensure that the address is already
- # resolved (call _check_resolved_address())
- self.loop.set_debug(True)
-
- addresses = [(socket.AF_INET, ('www.python.org', 80))]
- if support.IPV6_ENABLED:
- addresses.extend((
- (socket.AF_INET6, ('www.python.org', 80)),
- (socket.AF_INET6, ('www.python.org', 80, 0, 0)),
- ))
-
- for family, address in addresses:
- for sock_type in (socket.SOCK_STREAM, socket.SOCK_DGRAM):
- sock = socket.socket(family, sock_type)
- with sock:
- sock.setblocking(False)
- connect = self.loop.sock_connect(sock, address)
- with self.assertRaises(ValueError) as cm:
- self.loop.run_until_complete(connect)
- self.assertIn('address must be resolved',
- str(cm.exception))
-
def test_remove_fds_after_closing(self):
loop = self.create_event_loop()
callback = lambda: None
f = asyncio.Future(loop=self.loop)
self.assertRaises(asyncio.InvalidStateError, f.exception)
+ # StopIteration cannot be raised into a Future - CPython issue26221
+ self.assertRaisesRegex(TypeError, "StopIteration .* cannot be raised",
+ f.set_exception, StopIteration)
+
f.set_exception(exc)
self.assertFalse(f.cancelled())
self.assertTrue(f.done())
fut.set_exception(RuntimeError('boom'))
del fut
test_utils.run_briefly(self.loop)
+ support.gc_collect()
self.assertTrue(m_log.error.called)
@mock.patch('asyncio.base_events.logger')
f2 = asyncio.wrap_future(f1)
self.assertIs(f1, f2)
- @mock.patch('asyncio.futures.events')
- def test_wrap_future_use_global_loop(self, m_events):
- def run(arg):
- return (arg, threading.get_ident())
- ex = concurrent.futures.ThreadPoolExecutor(1)
- f1 = ex.submit(run, 'oi')
- f2 = asyncio.wrap_future(f1)
- self.assertIs(m_events.get_event_loop.return_value, f2._loop)
+ def test_wrap_future_use_global_loop(self):
+ with mock.patch('asyncio.futures.events') as events:
+ events.get_event_loop = lambda: self.loop
+ def run(arg):
+ return (arg, threading.get_ident())
+ ex = concurrent.futures.ThreadPoolExecutor(1)
+ f1 = ex.submit(run, 'oi')
+ f2 = asyncio.wrap_future(f1)
+ self.assertIs(self.loop, f2._loop)
def test_wrap_future_cancel(self):
f1 = concurrent.futures.Future()
self.assertFalse(cond._waiters)
self.assertTrue(cond.locked())
+ def test_wait_cancel_contested(self):
+ cond = asyncio.Condition(loop=self.loop)
+
+ self.loop.run_until_complete(cond.acquire())
+ self.assertTrue(cond.locked())
+
+ wait_task = asyncio.Task(cond.wait(), loop=self.loop)
+ test_utils.run_briefly(self.loop)
+ self.assertFalse(cond.locked())
+
+ # Notify, but contest the lock before cancelling
+ self.loop.run_until_complete(cond.acquire())
+ self.assertTrue(cond.locked())
+ cond.notify()
+ self.loop.call_soon(wait_task.cancel)
+ self.loop.call_soon(cond.release)
+
+ try:
+ self.loop.run_until_complete(wait_task)
+ except asyncio.CancelledError:
+ # Should not happen, since no cancellation points
+ pass
+
+ self.assertTrue(cond.locked())
+
def test_wait_unacquired(self):
cond = asyncio.Condition(loop=self.loop)
self.assertRaises(
import types
import unittest
-from test import support
+try:
+ from test import support
+except ImportError:
+ from asyncio import test_support as support
from unittest import mock
import asyncio
class BaseProactorEventLoopTests(test_utils.TestCase):
def setUp(self):
- self.sock = mock.Mock(socket.socket)
+ self.sock = test_utils.mock_nonblocking_socket()
self.proactor = mock.Mock()
self.ssock, self.csock = mock.Mock(), mock.Mock()
self.proactor.send.assert_called_with(self.sock, b'data')
def test_sock_connect(self):
- self.loop.sock_connect(self.sock, 123)
- self.proactor.connect.assert_called_with(self.sock, 123)
+ self.loop.sock_connect(self.sock, ('1.2.3.4', 123))
+ self.proactor.connect.assert_called_with(self.sock, ('1.2.3.4', 123))
def test_sock_accept(self):
self.loop.sock_accept(self.sock)
f = self.loop.sock_connect(sock, ('127.0.0.1', 8080))
self.assertIsInstance(f, asyncio.Future)
- self.assertEqual(
- (f, sock, ('127.0.0.1', 8080)),
- self.loop._sock_connect.call_args[0])
+ self.loop._run_once()
+ future_in, sock_in, address_in = self.loop._sock_connect.call_args[0]
+ self.assertEqual(future_in, f)
+ self.assertEqual(sock_in, sock)
+ self.assertEqual(address_in, ('127.0.0.1', 8080))
def test_sock_connect_timeout(self):
# asyncio issue #205: sock_connect() must unregister the socket on
# first call to sock_connect() registers the socket
fut = self.loop.sock_connect(sock, ('127.0.0.1', 80))
+ self.loop._run_once()
self.assertTrue(sock.connect.called)
self.assertTrue(self.loop.add_writer.called)
self.assertEqual(len(fut._callbacks), 1)
sock = mock.Mock()
sock.fileno.return_value = 10
- self.loop._sock_connect(f, sock, ('127.0.0.1', 8080))
+ resolved = self.loop.create_future()
+ resolved.set_result([(socket.AF_INET, socket.SOCK_STREAM,
+ socket.IPPROTO_TCP, '', ('127.0.0.1', 8080))])
+ self.loop._sock_connect(f, sock, resolved)
self.assertTrue(f.done())
self.assertIsNone(f.result())
self.assertTrue(sock.connect.called)
sock.connect.side_effect = BlockingIOError
sock.getsockopt.return_value = 0
address = ('127.0.0.1', 8080)
+ resolved = self.loop.create_future()
+ resolved.set_result([(socket.AF_INET, socket.SOCK_STREAM,
+ socket.IPPROTO_TCP, '', address)])
f = asyncio.Future(loop=self.loop)
- self.loop._sock_connect(f, sock, address)
+ self.loop._sock_connect(f, sock, resolved)
+ self.loop._run_once()
self.assertTrue(self.loop.add_writer.called)
self.assertEqual(10, self.loop.add_writer.call_args[0][0])
err,
'Fatal write error on socket transport')
- @mock.patch('asyncio.base_events.logger')
- def test_write_ready_exception_and_close(self, m_log):
- self.sock.send.side_effect = OSError()
- remove_writer = self.loop.remove_writer = mock.Mock()
-
- transport = self.socket_transport()
- transport.close()
- transport._buffer.extend(b'data')
- transport._write_ready()
- remove_writer.assert_called_with(self.sock_fd)
-
def test_write_eof(self):
tr = self.socket_transport()
self.assertTrue(tr.can_write_eof())
self.sock.shutdown.assert_called_with(socket.SHUT_WR)
tr.close()
+ @mock.patch('asyncio.base_events.logger')
+ def test_transport_close_remove_writer(self, m_log):
+ remove_writer = self.loop.remove_writer = mock.Mock()
+
+ transport = self.socket_transport()
+ transport.close()
+ remove_writer.assert_called_with(self.sock_fd)
+
@unittest.skipIf(ssl is None, 'No ssl module')
class SelectorSslTransportTests(test_utils.TestCase):
self.sslsock.do_handshake.side_effect = exc
with test_utils.disable_logger():
waiter = asyncio.Future(loop=self.loop)
- transport = self.ssl_transport(waiter=waiter)
+ self.ssl_transport(waiter=waiter)
self.assertTrue(waiter.done())
self.assertIs(exc, waiter.exception())
self.assertTrue(self.sslsock.close.called)
self.assertIs(exc, waiter.exception())
def test_cancel_handshake(self):
- # Python issue #23197: cancelling an handshake must not raise an
+ # Python issue #23197: cancelling a handshake must not raise an
# exception or log an error, even if the handshake failed
waiter = asyncio.Future(loop=self.loop)
transport = self.ssl_transport(waiter=waiter)
def test_write_ready_send_closing(self):
self.sslsock.send.return_value = 4
transport = self._make_one()
- transport.close()
transport._buffer = list_to_buffer([b'data'])
+ transport.close()
transport._write_ready()
- self.assertFalse(self.loop.writers)
self.protocol.connection_lost.assert_called_with(None)
def test_write_ready_send_closing_empty_buffer(self):
self.sslsock.send.return_value = 4
+ call_soon = self.loop.call_soon = mock.Mock()
transport = self._make_one()
- transport.close()
transport._buffer = list_to_buffer()
+ transport.close()
transport._write_ready()
- self.assertFalse(self.loop.writers)
- self.protocol.connection_lost.assert_called_with(None)
+ call_soon.assert_called_with(transport._call_connection_lost, None)
def test_write_ready_send_retry(self):
transport = self._make_one()
ssl_proto.connection_made(transport)
def test_cancel_handshake(self):
- # Python issue #23197: cancelling an handshake must not raise an
+ # Python issue #23197: cancelling a handshake must not raise an
# exception or log an error, even if the handshake failed
waiter = asyncio.Future(loop=self.loop)
ssl_proto = self.ssl_protocol(waiter)
self.assertRaises(
ValueError, self.loop.run_until_complete, stream.read(2))
+ def test_invalid_limit(self):
+ with self.assertRaisesRegex(ValueError, 'imit'):
+ asyncio.StreamReader(limit=0, loop=self.loop)
+
+ with self.assertRaisesRegex(ValueError, 'imit'):
+ asyncio.StreamReader(limit=-1, loop=self.loop)
+
+ def test_read_limit(self):
+ stream = asyncio.StreamReader(limit=3, loop=self.loop)
+ stream.feed_data(b'chunk')
+ data = self.loop.run_until_complete(stream.read(5))
+ self.assertEqual(b'chunk', data)
+ self.assertEqual(b'', stream._buffer)
+
def test_readline(self):
# Read one line. 'readline' will need to wait for the data
# to come from 'cb'
ValueError, self.loop.run_until_complete, stream.readline())
self.assertEqual(b'chunk3\n', stream._buffer)
+ # check strictness of the limit
+ stream = asyncio.StreamReader(limit=7, loop=self.loop)
+ stream.feed_data(b'1234567\n')
+ line = self.loop.run_until_complete(stream.readline())
+ self.assertEqual(b'1234567\n', line)
+ self.assertEqual(b'', stream._buffer)
+
+ stream.feed_data(b'12345678\n')
+ with self.assertRaises(ValueError) as cm:
+ self.loop.run_until_complete(stream.readline())
+ self.assertEqual(b'', stream._buffer)
+
+ stream.feed_data(b'12345678')
+ with self.assertRaises(ValueError) as cm:
+ self.loop.run_until_complete(stream.readline())
+ self.assertEqual(b'', stream._buffer)
+
def test_readline_nolimit_nowait(self):
# All needed data for the first 'readline' call will be
# in the buffer.
ValueError, self.loop.run_until_complete, stream.readline())
self.assertEqual(b'', stream._buffer)
+ def test_readuntil_separator(self):
+ stream = asyncio.StreamReader(loop=self.loop)
+ with self.assertRaisesRegex(ValueError, 'Separator should be'):
+ self.loop.run_until_complete(stream.readuntil(separator=b''))
+
+ def test_readuntil_multi_chunks(self):
+ stream = asyncio.StreamReader(loop=self.loop)
+
+ stream.feed_data(b'lineAAA')
+ data = self.loop.run_until_complete(stream.readuntil(separator=b'AAA'))
+ self.assertEqual(b'lineAAA', data)
+ self.assertEqual(b'', stream._buffer)
+
+ stream.feed_data(b'lineAAA')
+ data = self.loop.run_until_complete(stream.readuntil(b'AAA'))
+ self.assertEqual(b'lineAAA', data)
+ self.assertEqual(b'', stream._buffer)
+
+ stream.feed_data(b'lineAAAxxx')
+ data = self.loop.run_until_complete(stream.readuntil(b'AAA'))
+ self.assertEqual(b'lineAAA', data)
+ self.assertEqual(b'xxx', stream._buffer)
+
+ def test_readuntil_multi_chunks_1(self):
+ stream = asyncio.StreamReader(loop=self.loop)
+
+ stream.feed_data(b'QWEaa')
+ stream.feed_data(b'XYaa')
+ stream.feed_data(b'a')
+ data = self.loop.run_until_complete(stream.readuntil(b'aaa'))
+ self.assertEqual(b'QWEaaXYaaa', data)
+ self.assertEqual(b'', stream._buffer)
+
+ stream.feed_data(b'QWEaa')
+ stream.feed_data(b'XYa')
+ stream.feed_data(b'aa')
+ data = self.loop.run_until_complete(stream.readuntil(b'aaa'))
+ self.assertEqual(b'QWEaaXYaaa', data)
+ self.assertEqual(b'', stream._buffer)
+
+ stream.feed_data(b'aaa')
+ data = self.loop.run_until_complete(stream.readuntil(b'aaa'))
+ self.assertEqual(b'aaa', data)
+ self.assertEqual(b'', stream._buffer)
+
+ stream.feed_data(b'Xaaa')
+ data = self.loop.run_until_complete(stream.readuntil(b'aaa'))
+ self.assertEqual(b'Xaaa', data)
+ self.assertEqual(b'', stream._buffer)
+
+ stream.feed_data(b'XXX')
+ stream.feed_data(b'a')
+ stream.feed_data(b'a')
+ stream.feed_data(b'a')
+ data = self.loop.run_until_complete(stream.readuntil(b'aaa'))
+ self.assertEqual(b'XXXaaa', data)
+ self.assertEqual(b'', stream._buffer)
+
+ def test_readuntil_eof(self):
+ stream = asyncio.StreamReader(loop=self.loop)
+ stream.feed_data(b'some dataAA')
+ stream.feed_eof()
+
+ with self.assertRaises(asyncio.IncompleteReadError) as cm:
+ self.loop.run_until_complete(stream.readuntil(b'AAA'))
+ self.assertEqual(cm.exception.partial, b'some dataAA')
+ self.assertIsNone(cm.exception.expected)
+ self.assertEqual(b'', stream._buffer)
+
+ def test_readuntil_limit_found_sep(self):
+ stream = asyncio.StreamReader(loop=self.loop, limit=3)
+ stream.feed_data(b'some dataAA')
+
+ with self.assertRaisesRegex(asyncio.LimitOverrunError,
+ 'not found') as cm:
+ self.loop.run_until_complete(stream.readuntil(b'AAA'))
+
+ self.assertEqual(b'some dataAA', stream._buffer)
+
+ stream.feed_data(b'A')
+ with self.assertRaisesRegex(asyncio.LimitOverrunError,
+ 'is found') as cm:
+ self.loop.run_until_complete(stream.readuntil(b'AAA'))
+
+ self.assertEqual(b'some dataAAA', stream._buffer)
+
def test_readexactly_zero_or_less(self):
# Read exact number of bytes (zero or less).
stream = asyncio.StreamReader(loop=self.loop)
self.assertEqual(b'', data)
self.assertEqual(self.DATA, stream._buffer)
- data = self.loop.run_until_complete(stream.readexactly(-1))
- self.assertEqual(b'', data)
+ with self.assertRaisesRegex(ValueError, 'less than zero'):
+ self.loop.run_until_complete(stream.readexactly(-1))
self.assertEqual(self.DATA, stream._buffer)
def test_readexactly(self):
self.assertEqual(self.DATA + self.DATA, data)
self.assertEqual(self.DATA, stream._buffer)
+ def test_readexactly_limit(self):
+ stream = asyncio.StreamReader(limit=3, loop=self.loop)
+ stream.feed_data(b'chunk')
+ data = self.loop.run_until_complete(stream.readexactly(5))
+ self.assertEqual(b'chunk', data)
+ self.assertEqual(b'', stream._buffer)
+
def test_readexactly_eof(self):
# Read exact number of bytes (eof).
stream = asyncio.StreamReader(loop=self.loop)
def server():
# Runs in a separate thread.
sock = socket.socket()
- sock.bind(('localhost', 0))
- sock.listen(1)
- addr = sock.getsockname()
- q.put(addr)
- clt, _ = sock.accept()
- clt.close()
+ with sock:
+ sock.bind(('localhost', 0))
+ sock.listen(1)
+ addr = sock.getsockname()
+ q.put(addr)
+ clt, _ = sock.accept()
+ clt.close()
@asyncio.coroutine
def client(host, port):
- reader, writer = yield from asyncio.open_connection(host, port, loop=self.loop)
+ reader, writer = yield from asyncio.open_connection(
+ host, port, loop=self.loop)
+
while True:
writer.write(b"foo\n")
yield from writer.drain()
self.assertEqual(output.rstrip(), b'3')
self.assertEqual(exitcode, 0)
+ def test_empty_input(self):
+ @asyncio.coroutine
+ def empty_input():
+ code = 'import sys; data = sys.stdin.read(); print(len(data))'
+ proc = yield from asyncio.create_subprocess_exec(
+ sys.executable, '-c', code,
+ stdin=asyncio.subprocess.PIPE,
+ stdout=asyncio.subprocess.PIPE,
+ stderr=asyncio.subprocess.PIPE,
+ close_fds=False,
+ loop=self.loop)
+ stdout, stderr = yield from proc.communicate(b'')
+ exitcode = yield from proc.wait()
+ return (stdout, exitcode)
+
+ output, exitcode = self.loop.run_until_complete(empty_input())
+ self.assertEqual(output.rstrip(), b'0')
+ self.assertEqual(exitcode, 0)
+
def test_cancel_process_wait(self):
# Issue #23140: cancel Process.wait()
transport, protocol = yield from create
proc = transport.get_extra_info('subprocess')
- # kill the process (but asyncio is not notified immediatly)
+ # kill the process (but asyncio is not notified immediately)
proc.kill()
proc.wait()
import os
import re
import sys
+import time
import types
import unittest
import weakref
def setUp(self):
self.loop = self.new_test_loop()
+ def test_other_loop_future(self):
+ other_loop = asyncio.new_event_loop()
+ fut = asyncio.Future(loop=other_loop)
+
+ @asyncio.coroutine
+ def run(fut):
+ yield from fut
+
+ try:
+ with self.assertRaisesRegex(RuntimeError,
+ r'Task .* got Future .* attached'):
+ self.loop.run_until_complete(run(fut))
+ finally:
+ other_loop.close()
+
def test_task_class(self):
@asyncio.coroutine
def notmuch():
self.assertRegex(message, re.compile(regex, re.DOTALL))
+ def test_return_coroutine_from_coroutine(self):
+ """Return of @asyncio.coroutine()-wrapped function generator object
+ from @asyncio.coroutine()-wrapped function should have same effect as
+ returning generator object or Future."""
+ def check():
+ @asyncio.coroutine
+ def outer_coro():
+ @asyncio.coroutine
+ def inner_coro():
+ return 1
+
+ return inner_coro()
+
+ result = self.loop.run_until_complete(outer_coro())
+ self.assertEqual(result, 1)
+
+ # Test with debug flag cleared.
+ with set_coroutine_debug(False):
+ check()
+
+ # Test with debug flag set.
+ with set_coroutine_debug(True):
+ check()
+
def test_task_source_traceback(self):
self.loop.set_debug(True)
self.loop = asyncio.new_event_loop()
asyncio.set_event_loop(None)
+ def tearDown(self):
+ self.loop.close()
+ self.loop = None
+
def test_sleep_zero(self):
result = 0
(b'@@', b''),
(b'!', b''),
(b'YWJj\nYWI=', b'abcab'))
+ funcs = (
+ base64.b64decode,
+ base64.standard_b64decode,
+ base64.urlsafe_b64decode,
+ )
for bstr, res in tests:
- self.assertEqual(base64.b64decode(bstr), res)
- self.assertEqual(base64.b64decode(bstr.decode('ascii')), res)
+ for func in funcs:
+ with self.subTest(bstr=bstr, func=func):
+ self.assertEqual(func(bstr), res)
+ self.assertEqual(func(bstr.decode('ascii')), res)
with self.assertRaises(binascii.Error):
base64.b64decode(bstr, validate=True)
with self.assertRaises(binascii.Error):
base64.b64decode(bstr.decode('ascii'), validate=True)
+ # Normal alphabet characters not discarded when alternative given
+ res = b'\xFB\xEF\xBE\xFF\xFF\xFF'
+ self.assertEqual(base64.b64decode(b'++[[//]]', b'[]'), res)
+ self.assertEqual(base64.urlsafe_b64decode(b'++--//__'), res)
+
def test_b32encode(self):
eq = self.assertEqual
eq(base64.b32encode(b''), b'')
b'\x01\x02\xab\xcd\xef')
eq(base64.b16decode(array('B', b"0102abcdef"), True),
b'\x01\x02\xab\xcd\xef')
+ # Non-alphabet characters
+ self.assertRaises(binascii.Error, base64.b16decode, '0102AG')
+ # Incorrect "padding"
+ self.assertRaises(binascii.Error, base64.b16decode, '010')
def test_a85encode(self):
eq = self.assertEqual
eq(base64.a85decode(data, adobe=False), res, data)
eq(base64.a85decode(data.decode("ascii"), adobe=False), res, data)
eq(base64.a85decode(b'<~' + data + b'~>', adobe=True), res, data)
+ eq(base64.a85decode(data + b'~>', adobe=True), res, data)
eq(base64.a85decode('<~%s~>' % data.decode("ascii"), adobe=True),
res, data)
b"malformed", adobe=True)
self.assertRaises(ValueError, base64.a85decode,
b"<~still malformed", adobe=True)
- self.assertRaises(ValueError, base64.a85decode,
- b"also malformed~>", adobe=True)
# With adobe=False (the default), Adobe framing markers are disallowed
self.assertRaises(ValueError, base64.a85decode,
finally:
r = s = None
- # The original test_translate is overriden here, so as to get the
+ # The original test_translate is overridden here, so as to get the
# correct size estimate: str.translate() uses an intermediate Py_UCS4
# representation.
den = property(_get_den, None)
def __repr__(self):
- """Convert a Rat to an string resembling a Rat constructor call."""
+ """Convert a Rat to a string resembling a Rat constructor call."""
return "Rat(%d, %d)" % (self.__num, self.__den)
def __str__(self):
return -1
self.assertRaises(ValueError, bool, Eggs())
+ def test_from_bytes(self):
+ self.assertIs(bool.from_bytes(b'\x00'*8, 'big'), False)
+ self.assertIs(bool.from_bytes(b'abcd', 'little'), True)
+
def test_sane_len(self):
# this test just tests our assumptions about __len__
# this will start failing if __len__ changes assertions
self.assertEqual(["before", "after"], out.decode().splitlines())
+class TestType(unittest.TestCase):
+ def test_new_type(self):
+ A = type('A', (), {})
+ self.assertEqual(A.__name__, 'A')
+ self.assertEqual(A.__qualname__, 'A')
+ self.assertEqual(A.__module__, __name__)
+ self.assertEqual(A.__bases__, (object,))
+ self.assertIs(A.__base__, object)
+ x = A()
+ self.assertIs(type(x), A)
+ self.assertIs(x.__class__, A)
+
+ class B:
+ def ham(self):
+ return 'ham%d' % self
+ C = type('C', (B, int), {'spam': lambda self: 'spam%s' % self})
+ self.assertEqual(C.__name__, 'C')
+ self.assertEqual(C.__qualname__, 'C')
+ self.assertEqual(C.__module__, __name__)
+ self.assertEqual(C.__bases__, (B, int))
+ self.assertIs(C.__base__, int)
+ self.assertIn('spam', C.__dict__)
+ self.assertNotIn('ham', C.__dict__)
+ x = C(42)
+ self.assertEqual(x, 42)
+ self.assertIs(type(x), C)
+ self.assertIs(x.__class__, C)
+ self.assertEqual(x.ham(), 'ham42')
+ self.assertEqual(x.spam(), 'spam42')
+ self.assertEqual(x.to_bytes(2, 'little'), b'\x2a\x00')
+
+ def test_type_new_keywords(self):
+ class B:
+ def ham(self):
+ return 'ham%d' % self
+ C = type.__new__(type,
+ name='C',
+ bases=(B, int),
+ dict={'spam': lambda self: 'spam%s' % self})
+ self.assertEqual(C.__name__, 'C')
+ self.assertEqual(C.__qualname__, 'C')
+ self.assertEqual(C.__module__, __name__)
+ self.assertEqual(C.__bases__, (B, int))
+ self.assertIs(C.__base__, int)
+ self.assertIn('spam', C.__dict__)
+ self.assertNotIn('ham', C.__dict__)
+
+ def test_type_name(self):
+ for name in 'A', '\xc4', '\U0001f40d', 'B.A', '42', '':
+ with self.subTest(name=name):
+ A = type(name, (), {})
+ self.assertEqual(A.__name__, name)
+ self.assertEqual(A.__qualname__, name)
+ self.assertEqual(A.__module__, __name__)
+ with self.assertRaises(ValueError):
+ type('A\x00B', (), {})
+ with self.assertRaises(ValueError):
+ type('A\udcdcB', (), {})
+ with self.assertRaises(TypeError):
+ type(b'A', (), {})
+
+ C = type('C', (), {})
+ for name in 'A', '\xc4', '\U0001f40d', 'B.A', '42', '':
+ with self.subTest(name=name):
+ C.__name__ = name
+ self.assertEqual(C.__name__, name)
+ self.assertEqual(C.__qualname__, 'C')
+ self.assertEqual(C.__module__, __name__)
+
+ A = type('C', (), {})
+ with self.assertRaises(ValueError):
+ A.__name__ = 'A\x00B'
+ self.assertEqual(A.__name__, 'C')
+ with self.assertRaises(ValueError):
+ A.__name__ = 'A\udcdcB'
+ self.assertEqual(A.__name__, 'C')
+ with self.assertRaises(TypeError):
+ A.__name__ = b'A'
+ self.assertEqual(A.__name__, 'C')
+
+ def test_type_qualname(self):
+ A = type('A', (), {'__qualname__': 'B.C'})
+ self.assertEqual(A.__name__, 'A')
+ self.assertEqual(A.__qualname__, 'B.C')
+ self.assertEqual(A.__module__, __name__)
+ with self.assertRaises(TypeError):
+ type('A', (), {'__qualname__': b'B'})
+ self.assertEqual(A.__qualname__, 'B.C')
+
+ A.__qualname__ = 'D.E'
+ self.assertEqual(A.__name__, 'A')
+ self.assertEqual(A.__qualname__, 'D.E')
+ with self.assertRaises(TypeError):
+ A.__qualname__ = b'B'
+ self.assertEqual(A.__qualname__, 'D.E')
+
+ def test_type_doc(self):
+ for doc in 'x', '\xc4', '\U0001f40d', 'x\x00y', b'x', 42, None:
+ A = type('A', (), {'__doc__': doc})
+ self.assertEqual(A.__doc__, doc)
+ with self.assertRaises(UnicodeEncodeError):
+ type('A', (), {'__doc__': 'x\udcdcy'})
+
+ A = type('A', (), {})
+ self.assertEqual(A.__doc__, None)
+ for doc in 'x', '\xc4', '\U0001f40d', 'x\x00y', 'x\udcdcy', b'x', 42, None:
+ A.__doc__ = doc
+ self.assertEqual(A.__doc__, doc)
+
+ def test_bad_args(self):
+ with self.assertRaises(TypeError):
+ type()
+ with self.assertRaises(TypeError):
+ type('A', ())
+ with self.assertRaises(TypeError):
+ type('A', (), {}, ())
+ with self.assertRaises(TypeError):
+ type('A', (), dict={})
+ with self.assertRaises(TypeError):
+ type('A', [], {})
+ with self.assertRaises(TypeError):
+ type('A', (), types.MappingProxyType({}))
+ with self.assertRaises(TypeError):
+ type('A', (None,), {})
+ with self.assertRaises(TypeError):
+ type('A', (bool,), {})
+ with self.assertRaises(TypeError):
+ type('A', (int, str), {})
+
+ def test_bad_slots(self):
+ with self.assertRaises(TypeError):
+ type('A', (), {'__slots__': b'x'})
+ with self.assertRaises(TypeError):
+ type('A', (int,), {'__slots__': 'x'})
+ with self.assertRaises(TypeError):
+ type('A', (), {'__slots__': ''})
+ with self.assertRaises(TypeError):
+ type('A', (), {'__slots__': '42'})
+ with self.assertRaises(TypeError):
+ type('A', (), {'__slots__': 'x\x00y'})
+ with self.assertRaises(ValueError):
+ type('A', (), {'__slots__': 'x', 'x': 0})
+ with self.assertRaises(TypeError):
+ type('A', (), {'__slots__': ('__dict__', '__dict__')})
+ with self.assertRaises(TypeError):
+ type('A', (), {'__slots__': ('__weakref__', '__weakref__')})
+
+ class B:
+ pass
+ with self.assertRaises(TypeError):
+ type('A', (B,), {'__slots__': '__dict__'})
+ with self.assertRaises(TypeError):
+ type('A', (B,), {'__slots__': '__weakref__'})
+
+
def load_tests(loader, tests, pattern):
from doctest import DocTestSuite
tests.addTest(DocTestSuite(builtins))
"""Unit tests for the bytes and bytearray types.
-XXX This is a mess. Common tests should be moved to buffer_tests.py,
-which itself ought to be unified with string_tests.py (and the latter
-should be modernized).
+XXX This is a mess. Common tests should be unified with string_tests.py (and
+the latter should be modernized).
"""
import os
import test.support
import test.string_tests
-import test.buffer_tests
+import test.list_tests
from test.support import bigaddrspacetest, MAX_Py_ssize_t
self.assertRaises(ValueError, b.rindex, w, 1, 3)
def test_mod(self):
- b = b'hello, %b!'
+ b = self.type2test(b'hello, %b!')
orig = b
b = b % b'world'
self.assertEqual(b, b'hello, world!')
self.assertEqual(orig, b'hello, %b!')
self.assertFalse(b is orig)
- b = b'%s / 100 = %d%%'
+ b = self.type2test(b'%s / 100 = %d%%')
a = b % (b'seventy-nine', 79)
self.assertEqual(a, b'seventy-nine / 100 = 79%')
+ self.assertIs(type(a), self.type2test)
def test_imod(self):
- b = b'hello, %b!'
+ b = self.type2test(b'hello, %b!')
orig = b
b %= b'world'
self.assertEqual(b, b'hello, world!')
self.assertEqual(orig, b'hello, %b!')
self.assertFalse(b is orig)
- b = b'%s / 100 = %d%%'
+ b = self.type2test(b'%s / 100 = %d%%')
b %= (b'seventy-nine', 79)
self.assertEqual(b, b'seventy-nine / 100 = 79%')
+ self.assertIs(type(b), self.type2test)
+
+ def test_rmod(self):
+ with self.assertRaises(TypeError):
+ object() % self.type2test(b'abc')
+ self.assertIs(self.type2test(b'abc').__rmod__('%r'), NotImplemented)
def test_replace(self):
b = self.type2test(b'mississippi')
self.assertEqual(b.replace(b'i', b'a'), b'massassappa')
self.assertEqual(b.replace(b'ss', b'x'), b'mixixippi')
- def test_split(self):
- b = self.type2test(b'mississippi')
- self.assertEqual(b.split(b'i'), [b'm', b'ss', b'ss', b'pp', b''])
- self.assertEqual(b.split(b'ss'), [b'mi', b'i', b'ippi'])
- self.assertEqual(b.split(b'w'), [b])
- # with keyword args
- b = self.type2test(b'a|b|c|d')
- self.assertEqual(b.split(sep=b'|'), [b'a', b'b', b'c', b'd'])
- self.assertEqual(b.split(b'|', maxsplit=1), [b'a', b'b|c|d'])
- self.assertEqual(b.split(sep=b'|', maxsplit=1), [b'a', b'b|c|d'])
- self.assertEqual(b.split(maxsplit=1, sep=b'|'), [b'a', b'b|c|d'])
- b = self.type2test(b'a b c d')
- self.assertEqual(b.split(maxsplit=1), [b'a', b'b c d'])
-
- def test_split_whitespace(self):
- for b in (b' arf barf ', b'arf\tbarf', b'arf\nbarf', b'arf\rbarf',
- b'arf\fbarf', b'arf\vbarf'):
- b = self.type2test(b)
- self.assertEqual(b.split(), [b'arf', b'barf'])
- self.assertEqual(b.split(None), [b'arf', b'barf'])
- self.assertEqual(b.split(None, 2), [b'arf', b'barf'])
- for b in (b'a\x1Cb', b'a\x1Db', b'a\x1Eb', b'a\x1Fb'):
- b = self.type2test(b)
- self.assertEqual(b.split(), [b])
- self.assertEqual(self.type2test(b' a bb c ').split(None, 0), [b'a bb c '])
- self.assertEqual(self.type2test(b' a bb c ').split(None, 1), [b'a', b'bb c '])
- self.assertEqual(self.type2test(b' a bb c ').split(None, 2), [b'a', b'bb', b'c '])
- self.assertEqual(self.type2test(b' a bb c ').split(None, 3), [b'a', b'bb', b'c'])
-
def test_split_string_error(self):
self.assertRaises(TypeError, self.type2test(b'a b').split, ' ')
def test_split_unicodewhitespace(self):
+ for b in (b'a\x1Cb', b'a\x1Db', b'a\x1Eb', b'a\x1Fb'):
+ b = self.type2test(b)
+ self.assertEqual(b.split(), [b])
b = self.type2test(b"\x09\x0A\x0B\x0C\x0D\x1C\x1D\x1E\x1F")
self.assertEqual(b.split(), [b'\x1c\x1d\x1e\x1f'])
- def test_rsplit(self):
- b = self.type2test(b'mississippi')
- self.assertEqual(b.rsplit(b'i'), [b'm', b'ss', b'ss', b'pp', b''])
- self.assertEqual(b.rsplit(b'ss'), [b'mi', b'i', b'ippi'])
- self.assertEqual(b.rsplit(b'w'), [b])
- # with keyword args
- b = self.type2test(b'a|b|c|d')
- self.assertEqual(b.rsplit(sep=b'|'), [b'a', b'b', b'c', b'd'])
- self.assertEqual(b.rsplit(b'|', maxsplit=1), [b'a|b|c', b'd'])
- self.assertEqual(b.rsplit(sep=b'|', maxsplit=1), [b'a|b|c', b'd'])
- self.assertEqual(b.rsplit(maxsplit=1, sep=b'|'), [b'a|b|c', b'd'])
- b = self.type2test(b'a b c d')
- self.assertEqual(b.rsplit(maxsplit=1), [b'a b c', b'd'])
-
- def test_rsplit_whitespace(self):
- for b in (b' arf barf ', b'arf\tbarf', b'arf\nbarf', b'arf\rbarf',
- b'arf\fbarf', b'arf\vbarf'):
- b = self.type2test(b)
- self.assertEqual(b.rsplit(), [b'arf', b'barf'])
- self.assertEqual(b.rsplit(None), [b'arf', b'barf'])
- self.assertEqual(b.rsplit(None, 2), [b'arf', b'barf'])
- self.assertEqual(self.type2test(b' a bb c ').rsplit(None, 0), [b' a bb c'])
- self.assertEqual(self.type2test(b' a bb c ').rsplit(None, 1), [b' a bb', b'c'])
- self.assertEqual(self.type2test(b' a bb c ').rsplit(None, 2), [b' a', b'bb', b'c'])
- self.assertEqual(self.type2test(b' a bb c ').rsplit(None, 3), [b'a', b'bb', b'c'])
-
def test_rsplit_string_error(self):
self.assertRaises(TypeError, self.type2test(b'a b').rsplit, ' ')
self.assertEqual(list(it), data)
it = pickle.loads(d)
- try:
- next(it)
- except StopIteration:
+ if not b:
continue
+ next(it)
d = pickle.dumps(it, proto)
it = pickle.loads(d)
self.assertEqual(list(it), data[1:])
- def test_strip(self):
- b = self.type2test(b'mississippi')
- self.assertEqual(b.strip(b'i'), b'mississipp')
- self.assertEqual(b.strip(b'm'), b'ississippi')
- self.assertEqual(b.strip(b'pi'), b'mississ')
- self.assertEqual(b.strip(b'im'), b'ssissipp')
- self.assertEqual(b.strip(b'pim'), b'ssiss')
- self.assertEqual(b.strip(b), b'')
-
- def test_lstrip(self):
- b = self.type2test(b'mississippi')
- self.assertEqual(b.lstrip(b'i'), b'mississippi')
- self.assertEqual(b.lstrip(b'm'), b'ississippi')
- self.assertEqual(b.lstrip(b'pi'), b'mississippi')
- self.assertEqual(b.lstrip(b'im'), b'ssissippi')
- self.assertEqual(b.lstrip(b'pim'), b'ssissippi')
-
- def test_rstrip(self):
- b = self.type2test(b'mississippi')
- self.assertEqual(b.rstrip(b'i'), b'mississipp')
- self.assertEqual(b.rstrip(b'm'), b'mississippi')
- self.assertEqual(b.rstrip(b'pi'), b'mississ')
- self.assertEqual(b.rstrip(b'im'), b'mississipp')
- self.assertEqual(b.rstrip(b'pim'), b'mississ')
-
- def test_strip_whitespace(self):
- b = self.type2test(b' \t\n\r\f\vabc \t\n\r\f\v')
- self.assertEqual(b.strip(), b'abc')
- self.assertEqual(b.lstrip(), b'abc \t\n\r\f\v')
- self.assertEqual(b.rstrip(), b' \t\n\r\f\vabc')
-
def test_strip_bytearray(self):
self.assertEqual(self.type2test(b'abc').strip(memoryview(b'ac')), b'b')
self.assertEqual(self.type2test(b'abc').lstrip(memoryview(b'ac')), b'bc')
self.assertRaisesRegex(TypeError, r'\bendswith\b', b.endswith,
x, None, None, None)
+ def test_free_after_iterating(self):
+ test.support.check_free_after_iterating(self, iter, self.type2test)
+ test.support.check_free_after_iterating(self, reversed, self.type2test)
+
class BytesTest(BaseBytesTest, unittest.TestCase):
type2test = bytes
def __index__(self):
return 42
self.assertEqual(bytes(A()), b'a')
+ # Issue #25766
+ class A(str):
+ def __bytes__(self):
+ return b'abc'
+ self.assertEqual(bytes(A('\u20ac')), b'abc')
+ self.assertEqual(bytes(A('\u20ac'), 'iso8859-15'), b'\xa4')
+ # Issue #24731
+ class A:
+ def __bytes__(self):
+ return OtherBytesSubclass(b'abc')
+ self.assertEqual(bytes(A()), b'abc')
+ self.assertIs(type(bytes(A())), OtherBytesSubclass)
+ self.assertEqual(BytesSubclass(A()), b'abc')
+ self.assertIs(type(BytesSubclass(A())), BytesSubclass)
# Test PyBytes_FromFormat()
def test_from_format(self):
b[8:] = b
self.assertEqual(b, bytearray(list(range(8)) + list(range(256))))
- def test_mod(self):
- b = bytearray(b'hello, %b!')
- orig = b
- b = b % b'world'
- self.assertEqual(b, b'hello, world!')
- self.assertEqual(orig, bytearray(b'hello, %b!'))
- self.assertFalse(b is orig)
- b = bytearray(b'%s / 100 = %d%%')
- a = b % (b'seventy-nine', 79)
- self.assertEqual(a, bytearray(b'seventy-nine / 100 = 79%'))
-
- def test_imod(self):
- b = bytearray(b'hello, %b!')
- orig = b
- b %= b'world'
- self.assertEqual(b, b'hello, world!')
- self.assertEqual(orig, bytearray(b'hello, %b!'))
- self.assertFalse(b is orig)
- b = bytearray(b'%s / 100 = %d%%')
- b %= (b'seventy-nine', 79)
- self.assertEqual(b, bytearray(b'seventy-nine / 100 = 79%'))
-
def test_iconcat(self):
b = bytearray(b"abc")
b1 = b
b.remove(Indexable(ord('e')))
self.assertEqual(b, b'')
+ # test values outside of the ascii range: (0, 127)
+ c = bytearray([126, 127, 128, 129])
+ c.remove(127)
+ self.assertEqual(c, bytes([126, 128, 129]))
+ c.remove(129)
+ self.assertEqual(c, bytes([126, 128]))
+
def test_pop(self):
b = bytearray(b'world')
self.assertEqual(b.pop(), ord('d'))
from _testcapi import getbuffer_with_null_view
self.assertRaises(BufferError, getbuffer_with_null_view, bytearray())
+ def test_iterator_pickling2(self):
+ orig = bytearray(b'abc')
+ data = list(b'qwerty')
+ for proto in range(pickle.HIGHEST_PROTOCOL + 1):
+ # initial iterator
+ itorig = iter(orig)
+ d = pickle.dumps((itorig, orig), proto)
+ it, b = pickle.loads(d)
+ b[:] = data
+ self.assertEqual(type(it), type(itorig))
+ self.assertEqual(list(it), data)
+
+ # running iterator
+ next(itorig)
+ d = pickle.dumps((itorig, orig), proto)
+ it, b = pickle.loads(d)
+ b[:] = data
+ self.assertEqual(type(it), type(itorig))
+ self.assertEqual(list(it), data[1:])
+
+ # empty iterator
+ for i in range(1, len(orig)):
+ next(itorig)
+ d = pickle.dumps((itorig, orig), proto)
+ it, b = pickle.loads(d)
+ b[:] = data
+ self.assertEqual(type(it), type(itorig))
+ self.assertEqual(list(it), data[len(orig):])
+
+ # exhausted iterator
+ self.assertRaises(StopIteration, next, itorig)
+ d = pickle.dumps((itorig, orig), proto)
+ it, b = pickle.loads(d)
+ b[:] = data
+ self.assertEqual(list(it), [])
+
+ test_exhausted_iterator = test.list_tests.CommonTest.test_exhausted_iterator
+
class AssortedBytesTest(unittest.TestCase):
#
# Test various combinations of bytes and bytearray
# XXX More string methods? (Those that don't use character properties)
# There are tests in string_tests.py that are more
- # comprehensive for things like split, partition, etc.
+ # comprehensive for things like partition, etc.
# Unfortunately they are all bundled with tests that
# are not appropriate for bytes
# the rest that make sense (the code can be cleaned up to use modern
# unittest methods at the same time).
-class BytearrayPEP3137Test(unittest.TestCase,
- test.buffer_tests.MixinBytesBufferCommonTests):
+class BytearrayPEP3137Test(unittest.TestCase):
def marshal(self, x):
return bytearray(x)
class FixedStringTest(test.string_tests.BaseTest):
-
def fixtype(self, obj):
if isinstance(obj, str):
- return obj.encode("utf-8")
+ return self.type2test(obj.encode("utf-8"))
return super().fixtype(obj)
- # Currently the bytes containment testing uses a single integer
- # value. This may not be the final design, but until then the
- # bytes section with in a bytes containment not valid
- def test_contains(self):
- pass
- def test_expandtabs(self):
- pass
- def test_upper(self):
- pass
- def test_lower(self):
- pass
+ contains_bytes = True
class ByteArrayAsStringTest(FixedStringTest, unittest.TestCase):
type2test = bytearray
- contains_bytes = True
class BytesAsStringTest(FixedStringTest, unittest.TestCase):
type2test = bytes
- contains_bytes = True
class SubclassTest:
def test_basic(self):
- self.assertTrue(issubclass(self.subclass2test, self.type2test))
- self.assertIsInstance(self.subclass2test(), self.type2test)
+ self.assertTrue(issubclass(self.type2test, self.basetype))
+ self.assertIsInstance(self.type2test(), self.basetype)
a, b = b"abcd", b"efgh"
- _a, _b = self.subclass2test(a), self.subclass2test(b)
+ _a, _b = self.type2test(a), self.type2test(b)
# test comparison operators with subclass instances
self.assertTrue(_a == _a)
# Make sure join returns a NEW object for single item sequences
# involving a subclass.
# Make sure that it is of the appropriate type.
- s1 = self.subclass2test(b"abcd")
- s2 = self.type2test().join([s1])
+ s1 = self.type2test(b"abcd")
+ s2 = self.basetype().join([s1])
self.assertTrue(s1 is not s2)
- self.assertTrue(type(s2) is self.type2test, type(s2))
+ self.assertTrue(type(s2) is self.basetype, type(s2))
# Test reverse, calling join on subclass
s3 = s1.join([b"abcd"])
- self.assertTrue(type(s3) is self.type2test)
+ self.assertTrue(type(s3) is self.basetype)
def test_pickle(self):
- a = self.subclass2test(b"abcd")
+ a = self.type2test(b"abcd")
a.x = 10
- a.y = self.subclass2test(b"efgh")
+ a.y = self.type2test(b"efgh")
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
b = pickle.loads(pickle.dumps(a, proto))
self.assertNotEqual(id(a), id(b))
self.assertEqual(type(a.y), type(b.y))
def test_copy(self):
- a = self.subclass2test(b"abcd")
+ a = self.type2test(b"abcd")
a.x = 10
- a.y = self.subclass2test(b"efgh")
+ a.y = self.type2test(b"efgh")
for copy_method in (copy.copy, copy.deepcopy):
b = copy_method(a)
self.assertNotEqual(id(a), id(b))
self.assertEqual(type(a), type(b))
self.assertEqual(type(a.y), type(b.y))
+ test_fromhex = BaseBytesTest.test_fromhex
+
class ByteArraySubclass(bytearray):
pass
class BytesSubclass(bytes):
pass
+class OtherBytesSubclass(bytes):
+ pass
+
class ByteArraySubclassTest(SubclassTest, unittest.TestCase):
- type2test = bytearray
- subclass2test = ByteArraySubclass
+ basetype = bytearray
+ type2test = ByteArraySubclass
def test_init_override(self):
class subclass(bytearray):
class BytesSubclassTest(SubclassTest, unittest.TestCase):
- type2test = bytes
- subclass2test = BytesSubclass
+ basetype = bytes
+ type2test = BytesSubclass
if __name__ == "__main__":
'return_result_with_error.* '
'returned a result with an error set')
+ def test_buildvalue_N(self):
+ _testcapi.test_buildvalue_N()
+
@unittest.skipUnless(threading, 'Threading required for this test.')
class TestPendingCalls(unittest.TestCase):
class EmbeddingTests(unittest.TestCase):
def setUp(self):
- basepath = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
+ here = os.path.abspath(__file__)
+ basepath = os.path.dirname(os.path.dirname(os.path.dirname(here)))
exename = "_testembed"
if sys.platform.startswith("win"):
ext = ("_d" if "_d" in sys.executable else "") + ".exe"
test and not for the other, there's a mismatch, and the test fails.
** Some format units have special funny semantics and it would
- be difficult to accomodate them here. Since these are all
+ be difficult to accommodate them here. Since these are all
well-established and properly skipped in skipitem() we can
get away with not testing them--this test is really intended
to catch *new* format units.
format.encode("ascii"), keywords)
when_not_skipped = False
except TypeError as e:
- s = "argument 1 must be impossible<bad format char>, not int"
+ s = "argument 1 (impossible<bad format char>)"
when_not_skipped = (str(e) == s)
except RuntimeError as e:
when_not_skipped = False
# Verify that -R enables hash randomization:
self.verify_valid_flag('-R')
hashes = []
- for i in range(2):
+ if os.environ.get('PYTHONHASHSEED', 'random') != 'random':
+ env = dict(os.environ) # copy
+ # We need to test that it is enabled by default without
+ # the environment variable enabling it for us.
+ del env['PYTHONHASHSEED']
+ env['__cleanenv'] = '1' # consumed by assert_python_ok()
+ else:
+ env = {}
+ for i in range(3):
code = 'print(hash("spam"))'
- rc, out, err = assert_python_ok('-c', code)
+ rc, out, err = assert_python_ok('-c', code, **env)
self.assertEqual(rc, 0)
hashes.append(out)
- self.assertNotEqual(hashes[0], hashes[1])
+ hashes = sorted(set(hashes)) # uniq
+ # Rare chance of failure due to 3 random seeds honestly being equal.
+ self.assertGreater(len(hashes), 1,
+ msg='3 runs produced an identical random hash '
+ ' for "spam": {}'.format(hashes))
# Verify that sys.flags contains hash_randomization
code = 'import sys; print("random is", sys.flags.hash_randomization)'
script_name, script_name, '', '',
importlib.machinery.SourceFileLoader)
+ @contextlib.contextmanager
+ def setup_test_pkg(self, *args):
+ with support.temp_dir() as script_dir, \
+ support.change_cwd(path=script_dir):
+ pkg_dir = os.path.join(script_dir, 'test_pkg')
+ make_pkg(pkg_dir, *args)
+ yield pkg_dir
+
+ def check_dash_m_failure(self, *args):
+ rc, out, err = assert_python_failure('-m', *args, __isolated=False)
+ if verbose > 1:
+ print(repr(out))
+ self.assertEqual(rc, 1)
+ return err
+
def test_dash_m_error_code_is_one(self):
# If a module is invoked with the -m command line flag
# and results in an error that the return code to the
# shell is '1'
- with support.temp_dir() as script_dir:
- with support.change_cwd(path=script_dir):
- pkg_dir = os.path.join(script_dir, 'test_pkg')
- make_pkg(pkg_dir)
- script_name = _make_test_script(pkg_dir, 'other',
- "if __name__ == '__main__': raise ValueError")
- rc, out, err = assert_python_failure('-m', 'test_pkg.other', *example_args)
- if verbose > 1:
- print(repr(out))
+ with self.setup_test_pkg() as pkg_dir:
+ script_name = _make_test_script(pkg_dir, 'other',
+ "if __name__ == '__main__': raise ValueError")
+ err = self.check_dash_m_failure('test_pkg.other', *example_args)
+ self.assertIn(b'ValueError', err)
+
+ def test_dash_m_errors(self):
+ # Exercise error reporting for various invalid package executions
+ tests = (
+ ('builtins', br'No code object available'),
+ ('builtins.x', br'Error while finding spec.*AttributeError'),
+ ('builtins.x.y', br'Error while finding spec.*'
+ br'ImportError.*No module named.*not a package'),
+ ('os.path', br'loader.*cannot handle'),
+ ('importlib', br'No module named.*'
+ br'is a package and cannot be directly executed'),
+ ('importlib.nonexistant', br'No module named'),
+ ('.unittest', br'Relative module names not supported'),
+ )
+ for name, regex in tests:
+ with self.subTest(name):
+ rc, _, err = assert_python_failure('-m', name)
self.assertEqual(rc, 1)
+ self.assertRegex(err, regex)
+ self.assertNotIn(b'Traceback', err)
+
+ def test_dash_m_bad_pyc(self):
+ with support.temp_dir() as script_dir, \
+ support.change_cwd(path=script_dir):
+ os.mkdir('test_pkg')
+ # Create invalid *.pyc as empty file
+ with open('test_pkg/__init__.pyc', 'wb'):
+ pass
+ err = self.check_dash_m_failure('test_pkg')
+ self.assertRegex(err, br'Error while finding spec.*'
+ br'ImportError.*bad magic number')
+ self.assertNotIn(b'is a package', err)
+ self.assertNotIn(b'Traceback', err)
+
+ def test_dash_m_init_traceback(self):
+ # These were wrapped in an ImportError and tracebacks were
+ # suppressed; see Issue 14285
+ exceptions = (ImportError, AttributeError, TypeError, ValueError)
+ for exception in exceptions:
+ exception = exception.__name__
+ init = "raise {0}('Exception in __init__.py')".format(exception)
+ with self.subTest(exception), \
+ self.setup_test_pkg(init) as pkg_dir:
+ err = self.check_dash_m_failure('test_pkg')
+ self.assertIn(exception.encode('ascii'), err)
+ self.assertIn(b'Exception in __init__.py', err)
+ self.assertIn(b'Traceback', err)
+
+ def test_dash_m_main_traceback(self):
+ # Ensure that an ImportError's traceback is reported
+ with self.setup_test_pkg() as pkg_dir:
+ main = "raise ImportError('Exception in __main__ module')"
+ _make_test_script(pkg_dir, '__main__', main)
+ err = self.check_dash_m_failure('test_pkg')
+ self.assertIn(b'ImportError', err)
+ self.assertIn(b'Exception in __main__ module', err)
+ self.assertIn(b'Traceback', err)
def test_pep_409_verbiage(self):
# Make sure PEP 409 syntax properly suppresses
def test_non_ascii(self):
# Mac OS X denies the creation of a file with an invalid UTF-8 name.
- # Windows allows to create a name with an arbitrary bytes name, but
+ # Windows allows creating a name with an arbitrary bytes name, but
# Python cannot a undecodable bytes argument to a subprocess.
if (support.TESTFN_UNDECODABLE
and sys.platform not in ('win32', 'darwin')):
self.assertRaises(TypeError, decoder, "xxx")
def test_unicode_escape(self):
- # Escape-decoding an unicode string is supported ang gives the same
+ # Escape-decoding a unicode string is supported and gives the same
# result as decoding the equivalent ASCII bytes string.
self.assertEqual(codecs.unicode_escape_decode(r"\u1234"), ("\u1234", 6))
self.assertEqual(codecs.unicode_escape_decode(br"\u1234"), ("\u1234", 6))
# type and a single str argument.
# Use a local codec registry to avoid appearing to leak objects when
-# registering multiple seach functions
+# registering multiple search functions
_TEST_CODECS = {}
def _get_test_codec(codec_name):
"""Unit tests for collections.py."""
-import unittest, doctest, operator
-from test.support import TESTFN, forget, unlink, import_fresh_module
-import contextlib
+import collections
+import copy
+import doctest
import inspect
-from test import support
-from collections import namedtuple, Counter, OrderedDict, _count_elements
-from test import mapping_tests
-import pickle, copy
-from random import randrange, shuffle
import keyword
+import operator
+import pickle
+from random import choice, randrange
import re
+import string
import sys
+from test import support
import types
+import unittest
+
+from collections import namedtuple, Counter, OrderedDict, _count_elements
from collections import UserDict, UserString, UserList
from collections import ChainMap
from collections import deque
# n = 5000
n = 254 # SyntaxError: more than 255 arguments:
- import string, random
- names = list(set(''.join([random.choice(string.ascii_letters)
+ names = list(set(''.join([choice(string.ascii_letters)
for j in range(10)]) for i in range(n)))
n = len(names)
Big = namedtuple('Big', names)
################################################################################
-### OrderedDict
-################################################################################
-
-py_coll = import_fresh_module('collections', blocked=['_collections'])
-c_coll = import_fresh_module('collections', fresh=['_collections'])
-
-
-@contextlib.contextmanager
-def replaced_module(name, replacement):
- original_module = sys.modules[name]
- sys.modules[name] = replacement
- try:
- yield
- finally:
- sys.modules[name] = original_module
-
-
-class OrderedDictTests:
-
- def test_init(self):
- OrderedDict = self.OrderedDict
- with self.assertRaises(TypeError):
- OrderedDict([('a', 1), ('b', 2)], None) # too many args
- pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
- self.assertEqual(sorted(OrderedDict(dict(pairs)).items()), pairs) # dict input
- self.assertEqual(sorted(OrderedDict(**dict(pairs)).items()), pairs) # kwds input
- self.assertEqual(list(OrderedDict(pairs).items()), pairs) # pairs input
- self.assertEqual(list(OrderedDict([('a', 1), ('b', 2), ('c', 9), ('d', 4)],
- c=3, e=5).items()), pairs) # mixed input
-
- # make sure no positional args conflict with possible kwdargs
- self.assertEqual(list(OrderedDict(self=42).items()), [('self', 42)])
- self.assertEqual(list(OrderedDict(other=42).items()), [('other', 42)])
- self.assertRaises(TypeError, OrderedDict, 42)
- self.assertRaises(TypeError, OrderedDict, (), ())
- self.assertRaises(TypeError, OrderedDict.__init__)
-
- # Make sure that direct calls to __init__ do not clear previous contents
- d = OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 44), ('e', 55)])
- d.__init__([('e', 5), ('f', 6)], g=7, d=4)
- self.assertEqual(list(d.items()),
- [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)])
-
- def test_update(self):
- OrderedDict = self.OrderedDict
- with self.assertRaises(TypeError):
- OrderedDict().update([('a', 1), ('b', 2)], None) # too many args
- pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
- od = OrderedDict()
- od.update(dict(pairs))
- self.assertEqual(sorted(od.items()), pairs) # dict input
- od = OrderedDict()
- od.update(**dict(pairs))
- self.assertEqual(sorted(od.items()), pairs) # kwds input
- od = OrderedDict()
- od.update(pairs)
- self.assertEqual(list(od.items()), pairs) # pairs input
- od = OrderedDict()
- od.update([('a', 1), ('b', 2), ('c', 9), ('d', 4)], c=3, e=5)
- self.assertEqual(list(od.items()), pairs) # mixed input
-
- # Issue 9137: Named argument called 'other' or 'self'
- # shouldn't be treated specially.
- od = OrderedDict()
- od.update(self=23)
- self.assertEqual(list(od.items()), [('self', 23)])
- od = OrderedDict()
- od.update(other={})
- self.assertEqual(list(od.items()), [('other', {})])
- od = OrderedDict()
- od.update(red=5, blue=6, other=7, self=8)
- self.assertEqual(sorted(list(od.items())),
- [('blue', 6), ('other', 7), ('red', 5), ('self', 8)])
-
- # Make sure that direct calls to update do not clear previous contents
- # add that updates items are not moved to the end
- d = OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 44), ('e', 55)])
- d.update([('e', 5), ('f', 6)], g=7, d=4)
- self.assertEqual(list(d.items()),
- [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)])
-
- self.assertRaises(TypeError, OrderedDict().update, 42)
- self.assertRaises(TypeError, OrderedDict().update, (), ())
- self.assertRaises(TypeError, OrderedDict.update)
-
- self.assertRaises(TypeError, OrderedDict().update, 42)
- self.assertRaises(TypeError, OrderedDict().update, (), ())
- self.assertRaises(TypeError, OrderedDict.update)
-
- def test_fromkeys(self):
- OrderedDict = self.OrderedDict
- od = OrderedDict.fromkeys('abc')
- self.assertEqual(list(od.items()), [(c, None) for c in 'abc'])
- od = OrderedDict.fromkeys('abc', value=None)
- self.assertEqual(list(od.items()), [(c, None) for c in 'abc'])
- od = OrderedDict.fromkeys('abc', value=0)
- self.assertEqual(list(od.items()), [(c, 0) for c in 'abc'])
-
- def test_abc(self):
- OrderedDict = self.OrderedDict
- self.assertIsInstance(OrderedDict(), MutableMapping)
- self.assertTrue(issubclass(OrderedDict, MutableMapping))
-
- def test_clear(self):
- OrderedDict = self.OrderedDict
- pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
- shuffle(pairs)
- od = OrderedDict(pairs)
- self.assertEqual(len(od), len(pairs))
- od.clear()
- self.assertEqual(len(od), 0)
-
- def test_delitem(self):
- OrderedDict = self.OrderedDict
- pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
- od = OrderedDict(pairs)
- del od['a']
- self.assertNotIn('a', od)
- with self.assertRaises(KeyError):
- del od['a']
- self.assertEqual(list(od.items()), pairs[:2] + pairs[3:])
-
- def test_setitem(self):
- OrderedDict = self.OrderedDict
- od = OrderedDict([('d', 1), ('b', 2), ('c', 3), ('a', 4), ('e', 5)])
- od['c'] = 10 # existing element
- od['f'] = 20 # new element
- self.assertEqual(list(od.items()),
- [('d', 1), ('b', 2), ('c', 10), ('a', 4), ('e', 5), ('f', 20)])
-
- def test_iterators(self):
- OrderedDict = self.OrderedDict
- pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
- shuffle(pairs)
- od = OrderedDict(pairs)
- self.assertEqual(list(od), [t[0] for t in pairs])
- self.assertEqual(list(od.keys()), [t[0] for t in pairs])
- self.assertEqual(list(od.values()), [t[1] for t in pairs])
- self.assertEqual(list(od.items()), pairs)
- self.assertEqual(list(reversed(od)),
- [t[0] for t in reversed(pairs)])
- self.assertEqual(list(reversed(od.keys())),
- [t[0] for t in reversed(pairs)])
- self.assertEqual(list(reversed(od.values())),
- [t[1] for t in reversed(pairs)])
- self.assertEqual(list(reversed(od.items())), list(reversed(pairs)))
-
- def test_detect_deletion_during_iteration(self):
- OrderedDict = self.OrderedDict
- od = OrderedDict.fromkeys('abc')
- it = iter(od)
- key = next(it)
- del od[key]
- with self.assertRaises(Exception):
- # Note, the exact exception raised is not guaranteed
- # The only guarantee that the next() will not succeed
- next(it)
-
- def test_sorted_iterators(self):
- OrderedDict = self.OrderedDict
- with self.assertRaises(TypeError):
- OrderedDict([('a', 1), ('b', 2)], None)
- pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
- od = OrderedDict(pairs)
- self.assertEqual(sorted(od), [t[0] for t in pairs])
- self.assertEqual(sorted(od.keys()), [t[0] for t in pairs])
- self.assertEqual(sorted(od.values()), [t[1] for t in pairs])
- self.assertEqual(sorted(od.items()), pairs)
- self.assertEqual(sorted(reversed(od)),
- sorted([t[0] for t in reversed(pairs)]))
-
- def test_iterators_empty(self):
- OrderedDict = self.OrderedDict
- od = OrderedDict()
- empty = []
- self.assertEqual(list(od), empty)
- self.assertEqual(list(od.keys()), empty)
- self.assertEqual(list(od.values()), empty)
- self.assertEqual(list(od.items()), empty)
- self.assertEqual(list(reversed(od)), empty)
- self.assertEqual(list(reversed(od.keys())), empty)
- self.assertEqual(list(reversed(od.values())), empty)
- self.assertEqual(list(reversed(od.items())), empty)
-
- def test_popitem(self):
- OrderedDict = self.OrderedDict
- pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
- shuffle(pairs)
- od = OrderedDict(pairs)
- while pairs:
- self.assertEqual(od.popitem(), pairs.pop())
- with self.assertRaises(KeyError):
- od.popitem()
- self.assertEqual(len(od), 0)
-
- def test_popitem_last(self):
- OrderedDict = self.OrderedDict
- pairs = [(i, i) for i in range(30)]
-
- obj = OrderedDict(pairs)
- for i in range(8):
- obj.popitem(True)
- obj.popitem(True)
- obj.popitem(last=True)
- self.assertEqual(len(obj), 20)
-
- def test_pop(self):
- OrderedDict = self.OrderedDict
- pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
- shuffle(pairs)
- od = OrderedDict(pairs)
- shuffle(pairs)
- while pairs:
- k, v = pairs.pop()
- self.assertEqual(od.pop(k), v)
- with self.assertRaises(KeyError):
- od.pop('xyz')
- self.assertEqual(len(od), 0)
- self.assertEqual(od.pop(k, 12345), 12345)
-
- # make sure pop still works when __missing__ is defined
- class Missing(OrderedDict):
- def __missing__(self, key):
- return 0
- m = Missing(a=1)
- self.assertEqual(m.pop('b', 5), 5)
- self.assertEqual(m.pop('a', 6), 1)
- self.assertEqual(m.pop('a', 6), 6)
- self.assertEqual(m.pop('a', default=6), 6)
- with self.assertRaises(KeyError):
- m.pop('a')
-
- def test_equality(self):
- OrderedDict = self.OrderedDict
- pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
- shuffle(pairs)
- od1 = OrderedDict(pairs)
- od2 = OrderedDict(pairs)
- self.assertEqual(od1, od2) # same order implies equality
- pairs = pairs[2:] + pairs[:2]
- od2 = OrderedDict(pairs)
- self.assertNotEqual(od1, od2) # different order implies inequality
- # comparison to regular dict is not order sensitive
- self.assertEqual(od1, dict(od2))
- self.assertEqual(dict(od2), od1)
- # different length implied inequality
- self.assertNotEqual(od1, OrderedDict(pairs[:-1]))
-
- def test_copying(self):
- OrderedDict = self.OrderedDict
- # Check that ordered dicts are copyable, deepcopyable, picklable,
- # and have a repr/eval round-trip
- pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
- od = OrderedDict(pairs)
- def check(dup):
- msg = "\ncopy: %s\nod: %s" % (dup, od)
- self.assertIsNot(dup, od, msg)
- self.assertEqual(dup, od)
- self.assertEqual(list(dup.items()), list(od.items()))
- self.assertEqual(len(dup), len(od))
- self.assertEqual(type(dup), type(od))
- check(od.copy())
- check(copy.copy(od))
- check(copy.deepcopy(od))
- # pickle directly pulls the module, so we have to fake it
- with replaced_module('collections', self.module):
- for proto in range(pickle.HIGHEST_PROTOCOL + 1):
- with self.subTest(proto=proto):
- check(pickle.loads(pickle.dumps(od, proto)))
- check(eval(repr(od)))
- update_test = OrderedDict()
- update_test.update(od)
- check(update_test)
- check(OrderedDict(od))
-
- def test_yaml_linkage(self):
- OrderedDict = self.OrderedDict
- # Verify that __reduce__ is setup in a way that supports PyYAML's dump() feature.
- # In yaml, lists are native but tuples are not.
- pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
- od = OrderedDict(pairs)
- # yaml.dump(od) -->
- # '!!python/object/apply:__main__.OrderedDict\n- - [a, 1]\n - [b, 2]\n'
- self.assertTrue(all(type(pair)==list for pair in od.__reduce__()[1]))
-
- def test_reduce_not_too_fat(self):
- OrderedDict = self.OrderedDict
- # do not save instance dictionary if not needed
- pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
- od = OrderedDict(pairs)
- self.assertIsNone(od.__reduce__()[2])
- od.x = 10
- self.assertIsNotNone(od.__reduce__()[2])
-
- def test_pickle_recursive(self):
- OrderedDict = self.OrderedDict
- od = OrderedDict()
- od[1] = od
-
- # pickle directly pulls the module, so we have to fake it
- with replaced_module('collections', self.module):
- for proto in range(-1, pickle.HIGHEST_PROTOCOL + 1):
- dup = pickle.loads(pickle.dumps(od, proto))
- self.assertIsNot(dup, od)
- self.assertEqual(list(dup.keys()), [1])
- self.assertIs(dup[1], dup)
-
- def test_repr(self):
- OrderedDict = self.OrderedDict
- od = OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)])
- self.assertEqual(repr(od),
- "OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)])")
- self.assertEqual(eval(repr(od)), od)
- self.assertEqual(repr(OrderedDict()), "OrderedDict()")
-
- def test_repr_recursive(self):
- OrderedDict = self.OrderedDict
- # See issue #9826
- od = OrderedDict.fromkeys('abc')
- od['x'] = od
- self.assertEqual(repr(od),
- "OrderedDict([('a', None), ('b', None), ('c', None), ('x', ...)])")
-
- def test_setdefault(self):
- OrderedDict = self.OrderedDict
- pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
- shuffle(pairs)
- od = OrderedDict(pairs)
- pair_order = list(od.items())
- self.assertEqual(od.setdefault('a', 10), 3)
- # make sure order didn't change
- self.assertEqual(list(od.items()), pair_order)
- self.assertEqual(od.setdefault('x', 10), 10)
- # make sure 'x' is added to the end
- self.assertEqual(list(od.items())[-1], ('x', 10))
- self.assertEqual(od.setdefault('g', default=9), 9)
-
- # make sure setdefault still works when __missing__ is defined
- class Missing(OrderedDict):
- def __missing__(self, key):
- return 0
- self.assertEqual(Missing().setdefault(5, 9), 9)
-
- def test_reinsert(self):
- OrderedDict = self.OrderedDict
- # Given insert a, insert b, delete a, re-insert a,
- # verify that a is now later than b.
- od = OrderedDict()
- od['a'] = 1
- od['b'] = 2
- del od['a']
- self.assertEqual(list(od.items()), [('b', 2)])
- od['a'] = 1
- self.assertEqual(list(od.items()), [('b', 2), ('a', 1)])
-
- def test_move_to_end(self):
- OrderedDict = self.OrderedDict
- od = OrderedDict.fromkeys('abcde')
- self.assertEqual(list(od), list('abcde'))
- od.move_to_end('c')
- self.assertEqual(list(od), list('abdec'))
- od.move_to_end('c', 0)
- self.assertEqual(list(od), list('cabde'))
- od.move_to_end('c', 0)
- self.assertEqual(list(od), list('cabde'))
- od.move_to_end('e')
- self.assertEqual(list(od), list('cabde'))
- od.move_to_end('b', last=False)
- self.assertEqual(list(od), list('bcade'))
- with self.assertRaises(KeyError):
- od.move_to_end('x')
- with self.assertRaises(KeyError):
- od.move_to_end('x', 0)
-
- def test_move_to_end_issue25406(self):
- OrderedDict = self.OrderedDict
- od = OrderedDict.fromkeys('abc')
- od.move_to_end('c', last=False)
- self.assertEqual(list(od), list('cab'))
- od.move_to_end('a', last=False)
- self.assertEqual(list(od), list('acb'))
-
- od = OrderedDict.fromkeys('abc')
- od.move_to_end('a')
- self.assertEqual(list(od), list('bca'))
- od.move_to_end('c')
- self.assertEqual(list(od), list('bac'))
-
- def test_sizeof(self):
- OrderedDict = self.OrderedDict
- # Wimpy test: Just verify the reported size is larger than a regular dict
- d = dict(a=1)
- od = OrderedDict(**d)
- self.assertGreater(sys.getsizeof(od), sys.getsizeof(d))
-
- def test_override_update(self):
- OrderedDict = self.OrderedDict
- # Verify that subclasses can override update() without breaking __init__()
- class MyOD(OrderedDict):
- def update(self, *args, **kwds):
- raise Exception()
- items = [('a', 1), ('c', 3), ('b', 2)]
- self.assertEqual(list(MyOD(items).items()), items)
-
- def test_highly_nested(self):
- # Issue 25395: crashes during garbage collection
- OrderedDict = self.OrderedDict
- obj = None
- for _ in range(1000):
- obj = OrderedDict([(None, obj)])
- del obj
- support.gc_collect()
-
- def test_highly_nested_subclass(self):
- # Issue 25395: crashes during garbage collection
- OrderedDict = self.OrderedDict
- deleted = []
- class MyOD(OrderedDict):
- def __del__(self):
- deleted.append(self.i)
- obj = None
- for i in range(100):
- obj = MyOD([(None, obj)])
- obj.i = i
- del obj
- support.gc_collect()
- self.assertEqual(deleted, list(reversed(range(100))))
-
- def test_delitem_hash_collision(self):
- OrderedDict = self.OrderedDict
-
- class Key:
- def __init__(self, hash):
- self._hash = hash
- self.value = str(id(self))
- def __hash__(self):
- return self._hash
- def __eq__(self, other):
- try:
- return self.value == other.value
- except AttributeError:
- return False
- def __repr__(self):
- return self.value
-
- def blocking_hash(hash):
- # See the collision-handling in lookdict (in Objects/dictobject.c).
- MINSIZE = 8
- i = (hash & MINSIZE-1)
- return (i << 2) + i + hash + 1
-
- COLLIDING = 1
-
- key = Key(COLLIDING)
- colliding = Key(COLLIDING)
- blocking = Key(blocking_hash(COLLIDING))
-
- od = OrderedDict()
- od[key] = ...
- od[blocking] = ...
- od[colliding] = ...
- od['after'] = ...
-
- del od[blocking]
- del od[colliding]
- self.assertEqual(list(od.items()), [(key, ...), ('after', ...)])
-
- def test_issue24347(self):
- OrderedDict = self.OrderedDict
-
- class Key:
- def __hash__(self):
- return randrange(100000)
-
- od = OrderedDict()
- for i in range(100):
- key = Key()
- od[key] = i
-
- # These should not crash.
- with self.assertRaises(KeyError):
- list(od.values())
- with self.assertRaises(KeyError):
- list(od.items())
- with self.assertRaises(KeyError):
- repr(od)
- with self.assertRaises(KeyError):
- od.copy()
-
- def test_issue24348(self):
- OrderedDict = self.OrderedDict
-
- class Key:
- def __hash__(self):
- return 1
-
- od = OrderedDict()
- od[Key()] = 0
- # This should not crash.
- od.popitem()
-
- def test_issue24667(self):
- """
- dict resizes after a certain number of insertion operations,
- whether or not there were deletions that freed up slots in the
- hash table. During fast node lookup, OrderedDict must correctly
- respond to all resizes, even if the current "size" is the same
- as the old one. We verify that here by forcing a dict resize
- on a sparse odict and then perform an operation that should
- trigger an odict resize (e.g. popitem). One key aspect here is
- that we will keep the size of the odict the same at each popitem
- call. This verifies that we handled the dict resize properly.
- """
- OrderedDict = self.OrderedDict
-
- od = OrderedDict()
- for c0 in '0123456789ABCDEF':
- for c1 in '0123456789ABCDEF':
- if len(od) == 4:
- # This should not raise a KeyError.
- od.popitem(last=False)
- key = c0 + c1
- od[key] = key
-
- # Direct use of dict methods
-
- def test_dict_setitem(self):
- OrderedDict = self.OrderedDict
- od = OrderedDict()
- dict.__setitem__(od, 'spam', 1)
- self.assertNotIn('NULL', repr(od))
-
- def test_dict_delitem(self):
- OrderedDict = self.OrderedDict
- od = OrderedDict()
- od['spam'] = 1
- od['ham'] = 2
- dict.__delitem__(od, 'spam')
- with self.assertRaises(KeyError):
- repr(od)
-
- def test_dict_clear(self):
- OrderedDict = self.OrderedDict
- od = OrderedDict()
- od['spam'] = 1
- od['ham'] = 2
- dict.clear(od)
- self.assertNotIn('NULL', repr(od))
-
- def test_dict_pop(self):
- OrderedDict = self.OrderedDict
- od = OrderedDict()
- od['spam'] = 1
- od['ham'] = 2
- dict.pop(od, 'spam')
- with self.assertRaises(KeyError):
- repr(od)
-
- def test_dict_popitem(self):
- OrderedDict = self.OrderedDict
- od = OrderedDict()
- od['spam'] = 1
- od['ham'] = 2
- dict.popitem(od)
- with self.assertRaises(KeyError):
- repr(od)
-
- def test_dict_setdefault(self):
- OrderedDict = self.OrderedDict
- od = OrderedDict()
- dict.setdefault(od, 'spam', 1)
- self.assertNotIn('NULL', repr(od))
-
- def test_dict_update(self):
- od = OrderedDict()
- dict.update(od, [('spam', 1)])
- self.assertNotIn('NULL', repr(od))
-
-
-class PurePythonOrderedDictTests(OrderedDictTests, unittest.TestCase):
-
- module = py_coll
- OrderedDict = py_coll.OrderedDict
-
-
-@unittest.skipUnless(c_coll, 'requires the C version of the collections module')
-class CPythonOrderedDictTests(OrderedDictTests, unittest.TestCase):
-
- module = c_coll
- OrderedDict = c_coll.OrderedDict
-
- def test_key_change_during_iteration(self):
- OrderedDict = self.OrderedDict
-
- od = OrderedDict.fromkeys('abcde')
- self.assertEqual(list(od), list('abcde'))
- with self.assertRaises(RuntimeError):
- for i, k in enumerate(od):
- od.move_to_end(k)
- self.assertLess(i, 5)
- with self.assertRaises(RuntimeError):
- for k in od:
- od['f'] = None
- with self.assertRaises(RuntimeError):
- for k in od:
- del od['c']
- self.assertEqual(list(od), list('bdeaf'))
-
-
-class PurePythonOrderedDictSubclassTests(PurePythonOrderedDictTests):
-
- module = py_coll
- class OrderedDict(py_coll.OrderedDict):
- pass
-
-
-class CPythonOrderedDictSubclassTests(CPythonOrderedDictTests):
-
- module = c_coll
- class OrderedDict(c_coll.OrderedDict):
- pass
-
-
-class PurePythonGeneralMappingTests(mapping_tests.BasicTestMappingProtocol):
-
- @classmethod
- def setUpClass(cls):
- cls.type2test = py_coll.OrderedDict
-
- def test_popitem(self):
- d = self._empty_mapping()
- self.assertRaises(KeyError, d.popitem)
-
-
-@unittest.skipUnless(c_coll, 'requires the C version of the collections module')
-class CPythonGeneralMappingTests(mapping_tests.BasicTestMappingProtocol):
-
- @classmethod
- def setUpClass(cls):
- cls.type2test = c_coll.OrderedDict
-
- def test_popitem(self):
- d = self._empty_mapping()
- self.assertRaises(KeyError, d.popitem)
-
-
-class PurePythonSubclassMappingTests(mapping_tests.BasicTestMappingProtocol):
-
- @classmethod
- def setUpClass(cls):
- class MyOrderedDict(py_coll.OrderedDict):
- pass
- cls.type2test = MyOrderedDict
-
- def test_popitem(self):
- d = self._empty_mapping()
- self.assertRaises(KeyError, d.popitem)
-
-
-@unittest.skipUnless(c_coll, 'requires the C version of the collections module')
-class CPythonSubclassMappingTests(mapping_tests.BasicTestMappingProtocol):
-
- @classmethod
- def setUpClass(cls):
- class MyOrderedDict(c_coll.OrderedDict):
- pass
- cls.type2test = MyOrderedDict
-
- def test_popitem(self):
- d = self._empty_mapping()
- self.assertRaises(KeyError, d.popitem)
-
-
-################################################################################
### Run tests
################################################################################
-import doctest, collections
-
def test_main(verbose=None):
NamedTupleDocs = doctest.DocTestSuite(module=collections)
test_classes = [TestNamedTuple, NamedTupleDocs, TestOneTrickPonyABCs,
TestCollectionABCs, TestCounter, TestChainMap,
- PurePythonOrderedDictTests, CPythonOrderedDictTests,
- PurePythonOrderedDictSubclassTests,
- CPythonOrderedDictSubclassTests,
- PurePythonGeneralMappingTests, CPythonGeneralMappingTests,
- PurePythonSubclassMappingTests, CPythonSubclassMappingTests,
TestUserObjects,
]
support.run_unittest(*test_classes)
exec(memoryview(b"ax = 123")[1:-1], namespace)
self.assertEqual(namespace['x'], 12)
+ def check_constant(self, func, expected):
+ for const in func.__code__.co_consts:
+ if repr(const) == repr(expected):
+ break
+ else:
+ self.fail("unable to find constant %r in %r"
+ % (expected, func.__code__.co_consts))
+
+ # Merging equal constants is not a strict requirement for the Python
+ # semantics, it's a more an implementation detail.
+ @support.cpython_only
+ def test_merge_constants(self):
+ # Issue #25843: compile() must merge constants which are equal
+ # and have the same type.
+
+ def check_same_constant(const):
+ ns = {}
+ code = "f1, f2 = lambda: %r, lambda: %r" % (const, const)
+ exec(code, ns)
+ f1 = ns['f1']
+ f2 = ns['f2']
+ self.assertIs(f1.__code__, f2.__code__)
+ self.check_constant(f1, const)
+ self.assertEqual(repr(f1()), repr(const))
+
+ check_same_constant(None)
+ check_same_constant(0)
+ check_same_constant(0.0)
+ check_same_constant(b'abc')
+ check_same_constant('abc')
+
+ # Note: "lambda: ..." emits "LOAD_CONST Ellipsis",
+ # whereas "lambda: Ellipsis" emits "LOAD_GLOBAL Ellipsis"
+ f1, f2 = lambda: ..., lambda: ...
+ self.assertIs(f1.__code__, f2.__code__)
+ self.check_constant(f1, Ellipsis)
+ self.assertEqual(repr(f1()), repr(Ellipsis))
+
+ # {0} is converted to a constant frozenset({0}) by the peephole
+ # optimizer
+ f1, f2 = lambda x: x in {0}, lambda x: x in {0}
+ self.assertIs(f1.__code__, f2.__code__)
+ self.check_constant(f1, frozenset({0}))
+ self.assertTrue(f1(0))
+
+ def test_dont_merge_constants(self):
+ # Issue #25843: compile() must not merge constants which are equal
+ # but have a different type.
+
+ def check_different_constants(const1, const2):
+ ns = {}
+ exec("f1, f2 = lambda: %r, lambda: %r" % (const1, const2), ns)
+ f1 = ns['f1']
+ f2 = ns['f2']
+ self.assertIsNot(f1.__code__, f2.__code__)
+ self.check_constant(f1, const1)
+ self.check_constant(f2, const2)
+ self.assertEqual(repr(f1()), repr(const1))
+ self.assertEqual(repr(f2()), repr(const2))
+
+ check_different_constants(0, 0.0)
+ check_different_constants(+0.0, -0.0)
+ check_different_constants((0,), (0.0,))
+
+ # check_different_constants() cannot be used because repr(-0j) is
+ # '(-0-0j)', but when '(-0-0j)' is evaluated to 0j: we loose the sign.
+ f1, f2 = lambda: +0.0j, lambda: -0.0j
+ self.assertIsNot(f1.__code__, f2.__code__)
+ self.check_constant(f1, +0.0j)
+ self.check_constant(f2, -0.0j)
+ self.assertEqual(repr(f1()), repr(+0.0j))
+ self.assertEqual(repr(f2()), repr(-0.0j))
+
+ # {0} is converted to a constant frozenset({0}) by the peephole
+ # optimizer
+ f1, f2 = lambda x: x in {0}, lambda x: x in {0.0}
+ self.assertIsNot(f1.__code__, f2.__code__)
+ self.check_constant(f1, frozenset({0}))
+ self.check_constant(f2, frozenset({0.0}))
+ self.assertTrue(f1(0))
+ self.assertTrue(f2(0.0))
+
class TestStackSize(unittest.TestCase):
# These tests check that the computed stack size for a code object
self.assertCompiled(init2fn)
self.assertCompiled(bar2fn)
- def test_d_takes_exactly_one_dir(self):
- rc, out, err = self.assertRunNotOK('-d', 'foo')
- self.assertEqual(out, b'')
- self.assertRegex(err, b'-d')
- rc, out, err = self.assertRunNotOK('-d', 'foo', 'bar')
- self.assertEqual(out, b'')
- self.assertRegex(err, b'-d')
-
def test_d_compile_error(self):
script_helper.make_script(self.pkgdir, 'crunchyfrog', 'bad(syntax')
rc, out, err = self.assertRunNotOK('-q', '-d', 'dinsdale', self.pkgdir)
self.assertEqual(SUCCESSFUL_FUTURE.result(timeout=0), 42)
def test_result_with_success(self):
- # TODO(brian@sweetapp.com): This test is timing dependant.
+ # TODO(brian@sweetapp.com): This test is timing dependent.
def notification():
# Wait until the main thread is waiting for the result.
time.sleep(1)
self.assertEqual(f1.result(timeout=5), 42)
def test_result_with_cancel(self):
- # TODO(brian@sweetapp.com): This test is timing dependant.
+ # TODO(brian@sweetapp.com): This test is timing dependent.
def notification():
# Wait until the main thread is waiting for the result.
time.sleep(1)
pass
class WithMetaclass(metaclass=abc.ABCMeta):
pass
- tests = [None, 42, 2**100, 3.14, True, False, 1j,
+ tests = [None, ..., NotImplemented,
+ 42, 2**100, 3.14, True, False, 1j,
"hello", "hello\u1234", f.__code__,
- b"world", bytes(range(256)),
- NewStyle, range(10), Classic, max, WithMetaclass]
+ b"world", bytes(range(256)), range(10),
+ NewStyle, Classic, max, WithMetaclass]
for x in tests:
self.assertIs(copy.copy(x), x)
def test_copy_list(self):
x = [1, 2, 3]
- self.assertEqual(copy.copy(x), x)
+ y = copy.copy(x)
+ self.assertEqual(y, x)
+ self.assertIsNot(y, x)
+ x = []
+ y = copy.copy(x)
+ self.assertEqual(y, x)
+ self.assertIsNot(y, x)
def test_copy_tuple(self):
x = (1, 2, 3)
- self.assertEqual(copy.copy(x), x)
+ self.assertIs(copy.copy(x), x)
+ x = ()
+ self.assertIs(copy.copy(x), x)
+ x = (1, 2, 3, [])
+ self.assertIs(copy.copy(x), x)
def test_copy_dict(self):
x = {"foo": 1, "bar": 2}
- self.assertEqual(copy.copy(x), x)
+ y = copy.copy(x)
+ self.assertEqual(y, x)
+ self.assertIsNot(y, x)
+ x = {}
+ y = copy.copy(x)
+ self.assertEqual(y, x)
+ self.assertIsNot(y, x)
+
+ def test_copy_set(self):
+ x = {1, 2, 3}
+ y = copy.copy(x)
+ self.assertEqual(y, x)
+ self.assertIsNot(y, x)
+ x = set()
+ y = copy.copy(x)
+ self.assertEqual(y, x)
+ self.assertIsNot(y, x)
+
+ def test_copy_frozenset(self):
+ x = frozenset({1, 2, 3})
+ self.assertIs(copy.copy(x), x)
+ x = frozenset()
+ self.assertIs(copy.copy(x), x)
+
+ def test_copy_bytearray(self):
+ x = bytearray(b'abc')
+ y = copy.copy(x)
+ self.assertEqual(y, x)
+ self.assertIsNot(y, x)
+ x = bytearray()
+ y = copy.copy(x)
+ self.assertEqual(y, x)
+ self.assertIsNot(y, x)
def test_copy_inst_vanilla(self):
class C:
return self.foo == other.foo
x = C(42)
self.assertEqual(copy.copy(x), x)
+ # State with boolean value is false (issue #25718)
+ x = C(0.0)
+ self.assertEqual(copy.copy(x), x)
# The deepcopy() method
pass
tests = [None, 42, 2**100, 3.14, True, False, 1j,
"hello", "hello\u1234", f.__code__,
- NewStyle, range(10), Classic, max]
+ NewStyle, Classic, max]
for x in tests:
self.assertIs(copy.deepcopy(x), x)
self.assertEqual(y, x)
self.assertIsNot(y, x)
self.assertIsNot(y.foo, x.foo)
+ # State with boolean value is false (issue #25718)
+ x = C([])
+ y = copy.deepcopy(x)
+ self.assertEqual(y, x)
+ self.assertIsNot(y, x)
+ self.assertIsNot(y.foo, x.foo)
def test_deepcopy_reflexive_inst(self):
class C:
self.assertIsNot(y, x)
self.assertIs(y.foo, y)
+ def test_deepcopy_range(self):
+ class I(int):
+ pass
+ x = range(I(10))
+ y = copy.deepcopy(x)
+ self.assertIsNot(y, x)
+ self.assertEqual(y, x)
+ self.assertIsNot(y.stop, x.stop)
+ self.assertEqual(y.stop, x.stop)
+ self.assertIsInstance(y.stop, I)
+
# _reconstruct()
def test_reconstruct_string(self):
"coroutine ignored GeneratorExit"):
c.close()
+ def test_func_15(self):
+ # See http://bugs.python.org/issue25887 for details
+
+ async def spammer():
+ return 'spam'
+ async def reader(coro):
+ return await coro
+
+ spammer_coro = spammer()
+
+ with self.assertRaisesRegex(StopIteration, 'spam'):
+ reader(spammer_coro).send(None)
+
+ with self.assertRaisesRegex(RuntimeError,
+ 'cannot reuse already awaited coroutine'):
+ reader(spammer_coro).send(None)
+
+ def test_func_16(self):
+ # See http://bugs.python.org/issue25887 for details
+
+ @types.coroutine
+ def nop():
+ yield
+ async def send():
+ await nop()
+ return 'spam'
+ async def read(coro):
+ await nop()
+ return await coro
+
+ spammer = send()
+
+ reader = read(spammer)
+ reader.send(None)
+ reader.send(None)
+ with self.assertRaisesRegex(Exception, 'ham'):
+ reader.throw(Exception('ham'))
+
+ reader = read(spammer)
+ reader.send(None)
+ with self.assertRaisesRegex(RuntimeError,
+ 'cannot reuse already awaited coroutine'):
+ reader.send(None)
+
+ with self.assertRaisesRegex(RuntimeError,
+ 'cannot reuse already awaited coroutine'):
+ reader.throw(Exception('wat'))
+
+ def test_func_17(self):
+ # See http://bugs.python.org/issue25887 for details
+
+ async def coroutine():
+ return 'spam'
+
+ coro = coroutine()
+ with self.assertRaisesRegex(StopIteration, 'spam'):
+ coro.send(None)
+
+ with self.assertRaisesRegex(RuntimeError,
+ 'cannot reuse already awaited coroutine'):
+ coro.send(None)
+
+ with self.assertRaisesRegex(RuntimeError,
+ 'cannot reuse already awaited coroutine'):
+ coro.throw(Exception('wat'))
+
+ # Closing a coroutine shouldn't raise any exception even if it's
+ # already closed/exhausted (similar to generators)
+ coro.close()
+ coro.close()
+
+ def test_func_18(self):
+ # See http://bugs.python.org/issue25887 for details
+
+ async def coroutine():
+ return 'spam'
+
+ coro = coroutine()
+ await_iter = coro.__await__()
+ it = iter(await_iter)
+
+ with self.assertRaisesRegex(StopIteration, 'spam'):
+ it.send(None)
+
+ with self.assertRaisesRegex(RuntimeError,
+ 'cannot reuse already awaited coroutine'):
+ it.send(None)
+
+ with self.assertRaisesRegex(RuntimeError,
+ 'cannot reuse already awaited coroutine'):
+ # Although the iterator protocol requires iterators to
+ # raise another StopIteration here, we don't want to do
+ # that. In this particular case, the iterator will raise
+ # a RuntimeError, so that 'yield from' and 'await'
+ # expressions will trigger the error, instead of silently
+ # ignoring the call.
+ next(it)
+
+ with self.assertRaisesRegex(RuntimeError,
+ 'cannot reuse already awaited coroutine'):
+ it.throw(Exception('wat'))
+
+ with self.assertRaisesRegex(RuntimeError,
+ 'cannot reuse already awaited coroutine'):
+ it.throw(Exception('wat'))
+
+ # Closing a coroutine shouldn't raise any exception even if it's
+ # already closed/exhausted (similar to generators)
+ it.close()
+ it.close()
+
+ def test_func_19(self):
+ CHK = 0
+
+ @types.coroutine
+ def foo():
+ nonlocal CHK
+ yield
+ try:
+ yield
+ except GeneratorExit:
+ CHK += 1
+
+ async def coroutine():
+ await foo()
+
+ coro = coroutine()
+
+ coro.send(None)
+ coro.send(None)
+
+ self.assertEqual(CHK, 0)
+ coro.close()
+ self.assertEqual(CHK, 1)
+
+ for _ in range(3):
+ # Closing a coroutine shouldn't raise any exception even if it's
+ # already closed/exhausted (similar to generators)
+ coro.close()
+ self.assertEqual(CHK, 1)
+
def test_cr_await(self):
@types.coroutine
def a():
with self.assertRaises(Marker):
c.throw(ZeroDivisionError)
+ def test_await_15(self):
+ @types.coroutine
+ def nop():
+ yield
+
+ async def coroutine():
+ await nop()
+
+ async def waiter(coro):
+ await coro
+
+ coro = coroutine()
+ coro.send(None)
+
+ with self.assertRaisesRegex(RuntimeError,
+ "coroutine is being awaited already"):
+ waiter(coro).send(None)
+
def test_with_1(self):
class Manager:
def __init__(self, name):
buffer = []
async def test1():
- async for i1, i2 in AsyncIter():
- buffer.append(i1 + i2)
+ with self.assertWarnsRegex(PendingDeprecationWarning, "legacy"):
+ async for i1, i2 in AsyncIter():
+ buffer.append(i1 + i2)
yielded, _ = run_async(test1())
# Make sure that __aiter__ was called only once
buffer = []
async def test2():
nonlocal buffer
- async for i in AsyncIter():
- buffer.append(i[0])
- if i[0] == 20:
- break
- else:
- buffer.append('what?')
+ with self.assertWarnsRegex(PendingDeprecationWarning, "legacy"):
+ async for i in AsyncIter():
+ buffer.append(i[0])
+ if i[0] == 20:
+ break
+ else:
+ buffer.append('what?')
buffer.append('end')
yielded, _ = run_async(test2())
buffer = []
async def test3():
nonlocal buffer
- async for i in AsyncIter():
- if i[0] > 20:
- continue
- buffer.append(i[0])
- else:
- buffer.append('what?')
+ with self.assertWarnsRegex(PendingDeprecationWarning, "legacy"):
+ async for i in AsyncIter():
+ if i[0] > 20:
+ continue
+ buffer.append(i[0])
+ else:
+ buffer.append('what?')
buffer.append('end')
yielded, _ = run_async(test3())
def test_for_4(self):
class I:
- async def __aiter__(self):
+ def __aiter__(self):
return self
def __anext__(self):
return 123
async def foo():
- async for i in I():
- print('never going to happen')
+ with self.assertWarnsRegex(PendingDeprecationWarning, "legacy"):
+ async for i in I():
+ print('never going to happen')
with self.assertRaisesRegex(
TypeError,
def __init__(self):
self.i = 0
- async def __aiter__(self):
+ def __aiter__(self):
return self
async def __anext__(self):
I += 1
I += 1000
- run_async(main())
+ with warnings.catch_warnings():
+ warnings.simplefilter("error")
+ # Test that __aiter__ that returns an asyncronous iterator
+ # directly does not throw any warnings.
+ run_async(main())
self.assertEqual(I, 111011)
self.assertEqual(sys.getrefcount(manager), mrefs_before)
1/0
async def foo():
nonlocal CNT
+ with self.assertWarnsRegex(PendingDeprecationWarning, "legacy"):
+ async for i in AI():
+ CNT += 1
+ CNT += 10
+ with self.assertRaises(ZeroDivisionError):
+ run_async(foo())
+ self.assertEqual(CNT, 0)
+
+ def test_for_8(self):
+ CNT = 0
+ class AI:
+ def __aiter__(self):
+ 1/0
+ async def foo():
+ nonlocal CNT
async for i in AI():
CNT += 1
CNT += 10
with self.assertRaises(ZeroDivisionError):
- run_async(foo())
+ with warnings.catch_warnings():
+ warnings.simplefilter("error")
+ # Test that if __aiter__ raises an exception it propagates
+ # without any kind of warning.
+ run_async(foo())
self.assertEqual(CNT, 0)
+ def test_for_9(self):
+ # Test that PendingDeprecationWarning can safely be converted into
+ # an exception (__aiter__ should not have a chance to raise
+ # a ZeroDivisionError.)
+ class AI:
+ async def __aiter__(self):
+ 1/0
+ async def foo():
+ async for i in AI():
+ pass
+
+ with self.assertRaises(PendingDeprecationWarning):
+ with warnings.catch_warnings():
+ warnings.simplefilter("error")
+ run_async(foo())
+
+ def test_for_10(self):
+ # Test that PendingDeprecationWarning can safely be converted into
+ # an exception.
+ class AI:
+ async def __aiter__(self):
+ pass
+ async def foo():
+ async for i in AI():
+ pass
+
+ with self.assertRaises(PendingDeprecationWarning):
+ with warnings.catch_warnings():
+ warnings.simplefilter("error")
+ run_async(foo())
+
def test_copy(self):
async def func(): pass
coro = func()
self.assertEqual(len(pw), method.total_size)
def test_methods(self):
- # Gurantee that METHOD_CRYPT is the last method in crypt.methods.
+ # Guarantee that METHOD_CRYPT is the last method in crypt.methods.
self.assertTrue(len(crypt.methods) >= 1)
self.assertEqual(crypt.METHOD_CRYPT, crypt.methods[-1])
# Copyright (C) 2001,2002 Python Software Foundation
# csv package unit tests
+import copy
import io
import sys
import os
from tempfile import TemporaryFile
import csv
import gc
+import pickle
from test import support
class Test_Csv(unittest.TestCase):
self.assertRaises(TypeError, csv.reader, [], quoting = -1)
self.assertRaises(TypeError, csv.reader, [], quoting = 100)
+ # See issue #22995
+ ## def test_copy(self):
+ ## for name in csv.list_dialects():
+ ## dialect = csv.get_dialect(name)
+ ## self.assertRaises(TypeError, copy.copy, dialect)
+
+ ## def test_pickle(self):
+ ## for name in csv.list_dialects():
+ ## dialect = csv.get_dialect(name)
+ ## for proto in range(pickle.HIGHEST_PROTOCOL + 1):
+ ## self.assertRaises(TypeError, pickle.dumps, dialect, proto)
+
class TestCsvBase(unittest.TestCase):
def readerAssertEqual(self, input, expected_result):
with TemporaryFile("w+", newline='') as fileobj:
# If either of these don't exist, skip the tests.
curses = import_module('curses')
-curses.panel = import_module('curses.panel')
+import_module('curses.panel')
+import_module('curses.ascii')
-term = os.environ.get('TERM', 'unknown')
+def requires_curses_func(name):
+ return unittest.skipUnless(hasattr(curses, name),
+ 'requires curses.%s' % name)
-@unittest.skipUnless(sys.__stdout__.isatty(), 'sys.__stdout__ is not a tty')
-@unittest.skipIf(term == 'unknown',
+term = os.environ.get('TERM')
+
+# If newterm was supported we could use it instead of initscr and not exit
+@unittest.skipIf(not term or term == 'unknown',
"$TERM=%r, calling initscr() may cause exit" % term)
@unittest.skipIf(sys.platform == "cygwin",
"cygwin's curses mostly just hangs")
class TestCurses(unittest.TestCase):
+
@classmethod
def setUpClass(cls):
- curses.setupterm(fd=sys.__stdout__.fileno())
+ 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()
+ # 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
def setUp(self):
if verbose:
for meth in [stdscr.addch, stdscr.addstr]:
for args in [('a'), ('a', curses.A_BOLD),
(4,4, 'a'), (5,5, 'a', curses.A_BOLD)]:
- meth(*args)
+ with self.subTest(meth=meth.__qualname__, args=args):
+ meth(*args)
for meth in [stdscr.box, stdscr.clear, stdscr.clrtobot,
stdscr.clrtoeol, stdscr.cursyncup, stdscr.delch,
win.noutrefresh, stdscr.redrawwin, stdscr.refresh,
stdscr.standout, stdscr.standend, stdscr.syncdown,
stdscr.syncup, stdscr.touchwin, stdscr.untouchwin]:
- meth()
+ with self.subTest(meth=meth.__qualname__):
+ meth()
stdscr.addnstr('1234', 3)
stdscr.addnstr('1234', 3, curses.A_BOLD)
def test_module_funcs(self):
"Test module-level functions"
- stdscr = self.stdscr
for func in [curses.baudrate, curses.beep, curses.can_change_color,
curses.cbreak, curses.def_prog_mode, curses.doupdate,
curses.filter, curses.flash, curses.flushinp,
curses.noqiflush, curses.noraw,
curses.reset_prog_mode, curses.termattrs,
curses.termname, curses.erasechar, curses.getsyx]:
- func()
+ with self.subTest(func=func.__qualname__):
+ func()
# Functions that actually need arguments
if curses.tigetstr("cnorm"):
curses.delay_output(1)
curses.echo() ; curses.echo(1)
- f = tempfile.TemporaryFile()
- stdscr.putwin(f)
- f.seek(0)
- curses.getwin(f)
- f.close()
+ with tempfile.TemporaryFile() as f:
+ self.stdscr.putwin(f)
+ f.seek(0)
+ curses.getwin(f)
curses.halfdelay(1)
curses.intrflush(1)
curses.ungetch('a')
curses.use_env(1)
- # Functions only available on a few platforms
- if curses.has_colors():
- curses.start_color()
- curses.init_pair(2, 1,1)
- curses.color_content(1)
- curses.color_pair(2)
- curses.pair_content(curses.COLOR_PAIRS - 1)
- curses.pair_number(0)
-
- if hasattr(curses, 'use_default_colors'):
- curses.use_default_colors()
-
- if hasattr(curses, 'keyname'):
- curses.keyname(13)
-
- if hasattr(curses, 'has_key'):
- curses.has_key(13)
-
- if hasattr(curses, 'getmouse'):
- (availmask, oldmask) = curses.mousemask(curses.BUTTON1_PRESSED)
- # availmask indicates that mouse stuff not available.
- if availmask != 0:
- curses.mouseinterval(10)
- # just verify these don't cause errors
- curses.ungetmouse(0, 0, 0, 0, curses.BUTTON1_PRESSED)
- m = curses.getmouse()
-
- if hasattr(curses, 'is_term_resized'):
- curses.is_term_resized(*stdscr.getmaxyx())
- if hasattr(curses, 'resizeterm'):
- curses.resizeterm(*stdscr.getmaxyx())
- if hasattr(curses, 'resize_term'):
- curses.resize_term(*stdscr.getmaxyx())
-
- def test_unctrl(self):
- from curses import ascii
- for ch, expected in [('a', 'a'), ('A', 'A'),
- (';', ';'), (' ', ' '),
- ('\x7f', '^?'), ('\n', '^J'), ('\0', '^@'),
- # Meta-bit characters
- ('\x8a', '!^J'), ('\xc1', '!A'),
- ]:
- self.assertEqual(ascii.unctrl(ch), expected,
- 'curses.unctrl fails on character %r' % ch)
-
+ # Functions only available on a few platforms
+ def test_colors_funcs(self):
+ if not curses.has_colors():
+ self.skip('requires colors support')
+ curses.start_color()
+ curses.init_pair(2, 1,1)
+ curses.color_content(1)
+ curses.color_pair(2)
+ curses.pair_content(curses.COLOR_PAIRS - 1)
+ curses.pair_number(0)
+
+ if hasattr(curses, 'use_default_colors'):
+ curses.use_default_colors()
+
+ @requires_curses_func('keyname')
+ def test_keyname(self):
+ curses.keyname(13)
+
+ @requires_curses_func('has_key')
+ def test_has_key(self):
+ curses.has_key(13)
+
+ @requires_curses_func('getmouse')
+ def test_getmouse(self):
+ (availmask, oldmask) = curses.mousemask(curses.BUTTON1_PRESSED)
+ if availmask == 0:
+ self.skip('mouse stuff not available')
+ curses.mouseinterval(10)
+ # just verify these don't cause errors
+ curses.ungetmouse(0, 0, 0, 0, curses.BUTTON1_PRESSED)
+ m = curses.getmouse()
def test_userptr_without_set(self):
w = curses.newwin(10, 10)
panel.set_userptr(A())
panel.set_userptr(None)
- @unittest.skipUnless(hasattr(curses, 'resizeterm'),
- 'resizeterm not available')
+ def test_new_curses_panel(self):
+ panel = curses.panel.new_panel(self.stdscr)
+ self.assertRaises(TypeError, type(panel))
+
+ @requires_curses_func('is_term_resized')
+ def test_is_term_resized(self):
+ curses.is_term_resized(*self.stdscr.getmaxyx())
+
+ @requires_curses_func('resize_term')
def test_resize_term(self):
+ curses.resize_term(*self.stdscr.getmaxyx())
+
+ @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
curses.ungetch(1025)
self.stdscr.getkey()
- @unittest.skipUnless(hasattr(curses, 'unget_wch'),
- 'unget_wch not available')
+ @requires_curses_func('unget_wch')
def test_unget_wch(self):
stdscr = self.stdscr
encoding = stdscr.encoding
def test_issue10570(self):
b = curses.tparm(curses.tigetstr("cup"), 5, 3)
self.assertIs(type(b), bytes)
- curses.putp(b)
def test_encoding(self):
stdscr = self.stdscr
import codecs
encoding = stdscr.encoding
codecs.lookup(encoding)
-
with self.assertRaises(TypeError):
stdscr.encoding = 10
-
stdscr.encoding = encoding
with self.assertRaises(TypeError):
del stdscr.encoding
# be reasonably certain the generated parsing code will be
# correct too.
human_readable_signature = stdscr.addch.__doc__.split("\n")[0]
- offset = human_readable_signature.find("[y, x,]")
- assert offset >= 0, ""
+ self.assertIn("[y, x,]", human_readable_signature)
+
+
+class MiscTests(unittest.TestCase):
def test_update_lines_cols(self):
# this doesn't actually test that LINES and COLS are updated,
curses.update_lines_cols()
+class TestAscii(unittest.TestCase):
+
+ def test_unctrl(self):
+ unctrl = curses.ascii.unctrl
+ self.assertEqual(unctrl('a'), 'a')
+ self.assertEqual(unctrl('A'), 'A')
+ self.assertEqual(unctrl(';'), ';')
+ self.assertEqual(unctrl(' '), ' ')
+ self.assertEqual(unctrl('\x7f'), '^?')
+ self.assertEqual(unctrl('\n'), '^J')
+ self.assertEqual(unctrl('\0'), '^@')
+ # Meta-bit characters
+ self.assertEqual(unctrl('\x8a'), '!^J')
+ self.assertEqual(unctrl('\xc1'), '!A')
+
+
if __name__ == '__main__':
unittest.main()
self.assertTrue(P.HAVE_THREADS is True or P.HAVE_THREADS is False)
self.assertEqual(C.__version__, P.__version__)
- self.assertEqual(C.__libmpdec_version__, P.__libmpdec_version__)
self.assertEqual(dir(C), dir(P))
s.insert(i, 'Z')
self.assertEqual(list(d), s)
+ def test_insert_bug_26194(self):
+ data = 'ABC'
+ d = deque(data, maxlen=len(data))
+ with self.assertRaises(IndexError):
+ d.insert(2, None)
+
+ elements = 'ABCDEFGHI'
+ for i in range(-len(elements), len(elements)):
+ d = deque(elements, maxlen=len(elements)+1)
+ d.insert(i, 'Z')
+ if i >= 0:
+ self.assertEqual(d[i], 'Z')
+ else:
+ self.assertEqual(d[i-1], 'Z')
+
def test_imul(self):
for n in (-10, -1, 0, 1, 2, 10, 1000):
d = deque()
## self.assertEqual(id(e), id(e[-1]))
def test_iterator_pickle(self):
- data = deque(range(200))
+ orig = deque(range(200))
+ data = [i*1.01 for i in orig]
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
- it = itorg = iter(data)
- d = pickle.dumps(it, proto)
- it = pickle.loads(d)
- self.assertEqual(type(itorg), type(it))
- self.assertEqual(list(it), list(data))
-
- it = pickle.loads(d)
- next(it)
- d = pickle.dumps(it, proto)
- self.assertEqual(list(it), list(data)[1:])
+ # initial iterator
+ itorg = iter(orig)
+ dump = pickle.dumps((itorg, orig), proto)
+ it, d = pickle.loads(dump)
+ for i, x in enumerate(data):
+ d[i] = x
+ self.assertEqual(type(it), type(itorg))
+ self.assertEqual(list(it), data)
+
+ # running iterator
+ next(itorg)
+ dump = pickle.dumps((itorg, orig), proto)
+ it, d = pickle.loads(dump)
+ for i, x in enumerate(data):
+ d[i] = x
+ self.assertEqual(type(it), type(itorg))
+ self.assertEqual(list(it), data[1:])
+
+ # empty iterator
+ for i in range(1, len(data)):
+ next(itorg)
+ dump = pickle.dumps((itorg, orig), proto)
+ it, d = pickle.loads(dump)
+ for i, x in enumerate(data):
+ d[i] = x
+ self.assertEqual(type(it), type(itorg))
+ self.assertEqual(list(it), [])
+
+ # exhausted iterator
+ self.assertRaises(StopIteration, next, itorg)
+ dump = pickle.dumps((itorg, orig), proto)
+ it, d = pickle.loads(dump)
+ for i, x in enumerate(data):
+ d[i] = x
+ self.assertEqual(type(it), type(itorg))
+ self.assertEqual(list(it), [])
def test_deepcopy(self):
mut = [10]
@support.cpython_only
def test_sizeof(self):
BLOCKLEN = 64
- basesize = support.calcobjsize('2P4nlP')
- blocksize = struct.calcsize('2P%dP' % BLOCKLEN)
+ basesize = support.calcvobjsize('2P4nP')
+ blocksize = struct.calcsize('P%dPP' % BLOCKLEN)
self.assertEqual(object.__sizeof__(deque()), basesize)
check = self.check_sizeof
check(deque(), basesize + blocksize)
# For now, bypass tests that require slicing
pass
+ def test_free_after_iterating(self):
+ # For now, bypass tests that require slicing
+ self.skipTest("Exhausted deque iterator doesn't free a deque")
+
#==============================================================================
libreftest = """
b.a = a
z = deepcopy(a) # This blew up before
- def test_unintialized_modules(self):
+ def test_uninitialized_modules(self):
# Testing uninitialized module objects...
from types import ModuleType as M
m = M.__new__(M)
objcopy2 = deepcopy(objcopy)
self._assert_is_copy(obj, objcopy2)
+ def test_issue24097(self):
+ # Slot name is freed inside __getattr__ and is later used.
+ class S(str): # Not interned
+ pass
+ class A:
+ __slotnames__ = [S('spam')]
+ def __getattr__(self, attr):
+ if attr == 'spam':
+ A.__slotnames__[:] = [S('spam')]
+ return 42
+ else:
+ raise AttributeError
+
+ import copyreg
+ expected = (copyreg.__newobj__, (A,), (None, {'spam': 42}), None, None)
+ self.assertEqual(A().__reduce__(2), expected) # Shouldn't crash
+
class SharedKeyTests(unittest.TestCase):
itorg = iter(data.items())
d = pickle.dumps(itorg, proto)
it = pickle.loads(d)
- # note that the type of type of the unpickled iterator
+ # note that the type of the unpickled iterator
# is not necessarily the same as the original. It is
# merely an object supporting the iterator protocol, yielding
# the same objects as the original one.
d = {X(): 0, 1: 1}
self.assertRaises(RuntimeError, d.update, other)
+ def test_free_after_iterating(self):
+ support.check_free_after_iterating(self, iter, dict)
+ support.check_free_after_iterating(self, lambda d: iter(d.keys()), dict)
+ support.check_free_after_iterating(self, lambda d: iter(d.values()), dict)
+ support.check_free_after_iterating(self, lambda d: iter(d.items()), dict)
+
from test import mapping_tests
class GeneralMappingTests(mapping_tests.BasicTestMappingProtocol):
self.assertEqual(d1.keys() & set(d1.keys()), {'a', 'b'})
self.assertEqual(d1.keys() & set(d2.keys()), {'b'})
self.assertEqual(d1.keys() & set(d3.keys()), set())
+ self.assertEqual(d1.keys() & tuple(d1.keys()), {'a', 'b'})
self.assertEqual(d1.keys() | d1.keys(), {'a', 'b'})
self.assertEqual(d1.keys() | d2.keys(), {'a', 'b', 'c'})
self.assertEqual(d1.keys() | set(d2.keys()), {'a', 'b', 'c'})
self.assertEqual(d1.keys() | set(d3.keys()),
{'a', 'b', 'd', 'e'})
+ self.assertEqual(d1.keys() | (1, 2), {'a', 'b', 1, 2})
self.assertEqual(d1.keys() ^ d1.keys(), set())
self.assertEqual(d1.keys() ^ d2.keys(), {'a', 'c'})
self.assertEqual(d1.keys() ^ set(d2.keys()), {'a', 'c'})
self.assertEqual(d1.keys() ^ set(d3.keys()),
{'a', 'b', 'd', 'e'})
+ self.assertEqual(d1.keys() ^ tuple(d2.keys()), {'a', 'c'})
self.assertEqual(d1.keys() - d1.keys(), set())
self.assertEqual(d1.keys() - d2.keys(), {'a'})
self.assertEqual(d1.keys() - set(d1.keys()), set())
self.assertEqual(d1.keys() - set(d2.keys()), {'a'})
self.assertEqual(d1.keys() - set(d3.keys()), {'a', 'b'})
+ self.assertEqual(d1.keys() - (0, 1), {'a', 'b'})
self.assertFalse(d1.keys().isdisjoint(d1.keys()))
self.assertFalse(d1.keys().isdisjoint(d2.keys()))
def __init__(self, x):
self.x = x == 1
+ @staticmethod
+ def sm(x):
+ x = x == 1
+
+ @classmethod
+ def cm(cls, x):
+ cls.x = x == 1
+
dis_c_instance_method = """\
- %-4d 0 LOAD_FAST 1 (x)
+%3d 0 LOAD_FAST 1 (x)
3 LOAD_CONST 1 (1)
6 COMPARE_OP 2 (==)
9 LOAD_FAST 0 (self)
18 RETURN_VALUE
"""
+dis_c_class_method = """\
+%3d 0 LOAD_FAST 1 (x)
+ 3 LOAD_CONST 1 (1)
+ 6 COMPARE_OP 2 (==)
+ 9 LOAD_FAST 0 (cls)
+ 12 STORE_ATTR 0 (x)
+ 15 LOAD_CONST 0 (None)
+ 18 RETURN_VALUE
+""" % (_C.cm.__code__.co_firstlineno + 2,)
+
+dis_c_static_method = """\
+%3d 0 LOAD_FAST 0 (x)
+ 3 LOAD_CONST 1 (1)
+ 6 COMPARE_OP 2 (==)
+ 9 STORE_FAST 0 (x)
+ 12 LOAD_CONST 0 (None)
+ 15 RETURN_VALUE
+""" % (_C.sm.__code__.co_firstlineno + 2,)
+
+# Class disassembling info has an extra newline at end.
+dis_c = """\
+Disassembly of %s:
+%s
+Disassembly of %s:
+%s
+Disassembly of %s:
+%s
+""" % (_C.__init__.__name__, dis_c_instance_method,
+ _C.cm.__name__, dis_c_class_method,
+ _C.sm.__name__, dis_c_static_method)
+
def _f(a):
print(a)
return 1
dis_f = """\
- %-4d 0 LOAD_GLOBAL 0 (print)
+%3d 0 LOAD_GLOBAL 0 (print)
3 LOAD_FAST 0 (a)
6 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
9 POP_TOP
- %-4d 10 LOAD_CONST 1 (1)
+%3d 10 LOAD_CONST 1 (1)
13 RETURN_VALUE
""" % (_f.__code__.co_firstlineno + 1,
_f.__code__.co_firstlineno + 2)
pass
dis_bug708901 = """\
- %-4d 0 SETUP_LOOP 23 (to 26)
+%3d 0 SETUP_LOOP 23 (to 26)
3 LOAD_GLOBAL 0 (range)
6 LOAD_CONST 1 (1)
- %-4d 9 LOAD_CONST 2 (10)
+%3d 9 LOAD_CONST 2 (10)
12 CALL_FUNCTION 2 (2 positional, 0 keyword pair)
15 GET_ITER
>> 16 FOR_ITER 6 (to 25)
19 STORE_FAST 0 (res)
- %-4d 22 JUMP_ABSOLUTE 16
+%3d 22 JUMP_ABSOLUTE 16
>> 25 POP_BLOCK
>> 26 LOAD_CONST 0 (None)
29 RETURN_VALUE
"""
dis_traceback = """\
- %-4d 0 SETUP_EXCEPT 12 (to 15)
+%3d 0 SETUP_EXCEPT 12 (to 15)
- %-4d 3 LOAD_CONST 1 (1)
+%3d 3 LOAD_CONST 1 (1)
6 LOAD_CONST 2 (0)
--> 9 BINARY_TRUE_DIVIDE
10 POP_TOP
11 POP_BLOCK
12 JUMP_FORWARD 46 (to 61)
- %-4d >> 15 DUP_TOP
+%3d >> 15 DUP_TOP
16 LOAD_GLOBAL 0 (Exception)
19 COMPARE_OP 10 (exception match)
22 POP_JUMP_IF_FALSE 60
29 POP_TOP
30 SETUP_FINALLY 14 (to 47)
- %-4d 33 LOAD_FAST 0 (e)
+%3d 33 LOAD_FAST 0 (e)
36 LOAD_ATTR 1 (__traceback__)
39 STORE_FAST 1 (tb)
42 POP_BLOCK
57 JUMP_FORWARD 1 (to 61)
>> 60 END_FINALLY
- %-4d >> 61 LOAD_FAST 1 (tb)
+%3d >> 61 LOAD_FAST 1 (tb)
64 RETURN_VALUE
""" % (TRACEBACK_CODE.co_firstlineno + 1,
TRACEBACK_CODE.co_firstlineno + 2,
def test_disassemble_bytes(self):
self.do_disassembly_test(_f.__code__.co_code, dis_f_co_code)
- def test_disassemble_method(self):
+ def test_disassemble_class(self):
+ self.do_disassembly_test(_C, dis_c)
+
+ def test_disassemble_instance_method(self):
self.do_disassembly_test(_C(1).__init__, dis_c_instance_method)
- def test_disassemble_method_bytes(self):
+ def test_disassemble_instance_method_bytes(self):
method_bytecode = _C(1).__init__.__code__.co_code
self.do_disassembly_test(method_bytecode, dis_c_instance_method_bytes)
+ def test_disassemble_static_method(self):
+ self.do_disassembly_test(_C.sm, dis_c_static_method)
+
+ def test_disassemble_class_method(self):
+ self.do_disassembly_test(_C.cm, dis_c_class_method)
+
def test_disassemble_generator(self):
gen_func_disas = self.get_disassembly(_g) # Disassemble generator function
gen_disas = self.get_disassembly(_g(1)) # Disassemble generator itself
>>> test.lineno + e2.lineno
26
-If the docstring contains inconsistant leading whitespace in the
+If the docstring contains inconsistent leading whitespace in the
expected output of an example, then `DocTest` will raise a ValueError:
>>> docstring = r'''
>>> with open(fn, 'wb') as f:
... f.write(b'Test:\r\n\r\n >>> x = 1 + 1\r\n\r\nDone.\r\n')
35
- >>> doctest.testfile(fn, False)
+ >>> doctest.testfile(fn, module_relative=False, verbose=False)
TestResults(failed=0, attempted=1)
>>> os.remove(fn)
>>> with open(fn, 'wb') as f:
... f.write(b'Test:\n\n >>> x = 1 + 1\n\nDone.\n')
30
- >>> doctest.testfile(fn, False)
+ >>> doctest.testfile(fn, module_relative=False, verbose=False)
TestResults(failed=0, attempted=1)
>>> os.remove(fn)
with two tests, both of the files having "errors" in the tests that can be made
non-errors by applying the appropriate doctest options to the run (ELLIPSIS in
the first file, NORMALIZE_WHITESPACE in the second). This combination will
-allow to thoroughly test the -f and -o flags, as well as the doctest command's
+allow thoroughly testing the -f and -o flags, as well as the doctest command's
ability to process more than one file on the command line and, since the second
file ends in '.py', its handling of python module files (as opposed to straight
text files).
def test_initlock(self):
#Make sure locks start locked
- self.assertTrue(not self.lock.locked(),
+ self.assertFalse(self.lock.locked(),
"Lock object is not initialized unlocked.")
def test_release(self):
# Test self.lock.release()
self.lock.acquire()
self.lock.release()
- self.assertTrue(not self.lock.locked(),
+ self.assertFalse(self.lock.locked(),
"Lock object did not release properly.")
def test_improper_release(self):
def test_cond_acquire_fail(self):
#Test acquiring locked lock returns False
self.lock.acquire(0)
- self.assertTrue(not self.lock.acquire(0),
+ self.assertFalse(self.lock.acquire(0),
"Conditional acquiring of a locked lock incorrectly "
"succeeded.")
def test_uncond_acquire_return_val(self):
#Make sure that an unconditional locking returns True.
- self.assertTrue(self.lock.acquire(1) is True,
+ self.assertIs(self.lock.acquire(1), True,
"Unconditional locking did not return True.")
- self.assertTrue(self.lock.acquire() is True)
+ self.assertIs(self.lock.acquire(), True)
def test_uncond_acquire_blocking(self):
#Make sure that unconditional acquiring of a locked lock blocks.
end_time = int(time.time())
if support.verbose:
print("done")
- self.assertTrue((end_time - start_time) >= DELAY,
+ self.assertGreaterEqual(end_time - start_time, DELAY,
"Blocking by unconditional acquiring failed.")
class MiscTests(unittest.TestCase):
#Test sanity of _thread.get_ident()
self.assertIsInstance(_thread.get_ident(), int,
"_thread.get_ident() returned a non-integer")
- self.assertTrue(_thread.get_ident() != 0,
+ self.assertNotEqual(_thread.get_ident(), 0,
"_thread.get_ident() returned 0")
def test_LockType(self):
time.sleep(DELAY)
if support.verbose:
print('done')
- self.assertTrue(testing_queue.qsize() == thread_count,
+ self.assertEqual(testing_queue.qsize(), thread_count,
"Not all %s threads executed properly after %s sec." %
(thread_count, DELAY))
# Note that it is undefined what we should do for error recovery when
# there are duplicate parameter names or duplicate parts in a split
# part. We choose to ignore all duplicate parameters after the first
- # and to take duplicate or missing rfc 2231 parts in apperance order.
+ # and to take duplicate or missing rfc 2231 parts in appearance order.
# This is backward compatible with get_param's behavior, but the
# decisions are arbitrary.
import unittest
from test.support import run_unittest
-from test.test_email.test_email import TestEmailBase
+from test.test_email import TestEmailBase
from email.charset import Charset
from email.header import Header, decode_header
from email.message import Message
raise unittest.SkipTest
-\f
+
class TestEmailAsianCodecs(TestEmailBase):
def test_japanese_codecs(self):
eq = self.ndiffAssertEqual
self.assertEqual(jhello, ustr)
-\f
+
if __name__ == '__main__':
unittest.main()
self.assertEqual(m.get_content(), content)
def test_set_application_octet_stream_with_8bit_cte(self):
- # In 8bit mode, univeral line end logic applies. It is up to the
+ # In 8bit mode, universal line end logic applies. It is up to the
# application to make sure the lines are short enough; we don't check.
m = self._make_message()
content = b'b\xFFgus\tcon\nt\rent\n' + b'z'*60 + b'\n'
with self.assertRaisesRegex(self.MyDefect, "the telly is broken"):
self.MyPolicy(raise_on_defect=True).handle_defect(foo, defect)
- def test_overriden_register_defect_works(self):
+ def test_overridden_register_defect_works(self):
foo = self.MyObj()
defect1 = self.MyDefect("one")
my_policy = self.MyPolicy()
import os
import unittest
from io import StringIO
-from types import ListType
-from email.test.test_email import TestEmailBase
-from test.support import TestSkipped, run_unittest
+from test.test_email import TestEmailBase
+from test.support import run_unittest
import email
from email import __file__ as testfile
try:
openfile('crispin-torture.txt')
except OSError:
- raise TestSkipped
+ raise unittest.SkipTest
+
-\f
class TortureBase(TestEmailBase):
def _msgobj(self, filename):
fp = openfile(filename)
return msg
-\f
+
class TestCrispinTorture(TortureBase):
# Mark Crispin's torture test from the SquirrelMail project
def test_mondo_message(self):
neq = self.ndiffAssertEqual
msg = self._msgobj('crispin-torture.txt')
payload = msg.get_payload()
- eq(type(payload), ListType)
+ eq(type(payload), list)
eq(len(payload), 12)
eq(msg.preamble, None)
eq(msg.epilogue, '\n')
audio/x-sun
""")
-\f
def _testclasses():
mod = sys.modules[__name__]
return [getattr(mod, name) for name in dir(mod) if name.startswith('Test')]
run_unittest(testclass)
-\f
if __name__ == '__main__':
unittest.main(defaultTest='suite')
with self.assertRaises(AttributeError):
del Season.SPRING.name
+ def test_bool_of_class(self):
+ class Empty(Enum):
+ pass
+ self.assertTrue(bool(Empty))
+
+ def test_bool_of_member(self):
+ class Count(Enum):
+ zero = 0
+ one = 1
+ two = 2
+ for member in Count:
+ self.assertTrue(bool(member))
+
def test_invalid_names(self):
with self.assertRaises(ValueError):
class Wrong(Enum):
self.assertEqual([k for k,v in WeekDay.__members__.items()
if v.name != k], ['TEUSDAY', ])
+ def test_intenum_from_bytes(self):
+ self.assertIs(IntStooges.from_bytes(b'\x00\x03', 'big'), IntStooges.MOE)
+ with self.assertRaises(ValueError):
+ IntStooges.from_bytes(b'\x00\x05', 'big')
+
+ def test_floatenum_fromhex(self):
+ h = float.hex(FloatStooges.MOE.value)
+ self.assertIs(FloatStooges.fromhex(h), FloatStooges.MOE)
+ h = float.hex(FloatStooges.MOE.value + 0.01)
+ with self.assertRaises(ValueError):
+ FloatStooges.fromhex(h)
+
def test_pickle_enum(self):
if isinstance(Stooges, Exception):
raise Stooges
triple = 3
turkey = 3
+ def test_unique_with_name(self):
+ @unique
+ class Silly(Enum):
+ one = 1
+ two = 'dos'
+ name = 3
+ @unique
+ class Sillier(IntEnum):
+ single = 1
+ name = 2
+ triple = 3
+ value = 4
+
expected_help_output_with_docs = """\
Help on class Color in module %s:
import weakref
import errno
-from test.support import (TESTFN, captured_output, check_impl_detail,
+from test.support import (TESTFN, captured_stderr, check_impl_detail,
check_warnings, cpython_only, gc_collect, run_unittest,
no_tracing, unlink, import_module)
def __init__(self, x):
self.x = x
+class BrokenStrException(Exception):
+ def __str__(self):
+ raise Exception("str() is broken")
+
# XXX This is not really enough, each *operation* should be tested!
class ExceptionTests(unittest.TestCase):
class MyException(Exception, metaclass=Meta):
pass
- with captured_output("stderr") as stderr:
+ with captured_stderr() as stderr:
try:
raise KeyError()
except MyException as e:
os.listdir(__file__)
self.assertEqual(cm.exception.errno, errno.ENOTDIR, cm.exception)
+ def test_unraisable(self):
+ # Issue #22836: PyErr_WriteUnraisable() should give sensible reports
+ class BrokenDel:
+ def __del__(self):
+ exc = ValueError("del is broken")
+ # The following line is included in the traceback report:
+ raise exc
+
+ class BrokenRepr(BrokenDel):
+ def __repr__(self):
+ raise AttributeError("repr() is broken")
+
+ class BrokenExceptionDel:
+ def __del__(self):
+ exc = BrokenStrException()
+ # The following line is included in the traceback report:
+ raise exc
+
+ for test_class in (BrokenDel, BrokenRepr, BrokenExceptionDel):
+ with self.subTest(test_class):
+ obj = test_class()
+ with captured_stderr() as stderr:
+ del obj
+ report = stderr.getvalue()
+ self.assertIn("Exception ignored", report)
+ if test_class is BrokenRepr:
+ self.assertIn("<object repr() failed>", report)
+ else:
+ self.assertIn(test_class.__del__.__qualname__, report)
+ self.assertIn("test_exceptions.py", report)
+ self.assertIn("raise exc", report)
+ if test_class is BrokenExceptionDel:
+ self.assertIn("BrokenStrException", report)
+ self.assertIn("<exception str() failed>", report)
+ else:
+ self.assertIn("ValueError", report)
+ self.assertIn("del is broken", report)
+ self.assertTrue(report.endswith("\n"))
+
+ def test_unhandled(self):
+ # Check for sensible reporting of unhandled exceptions
+ for exc_type in (ValueError, BrokenStrException):
+ with self.subTest(exc_type):
+ try:
+ exc = exc_type("test message")
+ # The following line is included in the traceback report:
+ raise exc
+ except exc_type:
+ with captured_stderr() as stderr:
+ sys.__excepthook__(*sys.exc_info())
+ report = stderr.getvalue()
+ self.assertIn("test_exceptions.py", report)
+ self.assertIn("raise exc", report)
+ self.assertIn(exc_type.__name__, report)
+ if exc_type is BrokenStrException:
+ self.assertIn("<exception str() failed>", report)
+ else:
+ self.assertIn("test message", report)
+ self.assertTrue(report.endswith("\n"))
+
class ImportErrorTests(unittest.TestCase):
>>> g(*Nothing())
Traceback (most recent call last):
...
- TypeError: g() argument after * must be a sequence, not Nothing
+ TypeError: g() argument after * must be an iterable, not Nothing
>>> class Nothing:
... def __len__(self): return 5
>>> g(*Nothing())
Traceback (most recent call last):
...
- TypeError: g() argument after * must be a sequence, not Nothing
+ TypeError: g() argument after * must be an iterable, not Nothing
>>> class Nothing():
... def __len__(self): return 5
>>> g(*Nothing())
0 (1, 2, 3) {}
+Check for issue #4806: Does a TypeError in a generator get propagated with the
+right error message? (Also check with other iterables.)
+
+ >>> def broken(): raise TypeError("myerror")
+ ...
+
+ >>> g(*(broken() for i in range(1)))
+ Traceback (most recent call last):
+ ...
+ TypeError: myerror
+
+ >>> class BrokenIterable1:
+ ... def __iter__(self):
+ ... raise TypeError('myerror')
+ ...
+ >>> g(*BrokenIterable1())
+ Traceback (most recent call last):
+ ...
+ TypeError: myerror
+
+ >>> class BrokenIterable2:
+ ... def __iter__(self):
+ ... yield 0
+ ... raise TypeError('myerror')
+ ...
+ >>> g(*BrokenIterable2())
+ Traceback (most recent call last):
+ ...
+ TypeError: myerror
+
+ >>> class BrokenSequence:
+ ... def __getitem__(self, idx):
+ ... raise TypeError('myerror')
+ ...
+ >>> g(*BrokenSequence())
+ Traceback (most recent call last):
+ ...
+ TypeError: myerror
+
Make sure that the function doesn't stomp the dictionary
>>> d = {'a': 1, 'b': 2, 'c': 3}
>>> h(*h)
Traceback (most recent call last):
...
- TypeError: h() argument after * must be a sequence, not function
+ TypeError: h() argument after * must be an iterable, not function
>>> dir(*h)
Traceback (most recent call last):
...
- TypeError: dir() argument after * must be a sequence, not function
+ TypeError: dir() argument after * must be an iterable, not function
>>> None(*h)
Traceback (most recent call last):
...
- TypeError: NoneType object argument after * must be a sequence, \
+ TypeError: NoneType object argument after * must be an iterable, \
not function
>>> h(**h)
2,
'xyz')
+ def test_fatal_error_without_gil(self):
+ self.check_fatal_error("""
+ import faulthandler
+ faulthandler._fatal_error(b'xyz', True)
+ """,
+ 2,
+ 'xyz')
+
@unittest.skipIf(sys.platform.startswith('openbsd') and HAVE_THREADS,
"Issue #12868: sigaltstack() doesn't work on "
"OpenBSD if Python is compiled with pthread")
sys.stderr = stderr
def test_stderr_None(self):
- # Issue #21497: provide an helpful error if sys.stderr is None,
+ # Issue #21497: provide a helpful error if sys.stderr is None,
# instead of just an attribute error: "None has no attribute fileno".
with self.check_stderr_none():
faulthandler.enable()
if name:
safe_unlink(name)
+class LineReader:
+
+ def __init__(self):
+ self._linesread = []
+
+ @property
+ def linesread(self):
+ try:
+ return self._linesread[:]
+ finally:
+ self._linesread = []
+
+ def openhook(self, filename, mode):
+ self.it = iter(filename.splitlines(True))
+ return self
+
+ def readline(self, size=None):
+ line = next(self.it, '')
+ self._linesread.append(line)
+ return line
+
+ def readlines(self, hint=-1):
+ lines = []
+ size = 0
+ while True:
+ line = self.readline()
+ if not line:
+ return lines
+ lines.append(line)
+ size += len(line)
+ if size >= hint:
+ return lines
+
+ def close(self):
+ pass
+
class BufferSizesTests(unittest.TestCase):
def test_buffer_sizes(self):
# First, run the tests with default and teeny buffer size.
lines = list(fi)
self.assertEqual(lines, [b'spam, bacon, sausage, and spam'])
+ def test_detached_stdin_binary_mode(self):
+ orig_stdin = sys.stdin
+ try:
+ sys.stdin = BytesIO(b'spam, bacon, sausage, and spam')
+ self.assertFalse(hasattr(sys.stdin, 'buffer'))
+ fi = FileInput(files=['-'], mode='rb')
+ lines = list(fi)
+ self.assertEqual(lines, [b'spam, bacon, sausage, and spam'])
+ finally:
+ sys.stdin = orig_stdin
+
def test_file_opening_hook(self):
try:
# cannot use openhook and inplace mode
self.addCleanup(safe_unlink, TESTFN)
with FileInput(files=TESTFN,
- openhook=hook_encoded('ascii'), bufsize=8) as fi:
+ openhook=hook_encoded('ascii')) as fi:
try:
self.assertEqual(fi.readline(), 'A\n')
self.assertEqual(fi.readline(), 'B\n')
self.assertEqual(result, -1, "fileno() should return -1")
+ def test_readline_buffering(self):
+ src = LineReader()
+ with FileInput(files=['line1\nline2', 'line3\n'],
+ openhook=src.openhook) as fi:
+ self.assertEqual(src.linesread, [])
+ self.assertEqual(fi.readline(), 'line1\n')
+ self.assertEqual(src.linesread, ['line1\n'])
+ self.assertEqual(fi.readline(), 'line2')
+ self.assertEqual(src.linesread, ['line2'])
+ self.assertEqual(fi.readline(), 'line3\n')
+ self.assertEqual(src.linesread, ['', 'line3\n'])
+ self.assertEqual(fi.readline(), '')
+ self.assertEqual(src.linesread, [''])
+ self.assertEqual(fi.readline(), '')
+ self.assertEqual(src.linesread, [])
+
+ def test_iteration_buffering(self):
+ src = LineReader()
+ with FileInput(files=['line1\nline2', 'line3\n'],
+ openhook=src.openhook) as fi:
+ self.assertEqual(src.linesread, [])
+ self.assertEqual(next(fi), 'line1\n')
+ self.assertEqual(src.linesread, ['line1\n'])
+ self.assertEqual(next(fi), 'line2')
+ self.assertEqual(src.linesread, ['line2'])
+ self.assertEqual(next(fi), 'line3\n')
+ self.assertEqual(src.linesread, ['', 'line3\n'])
+ self.assertRaises(StopIteration, next, fi)
+ self.assertEqual(src.linesread, [''])
+ self.assertRaises(StopIteration, next, fi)
+ self.assertEqual(src.linesread, [])
+
class MockFileInput:
"""A class that mocks out fileinput.FileInput for use during unit tests"""
test_dir = os.path.dirname(__file__) or os.curdir
format_testfile = os.path.join(test_dir, 'formatfloat_testcases.txt')
+class FloatSubclass(float):
+ pass
+
+class OtherFloatSubclass(float):
+ pass
+
class GeneralFloatCases(unittest.TestCase):
def test_float(self):
return ""
self.assertRaises(TypeError, time.sleep, Foo5())
+ # Issue #24731
+ class F:
+ def __float__(self):
+ return OtherFloatSubclass(42.)
+ self.assertAlmostEqual(float(F()), 42.)
+ self.assertIs(type(float(F())), OtherFloatSubclass)
+ self.assertAlmostEqual(FloatSubclass(F()), 42.)
+ self.assertIs(type(FloatSubclass(F())), FloatSubclass)
+
def test_is_integer(self):
self.assertFalse((1.1).is_integer())
self.assertTrue((1.).is_integer())
else:
self.identical(x, fromHex(toHex(x)))
+ def test_subclass(self):
+ class F(float):
+ def __new__(cls, value):
+ return float.__new__(cls, value + 1)
+
+ f = F.fromhex((1.5).hex())
+ self.assertIs(type(f), F)
+ self.assertEqual(f, 2.5)
+
+ class F2(float):
+ def __init__(self, value):
+ self.foo = 'bar'
+
+ f = F2.fromhex((1.5).hex())
+ self.assertIs(type(f), F2)
+ self.assertEqual(f, 1.5)
+ self.assertEqual(getattr(f, 'foo', 'none'), 'bar')
+
if __name__ == '__main__':
unittest.main()
import signal
import sys
import time
+import unittest
from test.fork_wait import ForkWait
from test.support import (reap_children, get_attribute,
""" return the signature of a partial object """
return (part.func, part.args, part.keywords, part.__dict__)
+class MyTuple(tuple):
+ pass
+
+class BadTuple(tuple):
+ def __add__(self, other):
+ return list(self) + list(other)
+
+class MyDict(dict):
+ pass
+
class TestPartial:
for kwargs_repr in kwargs_reprs])
def test_pickle(self):
- f = self.partial(signature, 'asdf', bar=True)
- f.add_something_to__dict__ = True
+ f = self.partial(signature, ['asdf'], bar=[True])
+ f.attr = []
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
f_copy = pickle.loads(pickle.dumps(f, proto))
- self.assertEqual(signature(f), signature(f_copy))
+ self.assertEqual(signature(f_copy), signature(f))
+
+ def test_copy(self):
+ f = self.partial(signature, ['asdf'], bar=[True])
+ f.attr = []
+ f_copy = copy.copy(f)
+ self.assertEqual(signature(f_copy), signature(f))
+ self.assertIs(f_copy.attr, f.attr)
+ self.assertIs(f_copy.args, f.args)
+ self.assertIs(f_copy.keywords, f.keywords)
+
+ def test_deepcopy(self):
+ f = self.partial(signature, ['asdf'], bar=[True])
+ f.attr = []
+ f_copy = copy.deepcopy(f)
+ self.assertEqual(signature(f_copy), signature(f))
+ self.assertIsNot(f_copy.attr, f.attr)
+ self.assertIsNot(f_copy.args, f.args)
+ self.assertIsNot(f_copy.args[0], f.args[0])
+ self.assertIsNot(f_copy.keywords, f.keywords)
+ self.assertIsNot(f_copy.keywords['bar'], f.keywords['bar'])
+
+ def test_setstate(self):
+ f = self.partial(signature)
+ f.__setstate__((capture, (1,), dict(a=10), dict(attr=[])))
+ self.assertEqual(signature(f),
+ (capture, (1,), dict(a=10), dict(attr=[])))
+ self.assertEqual(f(2, b=20), ((1, 2), {'a': 10, 'b': 20}))
+
+ f.__setstate__((capture, (1,), dict(a=10), None))
+ self.assertEqual(signature(f), (capture, (1,), dict(a=10), {}))
+ self.assertEqual(f(2, b=20), ((1, 2), {'a': 10, 'b': 20}))
+
+ f.__setstate__((capture, (1,), None, None))
+ #self.assertEqual(signature(f), (capture, (1,), {}, {}))
+ self.assertEqual(f(2, b=20), ((1, 2), {'b': 20}))
+ self.assertEqual(f(2), ((1, 2), {}))
+ self.assertEqual(f(), ((1,), {}))
+
+ f.__setstate__((capture, (), {}, None))
+ self.assertEqual(signature(f), (capture, (), {}, {}))
+ self.assertEqual(f(2, b=20), ((2,), {'b': 20}))
+ self.assertEqual(f(2), ((2,), {}))
+ self.assertEqual(f(), ((), {}))
+
+ def test_setstate_errors(self):
+ f = self.partial(signature)
+ self.assertRaises(TypeError, f.__setstate__, (capture, (), {}))
+ self.assertRaises(TypeError, f.__setstate__, (capture, (), {}, {}, None))
+ self.assertRaises(TypeError, f.__setstate__, [capture, (), {}, None])
+ self.assertRaises(TypeError, f.__setstate__, (None, (), {}, None))
+ self.assertRaises(TypeError, f.__setstate__, (capture, None, {}, None))
+ self.assertRaises(TypeError, f.__setstate__, (capture, [], {}, None))
+ self.assertRaises(TypeError, f.__setstate__, (capture, (), [], None))
+
+ def test_setstate_subclasses(self):
+ f = self.partial(signature)
+ f.__setstate__((capture, MyTuple((1,)), MyDict(a=10), None))
+ s = signature(f)
+ self.assertEqual(s, (capture, (1,), dict(a=10), {}))
+ self.assertIs(type(s[1]), tuple)
+ self.assertIs(type(s[2]), dict)
+ r = f()
+ self.assertEqual(r, ((1,), {'a': 10}))
+ self.assertIs(type(r[0]), tuple)
+ self.assertIs(type(r[1]), dict)
+
+ f.__setstate__((capture, BadTuple((1,)), {}, None))
+ s = signature(f)
+ self.assertEqual(s, (capture, (1,), {}, {}))
+ self.assertIs(type(s[1]), tuple)
+ r = f(2)
+ self.assertEqual(r, ((1, 2), {}))
+ self.assertIs(type(r[0]), tuple)
# Issue 6083: Reference counting bug
def test_setstate_refcount(self):
raise IndexError
f = self.partial(object)
- self.assertRaisesRegex(SystemError,
- "new style getargs format but argument is not a tuple",
- f.__setstate__, BadSequence())
+ self.assertRaises(TypeError, f.__setstate__, BadSequence())
class TestPartialPy(TestPartial, unittest.TestCase):
def test_copy(self):
cls = self.__class__
- for f in cls.cached_func[0], cls.cached_meth, cls.cached_staticmeth:
+ def orig(x, y):
+ return 3 * x + y
+ part = self.module.partial(orig, 2)
+ funcs = (cls.cached_func[0], cls.cached_meth, cls.cached_staticmeth,
+ self.module.lru_cache(2)(part))
+ for f in funcs:
with self.subTest(func=f):
f_copy = copy.copy(f)
self.assertIs(f_copy, f)
def test_deepcopy(self):
cls = self.__class__
- for f in cls.cached_func[0], cls.cached_meth, cls.cached_staticmeth:
+ def orig(x, y):
+ return 3 * x + y
+ part = self.module.partial(orig, 2)
+ funcs = (cls.cached_func[0], cls.cached_meth, cls.cached_staticmeth,
+ self.module.lru_cache(2)(part))
+ for f in funcs:
with self.subTest(func=f):
f_copy = copy.deepcopy(f)
self.assertIs(f_copy, f)
object])
# MutableSequence below is registered directly on D. In other words, it
- # preceeds MutableMapping which means single dispatch will always
+ # precedes MutableMapping which means single dispatch will always
# choose MutableSequence here.
class D(c.defaultdict):
pass
if (gdb_major_version, gdb_minor_version) >= (7, 4):
base_cmd += ('-iex', 'add-auto-load-safe-path ' + checkout_hook_path)
proc = subprocess.Popen(base_cmd + args,
+ # Redirect stdin to prevent GDB from messing with
+ # the terminal settings
+ stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
env=env)
# Verify that "gdb" can load our custom hooks, as OS security settings may
# disallow this without a customised .gdbinit.
-cmd = ['--args', sys.executable]
_, gdbpy_errors = run_gdb('--args', sys.executable)
if "auto-loading has been declined" in gdbpy_errors:
msg = "gdb security settings prevent use of custom hooks: "
# print commands
# Use "commands" to generate the arguments with which to invoke "gdb":
- args = ["gdb", "--batch", "-nx"]
- args += ['--eval-command=%s' % cmd for cmd in commands]
+ args = ['--eval-command=%s' % cmd for cmd in commands]
args += ["--args",
sys.executable]
# Ignore some benign messages on stderr.
ignore_patterns = (
'Function "%s" not defined.' % breakpoint,
- "warning: no loadable sections found in added symbol-file"
- " system-supplied DSO",
- "warning: Unable to find libthread_db matching"
- " inferior's thread library, thread debugging will"
- " not be available.",
- "warning: Cannot initialize thread debugging"
- " library: Debugger service failed",
- 'warning: Could not load shared library symbols for '
- 'linux-vdso.so',
- 'warning: Could not load shared library symbols for '
- 'linux-gate.so',
- 'warning: Could not load shared library symbols for '
- 'linux-vdso64.so',
'Do you need "set solib-search-path" or '
'"set sysroot"?',
- 'warning: Source file is more recent than executable.',
- # Issue #19753: missing symbols on System Z
- 'Missing separate debuginfo for ',
- 'Try: zypper install -C ',
+ # BFD: /usr/lib/debug/(...): unable to initialize decompress
+ # status for section .debug_aranges
+ 'BFD: ',
+ # ignore all warnings
+ 'warning: ',
)
for line in errlines:
+ if not line:
+ continue
if not line.startswith(ignore_patterns):
unexpected_errlines.append(line)
# For each square, compute a bit vector of the columns and
# diagonals it covers, and for each row compute a function that
- # generates the possiblities for the columns in that row.
+ # generates the possibilities for the columns in that row.
self.rowgenerators = []
for i in rangen:
rowuses = [(1 << j) | # column ordinal
def test_nonascii_abspath(self):
if (support.TESTFN_UNDECODABLE
# Mac OS X denies the creation of a directory with an invalid
- # UTF-8 name. Windows allows to create a directory with an
+ # UTF-8 name. Windows allows creating a directory with an
# arbitrary bytes name, but fails to enter this directory
# (when the bytes name is used).
and sys.platform not in ('win32', 'darwin')):
import unittest
+import math
+import sys
from test import support
# Skip this test if the _testcapi module isn't available.
support.import_module('_testcapi')
from _testcapi import UCHAR_MAX, USHRT_MAX, UINT_MAX, ULONG_MAX, INT_MAX, \
INT_MIN, LONG_MIN, LONG_MAX, PY_SSIZE_T_MIN, PY_SSIZE_T_MAX, \
- SHRT_MIN, SHRT_MAX
+ SHRT_MIN, SHRT_MAX, FLT_MIN, FLT_MAX, DBL_MIN, DBL_MAX
+
+DBL_MAX_EXP = sys.float_info.max_exp
+INF = float('inf')
+NAN = float('nan')
# fake, they are not defined in Python's header files
LLONG_MAX = 2**63-1
return True
+class Float:
+ def __float__(self):
+ return 4.25
+
+class FloatSubclass(float):
+ pass
+
+class FloatSubclass2(float):
+ def __float__(self):
+ return 4.25
+
+class BadFloat:
+ def __float__(self):
+ return 687
+
+class BadFloat2:
+ def __float__(self):
+ return FloatSubclass(4.25)
+
+class BadFloat3(float):
+ def __float__(self):
+ return FloatSubclass(4.25)
+
+
+class Complex:
+ def __complex__(self):
+ return 4.25+0.5j
+
+class ComplexSubclass(complex):
+ pass
+
+class ComplexSubclass2(complex):
+ def __complex__(self):
+ return 4.25+0.5j
+
+class BadComplex:
+ def __complex__(self):
+ return 1.25
+
+class BadComplex2:
+ def __complex__(self):
+ return ComplexSubclass(4.25+0.5j)
+
+class BadComplex3(complex):
+ def __complex__(self):
+ return ComplexSubclass(4.25+0.5j)
+
+
+class TupleSubclass(tuple):
+ pass
+
+class DictSubclass(dict):
+ pass
+
+
class Unsigned_TestCase(unittest.TestCase):
def test_b(self):
from _testcapi import getargs_b
self.assertEqual(VERY_LARGE & ULLONG_MAX, getargs_K(VERY_LARGE))
+
+class Float_TestCase(unittest.TestCase):
+ def assertEqualWithSign(self, actual, expected):
+ self.assertEqual(actual, expected)
+ self.assertEqual(math.copysign(1, actual), math.copysign(1, expected))
+
+ def test_f(self):
+ from _testcapi import getargs_f
+ self.assertEqual(getargs_f(4.25), 4.25)
+ self.assertEqual(getargs_f(4), 4.0)
+ self.assertRaises(TypeError, getargs_f, 4.25+0j)
+ self.assertEqual(getargs_f(Float()), 4.25)
+ self.assertEqual(getargs_f(FloatSubclass(7.5)), 7.5)
+ self.assertEqual(getargs_f(FloatSubclass2(7.5)), 7.5)
+ self.assertRaises(TypeError, getargs_f, BadFloat())
+ self.assertEqual(getargs_f(BadFloat2()), 4.25)
+ self.assertEqual(getargs_f(BadFloat3(7.5)), 7.5)
+
+ for x in (FLT_MIN, -FLT_MIN, FLT_MAX, -FLT_MAX, INF, -INF):
+ self.assertEqual(getargs_f(x), x)
+ if FLT_MAX < DBL_MAX:
+ self.assertEqual(getargs_f(DBL_MAX), INF)
+ self.assertEqual(getargs_f(-DBL_MAX), -INF)
+ if FLT_MIN > DBL_MIN:
+ self.assertEqualWithSign(getargs_f(DBL_MIN), 0.0)
+ self.assertEqualWithSign(getargs_f(-DBL_MIN), -0.0)
+ self.assertEqualWithSign(getargs_f(0.0), 0.0)
+ self.assertEqualWithSign(getargs_f(-0.0), -0.0)
+ r = getargs_f(NAN)
+ self.assertNotEqual(r, r)
+
+ def test_d(self):
+ from _testcapi import getargs_d
+ self.assertEqual(getargs_d(4.25), 4.25)
+ self.assertEqual(getargs_d(4), 4.0)
+ self.assertRaises(TypeError, getargs_d, 4.25+0j)
+ self.assertEqual(getargs_d(Float()), 4.25)
+ self.assertEqual(getargs_d(FloatSubclass(7.5)), 7.5)
+ self.assertEqual(getargs_d(FloatSubclass2(7.5)), 7.5)
+ self.assertRaises(TypeError, getargs_d, BadFloat())
+ self.assertEqual(getargs_d(BadFloat2()), 4.25)
+ self.assertEqual(getargs_d(BadFloat3(7.5)), 7.5)
+
+ for x in (DBL_MIN, -DBL_MIN, DBL_MAX, -DBL_MAX, INF, -INF):
+ self.assertEqual(getargs_d(x), x)
+ self.assertRaises(OverflowError, getargs_d, 1<<DBL_MAX_EXP)
+ self.assertRaises(OverflowError, getargs_d, -1<<DBL_MAX_EXP)
+ self.assertEqualWithSign(getargs_d(0.0), 0.0)
+ self.assertEqualWithSign(getargs_d(-0.0), -0.0)
+ r = getargs_d(NAN)
+ self.assertNotEqual(r, r)
+
+ def test_D(self):
+ from _testcapi import getargs_D
+ self.assertEqual(getargs_D(4.25+0.5j), 4.25+0.5j)
+ self.assertEqual(getargs_D(4.25), 4.25+0j)
+ self.assertEqual(getargs_D(4), 4.0+0j)
+ self.assertEqual(getargs_D(Complex()), 4.25+0.5j)
+ self.assertEqual(getargs_D(ComplexSubclass(7.5+0.25j)), 7.5+0.25j)
+ self.assertEqual(getargs_D(ComplexSubclass2(7.5+0.25j)), 7.5+0.25j)
+ self.assertRaises(TypeError, getargs_D, BadComplex())
+ self.assertEqual(getargs_D(BadComplex2()), 4.25+0.5j)
+ self.assertEqual(getargs_D(BadComplex3(7.5+0.25j)), 7.5+0.25j)
+
+ for x in (DBL_MIN, -DBL_MIN, DBL_MAX, -DBL_MAX, INF, -INF):
+ c = complex(x, 1.0)
+ self.assertEqual(getargs_D(c), c)
+ c = complex(1.0, x)
+ self.assertEqual(getargs_D(c), c)
+ self.assertEqualWithSign(getargs_D(complex(0.0, 1.0)).real, 0.0)
+ self.assertEqualWithSign(getargs_D(complex(-0.0, 1.0)).real, -0.0)
+ self.assertEqualWithSign(getargs_D(complex(1.0, 0.0)).imag, 0.0)
+ self.assertEqualWithSign(getargs_D(complex(1.0, -0.0)).imag, -0.0)
+
+
class Paradox:
"This statement is false."
def __bool__(self):
class Tuple_TestCase(unittest.TestCase):
+ def test_args(self):
+ from _testcapi import get_args
+
+ ret = get_args(1, 2)
+ self.assertEqual(ret, (1, 2))
+ self.assertIs(type(ret), tuple)
+
+ ret = get_args(1, *(2, 3))
+ self.assertEqual(ret, (1, 2, 3))
+ self.assertIs(type(ret), tuple)
+
+ ret = get_args(*[1, 2])
+ self.assertEqual(ret, (1, 2))
+ self.assertIs(type(ret), tuple)
+
+ ret = get_args(*TupleSubclass([1, 2]))
+ self.assertEqual(ret, (1, 2))
+ self.assertIsInstance(ret, tuple)
+
+ ret = get_args()
+ self.assertIn(ret, ((), None))
+ self.assertIn(type(ret), (tuple, type(None)))
+
+ ret = get_args(*())
+ self.assertIn(ret, ((), None))
+ self.assertIn(type(ret), (tuple, type(None)))
+
def test_tuple(self):
from _testcapi import getargs_tuple
self.assertRaises(TypeError, getargs_tuple, 1, seq())
class Keywords_TestCase(unittest.TestCase):
+ def test_kwargs(self):
+ from _testcapi import get_kwargs
+
+ ret = get_kwargs(a=1, b=2)
+ self.assertEqual(ret, {'a': 1, 'b': 2})
+ self.assertIs(type(ret), dict)
+
+ ret = get_kwargs(a=1, **{'b': 2, 'c': 3})
+ self.assertEqual(ret, {'a': 1, 'b': 2, 'c': 3})
+ self.assertIs(type(ret), dict)
+
+ ret = get_kwargs(**DictSubclass({'a': 1, 'b': 2}))
+ self.assertEqual(ret, {'a': 1, 'b': 2})
+ self.assertIsInstance(ret, dict)
+
+ ret = get_kwargs()
+ self.assertIn(ret, ({}, None))
+ self.assertIn(type(ret), (dict, type(None)))
+
+ ret = get_kwargs(**{})
+ self.assertIn(ret, ({}, None))
+ self.assertIn(type(ret), (dict, type(None)))
+
def test_positional_args(self):
# using all positional args
self.assertEqual(
"'\udc80' is an invalid keyword argument for this function"):
getargs_keyword_only(1, 2, **{'\uDC80': 10})
+
class Bytes_TestCase(unittest.TestCase):
def test_c(self):
from _testcapi import getargs_c
self.assertRaises(TypeError, getargs_c, b'abc') # len > 1
- self.assertEqual(getargs_c(b'a'), b'a')
- self.assertEqual(getargs_c(bytearray(b'a')), b'a')
+ self.assertEqual(getargs_c(b'a'), 97)
+ self.assertEqual(getargs_c(bytearray(b'a')), 97)
self.assertRaises(TypeError, getargs_c, memoryview(b'a'))
self.assertRaises(TypeError, getargs_c, 's')
+ self.assertRaises(TypeError, getargs_c, 97)
self.assertRaises(TypeError, getargs_c, None)
+ def test_y(self):
+ from _testcapi import getargs_y
+ self.assertRaises(TypeError, getargs_y, 'abc\xe9')
+ self.assertEqual(getargs_y(b'bytes'), b'bytes')
+ self.assertRaises(ValueError, getargs_y, b'nul:\0')
+ self.assertRaises(TypeError, getargs_y, bytearray(b'bytearray'))
+ self.assertRaises(TypeError, getargs_y, memoryview(b'memoryview'))
+ self.assertRaises(TypeError, getargs_y, None)
+
+ def test_y_star(self):
+ from _testcapi import getargs_y_star
+ self.assertRaises(TypeError, getargs_y_star, 'abc\xe9')
+ self.assertEqual(getargs_y_star(b'bytes'), b'bytes')
+ self.assertEqual(getargs_y_star(b'nul:\0'), b'nul:\0')
+ self.assertEqual(getargs_y_star(bytearray(b'bytearray')), b'bytearray')
+ self.assertEqual(getargs_y_star(memoryview(b'memoryview')), b'memoryview')
+ self.assertRaises(TypeError, getargs_y_star, None)
+
+ def test_y_hash(self):
+ from _testcapi import getargs_y_hash
+ self.assertRaises(TypeError, getargs_y_hash, 'abc\xe9')
+ self.assertEqual(getargs_y_hash(b'bytes'), b'bytes')
+ self.assertEqual(getargs_y_hash(b'nul:\0'), b'nul:\0')
+ self.assertRaises(TypeError, getargs_y_hash, bytearray(b'bytearray'))
+ self.assertRaises(TypeError, getargs_y_hash, memoryview(b'memoryview'))
+ self.assertRaises(TypeError, getargs_y_hash, None)
+
+ def test_w_star(self):
+ # getargs_w_star() modifies first and last byte
+ from _testcapi import getargs_w_star
+ self.assertRaises(TypeError, getargs_w_star, 'abc\xe9')
+ self.assertRaises(TypeError, getargs_w_star, b'bytes')
+ self.assertRaises(TypeError, getargs_w_star, b'nul:\0')
+ self.assertRaises(TypeError, getargs_w_star, memoryview(b'bytes'))
+ buf = bytearray(b'bytearray')
+ self.assertEqual(getargs_w_star(buf), b'[ytearra]')
+ self.assertEqual(buf, bytearray(b'[ytearra]'))
+ buf = bytearray(b'memoryview')
+ self.assertEqual(getargs_w_star(memoryview(buf)), b'[emoryvie]')
+ self.assertEqual(buf, bytearray(b'[emoryvie]'))
+ self.assertRaises(TypeError, getargs_w_star, None)
+
+
+class String_TestCase(unittest.TestCase):
+ def test_C(self):
+ from _testcapi import getargs_C
+ self.assertRaises(TypeError, getargs_C, 'abc') # len > 1
+ self.assertEqual(getargs_C('a'), 97)
+ self.assertEqual(getargs_C('\u20ac'), 0x20ac)
+ self.assertEqual(getargs_C('\U0001f40d'), 0x1f40d)
+ self.assertRaises(TypeError, getargs_C, b'a')
+ self.assertRaises(TypeError, getargs_C, bytearray(b'a'))
+ self.assertRaises(TypeError, getargs_C, memoryview(b'a'))
+ self.assertRaises(TypeError, getargs_C, 97)
+ self.assertRaises(TypeError, getargs_C, None)
+
def test_s(self):
from _testcapi import getargs_s
self.assertEqual(getargs_s('abc\xe9'), b'abc\xc3\xa9')
self.assertRaises(TypeError, getargs_z_hash, memoryview(b'memoryview'))
self.assertIsNone(getargs_z_hash(None))
- def test_y(self):
- from _testcapi import getargs_y
- self.assertRaises(TypeError, getargs_y, 'abc\xe9')
- self.assertEqual(getargs_y(b'bytes'), b'bytes')
- self.assertRaises(ValueError, getargs_y, b'nul:\0')
- self.assertRaises(TypeError, getargs_y, bytearray(b'bytearray'))
- self.assertRaises(TypeError, getargs_y, memoryview(b'memoryview'))
- self.assertRaises(TypeError, getargs_y, None)
+ def test_es(self):
+ from _testcapi import getargs_es
+ self.assertEqual(getargs_es('abc\xe9'), b'abc\xc3\xa9')
+ self.assertEqual(getargs_es('abc\xe9', 'latin1'), b'abc\xe9')
+ self.assertRaises(UnicodeEncodeError, getargs_es, 'abc\xe9', 'ascii')
+ self.assertRaises(LookupError, getargs_es, 'abc\xe9', 'spam')
+ self.assertRaises(TypeError, getargs_es, b'bytes', 'latin1')
+ self.assertRaises(TypeError, getargs_es, bytearray(b'bytearray'), 'latin1')
+ self.assertRaises(TypeError, getargs_es, memoryview(b'memoryview'), 'latin1')
+ self.assertRaises(TypeError, getargs_es, None, 'latin1')
+ self.assertRaises(TypeError, getargs_es, 'nul:\0', 'latin1')
+
+ def test_et(self):
+ from _testcapi import getargs_et
+ self.assertEqual(getargs_et('abc\xe9'), b'abc\xc3\xa9')
+ self.assertEqual(getargs_et('abc\xe9', 'latin1'), b'abc\xe9')
+ self.assertRaises(UnicodeEncodeError, getargs_et, 'abc\xe9', 'ascii')
+ self.assertRaises(LookupError, getargs_et, 'abc\xe9', 'spam')
+ self.assertEqual(getargs_et(b'bytes', 'latin1'), b'bytes')
+ self.assertEqual(getargs_et(bytearray(b'bytearray'), 'latin1'), b'bytearray')
+ self.assertRaises(TypeError, getargs_et, memoryview(b'memoryview'), 'latin1')
+ self.assertRaises(TypeError, getargs_et, None, 'latin1')
+ self.assertRaises(TypeError, getargs_et, 'nul:\0', 'latin1')
+ self.assertRaises(TypeError, getargs_et, b'nul:\0', 'latin1')
+ self.assertRaises(TypeError, getargs_et, bytearray(b'nul:\0'), 'latin1')
+
+ def test_es_hash(self):
+ from _testcapi import getargs_es_hash
+ self.assertEqual(getargs_es_hash('abc\xe9'), b'abc\xc3\xa9')
+ self.assertEqual(getargs_es_hash('abc\xe9', 'latin1'), b'abc\xe9')
+ self.assertRaises(UnicodeEncodeError, getargs_es_hash, 'abc\xe9', 'ascii')
+ self.assertRaises(LookupError, getargs_es_hash, 'abc\xe9', 'spam')
+ self.assertRaises(TypeError, getargs_es_hash, b'bytes', 'latin1')
+ self.assertRaises(TypeError, getargs_es_hash, bytearray(b'bytearray'), 'latin1')
+ self.assertRaises(TypeError, getargs_es_hash, memoryview(b'memoryview'), 'latin1')
+ self.assertRaises(TypeError, getargs_es_hash, None, 'latin1')
+ self.assertEqual(getargs_es_hash('nul:\0', 'latin1'), b'nul:\0')
+
+ buf = bytearray(b'x'*8)
+ self.assertEqual(getargs_es_hash('abc\xe9', 'latin1', buf), b'abc\xe9')
+ self.assertEqual(buf, bytearray(b'abc\xe9\x00xxx'))
+ buf = bytearray(b'x'*5)
+ self.assertEqual(getargs_es_hash('abc\xe9', 'latin1', buf), b'abc\xe9')
+ self.assertEqual(buf, bytearray(b'abc\xe9\x00'))
+ buf = bytearray(b'x'*4)
+ self.assertRaises(TypeError, getargs_es_hash, 'abc\xe9', 'latin1', buf)
+ self.assertEqual(buf, bytearray(b'x'*4))
+ buf = bytearray()
+ self.assertRaises(TypeError, getargs_es_hash, 'abc\xe9', 'latin1', buf)
+
+ def test_et_hash(self):
+ from _testcapi import getargs_et_hash
+ self.assertEqual(getargs_et_hash('abc\xe9'), b'abc\xc3\xa9')
+ self.assertEqual(getargs_et_hash('abc\xe9', 'latin1'), b'abc\xe9')
+ self.assertRaises(UnicodeEncodeError, getargs_et_hash, 'abc\xe9', 'ascii')
+ self.assertRaises(LookupError, getargs_et_hash, 'abc\xe9', 'spam')
+ self.assertEqual(getargs_et_hash(b'bytes', 'latin1'), b'bytes')
+ self.assertEqual(getargs_et_hash(bytearray(b'bytearray'), 'latin1'), b'bytearray')
+ self.assertRaises(TypeError, getargs_et_hash, memoryview(b'memoryview'), 'latin1')
+ self.assertRaises(TypeError, getargs_et_hash, None, 'latin1')
+ self.assertEqual(getargs_et_hash('nul:\0', 'latin1'), b'nul:\0')
+ self.assertEqual(getargs_et_hash(b'nul:\0', 'latin1'), b'nul:\0')
+ self.assertEqual(getargs_et_hash(bytearray(b'nul:\0'), 'latin1'), b'nul:\0')
+
+ buf = bytearray(b'x'*8)
+ self.assertEqual(getargs_et_hash('abc\xe9', 'latin1', buf), b'abc\xe9')
+ self.assertEqual(buf, bytearray(b'abc\xe9\x00xxx'))
+ buf = bytearray(b'x'*5)
+ self.assertEqual(getargs_et_hash('abc\xe9', 'latin1', buf), b'abc\xe9')
+ self.assertEqual(buf, bytearray(b'abc\xe9\x00'))
+ buf = bytearray(b'x'*4)
+ self.assertRaises(TypeError, getargs_et_hash, 'abc\xe9', 'latin1', buf)
+ self.assertEqual(buf, bytearray(b'x'*4))
+ buf = bytearray()
+ self.assertRaises(TypeError, getargs_et_hash, 'abc\xe9', 'latin1', buf)
- def test_y_star(self):
- from _testcapi import getargs_y_star
- self.assertRaises(TypeError, getargs_y_star, 'abc\xe9')
- self.assertEqual(getargs_y_star(b'bytes'), b'bytes')
- self.assertEqual(getargs_y_star(b'nul:\0'), b'nul:\0')
- self.assertEqual(getargs_y_star(bytearray(b'bytearray')), b'bytearray')
- self.assertEqual(getargs_y_star(memoryview(b'memoryview')), b'memoryview')
- self.assertRaises(TypeError, getargs_y_star, None)
-
- def test_y_hash(self):
- from _testcapi import getargs_y_hash
- self.assertRaises(TypeError, getargs_y_hash, 'abc\xe9')
- self.assertEqual(getargs_y_hash(b'bytes'), b'bytes')
- self.assertEqual(getargs_y_hash(b'nul:\0'), b'nul:\0')
- self.assertRaises(TypeError, getargs_y_hash, bytearray(b'bytearray'))
- self.assertRaises(TypeError, getargs_y_hash, memoryview(b'memoryview'))
- self.assertRaises(TypeError, getargs_y_hash, None)
-
- def test_w_star(self):
- # getargs_w_star() modifies first and last byte
- from _testcapi import getargs_w_star
- self.assertRaises(TypeError, getargs_w_star, 'abc\xe9')
- self.assertRaises(TypeError, getargs_w_star, b'bytes')
- self.assertRaises(TypeError, getargs_w_star, b'nul:\0')
- self.assertRaises(TypeError, getargs_w_star, memoryview(b'bytes'))
- self.assertEqual(getargs_w_star(bytearray(b'bytearray')), b'[ytearra]')
- self.assertEqual(getargs_w_star(memoryview(bytearray(b'memoryview'))),
- b'[emoryvie]')
- self.assertRaises(TypeError, getargs_w_star, None)
-
-
-class Unicode_TestCase(unittest.TestCase):
def test_u(self):
from _testcapi import getargs_u
self.assertEqual(getargs_u('abc\xe9'), 'abc\xe9')
self.assertIsNone(getargs_Z_hash(None))
+class Object_TestCase(unittest.TestCase):
+ def test_S(self):
+ from _testcapi import getargs_S
+ obj = b'bytes'
+ self.assertIs(getargs_S(obj), obj)
+ self.assertRaises(TypeError, getargs_S, bytearray(b'bytearray'))
+ self.assertRaises(TypeError, getargs_S, 'str')
+ self.assertRaises(TypeError, getargs_S, None)
+ self.assertRaises(TypeError, getargs_S, memoryview(obj))
+
+ def test_Y(self):
+ from _testcapi import getargs_Y
+ obj = bytearray(b'bytearray')
+ self.assertIs(getargs_Y(obj), obj)
+ self.assertRaises(TypeError, getargs_Y, b'bytes')
+ self.assertRaises(TypeError, getargs_Y, 'str')
+ self.assertRaises(TypeError, getargs_Y, None)
+ self.assertRaises(TypeError, getargs_Y, memoryview(obj))
+
+ def test_U(self):
+ from _testcapi import getargs_U
+ obj = 'str'
+ self.assertIs(getargs_U(obj), obj)
+ self.assertRaises(TypeError, getargs_U, b'bytes')
+ self.assertRaises(TypeError, getargs_U, bytearray(b'bytearray'))
+ self.assertRaises(TypeError, getargs_U, None)
+
+
if __name__ == "__main__":
unittest.main()
# Test ifelse expressions in various cases
def _checkeval(msg, ret):
"helper to check that evaluation of expressions is done correctly"
- print(x)
+ print(msg)
return ret
# the next line is not allowed anymore
class Done(Exception): pass
class AIter:
- async def __aiter__(self):
+ def __aiter__(self):
return self
async def __anext__(self):
raise StopAsyncIteration
pbkdf2_results = {
"sha1": [
- # offical test vectors from RFC 6070
+ # official test vectors from RFC 6070
(bytes.fromhex('0c60c80f961f0e71f3a9b524af6012062fe037a6'), None),
(bytes.fromhex('ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957'), None),
(bytes.fromhex('4b007901b765489abead49d926f721d065a429c1'), None),
self.assertRaises(ValueError, pbkdf2, 'sha1', b'pass', b'salt', 1, -1)
with self.assertRaisesRegex(ValueError, 'unsupported hash type'):
pbkdf2('unknown', b'pass', b'salt', 1)
+ out = pbkdf2(hash_name='sha1', password=b'password', salt=b'salt',
+ iterations=1, dklen=None)
+ self.assertEqual(out, self.pbkdf2_results['sha1'][0][0])
def test_pbkdf2_hmac_py(self):
self._test_pbkdf2_hmac(py_hashlib.pbkdf2_hmac)
'01-01-1980 25:00:00',
'01-01-1980 00:61:00',
'01-01-1980 00:00:62',
+ '08-Oct-3697739',
+ '08-01-3697739',
+ '09 Feb 19942632 22:23:32 GMT',
+ 'Wed, 09 Feb 1994834 22:23:32 GMT',
]:
self.assertIsNone(http2time(test),
"http2time(%s) is not None\n"
key = "%s_after" % cookie.value
counter[key] = counter[key] + 1
- # a permanent cookie got lost accidently
+ # a permanent cookie got lost accidentally
self.assertEqual(counter["perm_after"], counter["perm_before"])
# a session cookie hasn't been cleared
self.assertEqual(counter["session_after"], 0)
C1 = pickle.loads(pickle.dumps(C, protocol=proto))
self.assertEqual(C1.output(), expected_output)
+ def test_illegal_chars(self):
+ rawdata = "a=b; c,d=e"
+ C = cookies.SimpleCookie()
+ with self.assertRaises(cookies.CookieError):
+ C.load(rawdata)
+
class MorselTests(unittest.TestCase):
"""Tests for the Morsel object."""
self.assertIn(b'\xa0NonbreakSpace: value', conn._buffer)
def test_ipv6host_header(self):
- # Default host header on IPv6 transaction should wrapped by [] if
- # its actual IPv6 address
+ # Default host header on IPv6 transaction should be wrapped by [] if
+ # it is an IPv6 address
expected = b'GET /foo HTTP/1.1\r\nHost: [2001::]:81\r\n' \
b'Accept-Encoding: identity\r\n\r\n'
conn = client.HTTPConnection('[2001::]:81')
self.assertEqual(repr(exc), '''BadStatusLine("\'\'",)''')
def test_partial_reads(self):
- # if we have a length, the system knows when to close itself
- # same behaviour than when we read the whole thing with read()
+ # if we have Content-Length, HTTPResponse knows when to close itself,
+ # the same behaviour as when we read the whole thing with read()
body = "HTTP/1.1 200 Ok\r\nContent-Length: 4\r\n\r\nText"
sock = FakeSocket(body)
resp = client.HTTPResponse(sock)
resp.close()
self.assertTrue(resp.closed)
+ def test_mixed_reads(self):
+ # readline() should update the remaining length, so that read() knows
+ # how much data is left and does not raise IncompleteRead
+ body = "HTTP/1.1 200 Ok\r\nContent-Length: 13\r\n\r\nText\r\nAnother"
+ sock = FakeSocket(body)
+ resp = client.HTTPResponse(sock)
+ resp.begin()
+ self.assertEqual(resp.readline(), b'Text\r\n')
+ self.assertFalse(resp.isclosed())
+ self.assertEqual(resp.read(), b'Another')
+ self.assertTrue(resp.isclosed())
+ self.assertFalse(resp.closed)
+ resp.close()
+ self.assertTrue(resp.closed)
+
def test_partial_readintos(self):
- # if we have a length, the system knows when to close itself
- # same behaviour than when we read the whole thing with read()
+ # if we have Content-Length, HTTPResponse knows when to close itself,
+ # the same behaviour as when we read the whole thing with read()
body = "HTTP/1.1 200 Ok\r\nContent-Length: 4\r\n\r\nText"
sock = FakeSocket(body)
resp = client.HTTPResponse(sock)
resp.begin()
self.assertEqual(resp.read(), expected)
# we should have reached the end of the file
- self.assertEqual(sock.file.read(100), b"") #we read to the end
+ self.assertEqual(sock.file.read(), b"") #we read to the end
resp.close()
def test_chunked_sync(self):
resp.begin()
self.assertEqual(resp.read(), expected)
# the file should now have our extradata ready to be read
- self.assertEqual(sock.file.read(100), extradata.encode("ascii")) #we read to the end
+ self.assertEqual(sock.file.read(), extradata.encode("ascii")) #we read to the end
resp.close()
def test_content_length_sync(self):
"""Check that we don't read past the end of the Content-Length stream"""
- extradata = "extradata"
+ extradata = b"extradata"
+ expected = b"Hello123\r\n"
+ sock = FakeSocket(b'HTTP/1.1 200 OK\r\nContent-Length: 10\r\n\r\n' + expected + extradata)
+ resp = client.HTTPResponse(sock, method="GET")
+ resp.begin()
+ self.assertEqual(resp.read(), expected)
+ # the file should now have our extradata ready to be read
+ self.assertEqual(sock.file.read(), extradata) #we read to the end
+ resp.close()
+
+ def test_readlines_content_length(self):
+ extradata = b"extradata"
+ expected = b"Hello123\r\n"
+ sock = FakeSocket(b'HTTP/1.1 200 OK\r\nContent-Length: 10\r\n\r\n' + expected + extradata)
+ resp = client.HTTPResponse(sock, method="GET")
+ resp.begin()
+ self.assertEqual(resp.readlines(2000), [expected])
+ # the file should now have our extradata ready to be read
+ self.assertEqual(sock.file.read(), extradata) #we read to the end
+ resp.close()
+
+ def test_read1_content_length(self):
+ extradata = b"extradata"
+ expected = b"Hello123\r\n"
+ sock = FakeSocket(b'HTTP/1.1 200 OK\r\nContent-Length: 10\r\n\r\n' + expected + extradata)
+ resp = client.HTTPResponse(sock, method="GET")
+ resp.begin()
+ self.assertEqual(resp.read1(2000), expected)
+ # the file should now have our extradata ready to be read
+ self.assertEqual(sock.file.read(), extradata) #we read to the end
+ resp.close()
+
+ def test_readline_bound_content_length(self):
+ extradata = b"extradata"
+ expected = b"Hello123\r\n"
+ sock = FakeSocket(b'HTTP/1.1 200 OK\r\nContent-Length: 10\r\n\r\n' + expected + extradata)
+ resp = client.HTTPResponse(sock, method="GET")
+ resp.begin()
+ self.assertEqual(resp.readline(10), expected)
+ self.assertEqual(resp.readline(10), b"")
+ # the file should now have our extradata ready to be read
+ self.assertEqual(sock.file.read(), extradata) #we read to the end
+ resp.close()
+
+ def test_read1_bound_content_length(self):
+ extradata = b"extradata"
expected = b"Hello123\r\n"
- sock = FakeSocket('HTTP/1.1 200 OK\r\nContent-Length: 10\r\n\r\nHello123\r\n' + extradata)
+ sock = FakeSocket(b'HTTP/1.1 200 OK\r\nContent-Length: 30\r\n\r\n' + expected*3 + extradata)
resp = client.HTTPResponse(sock, method="GET")
resp.begin()
+ self.assertEqual(resp.read1(20), expected*2)
self.assertEqual(resp.read(), expected)
# the file should now have our extradata ready to be read
- self.assertEqual(sock.file.read(100), extradata.encode("ascii")) #we read to the end
+ self.assertEqual(sock.file.read(), extradata) #we read to the end
resp.close()
+ def test_response_fileno(self):
+ # Make sure fd returned by fileno is valid.
+ threading = support.import_module("threading")
+
+ serv = socket.socket(
+ socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP)
+ self.addCleanup(serv.close)
+ serv.bind((HOST, 0))
+ serv.listen()
+
+ result = None
+ def run_server():
+ [conn, address] = serv.accept()
+ with conn, conn.makefile("rb") as reader:
+ # Read the request header until a blank line
+ while True:
+ line = reader.readline()
+ if not line.rstrip(b"\r\n"):
+ break
+ conn.sendall(b"HTTP/1.1 200 Connection established\r\n\r\n")
+ nonlocal result
+ result = reader.read()
+
+ thread = threading.Thread(target=run_server)
+ thread.start()
+ conn = client.HTTPConnection(*serv.getsockname())
+ conn.request("CONNECT", "dummy:1234")
+ response = conn.getresponse()
+ try:
+ self.assertEqual(response.status, client.OK)
+ s = socket.socket(fileno=response.fileno())
+ try:
+ s.sendall(b"proxied data\n")
+ finally:
+ s.detach()
+ finally:
+ response.close()
+ conn.close()
+ thread.join()
+ self.assertEqual(result, b"proxied data\n")
+
class ExtendedReadTest(TestCase):
"""
Test peek(), read1(), readline()
# intentionally omitted for simplicity
blacklist = {"HTTPMessage", "parse_headers"}
for name in dir(client):
- if name in blacklist:
+ if name.startswith("_") or name in blacklist:
continue
module_object = getattr(client, name)
if getattr(module_object, "__module__", None) == "http.client":
import sys
import re
import base64
+import ntpath
import shutil
import urllib.parse
import html
def do_EXPLAINERROR(self):
self.send_error(999, "Short Message",
- "This is a long \n explaination")
+ "This is a long \n explanation")
def do_CUSTOM(self):
self.send_response(999)
body = self.headers['x-special-incoming'].encode('utf-8')
self.wfile.write(body)
+ def do_SEND_ERROR(self):
+ self.send_error(int(self.path[1:]))
+
+ def do_HEAD(self):
+ self.send_error(int(self.path[1:]))
+
def setUp(self):
BaseTestCase.setUp(self)
self.con = http.client.HTTPConnection(self.HOST, self.PORT)
data = res.read()
self.assertEqual(int(res.getheader('Content-Length')), len(data))
+ def test_send_error(self):
+ allow_transfer_encoding_codes = (HTTPStatus.NOT_MODIFIED,
+ HTTPStatus.RESET_CONTENT)
+ for code in (HTTPStatus.NO_CONTENT, HTTPStatus.NOT_MODIFIED,
+ HTTPStatus.PROCESSING, HTTPStatus.RESET_CONTENT,
+ HTTPStatus.SWITCHING_PROTOCOLS):
+ self.con.request('SEND_ERROR', '/{}'.format(code))
+ res = self.con.getresponse()
+ self.assertEqual(code, res.status)
+ self.assertEqual(None, res.getheader('Content-Length'))
+ self.assertEqual(None, res.getheader('Content-Type'))
+ if code not in allow_transfer_encoding_codes:
+ self.assertEqual(None, res.getheader('Transfer-Encoding'))
+
+ data = res.read()
+ self.assertEqual(b'', data)
+
+ def test_head_via_send_error(self):
+ allow_transfer_encoding_codes = (HTTPStatus.NOT_MODIFIED,
+ HTTPStatus.RESET_CONTENT)
+ for code in (HTTPStatus.OK, HTTPStatus.NO_CONTENT,
+ HTTPStatus.NOT_MODIFIED, HTTPStatus.RESET_CONTENT,
+ HTTPStatus.SWITCHING_PROTOCOLS):
+ self.con.request('HEAD', '/{}'.format(code))
+ res = self.con.getresponse()
+ self.assertEqual(code, res.status)
+ if code == HTTPStatus.OK:
+ self.assertTrue(int(res.getheader('Content-Length')) > 0)
+ self.assertIn('text/html', res.getheader('Content-Type'))
+ else:
+ self.assertEqual(None, res.getheader('Content-Length'))
+ self.assertEqual(None, res.getheader('Content-Type'))
+ if code not in allow_transfer_encoding_codes:
+ self.assertEqual(None, res.getheader('Transfer-Encoding'))
+
+ data = res.read()
+ self.assertEqual(b'', data)
+
class RequestHandlerLoggingTestCase(BaseTestCase):
class request_handler(BaseHTTPRequestHandler):
self.data = b'We are the knights who say Ni!'
self.tempdir = tempfile.mkdtemp(dir=basetempdir)
self.tempdir_name = os.path.basename(self.tempdir)
+ self.base_url = '/' + self.tempdir_name
with open(os.path.join(self.tempdir, 'test'), 'wb') as temp:
temp.write(self.data)
filename = os.fsdecode(support.TESTFN_UNDECODABLE) + '.txt'
with open(os.path.join(self.tempdir, filename), 'wb') as f:
f.write(support.TESTFN_UNDECODABLE)
- response = self.request(self.tempdir_name + '/')
+ response = self.request(self.base_url + '/')
if sys.platform == 'darwin':
# On Mac OS the HFS+ filesystem replaces bytes that aren't valid
# UTF-8 into a percent-encoded value.
.encode(enc, 'surrogateescape'), body)
self.assertIn(('>%s<' % html.escape(filename))
.encode(enc, 'surrogateescape'), body)
- response = self.request(self.tempdir_name + '/' + quotedname)
+ response = self.request(self.base_url + '/' + quotedname)
self.check_status_and_reason(response, HTTPStatus.OK,
data=support.TESTFN_UNDECODABLE)
def test_get(self):
#constructs the path relative to the root directory of the HTTPServer
- response = self.request(self.tempdir_name + '/test')
+ response = self.request(self.base_url + '/test')
self.check_status_and_reason(response, HTTPStatus.OK, data=self.data)
# check for trailing "/" which should return 404. See Issue17324
- response = self.request(self.tempdir_name + '/test/')
+ response = self.request(self.base_url + '/test/')
self.check_status_and_reason(response, HTTPStatus.NOT_FOUND)
- response = self.request(self.tempdir_name + '/')
+ response = self.request(self.base_url + '/')
self.check_status_and_reason(response, HTTPStatus.OK)
- response = self.request(self.tempdir_name)
+ response = self.request(self.base_url)
self.check_status_and_reason(response, HTTPStatus.MOVED_PERMANENTLY)
- response = self.request(self.tempdir_name + '/?hi=2')
+ response = self.request(self.base_url + '/?hi=2')
self.check_status_and_reason(response, HTTPStatus.OK)
- response = self.request(self.tempdir_name + '?hi=1')
+ response = self.request(self.base_url + '?hi=1')
self.check_status_and_reason(response, HTTPStatus.MOVED_PERMANENTLY)
self.assertEqual(response.getheader("Location"),
- self.tempdir_name + "/?hi=1")
+ self.base_url + "/?hi=1")
response = self.request('/ThisDoesNotExist')
self.check_status_and_reason(response, HTTPStatus.NOT_FOUND)
response = self.request('/' + 'ThisDoesNotExist' + '/')
data = b"Dummy index file\r\n"
with open(os.path.join(self.tempdir_name, 'index.html'), 'wb') as f:
f.write(data)
- response = self.request('/' + self.tempdir_name + '/')
+ response = self.request(self.base_url + '/')
self.check_status_and_reason(response, HTTPStatus.OK, data)
# chmod() doesn't work as expected on Windows, and filesystem
if os.name == 'posix' and os.geteuid() != 0:
os.chmod(self.tempdir, 0)
try:
- response = self.request(self.tempdir_name + '/')
+ response = self.request(self.base_url + '/')
self.check_status_and_reason(response, HTTPStatus.NOT_FOUND)
finally:
os.chmod(self.tempdir, 0o755)
def test_head(self):
response = self.request(
- self.tempdir_name + '/test', method='HEAD')
+ self.base_url + '/test', method='HEAD')
self.check_status_and_reason(response, HTTPStatus.OK)
self.assertEqual(response.getheader('content-length'),
str(len(self.data)))
response = self.request('/', method='GETs')
self.check_status_and_reason(response, HTTPStatus.NOT_IMPLEMENTED)
+ def test_path_without_leading_slash(self):
+ response = self.request(self.tempdir_name + '/test')
+ self.check_status_and_reason(response, HTTPStatus.OK, data=self.data)
+ response = self.request(self.tempdir_name + '/test/')
+ self.check_status_and_reason(response, HTTPStatus.NOT_FOUND)
+ response = self.request(self.tempdir_name + '/')
+ self.check_status_and_reason(response, HTTPStatus.OK)
+ response = self.request(self.tempdir_name)
+ self.check_status_and_reason(response, HTTPStatus.MOVED_PERMANENTLY)
+ response = self.request(self.tempdir_name + '/?hi=2')
+ self.check_status_and_reason(response, HTTPStatus.OK)
+ response = self.request(self.tempdir_name + '?hi=1')
+ self.check_status_and_reason(response, HTTPStatus.MOVED_PERMANENTLY)
+ self.assertEqual(response.getheader("Location"),
+ self.tempdir_name + "/?hi=1")
+
cgi_file1 = """\
#!%s
self.assertFalse(self.handler.get_called)
self.assertEqual(self.handler.requestline, 'GET / HTTP/1.1')
+ def test_too_many_headers(self):
+ result = self.send_typical_request(
+ b'GET / HTTP/1.1\r\n' + b'X-Foo: bar\r\n' * 101 + b'\r\n')
+ self.assertEqual(result[0], b'HTTP/1.1 431 Too many headers\r\n')
+ self.assertFalse(self.handler.get_called)
+ self.assertEqual(self.handler.requestline, 'GET / HTTP/1.1')
+
def test_close_connection(self):
# handle_one_request() should be repeatedly called until
# it sets close_connection
path = self.handler.translate_path('//filename?foo=bar')
self.assertEqual(path, self.translated)
+ def test_windows_colon(self):
+ with support.swap_attr(server.os, 'path', ntpath):
+ path = self.handler.translate_path('c:c:c:foo/filename')
+ path = path.replace(ntpath.sep, os.sep)
+ self.assertEqual(path, self.translated)
+
+ path = self.handler.translate_path('\\c:../filename')
+ path = path.replace(ntpath.sep, os.sep)
+ self.assertEqual(path, self.translated)
+
+ path = self.handler.translate_path('c:\\c:..\\foo/filename')
+ path = path.replace(ntpath.sep, os.sep)
+ self.assertEqual(path, self.translated)
+
+ path = self.handler.translate_path('c:c:foo\\c:c:bar/filename')
+ path = path.replace(ntpath.sep, os.sep)
+ self.assertEqual(path, self.translated)
+
class MiscTestCase(unittest.TestCase):
def test_all(self):
"""))
script_helper.assert_python_ok(testfn)
+ @skip_if_dont_write_bytecode
def test_timestamp_overflow(self):
# A modification timestamp larger than 2**32 should not be a problem
# when importing a module (issue #11235).
with self.assertRaises(KeyError):
self.__import__('sys', level=1)
+ def test_relative_import_no_package_exists_absolute(self):
+ with self.assertRaises(SystemError):
+ self.__import__('sys', {'__package__': '', '__spec__': None},
+ level=1)
+
(Frozen_RelativeImports,
Source_RelativeImports
import warnings
-CODING_RE = re.compile(r'^[ \t\f]*#.*coding[:=][ \t]*([-\w.]+)', re.ASCII)
+CODING_RE = re.compile(r'^[ \t\f]*#.*?coding[:=][ \t]*([-\w.]+)', re.ASCII)
class EncodingTest:
def test_init(self):
with self.assertRaises(TypeError):
+ # Classes that dono't define exec_module() trigger TypeError.
util.LazyLoader(object)
def new_module(self, source_code=None):
ba.apply_defaults()
self.assertEqual(list(ba.arguments.items()), [])
+ # Make sure a no-args binding still acquires proper defaults.
+ def foo(a='spam'): pass
+ sig = inspect.signature(foo)
+ ba = sig.bind()
+ ba.apply_defaults()
+ self.assertEqual(list(ba.arguments.items()), [('a', 'spam')])
+
class TestSignaturePrivateHelpers(unittest.TestCase):
def test_signature_get_bound_param(self):
("\u0200", ValueError)
]
+class IntSubclass(int):
+ pass
+
class IntTestCases(unittest.TestCase):
def test_basic(self):
good_int = TruncReturnsIntSubclass()
n = int(good_int)
self.assertEqual(n, 1)
+ self.assertIs(type(n), bool)
+ n = IntSubclass(good_int)
+ self.assertEqual(n, 1)
+ self.assertIs(type(n), IntSubclass)
def test_error_message(self):
def check(s, base=None):
except ImportError:
threading = None
+try:
+ import ctypes
+except ImportError:
+ def byteslike(*pos, **kw):
+ return array.array("b", bytes(*pos, **kw))
+else:
+ def byteslike(*pos, **kw):
+ """Create a bytes-like object having no string or sequence methods"""
+ data = bytes(*pos, **kw)
+ obj = EmptyStruct()
+ ctypes.resize(obj, len(data))
+ memoryview(obj).cast("B")[:] = data
+ return obj
+ class EmptyStruct(ctypes.Structure):
+ pass
+
def _default_chunk_size():
"""Get the default TextIOWrapper chunk size"""
with open(__file__, "r", encoding="latin-1") as f:
def tell(self, *args):
raise self.UnsupportedOperation("not seekable")
+ def truncate(self, *args):
+ raise self.UnsupportedOperation("not seekable")
+
class CMockUnseekableIO(MockUnseekableIO, io.BytesIO):
UnsupportedOperation = io.UnsupportedOperation
self.assertEqual(f.tell(), 6)
self.assertEqual(f.seek(-1, 1), 5)
self.assertEqual(f.tell(), 5)
- self.assertEqual(f.write(bytearray(b" world\n\n\n")), 9)
+ buffer = bytearray(b" world\n\n\n")
+ self.assertEqual(f.write(buffer), 9)
+ buffer[:] = b"*" * 9 # Overwrite our copy of the data
self.assertEqual(f.seek(0), 0)
self.assertEqual(f.write(b"h"), 1)
self.assertEqual(f.seek(-1, 2), 13)
def read_ops(self, f, buffered=False):
data = f.read(5)
self.assertEqual(data, b"hello")
- data = bytearray(data)
+ data = byteslike(data)
self.assertEqual(f.readinto(data), 5)
- self.assertEqual(data, b" worl")
+ self.assertEqual(bytes(data), b" worl")
+ data = bytearray(5)
self.assertEqual(f.readinto(data), 2)
self.assertEqual(len(data), 5)
self.assertEqual(data[:2], b"d\n")
self.assertEqual(f.seek(0), 0)
self.assertEqual(f.read(20), b"hello world\n")
self.assertEqual(f.read(1), b"")
- self.assertEqual(f.readinto(bytearray(b"x")), 0)
+ self.assertEqual(f.readinto(byteslike(b"x")), 0)
self.assertEqual(f.seek(-6, 2), 6)
self.assertEqual(f.read(5), b"world")
self.assertEqual(f.read(0), b"")
- self.assertEqual(f.readinto(bytearray()), 0)
+ self.assertEqual(f.readinto(byteslike()), 0)
self.assertEqual(f.seek(-6, 1), 5)
self.assertEqual(f.read(5), b" worl")
self.assertEqual(f.tell(), 10)
f.seek(6)
self.assertEqual(f.read(), b"world\n")
self.assertEqual(f.read(), b"")
+ f.seek(0)
+ data = byteslike(5)
+ self.assertEqual(f.readinto1(data), 5)
+ self.assertEqual(bytes(data), b"hello")
LARGE = 2**31
self.assertRaises(exc, fp.seek, 1, self.SEEK_CUR)
self.assertRaises(exc, fp.seek, -1, self.SEEK_END)
+ def test_optional_abilities(self):
+ # Test for OSError when optional APIs are not supported
+ # The purpose of this test is to try fileno(), reading, writing and
+ # seeking operations with various objects that indicate they do not
+ # support these operations.
+
+ def pipe_reader():
+ [r, w] = os.pipe()
+ os.close(w) # So that read() is harmless
+ return self.FileIO(r, "r")
+
+ def pipe_writer():
+ [r, w] = os.pipe()
+ self.addCleanup(os.close, r)
+ # Guarantee that we can write into the pipe without blocking
+ thread = threading.Thread(target=os.read, args=(r, 100))
+ thread.start()
+ self.addCleanup(thread.join)
+ return self.FileIO(w, "w")
+
+ def buffered_reader():
+ return self.BufferedReader(self.MockUnseekableIO())
+
+ def buffered_writer():
+ return self.BufferedWriter(self.MockUnseekableIO())
+
+ def buffered_random():
+ return self.BufferedRandom(self.BytesIO())
+
+ def buffered_rw_pair():
+ return self.BufferedRWPair(self.MockUnseekableIO(),
+ self.MockUnseekableIO())
+
+ def text_reader():
+ class UnseekableReader(self.MockUnseekableIO):
+ writable = self.BufferedIOBase.writable
+ write = self.BufferedIOBase.write
+ return self.TextIOWrapper(UnseekableReader(), "ascii")
+
+ def text_writer():
+ class UnseekableWriter(self.MockUnseekableIO):
+ readable = self.BufferedIOBase.readable
+ read = self.BufferedIOBase.read
+ return self.TextIOWrapper(UnseekableWriter(), "ascii")
+
+ tests = (
+ (pipe_reader, "fr"), (pipe_writer, "fw"),
+ (buffered_reader, "r"), (buffered_writer, "w"),
+ (buffered_random, "rws"), (buffered_rw_pair, "rw"),
+ (text_reader, "r"), (text_writer, "w"),
+ (self.BytesIO, "rws"), (self.StringIO, "rws"),
+ )
+ for [test, abilities] in tests:
+ if test is pipe_writer and not threading:
+ continue # Skip subtest that uses a background thread
+ with self.subTest(test), test() as obj:
+ readable = "r" in abilities
+ self.assertEqual(obj.readable(), readable)
+ writable = "w" in abilities
+ self.assertEqual(obj.writable(), writable)
+
+ if isinstance(obj, self.TextIOBase):
+ data = "3"
+ elif isinstance(obj, (self.BufferedIOBase, self.RawIOBase)):
+ data = b"3"
+ else:
+ self.fail("Unknown base class")
+
+ if "f" in abilities:
+ obj.fileno()
+ else:
+ self.assertRaises(OSError, obj.fileno)
+
+ if readable:
+ obj.read(1)
+ obj.read()
+ else:
+ self.assertRaises(OSError, obj.read, 1)
+ self.assertRaises(OSError, obj.read)
+
+ if writable:
+ obj.write(data)
+ else:
+ self.assertRaises(OSError, obj.write, data)
+
+ if sys.platform.startswith("win") and test in (
+ pipe_reader, pipe_writer):
+ # Pipes seem to appear as seekable on Windows
+ continue
+ seekable = "s" in abilities
+ self.assertEqual(obj.seekable(), seekable)
+
+ if seekable:
+ obj.tell()
+ obj.seek(0)
+ else:
+ self.assertRaises(OSError, obj.tell)
+ self.assertRaises(OSError, obj.seek, 0)
+
+ if writable and seekable:
+ obj.truncate()
+ obj.truncate(0)
+ else:
+ self.assertRaises(OSError, obj.truncate)
+ self.assertRaises(OSError, obj.truncate, 0)
+
def test_open_handles_NUL_chars(self):
fn_with_NUL = 'foo\0bar'
self.assertRaises(ValueError, self.open, fn_with_NUL, 'w')
def test_array_writes(self):
a = array.array('i', range(10))
n = len(a.tobytes())
- with self.open(support.TESTFN, "wb", 0) as f:
- self.assertEqual(f.write(a), n)
- with self.open(support.TESTFN, "wb") as f:
- self.assertEqual(f.write(a), n)
+ def check(f):
+ with f:
+ self.assertEqual(f.write(a), n)
+ f.writelines((a,))
+ check(self.BytesIO())
+ check(self.FileIO(support.TESTFN, "w"))
+ check(self.BufferedWriter(self.MockRawIO()))
+ check(self.BufferedRandom(self.MockRawIO()))
+ check(self.BufferedRWPair(self.MockRawIO(), self.MockRawIO()))
def test_closefd(self):
self.assertRaises(ValueError, self.open, support.TESTFN, 'w',
with self.open("non-existent", "r", opener=opener) as f:
self.assertEqual(f.read(), "egg\n")
+ def test_bad_opener_negative_1(self):
+ # Issue #27066.
+ def badopener(fname, flags):
+ return -1
+ with self.assertRaises(ValueError) as cm:
+ open('non-existent', 'r', opener=badopener)
+ self.assertEqual(str(cm.exception), 'opener returned -1')
+
+ def test_bad_opener_other_negative(self):
+ # Issue #27066.
+ def badopener(fname, flags):
+ return -2
+ with self.assertRaises(ValueError) as cm:
+ open('non-existent', 'r', opener=badopener)
+ self.assertEqual(str(cm.exception), 'opener returned -2')
+
def test_fileio_closefd(self):
# Issue #4841
with self.open(__file__, 'rb') as f1, \
f2.readline()
def test_nonbuffered_textio(self):
- with warnings.catch_warnings(record=True) as recorded:
+ with support.check_no_resource_warning(self):
with self.assertRaises(ValueError):
self.open(support.TESTFN, 'w', buffering=0)
- support.gc_collect()
- self.assertEqual(recorded, [])
def test_invalid_newline(self):
- with warnings.catch_warnings(record=True) as recorded:
+ with support.check_no_resource_warning(self):
with self.assertRaises(ValueError):
self.open(support.TESTFN, 'w', newline='invalid')
- support.gc_collect()
- self.assertEqual(recorded, [])
+
+ def test_buffered_readinto_mixin(self):
+ # Test the implementation provided by BufferedIOBase
+ class Stream(self.BufferedIOBase):
+ def read(self, size):
+ return b"12345"
+ read1 = read
+ stream = Stream()
+ for method in ("readinto", "readinto1"):
+ with self.subTest(method):
+ buffer = byteslike(5)
+ self.assertEqual(getattr(stream, method)(buffer), 5)
+ self.assertEqual(bytes(buffer), b"12345")
class CIOTest(IOTest):
self.assertEqual(42, bufio.fileno())
- @unittest.skip('test having existential crisis')
- def test_no_fileno(self):
- # XXX will we always have fileno() function? If so, kill
- # this test. Else, write it.
- pass
-
def test_invalid_args(self):
rawio = self.MockRawIO()
bufio = self.tp(rawio)
super().flush()
rawio = self.MockRawIO()
bufio = MyBufferedIO(rawio)
- writable = bufio.writable()
del bufio
support.gc_collect()
- if writable:
- self.assertEqual(record, [1, 2, 3])
- else:
- self.assertEqual(record, [1, 2])
+ self.assertEqual(record, [1, 2, 3])
def test_context_manager(self):
# Test usability as a context manager
bufio = self.tp(writer, 8)
bufio.write(b"abc")
self.assertFalse(writer._write_stack)
+ buffer = bytearray(b"def")
+ bufio.write(buffer)
+ buffer[:] = b"***" # Overwrite our copy of the data
+ bufio.flush()
+ self.assertEqual(b"".join(writer._write_stack), b"abcdef")
def test_write_overflow(self):
writer = self.MockRawIO()
self.assertEqual(pair.read1(3), b"abc")
def test_readinto(self):
- pair = self.tp(self.BytesIO(b"abcdef"), self.MockRawIO())
+ for method in ("readinto", "readinto1"):
+ with self.subTest(method):
+ pair = self.tp(self.BytesIO(b"abcdef"), self.MockRawIO())
- data = bytearray(5)
- self.assertEqual(pair.readinto(data), 5)
- self.assertEqual(data, b"abcde")
+ data = byteslike(5)
+ self.assertEqual(getattr(pair, method)(data), 5)
+ self.assertEqual(bytes(data), b"abcde")
def test_write(self):
w = self.MockRawIO()
pair.write(b"abc")
pair.flush()
- pair.write(b"def")
+ buffer = bytearray(b"def")
+ pair.write(buffer)
+ buffer[:] = b"***" # Overwrite our copy of the data
pair.flush()
self.assertEqual(w._write_stack, [b"abc", b"def"])
# When using closefd=False, there's no warning
r, w = os.pipe()
fds += r, w
- with warnings.catch_warnings(record=True) as recorded:
+ with support.check_no_resource_warning(self):
open(r, *args, closefd=False, **kwargs)
- support.gc_collect()
- self.assertEqual(recorded, [])
def test_warn_on_dealloc_fd(self):
self._check_warn_on_dealloc_fd("rb", buffering=0)
v4_objects = v4_addresses + [v4net]
v6_addresses = [v6addr, v6intf]
v6_objects = v6_addresses + [v6net]
+
objects = v4_objects + v6_objects
+ v4addr2 = ipaddress.IPv4Address(2)
+ v4net2 = ipaddress.IPv4Network(2)
+ v4intf2 = ipaddress.IPv4Interface(2)
+ v6addr2 = ipaddress.IPv6Address(2)
+ v6net2 = ipaddress.IPv6Network(2)
+ v6intf2 = ipaddress.IPv6Interface(2)
+
def test_foreign_type_equality(self):
# __eq__ should never raise TypeError directly
other = object()
continue
self.assertNotEqual(lhs, rhs)
+ def test_same_type_equality(self):
+ for obj in self.objects:
+ self.assertEqual(obj, obj)
+ self.assertLessEqual(obj, obj)
+ self.assertGreaterEqual(obj, obj)
+
+ def test_same_type_ordering(self):
+ for lhs, rhs in (
+ (self.v4addr, self.v4addr2),
+ (self.v4net, self.v4net2),
+ (self.v4intf, self.v4intf2),
+ (self.v6addr, self.v6addr2),
+ (self.v6net, self.v6net2),
+ (self.v6intf, self.v6intf2),
+ ):
+ self.assertNotEqual(lhs, rhs)
+ self.assertLess(lhs, rhs)
+ self.assertLessEqual(lhs, rhs)
+ self.assertGreater(rhs, lhs)
+ self.assertGreaterEqual(rhs, lhs)
+ self.assertFalse(lhs > rhs)
+ self.assertFalse(rhs < lhs)
+ self.assertFalse(lhs >= rhs)
+ self.assertFalse(rhs <= lhs)
+
def test_containment(self):
for obj in self.v4_addresses:
self.assertIn(obj, self.v4net)
'2001:658:22a:cafe:8000::/66',
'2001:658:22a:cafe:c000::/66'])
+ def testGetSubnets3(self):
+ subnets = [str(x) for x in self.ipv4_network.subnets(8)]
+ self.assertEqual(subnets[:3],
+ ['1.2.3.0/32', '1.2.3.1/32', '1.2.3.2/32'])
+ self.assertEqual(subnets[-3:],
+ ['1.2.3.253/32', '1.2.3.254/32', '1.2.3.255/32'])
+ self.assertEqual(len(subnets), 256)
+
+ ipv6_network = ipaddress.IPv6Network('2001:658:22a:cafe::/120')
+ subnets = [str(x) for x in ipv6_network.subnets(8)]
+ self.assertEqual(subnets[:3],
+ ['2001:658:22a:cafe::/128',
+ '2001:658:22a:cafe::1/128',
+ '2001:658:22a:cafe::2/128'])
+ self.assertEqual(subnets[-3:],
+ ['2001:658:22a:cafe::fd/128',
+ '2001:658:22a:cafe::fe/128',
+ '2001:658:22a:cafe::ff/128'])
+ self.assertEqual(len(subnets), 256)
+
def testSubnetFailsForLargeCidrDiff(self):
self.assertRaises(ValueError, list,
self.ipv4_interface.network.subnets(9))
self.assertEqual(False,
ipaddress.ip_address('169.255.100.200').is_link_local)
+ self.assertTrue(ipaddress.ip_address('192.0.7.1').is_global)
+ self.assertFalse(ipaddress.ip_address('203.0.113.1').is_global)
+
self.assertEqual(True,
ipaddress.ip_address('127.100.200.254').is_loopback)
self.assertEqual(True, ipaddress.ip_address('127.42.0.0').is_loopback)
addr3 = ipaddress.ip_network('10.2.1.0/24')
addr4 = ipaddress.ip_address('10.1.1.0')
addr5 = ipaddress.ip_network('2001:db8::0/32')
+ addr6 = ipaddress.ip_network('10.1.1.5/32')
self.assertEqual(sorted(list(addr1.address_exclude(addr2))),
[ipaddress.ip_network('10.1.1.64/26'),
ipaddress.ip_network('10.1.1.128/25')])
self.assertRaises(TypeError, list, addr1.address_exclude(addr4))
self.assertRaises(TypeError, list, addr1.address_exclude(addr5))
self.assertEqual(list(addr1.address_exclude(addr1)), [])
+ self.assertEqual(sorted(list(addr1.address_exclude(addr6))),
+ [ipaddress.ip_network('10.1.1.0/30'),
+ ipaddress.ip_network('10.1.1.4/32'),
+ ipaddress.ip_network('10.1.1.6/31'),
+ ipaddress.ip_network('10.1.1.8/29'),
+ ipaddress.ip_network('10.1.1.16/28'),
+ ipaddress.ip_network('10.1.1.32/27'),
+ ipaddress.ip_network('10.1.1.64/26'),
+ ipaddress.ip_network('10.1.1.128/25')])
def testHash(self):
self.assertEqual(hash(ipaddress.ip_interface('10.1.1.0/24')),
'2001:0:0:4:0:0:0:8': '2001:0:0:4::8/128',
'2001:0:0:4:5:6:7:8': '2001::4:5:6:7:8/128',
'2001:0:3:4:5:6:7:8': '2001:0:3:4:5:6:7:8/128',
- '2001:0:3:4:5:6:7:8': '2001:0:3:4:5:6:7:8/128',
'0:0:3:0:0:0:0:ffff': '0:0:3::ffff/128',
'0:0:0:4:0:0:0:ffff': '::4:0:0:0:ffff/128',
'0:0:0:0:5:0:0:ffff': '::5:0:0:ffff/128',
import sys
import unittest
from test.support import run_unittest, TESTFN, unlink, cpython_only
+from test.support import check_free_after_iterating
import pickle
import collections.abc
def test_seq_class_iter(self):
self.check_iterator(iter(SequenceClass(10)), list(range(10)))
+ def test_mutating_seq_class_iter_pickle(self):
+ orig = SequenceClass(5)
+ for proto in range(pickle.HIGHEST_PROTOCOL + 1):
+ # initial iterator
+ itorig = iter(orig)
+ d = pickle.dumps((itorig, orig), proto)
+ it, seq = pickle.loads(d)
+ seq.n = 7
+ self.assertIs(type(it), type(itorig))
+ self.assertEqual(list(it), list(range(7)))
+
+ # running iterator
+ next(itorig)
+ d = pickle.dumps((itorig, orig), proto)
+ it, seq = pickle.loads(d)
+ seq.n = 7
+ self.assertIs(type(it), type(itorig))
+ self.assertEqual(list(it), list(range(1, 7)))
+
+ # empty iterator
+ for i in range(1, 5):
+ next(itorig)
+ d = pickle.dumps((itorig, orig), proto)
+ it, seq = pickle.loads(d)
+ seq.n = 7
+ self.assertIs(type(it), type(itorig))
+ self.assertEqual(list(it), list(range(5, 7)))
+
+ # exhausted iterator
+ self.assertRaises(StopIteration, next, itorig)
+ d = pickle.dumps((itorig, orig), proto)
+ it, seq = pickle.loads(d)
+ seq.n = 7
+ self.assertTrue(isinstance(it, collections.abc.Iterator))
+ self.assertEqual(list(it), [])
+
+ def test_mutating_seq_class_exhausted_iter(self):
+ a = SequenceClass(5)
+ exhit = iter(a)
+ empit = iter(a)
+ for x in exhit: # exhaust the iterator
+ next(empit) # not exhausted
+ a.n = 7
+ self.assertEqual(list(exhit), [])
+ self.assertEqual(list(empit), [5, 6])
+ self.assertEqual(list(a), [0, 1, 2, 3, 4, 5, 6])
+
# Test a new_style class with __iter__ but no next() method
def test_new_style_iter_class(self):
class IterClass(object):
self.assertEqual(next(it), 0)
self.assertEqual(next(it), 1)
+ def test_free_after_iterating(self):
+ check_free_after_iterating(self, iter, SequenceClass, (0,))
+
def test_main():
run_unittest(TestCase)
self.assertEqual(list(copy.deepcopy(it)), accumulated[1:])
self.assertEqual(list(copy.copy(it)), accumulated[1:])
+ def test_accumulate_reducible_none(self):
+ # Issue #25718: total is None
+ it = accumulate([None, None, None], operator.is_)
+ self.assertEqual(next(it), None)
+ for proto in range(pickle.HIGHEST_PROTOCOL + 1):
+ it_copy = pickle.loads(pickle.dumps(it, proto))
+ self.assertEqual(list(it_copy), [True, False])
+ self.assertEqual(list(copy.deepcopy(it)), [True, False])
+ self.assertEqual(list(copy.copy(it)), [True, False])
+
def test_chain(self):
self.assertEqual(''.join(chain('ABC', 'DEF')), 'ABCDEF')
... "Returns the nth item or a default value"
... return next(islice(iterable, n, None), default)
+>>> def all_equal(iterable):
+... "Returns True if all the elements are equal to each other"
+... g = groupby(iterable)
+... return next(g, True) and not next(g, False)
+
>>> def quantify(iterable, pred=bool):
... "Count how many times the predicate is true"
... return sum(map(pred, iterable))
>>> nth('abcde', 9) is None
True
+>>> [all_equal(s) for s in ('', 'A', 'AAAA', 'AAAB', 'AAABA')]
+[True, True, True, False, False]
+
>>> quantify(range(99), lambda x: x%2==0)
50
self.assertEqual(
True, linecache.lazycache(NONEXISTENT_FILENAME, globals()))
self.assertEqual(1, len(linecache.cache[NONEXISTENT_FILENAME]))
- # Note here that we're looking up a non existant filename with no
+ # Note here that we're looking up a nonexistent filename with no
# globals: this would error if the lazy value wasn't resolved.
self.assertEqual(lines, linecache.getlines(NONEXISTENT_FILENAME))
import sys
from test import support, list_tests
import pickle
+import unittest
class ListTest(list_tests.CommonTest):
type2test = list
check(1000000)
def test_iterator_pickle(self):
- # Userlist iterators don't support pickling yet since
- # they are based on generators.
- data = self.type2test([4, 5, 6, 7])
+ orig = self.type2test([4, 5, 6, 7])
+ data = [10, 11, 12, 13, 14, 15]
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
- it = itorg = iter(data)
- d = pickle.dumps(it, proto)
- it = pickle.loads(d)
- self.assertEqual(type(itorg), type(it))
- self.assertEqual(self.type2test(it), self.type2test(data))
-
- it = pickle.loads(d)
- next(it)
- d = pickle.dumps(it, proto)
- self.assertEqual(self.type2test(it), self.type2test(data)[1:])
+ # initial iterator
+ itorig = iter(orig)
+ d = pickle.dumps((itorig, orig), proto)
+ it, a = pickle.loads(d)
+ a[:] = data
+ self.assertEqual(type(it), type(itorig))
+ self.assertEqual(list(it), data)
+
+ # running iterator
+ next(itorig)
+ d = pickle.dumps((itorig, orig), proto)
+ it, a = pickle.loads(d)
+ a[:] = data
+ self.assertEqual(type(it), type(itorig))
+ self.assertEqual(list(it), data[1:])
+
+ # empty iterator
+ for i in range(1, len(orig)):
+ next(itorig)
+ d = pickle.dumps((itorig, orig), proto)
+ it, a = pickle.loads(d)
+ a[:] = data
+ self.assertEqual(type(it), type(itorig))
+ self.assertEqual(list(it), data[len(orig):])
+
+ # exhausted iterator
+ self.assertRaises(StopIteration, next, itorig)
+ d = pickle.dumps((itorig, orig), proto)
+ it, a = pickle.loads(d)
+ a[:] = data
+ self.assertEqual(list(it), [])
def test_reversed_pickle(self):
- data = self.type2test([4, 5, 6, 7])
+ orig = self.type2test([4, 5, 6, 7])
+ data = [10, 11, 12, 13, 14, 15]
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
- it = itorg = reversed(data)
- d = pickle.dumps(it, proto)
- it = pickle.loads(d)
- self.assertEqual(type(itorg), type(it))
- self.assertEqual(self.type2test(it), self.type2test(reversed(data)))
-
- it = pickle.loads(d)
- next(it)
- d = pickle.dumps(it, proto)
- self.assertEqual(self.type2test(it), self.type2test(reversed(data))[1:])
+ # initial iterator
+ itorig = reversed(orig)
+ d = pickle.dumps((itorig, orig), proto)
+ it, a = pickle.loads(d)
+ a[:] = data
+ self.assertEqual(type(it), type(itorig))
+ self.assertEqual(list(it), data[len(orig)-1::-1])
+
+ # running iterator
+ next(itorig)
+ d = pickle.dumps((itorig, orig), proto)
+ it, a = pickle.loads(d)
+ a[:] = data
+ self.assertEqual(type(it), type(itorig))
+ self.assertEqual(list(it), data[len(orig)-2::-1])
+
+ # empty iterator
+ for i in range(1, len(orig)):
+ next(itorig)
+ d = pickle.dumps((itorig, orig), proto)
+ it, a = pickle.loads(d)
+ a[:] = data
+ self.assertEqual(type(it), type(itorig))
+ self.assertEqual(list(it), [])
+
+ # exhausted iterator
+ self.assertRaises(StopIteration, next, itorig)
+ d = pickle.dumps((itorig, orig), proto)
+ it, a = pickle.loads(d)
+ a[:] = data
+ self.assertEqual(list(it), [])
def test_no_comdat_folding(self):
# Issue 8847: In the PGO build, the MSVC linker's COMDAT folding
secure_client = secure and sslctx
self.h_hdlr = logging.handlers.HTTPHandler(host, '/frob',
secure=secure_client,
- context=context)
+ context=context,
+ credentials=('foo', 'bar'))
self.log_data = None
root_logger.addHandler(self.h_hdlr)
self.assertRaises(TypeError, myint.from_bytes, 0, 'big')
self.assertRaises(TypeError, int.from_bytes, 0, 'big', True)
+ class myint2(int):
+ def __new__(cls, value):
+ return int.__new__(cls, value + 1)
+
+ i = myint2.from_bytes(b'\x01', 'big')
+ self.assertIs(type(i), myint2)
+ self.assertEqual(i, 2)
+
+ class myint3(int):
+ def __init__(self, value):
+ self.foo = 'bar'
+
+ i = myint3.from_bytes(b'\x01', 'big')
+ self.assertIs(type(i), myint3)
+ self.assertEqual(i, 1)
+ self.assertEqual(getattr(i, 'foo', 'none'), 'bar')
+
def test_access_to_nonexistent_digit_0(self):
# http://bugs.python.org/issue14630: A bug in _PyLong_Copy meant that
# ob_digit[0] was being incorrectly accessed for instances of a
self.assertEqual(f.read(), uncompressed)
def test_encoding_error_handler(self):
- # Test wih non-default encoding error handler.
+ # Test with non-default encoding error handler.
with BytesIO(lzma.compress(b"foo\xffbar")) as bio:
with lzma.open(bio, "rt", encoding="ascii", errors="ignore") as f:
self.assertEqual(f.read(), "foobar")
# Pickle expects the class to be on the module level. Here we use a
# little hack to allow the PickleTestMemIO class to derive from
- # self.ioclass without having to define all combinations explictly on
+ # self.ioclass without having to define all combinations explicitly on
# the module-level.
import __main__
PickleTestMemIO.__module__ = '__main__'
del __main__.PickleTestMemIO
-class BytesIOMixin:
+class PyBytesIOTest(MemoryTestMixin, MemorySeekTestMixin, unittest.TestCase):
+ # Test _pyio.BytesIO; class also inherited for testing C implementation
+
+ UnsupportedOperation = pyio.UnsupportedOperation
+
+ @staticmethod
+ def buftype(s):
+ return s.encode("ascii")
+ ioclass = pyio.BytesIO
+ EOF = b""
def test_getbuffer(self):
memio = self.ioclass(b"1234567890")
memio.close()
self.assertRaises(ValueError, memio.getbuffer)
-
-class PyBytesIOTest(MemoryTestMixin, MemorySeekTestMixin,
- BytesIOMixin, unittest.TestCase):
-
- UnsupportedOperation = pyio.UnsupportedOperation
-
- @staticmethod
- def buftype(s):
- return s.encode("ascii")
- ioclass = pyio.BytesIO
- EOF = b""
-
def test_read1(self):
buf = self.buftype("1234567890")
memio = self.ioclass(buf)
import weakref
import array
import io
+import copy
+import pickle
class AbstractMemoryTests:
m2 = m1[::-1]
self.assertEqual(m2.hex(), '30' * 200000)
+ def test_copy(self):
+ m = memoryview(b'abc')
+ with self.assertRaises(TypeError):
+ copy.copy(m)
+
+ def test_pickle(self):
+ m = memoryview(b'abc')
+ for proto in range(pickle.HIGHEST_PROTOCOL + 1):
+ with self.assertRaises(TypeError):
+ pickle.dumps(m, proto)
+
if __name__ == "__main__":
unittest.main()
# test for xml.dom.minidom
+import copy
import pickle
from test.support import findfile
import unittest
tstfile = findfile("test.xml", subdir="xmltestdata")
+sample = ("<?xml version='1.0' encoding='us-ascii'?>\n"
+ "<!DOCTYPE doc PUBLIC 'http://xml.python.org/public'"
+ " 'http://xml.python.org/system' [\n"
+ " <!ELEMENT e EMPTY>\n"
+ " <!ENTITY ent SYSTEM 'http://xml.python.org/entity'>\n"
+ "]><doc attr='value'> text\n"
+ "<?pi sample?> <!-- comment --> <e/> </doc>")
# The tests of DocumentType importing use these helpers to construct
# the documents to work with, since not all DOM builders actually
self.confirm(e.isSameNode(doc.getElementById("w"))
and a2.isId)
+ def assert_recursive_equal(self, doc, doc2):
+ stack = [(doc, doc2)]
+ while stack:
+ n1, n2 = stack.pop()
+ self.assertEqual(n1.nodeType, n2.nodeType)
+ self.assertEqual(len(n1.childNodes), len(n2.childNodes))
+ self.assertEqual(n1.nodeName, n2.nodeName)
+ self.assertFalse(n1.isSameNode(n2))
+ self.assertFalse(n2.isSameNode(n1))
+ if n1.nodeType == Node.DOCUMENT_TYPE_NODE:
+ len(n1.entities)
+ len(n2.entities)
+ len(n1.notations)
+ len(n2.notations)
+ self.assertEqual(len(n1.entities), len(n2.entities))
+ self.assertEqual(len(n1.notations), len(n2.notations))
+ for i in range(len(n1.notations)):
+ # XXX this loop body doesn't seem to be executed?
+ no1 = n1.notations.item(i)
+ no2 = n1.notations.item(i)
+ self.assertEqual(no1.name, no2.name)
+ self.assertEqual(no1.publicId, no2.publicId)
+ self.assertEqual(no1.systemId, no2.systemId)
+ stack.append((no1, no2))
+ for i in range(len(n1.entities)):
+ e1 = n1.entities.item(i)
+ e2 = n2.entities.item(i)
+ self.assertEqual(e1.notationName, e2.notationName)
+ self.assertEqual(e1.publicId, e2.publicId)
+ self.assertEqual(e1.systemId, e2.systemId)
+ stack.append((e1, e2))
+ if n1.nodeType != Node.DOCUMENT_NODE:
+ self.assertTrue(n1.ownerDocument.isSameNode(doc))
+ self.assertTrue(n2.ownerDocument.isSameNode(doc2))
+ for i in range(len(n1.childNodes)):
+ stack.append((n1.childNodes[i], n2.childNodes[i]))
+
def testPickledDocument(self):
- doc = parseString("<?xml version='1.0' encoding='us-ascii'?>\n"
- "<!DOCTYPE doc PUBLIC 'http://xml.python.org/public'"
- " 'http://xml.python.org/system' [\n"
- " <!ELEMENT e EMPTY>\n"
- " <!ENTITY ent SYSTEM 'http://xml.python.org/entity'>\n"
- "]><doc attr='value'> text\n"
- "<?pi sample?> <!-- comment --> <e/> </doc>")
+ doc = parseString(sample)
for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
s = pickle.dumps(doc, proto)
doc2 = pickle.loads(s)
- stack = [(doc, doc2)]
- while stack:
- n1, n2 = stack.pop()
- self.confirm(n1.nodeType == n2.nodeType
- and len(n1.childNodes) == len(n2.childNodes)
- and n1.nodeName == n2.nodeName
- and not n1.isSameNode(n2)
- and not n2.isSameNode(n1))
- if n1.nodeType == Node.DOCUMENT_TYPE_NODE:
- len(n1.entities)
- len(n2.entities)
- len(n1.notations)
- len(n2.notations)
- self.confirm(len(n1.entities) == len(n2.entities)
- and len(n1.notations) == len(n2.notations))
- for i in range(len(n1.notations)):
- # XXX this loop body doesn't seem to be executed?
- no1 = n1.notations.item(i)
- no2 = n1.notations.item(i)
- self.confirm(no1.name == no2.name
- and no1.publicId == no2.publicId
- and no1.systemId == no2.systemId)
- stack.append((no1, no2))
- for i in range(len(n1.entities)):
- e1 = n1.entities.item(i)
- e2 = n2.entities.item(i)
- self.confirm(e1.notationName == e2.notationName
- and e1.publicId == e2.publicId
- and e1.systemId == e2.systemId)
- stack.append((e1, e2))
- if n1.nodeType != Node.DOCUMENT_NODE:
- self.confirm(n1.ownerDocument.isSameNode(doc)
- and n2.ownerDocument.isSameNode(doc2))
- for i in range(len(n1.childNodes)):
- stack.append((n1.childNodes[i], n2.childNodes[i]))
+ self.assert_recursive_equal(doc, doc2)
+
+ def testDeepcopiedDocument(self):
+ doc = parseString(sample)
+ doc2 = copy.deepcopy(doc)
+ self.assert_recursive_equal(doc, doc2)
def testSerializeCommentNodeWithDoubleHyphen(self):
doc = create_doc_without_doctype()
f.seek(num_zeroes)
f.write(tail)
f.flush()
- except (OSError, OverflowError):
+ except (OSError, OverflowError, ValueError):
try:
f.close()
except (OSError, OverflowError):
pass
self.assertEqual(foo.__doc__, ModuleType.__doc__)
- def test_unintialized_missing_getattr(self):
+ def test_uninitialized_missing_getattr(self):
# Issue 8297
# test the text in the AttributeError of an uninitialized module
foo = ModuleType.__new__(ModuleType)
b"len = len",
b"shutil.rmtree = rmtree"})
- def test_descriptor_errors_propogate(self):
+ def test_descriptor_errors_propagate(self):
class Descr:
def __get__(self, o, t):
raise RuntimeError
expected = "co_filename %r changed to %r" % (old_path, new_path)
self.assertIn(expected, output)
+ def test_extended_opargs(self):
+ extended_opargs_test = [
+ "a",
+ ["a", "b"],
+ [], [],
+ """\
+a.py
+ %r
+ import b
+b.py
+""" % list(range(2**16))] # 2**16 constants
+ self._do_test(extended_opargs_test)
+
if __name__ == "__main__":
unittest.main()
_multibytecodec.MultibyteStreamWriter, None)
def test_decode_unicode(self):
- # Trying to decode an unicode string should raise a TypeError
+ # Trying to decode a unicode string should raise a TypeError
for enc in ALL_CJKENCODINGS:
self.assertRaises(TypeError, codecs.getdecoder(enc), "")
self.assertEqual(decoder.decode(b'B@$'), '\u4e16')
def test_decode_unicode(self):
- # Trying to decode an unicode string should raise a TypeError
+ # Trying to decode a unicode string should raise a TypeError
for enc in ALL_CJKENCODINGS:
decoder = codecs.getincrementaldecoder(enc)()
self.assertRaises(TypeError, decoder.decode, "")
import unittest
import functools
import contextlib
+import os.path
from test import support
from nntplib import NNTP, GroupInfo
import nntplib
import ssl
except ImportError:
ssl = None
+try:
+ import threading
+except ImportError:
+ threading = None
TIMEOUT = 30
+certfile = os.path.join(os.path.dirname(__file__), 'keycert3.pem')
# TODO:
# - test the `file` arg to more commands
resp, caps = self.server.capabilities()
_check_caps(caps)
- @unittest.skipUnless(ssl, 'requires SSL support')
- def test_starttls(self):
- file = self.server.file
- sock = self.server.sock
- try:
- self.server.starttls()
- except nntplib.NNTPPermanentError:
- self.skipTest("STARTTLS not supported by server.")
- else:
- # Check that the socket and internal pseudo-file really were
- # changed.
- self.assertNotEqual(file, self.server.file)
- self.assertNotEqual(sock, self.server.sock)
- # Check that the new socket really is an SSL one
- self.assertIsInstance(self.server.sock, ssl.SSLSocket)
- # Check that trying starttls when it's already active fails.
- self.assertRaises(ValueError, self.server.starttls)
-
def test_zlogin(self):
# This test must be the penultimate because further commands will be
# refused.
"\t\t6683\t16"
"\t"
"\n"
- # An UTF-8 overview line from fr.comp.lang.python
+ # A UTF-8 overview line from fr.comp.lang.python
"59\tRe: Message d'erreur incompréhensible (par moi)"
"\tEric Brunel <eric.brunel@pragmadev.nospam.com>"
"\tWed, 15 Sep 2010 18:09:15 +0200"
def nntp_class(*pos, **kw):
return nntplib.NNTP_SSL(*pos, ssl_context=bypass_context, **kw)
+@unittest.skipUnless(threading, 'requires multithreading')
+class LocalServerTests(unittest.TestCase):
+ def setUp(self):
+ sock = socket.socket()
+ port = support.bind_port(sock)
+ sock.listen()
+ self.background = threading.Thread(
+ target=self.run_server, args=(sock,))
+ self.background.start()
+ self.addCleanup(self.background.join)
+
+ self.nntp = NNTP(support.HOST, port, usenetrc=False).__enter__()
+ self.addCleanup(self.nntp.__exit__, None, None, None)
+
+ def run_server(self, sock):
+ # Could be generalized to handle more commands in separate methods
+ with sock:
+ [client, _] = sock.accept()
+ with contextlib.ExitStack() as cleanup:
+ cleanup.enter_context(client)
+ reader = cleanup.enter_context(client.makefile('rb'))
+ client.sendall(b'200 Server ready\r\n')
+ while True:
+ cmd = reader.readline()
+ if cmd == b'CAPABILITIES\r\n':
+ client.sendall(
+ b'101 Capability list:\r\n'
+ b'VERSION 2\r\n'
+ b'STARTTLS\r\n'
+ b'.\r\n'
+ )
+ elif cmd == b'STARTTLS\r\n':
+ reader.close()
+ client.sendall(b'382 Begin TLS negotiation now\r\n')
+ client = ssl.wrap_socket(
+ client, server_side=True, certfile=certfile)
+ cleanup.enter_context(client)
+ reader = cleanup.enter_context(client.makefile('rb'))
+ elif cmd == b'QUIT\r\n':
+ client.sendall(b'205 Bye!\r\n')
+ break
+ else:
+ raise ValueError('Unexpected command {!r}'.format(cmd))
+
+ @unittest.skipUnless(ssl, 'requires SSL support')
+ def test_starttls(self):
+ file = self.nntp.file
+ sock = self.nntp.sock
+ self.nntp.starttls()
+ # Check that the socket and internal pseudo-file really were
+ # changed.
+ self.assertNotEqual(file, self.nntp.file)
+ self.assertNotEqual(sock, self.nntp.sock)
+ # Check that the new socket really is an SSL one
+ self.assertIsInstance(self.nntp.sock, ssl.SSLSocket)
+ # Check that trying starttls when it's already active fails.
+ self.assertRaises(ValueError, self.nntp.starttls)
+
if __name__ == "__main__":
unittest.main()
a.name = 'arthur'
f = operator.attrgetter('name')
self.assertEqual(f(a), 'arthur')
+ self.assertRaises(TypeError, f)
+ self.assertRaises(TypeError, f, a, 'dent')
+ self.assertRaises(TypeError, f, a, surname='dent')
f = operator.attrgetter('rank')
self.assertRaises(AttributeError, f, a)
self.assertRaises(TypeError, operator.attrgetter, 2)
a = 'ABCDE'
f = operator.itemgetter(2)
self.assertEqual(f(a), 'C')
+ self.assertRaises(TypeError, f)
+ self.assertRaises(TypeError, f, a, 3)
+ self.assertRaises(TypeError, f, a, size=3)
f = operator.itemgetter(10)
self.assertRaises(IndexError, f, a)
self.assertRaises(IndexError, f, a)
f = operator.methodcaller('foo', 1, 2)
self.assertEqual(f(a), 3)
+ self.assertRaises(TypeError, f)
+ self.assertRaises(TypeError, f, a, 3)
+ self.assertRaises(TypeError, f, a, spam=3)
f = operator.methodcaller('bar')
self.assertEqual(f(a), 42)
self.assertRaises(TypeError, f, a, a)
--- /dev/null
+import contextlib
+import copy
+import gc
+import pickle
+from random import randrange, shuffle
+import struct
+import sys
+import unittest
+import weakref
+from collections.abc import MutableMapping
+from test import mapping_tests, support
+
+
+py_coll = support.import_fresh_module('collections', blocked=['_collections'])
+c_coll = support.import_fresh_module('collections', fresh=['_collections'])
+
+
+@contextlib.contextmanager
+def replaced_module(name, replacement):
+ original_module = sys.modules[name]
+ sys.modules[name] = replacement
+ try:
+ yield
+ finally:
+ sys.modules[name] = original_module
+
+
+class OrderedDictTests:
+
+ def test_init(self):
+ OrderedDict = self.OrderedDict
+ with self.assertRaises(TypeError):
+ OrderedDict([('a', 1), ('b', 2)], None) # too many args
+ pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
+ self.assertEqual(sorted(OrderedDict(dict(pairs)).items()), pairs) # dict input
+ self.assertEqual(sorted(OrderedDict(**dict(pairs)).items()), pairs) # kwds input
+ self.assertEqual(list(OrderedDict(pairs).items()), pairs) # pairs input
+ self.assertEqual(list(OrderedDict([('a', 1), ('b', 2), ('c', 9), ('d', 4)],
+ c=3, e=5).items()), pairs) # mixed input
+
+ # make sure no positional args conflict with possible kwdargs
+ self.assertEqual(list(OrderedDict(self=42).items()), [('self', 42)])
+ self.assertEqual(list(OrderedDict(other=42).items()), [('other', 42)])
+ self.assertRaises(TypeError, OrderedDict, 42)
+ self.assertRaises(TypeError, OrderedDict, (), ())
+ self.assertRaises(TypeError, OrderedDict.__init__)
+
+ # Make sure that direct calls to __init__ do not clear previous contents
+ d = OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 44), ('e', 55)])
+ d.__init__([('e', 5), ('f', 6)], g=7, d=4)
+ self.assertEqual(list(d.items()),
+ [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)])
+
+ def test_update(self):
+ OrderedDict = self.OrderedDict
+ with self.assertRaises(TypeError):
+ OrderedDict().update([('a', 1), ('b', 2)], None) # too many args
+ pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
+ od = OrderedDict()
+ od.update(dict(pairs))
+ self.assertEqual(sorted(od.items()), pairs) # dict input
+ od = OrderedDict()
+ od.update(**dict(pairs))
+ self.assertEqual(sorted(od.items()), pairs) # kwds input
+ od = OrderedDict()
+ od.update(pairs)
+ self.assertEqual(list(od.items()), pairs) # pairs input
+ od = OrderedDict()
+ od.update([('a', 1), ('b', 2), ('c', 9), ('d', 4)], c=3, e=5)
+ self.assertEqual(list(od.items()), pairs) # mixed input
+
+ # Issue 9137: Named argument called 'other' or 'self'
+ # shouldn't be treated specially.
+ od = OrderedDict()
+ od.update(self=23)
+ self.assertEqual(list(od.items()), [('self', 23)])
+ od = OrderedDict()
+ od.update(other={})
+ self.assertEqual(list(od.items()), [('other', {})])
+ od = OrderedDict()
+ od.update(red=5, blue=6, other=7, self=8)
+ self.assertEqual(sorted(list(od.items())),
+ [('blue', 6), ('other', 7), ('red', 5), ('self', 8)])
+
+ # Make sure that direct calls to update do not clear previous contents
+ # add that updates items are not moved to the end
+ d = OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 44), ('e', 55)])
+ d.update([('e', 5), ('f', 6)], g=7, d=4)
+ self.assertEqual(list(d.items()),
+ [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)])
+
+ self.assertRaises(TypeError, OrderedDict().update, 42)
+ self.assertRaises(TypeError, OrderedDict().update, (), ())
+ self.assertRaises(TypeError, OrderedDict.update)
+
+ self.assertRaises(TypeError, OrderedDict().update, 42)
+ self.assertRaises(TypeError, OrderedDict().update, (), ())
+ self.assertRaises(TypeError, OrderedDict.update)
+
+ def test_fromkeys(self):
+ OrderedDict = self.OrderedDict
+ od = OrderedDict.fromkeys('abc')
+ self.assertEqual(list(od.items()), [(c, None) for c in 'abc'])
+ od = OrderedDict.fromkeys('abc', value=None)
+ self.assertEqual(list(od.items()), [(c, None) for c in 'abc'])
+ od = OrderedDict.fromkeys('abc', value=0)
+ self.assertEqual(list(od.items()), [(c, 0) for c in 'abc'])
+
+ def test_abc(self):
+ OrderedDict = self.OrderedDict
+ self.assertIsInstance(OrderedDict(), MutableMapping)
+ self.assertTrue(issubclass(OrderedDict, MutableMapping))
+
+ def test_clear(self):
+ OrderedDict = self.OrderedDict
+ pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
+ shuffle(pairs)
+ od = OrderedDict(pairs)
+ self.assertEqual(len(od), len(pairs))
+ od.clear()
+ self.assertEqual(len(od), 0)
+
+ def test_delitem(self):
+ OrderedDict = self.OrderedDict
+ pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
+ od = OrderedDict(pairs)
+ del od['a']
+ self.assertNotIn('a', od)
+ with self.assertRaises(KeyError):
+ del od['a']
+ self.assertEqual(list(od.items()), pairs[:2] + pairs[3:])
+
+ def test_setitem(self):
+ OrderedDict = self.OrderedDict
+ od = OrderedDict([('d', 1), ('b', 2), ('c', 3), ('a', 4), ('e', 5)])
+ od['c'] = 10 # existing element
+ od['f'] = 20 # new element
+ self.assertEqual(list(od.items()),
+ [('d', 1), ('b', 2), ('c', 10), ('a', 4), ('e', 5), ('f', 20)])
+
+ def test_iterators(self):
+ OrderedDict = self.OrderedDict
+ pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
+ shuffle(pairs)
+ od = OrderedDict(pairs)
+ self.assertEqual(list(od), [t[0] for t in pairs])
+ self.assertEqual(list(od.keys()), [t[0] for t in pairs])
+ self.assertEqual(list(od.values()), [t[1] for t in pairs])
+ self.assertEqual(list(od.items()), pairs)
+ self.assertEqual(list(reversed(od)),
+ [t[0] for t in reversed(pairs)])
+ self.assertEqual(list(reversed(od.keys())),
+ [t[0] for t in reversed(pairs)])
+ self.assertEqual(list(reversed(od.values())),
+ [t[1] for t in reversed(pairs)])
+ self.assertEqual(list(reversed(od.items())), list(reversed(pairs)))
+
+ def test_detect_deletion_during_iteration(self):
+ OrderedDict = self.OrderedDict
+ od = OrderedDict.fromkeys('abc')
+ it = iter(od)
+ key = next(it)
+ del od[key]
+ with self.assertRaises(Exception):
+ # Note, the exact exception raised is not guaranteed
+ # The only guarantee that the next() will not succeed
+ next(it)
+
+ def test_sorted_iterators(self):
+ OrderedDict = self.OrderedDict
+ with self.assertRaises(TypeError):
+ OrderedDict([('a', 1), ('b', 2)], None)
+ pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
+ od = OrderedDict(pairs)
+ self.assertEqual(sorted(od), [t[0] for t in pairs])
+ self.assertEqual(sorted(od.keys()), [t[0] for t in pairs])
+ self.assertEqual(sorted(od.values()), [t[1] for t in pairs])
+ self.assertEqual(sorted(od.items()), pairs)
+ self.assertEqual(sorted(reversed(od)),
+ sorted([t[0] for t in reversed(pairs)]))
+
+ def test_iterators_empty(self):
+ OrderedDict = self.OrderedDict
+ od = OrderedDict()
+ empty = []
+ self.assertEqual(list(od), empty)
+ self.assertEqual(list(od.keys()), empty)
+ self.assertEqual(list(od.values()), empty)
+ self.assertEqual(list(od.items()), empty)
+ self.assertEqual(list(reversed(od)), empty)
+ self.assertEqual(list(reversed(od.keys())), empty)
+ self.assertEqual(list(reversed(od.values())), empty)
+ self.assertEqual(list(reversed(od.items())), empty)
+
+ def test_popitem(self):
+ OrderedDict = self.OrderedDict
+ pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
+ shuffle(pairs)
+ od = OrderedDict(pairs)
+ while pairs:
+ self.assertEqual(od.popitem(), pairs.pop())
+ with self.assertRaises(KeyError):
+ od.popitem()
+ self.assertEqual(len(od), 0)
+
+ def test_popitem_last(self):
+ OrderedDict = self.OrderedDict
+ pairs = [(i, i) for i in range(30)]
+
+ obj = OrderedDict(pairs)
+ for i in range(8):
+ obj.popitem(True)
+ obj.popitem(True)
+ obj.popitem(last=True)
+ self.assertEqual(len(obj), 20)
+
+ def test_pop(self):
+ OrderedDict = self.OrderedDict
+ pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
+ shuffle(pairs)
+ od = OrderedDict(pairs)
+ shuffle(pairs)
+ while pairs:
+ k, v = pairs.pop()
+ self.assertEqual(od.pop(k), v)
+ with self.assertRaises(KeyError):
+ od.pop('xyz')
+ self.assertEqual(len(od), 0)
+ self.assertEqual(od.pop(k, 12345), 12345)
+
+ # make sure pop still works when __missing__ is defined
+ class Missing(OrderedDict):
+ def __missing__(self, key):
+ return 0
+ m = Missing(a=1)
+ self.assertEqual(m.pop('b', 5), 5)
+ self.assertEqual(m.pop('a', 6), 1)
+ self.assertEqual(m.pop('a', 6), 6)
+ self.assertEqual(m.pop('a', default=6), 6)
+ with self.assertRaises(KeyError):
+ m.pop('a')
+
+ def test_equality(self):
+ OrderedDict = self.OrderedDict
+ pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
+ shuffle(pairs)
+ od1 = OrderedDict(pairs)
+ od2 = OrderedDict(pairs)
+ self.assertEqual(od1, od2) # same order implies equality
+ pairs = pairs[2:] + pairs[:2]
+ od2 = OrderedDict(pairs)
+ self.assertNotEqual(od1, od2) # different order implies inequality
+ # comparison to regular dict is not order sensitive
+ self.assertEqual(od1, dict(od2))
+ self.assertEqual(dict(od2), od1)
+ # different length implied inequality
+ self.assertNotEqual(od1, OrderedDict(pairs[:-1]))
+
+ def test_copying(self):
+ OrderedDict = self.OrderedDict
+ # Check that ordered dicts are copyable, deepcopyable, picklable,
+ # and have a repr/eval round-trip
+ pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
+ od = OrderedDict(pairs)
+ def check(dup):
+ msg = "\ncopy: %s\nod: %s" % (dup, od)
+ self.assertIsNot(dup, od, msg)
+ self.assertEqual(dup, od)
+ self.assertEqual(list(dup.items()), list(od.items()))
+ self.assertEqual(len(dup), len(od))
+ self.assertEqual(type(dup), type(od))
+ check(od.copy())
+ check(copy.copy(od))
+ check(copy.deepcopy(od))
+ # pickle directly pulls the module, so we have to fake it
+ with replaced_module('collections', self.module):
+ for proto in range(pickle.HIGHEST_PROTOCOL + 1):
+ with self.subTest(proto=proto):
+ check(pickle.loads(pickle.dumps(od, proto)))
+ check(eval(repr(od)))
+ update_test = OrderedDict()
+ update_test.update(od)
+ check(update_test)
+ check(OrderedDict(od))
+
+ def test_yaml_linkage(self):
+ OrderedDict = self.OrderedDict
+ # Verify that __reduce__ is setup in a way that supports PyYAML's dump() feature.
+ # In yaml, lists are native but tuples are not.
+ pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
+ od = OrderedDict(pairs)
+ # yaml.dump(od) -->
+ # '!!python/object/apply:__main__.OrderedDict\n- - [a, 1]\n - [b, 2]\n'
+ self.assertTrue(all(type(pair)==list for pair in od.__reduce__()[1]))
+
+ def test_reduce_not_too_fat(self):
+ OrderedDict = self.OrderedDict
+ # do not save instance dictionary if not needed
+ pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
+ od = OrderedDict(pairs)
+ self.assertIsNone(od.__reduce__()[2])
+ od.x = 10
+ self.assertIsNotNone(od.__reduce__()[2])
+
+ def test_pickle_recursive(self):
+ OrderedDict = self.OrderedDict
+ od = OrderedDict()
+ od[1] = od
+
+ # pickle directly pulls the module, so we have to fake it
+ with replaced_module('collections', self.module):
+ for proto in range(-1, pickle.HIGHEST_PROTOCOL + 1):
+ dup = pickle.loads(pickle.dumps(od, proto))
+ self.assertIsNot(dup, od)
+ self.assertEqual(list(dup.keys()), [1])
+ self.assertIs(dup[1], dup)
+
+ def test_repr(self):
+ OrderedDict = self.OrderedDict
+ od = OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)])
+ self.assertEqual(repr(od),
+ "OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)])")
+ self.assertEqual(eval(repr(od)), od)
+ self.assertEqual(repr(OrderedDict()), "OrderedDict()")
+
+ def test_repr_recursive(self):
+ OrderedDict = self.OrderedDict
+ # See issue #9826
+ od = OrderedDict.fromkeys('abc')
+ od['x'] = od
+ self.assertEqual(repr(od),
+ "OrderedDict([('a', None), ('b', None), ('c', None), ('x', ...)])")
+
+ def test_setdefault(self):
+ OrderedDict = self.OrderedDict
+ pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
+ shuffle(pairs)
+ od = OrderedDict(pairs)
+ pair_order = list(od.items())
+ self.assertEqual(od.setdefault('a', 10), 3)
+ # make sure order didn't change
+ self.assertEqual(list(od.items()), pair_order)
+ self.assertEqual(od.setdefault('x', 10), 10)
+ # make sure 'x' is added to the end
+ self.assertEqual(list(od.items())[-1], ('x', 10))
+ self.assertEqual(od.setdefault('g', default=9), 9)
+
+ # make sure setdefault still works when __missing__ is defined
+ class Missing(OrderedDict):
+ def __missing__(self, key):
+ return 0
+ self.assertEqual(Missing().setdefault(5, 9), 9)
+
+ def test_reinsert(self):
+ OrderedDict = self.OrderedDict
+ # Given insert a, insert b, delete a, re-insert a,
+ # verify that a is now later than b.
+ od = OrderedDict()
+ od['a'] = 1
+ od['b'] = 2
+ del od['a']
+ self.assertEqual(list(od.items()), [('b', 2)])
+ od['a'] = 1
+ self.assertEqual(list(od.items()), [('b', 2), ('a', 1)])
+
+ def test_move_to_end(self):
+ OrderedDict = self.OrderedDict
+ od = OrderedDict.fromkeys('abcde')
+ self.assertEqual(list(od), list('abcde'))
+ od.move_to_end('c')
+ self.assertEqual(list(od), list('abdec'))
+ od.move_to_end('c', 0)
+ self.assertEqual(list(od), list('cabde'))
+ od.move_to_end('c', 0)
+ self.assertEqual(list(od), list('cabde'))
+ od.move_to_end('e')
+ self.assertEqual(list(od), list('cabde'))
+ od.move_to_end('b', last=False)
+ self.assertEqual(list(od), list('bcade'))
+ with self.assertRaises(KeyError):
+ od.move_to_end('x')
+ with self.assertRaises(KeyError):
+ od.move_to_end('x', 0)
+
+ def test_move_to_end_issue25406(self):
+ OrderedDict = self.OrderedDict
+ od = OrderedDict.fromkeys('abc')
+ od.move_to_end('c', last=False)
+ self.assertEqual(list(od), list('cab'))
+ od.move_to_end('a', last=False)
+ self.assertEqual(list(od), list('acb'))
+
+ od = OrderedDict.fromkeys('abc')
+ od.move_to_end('a')
+ self.assertEqual(list(od), list('bca'))
+ od.move_to_end('c')
+ self.assertEqual(list(od), list('bac'))
+
+ def test_sizeof(self):
+ OrderedDict = self.OrderedDict
+ # Wimpy test: Just verify the reported size is larger than a regular dict
+ d = dict(a=1)
+ od = OrderedDict(**d)
+ self.assertGreater(sys.getsizeof(od), sys.getsizeof(d))
+
+ def test_override_update(self):
+ OrderedDict = self.OrderedDict
+ # Verify that subclasses can override update() without breaking __init__()
+ class MyOD(OrderedDict):
+ def update(self, *args, **kwds):
+ raise Exception()
+ items = [('a', 1), ('c', 3), ('b', 2)]
+ self.assertEqual(list(MyOD(items).items()), items)
+
+ def test_highly_nested(self):
+ # Issue 25395: crashes during garbage collection
+ OrderedDict = self.OrderedDict
+ obj = None
+ for _ in range(1000):
+ obj = OrderedDict([(None, obj)])
+ del obj
+ support.gc_collect()
+
+ def test_highly_nested_subclass(self):
+ # Issue 25395: crashes during garbage collection
+ OrderedDict = self.OrderedDict
+ deleted = []
+ class MyOD(OrderedDict):
+ def __del__(self):
+ deleted.append(self.i)
+ obj = None
+ for i in range(100):
+ obj = MyOD([(None, obj)])
+ obj.i = i
+ del obj
+ support.gc_collect()
+ self.assertEqual(deleted, list(reversed(range(100))))
+
+ def test_delitem_hash_collision(self):
+ OrderedDict = self.OrderedDict
+
+ class Key:
+ def __init__(self, hash):
+ self._hash = hash
+ self.value = str(id(self))
+ def __hash__(self):
+ return self._hash
+ def __eq__(self, other):
+ try:
+ return self.value == other.value
+ except AttributeError:
+ return False
+ def __repr__(self):
+ return self.value
+
+ def blocking_hash(hash):
+ # See the collision-handling in lookdict (in Objects/dictobject.c).
+ MINSIZE = 8
+ i = (hash & MINSIZE-1)
+ return (i << 2) + i + hash + 1
+
+ COLLIDING = 1
+
+ key = Key(COLLIDING)
+ colliding = Key(COLLIDING)
+ blocking = Key(blocking_hash(COLLIDING))
+
+ od = OrderedDict()
+ od[key] = ...
+ od[blocking] = ...
+ od[colliding] = ...
+ od['after'] = ...
+
+ del od[blocking]
+ del od[colliding]
+ self.assertEqual(list(od.items()), [(key, ...), ('after', ...)])
+
+ def test_issue24347(self):
+ OrderedDict = self.OrderedDict
+
+ class Key:
+ def __hash__(self):
+ return randrange(100000)
+
+ od = OrderedDict()
+ for i in range(100):
+ key = Key()
+ od[key] = i
+
+ # These should not crash.
+ with self.assertRaises(KeyError):
+ list(od.values())
+ with self.assertRaises(KeyError):
+ list(od.items())
+ with self.assertRaises(KeyError):
+ repr(od)
+ with self.assertRaises(KeyError):
+ od.copy()
+
+ def test_issue24348(self):
+ OrderedDict = self.OrderedDict
+
+ class Key:
+ def __hash__(self):
+ return 1
+
+ od = OrderedDict()
+ od[Key()] = 0
+ # This should not crash.
+ od.popitem()
+
+ def test_issue24667(self):
+ """
+ dict resizes after a certain number of insertion operations,
+ whether or not there were deletions that freed up slots in the
+ hash table. During fast node lookup, OrderedDict must correctly
+ respond to all resizes, even if the current "size" is the same
+ as the old one. We verify that here by forcing a dict resize
+ on a sparse odict and then perform an operation that should
+ trigger an odict resize (e.g. popitem). One key aspect here is
+ that we will keep the size of the odict the same at each popitem
+ call. This verifies that we handled the dict resize properly.
+ """
+ OrderedDict = self.OrderedDict
+
+ od = OrderedDict()
+ for c0 in '0123456789ABCDEF':
+ for c1 in '0123456789ABCDEF':
+ if len(od) == 4:
+ # This should not raise a KeyError.
+ od.popitem(last=False)
+ key = c0 + c1
+ od[key] = key
+
+ # Direct use of dict methods
+
+ def test_dict_setitem(self):
+ OrderedDict = self.OrderedDict
+ od = OrderedDict()
+ dict.__setitem__(od, 'spam', 1)
+ self.assertNotIn('NULL', repr(od))
+
+ def test_dict_delitem(self):
+ OrderedDict = self.OrderedDict
+ od = OrderedDict()
+ od['spam'] = 1
+ od['ham'] = 2
+ dict.__delitem__(od, 'spam')
+ with self.assertRaises(KeyError):
+ repr(od)
+
+ def test_dict_clear(self):
+ OrderedDict = self.OrderedDict
+ od = OrderedDict()
+ od['spam'] = 1
+ od['ham'] = 2
+ dict.clear(od)
+ self.assertNotIn('NULL', repr(od))
+
+ def test_dict_pop(self):
+ OrderedDict = self.OrderedDict
+ od = OrderedDict()
+ od['spam'] = 1
+ od['ham'] = 2
+ dict.pop(od, 'spam')
+ with self.assertRaises(KeyError):
+ repr(od)
+
+ def test_dict_popitem(self):
+ OrderedDict = self.OrderedDict
+ od = OrderedDict()
+ od['spam'] = 1
+ od['ham'] = 2
+ dict.popitem(od)
+ with self.assertRaises(KeyError):
+ repr(od)
+
+ def test_dict_setdefault(self):
+ OrderedDict = self.OrderedDict
+ od = OrderedDict()
+ dict.setdefault(od, 'spam', 1)
+ self.assertNotIn('NULL', repr(od))
+
+ def test_dict_update(self):
+ OrderedDict = self.OrderedDict
+ od = OrderedDict()
+ dict.update(od, [('spam', 1)])
+ self.assertNotIn('NULL', repr(od))
+
+ def test_reference_loop(self):
+ # Issue 25935
+ OrderedDict = self.OrderedDict
+ class A:
+ od = OrderedDict()
+ A.od[A] = None
+ r = weakref.ref(A)
+ del A
+ gc.collect()
+ self.assertIsNone(r())
+
+ def test_free_after_iterating(self):
+ support.check_free_after_iterating(self, iter, self.OrderedDict)
+ support.check_free_after_iterating(self, lambda d: iter(d.keys()), self.OrderedDict)
+ support.check_free_after_iterating(self, lambda d: iter(d.values()), self.OrderedDict)
+ support.check_free_after_iterating(self, lambda d: iter(d.items()), self.OrderedDict)
+
+
+class PurePythonOrderedDictTests(OrderedDictTests, unittest.TestCase):
+
+ module = py_coll
+ OrderedDict = py_coll.OrderedDict
+
+
+@unittest.skipUnless(c_coll, 'requires the C version of the collections module')
+class CPythonOrderedDictTests(OrderedDictTests, unittest.TestCase):
+
+ module = c_coll
+ OrderedDict = c_coll.OrderedDict
+ check_sizeof = support.check_sizeof
+
+ @support.cpython_only
+ def test_sizeof_exact(self):
+ OrderedDict = self.OrderedDict
+ calcsize = struct.calcsize
+ size = support.calcobjsize
+ check = self.check_sizeof
+
+ basicsize = size('n2P' + '3PnPn2P') + calcsize('2nPn')
+ entrysize = calcsize('n2P') + calcsize('P')
+ nodesize = calcsize('Pn2P')
+
+ od = OrderedDict()
+ check(od, basicsize + 8*entrysize)
+ od.x = 1
+ check(od, basicsize + 8*entrysize)
+ od.update([(i, i) for i in range(3)])
+ check(od, basicsize + 8*entrysize + 3*nodesize)
+ od.update([(i, i) for i in range(3, 10)])
+ check(od, basicsize + 16*entrysize + 10*nodesize)
+
+ check(od.keys(), size('P'))
+ check(od.items(), size('P'))
+ check(od.values(), size('P'))
+
+ itersize = size('iP2n2P')
+ check(iter(od), itersize)
+ check(iter(od.keys()), itersize)
+ check(iter(od.items()), itersize)
+ check(iter(od.values()), itersize)
+
+ def test_key_change_during_iteration(self):
+ OrderedDict = self.OrderedDict
+
+ od = OrderedDict.fromkeys('abcde')
+ self.assertEqual(list(od), list('abcde'))
+ with self.assertRaises(RuntimeError):
+ for i, k in enumerate(od):
+ od.move_to_end(k)
+ self.assertLess(i, 5)
+ with self.assertRaises(RuntimeError):
+ for k in od:
+ od['f'] = None
+ with self.assertRaises(RuntimeError):
+ for k in od:
+ del od['c']
+ self.assertEqual(list(od), list('bdeaf'))
+
+
+class PurePythonOrderedDictSubclassTests(PurePythonOrderedDictTests):
+
+ module = py_coll
+ class OrderedDict(py_coll.OrderedDict):
+ pass
+
+
+class CPythonOrderedDictSubclassTests(CPythonOrderedDictTests):
+
+ module = c_coll
+ class OrderedDict(c_coll.OrderedDict):
+ pass
+
+
+class PurePythonGeneralMappingTests(mapping_tests.BasicTestMappingProtocol):
+
+ @classmethod
+ def setUpClass(cls):
+ cls.type2test = py_coll.OrderedDict
+
+ def test_popitem(self):
+ d = self._empty_mapping()
+ self.assertRaises(KeyError, d.popitem)
+
+
+@unittest.skipUnless(c_coll, 'requires the C version of the collections module')
+class CPythonGeneralMappingTests(mapping_tests.BasicTestMappingProtocol):
+
+ @classmethod
+ def setUpClass(cls):
+ cls.type2test = c_coll.OrderedDict
+
+ def test_popitem(self):
+ d = self._empty_mapping()
+ self.assertRaises(KeyError, d.popitem)
+
+
+class PurePythonSubclassMappingTests(mapping_tests.BasicTestMappingProtocol):
+
+ @classmethod
+ def setUpClass(cls):
+ class MyOrderedDict(py_coll.OrderedDict):
+ pass
+ cls.type2test = MyOrderedDict
+
+ def test_popitem(self):
+ d = self._empty_mapping()
+ self.assertRaises(KeyError, d.popitem)
+
+
+@unittest.skipUnless(c_coll, 'requires the C version of the collections module')
+class CPythonSubclassMappingTests(mapping_tests.BasicTestMappingProtocol):
+
+ @classmethod
+ def setUpClass(cls):
+ class MyOrderedDict(c_coll.OrderedDict):
+ pass
+ cls.type2test = MyOrderedDict
+
+ def test_popitem(self):
+ d = self._empty_mapping()
+ self.assertRaises(KeyError, d.popitem)
+
+
+if __name__ == "__main__":
+ unittest.main()
# Wrapper to hide minor differences between os.walk and os.fwalk
# to tests both functions with the same code base
- def walk(self, directory, topdown=True, follow_symlinks=False):
- walk_it = os.walk(directory,
- topdown=topdown,
- followlinks=follow_symlinks)
- for root, dirs, files in walk_it:
- yield (root, dirs, files)
+ def walk(self, top, **kwargs):
+ if 'follow_symlinks' in kwargs:
+ kwargs['followlinks'] = kwargs.pop('follow_symlinks')
+ return os.walk(top, **kwargs)
def setUp(self):
join = os.path.join
def test_walk_topdown(self):
# Walk top-down.
- all = list(os.walk(self.walk_path))
+ all = list(self.walk(self.walk_path))
self.assertEqual(len(all), 4)
# We can't know which order SUB1 and SUB2 will appear in.
os.remove(dirname)
os.rmdir(support.TESTFN)
+ def test_walk_bad_dir(self):
+ # Walk top-down.
+ errors = []
+ walk_it = self.walk(self.walk_path, onerror=errors.append)
+ root, dirs, files = next(walk_it)
+ self.assertFalse(errors)
+ dir1 = dirs[0]
+ dir1new = dir1 + '.new'
+ os.rename(os.path.join(root, dir1), os.path.join(root, dir1new))
+ roots = [r for r, d, f in walk_it]
+ self.assertTrue(errors)
+ self.assertNotIn(os.path.join(root, dir1), roots)
+ self.assertNotIn(os.path.join(root, dir1new), roots)
+ for dir2 in dirs[1:]:
+ self.assertIn(os.path.join(root, dir2), roots)
+
@unittest.skipUnless(hasattr(os, 'fwalk'), "Test needs os.fwalk()")
class FwalkTests(WalkTests):
"""Tests for os.fwalk()."""
- def walk(self, directory, topdown=True, follow_symlinks=False):
- walk_it = os.fwalk(directory,
- topdown=topdown,
- follow_symlinks=follow_symlinks)
- for root, dirs, files, root_fd in walk_it:
+ def walk(self, top, **kwargs):
+ for root, dirs, files, root_fd in os.fwalk(top, **kwargs):
yield (root, dirs, files)
-
def _compare_to_walk(self, walk_kwargs, fwalk_kwargs):
"""
compare with walk() results.
os.unlink(name, dir_fd=rootfd)
os.rmdir(support.TESTFN)
+class BytesWalkTests(WalkTests):
+ """Tests for os.walk() with bytes."""
+ def setUp(self):
+ super().setUp()
+ self.stack = contextlib.ExitStack()
+ if os.name == 'nt':
+ self.stack.enter_context(warnings.catch_warnings())
+ warnings.simplefilter("ignore", DeprecationWarning)
+
+ def tearDown(self):
+ self.stack.close()
+ super().tearDown()
+
+ def walk(self, top, **kwargs):
+ if 'follow_symlinks' in kwargs:
+ kwargs['followlinks'] = kwargs.pop('follow_symlinks')
+ for broot, bdirs, bfiles in os.walk(os.fsencode(top), **kwargs):
+ root = os.fsdecode(broot)
+ dirs = list(map(os.fsdecode, bdirs))
+ files = list(map(os.fsdecode, bfiles))
+ yield (root, dirs, files)
+ bdirs[:] = list(map(os.fsencode, dirs))
+ bfiles[:] = list(map(os.fsencode, files))
+
class MakedirTests(unittest.TestCase):
def setUp(self):
def _check_str_subclass(self, *args):
# Issue #21127: it should be possible to construct a PurePath object
- # from an str subclass instance, and it then gets converted to
+ # from a str subclass instance, and it then gets converted to
# a pure str object.
class StrSubclass(str):
pass
# UNC paths are never reserved
self.assertIs(False, P('//my/share/nul/con/aux').is_reserved())
-
class PurePathTest(_BasePurePathTest, unittest.TestCase):
cls = pathlib.PurePath
class WindowsPathAsPureTest(PureWindowsPathTest):
cls = pathlib.WindowsPath
+ def test_owner(self):
+ P = self.cls
+ with self.assertRaises(NotImplementedError):
+ P('c:/').owner()
+
+ def test_group(self):
+ P = self.cls
+ with self.assertRaises(NotImplementedError):
+ P('c:/').group()
+
class _BasePathTest(object):
"""Tests for the FS-accessing functionalities of the Path classes."""
# (BASE)
# |
- # |-- dirA/
- # |-- linkC -> "../dirB"
- # |-- dirB/
- # | |-- fileB
- # |-- linkD -> "../dirB"
- # |-- dirC/
- # | |-- fileC
- # | |-- fileD
+ # |-- brokenLink -> non-existing
+ # |-- dirA
+ # | `-- linkC -> ../dirB
+ # |-- dirB
+ # | |-- fileB
+ # | `-- linkD -> ../dirB
+ # |-- dirC
+ # | |-- dirD
+ # | | `-- fileD
+ # | `-- fileC
+ # |-- dirE # No permissions
# |-- fileA
- # |-- linkA -> "fileA"
- # |-- linkB -> "dirB"
+ # |-- linkA -> fileA
+ # `-- linkB -> dirB
#
def setUp(self):
+ def cleanup():
+ os.chmod(join('dirE'), 0o777)
+ support.rmtree(BASE)
+ self.addCleanup(cleanup)
os.mkdir(BASE)
- self.addCleanup(support.rmtree, BASE)
os.mkdir(join('dirA'))
os.mkdir(join('dirB'))
os.mkdir(join('dirC'))
os.mkdir(join('dirC', 'dirD'))
+ os.mkdir(join('dirE'))
with open(join('fileA'), 'wb') as f:
f.write(b"this is file A\n")
with open(join('dirB', 'fileB'), 'wb') as f:
f.write(b"this is file C\n")
with open(join('dirC', 'dirD', 'fileD'), 'wb') as f:
f.write(b"this is file D\n")
+ os.chmod(join('dirE'), 0)
if not symlink_skip_reason:
# Relative symlinks
os.symlink('fileA', join('linkA'))
os.symlink('non-existing', join('brokenLink'))
self.dirlink('dirB', join('linkB'))
self.dirlink(os.path.join('..', 'dirB'), join('dirA', 'linkC'))
- # This one goes upwards but doesn't create a loop
+ # This one goes upwards, creating a loop
self.dirlink(os.path.join('..', 'dirB'), join('dirB', 'linkD'))
if os.name == 'nt':
p = P(BASE)
it = p.iterdir()
paths = set(it)
- expected = ['dirA', 'dirB', 'dirC', 'fileA']
+ expected = ['dirA', 'dirB', 'dirC', 'dirE', 'fileA']
if not symlink_skip_reason:
expected += ['linkA', 'linkB', 'brokenLink']
self.assertEqual(paths, { P(BASE, q) for q in expected })
p = P(BASE)
it = p.rglob("fileA")
self.assertIsInstance(it, collections.Iterator)
- # XXX cannot test because of symlink loops in the test setup
- #_check(it, ["fileA"])
- #_check(p.rglob("fileB"), ["dirB/fileB"])
- #_check(p.rglob("*/fileA"), [""])
- #_check(p.rglob("*/fileB"), ["dirB/fileB"])
- #_check(p.rglob("file*"), ["fileA", "dirB/fileB"])
- # No symlink loops here
+ _check(it, ["fileA"])
+ _check(p.rglob("fileB"), ["dirB/fileB"])
+ _check(p.rglob("*/fileA"), [])
+ if symlink_skip_reason:
+ _check(p.rglob("*/fileB"), ["dirB/fileB"])
+ else:
+ _check(p.rglob("*/fileB"), ["dirB/fileB", "dirB/linkD/fileB",
+ "linkB/fileB", "dirA/linkC/fileB"])
+ _check(p.rglob("file*"), ["fileA", "dirB/fileB",
+ "dirC/fileC", "dirC/dirD/fileD"])
p = P(BASE, "dirC")
_check(p.rglob("file*"), ["dirC/fileC", "dirC/dirD/fileD"])
_check(p.rglob("*/*"), ["dirC/dirD/fileD"])
+ @with_symlinks
+ def test_rglob_symlink_loop(self):
+ # Don't get fooled by symlink loops (Issue #26012)
+ P = self.cls
+ p = P(BASE)
+ given = set(p.rglob('*'))
+ expect = {'brokenLink',
+ 'dirA', 'dirA/linkC',
+ 'dirB', 'dirB/fileB', 'dirB/linkD',
+ 'dirC', 'dirC/dirD', 'dirC/dirD/fileD', 'dirC/fileC',
+ 'dirE',
+ 'fileA',
+ 'linkA',
+ 'linkB',
+ }
+ self.assertEqual(given, {p / x for x in expect})
+
def test_glob_dotdot(self):
# ".." is not special in globs
P = self.cls
else:
self.assertRaises(NotImplementedError, pathlib.WindowsPath)
+ def test_glob_empty_pattern(self):
+ p = self.cls()
+ with self.assertRaisesRegex(ValueError, 'Unacceptable pattern'):
+ list(p.glob(''))
+
@only_posix
class PosixPathTest(_BasePathTest, unittest.TestCase):
import pwd
pwdent = pwd.getpwuid(os.getuid())
username = pwdent.pw_name
- userhome = pwdent.pw_dir.rstrip('/')
+ userhome = pwdent.pw_dir.rstrip('/') or '/'
# find arbitrary different user (if exists)
for pwdent in pwd.getpwall():
othername = pwdent.pw_name
"""
def test_pdb_next_command_in_generator_for_loop():
- """The next command on returning from a generator controled by a for loop.
+ """The next command on returning from a generator controlled by a for loop.
>>> def test_gen():
... yield 0
+++ /dev/null
-# Copyright (C) 2004 Python Software Foundation
-# Author: barry@python.org (Barry Warsaw)
-# License: http://www.opensource.org/licenses/PythonSoftFoundation.php
-
-import unittest
-from string import Template
-
-
-class Bag:
- pass
-
-class Mapping:
- def __getitem__(self, name):
- obj = self
- for part in name.split('.'):
- try:
- obj = getattr(obj, part)
- except AttributeError:
- raise KeyError(name)
- return obj
-
-
-class TestTemplate(unittest.TestCase):
- def test_regular_templates(self):
- s = Template('$who likes to eat a bag of $what worth $$100')
- self.assertEqual(s.substitute(dict(who='tim', what='ham')),
- 'tim likes to eat a bag of ham worth $100')
- self.assertRaises(KeyError, s.substitute, dict(who='tim'))
- self.assertRaises(TypeError, Template.substitute)
-
- def test_regular_templates_with_braces(self):
- s = Template('$who likes ${what} for ${meal}')
- d = dict(who='tim', what='ham', meal='dinner')
- self.assertEqual(s.substitute(d), 'tim likes ham for dinner')
- self.assertRaises(KeyError, s.substitute,
- dict(who='tim', what='ham'))
-
- def test_escapes(self):
- eq = self.assertEqual
- s = Template('$who likes to eat a bag of $$what worth $$100')
- eq(s.substitute(dict(who='tim', what='ham')),
- 'tim likes to eat a bag of $what worth $100')
- s = Template('$who likes $$')
- eq(s.substitute(dict(who='tim', what='ham')), 'tim likes $')
-
- def test_percents(self):
- eq = self.assertEqual
- s = Template('%(foo)s $foo ${foo}')
- d = dict(foo='baz')
- eq(s.substitute(d), '%(foo)s baz baz')
- eq(s.safe_substitute(d), '%(foo)s baz baz')
-
- def test_stringification(self):
- eq = self.assertEqual
- s = Template('tim has eaten $count bags of ham today')
- d = dict(count=7)
- eq(s.substitute(d), 'tim has eaten 7 bags of ham today')
- eq(s.safe_substitute(d), 'tim has eaten 7 bags of ham today')
- s = Template('tim has eaten ${count} bags of ham today')
- eq(s.substitute(d), 'tim has eaten 7 bags of ham today')
-
- def test_tupleargs(self):
- eq = self.assertEqual
- s = Template('$who ate ${meal}')
- d = dict(who=('tim', 'fred'), meal=('ham', 'kung pao'))
- eq(s.substitute(d), "('tim', 'fred') ate ('ham', 'kung pao')")
- eq(s.safe_substitute(d), "('tim', 'fred') ate ('ham', 'kung pao')")
-
- def test_SafeTemplate(self):
- eq = self.assertEqual
- s = Template('$who likes ${what} for ${meal}')
- eq(s.safe_substitute(dict(who='tim')), 'tim likes ${what} for ${meal}')
- eq(s.safe_substitute(dict(what='ham')), '$who likes ham for ${meal}')
- eq(s.safe_substitute(dict(what='ham', meal='dinner')),
- '$who likes ham for dinner')
- eq(s.safe_substitute(dict(who='tim', what='ham')),
- 'tim likes ham for ${meal}')
- eq(s.safe_substitute(dict(who='tim', what='ham', meal='dinner')),
- 'tim likes ham for dinner')
-
- def test_invalid_placeholders(self):
- raises = self.assertRaises
- s = Template('$who likes $')
- raises(ValueError, s.substitute, dict(who='tim'))
- s = Template('$who likes ${what)')
- raises(ValueError, s.substitute, dict(who='tim'))
- s = Template('$who likes $100')
- raises(ValueError, s.substitute, dict(who='tim'))
-
- def test_idpattern_override(self):
- class PathPattern(Template):
- idpattern = r'[_a-z][._a-z0-9]*'
- m = Mapping()
- m.bag = Bag()
- m.bag.foo = Bag()
- m.bag.foo.who = 'tim'
- m.bag.what = 'ham'
- s = PathPattern('$bag.foo.who likes to eat a bag of $bag.what')
- self.assertEqual(s.substitute(m), 'tim likes to eat a bag of ham')
-
- def test_pattern_override(self):
- class MyPattern(Template):
- pattern = r"""
- (?P<escaped>@{2}) |
- @(?P<named>[_a-z][._a-z0-9]*) |
- @{(?P<braced>[_a-z][._a-z0-9]*)} |
- (?P<invalid>@)
- """
- m = Mapping()
- m.bag = Bag()
- m.bag.foo = Bag()
- m.bag.foo.who = 'tim'
- m.bag.what = 'ham'
- s = MyPattern('@bag.foo.who likes to eat a bag of @bag.what')
- self.assertEqual(s.substitute(m), 'tim likes to eat a bag of ham')
-
- class BadPattern(Template):
- pattern = r"""
- (?P<badname>.*) |
- (?P<escaped>@{2}) |
- @(?P<named>[_a-z][._a-z0-9]*) |
- @{(?P<braced>[_a-z][._a-z0-9]*)} |
- (?P<invalid>@) |
- """
- s = BadPattern('@bag.foo.who likes to eat a bag of @bag.what')
- self.assertRaises(ValueError, s.substitute, {})
- self.assertRaises(ValueError, s.safe_substitute, {})
-
- def test_braced_override(self):
- class MyTemplate(Template):
- pattern = r"""
- \$(?:
- (?P<escaped>$) |
- (?P<named>[_a-z][_a-z0-9]*) |
- @@(?P<braced>[_a-z][_a-z0-9]*)@@ |
- (?P<invalid>) |
- )
- """
-
- tmpl = 'PyCon in $@@location@@'
- t = MyTemplate(tmpl)
- self.assertRaises(KeyError, t.substitute, {})
- val = t.substitute({'location': 'Cleveland'})
- self.assertEqual(val, 'PyCon in Cleveland')
-
- def test_braced_override_safe(self):
- class MyTemplate(Template):
- pattern = r"""
- \$(?:
- (?P<escaped>$) |
- (?P<named>[_a-z][_a-z0-9]*) |
- @@(?P<braced>[_a-z][_a-z0-9]*)@@ |
- (?P<invalid>) |
- )
- """
-
- tmpl = 'PyCon in $@@location@@'
- t = MyTemplate(tmpl)
- self.assertEqual(t.safe_substitute(), tmpl)
- val = t.safe_substitute({'location': 'Cleveland'})
- self.assertEqual(val, 'PyCon in Cleveland')
-
- def test_invalid_with_no_lines(self):
- # The error formatting for invalid templates
- # has a special case for no data that the default
- # pattern can't trigger (always has at least '$')
- # So we craft a pattern that is always invalid
- # with no leading data.
- class MyTemplate(Template):
- pattern = r"""
- (?P<invalid>) |
- unreachable(
- (?P<named>) |
- (?P<braced>) |
- (?P<escaped>)
- )
- """
- s = MyTemplate('')
- with self.assertRaises(ValueError) as err:
- s.substitute({})
- self.assertIn('line 1, col 1', str(err.exception))
-
- def test_unicode_values(self):
- s = Template('$who likes $what')
- d = dict(who='t\xffm', what='f\xfe\fed')
- self.assertEqual(s.substitute(d), 't\xffm likes f\xfe\x0ced')
-
- def test_keyword_arguments(self):
- eq = self.assertEqual
- s = Template('$who likes $what')
- eq(s.substitute(who='tim', what='ham'), 'tim likes ham')
- eq(s.substitute(dict(who='tim'), what='ham'), 'tim likes ham')
- eq(s.substitute(dict(who='fred', what='kung pao'),
- who='tim', what='ham'),
- 'tim likes ham')
- s = Template('the mapping is $mapping')
- eq(s.substitute(dict(foo='none'), mapping='bozo'),
- 'the mapping is bozo')
- eq(s.substitute(dict(mapping='one'), mapping='two'),
- 'the mapping is two')
-
- s = Template('the self is $self')
- eq(s.substitute(self='bozo'), 'the self is bozo')
-
- def test_keyword_arguments_safe(self):
- eq = self.assertEqual
- raises = self.assertRaises
- s = Template('$who likes $what')
- eq(s.safe_substitute(who='tim', what='ham'), 'tim likes ham')
- eq(s.safe_substitute(dict(who='tim'), what='ham'), 'tim likes ham')
- eq(s.safe_substitute(dict(who='fred', what='kung pao'),
- who='tim', what='ham'),
- 'tim likes ham')
- s = Template('the mapping is $mapping')
- eq(s.safe_substitute(dict(foo='none'), mapping='bozo'),
- 'the mapping is bozo')
- eq(s.safe_substitute(dict(mapping='one'), mapping='two'),
- 'the mapping is two')
- d = dict(mapping='one')
- raises(TypeError, s.substitute, d, {})
- raises(TypeError, s.safe_substitute, d, {})
-
- s = Template('the self is $self')
- eq(s.safe_substitute(self='bozo'), 'the self is bozo')
-
- def test_delimiter_override(self):
- eq = self.assertEqual
- raises = self.assertRaises
- class AmpersandTemplate(Template):
- delimiter = '&'
- s = AmpersandTemplate('this &gift is for &{who} &&')
- eq(s.substitute(gift='bud', who='you'), 'this bud is for you &')
- raises(KeyError, s.substitute)
- eq(s.safe_substitute(gift='bud', who='you'), 'this bud is for you &')
- eq(s.safe_substitute(), 'this &gift is for &{who} &')
- s = AmpersandTemplate('this &gift is for &{who} &')
- raises(ValueError, s.substitute, dict(gift='bud', who='you'))
- eq(s.safe_substitute(), 'this &gift is for &{who} &')
-
- class PieDelims(Template):
- delimiter = '@'
- s = PieDelims('@who likes to eat a bag of @{what} worth $100')
- self.assertEqual(s.substitute(dict(who='tim', what='ham')),
- 'tim likes to eat a bag of ham worth $100')
-
-
-if __name__ == '__main__':
- unittest.main()
e = SubOSError(EEXIST, "Bad file descriptor")
self.assertIs(type(e), SubOSError)
- def test_init_overriden(self):
+ def test_init_overridden(self):
e = SubOSErrorWithInit("some message", "baz")
self.assertEqual(e.bar, "baz")
self.assertEqual(e.args, ("some message",))
self.assertEqual(e.bar, "baz")
self.assertEqual(e.args, ("some message",))
- def test_new_overriden(self):
+ def test_new_overridden(self):
e = SubOSErrorWithNew("some message", "baz")
self.assertEqual(e.baz, "baz")
self.assertEqual(e.args, ("some message",))
self.assertEqual(e.baz, "baz")
self.assertEqual(e.args, ("some message",))
- def test_init_new_overriden(self):
+ def test_init_new_overridden(self):
e = SubOSErrorCombinedInitFirst("some message", "baz")
self.assertEqual(e.bar, "baz")
self.assertEqual(e.baz, "baz")
class PyUnpicklerTests(AbstractUnpickleTests):
unpickler = pickle._Unpickler
+ bad_stack_errors = (IndexError,)
+ bad_mark_errors = (IndexError, pickle.UnpicklingError,
+ TypeError, AttributeError, EOFError)
+ truncated_errors = (pickle.UnpicklingError, EOFError,
+ AttributeError, ValueError,
+ struct.error, IndexError, ImportError)
def loads(self, buf, **kwds):
f = io.BytesIO(buf)
pickler = pickle._Pickler
unpickler = pickle._Unpickler
+ bad_stack_errors = (pickle.UnpicklingError, IndexError)
+ bad_mark_errors = (pickle.UnpicklingError, IndexError,
+ TypeError, AttributeError, EOFError)
+ truncated_errors = (pickle.UnpicklingError, EOFError,
+ AttributeError, ValueError,
+ struct.error, IndexError, ImportError)
def dumps(self, arg, protocol=None):
return pickle.dumps(arg, protocol)
if has_c_implementation:
class CUnpicklerTests(PyUnpicklerTests):
unpickler = _pickle.Unpickler
+ bad_stack_errors = (pickle.UnpicklingError,)
+ bad_mark_errors = (EOFError,)
+ truncated_errors = (pickle.UnpicklingError, EOFError,
+ AttributeError, ValueError)
class CPicklerTests(PyPicklerTests):
pickler = _pickle.Pickler
ALT_IMPORT_MAPPING = {
('_elementtree', 'xml.etree.ElementTree'),
('cPickle', 'pickle'),
+ ('StringIO', 'io'),
+ ('cStringIO', 'io'),
}
ALT_NAME_MAPPING = {
import os
import os.path
import tempfile
-import types
import shutil
import zipfile
for t in pkgutil.walk_packages(path=[self.dirname]):
self.fail("unexpected package found")
+ def test_walkpackages_filesys(self):
+ pkg1 = 'test_walkpackages_filesys'
+ pkg1_dir = os.path.join(self.dirname, pkg1)
+ os.mkdir(pkg1_dir)
+ f = open(os.path.join(pkg1_dir, '__init__.py'), "wb")
+ f.close()
+ os.mkdir(os.path.join(pkg1_dir, 'sub'))
+ f = open(os.path.join(pkg1_dir, 'sub', '__init__.py'), "wb")
+ f.close()
+ f = open(os.path.join(pkg1_dir, 'sub', 'mod.py'), "wb")
+ f.close()
+
+ # Now, to juice it up, let's add the opposite packages, too.
+ pkg2 = 'sub'
+ pkg2_dir = os.path.join(self.dirname, pkg2)
+ os.mkdir(pkg2_dir)
+ f = open(os.path.join(pkg2_dir, '__init__.py'), "wb")
+ f.close()
+ os.mkdir(os.path.join(pkg2_dir, 'test_walkpackages_filesys'))
+ f = open(os.path.join(pkg2_dir, 'test_walkpackages_filesys', '__init__.py'), "wb")
+ f.close()
+ f = open(os.path.join(pkg2_dir, 'test_walkpackages_filesys', 'mod.py'), "wb")
+ f.close()
+
+ expected = [
+ 'sub',
+ 'sub.test_walkpackages_filesys',
+ 'sub.test_walkpackages_filesys.mod',
+ 'test_walkpackages_filesys',
+ 'test_walkpackages_filesys.sub',
+ 'test_walkpackages_filesys.sub.mod',
+ ]
+ actual= [e[1] for e in pkgutil.walk_packages([self.dirname])]
+ self.assertEqual(actual, expected)
+
+ for pkg in expected:
+ if pkg.endswith('mod'):
+ continue
+ del sys.modules[pkg]
+
+ def test_walkpackages_zipfile(self):
+ """Tests the same as test_walkpackages_filesys, only with a zip file."""
+
+ zip = 'test_walkpackages_zipfile.zip'
+ pkg1 = 'test_walkpackages_zipfile'
+ pkg2 = 'sub'
+
+ zip_file = os.path.join(self.dirname, zip)
+ z = zipfile.ZipFile(zip_file, 'w')
+ z.writestr(pkg2 + '/__init__.py', "")
+ z.writestr(pkg2 + '/' + pkg1 + '/__init__.py', "")
+ z.writestr(pkg2 + '/' + pkg1 + '/mod.py', "")
+ z.writestr(pkg1 + '/__init__.py', "")
+ z.writestr(pkg1 + '/' + pkg2 + '/__init__.py', "")
+ z.writestr(pkg1 + '/' + pkg2 + '/mod.py', "")
+ z.close()
+
+ sys.path.insert(0, zip_file)
+ expected = [
+ 'sub',
+ 'sub.test_walkpackages_zipfile',
+ 'sub.test_walkpackages_zipfile.mod',
+ 'test_walkpackages_zipfile',
+ 'test_walkpackages_zipfile.sub',
+ 'test_walkpackages_zipfile.sub.mod',
+ ]
+ actual= [e[1] for e in pkgutil.walk_packages([zip_file])]
+ self.assertEqual(actual, expected)
+ del sys.path[0]
+
+ for pkg in expected:
+ if pkg.endswith('mod'):
+ continue
+ del sys.modules[pkg]
+
+
+
class PkgutilPEP302Tests(unittest.TestCase):
class MyTestLoader(object):
def test_importer_deprecated(self):
with self.check_deprecated():
- x = pkgutil.ImpImporter("")
+ pkgutil.ImpImporter("")
def test_loader_deprecated(self):
with self.check_deprecated():
- x = pkgutil.ImpLoader("", "", "", "")
+ pkgutil.ImpLoader("", "", "", "")
def test_get_loader_avoids_emulation(self):
with check_warnings() as w:
('IronPython', '1.0.60816', '', '', '', '', '.NET 2.0.50727.42')),
('IronPython 1.0 (1.0.61005.1977) on .NET 2.0.50727.42',
('IronPython', '1.0.0', '', '', '', '', '.NET 2.0.50727.42')),
+ ('2.4.3 (truncation, date, t) \n[GCC]',
+ ('CPython', '2.4.3', '', '', 'truncation', 'date t', 'GCC')),
+ ('2.4.3 (truncation, date, ) \n[GCC]',
+ ('CPython', '2.4.3', '', '', 'truncation', 'date', 'GCC')),
+ ('2.4.3 (truncation, date,) \n[GCC]',
+ ('CPython', '2.4.3', '', '', 'truncation', 'date', 'GCC')),
+ ('2.4.3 (truncation, date) \n[GCC]',
+ ('CPython', '2.4.3', '', '', 'truncation', 'date', 'GCC')),
+ ('2.4.3 (truncation, d) \n[GCC]',
+ ('CPython', '2.4.3', '', '', 'truncation', 'd', 'GCC')),
+ ('2.4.3 (truncation, ) \n[GCC]',
+ ('CPython', '2.4.3', '', '', 'truncation', '', 'GCC')),
+ ('2.4.3 (truncation,) \n[GCC]',
+ ('CPython', '2.4.3', '', '', 'truncation', '', 'GCC')),
+ ('2.4.3 (truncation) \n[GCC]',
+ ('CPython', '2.4.3', '', '', 'truncation', '', 'GCC')),
):
# branch and revision are not "parsed", but fetched
# from sys._mercurial. Ignore them
platform.dist()
self.assertEqual(str(cm.warning),
'dist() and linux_distribution() functions are '
- 'deprecated in Python 3.5 and will be removed in '
- 'Python 3.7')
+ 'deprecated in Python 3.5')
def test_linux_distribution_deprecation(self):
with self.assertWarns(PendingDeprecationWarning) as cm:
platform.linux_distribution()
self.assertEqual(str(cm.warning),
'dist() and linux_distribution() functions are '
- 'deprecated in Python 3.5 and will be removed in '
- 'Python 3.7')
+ 'deprecated in Python 3.5')
if __name__ == '__main__':
unittest.main()
b'\x00\x00\x00\x00\x00\x00\x00\x13')
self.assertEqual(plistlib.loads(data), {'a': 'b'})
+ def test_large_timestamp(self):
+ # Issue #26709: 32-bit timestamp out of range
+ for ts in -2**31-1, 2**31:
+ with self.subTest(ts=ts):
+ d = (datetime.datetime.utcfromtimestamp(0) +
+ datetime.timedelta(seconds=ts))
+ data = plistlib.dumps(d, fmt=plistlib.FMT_BINARY)
+ self.assertEqual(plistlib.loads(data), d)
+
class TestPlistlibDeprecated(unittest.TestCase):
def test_io_deprecated(self):
cur = plistlib.loads(buf)
self.assertEqual(cur, out_data)
- self.assertNotEqual(cur, in_data)
+ self.assertEqual(cur, in_data)
cur = plistlib.loads(buf, use_builtin_types=False)
- self.assertNotEqual(cur, out_data)
+ self.assertEqual(cur, out_data)
self.assertEqual(cur, in_data)
with self.assertWarns(DeprecationWarning):
cur = plistlib.readPlistFromBytes(buf)
- self.assertNotEqual(cur, out_data)
+ self.assertEqual(cur, out_data)
self.assertEqual(cur, in_data)
def test_expanduser(self):
self.assertEqual(posixpath.expanduser("foo"), "foo")
self.assertEqual(posixpath.expanduser(b"foo"), b"foo")
+ with support.EnvironmentVarGuard() as env:
+ for home in '/', '', '//', '///':
+ with self.subTest(home=home):
+ env['HOME'] = home
+ self.assertEqual(posixpath.expanduser("~"), "/")
+ self.assertEqual(posixpath.expanduser("~/"), "/")
+ self.assertEqual(posixpath.expanduser("~/foo"), "/foo")
try:
import pwd
except ImportError:
self.assertIsInstance(posixpath.expanduser(b"~foo/"), bytes)
with support.EnvironmentVarGuard() as env:
- env['HOME'] = '/'
- self.assertEqual(posixpath.expanduser("~"), "/")
- self.assertEqual(posixpath.expanduser("~/foo"), "/foo")
# expanduser should fall back to using the password database
del env['HOME']
home = pwd.getpwuid(os.getuid()).pw_dir
# $HOME can end with a trailing /, so strip it (see #17809)
- self.assertEqual(posixpath.expanduser("~"), home.rstrip("/"))
+ home = home.rstrip("/") or '/'
+ self.assertEqual(posixpath.expanduser("~"), home)
def test_normpath(self):
self.assertEqual(posixpath.normpath(""), ".")
"""new docstring"""
return 8
-class PropertyWritableDoc(object):
-
- @property
- def spam(self):
- """Eggs"""
- return "eggs"
-
class PropertyTests(unittest.TestCase):
def test_property_decorator_baseclass(self):
# see #1620
@unittest.skipIf(sys.flags.optimize >= 2,
"Docstrings are omitted with -O2 and above")
def test_property_decorator_doc_writable(self):
+ class PropertyWritableDoc(object):
+
+ @property
+ def spam(self):
+ """Eggs"""
+ return "eggs"
+
sub = PropertyWritableDoc()
self.assertEqual(sub.__class__.spam.__doc__, 'Eggs')
sub.__class__.spam.__doc__ = 'Spam'
import sys
from types import FunctionType, MethodType, BuiltinFunctionType
import pyclbr
-from unittest import TestCase
+from unittest import TestCase, main as unittest_main
StaticMethodType = type(staticmethod(lambda: None))
ClassMethodType = type(classmethod(lambda c: None))
if __name__ == "__main__":
- unittest.main()
+ unittest_main()
import unittest
import urllib.parse
import xml.etree
+import xml.etree.ElementTree
import textwrap
from io import StringIO
from collections import namedtuple
loc = "<br><a href=\"" + loc + "\">Module Docs</a>"
return output.strip(), loc
+def get_pydoc_link(module):
+ "Returns a documentation web link of a module"
+ dirname = os.path.dirname
+ basedir = os.path.join(dirname(dirname(__file__)))
+ doc = pydoc.TextDoc()
+ loc = doc.getdocloc(module, basedir=basedir)
+ return loc
+
def get_pydoc_text(module):
"Returns pydoc generated output as text"
doc = pydoc.TextDoc()
doc = pydoc.render_doc(BinaryInteger)
self.assertIn('<BinaryInteger.zero: 0>', doc)
+ def test_mixed_case_module_names_are_lower_cased(self):
+ # issue16484
+ doc_link = get_pydoc_link(xml.etree.ElementTree)
+ self.assertIn('xml.etree.elementtree', doc_link)
+
def test_issue8225(self):
# Test issue8225 to ensure no doc link appears for xml.etree
result, doc_loc = get_pydoc_text(xml.etree)
finally:
sys.path[:] = saved_paths
- @unittest.skip('causes undesireable side-effects (#20128)')
+ @unittest.skip('causes undesirable side-effects (#20128)')
def test_modules(self):
# See Helper.listmodules().
num_header_lines = 2
self.assertGreaterEqual(num_lines, expected)
- @unittest.skip('causes undesireable side-effects (#20128)')
+ @unittest.skip('causes undesirable side-effects (#20128)')
def test_modules_search(self):
# See Helper.listmodules().
expected = 'pydoc - '
self.parser.specified_attributes = x
self.assertIs(self.parser.specified_attributes, bool(x))
- def test_specified_attributes(self):
- self.assertIs(self.parser.specified_attributes, False)
- for x in 0, 1, 2, 0:
- self.parser.specified_attributes = x
- self.assertIs(self.parser.specified_attributes, bool(x))
-
def test_invalid_attributes(self):
with self.assertRaises(AttributeError):
self.parser.returns_unicode = 1
self.assertTrue(2**k > n > 2**(k-1)) # note the stronger assertion
@unittest.mock.patch('random.Random.random')
- def test_randbelow_overriden_random(self, random_mock):
+ def test_randbelow_overridden_random(self, random_mock):
# Random._randbelow() can only use random() when the built-in one
# has been overridden but no new getrandbits() method was supplied.
random_mock.side_effect = random.SystemRandom().random
def __repr__(self):
return '<' + ', '.join(map(str, self.values)) + '>'
+class MyContainer3:
+ def __repr__(self):
+ 'Test document content'
+ pass
+ wrapped = __repr__
+ wrapper = recursive_repr()(wrapped)
+
class TestRecursiveRepr(unittest.TestCase):
def test_recursive_repr(self):
m = MyContainer(list('abcde'))
m.append(m)
self.assertEqual(repr(m), '<a, b, c, d, e, +++, x, +++>')
+ def test_assigned_attributes(self):
+ from functools import WRAPPER_ASSIGNMENTS as assigned
+ wrapped = MyContainer3.wrapped
+ wrapper = MyContainer3.wrapper
+ for name in assigned:
+ self.assertIs(getattr(wrapper, name), getattr(wrapped, name))
+
if __name__ == "__main__":
unittest.main()
import unittest
+import unittest.mock
import builtins
import rlcompleter
self.assertEqual(completer.complete('f.b', 0), 'f.bar')
self.assertEqual(f.calls, 1)
+ @unittest.mock.patch('rlcompleter._readline_available', False)
def test_complete(self):
completer = rlcompleter.Completer()
self.assertEqual(completer.complete('', 0), '\t')
self.assertEqual(completer.complete('as', 2), 'assert')
self.assertEqual(completer.complete('an', 0), 'and')
+ def test_duplicate_globals(self):
+ namespace = {
+ 'False': None, # Keyword vs builtin vs namespace
+ 'assert': None, # Keyword vs namespace
+ 'try': lambda: None, # Keyword vs callable
+ 'memoryview': None, # Callable builtin vs non-callable
+ 'Ellipsis': lambda: None, # Non-callable builtin vs callable
+ }
+ completer = rlcompleter.Completer(namespace)
+ self.assertEqual(completer.complete('False', 0), 'False')
+ self.assertIsNone(completer.complete('False', 1)) # No duplicates
+ self.assertEqual(completer.complete('assert', 0), 'assert')
+ self.assertIsNone(completer.complete('assert', 1))
+ self.assertEqual(completer.complete('try', 0), 'try')
+ self.assertIsNone(completer.complete('try', 1))
+ # No opening bracket "(" because we overrode the built-in class
+ self.assertEqual(completer.complete('memoryview', 0), 'memoryview')
+ self.assertIsNone(completer.complete('memoryview', 1))
+ self.assertEqual(completer.complete('Ellipsis', 0), 'Ellipsis(')
+ self.assertIsNone(completer.complete('Ellipsis', 1))
+
if __name__ == '__main__':
unittest.main()
self.expect_import_error("sys.imp.eric")
self.expect_import_error("os.path.half")
self.expect_import_error("a.bee")
+ # Relative names not allowed
self.expect_import_error(".howard")
self.expect_import_error("..eaten")
+ self.expect_import_error(".test_runpy")
+ self.expect_import_error(".unittest")
# Package without __main__.py
self.expect_import_error("multiprocessing")
if verbose > 1: print("Testing package depth:", depth)
self._check_package(depth)
+ def test_run_package_init_exceptions(self):
+ # These were previously wrapped in an ImportError; see Issue 14285
+ result = self._make_pkg("", 1, "__main__")
+ pkg_dir, _, mod_name, _ = result
+ mod_name = mod_name.replace(".__main__", "")
+ self.addCleanup(self._del_pkg, pkg_dir, 1, mod_name)
+ init = os.path.join(pkg_dir, "__runpy_pkg__", "__init__.py")
+
+ exceptions = (ImportError, AttributeError, TypeError, ValueError)
+ for exception in exceptions:
+ name = exception.__name__
+ with self.subTest(name):
+ source = "raise {0}('{0} in __init__.py.')".format(name)
+ with open(init, "wt", encoding="ascii") as mod_file:
+ mod_file.write(source)
+ try:
+ run_module(mod_name)
+ except exception as err:
+ self.assertNotIn("finding spec", format(err))
+ else:
+ self.fail("Nothing raised; expected {}".format(name))
+ try:
+ run_module(mod_name + ".submodule")
+ except exception as err:
+ self.assertNotIn("finding spec", format(err))
+ else:
+ self.fail("Nothing raised; expected {}".format(name))
+
def test_run_package_in_namespace_package(self):
for depth in range(1, 4):
if verbose > 1: print("Testing package depth:", depth)
gc.collect()
self.assertTrue(ref() is None, "Cycle was not collected")
+ def test_free_after_iterating(self):
+ support.check_free_after_iterating(self, iter, self.thetype)
+
class TestSet(TestJointOps, unittest.TestCase):
thetype = set
basetype = set
# http://en.wikipedia.org/wiki/Cuboctahedron
# 8 triangular faces and 6 square faces
- # 12 indentical vertices each connecting a triangle and square
+ # 12 identical vertices each connecting a triangle and square
g = cube(3)
cuboctahedron = linegraph(g) # V( --> {V1, V2, V3, V4}
names2 = zf.namelist()
self.assertEqual(sorted(names), sorted(names2))
+ @requires_zlib
+ @unittest.skipUnless(ZIP_SUPPORT, 'Need zip support to run')
+ @unittest.skipUnless(shutil.which('unzip'),
+ 'Need the unzip command to run')
+ def test_unzip_zipfile(self):
+ root_dir, base_dir = self._create_files()
+ base_name = os.path.join(self.mkdtemp(), 'archive')
+ archive = make_archive(base_name, 'zip', root_dir, base_dir)
+
+ # check if ZIP file was created
+ self.assertEqual(archive, base_name + '.zip')
+ self.assertTrue(os.path.isfile(archive))
+
+ # now check the ZIP file using `unzip -t`
+ zip_cmd = ['unzip', '-t', archive]
+ with support.change_cwd(root_dir):
+ try:
+ subprocess.check_output(zip_cmd, stderr=subprocess.STDOUT)
+ except subprocess.CalledProcessError as exc:
+ details = exc.output.decode(errors="replace")
+ msg = "{}\n\n**Unzip Output**\n{}"
+ self.fail(msg.format(exc, details))
+
def test_make_archive(self):
tmpdir = self.mkdtemp()
base_name = os.path.join(tmpdir, 'archive')
with support.EnvironmentVarGuard() as env:
env['COLUMNS'] = '777'
+ del env['LINES']
size = shutil.get_terminal_size()
self.assertEqual(size.columns, 777)
with support.EnvironmentVarGuard() as env:
+ del env['COLUMNS']
env['LINES'] = '888'
size = shutil.get_terminal_size()
self.assertEqual(size.lines, 888)
+ def test_bad_environ(self):
+ with support.EnvironmentVarGuard() as env:
+ env['COLUMNS'] = 'xxx'
+ env['LINES'] = 'yyy'
+ size = shutil.get_terminal_size()
+ self.assertGreaterEqual(size.columns, 0)
+ self.assertGreaterEqual(size.lines, 0)
+
@unittest.skipUnless(os.isatty(sys.__stdout__.fileno()), "not on tty")
+ @unittest.skipUnless(hasattr(os, 'get_terminal_size'),
+ 'need os.get_terminal_size()')
def test_stty_match(self):
"""Check if stty returns the same results ignoring env
self.assertEqual(expected, actual)
+ def test_fallback(self):
+ with support.EnvironmentVarGuard() as env:
+ del env['LINES']
+ del env['COLUMNS']
+
+ # sys.__stdout__ has no fileno()
+ with support.swap_attr(sys, '__stdout__', None):
+ size = shutil.get_terminal_size(fallback=(10, 20))
+ self.assertEqual(size.columns, 10)
+ self.assertEqual(size.lines, 20)
+
+ # sys.__stdout__ is not a terminal on Unix
+ # or fileno() not in (0, 1, 2) on Windows
+ with open(os.devnull, 'w') as f, \
+ support.swap_attr(sys, '__stdout__', f):
+ size = shutil.get_terminal_size(fallback=(30, 40))
+ self.assertEqual(size.columns, 30)
+ self.assertEqual(size.lines, 40)
+
class PublicAPITests(unittest.TestCase):
"""Ensures that the correct values are exposed in the public API."""
if site.ENABLE_USER_SITE and not os.path.isdir(site.USER_SITE):
# need to add user site directory for tests
- os.makedirs(site.USER_SITE)
- site.addsitedir(site.USER_SITE)
+ try:
+ os.makedirs(site.USER_SITE)
+ site.addsitedir(site.USER_SITE)
+ except PermissionError as exc:
+ raise unittest.SkipTest('unable to create user site directory (%r): %s'
+ % (site.USER_SITE, exc))
+
class HelperFunctionsTests(unittest.TestCase):
"""Tests for helper functions.
# tests for slice objects; in particular the indices method.
-import unittest
-from pickle import loads, dumps
-
import itertools
import operator
import sys
+import unittest
+import weakref
+
+from pickle import loads, dumps
+from test import support
def evaluate_slice_index(arg):
self.assertEqual(s.indices(15), t.indices(15))
self.assertNotEqual(id(s), id(t))
+ def test_cycle(self):
+ class myobj(): pass
+ o = myobj()
+ o.s = slice(o)
+ w = weakref.ref(o)
+ o = None
+ support.gc_collect()
+ self.assertIsNone(w())
+
if __name__ == "__main__":
unittest.main()
clientTearDown ()
Any new test functions within the class must then define
- tests in pairs, where the test name is preceeded with a
+ tests in pairs, where the test name is preceded with a
'_' to indicate the client portion of the test. Ex:
def testFoo(self):
# socket.gethostbyaddr('испытание.python.org')
def check_sendall_interrupted(self, with_timeout):
- # socketpair() is not stricly required, but it makes things easier.
+ # socketpair() is not strictly required, but it makes things easier.
if not hasattr(signal, 'alarm') or not hasattr(socket, 'socketpair'):
self.skipTest("signal.alarm and socket.socketpair required for this test")
# Our signal handlers clobber the C errno by calling a math function
self.assertRaises(ValueError, fp.writable)
self.assertRaises(ValueError, fp.seekable)
+ def test_makefile_mode(self):
+ for mode in 'r', 'rb', 'rw', 'w', 'wb':
+ with self.subTest(mode=mode):
+ with socket.socket() as sock:
+ with sock.makefile(mode) as fp:
+ self.assertEqual(fp.mode, mode)
+
+ def test_makefile_invalid_mode(self):
+ for mode in 'rt', 'x', '+', 'a':
+ with self.subTest(mode=mode):
+ with socket.socket() as sock:
+ with self.assertRaisesRegex(ValueError, 'invalid mode'):
+ sock.makefile(mode)
+
def test_pickle(self):
sock = socket.socket()
with sock:
self.addCleanup(self.conn.close)
def clientSetUp(self):
- # The is a hittable race between serverExplicitReady() and the
+ # There is a hittable race between serverExplicitReady() and the
# accept() call; sleep a little while to avoid it, otherwise
# we could get an exception
time.sleep(0.1)
def compareSockets(self, org, other):
# socket sharing is expected to work only for blocking socket
- # since the internal python timout value isn't transfered.
+ # since the internal python timeout value isn't transferred.
self.assertEqual(org.gettimeout(), None)
self.assertEqual(org.gettimeout(), other.gettimeout())
def dgram_examine(self, proto, addr):
s = socket.socket(proto, socket.SOCK_DGRAM)
+ if HAVE_UNIX_SOCKETS and proto == socket.AF_UNIX:
+ s.bind(self.pickaddr(proto))
s.sendto(TEST_STR, addr)
buf = data = receive(s, 100)
while data and b'\n' not in buf:
socketserver.DatagramRequestHandler,
self.dgram_examine)
- # Alas, on Linux (at least) recvfrom() doesn't return a meaningful
- # client address so this cannot work:
-
- # @requires_unix_sockets
- # def test_UnixDatagramServer(self):
- # self.run_server(socketserver.UnixDatagramServer,
- # socketserver.DatagramRequestHandler,
- # self.dgram_examine)
- #
- # @requires_unix_sockets
- # def test_ThreadingUnixDatagramServer(self):
- # self.run_server(socketserver.ThreadingUnixDatagramServer,
- # socketserver.DatagramRequestHandler,
- # self.dgram_examine)
- #
- # @requires_unix_sockets
- # @requires_forking
- # def test_ForkingUnixDatagramServer(self):
- # self.run_server(socketserver.ForkingUnixDatagramServer,
- # socketserver.DatagramRequestHandler,
- # self.dgram_examine)
+ @requires_unix_sockets
+ def test_UnixDatagramServer(self):
+ self.run_server(socketserver.UnixDatagramServer,
+ socketserver.DatagramRequestHandler,
+ self.dgram_examine)
+
+ @requires_unix_sockets
+ def test_ThreadingUnixDatagramServer(self):
+ self.run_server(socketserver.ThreadingUnixDatagramServer,
+ socketserver.DatagramRequestHandler,
+ self.dgram_examine)
+
+ @requires_unix_sockets
+ @requires_forking
+ def test_ForkingUnixDatagramServer(self):
+ self.run_server(ForkingUnixDatagramServer,
+ socketserver.DatagramRequestHandler,
+ self.dgram_examine)
@reap_threads
def test_shutdown(self):
expected.append(name)
self.assertCountEqual(socketserver.__all__, expected)
+ def test_shutdown_request_called_if_verify_request_false(self):
+ # Issue #26309: BaseServer should call shutdown_request even if
+ # verify_request is False
+
+ class MyServer(socketserver.TCPServer):
+ def verify_request(self, request, client_address):
+ return False
+
+ shutdown_called = 0
+ def shutdown_request(self, request):
+ self.shutdown_called += 1
+ socketserver.TCPServer.shutdown_request(self, request)
+
+ server = MyServer((HOST, 0), socketserver.StreamRequestHandler)
+ s = socket.socket(server.address_family, socket.SOCK_STREAM)
+ s.connect(server.server_address)
+ s.close()
+ server.handle_request()
+ self.assertEqual(server.shutdown_called, 1)
+ server.server_close()
+
if __name__ == "__main__":
unittest.main()
# -*- coding: koi8-r -*-
import unittest
-from test.support import TESTFN, unlink, unload, rmtree
+from test.support import TESTFN, unlink, unload, rmtree, script_helper, captured_stdout
import importlib
import os
import sys
import subprocess
+import tempfile
-class SourceEncodingTest(unittest.TestCase):
+class MiscSourceEncodingTest(unittest.TestCase):
def test_pep263(self):
self.assertEqual(
msg=c.exception.args[0])
+class AbstractSourceEncodingTest:
+
+ def test_default_coding(self):
+ src = (b'print(ascii("\xc3\xa4"))\n')
+ self.check_script_output(src, br"'\xe4'")
+
+ def test_first_coding_line(self):
+ src = (b'#coding:iso8859-15\n'
+ b'print(ascii("\xc3\xa4"))\n')
+ self.check_script_output(src, br"'\xc3\u20ac'")
+
+ def test_second_coding_line(self):
+ src = (b'#\n'
+ b'#coding:iso8859-15\n'
+ b'print(ascii("\xc3\xa4"))\n')
+ self.check_script_output(src, br"'\xc3\u20ac'")
+
+ def test_third_coding_line(self):
+ # Only first two lines are tested for a magic comment.
+ src = (b'#\n'
+ b'#\n'
+ b'#coding:iso8859-15\n'
+ b'print(ascii("\xc3\xa4"))\n')
+ self.check_script_output(src, br"'\xe4'")
+
+ def test_double_coding_line(self):
+ # If the first line matches the second line is ignored.
+ src = (b'#coding:iso8859-15\n'
+ b'#coding:latin1\n'
+ b'print(ascii("\xc3\xa4"))\n')
+ self.check_script_output(src, br"'\xc3\u20ac'")
+
+ def test_double_coding_same_line(self):
+ src = (b'#coding:iso8859-15 coding:latin1\n'
+ b'print(ascii("\xc3\xa4"))\n')
+ self.check_script_output(src, br"'\xc3\u20ac'")
+
+ def test_first_non_utf8_coding_line(self):
+ src = (b'#coding:iso-8859-15 \xa4\n'
+ b'print(ascii("\xc3\xa4"))\n')
+ self.check_script_output(src, br"'\xc3\u20ac'")
+
+ def test_second_non_utf8_coding_line(self):
+ src = (b'\n'
+ b'#coding:iso-8859-15 \xa4\n'
+ b'print(ascii("\xc3\xa4"))\n')
+ self.check_script_output(src, br"'\xc3\u20ac'")
+
+ def test_utf8_bom(self):
+ src = (b'\xef\xbb\xbfprint(ascii("\xc3\xa4"))\n')
+ self.check_script_output(src, br"'\xe4'")
+
+ def test_utf8_bom_and_utf8_coding_line(self):
+ src = (b'\xef\xbb\xbf#coding:utf-8\n'
+ b'print(ascii("\xc3\xa4"))\n')
+ self.check_script_output(src, br"'\xe4'")
+
+
+class BytesSourceEncodingTest(AbstractSourceEncodingTest, unittest.TestCase):
+
+ def check_script_output(self, src, expected):
+ with captured_stdout() as stdout:
+ exec(src)
+ out = stdout.getvalue().encode('latin1')
+ self.assertEqual(out.rstrip(), expected)
+
+
+class FileSourceEncodingTest(AbstractSourceEncodingTest, unittest.TestCase):
+
+ def check_script_output(self, src, expected):
+ with tempfile.TemporaryDirectory() as tmpd:
+ fn = os.path.join(tmpd, 'test.py')
+ with open(fn, 'wb') as fp:
+ fp.write(src)
+ res = script_helper.assert_python_ok(fn)
+ self.assertEqual(res.out.rstrip(), expected)
+
+
if __name__ == "__main__":
unittest.main()
SIGNED_CERTFILE2 = data_file("keycert4.pem")
SIGNING_CA = data_file("pycacert.pem")
-SVN_PYTHON_ORG_ROOT_CERT = data_file("https_svn_python_org_root.pem")
+REMOTE_HOST = "self-signed.pythontest.net"
+REMOTE_ROOT_CERT = data_file("selfsigned_pythontestdotnet.pem")
EMPTYCERT = data_file("nullcert.pem")
BADCERT = data_file("badcert.pem")
-WRONGCERT = data_file("XXXnonexisting.pem")
+NONEXISTINGCERT = data_file("XXXnonexisting.pem")
BADKEY = data_file("badkey.pem")
NOKIACERT = data_file("nokia.pem")
NULLBYTECERT = data_file("nullbytecert.pem")
self.assertEqual(p['subjectAltName'], san)
def test_DER_to_PEM(self):
- with open(SVN_PYTHON_ORG_ROOT_CERT, 'r') as f:
+ with open(CAFILE_CACERT, 'r') as f:
pem = f.read()
d1 = ssl.PEM_cert_to_DER_cert(pem)
p2 = ssl.DER_cert_to_PEM_cert(d1)
s.connect, (HOST, 8080))
with self.assertRaises(OSError) as cm:
with socket.socket() as sock:
- ssl.wrap_socket(sock, certfile=WRONGCERT)
+ ssl.wrap_socket(sock, certfile=NONEXISTINGCERT)
self.assertEqual(cm.exception.errno, errno.ENOENT)
with self.assertRaises(OSError) as cm:
with socket.socket() as sock:
- ssl.wrap_socket(sock, certfile=CERTFILE, keyfile=WRONGCERT)
+ ssl.wrap_socket(sock,
+ certfile=CERTFILE, keyfile=NONEXISTINGCERT)
self.assertEqual(cm.exception.errno, errno.ENOENT)
with self.assertRaises(OSError) as cm:
with socket.socket() as sock:
- ssl.wrap_socket(sock, certfile=WRONGCERT, keyfile=WRONGCERT)
+ ssl.wrap_socket(sock,
+ certfile=NONEXISTINGCERT, keyfile=NONEXISTINGCERT)
self.assertEqual(cm.exception.errno, errno.ENOENT)
+ def bad_cert_test(self, certfile):
+ """Check that trying to use the given client certificate fails"""
+ certfile = os.path.join(os.path.dirname(__file__) or os.curdir,
+ certfile)
+ sock = socket.socket()
+ self.addCleanup(sock.close)
+ with self.assertRaises(ssl.SSLError):
+ ssl.wrap_socket(sock,
+ certfile=certfile,
+ ssl_version=ssl.PROTOCOL_TLSv1)
+
+ def test_empty_cert(self):
+ """Wrapping with an empty cert file"""
+ self.bad_cert_test("nullcert.pem")
+
+ def test_malformed_cert(self):
+ """Wrapping with a badly formatted certificate (syntax error)"""
+ self.bad_cert_test("badcert.pem")
+
+ def test_malformed_key(self):
+ """Wrapping with a badly formatted key (syntax error)"""
+ self.bad_cert_test("badkey.pem")
+
def test_match_hostname(self):
def ok(cert, hostname):
ssl.match_hostname(cert, hostname)
self.assertEqual(ssl.OP_ALL | ssl.OP_NO_TLSv1 | ssl.OP_NO_SSLv3,
ctx.options)
ctx.options = 0
- self.assertEqual(0, ctx.options)
+ # Ubuntu has OP_NO_SSLv3 forced on by default
+ self.assertEqual(0, ctx.options & ~ssl.OP_NO_SSLv3)
else:
with self.assertRaises(ValueError):
ctx.options = 0
ctx.load_cert_chain(CERTFILE, keyfile=CERTFILE)
self.assertRaises(TypeError, ctx.load_cert_chain, keyfile=CERTFILE)
with self.assertRaises(OSError) as cm:
- ctx.load_cert_chain(WRONGCERT)
+ ctx.load_cert_chain(NONEXISTINGCERT)
self.assertEqual(cm.exception.errno, errno.ENOENT)
with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
ctx.load_cert_chain(BADCERT)
# Mismatching key and cert
ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
with self.assertRaisesRegex(ssl.SSLError, "key values mismatch"):
- ctx.load_cert_chain(SVN_PYTHON_ORG_ROOT_CERT, ONLYKEY)
+ ctx.load_cert_chain(CAFILE_CACERT, ONLYKEY)
# Password protected key and cert
ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD)
ctx.load_cert_chain(CERTFILE_PROTECTED, password=KEY_PASSWORD.encode())
self.assertRaises(TypeError, ctx.load_verify_locations)
self.assertRaises(TypeError, ctx.load_verify_locations, None, None, None)
with self.assertRaises(OSError) as cm:
- ctx.load_verify_locations(WRONGCERT)
+ ctx.load_verify_locations(NONEXISTINGCERT)
self.assertEqual(cm.exception.errno, errno.ENOENT)
with self.assertRaisesRegex(ssl.SSLError, "PEM lib"):
ctx.load_verify_locations(BADCERT)
self.assertRaises(TypeError, ctx.load_dh_params)
self.assertRaises(TypeError, ctx.load_dh_params, None)
with self.assertRaises(FileNotFoundError) as cm:
- ctx.load_dh_params(WRONGCERT)
+ ctx.load_dh_params(NONEXISTINGCERT)
self.assertEqual(cm.exception.errno, errno.ENOENT)
with self.assertRaises(ssl.SSLError) as cm:
ctx.load_dh_params(CERTFILE)
ctx.load_verify_locations(CERTFILE)
self.assertEqual(ctx.cert_store_stats(),
{'x509_ca': 0, 'crl': 0, 'x509': 1})
- ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
+ ctx.load_verify_locations(CAFILE_CACERT)
self.assertEqual(ctx.cert_store_stats(),
{'x509_ca': 1, 'crl': 0, 'x509': 2})
# CERTFILE is not flagged as X509v3 Basic Constraints: CA:TRUE
ctx.load_verify_locations(CERTFILE)
self.assertEqual(ctx.get_ca_certs(), [])
- # but SVN_PYTHON_ORG_ROOT_CERT is a CA cert
- ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
+ # but CAFILE_CACERT is a CA cert
+ ctx.load_verify_locations(CAFILE_CACERT)
self.assertEqual(ctx.get_ca_certs(),
[{'issuer': ((('organizationName', 'Root CA'),),
(('organizationalUnitName', 'http://www.cacert.org'),),
(('emailAddress', 'support@cacert.org'),)),
'version': 3}])
- with open(SVN_PYTHON_ORG_ROOT_CERT) as f:
+ with open(CAFILE_CACERT) as f:
pem = f.read()
der = ssl.PEM_cert_to_DER_cert(pem)
self.assertEqual(ctx.get_ca_certs(True), [der])
class NetworkedTests(unittest.TestCase):
def test_connect(self):
- with support.transient_internet("svn.python.org"):
+ with support.transient_internet(REMOTE_HOST):
s = ssl.wrap_socket(socket.socket(socket.AF_INET),
cert_reqs=ssl.CERT_NONE)
try:
- s.connect(("svn.python.org", 443))
+ s.connect((REMOTE_HOST, 443))
self.assertEqual({}, s.getpeercert())
finally:
s.close()
s = ssl.wrap_socket(socket.socket(socket.AF_INET),
cert_reqs=ssl.CERT_REQUIRED)
self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
- s.connect, ("svn.python.org", 443))
+ s.connect, (REMOTE_HOST, 443))
s.close()
# this should succeed because we specify the root cert
s = ssl.wrap_socket(socket.socket(socket.AF_INET),
cert_reqs=ssl.CERT_REQUIRED,
- ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
+ ca_certs=REMOTE_ROOT_CERT)
try:
- s.connect(("svn.python.org", 443))
+ s.connect((REMOTE_HOST, 443))
self.assertTrue(s.getpeercert())
finally:
s.close()
def test_connect_ex(self):
# Issue #11326: check connect_ex() implementation
- with support.transient_internet("svn.python.org"):
+ with support.transient_internet(REMOTE_HOST):
s = ssl.wrap_socket(socket.socket(socket.AF_INET),
cert_reqs=ssl.CERT_REQUIRED,
- ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
+ ca_certs=REMOTE_ROOT_CERT)
try:
- self.assertEqual(0, s.connect_ex(("svn.python.org", 443)))
+ self.assertEqual(0, s.connect_ex((REMOTE_HOST, 443)))
self.assertTrue(s.getpeercert())
finally:
s.close()
def test_non_blocking_connect_ex(self):
# Issue #11326: non-blocking connect_ex() should allow handshake
# to proceed after the socket gets ready.
- with support.transient_internet("svn.python.org"):
+ with support.transient_internet(REMOTE_HOST):
s = ssl.wrap_socket(socket.socket(socket.AF_INET),
cert_reqs=ssl.CERT_REQUIRED,
- ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
+ ca_certs=REMOTE_ROOT_CERT,
do_handshake_on_connect=False)
try:
s.setblocking(False)
- rc = s.connect_ex(('svn.python.org', 443))
+ rc = s.connect_ex((REMOTE_HOST, 443))
# EWOULDBLOCK under Windows, EINPROGRESS elsewhere
self.assertIn(rc, (0, errno.EINPROGRESS, errno.EWOULDBLOCK))
# Wait for connect to finish
def test_timeout_connect_ex(self):
# Issue #12065: on a timeout, connect_ex() should return the original
# errno (mimicking the behaviour of non-SSL sockets).
- with support.transient_internet("svn.python.org"):
+ with support.transient_internet(REMOTE_HOST):
s = ssl.wrap_socket(socket.socket(socket.AF_INET),
cert_reqs=ssl.CERT_REQUIRED,
- ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
+ ca_certs=REMOTE_ROOT_CERT,
do_handshake_on_connect=False)
try:
s.settimeout(0.0000001)
- rc = s.connect_ex(('svn.python.org', 443))
+ rc = s.connect_ex((REMOTE_HOST, 443))
if rc == 0:
- self.skipTest("svn.python.org responded too quickly")
+ self.skipTest("REMOTE_HOST responded too quickly")
self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
finally:
s.close()
def test_connect_ex_error(self):
- with support.transient_internet("svn.python.org"):
+ with support.transient_internet(REMOTE_HOST):
s = ssl.wrap_socket(socket.socket(socket.AF_INET),
cert_reqs=ssl.CERT_REQUIRED,
- ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
+ ca_certs=REMOTE_ROOT_CERT)
try:
- rc = s.connect_ex(("svn.python.org", 444))
+ rc = s.connect_ex((REMOTE_HOST, 444))
# Issue #19919: Windows machines or VMs hosted on Windows
# machines sometimes return EWOULDBLOCK.
- self.assertIn(rc, (errno.ECONNREFUSED, errno.EWOULDBLOCK))
+ errors = (
+ errno.ECONNREFUSED, errno.EHOSTUNREACH, errno.ETIMEDOUT,
+ errno.EWOULDBLOCK,
+ )
+ self.assertIn(rc, errors)
finally:
s.close()
def test_connect_with_context(self):
- with support.transient_internet("svn.python.org"):
+ with support.transient_internet(REMOTE_HOST):
# Same as test_connect, but with a separately created context
ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
s = ctx.wrap_socket(socket.socket(socket.AF_INET))
- s.connect(("svn.python.org", 443))
+ s.connect((REMOTE_HOST, 443))
try:
self.assertEqual({}, s.getpeercert())
finally:
s.close()
# Same with a server hostname
s = ctx.wrap_socket(socket.socket(socket.AF_INET),
- server_hostname="svn.python.org")
- s.connect(("svn.python.org", 443))
+ server_hostname=REMOTE_HOST)
+ s.connect((REMOTE_HOST, 443))
s.close()
# This should fail because we have no verification certs
ctx.verify_mode = ssl.CERT_REQUIRED
s = ctx.wrap_socket(socket.socket(socket.AF_INET))
self.assertRaisesRegex(ssl.SSLError, "certificate verify failed",
- s.connect, ("svn.python.org", 443))
+ s.connect, (REMOTE_HOST, 443))
s.close()
# This should succeed because we specify the root cert
- ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
+ ctx.load_verify_locations(REMOTE_ROOT_CERT)
s = ctx.wrap_socket(socket.socket(socket.AF_INET))
- s.connect(("svn.python.org", 443))
+ s.connect((REMOTE_HOST, 443))
try:
cert = s.getpeercert()
self.assertTrue(cert)
# OpenSSL 0.9.8n and 1.0.0, as a result the capath directory must
# contain both versions of each certificate (same content, different
# filename) for this test to be portable across OpenSSL releases.
- with support.transient_internet("svn.python.org"):
+ with support.transient_internet(REMOTE_HOST):
ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
ctx.verify_mode = ssl.CERT_REQUIRED
ctx.load_verify_locations(capath=CAPATH)
s = ctx.wrap_socket(socket.socket(socket.AF_INET))
- s.connect(("svn.python.org", 443))
+ s.connect((REMOTE_HOST, 443))
try:
cert = s.getpeercert()
self.assertTrue(cert)
ctx.verify_mode = ssl.CERT_REQUIRED
ctx.load_verify_locations(capath=BYTES_CAPATH)
s = ctx.wrap_socket(socket.socket(socket.AF_INET))
- s.connect(("svn.python.org", 443))
+ s.connect((REMOTE_HOST, 443))
try:
cert = s.getpeercert()
self.assertTrue(cert)
s.close()
def test_connect_cadata(self):
- with open(CAFILE_CACERT) as f:
+ with open(REMOTE_ROOT_CERT) as f:
pem = f.read()
der = ssl.PEM_cert_to_DER_cert(pem)
- with support.transient_internet("svn.python.org"):
+ with support.transient_internet(REMOTE_HOST):
ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
ctx.verify_mode = ssl.CERT_REQUIRED
ctx.load_verify_locations(cadata=pem)
with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
- s.connect(("svn.python.org", 443))
+ s.connect((REMOTE_HOST, 443))
cert = s.getpeercert()
self.assertTrue(cert)
ctx.verify_mode = ssl.CERT_REQUIRED
ctx.load_verify_locations(cadata=der)
with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s:
- s.connect(("svn.python.org", 443))
+ s.connect((REMOTE_HOST, 443))
cert = s.getpeercert()
self.assertTrue(cert)
# Issue #5238: creating a file-like object with makefile() shouldn't
# delay closing the underlying "real socket" (here tested with its
# file descriptor, hence skipping the test under Windows).
- with support.transient_internet("svn.python.org"):
+ with support.transient_internet(REMOTE_HOST):
ss = ssl.wrap_socket(socket.socket(socket.AF_INET))
- ss.connect(("svn.python.org", 443))
+ ss.connect((REMOTE_HOST, 443))
fd = ss.fileno()
f = ss.makefile()
f.close()
self.assertEqual(e.exception.errno, errno.EBADF)
def test_non_blocking_handshake(self):
- with support.transient_internet("svn.python.org"):
+ with support.transient_internet(REMOTE_HOST):
s = socket.socket(socket.AF_INET)
- s.connect(("svn.python.org", 443))
+ s.connect((REMOTE_HOST, 443))
s.setblocking(False)
s = ssl.wrap_socket(s,
cert_reqs=ssl.CERT_NONE,
if support.verbose:
sys.stdout.write("\nVerified certificate for %s:%s is\n%s\n" % (host, port ,pem))
- _test_get_server_certificate('svn.python.org', 443, SVN_PYTHON_ORG_ROOT_CERT)
+ _test_get_server_certificate(REMOTE_HOST, 443, REMOTE_ROOT_CERT)
if support.IPV6_ENABLED:
_test_get_server_certificate('ipv6.google.com', 443)
def test_ciphers(self):
- remote = ("svn.python.org", 443)
+ remote = (REMOTE_HOST, 443)
with support.transient_internet(remote[0]):
with ssl.wrap_socket(socket.socket(socket.AF_INET),
cert_reqs=ssl.CERT_NONE, ciphers="ALL") as s:
def test_get_ca_certs_capath(self):
# capath certs are loaded on request
- with support.transient_internet("svn.python.org"):
+ with support.transient_internet(REMOTE_HOST):
ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
ctx.verify_mode = ssl.CERT_REQUIRED
ctx.load_verify_locations(capath=CAPATH)
self.assertEqual(ctx.get_ca_certs(), [])
s = ctx.wrap_socket(socket.socket(socket.AF_INET))
- s.connect(("svn.python.org", 443))
+ s.connect((REMOTE_HOST, 443))
try:
cert = s.getpeercert()
self.assertTrue(cert)
@needs_sni
def test_context_setget(self):
# Check that the context of a connected socket can be replaced.
- with support.transient_internet("svn.python.org"):
+ with support.transient_internet(REMOTE_HOST):
ctx1 = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
ctx2 = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
s = socket.socket(socket.AF_INET)
with ctx1.wrap_socket(s) as ss:
- ss.connect(("svn.python.org", 443))
+ ss.connect((REMOTE_HOST, 443))
self.assertIs(ss.context, ctx1)
self.assertIs(ss._sslobj.context, ctx1)
ss.context = ctx2
try:
ret = func(*args)
except ssl.SSLError as e:
- # Note that we get a spurious -1/SSL_ERROR_SYSCALL for
- # non-blocking IO. The SSL_shutdown manpage hints at this.
- # It *should* be safe to just ignore SYS_ERROR_SYSCALL because
- # with a Memory BIO there's no syscalls (for IO at least).
if e.errno not in (ssl.SSL_ERROR_WANT_READ,
- ssl.SSL_ERROR_WANT_WRITE,
- ssl.SSL_ERROR_SYSCALL):
+ ssl.SSL_ERROR_WANT_WRITE):
raise
errno = e.errno
# Get any data from the outgoing BIO irrespective of any error, and
return ret
def test_handshake(self):
- with support.transient_internet("svn.python.org"):
+ with support.transient_internet(REMOTE_HOST):
sock = socket.socket(socket.AF_INET)
- sock.connect(("svn.python.org", 443))
+ sock.connect((REMOTE_HOST, 443))
incoming = ssl.MemoryBIO()
outgoing = ssl.MemoryBIO()
ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
ctx.verify_mode = ssl.CERT_REQUIRED
- ctx.load_verify_locations(SVN_PYTHON_ORG_ROOT_CERT)
+ ctx.load_verify_locations(REMOTE_ROOT_CERT)
ctx.check_hostname = True
- sslobj = ctx.wrap_bio(incoming, outgoing, False, 'svn.python.org')
+ sslobj = ctx.wrap_bio(incoming, outgoing, False, REMOTE_HOST)
self.assertIs(sslobj._sslobj.owner, sslobj)
self.assertIsNone(sslobj.cipher())
self.assertIsNone(sslobj.shared_ciphers())
self.assertTrue(sslobj.getpeercert())
if 'tls-unique' in ssl.CHANNEL_BINDING_TYPES:
self.assertTrue(sslobj.get_channel_binding('tls-unique'))
- self.ssl_io_loop(sock, incoming, outgoing, sslobj.unwrap)
+ try:
+ self.ssl_io_loop(sock, incoming, outgoing, sslobj.unwrap)
+ except ssl.SSLSyscallError:
+ # self-signed.pythontest.net probably shuts down the TCP
+ # connection without sending a secure shutdown message, and
+ # this is reported as SSL_ERROR_SYSCALL
+ pass
self.assertRaises(ssl.SSLError, sslobj.write, b'foo')
sock.close()
def test_read_write_data(self):
- with support.transient_internet("svn.python.org"):
+ with support.transient_internet(REMOTE_HOST):
sock = socket.socket(socket.AF_INET)
- sock.connect(("svn.python.org", 443))
+ sock.connect((REMOTE_HOST, 443))
incoming = ssl.MemoryBIO()
outgoing = ssl.MemoryBIO()
ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
self.active = False
self.server.close()
- def bad_cert_test(certfile):
- """
- Launch a server with CERT_REQUIRED, and check that trying to
- connect to it with the given client certificate fails.
- """
- server = ThreadedEchoServer(CERTFILE,
- certreqs=ssl.CERT_REQUIRED,
- cacerts=CERTFILE, chatty=False,
- connectionchatty=False)
- with server:
- try:
- with socket.socket() as sock:
- s = ssl.wrap_socket(sock,
- certfile=certfile,
- ssl_version=ssl.PROTOCOL_TLSv1)
- s.connect((HOST, server.port))
- except ssl.SSLError as x:
- if support.verbose:
- sys.stdout.write("\nSSLError is %s\n" % x.args[1])
- except OSError as x:
- if support.verbose:
- sys.stdout.write("\nOSError is %s\n" % x.args[1])
- except OSError as x:
- if x.errno != errno.ENOENT:
- raise
- if support.verbose:
- sys.stdout.write("\OSError is %s\n" % str(x))
- else:
- raise AssertionError("Use of invalid cert should have failed!")
-
def server_params_test(client_context, server_context, indata=b"FOO\n",
chatty=True, connectionchatty=False, sni_name=None):
"""
"check_hostname requires server_hostname"):
context.wrap_socket(s)
- def test_empty_cert(self):
- """Connecting with an empty cert file"""
- bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
- "nullcert.pem"))
- def test_malformed_cert(self):
- """Connecting with a badly formatted certificate (syntax error)"""
- bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
- "badcert.pem"))
- def test_nonexisting_cert(self):
- """Connecting with a non-existing cert file"""
- bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
- "wrongcert.pem"))
- def test_malformed_key(self):
- """Connecting with a badly formatted key (syntax error)"""
- bad_cert_test(os.path.join(os.path.dirname(__file__) or os.curdir,
- "badkey.pem"))
+ def test_wrong_cert(self):
+ """Connecting when the server rejects the client's certificate
+
+ Launch a server with CERT_REQUIRED, and check that trying to
+ connect to it with a wrong client certificate fails.
+ """
+ certfile = os.path.join(os.path.dirname(__file__) or os.curdir,
+ "wrongcert.pem")
+ server = ThreadedEchoServer(CERTFILE,
+ certreqs=ssl.CERT_REQUIRED,
+ cacerts=CERTFILE, chatty=False,
+ connectionchatty=False)
+ with server, \
+ socket.socket() as sock, \
+ ssl.wrap_socket(sock,
+ certfile=certfile,
+ ssl_version=ssl.PROTOCOL_TLSv1) as s:
+ try:
+ # Expect either an SSL error about the server rejecting
+ # the connection, or a low-level connection reset (which
+ # sometimes happens on Windows)
+ s.connect((HOST, server.port))
+ except ssl.SSLError as e:
+ if support.verbose:
+ sys.stdout.write("\nSSLError is %r\n" % e)
+ except OSError as e:
+ if e.errno != errno.ECONNRESET:
+ raise
+ if support.verbose:
+ sys.stdout.write("\nsocket.error is %r\n" % e)
+ else:
+ self.fail("Use of invalid cert should have failed!")
def test_rude_shutdown(self):
"""A brutal shutdown of an SSL server should raise an OSError
# consume data
s.read()
+ data = b"data"
+
+ # read(-1, buffer) is supported, even though read(-1) is not
+ s.send(data)
+ buffer = bytearray(len(data))
+ self.assertEqual(s.read(-1, buffer), len(data))
+ self.assertEqual(buffer, data)
+
+ # recv/read(0) should return no data
+ s.send(data)
+ self.assertEqual(s.recv(0), b"")
+ self.assertEqual(s.read(0), b"")
+ self.assertEqual(s.read(), data)
+
# Make sure sendmsg et al are disallowed to avoid
# inadvertent disclosure of data and/or corruption
# of the encrypted data stream
s.recvmsg_into, bytearray(100))
s.write(b"over\n")
+
+ self.assertRaises(ValueError, s.recv, -1)
+ self.assertRaises(ValueError, s.read, -1)
+
s.close()
def test_nonblocking_send(self):
pass
for filename in [
- CERTFILE, SVN_PYTHON_ORG_ROOT_CERT, BYTES_CERTFILE,
+ CERTFILE, REMOTE_ROOT_CERT, BYTES_CERTFILE,
ONLYCERT, ONLYKEY, BYTES_ONLYCERT, BYTES_ONLYKEY,
SIGNED_CERTFILE, SIGNED_CERTFILE2, SIGNING_CA,
BADCERT, BADKEY, EMPTYCERT]:
# === Helper functions and class ===
+def _nan_equal(a, b):
+ """Return True if a and b are both the same kind of NAN.
+
+ >>> _nan_equal(Decimal('NAN'), Decimal('NAN'))
+ True
+ >>> _nan_equal(Decimal('sNAN'), Decimal('sNAN'))
+ True
+ >>> _nan_equal(Decimal('NAN'), Decimal('sNAN'))
+ False
+ >>> _nan_equal(Decimal(42), Decimal('NAN'))
+ False
+
+ >>> _nan_equal(float('NAN'), float('NAN'))
+ True
+ >>> _nan_equal(float('NAN'), 0.5)
+ False
+
+ >>> _nan_equal(float('NAN'), Decimal('NAN'))
+ False
+
+ NAN payloads are not compared.
+ """
+ if type(a) is not type(b):
+ return False
+ if isinstance(a, float):
+ return math.isnan(a) and math.isnan(b)
+ aexp = a.as_tuple()[2]
+ bexp = b.as_tuple()[2]
+ return (aexp == bexp) and (aexp in ('n', 'N')) # Both NAN or both sNAN.
+
+
def _calc_errors(actual, expected):
"""Return the absolute and relative errors between two numbers.
self.assertEqual(_exact_ratio(D("12.345")), (12345, 1000))
self.assertEqual(_exact_ratio(D("-1.98")), (-198, 100))
+ def test_inf(self):
+ INF = float("INF")
+ class MyFloat(float):
+ pass
+ class MyDecimal(Decimal):
+ pass
+ for inf in (INF, -INF):
+ for type_ in (float, MyFloat, Decimal, MyDecimal):
+ x = type_(inf)
+ ratio = statistics._exact_ratio(x)
+ self.assertEqual(ratio, (x, None))
+ self.assertEqual(type(ratio[0]), type_)
+ self.assertTrue(math.isinf(ratio[0]))
+
+ def test_float_nan(self):
+ NAN = float("NAN")
+ class MyFloat(float):
+ pass
+ for nan in (NAN, MyFloat(NAN)):
+ ratio = statistics._exact_ratio(nan)
+ self.assertTrue(math.isnan(ratio[0]))
+ self.assertIs(ratio[1], None)
+ self.assertEqual(type(ratio[0]), type(nan))
+
+ def test_decimal_nan(self):
+ NAN = Decimal("NAN")
+ sNAN = Decimal("sNAN")
+ class MyDecimal(Decimal):
+ pass
+ for nan in (NAN, MyDecimal(NAN), sNAN, MyDecimal(sNAN)):
+ ratio = statistics._exact_ratio(nan)
+ self.assertTrue(_nan_equal(ratio[0], nan))
+ self.assertIs(ratio[1], None)
+ self.assertEqual(type(ratio[0]), type(nan))
+
class DecimalToRatioTest(unittest.TestCase):
# Test _decimal_to_ratio private function.
- def testSpecialsRaise(self):
- # Test that NANs and INFs raise ValueError.
- # Non-special values are covered by _exact_ratio above.
- for d in (Decimal('NAN'), Decimal('sNAN'), Decimal('INF')):
- self.assertRaises(ValueError, statistics._decimal_to_ratio, d)
+ def test_infinity(self):
+ # Test that INFs are handled correctly.
+ inf = Decimal('INF')
+ self.assertEqual(statistics._decimal_to_ratio(inf), (inf, None))
+ self.assertEqual(statistics._decimal_to_ratio(-inf), (-inf, None))
+
+ def test_nan(self):
+ # Test that NANs are handled correctly.
+ for nan in (Decimal('NAN'), Decimal('sNAN')):
+ num, den = statistics._decimal_to_ratio(nan)
+ # Because NANs always compare non-equal, we cannot use assertEqual.
+ # Nor can we use an identity test, as we don't guarantee anything
+ # about the object identity.
+ self.assertTrue(_nan_equal(num, nan))
+ self.assertIs(den, None)
def test_sign(self):
# Test sign is calculated correctly.
self.assertEqual(t, (147000, 1))
-class CheckTypeTest(unittest.TestCase):
- # Test _check_type private function.
+class IsFiniteTest(unittest.TestCase):
+ # Test _isfinite private function.
+
+ def test_finite(self):
+ # Test that finite numbers are recognised as finite.
+ for x in (5, Fraction(1, 3), 2.5, Decimal("5.5")):
+ self.assertTrue(statistics._isfinite(x))
- def test_allowed(self):
- # Test that a type which should be allowed is allowed.
- allowed = set([int, float])
- statistics._check_type(int, allowed)
- statistics._check_type(float, allowed)
+ def test_infinity(self):
+ # Test that INFs are not recognised as finite.
+ for x in (float("inf"), Decimal("inf")):
+ self.assertFalse(statistics._isfinite(x))
+
+ def test_nan(self):
+ # Test that NANs are not recognised as finite.
+ for x in (float("nan"), Decimal("NAN"), Decimal("sNAN")):
+ self.assertFalse(statistics._isfinite(x))
+
+
+class CoerceTest(unittest.TestCase):
+ # Test that private function _coerce correctly deals with types.
+
+ # The coercion rules are currently an implementation detail, although at
+ # some point that should change. The tests and comments here define the
+ # correct implementation.
+
+ # Pre-conditions of _coerce:
+ #
+ # - The first time _sum calls _coerce, the
+ # - coerce(T, S) will never be called with bool as the first argument;
+ # this is a pre-condition, guarded with an assertion.
+
+ #
+ # - coerce(T, T) will always return T; we assume T is a valid numeric
+ # type. Violate this assumption at your own risk.
+ #
+ # - Apart from as above, bool is treated as if it were actually int.
+ #
+ # - coerce(int, X) and coerce(X, int) return X.
+ # -
+ def test_bool(self):
+ # bool is somewhat special, due to the pre-condition that it is
+ # never given as the first argument to _coerce, and that it cannot
+ # be subclassed. So we test it specially.
+ for T in (int, float, Fraction, Decimal):
+ self.assertIs(statistics._coerce(T, bool), T)
+ class MyClass(T): pass
+ self.assertIs(statistics._coerce(MyClass, bool), MyClass)
+
+ def assertCoerceTo(self, A, B):
+ """Assert that type A coerces to B."""
+ self.assertIs(statistics._coerce(A, B), B)
+ self.assertIs(statistics._coerce(B, A), B)
+
+ def check_coerce_to(self, A, B):
+ """Checks that type A coerces to B, including subclasses."""
+ # Assert that type A is coerced to B.
+ self.assertCoerceTo(A, B)
+ # Subclasses of A are also coerced to B.
+ class SubclassOfA(A): pass
+ self.assertCoerceTo(SubclassOfA, B)
+ # A, and subclasses of A, are coerced to subclasses of B.
+ class SubclassOfB(B): pass
+ self.assertCoerceTo(A, SubclassOfB)
+ self.assertCoerceTo(SubclassOfA, SubclassOfB)
+
+ def assertCoerceRaises(self, A, B):
+ """Assert that coercing A to B, or vice versa, raises TypeError."""
+ self.assertRaises(TypeError, statistics._coerce, (A, B))
+ self.assertRaises(TypeError, statistics._coerce, (B, A))
+
+ def check_type_coercions(self, T):
+ """Check that type T coerces correctly with subclasses of itself."""
+ assert T is not bool
+ # Coercing a type with itself returns the same type.
+ self.assertIs(statistics._coerce(T, T), T)
+ # Coercing a type with a subclass of itself returns the subclass.
+ class U(T): pass
+ class V(T): pass
+ class W(U): pass
+ for typ in (U, V, W):
+ self.assertCoerceTo(T, typ)
+ self.assertCoerceTo(U, W)
+ # Coercing two subclasses that aren't parent/child is an error.
+ self.assertCoerceRaises(U, V)
+ self.assertCoerceRaises(V, W)
- def test_not_allowed(self):
- # Test that a type which should not be allowed raises.
- allowed = set([int, float])
- self.assertRaises(TypeError, statistics._check_type, Decimal, allowed)
+ def test_int(self):
+ # Check that int coerces correctly.
+ self.check_type_coercions(int)
+ for typ in (float, Fraction, Decimal):
+ self.check_coerce_to(int, typ)
- def test_add_to_allowed(self):
- # Test that a second type will be added to the allowed set.
- allowed = set([int])
- statistics._check_type(float, allowed)
- self.assertEqual(allowed, set([int, float]))
+ def test_fraction(self):
+ # Check that Fraction coerces correctly.
+ self.check_type_coercions(Fraction)
+ self.check_coerce_to(Fraction, float)
+
+ def test_decimal(self):
+ # Check that Decimal coerces correctly.
+ self.check_type_coercions(Decimal)
+
+ def test_float(self):
+ # Check that float coerces correctly.
+ self.check_type_coercions(float)
+
+ def test_non_numeric_types(self):
+ for bad_type in (str, list, type(None), tuple, dict):
+ for good_type in (int, float, Fraction, Decimal):
+ self.assertCoerceRaises(good_type, bad_type)
+
+ def test_incompatible_types(self):
+ # Test that incompatible types raise.
+ for T in (float, Fraction):
+ class MySubclass(T): pass
+ self.assertCoerceRaises(T, Decimal)
+ self.assertCoerceRaises(MySubclass, Decimal)
+
+
+class ConvertTest(unittest.TestCase):
+ # Test private _convert function.
+
+ def check_exact_equal(self, x, y):
+ """Check that x equals y, and has the same type as well."""
+ self.assertEqual(x, y)
+ self.assertIs(type(x), type(y))
+
+ def test_int(self):
+ # Test conversions to int.
+ x = statistics._convert(Fraction(71), int)
+ self.check_exact_equal(x, 71)
+ class MyInt(int): pass
+ x = statistics._convert(Fraction(17), MyInt)
+ self.check_exact_equal(x, MyInt(17))
+
+ def test_fraction(self):
+ # Test conversions to Fraction.
+ x = statistics._convert(Fraction(95, 99), Fraction)
+ self.check_exact_equal(x, Fraction(95, 99))
+ class MyFraction(Fraction):
+ def __truediv__(self, other):
+ return self.__class__(super().__truediv__(other))
+ x = statistics._convert(Fraction(71, 13), MyFraction)
+ self.check_exact_equal(x, MyFraction(71, 13))
+
+ def test_float(self):
+ # Test conversions to float.
+ x = statistics._convert(Fraction(-1, 2), float)
+ self.check_exact_equal(x, -0.5)
+ class MyFloat(float):
+ def __truediv__(self, other):
+ return self.__class__(super().__truediv__(other))
+ x = statistics._convert(Fraction(9, 8), MyFloat)
+ self.check_exact_equal(x, MyFloat(1.125))
+
+ def test_decimal(self):
+ # Test conversions to Decimal.
+ x = statistics._convert(Fraction(1, 40), Decimal)
+ self.check_exact_equal(x, Decimal("0.025"))
+ class MyDecimal(Decimal):
+ def __truediv__(self, other):
+ return self.__class__(super().__truediv__(other))
+ x = statistics._convert(Fraction(-15, 16), MyDecimal)
+ self.check_exact_equal(x, MyDecimal("-0.9375"))
+
+ def test_inf(self):
+ for INF in (float('inf'), Decimal('inf')):
+ for inf in (INF, -INF):
+ x = statistics._convert(inf, type(inf))
+ self.check_exact_equal(x, inf)
+
+ def test_nan(self):
+ for nan in (float('nan'), Decimal('NAN'), Decimal('sNAN')):
+ x = statistics._convert(nan, type(nan))
+ self.assertTrue(_nan_equal(x, nan))
# === Tests for public functions ===
self.assertIs(type(result), kind)
-class TestSum(NumericTestCase, UnivariateCommonMixin, UnivariateTypeMixin):
+class TestSumCommon(UnivariateCommonMixin, UnivariateTypeMixin):
+ # Common test cases for statistics._sum() function.
+
+ # This test suite looks only at the numeric value returned by _sum,
+ # after conversion to the appropriate type.
+ def setUp(self):
+ def simplified_sum(*args):
+ T, value, n = statistics._sum(*args)
+ return statistics._coerce(value, T)
+ self.func = simplified_sum
+
+
+class TestSum(NumericTestCase):
# Test cases for statistics._sum() function.
+ # These tests look at the entire three value tuple returned by _sum.
+
def setUp(self):
self.func = statistics._sum
def test_empty_data(self):
# Override test for empty data.
for data in ([], (), iter([])):
- self.assertEqual(self.func(data), 0)
- self.assertEqual(self.func(data, 23), 23)
- self.assertEqual(self.func(data, 2.3), 2.3)
+ self.assertEqual(self.func(data), (int, Fraction(0), 0))
+ self.assertEqual(self.func(data, 23), (int, Fraction(23), 0))
+ self.assertEqual(self.func(data, 2.3), (float, Fraction(2.3), 0))
def test_ints(self):
- self.assertEqual(self.func([1, 5, 3, -4, -8, 20, 42, 1]), 60)
- self.assertEqual(self.func([4, 2, 3, -8, 7], 1000), 1008)
+ self.assertEqual(self.func([1, 5, 3, -4, -8, 20, 42, 1]),
+ (int, Fraction(60), 8))
+ self.assertEqual(self.func([4, 2, 3, -8, 7], 1000),
+ (int, Fraction(1008), 5))
def test_floats(self):
- self.assertEqual(self.func([0.25]*20), 5.0)
- self.assertEqual(self.func([0.125, 0.25, 0.5, 0.75], 1.5), 3.125)
+ self.assertEqual(self.func([0.25]*20),
+ (float, Fraction(5.0), 20))
+ self.assertEqual(self.func([0.125, 0.25, 0.5, 0.75], 1.5),
+ (float, Fraction(3.125), 4))
def test_fractions(self):
- F = Fraction
- self.assertEqual(self.func([Fraction(1, 1000)]*500), Fraction(1, 2))
+ self.assertEqual(self.func([Fraction(1, 1000)]*500),
+ (Fraction, Fraction(1, 2), 500))
def test_decimals(self):
D = Decimal
data = [D("0.001"), D("5.246"), D("1.702"), D("-0.025"),
D("3.974"), D("2.328"), D("4.617"), D("2.843"),
]
- self.assertEqual(self.func(data), Decimal("20.686"))
+ self.assertEqual(self.func(data),
+ (Decimal, Decimal("20.686"), 8))
def test_compare_with_math_fsum(self):
# Compare with the math.fsum function.
# Ideally we ought to get the exact same result, but sometimes
# we differ by a very slight amount :-(
data = [random.uniform(-100, 1000) for _ in range(1000)]
- self.assertApproxEqual(self.func(data), math.fsum(data), rel=2e-16)
+ self.assertApproxEqual(float(self.func(data)[1]), math.fsum(data), rel=2e-16)
def test_start_argument(self):
# Test that the optional start argument works correctly.
data = [random.uniform(1, 1000) for _ in range(100)]
- t = self.func(data)
- self.assertEqual(t+42, self.func(data, 42))
- self.assertEqual(t-23, self.func(data, -23))
- self.assertEqual(t+1e20, self.func(data, 1e20))
+ t = self.func(data)[1]
+ self.assertEqual(t+42, self.func(data, 42)[1])
+ self.assertEqual(t-23, self.func(data, -23)[1])
+ self.assertEqual(t+Fraction(1e20), self.func(data, 1e20)[1])
def test_strings_fail(self):
# Sum of strings should fail.
def test_mixed_sum(self):
# Mixed input types are not (currently) allowed.
# Check that mixed data types fail.
- self.assertRaises(TypeError, self.func, [1, 2.0, Fraction(1, 2)])
+ self.assertRaises(TypeError, self.func, [1, 2.0, Decimal(1)])
# And so does mixed start argument.
self.assertRaises(TypeError, self.func, [1, 2.0], Decimal(1))
class SumTortureTest(NumericTestCase):
def test_torture(self):
# Tim Peters' torture test for sum, and variants of same.
- self.assertEqual(statistics._sum([1, 1e100, 1, -1e100]*10000), 20000.0)
- self.assertEqual(statistics._sum([1e100, 1, 1, -1e100]*10000), 20000.0)
- self.assertApproxEqual(
- statistics._sum([1e-100, 1, 1e-100, -1]*10000), 2.0e-96, rel=5e-16
- )
+ self.assertEqual(statistics._sum([1, 1e100, 1, -1e100]*10000),
+ (float, Fraction(20000.0), 40000))
+ self.assertEqual(statistics._sum([1e100, 1, 1, -1e100]*10000),
+ (float, Fraction(20000.0), 40000))
+ T, num, count = statistics._sum([1e-100, 1, 1e-100, -1]*10000)
+ self.assertIs(T, float)
+ self.assertEqual(count, 40000)
+ self.assertApproxEqual(float(num), 2.0e-96, rel=5e-16)
class SumSpecialValues(NumericTestCase):
def test_nan(self):
for type_ in (float, Decimal):
nan = type_('nan')
- result = statistics._sum([1, nan, 2])
+ result = statistics._sum([1, nan, 2])[1]
self.assertIs(type(result), type_)
self.assertTrue(math.isnan(result))
def do_test_inf(self, inf):
# Adding a single infinity gives infinity.
- result = statistics._sum([1, 2, inf, 3])
+ result = statistics._sum([1, 2, inf, 3])[1]
self.check_infinity(result, inf)
# Adding two infinities of the same sign also gives infinity.
- result = statistics._sum([1, 2, inf, 3, inf, 4])
+ result = statistics._sum([1, 2, inf, 3, inf, 4])[1]
self.check_infinity(result, inf)
def test_float_inf(self):
def test_float_mismatched_infs(self):
# Test that adding two infinities of opposite sign gives a NAN.
inf = float('inf')
- result = statistics._sum([1, 2, inf, 3, -inf, 4])
+ result = statistics._sum([1, 2, inf, 3, -inf, 4])[1]
self.assertTrue(math.isnan(result))
def test_decimal_extendedcontext_mismatched_infs_to_nan(self):
inf = Decimal('inf')
data = [1, 2, inf, 3, -inf, 4]
with decimal.localcontext(decimal.ExtendedContext):
- self.assertTrue(math.isnan(statistics._sum(data)))
+ self.assertTrue(math.isnan(statistics._sum(data)[1]))
def test_decimal_basiccontext_mismatched_infs_to_nan(self):
# Test adding Decimal INFs with opposite sign raises InvalidOperation.
d = Decimal('1e4')
self.assertEqual(statistics.mean([d]), d)
+ def test_regression_25177(self):
+ # Regression test for issue 25177.
+ # Ensure very big and very small floats don't overflow.
+ # See http://bugs.python.org/issue25177.
+ self.assertEqual(statistics.mean(
+ [8.988465674311579e+307, 8.98846567431158e+307]),
+ 8.98846567431158e+307)
+ big = 8.98846567431158e+307
+ tiny = 5e-324
+ for n in (2, 3, 5, 200):
+ self.assertEqual(statistics.mean([big]*n), big)
+ self.assertEqual(statistics.mean([tiny]*n), tiny)
+
class TestMedian(NumericTestCase, AverageMixin):
# Common tests for median and all median.* functions.
-import unittest, string
+import unittest
+import string
+from string import Template
class ModuleTest(unittest.TestCase):
self.assertIn("recursion", str(err.exception))
-if __name__ == "__main__":
+# Template tests (formerly housed in test_pep292.py)
+
+class Bag:
+ pass
+
+class Mapping:
+ def __getitem__(self, name):
+ obj = self
+ for part in name.split('.'):
+ try:
+ obj = getattr(obj, part)
+ except AttributeError:
+ raise KeyError(name)
+ return obj
+
+
+class TestTemplate(unittest.TestCase):
+ def test_regular_templates(self):
+ s = Template('$who likes to eat a bag of $what worth $$100')
+ self.assertEqual(s.substitute(dict(who='tim', what='ham')),
+ 'tim likes to eat a bag of ham worth $100')
+ self.assertRaises(KeyError, s.substitute, dict(who='tim'))
+ self.assertRaises(TypeError, Template.substitute)
+
+ def test_regular_templates_with_braces(self):
+ s = Template('$who likes ${what} for ${meal}')
+ d = dict(who='tim', what='ham', meal='dinner')
+ self.assertEqual(s.substitute(d), 'tim likes ham for dinner')
+ self.assertRaises(KeyError, s.substitute,
+ dict(who='tim', what='ham'))
+
+ def test_escapes(self):
+ eq = self.assertEqual
+ s = Template('$who likes to eat a bag of $$what worth $$100')
+ eq(s.substitute(dict(who='tim', what='ham')),
+ 'tim likes to eat a bag of $what worth $100')
+ s = Template('$who likes $$')
+ eq(s.substitute(dict(who='tim', what='ham')), 'tim likes $')
+
+ def test_percents(self):
+ eq = self.assertEqual
+ s = Template('%(foo)s $foo ${foo}')
+ d = dict(foo='baz')
+ eq(s.substitute(d), '%(foo)s baz baz')
+ eq(s.safe_substitute(d), '%(foo)s baz baz')
+
+ def test_stringification(self):
+ eq = self.assertEqual
+ s = Template('tim has eaten $count bags of ham today')
+ d = dict(count=7)
+ eq(s.substitute(d), 'tim has eaten 7 bags of ham today')
+ eq(s.safe_substitute(d), 'tim has eaten 7 bags of ham today')
+ s = Template('tim has eaten ${count} bags of ham today')
+ eq(s.substitute(d), 'tim has eaten 7 bags of ham today')
+
+ def test_tupleargs(self):
+ eq = self.assertEqual
+ s = Template('$who ate ${meal}')
+ d = dict(who=('tim', 'fred'), meal=('ham', 'kung pao'))
+ eq(s.substitute(d), "('tim', 'fred') ate ('ham', 'kung pao')")
+ eq(s.safe_substitute(d), "('tim', 'fred') ate ('ham', 'kung pao')")
+
+ def test_SafeTemplate(self):
+ eq = self.assertEqual
+ s = Template('$who likes ${what} for ${meal}')
+ eq(s.safe_substitute(dict(who='tim')), 'tim likes ${what} for ${meal}')
+ eq(s.safe_substitute(dict(what='ham')), '$who likes ham for ${meal}')
+ eq(s.safe_substitute(dict(what='ham', meal='dinner')),
+ '$who likes ham for dinner')
+ eq(s.safe_substitute(dict(who='tim', what='ham')),
+ 'tim likes ham for ${meal}')
+ eq(s.safe_substitute(dict(who='tim', what='ham', meal='dinner')),
+ 'tim likes ham for dinner')
+
+ def test_invalid_placeholders(self):
+ raises = self.assertRaises
+ s = Template('$who likes $')
+ raises(ValueError, s.substitute, dict(who='tim'))
+ s = Template('$who likes ${what)')
+ raises(ValueError, s.substitute, dict(who='tim'))
+ s = Template('$who likes $100')
+ raises(ValueError, s.substitute, dict(who='tim'))
+
+ def test_idpattern_override(self):
+ class PathPattern(Template):
+ idpattern = r'[_a-z][._a-z0-9]*'
+ m = Mapping()
+ m.bag = Bag()
+ m.bag.foo = Bag()
+ m.bag.foo.who = 'tim'
+ m.bag.what = 'ham'
+ s = PathPattern('$bag.foo.who likes to eat a bag of $bag.what')
+ self.assertEqual(s.substitute(m), 'tim likes to eat a bag of ham')
+
+ def test_pattern_override(self):
+ class MyPattern(Template):
+ pattern = r"""
+ (?P<escaped>@{2}) |
+ @(?P<named>[_a-z][._a-z0-9]*) |
+ @{(?P<braced>[_a-z][._a-z0-9]*)} |
+ (?P<invalid>@)
+ """
+ m = Mapping()
+ m.bag = Bag()
+ m.bag.foo = Bag()
+ m.bag.foo.who = 'tim'
+ m.bag.what = 'ham'
+ s = MyPattern('@bag.foo.who likes to eat a bag of @bag.what')
+ self.assertEqual(s.substitute(m), 'tim likes to eat a bag of ham')
+
+ class BadPattern(Template):
+ pattern = r"""
+ (?P<badname>.*) |
+ (?P<escaped>@{2}) |
+ @(?P<named>[_a-z][._a-z0-9]*) |
+ @{(?P<braced>[_a-z][._a-z0-9]*)} |
+ (?P<invalid>@) |
+ """
+ s = BadPattern('@bag.foo.who likes to eat a bag of @bag.what')
+ self.assertRaises(ValueError, s.substitute, {})
+ self.assertRaises(ValueError, s.safe_substitute, {})
+
+ def test_braced_override(self):
+ class MyTemplate(Template):
+ pattern = r"""
+ \$(?:
+ (?P<escaped>$) |
+ (?P<named>[_a-z][_a-z0-9]*) |
+ @@(?P<braced>[_a-z][_a-z0-9]*)@@ |
+ (?P<invalid>) |
+ )
+ """
+
+ tmpl = 'PyCon in $@@location@@'
+ t = MyTemplate(tmpl)
+ self.assertRaises(KeyError, t.substitute, {})
+ val = t.substitute({'location': 'Cleveland'})
+ self.assertEqual(val, 'PyCon in Cleveland')
+
+ def test_braced_override_safe(self):
+ class MyTemplate(Template):
+ pattern = r"""
+ \$(?:
+ (?P<escaped>$) |
+ (?P<named>[_a-z][_a-z0-9]*) |
+ @@(?P<braced>[_a-z][_a-z0-9]*)@@ |
+ (?P<invalid>) |
+ )
+ """
+
+ tmpl = 'PyCon in $@@location@@'
+ t = MyTemplate(tmpl)
+ self.assertEqual(t.safe_substitute(), tmpl)
+ val = t.safe_substitute({'location': 'Cleveland'})
+ self.assertEqual(val, 'PyCon in Cleveland')
+
+ def test_invalid_with_no_lines(self):
+ # The error formatting for invalid templates
+ # has a special case for no data that the default
+ # pattern can't trigger (always has at least '$')
+ # So we craft a pattern that is always invalid
+ # with no leading data.
+ class MyTemplate(Template):
+ pattern = r"""
+ (?P<invalid>) |
+ unreachable(
+ (?P<named>) |
+ (?P<braced>) |
+ (?P<escaped>)
+ )
+ """
+ s = MyTemplate('')
+ with self.assertRaises(ValueError) as err:
+ s.substitute({})
+ self.assertIn('line 1, col 1', str(err.exception))
+
+ def test_unicode_values(self):
+ s = Template('$who likes $what')
+ d = dict(who='t\xffm', what='f\xfe\fed')
+ self.assertEqual(s.substitute(d), 't\xffm likes f\xfe\x0ced')
+
+ def test_keyword_arguments(self):
+ eq = self.assertEqual
+ s = Template('$who likes $what')
+ eq(s.substitute(who='tim', what='ham'), 'tim likes ham')
+ eq(s.substitute(dict(who='tim'), what='ham'), 'tim likes ham')
+ eq(s.substitute(dict(who='fred', what='kung pao'),
+ who='tim', what='ham'),
+ 'tim likes ham')
+ s = Template('the mapping is $mapping')
+ eq(s.substitute(dict(foo='none'), mapping='bozo'),
+ 'the mapping is bozo')
+ eq(s.substitute(dict(mapping='one'), mapping='two'),
+ 'the mapping is two')
+
+ s = Template('the self is $self')
+ eq(s.substitute(self='bozo'), 'the self is bozo')
+
+ def test_keyword_arguments_safe(self):
+ eq = self.assertEqual
+ raises = self.assertRaises
+ s = Template('$who likes $what')
+ eq(s.safe_substitute(who='tim', what='ham'), 'tim likes ham')
+ eq(s.safe_substitute(dict(who='tim'), what='ham'), 'tim likes ham')
+ eq(s.safe_substitute(dict(who='fred', what='kung pao'),
+ who='tim', what='ham'),
+ 'tim likes ham')
+ s = Template('the mapping is $mapping')
+ eq(s.safe_substitute(dict(foo='none'), mapping='bozo'),
+ 'the mapping is bozo')
+ eq(s.safe_substitute(dict(mapping='one'), mapping='two'),
+ 'the mapping is two')
+ d = dict(mapping='one')
+ raises(TypeError, s.substitute, d, {})
+ raises(TypeError, s.safe_substitute, d, {})
+
+ s = Template('the self is $self')
+ eq(s.safe_substitute(self='bozo'), 'the self is bozo')
+
+ def test_delimiter_override(self):
+ eq = self.assertEqual
+ raises = self.assertRaises
+ class AmpersandTemplate(Template):
+ delimiter = '&'
+ s = AmpersandTemplate('this &gift is for &{who} &&')
+ eq(s.substitute(gift='bud', who='you'), 'this bud is for you &')
+ raises(KeyError, s.substitute)
+ eq(s.safe_substitute(gift='bud', who='you'), 'this bud is for you &')
+ eq(s.safe_substitute(), 'this &gift is for &{who} &')
+ s = AmpersandTemplate('this &gift is for &{who} &')
+ raises(ValueError, s.substitute, dict(gift='bud', who='you'))
+ eq(s.safe_substitute(), 'this &gift is for &{who} &')
+
+ class PieDelims(Template):
+ delimiter = '@'
+ s = PieDelims('@who likes to eat a bag of @{what} worth $100')
+ self.assertEqual(s.substitute(dict(who='tim', what='ham')),
+ 'tim likes to eat a bag of ham worth $100')
+
+
+if __name__ == '__main__':
unittest.main()
import time
import locale
import re
+import os
import sys
from test import support
from datetime import date as datetime_date
def test_whitespace_substitution(self):
# When pattern contains whitespace, make sure it is taken into account
- # so as to not allow to subpatterns to end up next to each other and
+ # so as to not allow subpatterns to end up next to each other and
# "steal" characters from each other.
pattern = self.time_re.pattern('%j %H')
self.assertFalse(re.match(pattern, "180"))
tz_name = time.tzname[0]
if tz_name.upper() in ("UTC", "GMT"):
self.skipTest('need non-UTC/GMT timezone')
- try:
- original_tzname = time.tzname
- original_daylight = time.daylight
+
+ with support.swap_attr(time, 'tzname', (tz_name, tz_name)), \
+ support.swap_attr(time, 'daylight', 1), \
+ support.swap_attr(time, 'tzset', lambda: None):
time.tzname = (tz_name, tz_name)
time.daylight = 1
tz_value = _strptime._strptime_time(tz_name, "%Z")[8]
"%s lead to a timezone value of %s instead of -1 when "
"time.daylight set to %s and passing in %s" %
(time.tzname, tz_value, time.daylight, tz_name))
- finally:
- time.tzname = original_tzname
- time.daylight = original_daylight
def test_date_time(self):
# Test %c directive
def test_week_0(self):
def check(value, format, *expected):
self.assertEqual(_strptime._strptime_time(value, format)[:-1], expected)
- check('2015 0 0', '%Y %U %w', 2014, 12, 28, 0, 0, 0, 6, -3)
+ check('2015 0 0', '%Y %U %w', 2014, 12, 28, 0, 0, 0, 6, 362)
check('2015 0 0', '%Y %W %w', 2015, 1, 4, 0, 0, 0, 6, 4)
- check('2015 0 1', '%Y %U %w', 2014, 12, 29, 0, 0, 0, 0, -2)
- check('2015 0 1', '%Y %W %w', 2014, 12, 29, 0, 0, 0, 0, -2)
- check('2015 0 2', '%Y %U %w', 2014, 12, 30, 0, 0, 0, 1, -1)
- check('2015 0 2', '%Y %W %w', 2014, 12, 30, 0, 0, 0, 1, -1)
- check('2015 0 3', '%Y %U %w', 2014, 12, 31, 0, 0, 0, 2, 0)
- check('2015 0 3', '%Y %W %w', 2014, 12, 31, 0, 0, 0, 2, 0)
+ check('2015 0 1', '%Y %U %w', 2014, 12, 29, 0, 0, 0, 0, 363)
+ check('2015 0 1', '%Y %W %w', 2014, 12, 29, 0, 0, 0, 0, 363)
+ check('2015 0 2', '%Y %U %w', 2014, 12, 30, 0, 0, 0, 1, 364)
+ check('2015 0 2', '%Y %W %w', 2014, 12, 30, 0, 0, 0, 1, 364)
+ check('2015 0 3', '%Y %U %w', 2014, 12, 31, 0, 0, 0, 2, 365)
+ check('2015 0 3', '%Y %W %w', 2014, 12, 31, 0, 0, 0, 2, 365)
check('2015 0 4', '%Y %U %w', 2015, 1, 1, 0, 0, 0, 3, 1)
check('2015 0 4', '%Y %W %w', 2015, 1, 1, 0, 0, 0, 3, 1)
check('2015 0 5', '%Y %U %w', 2015, 1, 2, 0, 0, 0, 4, 2)
check('2015 0 6', '%Y %U %w', 2015, 1, 3, 0, 0, 0, 5, 3)
check('2015 0 6', '%Y %W %w', 2015, 1, 3, 0, 0, 0, 5, 3)
+ check('2009 0 0', '%Y %U %w', 2008, 12, 28, 0, 0, 0, 6, 363)
+ check('2009 0 0', '%Y %W %w', 2009, 1, 4, 0, 0, 0, 6, 4)
+ check('2009 0 1', '%Y %U %w', 2008, 12, 29, 0, 0, 0, 0, 364)
+ check('2009 0 1', '%Y %W %w', 2008, 12, 29, 0, 0, 0, 0, 364)
+ check('2009 0 2', '%Y %U %w', 2008, 12, 30, 0, 0, 0, 1, 365)
+ check('2009 0 2', '%Y %W %w', 2008, 12, 30, 0, 0, 0, 1, 365)
+ check('2009 0 3', '%Y %U %w', 2008, 12, 31, 0, 0, 0, 2, 366)
+ check('2009 0 3', '%Y %W %w', 2008, 12, 31, 0, 0, 0, 2, 366)
+ check('2009 0 4', '%Y %U %w', 2009, 1, 1, 0, 0, 0, 3, 1)
+ check('2009 0 4', '%Y %W %w', 2009, 1, 1, 0, 0, 0, 3, 1)
+ check('2009 0 5', '%Y %U %w', 2009, 1, 2, 0, 0, 0, 4, 2)
+ check('2009 0 5', '%Y %W %w', 2009, 1, 2, 0, 0, 0, 4, 2)
+ check('2009 0 6', '%Y %U %w', 2009, 1, 3, 0, 0, 0, 5, 3)
+ check('2009 0 6', '%Y %W %w', 2009, 1, 3, 0, 0, 0, 5, 3)
class CacheTests(unittest.TestCase):
"""Test that caching works properly."""
_strptime._strptime_time("10", "%d")
self.assertIsNot(locale_time_id, _strptime._TimeRE_cache.locale_time)
- def test_TimeRE_recreation(self):
+ def test_TimeRE_recreation_locale(self):
# The TimeRE instance should be recreated upon changing the locale.
locale_info = locale.getlocale(locale.LC_TIME)
try:
finally:
locale.setlocale(locale.LC_TIME, locale_info)
+ @support.run_with_tz('STD-1DST')
+ def test_TimeRE_recreation_timezone(self):
+ # The TimeRE instance should be recreated upon changing the timezone.
+ oldtzname = time.tzname
+ tm = _strptime._strptime_time(time.tzname[0], '%Z')
+ self.assertEqual(tm.tm_isdst, 0)
+ tm = _strptime._strptime_time(time.tzname[1], '%Z')
+ self.assertEqual(tm.tm_isdst, 1)
+ # Get id of current cache object.
+ first_time_re = _strptime._TimeRE_cache
+ # Change the timezone and force a recreation of the cache.
+ os.environ['TZ'] = 'EST+05EDT,M3.2.0,M11.1.0'
+ time.tzset()
+ tm = _strptime._strptime_time(time.tzname[0], '%Z')
+ self.assertEqual(tm.tm_isdst, 0)
+ tm = _strptime._strptime_time(time.tzname[1], '%Z')
+ self.assertEqual(tm.tm_isdst, 1)
+ # Get the new cache object's id.
+ second_time_re = _strptime._TimeRE_cache
+ # They should not be equal.
+ self.assertIsNot(first_time_re, second_time_re)
+ # Make sure old names no longer accepted.
+ with self.assertRaises(ValueError):
+ _strptime._strptime_time(oldtzname[0], '%Z')
+ with self.assertRaises(ValueError):
+ _strptime._strptime_time(oldtzname[1], '%Z')
+
if __name__ == '__main__':
unittest.main()
import unittest
+from unittest import mock
from test.support import script_helper
from test import support
import subprocess
tf.seek(0)
self.assertStderrEqual(tf.read(), b"strawberry")
+ def test_stderr_redirect_with_no_stdout_redirect(self):
+ # test stderr=STDOUT while stdout=None (not set)
+
+ # - grandchild prints to stderr
+ # - child redirects grandchild's stderr to its stdout
+ # - the parent should get grandchild's stderr in child's stdout
+ p = subprocess.Popen([sys.executable, "-c",
+ 'import sys, subprocess;'
+ 'rc = subprocess.call([sys.executable, "-c",'
+ ' "import sys;"'
+ ' "sys.stderr.write(\'42\')"],'
+ ' stderr=subprocess.STDOUT);'
+ 'sys.exit(rc)'],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ stdout, stderr = p.communicate()
+ #NOTE: stdout should get stderr from grandchild
+ self.assertStderrEqual(stdout, b'42')
+ self.assertStderrEqual(stderr, b'') # should be empty
+ self.assertEqual(p.returncode, 0)
+
def test_stdout_stderr_pipe(self):
# capture stdout and stderr to the same pipe
p = subprocess.Popen([sys.executable, "-c",
if not enabled:
gc.disable()
+ @unittest.skipIf(
+ sys.platform == 'darwin', 'setrlimit() seems to fail on OS X')
+ def test_preexec_fork_failure(self):
+ # The internal code did not preserve the previous exception when
+ # re-enabling garbage collection
+ try:
+ from resource import getrlimit, setrlimit, RLIMIT_NPROC
+ except ImportError as err:
+ self.skipTest(err) # RLIMIT_NPROC is specific to Linux and BSD
+ limits = getrlimit(RLIMIT_NPROC)
+ [_, hard] = limits
+ setrlimit(RLIMIT_NPROC, (0, hard))
+ self.addCleanup(setrlimit, RLIMIT_NPROC, limits)
+ try:
+ subprocess.call([sys.executable, '-c', ''],
+ preexec_fn=lambda: None)
+ except BlockingIOError:
+ # Forking should raise EAGAIN, translated to BlockingIOError
+ pass
+ else:
+ self.skipTest('RLIMIT_NPROC had no effect; probably superuser')
+
def test_args_string(self):
# args is a string
fd, fname = tempfile.mkstemp()
if not gc_enabled:
gc.disable()
+ def test_communicate_BrokenPipeError_stdin_close(self):
+ # By not setting stdout or stderr or a timeout we force the fast path
+ # that just calls _stdin_write() internally due to our mock.
+ proc = subprocess.Popen([sys.executable, '-c', 'pass'])
+ with proc, mock.patch.object(proc, 'stdin') as mock_proc_stdin:
+ mock_proc_stdin.close.side_effect = BrokenPipeError
+ proc.communicate() # Should swallow BrokenPipeError from close.
+ mock_proc_stdin.close.assert_called_with()
+
+ def test_communicate_BrokenPipeError_stdin_write(self):
+ # By not setting stdout or stderr or a timeout we force the fast path
+ # that just calls _stdin_write() internally due to our mock.
+ proc = subprocess.Popen([sys.executable, '-c', 'pass'])
+ with proc, mock.patch.object(proc, 'stdin') as mock_proc_stdin:
+ mock_proc_stdin.write.side_effect = BrokenPipeError
+ proc.communicate(b'stuff') # Should swallow the BrokenPipeError.
+ mock_proc_stdin.write.assert_called_once_with(b'stuff')
+ mock_proc_stdin.close.assert_called_once_with()
+
+ def test_communicate_BrokenPipeError_stdin_flush(self):
+ # Setting stdin and stdout forces the ._communicate() code path.
+ # python -h exits faster than python -c pass (but spams stdout).
+ proc = subprocess.Popen([sys.executable, '-h'],
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE)
+ with proc, mock.patch.object(proc, 'stdin') as mock_proc_stdin, \
+ open(os.devnull, 'wb') as dev_null:
+ mock_proc_stdin.flush.side_effect = BrokenPipeError
+ # because _communicate registers a selector using proc.stdin...
+ mock_proc_stdin.fileno.return_value = dev_null.fileno()
+ # _communicate() should swallow BrokenPipeError from flush.
+ proc.communicate(b'stuff')
+ mock_proc_stdin.flush.assert_called_once_with()
+
+ def test_communicate_BrokenPipeError_stdin_close_with_timeout(self):
+ # Setting stdin and stdout forces the ._communicate() code path.
+ # python -h exits faster than python -c pass (but spams stdout).
+ proc = subprocess.Popen([sys.executable, '-h'],
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE)
+ with proc, mock.patch.object(proc, 'stdin') as mock_proc_stdin:
+ mock_proc_stdin.close.side_effect = BrokenPipeError
+ # _communicate() should swallow BrokenPipeError from close.
+ proc.communicate(timeout=999)
+ mock_proc_stdin.close.assert_called_once_with()
+
@unittest.skipUnless(mswindows, "Windows specific tests")
class Win32ProcessTestCase(BaseTestCase):
def test_terminate_dead(self):
self._kill_dead_process('terminate')
-class CommandTests(unittest.TestCase):
+class MiscTests(unittest.TestCase):
def test_getoutput(self):
self.assertEqual(subprocess.getoutput('echo xyzzy'), 'xyzzy')
self.assertEqual(subprocess.getstatusoutput('echo xyzzy'),
if dir is not None:
os.rmdir(dir)
-
-@unittest.skipUnless(hasattr(selectors, 'PollSelector'),
- "Test needs selectors.PollSelector")
-class ProcessTestCaseNoPoll(ProcessTestCase):
- def setUp(self):
- self.orig_selector = subprocess._PopenSelector
- subprocess._PopenSelector = selectors.SelectSelector
- ProcessTestCase.setUp(self)
-
- def tearDown(self):
- subprocess._PopenSelector = self.orig_selector
- ProcessTestCase.tearDown(self)
-
def test__all__(self):
"""Ensure that __all__ is populated properly."""
- intentionally_excluded = set(("list2cmdline",))
+ # STARTUPINFO added to __all__ in 3.6
+ intentionally_excluded = {"list2cmdline", "STARTUPINFO", "Handle"}
exported = set(subprocess.__all__)
possible_exports = set()
import types
self.assertEqual(exported, possible_exports - intentionally_excluded)
+@unittest.skipUnless(hasattr(selectors, 'PollSelector'),
+ "Test needs selectors.PollSelector")
+class ProcessTestCaseNoPoll(ProcessTestCase):
+ def setUp(self):
+ self.orig_selector = subprocess._PopenSelector
+ subprocess._PopenSelector = selectors.SelectSelector
+ ProcessTestCase.setUp(self)
+
+ def tearDown(self):
+ subprocess._PopenSelector = self.orig_selector
+ ProcessTestCase.tearDown(self)
+
@unittest.skipUnless(mswindows, "Windows-specific tests")
class CommandsWithSpaces (BaseTestCase):
unit_tests = (ProcessTestCase,
POSIXProcessTestCase,
Win32ProcessTestCase,
- CommandTests,
+ MiscTests,
ProcessTestCaseNoPoll,
CommandsWithSpaces,
ContextManagerTests,
c = f().__closure__[0]
self.assertRaises(TypeError, X.meth, c)
+ def test_super_init_leaks(self):
+ # Issue #26718: super.__init__ leaked memory if called multiple times.
+ # This will be caught by regrtest.py -R if this leak.
+ # NOTE: Despite the use in the test a direct call of super.__init__
+ # is not endorsed.
+ sp = super(float, 1.0)
+ for i in range(1000):
+ super.__init__(sp, int, i)
+
if __name__ == "__main__":
unittest.main()
## ...
## SyntaxWarning: name 'x' is assigned to before nonlocal declaration
+ From https://bugs.python.org/issue25973
+ >>> class A:
+ ... def f(self):
+ ... nonlocal __x
+ Traceback (most recent call last):
+ ...
+ SyntaxError: no binding for nonlocal '_A__x' found
+
This tests assignment-context; there was a bug in Python 2.5 where compiling
a complex 'if' (one with 'elif') would fail to notice an invalid suite,
self.assertEqual(os.path.abspath(sys.executable), sys.executable)
# Issue #7774: Ensure that sys.executable is an empty string if argv[0]
- # has been set to an non existent program name and Python is unable to
+ # has been set to a non existent program name and Python is unable to
# retrieve the real program name
# For a normal installation, it should work without 'cwd'
args = [sys.executable, "-c", code]
if isolated:
args.append("-I")
- elif encoding:
+ if encoding is not None:
env['PYTHONIOENCODING'] = encoding
+ else:
+ env.pop('PYTHONIOENCODING', None)
p = subprocess.Popen(args,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
'stderr: backslashreplace\n')
# replace the default error handler
- out = self.c_locale_get_error_handler(encoding=':strict')
+ out = self.c_locale_get_error_handler(encoding=':ignore')
self.assertEqual(out,
- 'stdin: strict\n'
- 'stdout: strict\n'
+ 'stdin: ignore\n'
+ 'stdout: ignore\n'
'stderr: backslashreplace\n')
# force the encoding
out = self.c_locale_get_error_handler(encoding='iso8859-1')
self.assertEqual(out,
+ 'stdin: strict\n'
+ 'stdout: strict\n'
+ 'stderr: backslashreplace\n')
+ out = self.c_locale_get_error_handler(encoding='iso8859-1:')
+ self.assertEqual(out,
+ 'stdin: strict\n'
+ 'stdout: strict\n'
+ 'stderr: backslashreplace\n')
+
+ # have no any effect
+ out = self.c_locale_get_error_handler(encoding=':')
+ self.assertEqual(out,
+ 'stdin: surrogateescape\n'
+ 'stdout: surrogateescape\n'
+ 'stderr: backslashreplace\n')
+ out = self.c_locale_get_error_handler(encoding='')
+ self.assertEqual(out,
'stdin: surrogateescape\n'
'stdout: surrogateescape\n'
'stderr: backslashreplace\n')
self.longdigit = sys.int_info.sizeof_digit
import _testcapi
self.gc_headsize = _testcapi.SIZEOF_PYGC_HEAD
- self.file = open(test.support.TESTFN, 'wb')
-
- def tearDown(self):
- self.file.close()
- test.support.unlink(test.support.TESTFN)
check_sizeof = test.support.check_sizeof
def test_objecttypes(self):
# check all types defined in Objects/
+ calcsize = struct.calcsize
size = test.support.calcobjsize
vsize = test.support.calcvobjsize
check = self.check_sizeof
# method-wrapper (descriptor object)
check({}.__iter__, size('2P'))
# dict
- check({}, size('n2P' + '2nPn' + 8*'n2P'))
+ check({}, size('n2P') + calcsize('2nPn') + 8*calcsize('n2P'))
longdict = {1:1, 2:2, 3:3, 4:4, 5:5, 6:6, 7:7, 8:8}
- check(longdict, size('n2P' + '2nPn') + 16*struct.calcsize('n2P'))
- # dictionary-keyiterator
+ check(longdict, size('n2P') + calcsize('2nPn') + 16*calcsize('n2P'))
+ # dictionary-keyview
check({}.keys(), size('P'))
- # dictionary-valueiterator
+ # dictionary-valueview
check({}.values(), size('P'))
- # dictionary-itemiterator
+ # dictionary-itemview
check({}.items(), size('P'))
# dictionary iterator
check(iter({}), size('P2nPn'))
+ # dictionary-keyiterator
+ check(iter({}.keys()), size('P2nPn'))
+ # dictionary-valueiterator
+ check(iter({}.values()), size('P2nPn'))
+ # dictionary-itemiterator
+ check(iter({}.items()), size('P2nPn'))
# dictproxy
class C(object): pass
check(C.__dict__, size('P'))
check(set(sample), s)
check(frozenset(sample), s)
else:
- check(set(sample), s + newsize*struct.calcsize('nP'))
- check(frozenset(sample), s + newsize*struct.calcsize('nP'))
+ check(set(sample), s + newsize*calcsize('nP'))
+ check(frozenset(sample), s + newsize*calcsize('nP'))
# setiterator
check(iter(set()), size('P3n'))
# slice
# static type: PyTypeObject
s = vsize('P2n15Pl4Pn9Pn11PIP')
check(int, s)
- # (PyTypeObject + PyAsyncMethods + PyNumberMethods + PyMappingMethods +
- # PySequenceMethods + PyBufferProcs + 4P)
- s = vsize('P2n17Pl4Pn9Pn11PIP') + struct.calcsize('34P 3P 3P 10P 2P 4P')
+ s = vsize('P2n15Pl4Pn9Pn11PIP' # PyTypeObject
+ '3P' # PyAsyncMethods
+ '36P' # PyNumberMethods
+ '3P' # PyMappingMethods
+ '10P' # PySequenceMethods
+ '2P' # PyBufferProcs
+ '4P')
# Separate block for PyDictKeysObject with 4 entries
- s += struct.calcsize("2nPn") + 4*struct.calcsize("n2P")
+ s += calcsize("2nPn") + 4*calcsize("n2P")
# class
class newstyleclass(object): pass
check(newstyleclass, s)
# weakcallableproxy
check(weakref.proxy(int), size('2Pn2P'))
+ def check_slots(self, obj, base, extra):
+ expected = sys.getsizeof(base) + struct.calcsize(extra)
+ if gc.is_tracked(obj) and not gc.is_tracked(base):
+ expected += self.gc_headsize
+ self.assertEqual(sys.getsizeof(obj), expected)
+
+ def test_slots(self):
+ # check all subclassable types defined in Objects/ that allow
+ # non-empty __slots__
+ check = self.check_slots
+ class BA(bytearray):
+ __slots__ = 'a', 'b', 'c'
+ check(BA(), bytearray(), '3P')
+ class D(dict):
+ __slots__ = 'a', 'b', 'c'
+ check(D(x=[]), {'x': []}, '3P')
+ class L(list):
+ __slots__ = 'a', 'b', 'c'
+ check(L(), [], '3P')
+ class S(set):
+ __slots__ = 'a', 'b', 'c'
+ check(S(), set(), '3P')
+ class FS(frozenset):
+ __slots__ = 'a', 'b', 'c'
+ check(FS(), frozenset(), '3P')
+ from collections import OrderedDict
+ class OD(OrderedDict):
+ __slots__ = 'a', 'b', 'c'
+ check(OD(x=[]), OrderedDict(x=[]), '3P')
+
def test_pythontypes(self):
# check all types defined in Python/
size = test.support.calcobjsize
(1, 'return', g_ident),
])
- def test_exception_propogation(self):
+ def test_exception_propagation(self):
def f(p):
1/0
def g(p):
(257, 'line'),
(257, 'return')])
+ def test_17_none_f_trace(self):
+ # Issue 20041: fix TypeError when f_trace is set to None.
+ def func():
+ sys._getframe().f_trace = None
+ lineno = 2
+ self.run_and_compare(func,
+ [(0, 'call'),
+ (1, 'line')])
+
class RaisingTraceFuncTestCase(unittest.TestCase):
def setUp(self):
print("var3=42", file=makefile)
print("var4=$/invalid", file=makefile)
print("var5=dollar$$5", file=makefile)
+ print("var6=${var3}/lib/python3.5/config-$(VAR2)$(var5)"
+ "-x86_64-linux-gnu", file=makefile)
vars = sysconfig._parse_makefile(TESTFN)
self.assertEqual(vars, {
'var1': 'ab42',
'var3': 42,
'var4': '$/invalid',
'var5': 'dollar$5',
+ 'var6': '42/lib/python3.5/config-b42dollar$5-x86_64-linux-gnu',
})
tar.close()
-class UstarUnicodeTest(unittest.TestCase):
-
- format = tarfile.USTAR_FORMAT
+class UnicodeTest:
def test_iso8859_1_filename(self):
self._test_unicode_filename("iso8859-1")
tar.close()
-class GNUUnicodeTest(UstarUnicodeTest):
+class UstarUnicodeTest(UnicodeTest, unittest.TestCase):
+
+ format = tarfile.USTAR_FORMAT
+
+ # Test whether the utf-8 encoded version of a filename exceeds the 100
+ # bytes name field limit (every occurrence of '\xff' will be expanded to 2
+ # bytes).
+ def test_unicode_name1(self):
+ self._test_ustar_name("0123456789" * 10)
+ self._test_ustar_name("0123456789" * 10 + "0", ValueError)
+ self._test_ustar_name("0123456789" * 9 + "01234567\xff")
+ self._test_ustar_name("0123456789" * 9 + "012345678\xff", ValueError)
+
+ def test_unicode_name2(self):
+ self._test_ustar_name("0123456789" * 9 + "012345\xff\xff")
+ self._test_ustar_name("0123456789" * 9 + "0123456\xff\xff", ValueError)
+
+ # Test whether the utf-8 encoded version of a filename exceeds the 155
+ # bytes prefix + '/' + 100 bytes name limit.
+ def test_unicode_longname1(self):
+ self._test_ustar_name("0123456789" * 15 + "01234/" + "0123456789" * 10)
+ self._test_ustar_name("0123456789" * 15 + "0123/4" + "0123456789" * 10, ValueError)
+ self._test_ustar_name("0123456789" * 15 + "012\xff/" + "0123456789" * 10)
+ self._test_ustar_name("0123456789" * 15 + "0123\xff/" + "0123456789" * 10, ValueError)
+
+ def test_unicode_longname2(self):
+ self._test_ustar_name("0123456789" * 15 + "01\xff/2" + "0123456789" * 10, ValueError)
+ self._test_ustar_name("0123456789" * 15 + "01\xff\xff/" + "0123456789" * 10, ValueError)
+
+ def test_unicode_longname3(self):
+ self._test_ustar_name("0123456789" * 15 + "01\xff\xff/2" + "0123456789" * 10, ValueError)
+ self._test_ustar_name("0123456789" * 15 + "01234/" + "0123456789" * 9 + "01234567\xff")
+ self._test_ustar_name("0123456789" * 15 + "01234/" + "0123456789" * 9 + "012345678\xff", ValueError)
+
+ def test_unicode_longname4(self):
+ self._test_ustar_name("0123456789" * 15 + "01234/" + "0123456789" * 9 + "012345\xff\xff")
+ self._test_ustar_name("0123456789" * 15 + "01234/" + "0123456789" * 9 + "0123456\xff\xff", ValueError)
+
+ def _test_ustar_name(self, name, exc=None):
+ with tarfile.open(tmpname, "w", format=self.format, encoding="utf-8") as tar:
+ t = tarfile.TarInfo(name)
+ if exc is None:
+ tar.addfile(t)
+ else:
+ self.assertRaises(exc, tar.addfile, t)
+
+ if exc is None:
+ with tarfile.open(tmpname, "r", encoding="utf-8") as tar:
+ for t in tar:
+ self.assertEqual(name, t.name)
+ break
+
+ # Test the same as above for the 100 bytes link field.
+ def test_unicode_link1(self):
+ self._test_ustar_link("0123456789" * 10)
+ self._test_ustar_link("0123456789" * 10 + "0", ValueError)
+ self._test_ustar_link("0123456789" * 9 + "01234567\xff")
+ self._test_ustar_link("0123456789" * 9 + "012345678\xff", ValueError)
+
+ def test_unicode_link2(self):
+ self._test_ustar_link("0123456789" * 9 + "012345\xff\xff")
+ self._test_ustar_link("0123456789" * 9 + "0123456\xff\xff", ValueError)
+
+ def _test_ustar_link(self, name, exc=None):
+ with tarfile.open(tmpname, "w", format=self.format, encoding="utf-8") as tar:
+ t = tarfile.TarInfo("foo")
+ t.linkname = name
+ if exc is None:
+ tar.addfile(t)
+ else:
+ self.assertRaises(exc, tar.addfile, t)
+
+ if exc is None:
+ with tarfile.open(tmpname, "r", encoding="utf-8") as tar:
+ for t in tar:
+ self.assertEqual(name, t.linkname)
+ break
+
+
+class GNUUnicodeTest(UnicodeTest, unittest.TestCase):
format = tarfile.GNU_FORMAT
self.fail("unable to read bad GNU tar pax header")
-class PAXUnicodeTest(UstarUnicodeTest):
+class PAXUnicodeTest(UnicodeTest, unittest.TestCase):
format = tarfile.PAX_FORMAT
expected = {'a': (1, 2, 3), 'something': 'foo', 'status': ''}
self.assertEqual(splitdict(tcl, arg), expected)
+ def test_new_tcl_obj(self):
+ self.assertRaises(TypeError, _tkinter.Tcl_Obj)
class BigmemTclTest(unittest.TestCase):
import time
import contextlib
-from unittest import TestCase
from test import support
+import unittest
threading = support.import_module('threading')
HOST = support.HOST
finally:
serv.close()
-class GeneralTests(TestCase):
+class GeneralTests(unittest.TestCase):
def setUp(self):
self.evt = threading.Event()
telnet._messages = '' # debuglevel output
return telnet
-class ExpectAndReadTestCase(TestCase):
+class ExpectAndReadTestCase(unittest.TestCase):
def setUp(self):
self.old_selector = telnetlib._TelnetSelector
telnetlib._TelnetSelector = MockSelector
self.assertEqual(data, want)
def test_read_eager(self):
- # read_eager and read_very_eager make the same gaurantees
- # (they behave differently but we only test the gaurantees)
+ # read_eager and read_very_eager make the same guarantees
+ # (they behave differently but we only test the guarantees)
self._read_eager('read_eager')
self._read_eager('read_very_eager')
# NB -- we need to test the IAC block which is mentioned in the
tl = telnetlib
-class WriteTests(TestCase):
+class WriteTests(unittest.TestCase):
'''The only thing that write does is replace each tl.IAC for
tl.IAC+tl.IAC'''
written = b''.join(telnet.sock.writes)
self.assertEqual(data.replace(tl.IAC,tl.IAC+tl.IAC), written)
-class OptionTests(TestCase):
+class OptionTests(unittest.TestCase):
# RFC 854 commands
cmds = [tl.AO, tl.AYT, tl.BRK, tl.EC, tl.EL, tl.GA, tl.IP, tl.NOP]
self.assertRaises(ValueError, tempfile.NamedTemporaryFile)
self.assertEqual(len(closed), 1)
- # How to test the mode and bufsize parameters?
+ def test_bad_mode(self):
+ dir = tempfile.mkdtemp()
+ self.addCleanup(support.rmtree, dir)
+ with self.assertRaises(ValueError):
+ tempfile.NamedTemporaryFile(mode='wr', dir=dir)
+ with self.assertRaises(TypeError):
+ tempfile.NamedTemporaryFile(mode=2, dir=dir)
+ self.assertEqual(os.listdir(dir), [])
+ # How to test the mode and bufsize parameters?
class TestSpooledTemporaryFile(BaseTestCase):
"""Test SpooledTemporaryFile()."""
self.nrunning.inc()
if verbose:
print(self.nrunning.get(), 'tasks are running')
- self.testcase.assertTrue(self.nrunning.get() <= 3)
+ self.testcase.assertLessEqual(self.nrunning.get(), 3)
time.sleep(delay)
if verbose:
with self.mutex:
self.nrunning.dec()
- self.testcase.assertTrue(self.nrunning.get() >= 0)
+ self.testcase.assertGreaterEqual(self.nrunning.get(), 0)
if verbose:
print('%s is finished. %d tasks are running' %
(self.name, self.nrunning.get()))
for i in range(NUMTASKS):
t = TestThread("<thread %d>"%i, self, sema, mutex, numrunning)
threads.append(t)
- self.assertEqual(t.ident, None)
- self.assertTrue(re.match('<TestThread\(.*, initial\)>', repr(t)))
+ self.assertIsNone(t.ident)
+ self.assertRegex(repr(t), r'^<TestThread\(.*, initial\)>$')
t.start()
if verbose:
print('waiting for all tasks to complete')
for t in threads:
t.join()
- self.assertTrue(not t.is_alive())
+ self.assertFalse(t.is_alive())
self.assertNotEqual(t.ident, 0)
- self.assertFalse(t.ident is None)
- self.assertTrue(re.match('<TestThread\(.*, stopped -?\d+\)>',
- repr(t)))
+ self.assertIsNotNone(t.ident)
+ self.assertRegex(repr(t), r'^<TestThread\(.*, stopped -?\d+\)>$')
if verbose:
print('all tasks done')
self.assertEqual(numrunning.get(), 0)
def test_ident_of_no_threading_threads(self):
# The ident still must work for the main thread and dummy threads.
- self.assertFalse(threading.currentThread().ident is None)
+ self.assertIsNotNone(threading.currentThread().ident)
def f():
ident.append(threading.currentThread().ident)
done.set()
ident = []
_thread.start_new_thread(f, ())
done.wait()
- self.assertFalse(ident[0] is None)
+ self.assertIsNotNone(ident[0])
# Kill the "immortal" _DummyThread
del threading._active[ident[0]]
self.assertTrue(ret)
if verbose:
print(" verifying worker hasn't exited")
- self.assertTrue(not t.finished)
+ self.assertFalse(t.finished)
if verbose:
print(" attempting to raise asynch exception in worker")
result = set_async_exc(ctypes.c_long(t.id), exception)
def test_repr_daemon(self):
t = threading.Thread()
- self.assertFalse('daemon' in repr(t))
+ self.assertNotIn('daemon', repr(t))
t.daemon = True
- self.assertTrue('daemon' in repr(t))
+ self.assertIn('daemon', repr(t))
def test_deamon_param(self):
t = threading.Thread()
tstate_lock.release()
self.assertFalse(t.is_alive())
# And verify the thread disposed of _tstate_lock.
- self.assertTrue(t._tstate_lock is None)
+ self.assertIsNone(t._tstate_lock)
def test_repr_stopped(self):
# Verify that "stopped" shows up in repr(Thread) appropriately.
eventtype = staticmethod(threading.Event)
class ConditionAsRLockTests(lock_tests.RLockTests):
- # An Condition uses an RLock by default and exports its API.
+ # Condition uses an RLock by default and exports its API.
locktype = staticmethod(threading.Condition)
class ConditionTests(lock_tests.ConditionTests):
wr = weakref.ref(x)
del x
gc.collect()
- self.assertIs(wr(), None)
+ self.assertIsNone(wr())
class ThreadLocalTest(unittest.TestCase, BaseLocalTest):
sys.argv = []
def test_gprof(self):
- # Issue #14508: this used to fail with an NameError.
+ # Issue #14508: this used to fail with a NameError.
with mock.patch.object(self.gprof, 'webbrowser') as wmock, \
tempfile.TemporaryDirectory() as tmpdir:
fn = os.path.join(tmpdir, 'abc')
def test_with_two_items(self):
self.check_roundtrip(with_two_items)
+ def test_dict_unpacking_in_dict(self):
+ # See issue 26489
+ self.check_roundtrip(r"""{**{'y': 2}, 'x': 1}""")
+ self.check_roundtrip(r"""{**{'y': 2}, **{'x': 1}}""")
+
class DirectoryTestCase(ASTTestCase):
"""Test roundtrip behaviour on all files in Lib and Lib/test."""
snapshot.dump(support.TESTFN)
self.addCleanup(support.unlink, support.TESTFN)
- # load() should recreates the attribute
+ # load() should recreate the attribute
snapshot2 = tracemalloc.Snapshot.load(support.TESTFN)
self.assertEqual(snapshot2.test_attr, "new")
from test import support, seq_tests
+import unittest
import gc
import pickle
--- /dev/null
+import pickle
+import unittest
+from test import support
+
+turtle = support.import_module('turtle')
+Vec2D = turtle.Vec2D
+
+test_config = """\
+width = 0.75
+height = 0.8
+canvwidth = 500
+canvheight = 200
+leftright = 100
+topbottom = 100
+mode = world
+colormode = 255
+delay = 100
+undobuffersize = 10000
+shape = circle
+pencolor = red
+fillcolor = blue
+resizemode = auto
+visible = None
+language = english
+exampleturtle = turtle
+examplescreen = screen
+title = Python Turtle Graphics
+using_IDLE = ''
+"""
+
+test_config_two = """\
+# Comments!
+# Testing comments!
+pencolor = red
+fillcolor = blue
+visible = False
+language = english
+# Some more
+# comments
+using_IDLE = False
+"""
+
+invalid_test_config = """
+pencolor = red
+fillcolor: blue
+visible = False
+"""
+
+
+class TurtleConfigTest(unittest.TestCase):
+
+ def get_cfg_file(self, cfg_str):
+ self.addCleanup(support.unlink, support.TESTFN)
+ with open(support.TESTFN, 'w') as f:
+ f.write(cfg_str)
+ return support.TESTFN
+
+ def test_config_dict(self):
+
+ cfg_name = self.get_cfg_file(test_config)
+ parsed_cfg = turtle.config_dict(cfg_name)
+
+ expected = {
+ 'width' : 0.75,
+ 'height' : 0.8,
+ 'canvwidth' : 500,
+ 'canvheight': 200,
+ 'leftright': 100,
+ 'topbottom': 100,
+ 'mode': 'world',
+ 'colormode': 255,
+ 'delay': 100,
+ 'undobuffersize': 10000,
+ 'shape': 'circle',
+ 'pencolor' : 'red',
+ 'fillcolor' : 'blue',
+ 'resizemode' : 'auto',
+ 'visible' : None,
+ 'language': 'english',
+ 'exampleturtle': 'turtle',
+ 'examplescreen': 'screen',
+ 'title': 'Python Turtle Graphics',
+ 'using_IDLE': '',
+ }
+
+ self.assertEqual(parsed_cfg, expected)
+
+ def test_partial_config_dict_with_commments(self):
+
+ cfg_name = self.get_cfg_file(test_config_two)
+ parsed_cfg = turtle.config_dict(cfg_name)
+
+ expected = {
+ 'pencolor': 'red',
+ 'fillcolor': 'blue',
+ 'visible': False,
+ 'language': 'english',
+ 'using_IDLE': False,
+ }
+
+ self.assertEqual(parsed_cfg, expected)
+
+ def test_config_dict_invalid(self):
+
+ cfg_name = self.get_cfg_file(invalid_test_config)
+
+ with support.captured_stdout() as stdout:
+ parsed_cfg = turtle.config_dict(cfg_name)
+
+ err_msg = stdout.getvalue()
+
+ self.assertIn('Bad line in config-file ', err_msg)
+ self.assertIn('fillcolor: blue', err_msg)
+
+ self.assertEqual(parsed_cfg, {
+ 'pencolor': 'red',
+ 'visible': False,
+ })
+
+
+class VectorComparisonMixin:
+
+ def assertVectorsAlmostEqual(self, vec1, vec2):
+ if len(vec1) != len(vec2):
+ self.fail("Tuples are not of equal size")
+ for idx, (i, j) in enumerate(zip(vec1, vec2)):
+ self.assertAlmostEqual(
+ i, j, msg='values at index {} do not match'.format(idx))
+
+
+class TestVec2D(VectorComparisonMixin, unittest.TestCase):
+
+ def test_constructor(self):
+ vec = Vec2D(0.5, 2)
+ self.assertEqual(vec[0], 0.5)
+ self.assertEqual(vec[1], 2)
+ self.assertIsInstance(vec, Vec2D)
+
+ self.assertRaises(TypeError, Vec2D)
+ self.assertRaises(TypeError, Vec2D, 0)
+ self.assertRaises(TypeError, Vec2D, (0, 1))
+ self.assertRaises(TypeError, Vec2D, vec)
+ self.assertRaises(TypeError, Vec2D, 0, 1, 2)
+
+ def test_repr(self):
+ vec = Vec2D(0.567, 1.234)
+ self.assertEqual(repr(vec), '(0.57,1.23)')
+
+ def test_equality(self):
+ vec1 = Vec2D(0, 1)
+ vec2 = Vec2D(0.0, 1)
+ vec3 = Vec2D(42, 1)
+ self.assertEqual(vec1, vec2)
+ self.assertEqual(vec1, tuple(vec1))
+ self.assertEqual(tuple(vec1), vec1)
+ self.assertNotEqual(vec1, vec3)
+ self.assertNotEqual(vec2, vec3)
+
+ def test_pickling(self):
+ vec = Vec2D(0.5, 2)
+ for proto in range(pickle.HIGHEST_PROTOCOL + 1):
+ with self.subTest(proto=proto):
+ pickled = pickle.dumps(vec, protocol=proto)
+ unpickled = pickle.loads(pickled)
+ self.assertEqual(unpickled, vec)
+ self.assertIsInstance(unpickled, Vec2D)
+
+ def _assert_arithmetic_cases(self, test_cases, lambda_operator):
+ for test_case in test_cases:
+ with self.subTest(case=test_case):
+
+ ((first, second), expected) = test_case
+
+ op1 = Vec2D(*first)
+ op2 = Vec2D(*second)
+
+ result = lambda_operator(op1, op2)
+
+ expected = Vec2D(*expected)
+
+ self.assertVectorsAlmostEqual(result, expected)
+
+ def test_vector_addition(self):
+
+ test_cases = [
+ (((0, 0), (1, 1)), (1.0, 1.0)),
+ (((-1, 0), (2, 2)), (1, 2)),
+ (((1.5, 0), (1, 1)), (2.5, 1)),
+ ]
+
+ self._assert_arithmetic_cases(test_cases, lambda x, y: x + y)
+
+ def test_vector_subtraction(self):
+
+ test_cases = [
+ (((0, 0), (1, 1)), (-1, -1)),
+ (((10.625, 0.125), (10, 0)), (0.625, 0.125)),
+ ]
+
+ self._assert_arithmetic_cases(test_cases, lambda x, y: x - y)
+
+ def test_vector_multiply(self):
+
+ vec1 = Vec2D(10, 10)
+ vec2 = Vec2D(0.5, 3)
+ answer = vec1 * vec2
+ expected = 35
+ self.assertAlmostEqual(answer, expected)
+
+ vec = Vec2D(0.5, 3)
+ answer = vec * 10
+ expected = Vec2D(5, 30)
+ self.assertVectorsAlmostEqual(answer, expected)
+
+ def test_vector_negative(self):
+ vec = Vec2D(10, -10)
+ expected = (-10, 10)
+ self.assertVectorsAlmostEqual(-vec, expected)
+
+ def test_distance(self):
+ vec = Vec2D(6, 8)
+ expected = 10
+ self.assertEqual(abs(vec), expected)
+
+ vec = Vec2D(0, 0)
+ expected = 0
+ self.assertEqual(abs(vec), expected)
+
+ vec = Vec2D(2.5, 6)
+ expected = 6.5
+ self.assertEqual(abs(vec), expected)
+
+ def test_rotate(self):
+
+ cases = [
+ (((0, 0), 0), (0, 0)),
+ (((0, 1), 90), (-1, 0)),
+ (((0, 1), -90), (1, 0)),
+ (((1, 0), 180), (-1, 0)),
+ (((1, 0), 360), (1, 0)),
+ ]
+
+ for case in cases:
+ with self.subTest(case=case):
+ (vec, rot), expected = case
+ vec = Vec2D(*vec)
+ got = vec.rotate(rot)
+ self.assertVectorsAlmostEqual(got, expected)
+
+
+class TestTNavigator(VectorComparisonMixin, unittest.TestCase):
+
+ def setUp(self):
+ self.nav = turtle.TNavigator()
+
+ def test_goto(self):
+ self.nav.goto(100, -100)
+ self.assertAlmostEqual(self.nav.xcor(), 100)
+ self.assertAlmostEqual(self.nav.ycor(), -100)
+
+ def test_pos(self):
+ self.assertEqual(self.nav.pos(), self.nav._position)
+ self.nav.goto(100, -100)
+ self.assertEqual(self.nav.pos(), self.nav._position)
+
+ def test_left(self):
+ self.assertEqual(self.nav._orient, (1.0, 0))
+ self.nav.left(90)
+ self.assertVectorsAlmostEqual(self.nav._orient, (0.0, 1.0))
+
+ def test_right(self):
+ self.assertEqual(self.nav._orient, (1.0, 0))
+ self.nav.right(90)
+ self.assertVectorsAlmostEqual(self.nav._orient, (0, -1.0))
+
+ def test_reset(self):
+ self.nav.goto(100, -100)
+ self.assertAlmostEqual(self.nav.xcor(), 100)
+ self.assertAlmostEqual(self.nav.ycor(), -100)
+ self.nav.reset()
+ self.assertAlmostEqual(self.nav.xcor(), 0)
+ self.assertAlmostEqual(self.nav.ycor(), 0)
+
+ def test_forward(self):
+ self.nav.forward(150)
+ expected = Vec2D(150, 0)
+ self.assertVectorsAlmostEqual(self.nav.position(), expected)
+
+ self.nav.reset()
+ self.nav.left(90)
+ self.nav.forward(150)
+ expected = Vec2D(0, 150)
+ self.assertVectorsAlmostEqual(self.nav.position(), expected)
+
+ self.assertRaises(TypeError, self.nav.forward, 'skldjfldsk')
+
+ def test_backwards(self):
+ self.nav.back(200)
+ expected = Vec2D(-200, 0)
+ self.assertVectorsAlmostEqual(self.nav.position(), expected)
+
+ self.nav.reset()
+ self.nav.right(90)
+ self.nav.back(200)
+ expected = Vec2D(0, 200)
+ self.assertVectorsAlmostEqual(self.nav.position(), expected)
+
+ def test_distance(self):
+ self.nav.forward(100)
+ expected = 100
+ self.assertAlmostEqual(self.nav.distance(Vec2D(0,0)), expected)
+
+ def test_radians_and_degrees(self):
+ self.nav.left(90)
+ self.assertAlmostEqual(self.nav.heading(), 90)
+ self.nav.radians()
+ self.assertAlmostEqual(self.nav.heading(), 1.57079633)
+ self.nav.degrees()
+ self.assertAlmostEqual(self.nav.heading(), 90)
+
+ def test_towards(self):
+
+ coordinates = [
+ # coordinates, expected
+ ((100, 0), 0.0),
+ ((100, 100), 45.0),
+ ((0, 100), 90.0),
+ ((-100, 100), 135.0),
+ ((-100, 0), 180.0),
+ ((-100, -100), 225.0),
+ ((0, -100), 270.0),
+ ((100, -100), 315.0),
+ ]
+
+ for (x, y), expected in coordinates:
+ self.assertEqual(self.nav.towards(x, y), expected)
+ self.assertEqual(self.nav.towards((x, y)), expected)
+ self.assertEqual(self.nav.towards(Vec2D(x, y)), expected)
+
+ def test_heading(self):
+
+ self.nav.left(90)
+ self.assertAlmostEqual(self.nav.heading(), 90)
+ self.nav.left(45)
+ self.assertAlmostEqual(self.nav.heading(), 135)
+ self.nav.right(1.6)
+ self.assertAlmostEqual(self.nav.heading(), 133.4)
+ self.assertRaises(TypeError, self.nav.right, 'sdkfjdsf')
+ self.nav.reset()
+
+ rotations = [10, 20, 170, 300]
+ result = sum(rotations) % 360
+ for num in rotations:
+ self.nav.left(num)
+ self.assertEqual(self.nav.heading(), result)
+ self.nav.reset()
+
+ result = (360-sum(rotations)) % 360
+ for num in rotations:
+ self.nav.right(num)
+ self.assertEqual(self.nav.heading(), result)
+ self.nav.reset()
+
+ rotations = [10, 20, -170, 300, -210, 34.3, -50.2, -10, -29.98, 500]
+ sum_so_far = 0
+ for num in rotations:
+ if num < 0:
+ self.nav.right(abs(num))
+ else:
+ self.nav.left(num)
+ sum_so_far += num
+ self.assertAlmostEqual(self.nav.heading(), sum_so_far % 360)
+
+ def test_setheading(self):
+ self.nav.setheading(102.32)
+ self.assertAlmostEqual(self.nav.heading(), 102.32)
+ self.nav.setheading(-123.23)
+ self.assertAlmostEqual(self.nav.heading(), (-123.23) % 360)
+ self.nav.setheading(-1000.34)
+ self.assertAlmostEqual(self.nav.heading(), (-1000.34) % 360)
+ self.nav.setheading(300000)
+ self.assertAlmostEqual(self.nav.heading(), 300000%360)
+
+ def test_positions(self):
+ self.nav.forward(100)
+ self.nav.left(90)
+ self.nav.forward(-200)
+ self.assertVectorsAlmostEqual(self.nav.pos(), (100.0, -200.0))
+
+ def test_setx_and_sety(self):
+ self.nav.setx(-1023.2334)
+ self.nav.sety(193323.234)
+ self.assertVectorsAlmostEqual(self.nav.pos(), (-1023.2334, 193323.234))
+
+ def test_home(self):
+ self.nav.left(30)
+ self.nav.forward(-100000)
+ self.nav.home()
+ self.assertVectorsAlmostEqual(self.nav.pos(), (0,0))
+ self.assertAlmostEqual(self.nav.heading(), 0)
+
+ def test_distance_method(self):
+ self.assertAlmostEqual(self.nav.distance(30, 40), 50)
+ vec = Vec2D(0.22, .001)
+ self.assertAlmostEqual(self.nav.distance(vec), 0.22000227271553355)
+ another_turtle = turtle.TNavigator()
+ another_turtle.left(90)
+ another_turtle.forward(10000)
+ self.assertAlmostEqual(self.nav.distance(another_turtle), 10000)
+
+
+class TestTPen(unittest.TestCase):
+
+ def test_pendown_and_penup(self):
+
+ tpen = turtle.TPen()
+
+ self.assertTrue(tpen.isdown())
+ tpen.penup()
+ self.assertFalse(tpen.isdown())
+ tpen.pendown()
+ self.assertTrue(tpen.isdown())
+
+ def test_showturtle_hideturtle_and_isvisible(self):
+
+ tpen = turtle.TPen()
+
+ self.assertTrue(tpen.isvisible())
+ tpen.hideturtle()
+ self.assertFalse(tpen.isvisible())
+ tpen.showturtle()
+ self.assertTrue(tpen.isvisible())
+
+
+if __name__ == '__main__':
+ unittest.main()
+import contextlib
+import collections
import pickle
import re
import sys
-from unittest import TestCase, main
+from unittest import TestCase, main, skipUnless, SkipTest
from typing import Any
from typing import TypeVar, AnyStr
from typing import cast
from typing import get_type_hints
from typing import no_type_check, no_type_check_decorator
+from typing import Type
+from typing import NewType
from typing import NamedTuple
from typing import IO, TextIO, BinaryIO
from typing import Pattern, Match
import typing
+class BaseTestCase(TestCase):
+
+ def assertIsSubclass(self, cls, class_or_tuple, msg=None):
+ if not issubclass(cls, class_or_tuple):
+ message = '%r is not a subclass of %r' % (cls, class_or_tuple)
+ if msg is not None:
+ message += ' : %s' % msg
+ raise self.failureException(message)
+
+ def assertNotIsSubclass(self, cls, class_or_tuple, msg=None):
+ if issubclass(cls, class_or_tuple):
+ message = '%r is a subclass of %r' % (cls, class_or_tuple)
+ if msg is not None:
+ message += ' : %s' % msg
+ raise self.failureException(message)
+
+
class Employee:
pass
pass
-class AnyTests(TestCase):
+class AnyTests(BaseTestCase):
def test_any_instance_type_error(self):
with self.assertRaises(TypeError):
def test_any_is_subclass(self):
# Any should be considered a subclass of everything.
- assert issubclass(Any, Any)
- assert issubclass(Any, typing.List)
- assert issubclass(Any, typing.List[int])
- assert issubclass(Any, typing.List[T])
- assert issubclass(Any, typing.Mapping)
- assert issubclass(Any, typing.Mapping[str, int])
- assert issubclass(Any, typing.Mapping[KT, VT])
- assert issubclass(Any, Generic)
- assert issubclass(Any, Generic[T])
- assert issubclass(Any, Generic[KT, VT])
- assert issubclass(Any, AnyStr)
- assert issubclass(Any, Union)
- assert issubclass(Any, Union[int, str])
- assert issubclass(Any, typing.Match)
- assert issubclass(Any, typing.Match[str])
+ self.assertIsSubclass(Any, Any)
+ self.assertIsSubclass(Any, typing.List)
+ self.assertIsSubclass(Any, typing.List[int])
+ self.assertIsSubclass(Any, typing.List[T])
+ self.assertIsSubclass(Any, typing.Mapping)
+ self.assertIsSubclass(Any, typing.Mapping[str, int])
+ self.assertIsSubclass(Any, typing.Mapping[KT, VT])
+ self.assertIsSubclass(Any, Generic)
+ self.assertIsSubclass(Any, Generic[T])
+ self.assertIsSubclass(Any, Generic[KT, VT])
+ self.assertIsSubclass(Any, AnyStr)
+ self.assertIsSubclass(Any, Union)
+ self.assertIsSubclass(Any, Union[int, str])
+ self.assertIsSubclass(Any, typing.Match)
+ self.assertIsSubclass(Any, typing.Match[str])
# These expressions must simply not fail.
typing.Match[Any]
typing.Pattern[Any]
typing.IO[Any]
-class TypeVarTests(TestCase):
+class TypeVarTests(BaseTestCase):
def test_basic_plain(self):
T = TypeVar('T')
# Every class is a subclass of T.
- assert issubclass(int, T)
- assert issubclass(str, T)
+ self.assertIsSubclass(int, T)
+ self.assertIsSubclass(str, T)
# T equals itself.
- assert T == T
+ self.assertEqual(T, T)
# T is a subclass of itself.
- assert issubclass(T, T)
+ self.assertIsSubclass(T, T)
# T is an instance of TypeVar
- assert isinstance(T, TypeVar)
+ self.assertIsInstance(T, TypeVar)
def test_typevar_instance_type_error(self):
T = TypeVar('T')
def test_basic_constrained(self):
A = TypeVar('A', str, bytes)
# Only str and bytes are subclasses of A.
- assert issubclass(str, A)
- assert issubclass(bytes, A)
- assert not issubclass(int, A)
+ self.assertIsSubclass(str, A)
+ self.assertIsSubclass(bytes, A)
+ self.assertNotIsSubclass(int, A)
# A equals itself.
- assert A == A
+ self.assertEqual(A, A)
# A is a subclass of itself.
- assert issubclass(A, A)
+ self.assertIsSubclass(A, A)
def test_constrained_error(self):
with self.assertRaises(TypeError):
X = TypeVar('X', int)
+ X
def test_union_unique(self):
X = TypeVar('X')
Y = TypeVar('Y')
- assert X != Y
- assert Union[X] == X
- assert Union[X] != Union[X, Y]
- assert Union[X, X] == X
- assert Union[X, int] != Union[X]
- assert Union[X, int] != Union[int]
- assert Union[X, int].__union_params__ == (X, int)
- assert Union[X, int].__union_set_params__ == {X, int}
+ self.assertNotEqual(X, Y)
+ self.assertEqual(Union[X], X)
+ self.assertNotEqual(Union[X], Union[X, Y])
+ self.assertEqual(Union[X, X], X)
+ self.assertNotEqual(Union[X, int], Union[X])
+ self.assertNotEqual(Union[X, int], Union[int])
+ self.assertEqual(Union[X, int].__union_params__, (X, int))
+ self.assertEqual(Union[X, int].__union_set_params__, {X, int})
def test_union_constrained(self):
A = TypeVar('A', str, bytes)
- assert Union[A, str] != Union[A]
+ self.assertNotEqual(Union[A, str], Union[A])
def test_repr(self):
self.assertEqual(repr(T), '~T')
def test_bound(self):
X = TypeVar('X', bound=Employee)
- assert issubclass(Employee, X)
- assert issubclass(Manager, X)
- assert not issubclass(int, X)
+ self.assertIsSubclass(Employee, X)
+ self.assertIsSubclass(Manager, X)
+ self.assertNotIsSubclass(int, X)
def test_bound_errors(self):
with self.assertRaises(TypeError):
TypeVar('X', str, float, bound=Employee)
-class UnionTests(TestCase):
+class UnionTests(BaseTestCase):
def test_basics(self):
u = Union[int, float]
Union[()]
def test_issubclass_union(self):
- assert issubclass(Union[int, str], Union)
- assert not issubclass(int, Union)
+ self.assertIsSubclass(Union[int, str], Union)
+ self.assertNotIsSubclass(int, Union)
def test_union_instance_type_error(self):
with self.assertRaises(TypeError):
def test_union_str_pattern(self):
# Shouldn't crash; see http://bugs.python.org/issue25390
A = Union[str, Pattern]
+ A
+
+ def test_etree(self):
+ # See https://github.com/python/typing/issues/229
+ # (Only relevant for Python 2.)
+ try:
+ from xml.etree.cElementTree import Element
+ except ImportError:
+ raise SkipTest("cElementTree not found")
+ Union[Element, str] # Shouldn't crash
+
+ def Elem(*args):
+ return Element(*args)
+ Union[Elem, str] # Nor should this
-class TypeVarUnionTests(TestCase):
+
+class TypeVarUnionTests(BaseTestCase):
def test_simpler(self):
A = TypeVar('A', int, str, float)
B = TypeVar('B', int, str)
- assert issubclass(A, A)
- assert issubclass(B, B)
- assert not issubclass(B, A)
- assert issubclass(A, Union[int, str, float])
- assert not issubclass(Union[int, str, float], A)
- assert not issubclass(Union[int, str], B)
- assert issubclass(B, Union[int, str])
- assert not issubclass(A, B)
- assert not issubclass(Union[int, str, float], B)
- assert not issubclass(A, Union[int, str])
+ self.assertIsSubclass(A, A)
+ self.assertIsSubclass(B, B)
+ self.assertNotIsSubclass(B, A)
+ self.assertIsSubclass(A, Union[int, str, float])
+ self.assertNotIsSubclass(Union[int, str, float], A)
+ self.assertNotIsSubclass(Union[int, str], B)
+ self.assertIsSubclass(B, Union[int, str])
+ self.assertNotIsSubclass(A, B)
+ self.assertNotIsSubclass(Union[int, str, float], B)
+ self.assertNotIsSubclass(A, Union[int, str])
def test_var_union_subclass(self):
self.assertTrue(issubclass(T, Union[int, T]))
def test_var_union(self):
TU = TypeVar('TU', Union[int, float], None)
- assert issubclass(int, TU)
- assert issubclass(float, TU)
+ self.assertIsSubclass(int, TU)
+ self.assertIsSubclass(float, TU)
-class TupleTests(TestCase):
+class TupleTests(BaseTestCase):
def test_basics(self):
self.assertTrue(issubclass(Tuple[int, str], Tuple))
self.assertTrue(issubclass(tuple, Tuple))
self.assertFalse(issubclass(Tuple, tuple)) # Can't have it both ways.
+ def test_equality(self):
+ self.assertEqual(Tuple[int], Tuple[int])
+ self.assertEqual(Tuple[int, ...], Tuple[int, ...])
+ self.assertNotEqual(Tuple[int], Tuple[int, int])
+ self.assertNotEqual(Tuple[int], Tuple[int, ...])
+
def test_tuple_subclass(self):
class MyTuple(tuple):
pass
class C(B):
pass
- assert not issubclass(Tuple[B], Tuple[B, ...])
- assert issubclass(Tuple[C, ...], Tuple[B, ...])
- assert not issubclass(Tuple[C, ...], Tuple[B])
- assert not issubclass(Tuple[C], Tuple[B, ...])
+ self.assertNotIsSubclass(Tuple[B], Tuple[B, ...])
+ self.assertIsSubclass(Tuple[C, ...], Tuple[B, ...])
+ self.assertNotIsSubclass(Tuple[C, ...], Tuple[B])
+ self.assertNotIsSubclass(Tuple[C], Tuple[B, ...])
def test_repr(self):
self.assertEqual(repr(Tuple), 'typing.Tuple')
- self.assertEqual(repr(Tuple[()]), 'typing.Tuple[]')
+ self.assertEqual(repr(Tuple[()]), 'typing.Tuple[()]')
self.assertEqual(repr(Tuple[int, float]), 'typing.Tuple[int, float]')
self.assertEqual(repr(Tuple[int, ...]), 'typing.Tuple[int, ...]')
issubclass(42, Tuple[int])
-class CallableTests(TestCase):
+class CallableTests(BaseTestCase):
def test_self_subclass(self):
self.assertTrue(issubclass(Callable[[int], int], Callable))
def test_callable_instance_works(self):
def f():
pass
- assert isinstance(f, Callable)
- assert not isinstance(None, Callable)
+ self.assertIsInstance(f, Callable)
+ self.assertNotIsInstance(None, Callable)
def test_callable_instance_type_error(self):
def f():
pass
with self.assertRaises(TypeError):
- assert isinstance(f, Callable[[], None])
+ self.assertIsInstance(f, Callable[[], None])
with self.assertRaises(TypeError):
- assert isinstance(f, Callable[[], Any])
+ self.assertIsInstance(f, Callable[[], Any])
with self.assertRaises(TypeError):
- assert not isinstance(None, Callable[[], None])
+ self.assertNotIsInstance(None, Callable[[], None])
with self.assertRaises(TypeError):
- assert not isinstance(None, Callable[[], Any])
+ self.assertNotIsInstance(None, Callable[[], Any])
def test_repr(self):
ct0 = Callable[[], bool]
...
-class MySimpleMapping(SimpleMapping):
+class MySimpleMapping(SimpleMapping[XK, XV]):
def __init__(self):
self.store = {}
return default
-class ProtocolTests(TestCase):
+class ProtocolTests(BaseTestCase):
def test_supports_int(self):
- assert issubclass(int, typing.SupportsInt)
- assert not issubclass(str, typing.SupportsInt)
+ self.assertIsSubclass(int, typing.SupportsInt)
+ self.assertNotIsSubclass(str, typing.SupportsInt)
def test_supports_float(self):
- assert issubclass(float, typing.SupportsFloat)
- assert not issubclass(str, typing.SupportsFloat)
+ self.assertIsSubclass(float, typing.SupportsFloat)
+ self.assertNotIsSubclass(str, typing.SupportsFloat)
def test_supports_complex(self):
def __complex__(self):
return 0j
- assert issubclass(C, typing.SupportsComplex)
- assert not issubclass(str, typing.SupportsComplex)
+ self.assertIsSubclass(C, typing.SupportsComplex)
+ self.assertNotIsSubclass(str, typing.SupportsComplex)
def test_supports_bytes(self):
def __bytes__(self):
return b''
- assert issubclass(B, typing.SupportsBytes)
- assert not issubclass(str, typing.SupportsBytes)
+ self.assertIsSubclass(B, typing.SupportsBytes)
+ self.assertNotIsSubclass(str, typing.SupportsBytes)
def test_supports_abs(self):
- assert issubclass(float, typing.SupportsAbs)
- assert issubclass(int, typing.SupportsAbs)
- assert not issubclass(str, typing.SupportsAbs)
+ self.assertIsSubclass(float, typing.SupportsAbs)
+ self.assertIsSubclass(int, typing.SupportsAbs)
+ self.assertNotIsSubclass(str, typing.SupportsAbs)
def test_supports_round(self):
- assert issubclass(float, typing.SupportsRound)
- assert issubclass(int, typing.SupportsRound)
- assert not issubclass(str, typing.SupportsRound)
+ issubclass(float, typing.SupportsRound)
+ self.assertIsSubclass(float, typing.SupportsRound)
+ self.assertIsSubclass(int, typing.SupportsRound)
+ self.assertNotIsSubclass(str, typing.SupportsRound)
def test_reversible(self):
- assert issubclass(list, typing.Reversible)
- assert not issubclass(int, typing.Reversible)
+ self.assertIsSubclass(list, typing.Reversible)
+ self.assertNotIsSubclass(int, typing.Reversible)
def test_protocol_instance_type_error(self):
with self.assertRaises(TypeError):
- isinstance([], typing.Reversible)
+ isinstance(0, typing.SupportsAbs)
-class GenericTests(TestCase):
+class GenericTests(BaseTestCase):
def test_basics(self):
X = SimpleMapping[str, Any]
- Y = SimpleMapping[XK, str]
- X[str, str]
- Y[str, str]
+ self.assertEqual(X.__parameters__, ())
with self.assertRaises(TypeError):
- X[int, str]
+ X[str]
with self.assertRaises(TypeError):
- Y[str, bytes]
+ X[str, str]
+ Y = SimpleMapping[XK, str]
+ self.assertEqual(Y.__parameters__, (XK,))
+ Y[str]
+ with self.assertRaises(TypeError):
+ Y[str, str]
def test_init(self):
T = TypeVar('T')
def test_repr(self):
self.assertEqual(repr(SimpleMapping),
- __name__ + '.' + 'SimpleMapping[~XK, ~XV]')
+ __name__ + '.' + 'SimpleMapping<~XK, ~XV>')
self.assertEqual(repr(MySimpleMapping),
- __name__ + '.' + 'MySimpleMapping[~XK, ~XV]')
+ __name__ + '.' + 'MySimpleMapping<~XK, ~XV>')
+
+ def test_chain_repr(self):
+ T = TypeVar('T')
+ S = TypeVar('S')
+
+ class C(Generic[T]):
+ pass
+
+ X = C[Tuple[S, T]]
+ self.assertEqual(X, C[Tuple[S, T]])
+ self.assertNotEqual(X, C[Tuple[T, S]])
+
+ Y = X[T, int]
+ self.assertEqual(Y, X[T, int])
+ self.assertNotEqual(Y, X[S, int])
+ self.assertNotEqual(Y, X[T, str])
+
+ Z = Y[str]
+ self.assertEqual(Z, Y[str])
+ self.assertNotEqual(Z, Y[int])
+ self.assertNotEqual(Z, Y[T])
+
+ self.assertTrue(str(Z).endswith(
+ '.C<~T>[typing.Tuple[~S, ~T]]<~S, ~T>[~T, int]<~T>[str]'))
def test_dict(self):
T = TypeVar('T')
+
class B(Generic[T]):
pass
+
b = B()
b.foo = 42
self.assertEqual(b.__dict__, {'foo': 42})
+
class C(B[int]):
pass
+
c = C()
c.bar = 'abc'
self.assertEqual(c.__dict__, {'bar': 'abc'})
def test_pickle(self):
+ global C # pickle wants to reference the class by name
T = TypeVar('T')
+
class B(Generic[T]):
pass
- global C # pickle wants to reference the class by name
+
class C(B[int]):
pass
+
c = C()
c.foo = 42
c.bar = 'abc'
class C(Generic[T]):
pass
- assert C.__module__ == __name__
+ self.assertEqual(C.__module__, __name__)
if not PY32:
- assert C.__qualname__ == 'GenericTests.test_repr_2.<locals>.C'
- assert repr(C).split('.')[-1] == 'C[~T]'
+ self.assertEqual(C.__qualname__,
+ 'GenericTests.test_repr_2.<locals>.C')
+ self.assertEqual(repr(C).split('.')[-1], 'C<~T>')
X = C[int]
- assert X.__module__ == __name__
+ self.assertEqual(X.__module__, __name__)
if not PY32:
- assert X.__qualname__ == 'C'
- assert repr(X).split('.')[-1] == 'C[int]'
+ self.assertEqual(X.__qualname__, 'C')
+ self.assertEqual(repr(X).split('.')[-1], 'C<~T>[int]')
class Y(C[int]):
pass
- assert Y.__module__ == __name__
+ self.assertEqual(Y.__module__, __name__)
if not PY32:
- assert Y.__qualname__ == 'GenericTests.test_repr_2.<locals>.Y'
- assert repr(Y).split('.')[-1] == 'Y[int]'
+ self.assertEqual(Y.__qualname__,
+ 'GenericTests.test_repr_2.<locals>.Y')
+ self.assertEqual(repr(Y).split('.')[-1], 'Y')
def test_eq_1(self):
- assert Generic == Generic
- assert Generic[T] == Generic[T]
- assert Generic[KT] != Generic[VT]
+ self.assertEqual(Generic, Generic)
+ self.assertEqual(Generic[T], Generic[T])
+ self.assertNotEqual(Generic[KT], Generic[VT])
def test_eq_2(self):
class B(Generic[T]):
pass
- assert A == A
- assert A != B
- assert A[T] == A[T]
- assert A[T] != B[T]
+ self.assertEqual(A, A)
+ self.assertNotEqual(A, B)
+ self.assertEqual(A[T], A[T])
+ self.assertNotEqual(A[T], B[T])
def test_multiple_inheritance(self):
class B(Generic[KT, T]):
pass
- class C(A, Generic[KT, VT], B):
+ class C(A[T, VT], Generic[VT, T, KT], B[KT, T]):
pass
- assert C.__parameters__ == (T, VT, KT)
+ self.assertEqual(C.__parameters__, (VT, T, KT))
def test_nested(self):
- class G(Generic):
- pass
+ G = Generic
class Visitor(G[T]):
a.set([])
a.append(1)
a.append(42)
- assert a.get() == [1, 42]
+ self.assertEqual(a.get(), [1, 42])
def test_type_erasure(self):
T = TypeVar('T')
a = Node(x)
b = Node[T](x)
c = Node[Any](x)
- assert type(a) is Node
- assert type(b) is Node
- assert type(c) is Node
+ self.assertIs(type(a), Node)
+ self.assertIs(type(b), Node)
+ self.assertIs(type(c), Node)
+ self.assertEqual(a.label, x)
+ self.assertEqual(b.label, x)
+ self.assertEqual(c.label, x)
foo(42)
+ def test_implicit_any(self):
+ T = TypeVar('T')
+
+ class C(Generic[T]):
+ pass
+
+ class D(C):
+ pass
+
+ self.assertEqual(D.__parameters__, ())
-class VarianceTests(TestCase):
+ with self.assertRaises(Exception):
+ D[int]
+ with self.assertRaises(Exception):
+ D[Any]
+ with self.assertRaises(Exception):
+ D[T]
+
+
+class VarianceTests(BaseTestCase):
def test_invariance(self):
# Because of invariance, List[subclass of X] is not a subclass
# of List[X], and ditto for MutableSequence.
- assert not issubclass(typing.List[Manager], typing.List[Employee])
- assert not issubclass(typing.MutableSequence[Manager],
+ self.assertNotIsSubclass(typing.List[Manager], typing.List[Employee])
+ self.assertNotIsSubclass(typing.MutableSequence[Manager],
typing.MutableSequence[Employee])
# It's still reflexive.
- assert issubclass(typing.List[Employee], typing.List[Employee])
- assert issubclass(typing.MutableSequence[Employee],
+ self.assertIsSubclass(typing.List[Employee], typing.List[Employee])
+ self.assertIsSubclass(typing.MutableSequence[Employee],
typing.MutableSequence[Employee])
def test_covariance_tuple(self):
# Check covariace for Tuple (which are really special cases).
- assert issubclass(Tuple[Manager], Tuple[Employee])
- assert not issubclass(Tuple[Employee], Tuple[Manager])
+ self.assertIsSubclass(Tuple[Manager], Tuple[Employee])
+ self.assertNotIsSubclass(Tuple[Employee], Tuple[Manager])
# And pairwise.
- assert issubclass(Tuple[Manager, Manager], Tuple[Employee, Employee])
- assert not issubclass(Tuple[Employee, Employee],
+ self.assertIsSubclass(Tuple[Manager, Manager],
+ Tuple[Employee, Employee])
+ self.assertNotIsSubclass(Tuple[Employee, Employee],
Tuple[Manager, Employee])
# And using ellipsis.
- assert issubclass(Tuple[Manager, ...], Tuple[Employee, ...])
- assert not issubclass(Tuple[Employee, ...], Tuple[Manager, ...])
+ self.assertIsSubclass(Tuple[Manager, ...], Tuple[Employee, ...])
+ self.assertNotIsSubclass(Tuple[Employee, ...], Tuple[Manager, ...])
def test_covariance_sequence(self):
# Check covariance for Sequence (which is just a generic class
# for this purpose, but using a covariant type variable).
- assert issubclass(typing.Sequence[Manager], typing.Sequence[Employee])
- assert not issubclass(typing.Sequence[Employee],
+ self.assertIsSubclass(typing.Sequence[Manager],
+ typing.Sequence[Employee])
+ self.assertNotIsSubclass(typing.Sequence[Employee],
typing.Sequence[Manager])
def test_covariance_mapping(self):
# Ditto for Mapping (covariant in the value, invariant in the key).
- assert issubclass(typing.Mapping[Employee, Manager],
+ self.assertIsSubclass(typing.Mapping[Employee, Manager],
typing.Mapping[Employee, Employee])
- assert not issubclass(typing.Mapping[Manager, Employee],
+ self.assertNotIsSubclass(typing.Mapping[Manager, Employee],
typing.Mapping[Employee, Employee])
- assert not issubclass(typing.Mapping[Employee, Manager],
+ self.assertNotIsSubclass(typing.Mapping[Employee, Manager],
typing.Mapping[Manager, Manager])
- assert not issubclass(typing.Mapping[Manager, Employee],
+ self.assertNotIsSubclass(typing.Mapping[Manager, Employee],
typing.Mapping[Manager, Manager])
-class CastTests(TestCase):
+class CastTests(BaseTestCase):
def test_basics(self):
- assert cast(int, 42) == 42
- assert cast(float, 42) == 42
- assert type(cast(float, 42)) is int
- assert cast(Any, 42) == 42
- assert cast(list, 42) == 42
- assert cast(Union[str, float], 42) == 42
- assert cast(AnyStr, 42) == 42
- assert cast(None, 42) == 42
+ self.assertEqual(cast(int, 42), 42)
+ self.assertEqual(cast(float, 42), 42)
+ self.assertIs(type(cast(float, 42)), int)
+ self.assertEqual(cast(Any, 42), 42)
+ self.assertEqual(cast(list, 42), 42)
+ self.assertEqual(cast(Union[str, float], 42), 42)
+ self.assertEqual(cast(AnyStr, 42), 42)
+ self.assertEqual(cast(None, 42), 42)
def test_errors(self):
# Bogus calls are not expected to fail.
cast('hello', 42)
-class ForwardRefTests(TestCase):
+class ForwardRefTests(BaseTestCase):
def test_basics(self):
t = Node[int]
both_hints = get_type_hints(t.add_both, globals(), locals())
- assert both_hints['left'] == both_hints['right'] == Optional[Node[T]]
- assert both_hints['stuff'] == Optional[int]
- assert 'blah' not in both_hints
+ self.assertEqual(both_hints['left'], Optional[Node[T]])
+ self.assertEqual(both_hints['right'], Optional[Node[T]])
+ self.assertEqual(both_hints['left'], both_hints['right'])
+ self.assertEqual(both_hints['stuff'], Optional[int])
+ self.assertNotIn('blah', both_hints)
left_hints = get_type_hints(t.add_left, globals(), locals())
- assert left_hints['node'] == Optional[Node[T]]
+ self.assertEqual(left_hints['node'], Optional[Node[T]])
right_hints = get_type_hints(t.add_right, globals(), locals())
- assert right_hints['node'] == Optional[Node[T]]
+ self.assertEqual(right_hints['node'], Optional[Node[T]])
def test_forwardref_instance_type_error(self):
fr = typing._ForwardRef('int')
ns = {}
exec(code, ns)
hints = get_type_hints(ns['C'].foo)
- assert hints == {'a': ns['C'], 'return': ns['D']}
+ self.assertEqual(hints, {'a': ns['C'], 'return': ns['D']})
-class OverloadTests(TestCase):
+class OverloadTests(BaseTestCase):
def test_overload_exists(self):
from typing import overload
from typing import overload
with self.assertRaises(RuntimeError):
+
@overload
def blah():
pass
+ blah()
+
+ def test_overload_succeeds(self):
+ from typing import overload
+
+ @overload
+ def blah():
+ pass
+
+ def blah():
+ pass
+
+ blah()
+
+
+PY35 = sys.version_info[:2] >= (3, 5)
-class CollectionsAbcTests(TestCase):
+PY35_TESTS = """
+import asyncio
+
+T_a = TypeVar('T')
+
+class AwaitableWrapper(typing.Awaitable[T_a]):
+
+ def __init__(self, value):
+ self.value = value
+
+ def __await__(self) -> typing.Iterator[T_a]:
+ yield
+ return self.value
+
+class AsyncIteratorWrapper(typing.AsyncIterator[T_a]):
+
+ def __init__(self, value: typing.Iterable[T_a]):
+ self.value = value
+
+ def __aiter__(self) -> typing.AsyncIterator[T_a]:
+ return self
+
+ @asyncio.coroutine
+ def __anext__(self) -> T_a:
+ data = yield from self.value
+ if data:
+ return data
+ else:
+ raise StopAsyncIteration
+"""
+
+if PY35:
+ exec(PY35_TESTS)
+
+
+class CollectionsAbcTests(BaseTestCase):
def test_hashable(self):
- assert isinstance(42, typing.Hashable)
- assert not isinstance([], typing.Hashable)
+ self.assertIsInstance(42, typing.Hashable)
+ self.assertNotIsInstance([], typing.Hashable)
def test_iterable(self):
- assert isinstance([], typing.Iterable)
+ self.assertIsInstance([], typing.Iterable)
# Due to ABC caching, the second time takes a separate code
# path and could fail. So call this a few times.
- assert isinstance([], typing.Iterable)
- assert isinstance([], typing.Iterable)
- assert isinstance([], typing.Iterable[int])
- assert not isinstance(42, typing.Iterable)
+ self.assertIsInstance([], typing.Iterable)
+ self.assertIsInstance([], typing.Iterable)
+ self.assertIsInstance([], typing.Iterable[int])
+ self.assertNotIsInstance(42, typing.Iterable)
# Just in case, also test issubclass() a few times.
- assert issubclass(list, typing.Iterable)
- assert issubclass(list, typing.Iterable)
+ self.assertIsSubclass(list, typing.Iterable)
+ self.assertIsSubclass(list, typing.Iterable)
def test_iterator(self):
it = iter([])
- assert isinstance(it, typing.Iterator)
- assert isinstance(it, typing.Iterator[int])
- assert not isinstance(42, typing.Iterator)
+ self.assertIsInstance(it, typing.Iterator)
+ self.assertIsInstance(it, typing.Iterator[int])
+ self.assertNotIsInstance(42, typing.Iterator)
+
+ @skipUnless(PY35, 'Python 3.5 required')
+ def test_awaitable(self):
+ ns = {}
+ exec(
+ "async def foo() -> typing.Awaitable[int]:\n"
+ " return await AwaitableWrapper(42)\n",
+ globals(), ns)
+ foo = ns['foo']
+ g = foo()
+ self.assertIsSubclass(type(g), typing.Awaitable[int])
+ self.assertIsInstance(g, typing.Awaitable)
+ self.assertNotIsInstance(foo, typing.Awaitable)
+ self.assertIsSubclass(typing.Awaitable[Manager],
+ typing.Awaitable[Employee])
+ self.assertNotIsSubclass(typing.Awaitable[Employee],
+ typing.Awaitable[Manager])
+ g.send(None) # Run foo() till completion, to avoid warning.
+
+ @skipUnless(PY35, 'Python 3.5 required')
+ def test_async_iterable(self):
+ base_it = range(10) # type: Iterator[int]
+ it = AsyncIteratorWrapper(base_it)
+ self.assertIsInstance(it, typing.AsyncIterable)
+ self.assertIsInstance(it, typing.AsyncIterable)
+ self.assertIsSubclass(typing.AsyncIterable[Manager],
+ typing.AsyncIterable[Employee])
+ self.assertNotIsInstance(42, typing.AsyncIterable)
+
+ @skipUnless(PY35, 'Python 3.5 required')
+ def test_async_iterator(self):
+ base_it = range(10) # type: Iterator[int]
+ it = AsyncIteratorWrapper(base_it)
+ self.assertIsInstance(it, typing.AsyncIterator)
+ self.assertIsSubclass(typing.AsyncIterator[Manager],
+ typing.AsyncIterator[Employee])
+ self.assertNotIsInstance(42, typing.AsyncIterator)
def test_sized(self):
- assert isinstance([], typing.Sized)
- assert not isinstance(42, typing.Sized)
+ self.assertIsInstance([], typing.Sized)
+ self.assertNotIsInstance(42, typing.Sized)
def test_container(self):
- assert isinstance([], typing.Container)
- assert not isinstance(42, typing.Container)
+ self.assertIsInstance([], typing.Container)
+ self.assertNotIsInstance(42, typing.Container)
def test_abstractset(self):
- assert isinstance(set(), typing.AbstractSet)
- assert not isinstance(42, typing.AbstractSet)
+ self.assertIsInstance(set(), typing.AbstractSet)
+ self.assertNotIsInstance(42, typing.AbstractSet)
def test_mutableset(self):
- assert isinstance(set(), typing.MutableSet)
- assert not isinstance(frozenset(), typing.MutableSet)
+ self.assertIsInstance(set(), typing.MutableSet)
+ self.assertNotIsInstance(frozenset(), typing.MutableSet)
def test_mapping(self):
- assert isinstance({}, typing.Mapping)
- assert not isinstance(42, typing.Mapping)
+ self.assertIsInstance({}, typing.Mapping)
+ self.assertNotIsInstance(42, typing.Mapping)
def test_mutablemapping(self):
- assert isinstance({}, typing.MutableMapping)
- assert not isinstance(42, typing.MutableMapping)
+ self.assertIsInstance({}, typing.MutableMapping)
+ self.assertNotIsInstance(42, typing.MutableMapping)
def test_sequence(self):
- assert isinstance([], typing.Sequence)
- assert not isinstance(42, typing.Sequence)
+ self.assertIsInstance([], typing.Sequence)
+ self.assertNotIsInstance(42, typing.Sequence)
def test_mutablesequence(self):
- assert isinstance([], typing.MutableSequence)
- assert not isinstance((), typing.MutableSequence)
+ self.assertIsInstance([], typing.MutableSequence)
+ self.assertNotIsInstance((), typing.MutableSequence)
def test_bytestring(self):
- assert isinstance(b'', typing.ByteString)
- assert isinstance(bytearray(b''), typing.ByteString)
+ self.assertIsInstance(b'', typing.ByteString)
+ self.assertIsInstance(bytearray(b''), typing.ByteString)
def test_list(self):
- assert issubclass(list, typing.List)
+ self.assertIsSubclass(list, typing.List)
def test_set(self):
- assert issubclass(set, typing.Set)
- assert not issubclass(frozenset, typing.Set)
+ self.assertIsSubclass(set, typing.Set)
+ self.assertNotIsSubclass(frozenset, typing.Set)
def test_frozenset(self):
- assert issubclass(frozenset, typing.FrozenSet)
- assert not issubclass(set, typing.FrozenSet)
+ self.assertIsSubclass(frozenset, typing.FrozenSet)
+ self.assertNotIsSubclass(set, typing.FrozenSet)
def test_dict(self):
- assert issubclass(dict, typing.Dict)
+ self.assertIsSubclass(dict, typing.Dict)
def test_no_list_instantiation(self):
with self.assertRaises(TypeError):
with self.assertRaises(TypeError):
typing.List[int]()
- def test_list_subclass_instantiation(self):
+ def test_list_subclass(self):
class MyList(typing.List[int]):
pass
a = MyList()
- assert isinstance(a, MyList)
+ self.assertIsInstance(a, MyList)
+ self.assertIsInstance(a, typing.Sequence)
+
+ self.assertIsSubclass(MyList, list)
+ self.assertNotIsSubclass(list, MyList)
def test_no_dict_instantiation(self):
with self.assertRaises(TypeError):
with self.assertRaises(TypeError):
typing.Dict[str, int]()
- def test_dict_subclass_instantiation(self):
+ def test_dict_subclass(self):
class MyDict(typing.Dict[str, int]):
pass
d = MyDict()
- assert isinstance(d, MyDict)
+ self.assertIsInstance(d, MyDict)
+ self.assertIsInstance(d, typing.MutableMapping)
+
+ self.assertIsSubclass(MyDict, dict)
+ self.assertNotIsSubclass(dict, MyDict)
+
+ def test_no_defaultdict_instantiation(self):
+ with self.assertRaises(TypeError):
+ typing.DefaultDict()
+ with self.assertRaises(TypeError):
+ typing.DefaultDict[KT, VT]()
+ with self.assertRaises(TypeError):
+ typing.DefaultDict[str, int]()
+
+ def test_defaultdict_subclass(self):
+
+ class MyDefDict(typing.DefaultDict[str, int]):
+ pass
+
+ dd = MyDefDict()
+ self.assertIsInstance(dd, MyDefDict)
+
+ self.assertIsSubclass(MyDefDict, collections.defaultdict)
+ self.assertNotIsSubclass(collections.defaultdict, MyDefDict)
def test_no_set_instantiation(self):
with self.assertRaises(TypeError):
pass
d = MySet()
- assert isinstance(d, MySet)
+ self.assertIsInstance(d, MySet)
def test_no_frozenset_instantiation(self):
with self.assertRaises(TypeError):
pass
d = MyFrozenSet()
- assert isinstance(d, MyFrozenSet)
+ self.assertIsInstance(d, MyFrozenSet)
def test_no_tuple_instantiation(self):
with self.assertRaises(TypeError):
def foo():
yield 42
g = foo()
- assert issubclass(type(g), typing.Generator)
- assert issubclass(typing.Generator[Manager, Employee, Manager],
+ self.assertIsSubclass(type(g), typing.Generator)
+ self.assertIsSubclass(typing.Generator[Manager, Employee, Manager],
typing.Generator[Employee, Manager, Employee])
- assert not issubclass(typing.Generator[Manager, Manager, Manager],
+ self.assertNotIsSubclass(typing.Generator[Manager, Manager, Manager],
typing.Generator[Employee, Employee, Employee])
def test_no_generator_instantiation(self):
def __len__(self):
return 0
- assert len(MMC()) == 0
+ self.assertEqual(len(MMC()), 0)
class MMB(typing.MutableMapping[KT, VT]):
def __len__(self):
return 0
- assert len(MMB()) == 0
- assert len(MMB[str, str]()) == 0
- assert len(MMB[KT, VT]()) == 0
+ self.assertEqual(len(MMB()), 0)
+ self.assertEqual(len(MMB[str, str]()), 0)
+ self.assertEqual(len(MMB[KT, VT]()), 0)
+
+ self.assertNotIsSubclass(dict, MMA)
+ self.assertNotIsSubclass(dict, MMB)
+
+ self.assertIsSubclass(MMA, typing.Mapping)
+ self.assertIsSubclass(MMB, typing.Mapping)
+ self.assertIsSubclass(MMC, typing.Mapping)
+
+
+class OtherABCTests(BaseTestCase):
+
+ @skipUnless(hasattr(typing, 'ContextManager'),
+ 'requires typing.ContextManager')
+ def test_contextmanager(self):
+ @contextlib.contextmanager
+ def manager():
+ yield 42
+
+ cm = manager()
+ self.assertIsInstance(cm, typing.ContextManager)
+ self.assertIsInstance(cm, typing.ContextManager[int])
+ self.assertNotIsInstance(42, typing.ContextManager)
+
+
+class TypeTests(BaseTestCase):
+
+ def test_type_basic(self):
+
+ class User: pass
+ class BasicUser(User): pass
+ class ProUser(User): pass
+
+ def new_user(user_class: Type[User]) -> User:
+ return user_class()
+
+ joe = new_user(BasicUser)
+
+ def test_type_typevar(self):
+
+ class User: pass
+ class BasicUser(User): pass
+ class ProUser(User): pass
+
+ U = TypeVar('U', bound=User)
+
+ def new_user(user_class: Type[U]) -> U:
+ return user_class()
+
+ joe = new_user(BasicUser)
+
+
+class NewTypeTests(BaseTestCase):
+
+ def test_basic(self):
+ UserId = NewType('UserId', int)
+ UserName = NewType('UserName', str)
+ self.assertIsInstance(UserId(5), int)
+ self.assertIsInstance(UserName('Joe'), str)
+ self.assertEqual(UserId(5) + 1, 6)
+
+ def test_errors(self):
+ UserId = NewType('UserId', int)
+ UserName = NewType('UserName', str)
+ with self.assertRaises(TypeError):
+ issubclass(UserId, int)
+ with self.assertRaises(TypeError):
+ class D(UserName):
+ pass
-class NamedTupleTests(TestCase):
+class NamedTupleTests(BaseTestCase):
def test_basics(self):
Emp = NamedTuple('Emp', [('name', str), ('id', int)])
- assert issubclass(Emp, tuple)
+ self.assertIsSubclass(Emp, tuple)
joe = Emp('Joe', 42)
jim = Emp(name='Jim', id=1)
- assert isinstance(joe, Emp)
- assert isinstance(joe, tuple)
- assert joe.name == 'Joe'
- assert joe.id == 42
- assert jim.name == 'Jim'
- assert jim.id == 1
- assert Emp.__name__ == 'Emp'
- assert Emp._fields == ('name', 'id')
- assert Emp._field_types == dict(name=str, id=int)
+ self.assertIsInstance(joe, Emp)
+ self.assertIsInstance(joe, tuple)
+ self.assertEqual(joe.name, 'Joe')
+ self.assertEqual(joe.id, 42)
+ self.assertEqual(jim.name, 'Jim')
+ self.assertEqual(jim.id, 1)
+ self.assertEqual(Emp.__name__, 'Emp')
+ self.assertEqual(Emp._fields, ('name', 'id'))
+ self.assertEqual(Emp._field_types, dict(name=str, id=int))
def test_pickle(self):
global Emp # pickle wants to reference the class by name
self.assertEqual(jane2, jane)
-class IOTests(TestCase):
+class IOTests(BaseTestCase):
def test_io(self):
return a.readline()
a = stuff.__annotations__['a']
- assert a.__parameters__ == (AnyStr,)
+ self.assertEqual(a.__parameters__, (AnyStr,))
def test_textio(self):
return a.readline()
a = stuff.__annotations__['a']
- assert a.__parameters__ == (str,)
+ self.assertEqual(a.__parameters__, ())
def test_binaryio(self):
return a.readline()
a = stuff.__annotations__['a']
- assert a.__parameters__ == (bytes,)
+ self.assertEqual(a.__parameters__, ())
def test_io_submodule(self):
from typing.io import IO, TextIO, BinaryIO, __all__, __name__
- assert IO is typing.IO
- assert TextIO is typing.TextIO
- assert BinaryIO is typing.BinaryIO
- assert set(__all__) == set(['IO', 'TextIO', 'BinaryIO'])
- assert __name__ == 'typing.io'
+ self.assertIs(IO, typing.IO)
+ self.assertIs(TextIO, typing.TextIO)
+ self.assertIs(BinaryIO, typing.BinaryIO)
+ self.assertEqual(set(__all__), set(['IO', 'TextIO', 'BinaryIO']))
+ self.assertEqual(__name__, 'typing.io')
-class RETests(TestCase):
+class RETests(BaseTestCase):
# Much of this is really testing _TypeAlias.
def test_basics(self):
pat = re.compile('[a-z]+', re.I)
- assert issubclass(pat.__class__, Pattern)
- assert issubclass(type(pat), Pattern)
- assert issubclass(type(pat), Pattern[str])
+ self.assertIsSubclass(pat.__class__, Pattern)
+ self.assertIsSubclass(type(pat), Pattern)
+ self.assertIsSubclass(type(pat), Pattern[str])
mat = pat.search('12345abcde.....')
- assert issubclass(mat.__class__, Match)
- assert issubclass(mat.__class__, Match[str])
- assert issubclass(mat.__class__, Match[bytes]) # Sad but true.
- assert issubclass(type(mat), Match)
- assert issubclass(type(mat), Match[str])
+ self.assertIsSubclass(mat.__class__, Match)
+ self.assertIsSubclass(mat.__class__, Match[str])
+ self.assertIsSubclass(mat.__class__, Match[bytes]) # Sad but true.
+ self.assertIsSubclass(type(mat), Match)
+ self.assertIsSubclass(type(mat), Match[str])
p = Pattern[Union[str, bytes]]
- assert issubclass(Pattern[str], Pattern)
- assert issubclass(Pattern[str], p)
+ self.assertIsSubclass(Pattern[str], Pattern)
+ self.assertIsSubclass(Pattern[str], p)
m = Match[Union[bytes, str]]
- assert issubclass(Match[bytes], Match)
- assert issubclass(Match[bytes], m)
+ self.assertIsSubclass(Match[bytes], Match)
+ self.assertIsSubclass(Match[bytes], m)
def test_errors(self):
with self.assertRaises(TypeError):
isinstance(42, Pattern[str])
def test_repr(self):
- assert repr(Pattern) == 'Pattern[~AnyStr]'
- assert repr(Pattern[str]) == 'Pattern[str]'
- assert repr(Pattern[bytes]) == 'Pattern[bytes]'
- assert repr(Match) == 'Match[~AnyStr]'
- assert repr(Match[str]) == 'Match[str]'
- assert repr(Match[bytes]) == 'Match[bytes]'
+ self.assertEqual(repr(Pattern), 'Pattern[~AnyStr]')
+ self.assertEqual(repr(Pattern[str]), 'Pattern[str]')
+ self.assertEqual(repr(Pattern[bytes]), 'Pattern[bytes]')
+ self.assertEqual(repr(Match), 'Match[~AnyStr]')
+ self.assertEqual(repr(Match[str]), 'Match[str]')
+ self.assertEqual(repr(Match[bytes]), 'Match[bytes]')
def test_re_submodule(self):
from typing.re import Match, Pattern, __all__, __name__
- assert Match is typing.Match
- assert Pattern is typing.Pattern
- assert set(__all__) == set(['Match', 'Pattern'])
- assert __name__ == 'typing.re'
+ self.assertIs(Match, typing.Match)
+ self.assertIs(Pattern, typing.Pattern)
+ self.assertEqual(set(__all__), set(['Match', 'Pattern']))
+ self.assertEqual(__name__, 'typing.re')
def test_cannot_subclass(self):
with self.assertRaises(TypeError) as ex:
class A(typing.Match):
pass
- assert str(ex.exception) == "A type alias cannot be subclassed"
+ self.assertEqual(str(ex.exception),
+ "A type alias cannot be subclassed")
-class AllTests(TestCase):
+class AllTests(BaseTestCase):
"""Tests for __all__."""
def test_all(self):
from typing import __all__ as a
# Just spot-check the first and last of every category.
- assert 'AbstractSet' in a
- assert 'ValuesView' in a
- assert 'cast' in a
- assert 'overload' in a
- assert 'io' in a
- assert 're' in a
+ self.assertIn('AbstractSet', a)
+ self.assertIn('ValuesView', a)
+ self.assertIn('cast', a)
+ self.assertIn('overload', a)
+ if hasattr(contextlib, 'AbstractContextManager'):
+ self.assertIn('ContextManager', a)
+ # Check that io and re are not exported.
+ self.assertNotIn('io', a)
+ self.assertNotIn('re', a)
# Spot-check that stdlib modules aren't exported.
- assert 'os' not in a
- assert 'sys' not in a
+ self.assertNotIn('os', a)
+ self.assertNotIn('sys', a)
+ # Check that Text is defined.
+ self.assertIn('Text', a)
if __name__ == '__main__':
"""
return text.encode().decode()
+class StrSubclass(str):
+ pass
+
class UnicodeTest(string_tests.CommonTest,
string_tests.MixinStrUnicodeUserStringTest,
string_tests.MixinStrUnicodeTest,
"[XXX]")
self.assertEqual("[a]".translate(str.maketrans({'a': '\xe9'})),
"[\xe9]")
+ self.assertEqual('axb'.translate(str.maketrans({'a': None, 'b': '123'})),
+ "x123")
+ self.assertEqual('axb'.translate(str.maketrans({'a': None, 'b': '\xe9'})),
+ "x\xe9")
+
+ # test non-ASCII (don't take the fast-path)
self.assertEqual("[a]".translate(str.maketrans({'a': '<\xe9>'})),
"[<\xe9>]")
self.assertEqual("[\xe9]".translate(str.maketrans({'\xe9': 'a'})),
"[a]")
self.assertEqual("[\xe9]".translate(str.maketrans({'\xe9': None})),
"[]")
+ self.assertEqual("[\xe9]".translate(str.maketrans({'\xe9': '123'})),
+ "[123]")
+ self.assertEqual("[a\xe9]".translate(str.maketrans({'a': '<\u20ac>'})),
+ "[<\u20ac>\xe9]")
# invalid Unicode characters
invalid_char = 0x10ffff+1
def test_split(self):
string_tests.CommonTest.test_split(self)
- # Mixed arguments
- self.checkequalnofix(['a', 'b', 'c', 'd'], 'a//b//c//d', 'split', '//')
- self.checkequalnofix(['a', 'b', 'c', 'd'], 'a//b//c//d', 'split', '//')
- self.checkequalnofix(['endcase ', ''], 'endcase test', 'split', 'test')
# test mixed kinds
for left, right in ('ba', '\u0101\u0100', '\U00010301\U00010300'):
left *= 9
self.assertTrue('\ud800\udc02' < '\ud84d\udc56')
def test_islower(self):
- string_tests.MixinStrUnicodeUserStringTest.test_islower(self)
+ super().test_islower()
self.checkequalnofix(False, '\u1FFc', 'islower')
self.assertFalse('\u2167'.islower())
self.assertTrue('\u2177'.islower())
self.assertFalse('\U0001F46F'.islower())
def test_isupper(self):
- string_tests.MixinStrUnicodeUserStringTest.test_isupper(self)
+ super().test_isupper()
if not sys.platform.startswith('java'):
self.checkequalnofix(False, '\u1FFc', 'isupper')
self.assertTrue('\u2167'.isupper())
self.assertFalse('\U0001F46F'.isupper())
def test_istitle(self):
- string_tests.MixinStrUnicodeUserStringTest.test_istitle(self)
+ super().test_istitle()
self.checkequalnofix(True, '\u1FFc', 'istitle')
self.checkequalnofix(True, 'Greek \u1FFcitlecases ...', 'istitle')
self.assertFalse(ch.istitle(), '{!a} is not title'.format(ch))
def test_isspace(self):
- string_tests.MixinStrUnicodeUserStringTest.test_isspace(self)
+ super().test_isspace()
self.checkequalnofix(True, '\u2000', 'isspace')
self.checkequalnofix(True, '\u200a', 'isspace')
self.checkequalnofix(False, '\u2014', 'isspace')
self.assertFalse(ch.isspace(), '{!a} is not space.'.format(ch))
def test_isalnum(self):
- string_tests.MixinStrUnicodeUserStringTest.test_isalnum(self)
+ super().test_isalnum()
for ch in ['\U00010401', '\U00010427', '\U00010429', '\U0001044E',
'\U0001D7F6', '\U00011066', '\U000104A0', '\U0001F107']:
self.assertTrue(ch.isalnum(), '{!a} is alnum.'.format(ch))
def test_isalpha(self):
- string_tests.MixinStrUnicodeUserStringTest.test_isalpha(self)
+ super().test_isalpha()
self.checkequalnofix(True, '\u1FFc', 'isalpha')
# non-BMP, cased
self.assertTrue('\U00010401'.isalpha())
self.assertTrue(ch.isdecimal(), '{!a} is decimal.'.format(ch))
def test_isdigit(self):
- string_tests.MixinStrUnicodeUserStringTest.test_isdigit(self)
+ super().test_isdigit()
self.checkequalnofix(True, '\u2460', 'isdigit')
self.checkequalnofix(False, '\xbc', 'isdigit')
self.checkequalnofix(True, '\u0660', 'isdigit')
self.assertEqual('A\u0345\u03a3'.capitalize(), 'A\u0345\u03c2')
def test_title(self):
- string_tests.MixinStrUnicodeUserStringTest.test_title(self)
+ super().test_title()
self.assertEqual('\U0001044F'.title(), '\U00010427')
self.assertEqual('\U0001044F\U0001044F'.title(),
'\U00010427\U0001044F')
'unicode remains unicode'
)
- class UnicodeSubclass(str):
- pass
-
for text in ('ascii', '\xe9', '\u20ac', '\U0010FFFF'):
- subclass = UnicodeSubclass(text)
+ subclass = StrSubclass(text)
self.assertEqual(str(subclass), text)
self.assertEqual(len(subclass), len(text))
if text == 'ascii':
def assertCorrectUTF8Decoding(self, seq, res, err):
"""
- Check that an invalid UTF-8 sequence raises an UnicodeDecodeError when
+ Check that an invalid UTF-8 sequence raises a UnicodeDecodeError when
'strict' is used, returns res when 'replace' is used, and that doesn't
return anything when 'ignore' is used.
"""
s = str(StrSubclassToStrSubclass("foo"))
self.assertEqual(s, "foofoo")
self.assertIs(type(s), StrSubclassToStrSubclass)
+ s = StrSubclass(StrSubclassToStrSubclass("foo"))
+ self.assertEqual(s, "foofoo")
+ self.assertIs(type(s), StrSubclass)
def test_unicode_repr(self):
class s1:
# Check that the second call returns the same result
self.assertEqual(getargs_s_hash(s), chr(k).encode() * (i + 1))
+ def test_free_after_iterating(self):
+ support.check_free_after_iterating(self, iter, str)
+ support.check_free_after_iterating(self, reversed, str)
+
class StringModuleTest(unittest.TestCase):
def test_formatter_parser(self):
-"""Regresssion tests for urllib"""
+"""Regresssion tests for what was in Python 2's "urllib" module"""
import urllib.parse
import urllib.request
if proxies is not None:
opener = urllib.request.FancyURLopener(proxies=proxies)
elif not _urlopener:
- with support.check_warnings(
- ('FancyURLopener style of invoking requests is deprecated.',
- DeprecationWarning)):
- opener = urllib.request.FancyURLopener()
+ opener = FancyURLopener()
_urlopener = opener
else:
opener = _urlopener
return opener.open(url, data)
+def FancyURLopener():
+ with support.check_warnings(
+ ('FancyURLopener style of invoking requests is deprecated.',
+ DeprecationWarning)):
+ return urllib.request.FancyURLopener()
+
+
def fakehttp(fakedata):
class FakeSocket(io.BytesIO):
io_refs = 1
# buffer to store data for verification in urlopen tests.
buf = None
- fakesock = FakeSocket(fakedata)
def connect(self):
- self.sock = self.fakesock
+ self.sock = FakeSocket(self.fakedata)
+ type(self).fakesock = self.sock
+ FakeHTTPConnection.fakedata = fakedata
return FakeHTTPConnection
# getproxies_environment use lowered case truncated (no '_proxy') keys
self.assertEqual('localhost', proxies['no'])
# List of no_proxies with space.
- self.env.set('NO_PROXY', 'localhost, anotherdomain.com, newdomain.com')
+ self.env.set('NO_PROXY', 'localhost, anotherdomain.com, newdomain.com:1234')
self.assertTrue(urllib.request.proxy_bypass_environment('anotherdomain.com'))
+ self.assertTrue(urllib.request.proxy_bypass_environment('anotherdomain.com:8888'))
+ self.assertTrue(urllib.request.proxy_bypass_environment('newdomain.com:1234'))
+
+ def test_proxy_bypass_environment_host_match(self):
+ bypass = urllib.request.proxy_bypass_environment
+ self.env.set('NO_PROXY',
+ 'localhost, anotherdomain.com, newdomain.com:1234')
+ self.assertTrue(bypass('localhost'))
+ self.assertTrue(bypass('LocalHost')) # MixedCase
+ self.assertTrue(bypass('LOCALHOST')) # UPPERCASE
+ self.assertTrue(bypass('newdomain.com:1234'))
+ self.assertTrue(bypass('anotherdomain.com:8888'))
+ self.assertTrue(bypass('www.newdomain.com:1234'))
+ self.assertFalse(bypass('prelocalhost'))
+ self.assertFalse(bypass('newdomain.com')) # no port
+ self.assertFalse(bypass('newdomain.com:1235')) # wrong port
+
+class ProxyTests_withOrderedEnv(unittest.TestCase):
+
+ def setUp(self):
+ # We need to test conditions, where variable order _is_ significant
+ self._saved_env = os.environ
+ # Monkey patch os.environ, start with empty fake environment
+ os.environ = collections.OrderedDict()
+
+ def tearDown(self):
+ os.environ = self._saved_env
+
+ def test_getproxies_environment_prefer_lowercase(self):
+ # Test lowercase preference with removal
+ os.environ['no_proxy'] = ''
+ os.environ['No_Proxy'] = 'localhost'
+ self.assertFalse(urllib.request.proxy_bypass_environment('localhost'))
+ self.assertFalse(urllib.request.proxy_bypass_environment('arbitrary'))
+ os.environ['http_proxy'] = ''
+ os.environ['HTTP_PROXY'] = 'http://somewhere:3128'
+ proxies = urllib.request.getproxies_environment()
+ self.assertEqual({}, proxies)
+ # Test lowercase preference of proxy bypass and correct matching including ports
+ os.environ['no_proxy'] = 'localhost, noproxy.com, my.proxy:1234'
+ os.environ['No_Proxy'] = 'xyz.com'
+ self.assertTrue(urllib.request.proxy_bypass_environment('localhost'))
+ self.assertTrue(urllib.request.proxy_bypass_environment('noproxy.com:5678'))
+ self.assertTrue(urllib.request.proxy_bypass_environment('my.proxy:1234'))
+ self.assertFalse(urllib.request.proxy_bypass_environment('my.proxy'))
+ self.assertFalse(urllib.request.proxy_bypass_environment('arbitrary'))
+ # Test lowercase preference with replacement
+ os.environ['http_proxy'] = 'http://somewhere:3128'
+ os.environ['Http_Proxy'] = 'http://somewhereelse:3128'
+ proxies = urllib.request.getproxies_environment()
+ self.assertEqual('http://somewhere:3128', proxies['http'])
class urlopen_HttpTests(unittest.TestCase, FakeHTTPMixin, FakeFTPMixin):
"""Test urlopen() opening a fake http connection."""
Content-Type: text/html; charset=iso-8859-1
''')
try:
- self.assertRaises(urllib.error.HTTPError, urlopen,
- "http://python.org/")
+ msg = "Redirection to url 'file:"
+ with self.assertRaisesRegex(urllib.error.HTTPError, msg):
+ urlopen("http://python.org/")
finally:
self.unfakehttp()
+ def test_redirect_limit_independent(self):
+ # Ticket #12923: make sure independent requests each use their
+ # own retry limit.
+ for i in range(FancyURLopener().maxtries):
+ self.fakehttp(b'''HTTP/1.1 302 Found
+Location: file://guidocomputer.athome.com:/python/license
+Connection: close
+''')
+ try:
+ self.assertRaises(urllib.error.HTTPError, urlopen,
+ "http://something")
+ finally:
+ self.unfakehttp()
+
def test_empty_socket(self):
# urlopen() raises OSError if the underlying socket does not send any
# data. (#1680230)
# proxy config data structure but is testable on all platforms.
from urllib.request import (Request, OpenerDirector, HTTPBasicAuthHandler,
HTTPPasswordMgrWithPriorAuth, _parse_proxy,
- _proxy_bypass_macosx_sysconf)
+ _proxy_bypass_macosx_sysconf,
+ AbstractDigestAuthHandler)
from urllib.parse import urlparse
import urllib.error
import http.client
self.requests = []
def http_open(self, req):
- import email, http.client, copy
+ import email, copy
self.requests.append(copy.deepcopy(req))
if self._count == 0:
self._count = self._count + 1
# Useful for testing the Proxy-Authorization request by verifying the
# properties of httpcon
- def __init__(self):
- urllib.request.AbstractHTTPHandler.__init__(self)
+ def __init__(self, debuglevel=0):
+ urllib.request.AbstractHTTPHandler.__init__(self, debuglevel=debuglevel)
self.httpconn = MockHTTPClass()
def https_open(self, req):
newreq = h.do_request_(req)
self.assertEqual(int(newreq.get_header('Content-length')),16)
+ def test_http_handler_debuglevel(self):
+ o = OpenerDirector()
+ h = MockHTTPSHandler(debuglevel=1)
+ o.add_handler(h)
+ o.open("https://www.example.com")
+ self.assertEqual(h._debuglevel, 1)
+
def test_http_doubleslash(self):
# Checks the presence of any unnecessary double slash in url does not
# break anything. Previously, a double slash directly after the host
fp = o.open('http://www.example.com')
self.assertEqual(fp.geturl(), redirected_url.strip())
+ def test_redirect_no_path(self):
+ # Issue 14132: Relative redirect strips original path
+ real_class = http.client.HTTPConnection
+ response1 = b"HTTP/1.1 302 Found\r\nLocation: ?query\r\n\r\n"
+ http.client.HTTPConnection = test_urllib.fakehttp(response1)
+ self.addCleanup(setattr, http.client, "HTTPConnection", real_class)
+ urls = iter(("/path", "/path?query"))
+ def request(conn, method, url, *pos, **kw):
+ self.assertEqual(url, next(urls))
+ real_class.request(conn, method, url, *pos, **kw)
+ # Change response for subsequent connection
+ conn.__class__.fakedata = b"HTTP/1.1 200 OK\r\n\r\nHello!"
+ http.client.HTTPConnection.request = request
+ fp = urllib.request.urlopen("http://python.org/path")
+ self.assertEqual(fp.geturl(), "http://python.org/path?query")
+
+ def test_redirect_encoding(self):
+ # Some characters in the redirect target may need special handling,
+ # but most ASCII characters should be treated as already encoded
+ class Handler(urllib.request.HTTPHandler):
+ def http_open(self, req):
+ result = self.do_open(self.connection, req)
+ self.last_buf = self.connection.buf
+ # Set up a normal response for the next request
+ self.connection = test_urllib.fakehttp(
+ b'HTTP/1.1 200 OK\r\n'
+ b'Content-Length: 3\r\n'
+ b'\r\n'
+ b'123'
+ )
+ return result
+ handler = Handler()
+ opener = urllib.request.build_opener(handler)
+ tests = (
+ (b'/p\xC3\xA5-dansk/', b'/p%C3%A5-dansk/'),
+ (b'/spaced%20path/', b'/spaced%20path/'),
+ (b'/spaced path/', b'/spaced%20path/'),
+ (b'/?p\xC3\xA5-dansk', b'/?p%C3%A5-dansk'),
+ )
+ for [location, result] in tests:
+ with self.subTest(repr(location)):
+ handler.connection = test_urllib.fakehttp(
+ b'HTTP/1.1 302 Redirect\r\n'
+ b'Location: ' + location + b'\r\n'
+ b'\r\n'
+ )
+ response = opener.open('http://example.com/')
+ expected = b'GET ' + result + b' '
+ request = handler.last_buf
+ self.assertTrue(request.startswith(expected), repr(request))
+
def test_proxy(self):
o = OpenerDirector()
ph = urllib.request.ProxyHandler(dict(http="proxy.example.com:3128"))
self.assertRaises(ValueError, _parse_proxy, 'file:/ftp.example.com'),
+ def test_unsupported_algorithm(self):
+ handler = AbstractDigestAuthHandler()
+ with self.assertRaises(ValueError) as exc:
+ handler.get_algorithm_impls('invalid')
+ self.assertEqual(
+ str(exc.exception),
+ "Unsupported digest authentication algorithm 'invalid'"
+ )
+
class RequestTests(unittest.TestCase):
class PutRequest(Request):
url = open_url.geturl()
self.assertEqual(url, "http://localhost:%s" % handler.port)
- def test_bad_address(self):
- # Make sure proper exception is raised when connecting to a bogus
- # address.
-
- # as indicated by the comment below, this might fail with some ISP,
- # so we run the test only when -unetwork/-uall is specified to
- # mitigate the problem a bit (see #17564)
- support.requires('network')
- self.assertRaises(OSError,
- # Given that both VeriSign and various ISPs have in
- # the past or are presently hijacking various invalid
- # domain name requests in an attempt to boost traffic
- # to their own sites, finding a domain name to use
- # for this test is difficult. RFC2606 leads one to
- # believe that '.invalid' should work, but experience
- # seemed to indicate otherwise. Single character
- # TLDs are likely to remain invalid, so this seems to
- # be the best choice. The trailing '.' prevents a
- # related problem: The normal DNS resolver appends
- # the domain names from the search path if there is
- # no '.' the end and, and if one of those domains
- # implements a '*' rule a result is returned.
- # However, none of this will prevent the test from
- # failing if the ISP hijacks all invalid domain
- # requests. The real solution would be to be able to
- # parameterize the framework with a mock resolver.
- urllib.request.urlopen,
- "http://sadflkjsasf.i.nvali.d./")
-
def test_iteration(self):
expected_response = b"pycon 2008..."
handler = self.start_server([(200, [], expected_response)])
for transparent redirection have been written.
setUp is not used for always constructing a connection to
- http://www.example.com/ since there a few tests that don't use that address
+ http://www.pythontest.net/ since there a few tests that don't use that address
and making a connection is expensive enough to warrant minimizing unneeded
connections.
"""
+ url = 'http://www.pythontest.net/'
+
@contextlib.contextmanager
def urlopen(self, *args, **kwargs):
resource = args[0]
def test_basic(self):
# Simple test expected to pass.
- with self.urlopen("http://www.example.com/") as open_url:
+ with self.urlopen(self.url) as open_url:
for attr in ("read", "readline", "readlines", "fileno", "close",
"info", "geturl"):
self.assertTrue(hasattr(open_url, attr), "object returned from "
def test_readlines(self):
# Test both readline and readlines.
- with self.urlopen("http://www.example.com/") as open_url:
+ with self.urlopen(self.url) as open_url:
self.assertIsInstance(open_url.readline(), bytes,
"readline did not return a string")
self.assertIsInstance(open_url.readlines(), list,
def test_info(self):
# Test 'info'.
- with self.urlopen("http://www.example.com/") as open_url:
+ with self.urlopen(self.url) as open_url:
info_obj = open_url.info()
self.assertIsInstance(info_obj, email.message.Message,
"object returned by 'info' is not an "
def test_geturl(self):
# Make sure same URL as opened is returned by geturl.
- URL = "http://www.example.com/"
- with self.urlopen(URL) as open_url:
+ with self.urlopen(self.url) as open_url:
gotten_url = open_url.geturl()
- self.assertEqual(gotten_url, URL)
+ self.assertEqual(gotten_url, self.url)
def test_getcode(self):
# test getcode() with the fancy opener to get 404 error codes
- URL = "http://www.example.com/XXXinvalidXXX"
+ URL = self.url + "XXXinvalidXXX"
with support.transient_internet(URL):
with self.assertWarns(DeprecationWarning):
open_url = urllib.request.FancyURLopener().open(URL)
open_url.close()
self.assertEqual(code, 404)
- # On Windows, socket handles are not file descriptors; this
- # test can't pass on Windows.
- @unittest.skipIf(sys.platform in ('win32',), 'not appropriate for Windows')
- def test_fileno(self):
- # Make sure fd returned by fileno is valid.
- with self.urlopen("http://www.google.com/", timeout=None) as open_url:
- fd = open_url.fileno()
- with os.fdopen(fd, 'rb') as f:
- self.assertTrue(f.read(), "reading from file created using fd "
- "returned by fileno failed")
-
def test_bad_address(self):
# Make sure proper exception is raised when connecting to a bogus
# address.
- bogus_domain = "sadflkjsasf.i.nvali.d"
+
+ # Given that both VeriSign and various ISPs have in
+ # the past or are presently hijacking various invalid
+ # domain name requests in an attempt to boost traffic
+ # to their own sites, finding a domain name to use
+ # for this test is difficult. RFC2606 leads one to
+ # believe that '.invalid' should work, but experience
+ # seemed to indicate otherwise. Single character
+ # TLDs are likely to remain invalid, so this seems to
+ # be the best choice. The trailing '.' prevents a
+ # related problem: The normal DNS resolver appends
+ # the domain names from the search path if there is
+ # no '.' the end and, and if one of those domains
+ # implements a '*' rule a result is returned.
+ # However, none of this will prevent the test from
+ # failing if the ISP hijacks all invalid domain
+ # requests. The real solution would be to be able to
+ # parameterize the framework with a mock resolver.
+ bogus_domain = "sadflkjsasf.i.nvali.d."
try:
socket.gethostbyname(bogus_domain)
except OSError:
'can be caused by a broken DNS server '
'(e.g. returns 404 or hijacks page)')
with self.assertRaises(OSError, msg=failure_explanation):
- # SF patch 809915: In Sep 2003, VeriSign started highjacking
- # invalid .com and .net addresses to boost traffic to their own
- # site. This test started failing then. One hopes the .invalid
- # domain will be spared to serve its defined purpose.
- urllib.request.urlopen("http://sadflkjsasf.i.nvali.d/")
+ urllib.request.urlopen("http://{}/".format(bogus_domain))
class urlretrieveNetworkTests(unittest.TestCase):
def test_basic(self):
# Test basic functionality.
- with self.urlretrieve("http://www.example.com/") as (file_location, info):
+ with self.urlretrieve(self.logo) as (file_location, info):
self.assertTrue(os.path.exists(file_location), "file location returned by"
" urlretrieve is not a valid path")
with open(file_location, 'rb') as f:
def test_specified_path(self):
# Make sure that specifying the location of the file to write to works.
- with self.urlretrieve("http://www.example.com/",
+ with self.urlretrieve(self.logo,
support.TESTFN) as (file_location, info):
self.assertEqual(file_location, support.TESTFN)
self.assertTrue(os.path.exists(file_location))
def test_header(self):
# Make sure header returned as 2nd value from urlretrieve is good.
- with self.urlretrieve("http://www.example.com/") as (file_location, info):
+ with self.urlretrieve(self.logo) as (file_location, info):
self.assertIsInstance(info, email.message.Message,
"info is not an instance of email.message.Message")
- logo = "http://www.example.com/"
+ logo = "http://www.pythontest.net/"
def test_data_header(self):
with self.urlretrieve(self.logo) as (file_location, fileheaders):
try:
time.strptime(datevalue, dateformat)
except ValueError:
- self.fail('Date value not in %r format', dateformat)
+ self.fail('Date value not in %r format' % dateformat)
def test_reporthook(self):
records = []
("=a", [('', 'a')]),
("a", [('a', '')]),
("a=", [('a', '')]),
- ("a=", [('a', '')]),
("&a=b", [('a', 'b')]),
("a=a+b&b=b+c", [('a', 'a b'), ('b', 'b c')]),
("a=1&a=2", [('a', '1'), ('a', '2')]),
(b"=a", [(b'', b'a')]),
(b"a", [(b'a', b'')]),
(b"a=", [(b'a', b'')]),
- (b"a=", [(b'a', b'')]),
(b"&a=b", [(b'a', b'b')]),
(b"a=a+b&b=b+c", [(b'a', b'a b'), (b'b', b'b c')]),
(b"a=1&a=2", [(b'a', b'1'), (b'a', b'2')]),
+ (";", []),
+ (";;", []),
+ (";a=b", [('a', 'b')]),
+ ("a=a+b;b=b+c", [('a', 'a b'), ('b', 'b c')]),
+ ("a=1;a=2", [('a', '1'), ('a', '2')]),
+ (b";", []),
+ (b";;", []),
+ (b";a=b", [(b'a', b'b')]),
+ (b"a=a+b;b=b+c", [(b'a', b'a b'), (b'b', b'b c')]),
+ (b"a=1;a=2", [(b'a', b'1'), (b'a', b'2')]),
+]
+
+parse_qs_test_cases = [
+ ("", {}),
+ ("&", {}),
+ ("&&", {}),
+ ("=", {'': ['']}),
+ ("=a", {'': ['a']}),
+ ("a", {'a': ['']}),
+ ("a=", {'a': ['']}),
+ ("&a=b", {'a': ['b']}),
+ ("a=a+b&b=b+c", {'a': ['a b'], 'b': ['b c']}),
+ ("a=1&a=2", {'a': ['1', '2']}),
+ (b"", {}),
+ (b"&", {}),
+ (b"&&", {}),
+ (b"=", {b'': [b'']}),
+ (b"=a", {b'': [b'a']}),
+ (b"a", {b'a': [b'']}),
+ (b"a=", {b'a': [b'']}),
+ (b"&a=b", {b'a': [b'b']}),
+ (b"a=a+b&b=b+c", {b'a': [b'a b'], b'b': [b'b c']}),
+ (b"a=1&a=2", {b'a': [b'1', b'2']}),
+ (";", {}),
+ (";;", {}),
+ (";a=b", {'a': ['b']}),
+ ("a=a+b;b=b+c", {'a': ['a b'], 'b': ['b c']}),
+ ("a=1;a=2", {'a': ['1', '2']}),
+ (b";", {}),
+ (b";;", {}),
+ (b";a=b", {b'a': [b'b']}),
+ (b"a=a+b;b=b+c", {b'a': [b'a b'], b'b': [b'b c']}),
+ (b"a=1;a=2", {b'a': [b'1', b'2']}),
]
class UrlParseTestCase(unittest.TestCase):
self.assertEqual(result, expect_without_blanks,
"Error parsing %r" % orig)
+ def test_qs(self):
+ for orig, expect in parse_qs_test_cases:
+ result = urllib.parse.parse_qs(orig, keep_blank_values=True)
+ self.assertEqual(result, expect, "Error parsing %r" % orig)
+ expect_without_blanks = {v: expect[v]
+ for v in expect if len(expect[v][0])}
+ result = urllib.parse.parse_qs(orig, keep_blank_values=False)
+ self.assertEqual(result, expect_without_blanks,
+ "Error parsing %r" % orig)
+
def test_roundtrips(self):
str_cases = [
('file:///tmp/junk.txt',
# Check every path through every method of UserDict
from test import support, mapping_tests
+import unittest
import collections
d0 = {}
from collections import UserList
from test import support, list_tests
+import unittest
class UserListTest(list_tests.CommonTest):
type2test = UserList
equal(u, uuid.UUID(v))
equal(str(u), v)
- @unittest.skipUnless(importable('ctypes'), 'requires ctypes')
def test_uuid4(self):
equal = self.assertEqual
import ensurepip
import os
import os.path
+import re
import struct
import subprocess
import sys
except ImportError:
ssl = None
+try:
+ import threading
+except ImportError:
+ threading = None
+
skipInVenv = unittest.skipIf(sys.prefix != sys.base_prefix,
'Test not appropriate in a venv')
# Requesting pip fails without SSL (http://bugs.python.org/issue19744)
@unittest.skipIf(ssl is None, ensurepip._MISSING_SSL_MESSAGE)
+ @unittest.skipUnless(threading, 'some dependencies of pip import threading'
+ ' module unconditionally')
def test_with_pip(self):
rmtree(self.env_dir)
with EnvironmentVarGuard() as envvars:
# We force everything to text, so unittest gives the detailed diff
# if we get unexpected results
err = err.decode("latin-1") # Force to text, prevent decoding errors
- self.assertEqual(err, "")
+ # Ignore the warning:
+ # "The directory '$HOME/.cache/pip/http' or its parent directory
+ # is not owned by the current user and the cache has been disabled.
+ # Please check the permissions and owner of that directory. If
+ # executing pip with sudo, you may want sudo's -H flag."
+ # where $HOME is replaced by the HOME environment variable.
+ err = re.sub("^The directory .* or its parent directory is not owned "
+ "by the current user .*$", "", err, flags=re.MULTILINE)
+ self.assertEqual(err.rstrip(), "")
# Being fairly specific regarding the expected behaviour for the
# initial bundling phase in Python 3.4. If the output changes in
# future pip versions, this test can likely be relaxed further.
import os
import time
import sys
+import unittest
from test.fork_wait import ForkWait
from test.support import reap_children, get_attribute
message = "FilterTests.test_ignore_after_default"
def f():
self.module.warn(message, UserWarning)
- f()
+
+ with support.captured_stderr() as stderr:
+ f()
+ stderr = stderr.getvalue()
+ self.assertIn("UserWarning: FilterTests.test_ignore_after_default",
+ stderr)
+ self.assertIn("self.module.warn(message, UserWarning)",
+ stderr)
+
self.module.filterwarnings("error", category=UserWarning)
self.assertRaises(UserWarning, f)
self.module.warn_explicit(UserWarning("b"), None, "f.py", 42)
self.assertEqual(str(w[-1].message), "b")
+ def test_filterwarnings_duplicate_filters(self):
+ with original_warnings.catch_warnings(module=self.module):
+ self.module.resetwarnings()
+ self.module.filterwarnings("error", category=UserWarning)
+ self.assertEqual(len(self.module.filters), 1)
+ self.module.filterwarnings("ignore", category=UserWarning)
+ self.module.filterwarnings("error", category=UserWarning)
+ self.assertEqual(
+ len(self.module.filters), 2,
+ "filterwarnings inserted duplicate filter"
+ )
+ self.assertEqual(
+ self.module.filters[0][0], "error",
+ "filterwarnings did not promote filter to "
+ "the beginning of list"
+ )
+
+ def test_simplefilter_duplicate_filters(self):
+ with original_warnings.catch_warnings(module=self.module):
+ self.module.resetwarnings()
+ self.module.simplefilter("error", category=UserWarning)
+ self.assertEqual(len(self.module.filters), 1)
+ self.module.simplefilter("ignore", category=UserWarning)
+ self.module.simplefilter("error", category=UserWarning)
+ self.assertEqual(
+ len(self.module.filters), 2,
+ "simplefilter inserted duplicate filter"
+ )
+ self.assertEqual(
+ self.module.filters[0][0], "error",
+ "simplefilter did not promote filter to the beginning of list"
+ )
+ def test_append_duplicate(self):
+ with original_warnings.catch_warnings(module=self.module,
+ record=True) as w:
+ self.module.resetwarnings()
+ self.module.simplefilter("ignore")
+ self.module.simplefilter("error", append=True)
+ self.module.simplefilter("ignore", append=True)
+ self.module.warn("test_append_duplicate", category=UserWarning)
+ self.assertEqual(len(self.module.filters), 2,
+ "simplefilter inserted duplicate filter"
+ )
+ self.assertEqual(len(w), 0,
+ "appended duplicate changed order of filters"
+ )
+
class CFilterTests(FilterTests, unittest.TestCase):
module = c_warnings
self.module._setoption('error::Warning::0')
self.assertRaises(UserWarning, self.module.warn, 'convert to error')
+
+class CWCmdLineTests(WCmdLineTests, unittest.TestCase):
+ module = c_warnings
+
+
+class PyWCmdLineTests(WCmdLineTests, unittest.TestCase):
+ module = py_warnings
+
def test_improper_option(self):
# Same as above, but check that the message is printed out when
# the interpreter is executed. This also checks that options are
self.assertFalse(out.strip())
self.assertNotIn(b'RuntimeWarning', err)
-class CWCmdLineTests(WCmdLineTests, unittest.TestCase):
- module = c_warnings
-
-class PyWCmdLineTests(WCmdLineTests, unittest.TestCase):
- module = py_warnings
-
class _WarningsTests(BaseTest, unittest.TestCase):
# Use -W to load warnings module at startup
assert_python_ok('-c', 'pass', '-W', 'always', PYTHONPATH=cwd)
+
class FinalizationTest(unittest.TestCase):
def test_finalization(self):
# Issue #19421: warnings.warn() should not crash
# of the script
self.assertEqual(err, b'__main__:7: UserWarning: test')
+ def test_late_resource_warning(self):
+ # Issue #21925: Emitting a ResourceWarning late during the Python
+ # shutdown must be logged.
+
+ expected = b"sys:1: ResourceWarning: unclosed file "
+
+ # don't import the warnings module
+ # (_warnings will try to import it)
+ code = "f = open(%a)" % __file__
+ rc, out, err = assert_python_ok("-Wd", "-c", code)
+ self.assertTrue(err.startswith(expected), ascii(err))
+
+ # import the warnings module
+ code = "import warnings; f = open(%a)" % __file__
+ rc, out, err = assert_python_ok("-Wd", "-c", code)
+ self.assertTrue(err.startswith(expected), ascii(err))
+
def setUpModule():
py_warnings.onceregistry.clear()
import warnings
-warnings.warn('module-level warning', DeprecationWarning, stacklevel=2)
\ No newline at end of file
+warnings.warn('module-level warning', DeprecationWarning, stacklevel=2)
ref1 = weakref.ref(c, callback)
del c
+ def test_constructor_kwargs(self):
+ c = C()
+ self.assertRaises(TypeError, weakref.ref, c, callback=None)
+
def test_proxy_ref(self):
o = C()
o.bar = 1
)
def test_alias_fallback(self):
- # In the absense of the ability to tell if a sound was actually
+ # In the absence of the ability to tell if a sound was actually
# played, this test has two acceptable outcomes: success (no error,
# sound was theoretically played; although as issue #19987 shows
# a box without a soundcard can "succeed") or RuntimeError. Any
+from unittest import mock
+from test import support
+from test.test_httpservers import NoLogRequestHandler
from unittest import TestCase
from wsgiref.util import setup_testing_defaults
from wsgiref.headers import Headers
-from wsgiref.handlers import BaseHandler, BaseCGIHandler
+from wsgiref.handlers import BaseHandler, BaseCGIHandler, SimpleHandler
from wsgiref import util
from wsgiref.validate import validator
from wsgiref.simple_server import WSGIServer, WSGIRequestHandler
from wsgiref.simple_server import make_server
+from http.client import HTTPConnection
from io import StringIO, BytesIO, BufferedReader
from socketserver import BaseServer
from platform import python_implementation
import os
import re
+import signal
import sys
import unittest
" be of type list: <class 'tuple'>"
)
+ def test_status_validation_errors(self):
+ def create_bad_app(status):
+ def bad_app(environ, start_response):
+ start_response(status, [("Content-Type", "text/plain; charset=utf-8")])
+ return [b"Hello, world!"]
+ return bad_app
+
+ tests = [
+ ('200', 'AssertionError: Status must be at least 4 characters'),
+ ('20X OK', 'AssertionError: Status message must begin w/3-digit code'),
+ ('200OK', 'AssertionError: Status message must have a space after code'),
+ ]
+
+ for status, exc_message in tests:
+ with self.subTest(status=status):
+ out, err = run_amock(create_bad_app(status))
+ self.assertTrue(out.endswith(
+ b"A server error occurred. Please contact the administrator."
+ ))
+ self.assertEqual(err.splitlines()[-2], exc_message)
+
def test_wsgi_input(self):
def bad_app(e,s):
e["wsgi.input"].read()
b"data",
out)
+ def test_cp1252_url(self):
+ def app(e, s):
+ s("200 OK", [
+ ("Content-Type", "text/plain"),
+ ("Date", "Wed, 24 Dec 2008 13:29:32 GMT"),
+ ])
+ # PEP3333 says environ variables are decoded as latin1.
+ # Encode as latin1 to get original bytes
+ return [e["PATH_INFO"].encode("latin1")]
+
+ out, err = run_amock(
+ validator(app), data=b"GET /\x80%80 HTTP/1.0")
+ self.assertEqual(
+ [
+ b"HTTP/1.0 200 OK",
+ mock.ANY,
+ b"Content-Type: text/plain",
+ b"Date: Wed, 24 Dec 2008 13:29:32 GMT",
+ b"",
+ b"/\x80\x80",
+ ],
+ out.splitlines())
+
+ def test_interrupted_write(self):
+ # BaseHandler._write() and _flush() have to write all data, even if
+ # it takes multiple send() calls. Test this by interrupting a send()
+ # call with a Unix signal.
+ threading = support.import_module("threading")
+ pthread_kill = support.get_attribute(signal, "pthread_kill")
+
+ def app(environ, start_response):
+ start_response("200 OK", [])
+ return [bytes(support.SOCK_MAX_SIZE)]
+
+ class WsgiHandler(NoLogRequestHandler, WSGIRequestHandler):
+ pass
+
+ server = make_server(support.HOST, 0, app, handler_class=WsgiHandler)
+ self.addCleanup(server.server_close)
+ interrupted = threading.Event()
+
+ def signal_handler(signum, frame):
+ interrupted.set()
+
+ original = signal.signal(signal.SIGUSR1, signal_handler)
+ self.addCleanup(signal.signal, signal.SIGUSR1, original)
+ received = None
+ main_thread = threading.get_ident()
+
+ def run_client():
+ http = HTTPConnection(*server.server_address)
+ http.request("GET", "/")
+ with http.getresponse() as response:
+ response.read(100)
+ # The main thread should now be blocking in a send() system
+ # call. But in theory, it could get interrupted by other
+ # signals, and then retried. So keep sending the signal in a
+ # loop, in case an earlier signal happens to be delivered at
+ # an inconvenient moment.
+ while True:
+ pthread_kill(main_thread, signal.SIGUSR1)
+ if interrupted.wait(timeout=float(1)):
+ break
+ nonlocal received
+ received = len(response.read())
+ http.close()
+
+ background = threading.Thread(target=run_client)
+ background.start()
+ server.handle_request()
+ background.join()
+ self.assertEqual(received, support.SOCK_MAX_SIZE - 100)
+
class UtilityTests(TestCase):
h.run(error_app)
self.assertEqual(side_effects['close_called'], True)
+ def testPartialWrite(self):
+ written = bytearray()
+
+ class PartialWriter:
+ def write(self, b):
+ partial = b[:7]
+ written.extend(partial)
+ return len(partial)
+
+ def flush(self):
+ pass
+
+ environ = {"SERVER_PROTOCOL": "HTTP/1.0"}
+ h = SimpleHandler(BytesIO(), PartialWriter(), sys.stderr, environ)
+ msg = "should not do partial writes"
+ with self.assertWarnsRegex(DeprecationWarning, msg):
+ h.run(hello_app)
+ self.assertEqual(b"HTTP/1.0 200 OK\r\n"
+ b"Content-Type: text/plain\r\n"
+ b"Date: Mon, 05 Jun 2006 18:49:54 GMT\r\n"
+ b"Content-Length: 13\r\n"
+ b"\r\n"
+ b"Hello, world!",
+ written)
+
if __name__ == "__main__":
unittest.main()
# Tests for xml.dom.minicompat
+import copy
import pickle
import unittest
node_list = NodeList()
pickled = pickle.dumps(node_list, proto)
unpickled = pickle.loads(pickled)
+ self.assertIsNot(unpickled, node_list)
self.assertEqual(unpickled, node_list)
# Non-empty NodeList.
node_list.append(2)
pickled = pickle.dumps(node_list, proto)
unpickled = pickle.loads(pickled)
+ self.assertIsNot(unpickled, node_list)
self.assertEqual(unpickled, node_list)
+ def test_nodelist_copy(self):
+ # Empty NodeList.
+ node_list = NodeList()
+ copied = copy.copy(node_list)
+ self.assertIsNot(copied, node_list)
+ self.assertEqual(copied, node_list)
+
+ # Non-empty NodeList.
+ node_list.append([1])
+ node_list.append([2])
+ copied = copy.copy(node_list)
+ self.assertIsNot(copied, node_list)
+ self.assertEqual(copied, node_list)
+ for x, y in zip(copied, node_list):
+ self.assertIs(x, y)
+
+ def test_nodelist_deepcopy(self):
+ # Empty NodeList.
+ node_list = NodeList()
+ copied = copy.deepcopy(node_list)
+ self.assertIsNot(copied, node_list)
+ self.assertEqual(copied, node_list)
+
+ # Non-empty NodeList.
+ node_list.append([1])
+ node_list.append([2])
+ copied = copy.deepcopy(node_list)
+ self.assertIsNot(copied, node_list)
+ self.assertEqual(copied, node_list)
+ for x, y in zip(copied, node_list):
+ self.assertIsNot(x, y)
+ self.assertEqual(x, y)
+
if __name__ == '__main__':
unittest.main()
self.assertEqual(ET.XML, ET.fromstring)
self.assertEqual(ET.PI, ET.ProcessingInstruction)
+ def test_set_attribute(self):
+ element = ET.Element('tag')
+
+ self.assertEqual(element.tag, 'tag')
+ element.tag = 'Tag'
+ self.assertEqual(element.tag, 'Tag')
+ element.tag = 'TAG'
+ self.assertEqual(element.tag, 'TAG')
+
+ self.assertIsNone(element.text)
+ element.text = 'Text'
+ self.assertEqual(element.text, 'Text')
+ element.text = 'TEXT'
+ self.assertEqual(element.text, 'TEXT')
+
+ self.assertIsNone(element.tail)
+ element.tail = 'Tail'
+ self.assertEqual(element.tail, 'Tail')
+ element.tail = 'TAIL'
+ self.assertEqual(element.tail, 'TAIL')
+
+ self.assertEqual(element.attrib, {})
+ element.attrib = {'a': 'b', 'c': 'd'}
+ self.assertEqual(element.attrib, {'a': 'b', 'c': 'd'})
+ element.attrib = {'A': 'B', 'C': 'D'}
+ self.assertEqual(element.attrib, {'A': 'B', 'C': 'D'})
+
def test_simpleops(self):
# Basic method sanity checks.
self.assertEqual(res, ['start-ns', 'end-ns'])
events = ("start", "end", "bogus")
- with self.assertRaises(ValueError) as cm:
- with open(SIMPLE_XMLFILE, "rb") as f:
+ with open(SIMPLE_XMLFILE, "rb") as f:
+ with self.assertRaises(ValueError) as cm:
iterparse(f, events)
+ self.assertFalse(f.closed)
self.assertEqual(str(cm.exception), "unknown event 'bogus'")
+ with support.check_no_resource_warning(self):
+ with self.assertRaises(ValueError) as cm:
+ iterparse(SIMPLE_XMLFILE, events)
+ self.assertEqual(str(cm.exception), "unknown event 'bogus'")
+ del cm
+
source = io.BytesIO(
b"<?xml version='1.0' encoding='iso-8859-1'?>\n"
b"<body xmlns='http://éffbot.org/ns'\n"
self.assertEqual(str(cm.exception),
'junk after document element: line 1, column 12')
+ with open(TESTFN, "wb") as f:
+ f.write(b"<document />junk")
+ it = iterparse(TESTFN)
+ action, elem = next(it)
+ self.assertEqual((action, elem.tag), ('end', 'document'))
+ with support.check_no_resource_warning(self):
+ with self.assertRaises(ET.ParseError) as cm:
+ next(it)
+ self.assertEqual(str(cm.exception),
+ 'junk after document element: line 1, column 12')
+ del cm, it
+
def test_writefile(self):
elem = ET.Element("tag")
elem.text = "text"
ET.register_namespace('test10777', 'http://myuri/')
ET.register_namespace('test10777', 'http://myuri/')
+ def test_lost_text(self):
+ # Issue #25902: Borrowed text can disappear
+ class Text:
+ def __bool__(self):
+ e.text = 'changed'
+ return True
+
+ e = ET.Element('tag')
+ e.text = Text()
+ i = e.itertext()
+ t = next(i)
+ self.assertIsInstance(t, Text)
+ self.assertIsInstance(e.text, str)
+ self.assertEqual(e.text, 'changed')
+
+ def test_lost_tail(self):
+ # Issue #25902: Borrowed tail can disappear
+ class Text:
+ def __bool__(self):
+ e[0].tail = 'changed'
+ return True
+
+ e = ET.Element('root')
+ e.append(ET.Element('tag'))
+ e[0].tail = Text()
+ i = e.itertext()
+ t = next(i)
+ self.assertIsInstance(t, Text)
+ self.assertIsInstance(e[0].tail, str)
+ self.assertEqual(e[0].tail, 'changed')
+
+ def test_lost_elem(self):
+ # Issue #25902: Borrowed element can disappear
+ class Tag:
+ def __eq__(self, other):
+ e[0] = ET.Element('changed')
+ next(i)
+ return True
+
+ e = ET.Element('root')
+ e.append(ET.Element(Tag()))
+ e.append(ET.Element('tag'))
+ i = e.iter('tag')
+ try:
+ t = next(i)
+ except ValueError:
+ self.skipTest('generators are not reentrant')
+ self.assertIsInstance(t.tag, Tag)
+ self.assertIsInstance(e[0].tag, str)
+ self.assertEqual(e[0].tag, 'changed')
+
# --------------------------------------------------------------------
self.assertEqual(e[-2].tag, 'a8')
self.assertRaises(IndexError, lambda: e[12])
+ self.assertRaises(IndexError, lambda: e[-12])
def test_getslice_range(self):
e = self._make_elem_with_children(6)
self.assertEqual(self._elem_tags(e[::3]), ['a0', 'a3', 'a6', 'a9'])
self.assertEqual(self._elem_tags(e[::8]), ['a0', 'a8'])
self.assertEqual(self._elem_tags(e[1::8]), ['a1', 'a9'])
+ self.assertEqual(self._elem_tags(e[3::sys.maxsize]), ['a3'])
+ self.assertEqual(self._elem_tags(e[3::sys.maxsize<<64]), ['a3'])
def test_getslice_negative_steps(self):
e = self._make_elem_with_children(4)
self.assertEqual(self._elem_tags(e[::-1]), ['a3', 'a2', 'a1', 'a0'])
self.assertEqual(self._elem_tags(e[::-2]), ['a3', 'a1'])
+ self.assertEqual(self._elem_tags(e[3::-sys.maxsize]), ['a3'])
+ self.assertEqual(self._elem_tags(e[3::-sys.maxsize-1]), ['a3'])
+ self.assertEqual(self._elem_tags(e[3::-sys.maxsize<<64]), ['a3'])
def test_delslice(self):
e = self._make_elem_with_children(4)
del e[::2]
self.assertEqual(self._subelem_tags(e), ['a1'])
+ def test_setslice_single_index(self):
+ e = self._make_elem_with_children(4)
+ e[1] = ET.Element('b')
+ self.assertEqual(self._subelem_tags(e), ['a0', 'b', 'a2', 'a3'])
+
+ e[-2] = ET.Element('c')
+ self.assertEqual(self._subelem_tags(e), ['a0', 'b', 'c', 'a3'])
+
+ with self.assertRaises(IndexError):
+ e[5] = ET.Element('d')
+ with self.assertRaises(IndexError):
+ e[-5] = ET.Element('d')
+ self.assertEqual(self._subelem_tags(e), ['a0', 'b', 'c', 'a3'])
+
+ def test_setslice_range(self):
+ e = self._make_elem_with_children(4)
+ e[1:3] = [ET.Element('b%s' % i) for i in range(2)]
+ self.assertEqual(self._subelem_tags(e), ['a0', 'b0', 'b1', 'a3'])
+
+ e = self._make_elem_with_children(4)
+ e[1:3] = [ET.Element('b')]
+ self.assertEqual(self._subelem_tags(e), ['a0', 'b', 'a3'])
+
+ e = self._make_elem_with_children(4)
+ e[1:3] = [ET.Element('b%s' % i) for i in range(3)]
+ self.assertEqual(self._subelem_tags(e), ['a0', 'b0', 'b1', 'b2', 'a3'])
+
+ def test_setslice_steps(self):
+ e = self._make_elem_with_children(6)
+ e[1:5:2] = [ET.Element('b%s' % i) for i in range(2)]
+ self.assertEqual(self._subelem_tags(e), ['a0', 'b0', 'a2', 'b1', 'a4', 'a5'])
+
+ e = self._make_elem_with_children(6)
+ with self.assertRaises(ValueError):
+ e[1:5:2] = [ET.Element('b')]
+ with self.assertRaises(ValueError):
+ e[1:5:2] = [ET.Element('b%s' % i) for i in range(3)]
+ with self.assertRaises(ValueError):
+ e[1:5:2] = []
+ self.assertEqual(self._subelem_tags(e), ['a0', 'a1', 'a2', 'a3', 'a4', 'a5'])
+
+ e = self._make_elem_with_children(4)
+ e[1::sys.maxsize] = [ET.Element('b')]
+ self.assertEqual(self._subelem_tags(e), ['a0', 'b', 'a2', 'a3'])
+ e[1::sys.maxsize<<64] = [ET.Element('c')]
+ self.assertEqual(self._subelem_tags(e), ['a0', 'c', 'a2', 'a3'])
+
+ def test_setslice_negative_steps(self):
+ e = self._make_elem_with_children(4)
+ e[2:0:-1] = [ET.Element('b%s' % i) for i in range(2)]
+ self.assertEqual(self._subelem_tags(e), ['a0', 'b1', 'b0', 'a3'])
+
+ e = self._make_elem_with_children(4)
+ with self.assertRaises(ValueError):
+ e[2:0:-1] = [ET.Element('b')]
+ with self.assertRaises(ValueError):
+ e[2:0:-1] = [ET.Element('b%s' % i) for i in range(3)]
+ with self.assertRaises(ValueError):
+ e[2:0:-1] = []
+ self.assertEqual(self._subelem_tags(e), ['a0', 'a1', 'a2', 'a3'])
+
+ e = self._make_elem_with_children(4)
+ e[1::-sys.maxsize] = [ET.Element('b')]
+ self.assertEqual(self._subelem_tags(e), ['a0', 'b', 'a2', 'a3'])
+ e[1::-sys.maxsize-1] = [ET.Element('c')]
+ self.assertEqual(self._subelem_tags(e), ['a0', 'c', 'a2', 'a3'])
+ e[1::-sys.maxsize<<64] = [ET.Element('d')]
+ self.assertEqual(self._subelem_tags(e), ['a0', 'd', 'a2', 'a3'])
+
class IOTest(unittest.TestCase):
def tearDown(self):
finally:
data = None
+ def test_del_attribute(self):
+ element = cET.Element('tag')
+
+ element.tag = 'TAG'
+ with self.assertRaises(AttributeError):
+ del element.tag
+ self.assertEqual(element.tag, 'TAG')
+
+ with self.assertRaises(AttributeError):
+ del element.text
+ self.assertIsNone(element.text)
+ element.text = 'TEXT'
+ with self.assertRaises(AttributeError):
+ del element.text
+ self.assertEqual(element.text, 'TEXT')
+
+ with self.assertRaises(AttributeError):
+ del element.tail
+ self.assertIsNone(element.tail)
+ element.tail = 'TAIL'
+ with self.assertRaises(AttributeError):
+ del element.tail
+ self.assertEqual(element.tail, 'TAIL')
+
+ with self.assertRaises(AttributeError):
+ del element.attrib
+ self.assertEqual(element.attrib, {})
+ element.attrib = {'A': 'B', 'C': 'D'}
+ with self.assertRaises(AttributeError):
+ del element.attrib
+ self.assertEqual(element.attrib, {'A': 'B', 'C': 'D'})
+
@unittest.skipUnless(cET, 'requires _elementtree')
class TestAliasWorking(unittest.TestCase):
import xmlrpc.client as xmlrpclib
import xmlrpc.server
import http.client
+import http, http.server
import socket
import os
import re
xmlrpclib.loads(strg)[0][0])
self.assertRaises(TypeError, xmlrpclib.dumps, (arg1,))
+ def test_dump_encoding(self):
+ value = {'key\u20ac\xa4':
+ 'value\u20ac\xa4'}
+ strg = xmlrpclib.dumps((value,), encoding='iso-8859-15')
+ strg = "<?xml version='1.0' encoding='iso-8859-15'?>" + strg
+ self.assertEqual(xmlrpclib.loads(strg)[0][0], value)
+ strg = strg.encode('iso-8859-15', 'xmlcharrefreplace')
+ self.assertEqual(xmlrpclib.loads(strg)[0][0], value)
+
+ strg = xmlrpclib.dumps((value,), encoding='iso-8859-15',
+ methodresponse=True)
+ self.assertEqual(xmlrpclib.loads(strg)[0][0], value)
+ strg = strg.encode('iso-8859-15', 'xmlcharrefreplace')
+ self.assertEqual(xmlrpclib.loads(strg)[0][0], value)
+
+ methodname = 'method\u20ac\xa4'
+ strg = xmlrpclib.dumps((value,), encoding='iso-8859-15',
+ methodname=methodname)
+ self.assertEqual(xmlrpclib.loads(strg)[0][0], value)
+ self.assertEqual(xmlrpclib.loads(strg)[1], methodname)
+
def test_dump_bytes(self):
sample = b"my dog has fleas"
self.assertEqual(sample, xmlrpclib.Binary(sample))
self.assertIs(type(newvalue), xmlrpclib.Binary)
self.assertIsNone(m)
+ def test_loads_unsupported(self):
+ ResponseError = xmlrpclib.ResponseError
+ data = '<params><param><value><spam/></value></param></params>'
+ self.assertRaises(ResponseError, xmlrpclib.loads, data)
+ data = ('<params><param><value><array>'
+ '<value><spam/></value>'
+ '</array></value></param></params>')
+ self.assertRaises(ResponseError, xmlrpclib.loads, data)
+ data = ('<params><param><value><struct>'
+ '<member><name>a</name><value><spam/></value></member>'
+ '<member><name>b</name><value><spam/></value></member>'
+ '</struct></value></param></params>')
+ self.assertRaises(ResponseError, xmlrpclib.loads, data)
+
def test_get_host_info(self):
# see bug #3613, this raised a TypeError
transp = xmlrpc.client.Transport()
except OSError:
self.assertTrue(has_ssl)
+ @unittest.skipUnless(threading, "Threading required for this test.")
+ def test_keepalive_disconnect(self):
+ class RequestHandler(http.server.BaseHTTPRequestHandler):
+ protocol_version = "HTTP/1.1"
+ handled = False
+
+ def do_POST(self):
+ length = int(self.headers.get("Content-Length"))
+ self.rfile.read(length)
+ if self.handled:
+ self.close_connection = True
+ return
+ response = xmlrpclib.dumps((5,), methodresponse=True)
+ response = response.encode()
+ self.send_response(http.HTTPStatus.OK)
+ self.send_header("Content-Length", len(response))
+ self.end_headers()
+ self.wfile.write(response)
+ self.handled = True
+ self.close_connection = False
+
+ def run_server():
+ server.socket.settimeout(float(1)) # Don't hang if client fails
+ server.handle_request() # First request and attempt at second
+ server.handle_request() # Retried second request
+
+ server = http.server.HTTPServer((support.HOST, 0), RequestHandler)
+ self.addCleanup(server.server_close)
+ thread = threading.Thread(target=run_server)
+ thread.start()
+ self.addCleanup(thread.join)
+ url = "http://{}:{}/".format(*server.server_address)
+ with xmlrpclib.ServerProxy(url) as p:
+ self.assertEqual(p.method(), 5)
+ self.assertEqual(p.method(), 5)
+
class HelperTestCase(unittest.TestCase):
def test_escape(self):
self.assertEqual(xmlrpclib.escape("a&b"), "a&b")
# The evt is set twice. First when the server is ready to serve.
# Second when the server has been shutdown. The user must clear
# the event after it has been set the first time to catch the second set.
-def http_server(evt, numrequests, requestHandler=None):
+def http_server(evt, numrequests, requestHandler=None, encoding=None):
class TestInstanceClass:
def div(self, x, y):
return x // y
if not requestHandler:
requestHandler = xmlrpc.server.SimpleXMLRPCRequestHandler
serv = MyXMLRPCServer(("localhost", 0), requestHandler,
+ encoding=encoding,
logRequests=False, bind_and_activate=False)
try:
serv.server_bind()
serv.register_multicall_functions()
serv.register_function(pow)
serv.register_function(lambda x,y: x+y, 'add')
+ serv.register_function(lambda x: x, 'têšt')
serv.register_function(my_function)
testInstance = TestInstanceClass()
serv.register_instance(testInstance, allow_dotted_names=True)
# protocol error; provide additional information in test output
self.fail("%s\n%s" % (e, getattr(e, "headers", "")))
+ def test_client_encoding(self):
+ start_string = '\u20ac'
+ end_string = '\xa4'
+
+ try:
+ p = xmlrpclib.ServerProxy(URL, encoding='iso-8859-15')
+ self.assertEqual(p.add(start_string, end_string),
+ start_string + end_string)
+ except (xmlrpclib.ProtocolError, socket.error) as e:
+ # ignore failures due to non-blocking socket unavailable errors.
+ if not is_unavailable_exception(e):
+ # protocol error; provide additional information in test output
+ self.fail("%s\n%s" % (e, getattr(e, "headers", "")))
+
+ def test_nonascii_methodname(self):
+ try:
+ p = xmlrpclib.ServerProxy(URL, encoding='ascii')
+ self.assertEqual(p.têšt(42), 42)
+ except (xmlrpclib.ProtocolError, socket.error) as e:
+ # ignore failures due to non-blocking socket unavailable errors.
+ if not is_unavailable_exception(e):
+ # protocol error; provide additional information in test output
+ self.fail("%s\n%s" % (e, getattr(e, "headers", "")))
+
# [ch] The test 404 is causing lots of false alarms.
def XXXtest_404(self):
# send POST with http.client, it should return 404 header and
self.assertEqual(response.reason, 'Not Found')
def test_introspection1(self):
- expected_methods = set(['pow', 'div', 'my_function', 'add',
+ expected_methods = set(['pow', 'div', 'my_function', 'add', 'têšt',
'system.listMethods', 'system.methodHelp',
'system.methodSignature', 'system.multicall',
'Fixture'])
(None, None))
+class SimpleServerEncodingTestCase(BaseServerTestCase):
+ @staticmethod
+ def threadFunc(evt, numrequests, requestHandler=None, encoding=None):
+ http_server(evt, numrequests, requestHandler, 'iso-8859-15')
+
+ def test_server_encoding(self):
+ start_string = '\u20ac'
+ end_string = '\xa4'
+
+ try:
+ p = xmlrpclib.ServerProxy(URL)
+ self.assertEqual(p.add(start_string, end_string),
+ start_string + end_string)
+ except (xmlrpclib.ProtocolError, socket.error) as e:
+ # ignore failures due to non-blocking socket unavailable errors.
+ if not is_unavailable_exception(e):
+ # protocol error; provide additional information in test output
+ self.fail("%s\n%s" % (e, getattr(e, "headers", "")))
+
+
class MultiPathServerTestCase(BaseServerTestCase):
threadFunc = staticmethod(http_multi_server)
request_count = 2
def test_main():
support.run_unittest(XMLRPCTestCase, HelperTestCase, DateTimeTestCase,
BinaryTestCase, FaultTestCase, UseBuiltinTypesTestCase,
- SimpleServerTestCase, KeepaliveServerTestCase1,
- KeepaliveServerTestCase2, GzipServerTestCase, GzipUtilTestCase,
+ SimpleServerTestCase, SimpleServerEncodingTestCase,
+ KeepaliveServerTestCase1, KeepaliveServerTestCase2,
+ GzipServerTestCase, GzipUtilTestCase,
MultiPathServerTestCase, ServerProxyTestCase, FailingServerTestCase,
CGIHandlerTestCase)
self.assertTrue(new_target.getvalue().startswith(b'#!python2.7\n'))
def test_read_from_pathobj(self):
- # Test that we can copy an archive using an pathlib.Path object
+ # Test that we can copy an archive using a pathlib.Path object
# for the source.
source = self.tmpdir / 'source'
source.mkdir()
for f in get_files(self):
self.make_test_archive(f)
with zipfile.ZipFile(f, mode="r") as zipf:
- with zipf.open('ones') as zopen1, zipf.open('twos') as zopen2:
+ with zipf.open('ones') as zopen1:
data1 = zopen1.read(500)
- data2 = zopen2.read(500)
- data1 += zopen1.read()
- data2 += zopen2.read()
+ with zipf.open('twos') as zopen2:
+ data2 = zopen2.read(500)
+ data1 += zopen1.read()
+ data2 += zopen2.read()
self.assertEqual(data1, self.data1)
self.assertEqual(data2, self.data2)
# from test_zipfile
from test import support
-# XXX(nnorwitz): disable this test by looking for extra largfile resource
+# XXX(nnorwitz): disable this test by looking for extralargefile resource,
# which doesn't exist. This test takes over 30 minutes to run in general
# and requires more disk space than most of the buildbots.
support.requires(
def testStored(self):
# Try the temp file first. If we do TESTFN2 first, then it hogs
# gigabytes of disk space for the duration of the test.
- for f in TemporaryFile(), TESTFN2:
+ with TemporaryFile() as f:
self.zipTest(f, zipfile.ZIP_STORED)
+ self.assertFalse(f.closed)
+ self.zipTest(TESTFN2, zipfile.ZIP_STORED)
@requires_zlib
def testDeflated(self):
# Try the temp file first. If we do TESTFN2 first, then it hogs
# gigabytes of disk space for the duration of the test.
- for f in TemporaryFile(), TESTFN2:
+ with TemporaryFile() as f:
self.zipTest(f, zipfile.ZIP_DEFLATED)
+ self.assertFalse(f.closed)
+ self.zipTest(TESTFN2, zipfile.ZIP_DEFLATED)
def tearDown(self):
for fname in TESTFN, TESTFN2:
import sys
import os
import marshal
+import importlib
import importlib.util
import struct
import time
TESTMOD = "ziptestmodule"
TESTPACK = "ziptestpackage"
TESTPACK2 = "ziptestpackage2"
+TEMP_DIR = os.path.abspath("junk95142")
TEMP_ZIP = os.path.abspath("junk95142.zip")
pyc_file = importlib.util.cache_from_source(TESTMOD + '.py')
def setUp(self):
# We're reusing the zip archive path, so we must clear the
- # cached directory info and linecache
+ # cached directory info and linecache.
linecache.clearcache()
zipimport._zip_directory_cache.clear()
ImportHooksBaseTestCase.setUp(self)
- def doTest(self, expected_ext, files, *modules, **kw):
- z = ZipFile(TEMP_ZIP, "w")
- try:
+ def makeTree(self, files, dirName=TEMP_DIR):
+ # Create a filesystem based set of modules/packages
+ # defined by files under the directory dirName.
+ self.addCleanup(support.rmtree, dirName)
+
+ for name, (mtime, data) in files.items():
+ path = os.path.join(dirName, name)
+ if path[-1] == os.sep:
+ if not os.path.isdir(path):
+ os.makedirs(path)
+ else:
+ dname = os.path.dirname(path)
+ if not os.path.isdir(dname):
+ os.makedirs(dname)
+ with open(path, 'wb') as fp:
+ fp.write(data)
+
+ def makeZip(self, files, zipName=TEMP_ZIP, **kw):
+ # Create a zip archive based set of modules/packages
+ # defined by files in the zip file zipName. If the
+ # key 'stuff' exists in kw it is prepended to the archive.
+ self.addCleanup(support.unlink, zipName)
+
+ with ZipFile(zipName, "w") as z:
for name, (mtime, data) in files.items():
zinfo = ZipInfo(name, time.localtime(mtime))
zinfo.compress_type = self.compression
z.writestr(zinfo, data)
- z.close()
- stuff = kw.get("stuff", None)
- if stuff is not None:
- # Prepend 'stuff' to the start of the zipfile
- with open(TEMP_ZIP, "rb") as f:
- data = f.read()
- with open(TEMP_ZIP, "wb") as f:
- f.write(stuff)
- f.write(data)
+ stuff = kw.get("stuff", None)
+ if stuff is not None:
+ # Prepend 'stuff' to the start of the zipfile
+ with open(zipName, "rb") as f:
+ data = f.read()
+ with open(zipName, "wb") as f:
+ f.write(stuff)
+ f.write(data)
+
+ def doTest(self, expected_ext, files, *modules, **kw):
+ self.makeZip(files, **kw)
- sys.path.insert(0, TEMP_ZIP)
+ sys.path.insert(0, TEMP_ZIP)
- mod = __import__(".".join(modules), globals(), locals(),
- ["__dummy__"])
+ mod = importlib.import_module(".".join(modules))
- call = kw.get('call')
- if call is not None:
- call(mod)
+ call = kw.get('call')
+ if call is not None:
+ call(mod)
- if expected_ext:
- file = mod.get_file()
- self.assertEqual(file, os.path.join(TEMP_ZIP,
+ if expected_ext:
+ file = mod.get_file()
+ self.assertEqual(file, os.path.join(TEMP_ZIP,
*modules) + expected_ext)
- finally:
- z.close()
- os.remove(TEMP_ZIP)
def testAFakeZlib(self):
#
packdir + TESTMOD + pyc_ext: (NOW, test_pyc)}
self.doTest(pyc_ext, files, TESTPACK, TESTMOD)
- def testDeepPackage(self):
+ def testSubPackage(self):
+ # Test that subpackages function when loaded from zip
+ # archives.
packdir = TESTPACK + os.sep
packdir2 = packdir + TESTPACK2 + os.sep
files = {packdir + "__init__" + pyc_ext: (NOW, test_pyc),
packdir2 + TESTMOD + pyc_ext: (NOW, test_pyc)}
self.doTest(pyc_ext, files, TESTPACK, TESTPACK2, TESTMOD)
+ def testSubNamespacePackage(self):
+ # Test that implicit namespace subpackages function
+ # when loaded from zip archives.
+ packdir = TESTPACK + os.sep
+ packdir2 = packdir + TESTPACK2 + os.sep
+ # The first two files are just directory entries (so have no data).
+ files = {packdir: (NOW, ""),
+ packdir2: (NOW, ""),
+ packdir2 + TESTMOD + pyc_ext: (NOW, test_pyc)}
+ self.doTest(pyc_ext, files, TESTPACK, TESTPACK2, TESTMOD)
+
+ def testMixedNamespacePackage(self):
+ # Test implicit namespace packages spread between a
+ # real filesystem and a zip archive.
+ packdir = TESTPACK + os.sep
+ packdir2 = packdir + TESTPACK2 + os.sep
+ packdir3 = packdir2 + TESTPACK + '3' + os.sep
+ files1 = {packdir: (NOW, ""),
+ packdir + TESTMOD + pyc_ext: (NOW, test_pyc),
+ packdir2: (NOW, ""),
+ packdir3: (NOW, ""),
+ packdir3 + TESTMOD + pyc_ext: (NOW, test_pyc),
+ packdir2 + TESTMOD + '3' + pyc_ext: (NOW, test_pyc),
+ packdir2 + TESTMOD + pyc_ext: (NOW, test_pyc)}
+ files2 = {packdir: (NOW, ""),
+ packdir + TESTMOD + '2' + pyc_ext: (NOW, test_pyc),
+ packdir2: (NOW, ""),
+ packdir2 + TESTMOD + '2' + pyc_ext: (NOW, test_pyc),
+ packdir2 + TESTMOD + pyc_ext: (NOW, test_pyc)}
+
+ zip1 = os.path.abspath("path1.zip")
+ self.makeZip(files1, zip1)
+
+ zip2 = TEMP_DIR
+ self.makeTree(files2, zip2)
+
+ # zip2 should override zip1.
+ sys.path.insert(0, zip1)
+ sys.path.insert(0, zip2)
+
+ mod = importlib.import_module(TESTPACK)
+
+ # if TESTPACK is functioning as a namespace pkg then
+ # there should be two entries in the __path__.
+ # First should be path2 and second path1.
+ self.assertEqual(2, len(mod.__path__))
+ p1, p2 = mod.__path__
+ self.assertEqual(os.path.basename(TEMP_DIR), p1.split(os.sep)[-2])
+ self.assertEqual("path1.zip", p2.split(os.sep)[-2])
+
+ # packdir3 should import as a namespace package.
+ # Its __path__ is an iterable of 1 element from zip1.
+ mod = importlib.import_module(packdir3.replace(os.sep, '.')[:-1])
+ self.assertEqual(1, len(mod.__path__))
+ mpath = list(mod.__path__)[0].split('path1.zip' + os.sep)[1]
+ self.assertEqual(packdir3[:-1], mpath)
+
+ # TESTPACK/TESTMOD only exists in path1.
+ mod = importlib.import_module('.'.join((TESTPACK, TESTMOD)))
+ self.assertEqual("path1.zip", mod.__file__.split(os.sep)[-3])
+
+ # And TESTPACK/(TESTMOD + '2') only exists in path2.
+ mod = importlib.import_module('.'.join((TESTPACK, TESTMOD + '2')))
+ self.assertEqual(os.path.basename(TEMP_DIR),
+ mod.__file__.split(os.sep)[-3])
+
+ # One level deeper...
+ subpkg = '.'.join((TESTPACK, TESTPACK2))
+ mod = importlib.import_module(subpkg)
+ self.assertEqual(2, len(mod.__path__))
+ p1, p2 = mod.__path__
+ self.assertEqual(os.path.basename(TEMP_DIR), p1.split(os.sep)[-3])
+ self.assertEqual("path1.zip", p2.split(os.sep)[-3])
+
+ # subpkg.TESTMOD exists in both zips should load from zip2.
+ mod = importlib.import_module('.'.join((subpkg, TESTMOD)))
+ self.assertEqual(os.path.basename(TEMP_DIR),
+ mod.__file__.split(os.sep)[-4])
+
+ # subpkg.TESTMOD + '2' only exists in zip2.
+ mod = importlib.import_module('.'.join((subpkg, TESTMOD + '2')))
+ self.assertEqual(os.path.basename(TEMP_DIR),
+ mod.__file__.split(os.sep)[-4])
+
+ # Finally subpkg.TESTMOD + '3' only exists in zip1.
+ mod = importlib.import_module('.'.join((subpkg, TESTMOD + '3')))
+ self.assertEqual('path1.zip', mod.__file__.split(os.sep)[-4])
+
+ def testNamespacePackage(self):
+ # Test implicit namespace packages spread between multiple zip
+ # archives.
+ packdir = TESTPACK + os.sep
+ packdir2 = packdir + TESTPACK2 + os.sep
+ packdir3 = packdir2 + TESTPACK + '3' + os.sep
+ files1 = {packdir: (NOW, ""),
+ packdir + TESTMOD + pyc_ext: (NOW, test_pyc),
+ packdir2: (NOW, ""),
+ packdir3: (NOW, ""),
+ packdir3 + TESTMOD + pyc_ext: (NOW, test_pyc),
+ packdir2 + TESTMOD + '3' + pyc_ext: (NOW, test_pyc),
+ packdir2 + TESTMOD + pyc_ext: (NOW, test_pyc)}
+ zip1 = os.path.abspath("path1.zip")
+ self.makeZip(files1, zip1)
+
+ files2 = {packdir: (NOW, ""),
+ packdir + TESTMOD + '2' + pyc_ext: (NOW, test_pyc),
+ packdir2: (NOW, ""),
+ packdir2 + TESTMOD + '2' + pyc_ext: (NOW, test_pyc),
+ packdir2 + TESTMOD + pyc_ext: (NOW, test_pyc)}
+ zip2 = os.path.abspath("path2.zip")
+ self.makeZip(files2, zip2)
+
+ # zip2 should override zip1.
+ sys.path.insert(0, zip1)
+ sys.path.insert(0, zip2)
+
+ mod = importlib.import_module(TESTPACK)
+
+ # if TESTPACK is functioning as a namespace pkg then
+ # there should be two entries in the __path__.
+ # First should be path2 and second path1.
+ self.assertEqual(2, len(mod.__path__))
+ p1, p2 = mod.__path__
+ self.assertEqual("path2.zip", p1.split(os.sep)[-2])
+ self.assertEqual("path1.zip", p2.split(os.sep)[-2])
+
+ # packdir3 should import as a namespace package.
+ # Tts __path__ is an iterable of 1 element from zip1.
+ mod = importlib.import_module(packdir3.replace(os.sep, '.')[:-1])
+ self.assertEqual(1, len(mod.__path__))
+ mpath = list(mod.__path__)[0].split('path1.zip' + os.sep)[1]
+ self.assertEqual(packdir3[:-1], mpath)
+
+ # TESTPACK/TESTMOD only exists in path1.
+ mod = importlib.import_module('.'.join((TESTPACK, TESTMOD)))
+ self.assertEqual("path1.zip", mod.__file__.split(os.sep)[-3])
+
+ # And TESTPACK/(TESTMOD + '2') only exists in path2.
+ mod = importlib.import_module('.'.join((TESTPACK, TESTMOD + '2')))
+ self.assertEqual("path2.zip", mod.__file__.split(os.sep)[-3])
+
+ # One level deeper...
+ subpkg = '.'.join((TESTPACK, TESTPACK2))
+ mod = importlib.import_module(subpkg)
+ self.assertEqual(2, len(mod.__path__))
+ p1, p2 = mod.__path__
+ self.assertEqual("path2.zip", p1.split(os.sep)[-3])
+ self.assertEqual("path1.zip", p2.split(os.sep)[-3])
+
+ # subpkg.TESTMOD exists in both zips should load from zip2.
+ mod = importlib.import_module('.'.join((subpkg, TESTMOD)))
+ self.assertEqual('path2.zip', mod.__file__.split(os.sep)[-4])
+
+ # subpkg.TESTMOD + '2' only exists in zip2.
+ mod = importlib.import_module('.'.join((subpkg, TESTMOD + '2')))
+ self.assertEqual('path2.zip', mod.__file__.split(os.sep)[-4])
+
+ # Finally subpkg.TESTMOD + '3' only exists in zip1.
+ mod = importlib.import_module('.'.join((subpkg, TESTMOD + '3')))
+ self.assertEqual('path1.zip', mod.__file__.split(os.sep)[-4])
+
def testZipImporterMethods(self):
packdir = TESTPACK + os.sep
packdir2 = packdir + TESTPACK2 + os.sep
mod = zi.load_module(TESTPACK)
self.assertEqual(zi.get_filename(TESTPACK), mod.__file__)
- existing_pack_path = __import__(TESTPACK).__path__[0]
+ existing_pack_path = importlib.import_module(TESTPACK).__path__[0]
expected_path_path = os.path.join(TEMP_ZIP, TESTPACK)
self.assertEqual(existing_pack_path, expected_path_path)
mod_path = packdir2 + TESTMOD
mod_name = module_path_to_dotted_name(mod_path)
- __import__(mod_name)
- mod = sys.modules[mod_name]
+ mod = importlib.import_module(mod_name)
+ self.assertTrue(mod_name in sys.modules)
self.assertEqual(zi.get_source(TESTPACK), None)
self.assertEqual(zi.get_source(mod_path), None)
self.assertEqual(zi.get_filename(mod_path), mod.__file__)
mod_path = TESTPACK2 + os.sep + TESTMOD
mod_name = module_path_to_dotted_name(mod_path)
- __import__(mod_name)
- mod = sys.modules[mod_name]
+ mod = importlib.import_module(mod_name)
+ self.assertTrue(mod_name in sys.modules)
self.assertEqual(zi.get_source(TESTPACK2), None)
self.assertEqual(zi.get_source(mod_path), None)
self.assertEqual(zi.get_filename(mod_path), mod.__file__)
# To pass in the module name instead of the path, we must use the
- # right importer
+ # right importer.
loader = mod.__loader__
self.assertEqual(loader.get_source(mod_name), None)
self.assertEqual(loader.get_filename(mod_name), mod.__file__)
self.assertEqual(zlib.adler32(b"", 1), 1)
self.assertEqual(zlib.adler32(b"", 432), 432)
- def assertEqual32(self, seen, expected):
- # 32-bit values masked -- checksums on 32- vs 64- bit machines
- # This is important if bit 31 (0x08000000L) is set.
- self.assertEqual(seen & 0x0FFFFFFFF, expected & 0x0FFFFFFFF)
-
def test_penguins(self):
- self.assertEqual32(zlib.crc32(b"penguin", 0), 0x0e5c1a120)
- self.assertEqual32(zlib.crc32(b"penguin", 1), 0x43b6aa94)
- self.assertEqual32(zlib.adler32(b"penguin", 0), 0x0bcf02f6)
- self.assertEqual32(zlib.adler32(b"penguin", 1), 0x0bd602f7)
+ self.assertEqual(zlib.crc32(b"penguin", 0), 0x0e5c1a120)
+ self.assertEqual(zlib.crc32(b"penguin", 1), 0x43b6aa94)
+ self.assertEqual(zlib.adler32(b"penguin", 0), 0x0bcf02f6)
+ self.assertEqual(zlib.adler32(b"penguin", 1), 0x0bd602f7)
self.assertEqual(zlib.crc32(b"penguin"), zlib.crc32(b"penguin", 0))
self.assertEqual(zlib.adler32(b"penguin"),zlib.adler32(b"penguin",1))
self.assertEqual(zlib.decompress(ob), data)
def test_incomplete_stream(self):
- # An useful error message is given
+ # A useful error message is given
x = zlib.compress(HAMLET_SCENE)
self.assertRaisesRegex(zlib.error,
"Error -5 while decompressing data: incomplete or truncated stream",
self.assertEqual(dco.unconsumed_tail, b'')
self.assertEqual(dco.unused_data, remainder)
+ # issue27164
+ def test_decompress_raw_with_dictionary(self):
+ zdict = b'abcdefghijklmnopqrstuvwxyz'
+ co = zlib.compressobj(wbits=-zlib.MAX_WBITS, zdict=zdict)
+ comp = co.compress(zdict) + co.flush()
+ dco = zlib.decompressobj(wbits=-zlib.MAX_WBITS, zdict=zdict)
+ uncomp = dco.decompress(comp) + dco.flush()
+ self.assertEqual(zdict, uncomp)
+
def test_flush_with_freed_input(self):
# Issue #16411: decompressor accesses input to last decompress() call
# in flush(), even if this object has been freed in the meanwhile.
finally:
data = None
+ def test_wbits(self):
+ # wbits=0 only supported since zlib v1.2.3.5
+ # Register "1.2.3" as "1.2.3.0"
+ v = (zlib.ZLIB_RUNTIME_VERSION + ".0").split(".", 4)
+ supports_wbits_0 = int(v[0]) > 1 or int(v[0]) == 1 \
+ and (int(v[1]) > 2 or int(v[1]) == 2
+ and (int(v[2]) > 3 or int(v[2]) == 3 and int(v[3]) >= 5))
+
+ co = zlib.compressobj(level=1, wbits=15)
+ zlib15 = co.compress(HAMLET_SCENE) + co.flush()
+ self.assertEqual(zlib.decompress(zlib15, 15), HAMLET_SCENE)
+ if supports_wbits_0:
+ self.assertEqual(zlib.decompress(zlib15, 0), HAMLET_SCENE)
+ self.assertEqual(zlib.decompress(zlib15, 32 + 15), HAMLET_SCENE)
+ with self.assertRaisesRegex(zlib.error, 'invalid window size'):
+ zlib.decompress(zlib15, 14)
+ dco = zlib.decompressobj(wbits=32 + 15)
+ self.assertEqual(dco.decompress(zlib15), HAMLET_SCENE)
+ dco = zlib.decompressobj(wbits=14)
+ with self.assertRaisesRegex(zlib.error, 'invalid window size'):
+ dco.decompress(zlib15)
+
+ co = zlib.compressobj(level=1, wbits=9)
+ zlib9 = co.compress(HAMLET_SCENE) + co.flush()
+ self.assertEqual(zlib.decompress(zlib9, 9), HAMLET_SCENE)
+ self.assertEqual(zlib.decompress(zlib9, 15), HAMLET_SCENE)
+ if supports_wbits_0:
+ self.assertEqual(zlib.decompress(zlib9, 0), HAMLET_SCENE)
+ self.assertEqual(zlib.decompress(zlib9, 32 + 9), HAMLET_SCENE)
+ dco = zlib.decompressobj(wbits=32 + 9)
+ self.assertEqual(dco.decompress(zlib9), HAMLET_SCENE)
+
+ co = zlib.compressobj(level=1, wbits=-15)
+ deflate15 = co.compress(HAMLET_SCENE) + co.flush()
+ self.assertEqual(zlib.decompress(deflate15, -15), HAMLET_SCENE)
+ dco = zlib.decompressobj(wbits=-15)
+ self.assertEqual(dco.decompress(deflate15), HAMLET_SCENE)
+
+ co = zlib.compressobj(level=1, wbits=-9)
+ deflate9 = co.compress(HAMLET_SCENE) + co.flush()
+ self.assertEqual(zlib.decompress(deflate9, -9), HAMLET_SCENE)
+ self.assertEqual(zlib.decompress(deflate9, -15), HAMLET_SCENE)
+ dco = zlib.decompressobj(wbits=-9)
+ self.assertEqual(dco.decompress(deflate9), HAMLET_SCENE)
+
+ co = zlib.compressobj(level=1, wbits=16 + 15)
+ gzip = co.compress(HAMLET_SCENE) + co.flush()
+ self.assertEqual(zlib.decompress(gzip, 16 + 15), HAMLET_SCENE)
+ self.assertEqual(zlib.decompress(gzip, 32 + 15), HAMLET_SCENE)
+ dco = zlib.decompressobj(32 + 15)
+ self.assertEqual(dco.decompress(gzip), HAMLET_SCENE)
+
def genblock(seed, length, step=1024, generator=random):
"""length-byte stream of random data from a seed (in step-byte blocks)."""
# IMPORTANT: this file has the utf-8 BOM signature '\xef\xbb\xbf'
# at the start of it. Make sure this is preserved if any changes
# are made! Also note that the coding cookie above conflicts with
-# the presense of a utf-8 BOM signature -- this is intended.
+# the presence of a utf-8 BOM signature -- this is intended.
# Arbitrary encoded utf-8 text (stolen from test_doctest2.py).
x = 'ЉЊЈЁЂ'
--- /dev/null
+-----BEGIN RSA PRIVATE KEY-----
+MIICXAIBAAKBgQC89ZNxjTgWgq7Z1g0tJ65w+k7lNAj5IgjLb155UkUrz0XsHDnH
+FlbsVUg2Xtk6+bo2UEYIzN7cIm5ImpmyW/2z0J1IDVDlvR2xJ659xrE0v5c2cB6T
+f9lnNTwpSoeK24Nd7Jwq4j9vk95fLrdqsBq0/KVlsCXeixS/CaqqduXfvwIDAQAB
+AoGAQFko4uyCgzfxr4Ezb4Mp5pN3Npqny5+Jey3r8EjSAX9Ogn+CNYgoBcdtFgbq
+1yif/0sK7ohGBJU9FUCAwrqNBI9ZHB6rcy7dx+gULOmRBGckln1o5S1+smVdmOsW
+7zUVLBVByKuNWqTYFlzfVd6s4iiXtAE2iHn3GCyYdlICwrECQQDhMQVxHd3EFbzg
+SFmJBTARlZ2GKA3c1g/h9/XbkEPQ9/RwI3vnjJ2RaSnjlfoLl8TOcf0uOGbOEyFe
+19RvCLXjAkEA1s+UE5ziF+YVkW3WolDCQ2kQ5WG9+ccfNebfh6b67B7Ln5iG0Sbg
+ky9cjsO3jbMJQtlzAQnH1850oRD5Gi51dQJAIbHCDLDZU9Ok1TI+I2BhVuA6F666
+lEZ7TeZaJSYq34OaUYUdrwG9OdqwZ9sy9LUav4ESzu2lhEQchCJrKMn23QJAReqs
+ZLHUeTjfXkVk7dHhWPWSlUZ6AhmIlA/AQ7Payg2/8wM/JkZEJEPvGVykms9iPUrv
+frADRr+hAGe43IewnQJBAJWKZllPgKuEBPwoEldHNS8nRu61D7HzxEzQ2xnfj+Nk
+2fgf1MAzzTRsikfGENhVsVWeqOcijWb6g5gsyCmlRpc=
+-----END RSA PRIVATE KEY-----
+-----BEGIN CERTIFICATE-----
+MIICsDCCAhmgAwIBAgIJAOqYOYFJfEEoMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
+BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX
+aWRnaXRzIFB0eSBMdGQwHhcNMDgwNjI2MTgxNTUyWhcNMDkwNjI2MTgxNTUyWjBF
+MQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50
+ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
+gQC89ZNxjTgWgq7Z1g0tJ65w+k7lNAj5IgjLb155UkUrz0XsHDnHFlbsVUg2Xtk6
++bo2UEYIzN7cIm5ImpmyW/2z0J1IDVDlvR2xJ659xrE0v5c2cB6Tf9lnNTwpSoeK
+24Nd7Jwq4j9vk95fLrdqsBq0/KVlsCXeixS/CaqqduXfvwIDAQABo4GnMIGkMB0G
+A1UdDgQWBBTctMtI3EO9OjLI0x9Zo2ifkwIiNjB1BgNVHSMEbjBsgBTctMtI3EO9
+OjLI0x9Zo2ifkwIiNqFJpEcwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUt
+U3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZIIJAOqYOYFJ
+fEEoMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAQwa7jya/DfhaDn7E
+usPkpgIX8WCL2B1SqnRTXEZfBPPVq/cUmFGyEVRVATySRuMwi8PXbVcOhXXuocA+
+43W+iIsD9pXapCZhhOerCq18TC1dWK98vLUsoK8PMjB6e5H/O8bqojv0EeC+fyCw
+eSHj5jpC8iZKjCHBn+mAi4cQ514=
+-----END CERTIFICATE-----
# self.
if _sys and _sys.stderr is not None:
print("Exception in thread %s:\n%s" %
- (self.name, _format_exc()), file=self._stderr)
+ (self.name, _format_exc()), file=_sys.stderr)
elif self._stderr is not None:
# Do the best job possible w/o a huge amt. of code to
# approximate a traceback (code ideas from
# Issue #18808: wait for the thread state to be gone.
# At the end of the thread's life, after all knowledge of the thread
# is removed from C data structures, C code releases our _tstate_lock.
- # This method passes its arguments to _tstate_lock.aquire().
+ # This method passes its arguments to _tstate_lock.acquire().
# If the lock is acquired, the C code is done, and self._stop() is
# called. That sets ._is_stopped to True, and ._tstate_lock to None.
lock = self._tstate_lock
nsign, b, f, h, k, s, t, w, x, y, A, E, K, N, W, T, X, Y, D = args
# Missing: (a, c, d, m, o, v, B, R)
e = Event()
- # serial field: valid vor all events
+ # serial field: valid for all events
# number of button: ButtonPress and ButtonRelease events only
# height field: Configure, ConfigureRequest, Create,
# ResizeRequest, and Expose events only
# time field: "valid for events that contain a time field"
# width field: Configure, ConfigureRequest, Create, ResizeRequest,
# and Expose events only
- # x field: "valid for events that contain a x field"
+ # x field: "valid for events that contain an x field"
# y field: "valid for events that contain a y field"
# keysym as decimal: KeyPress and KeyRelease events only
# x_root, y_root fields: ButtonPress, ButtonRelease, KeyPress,
- # KeyRelease,and Motion events
+ # KeyRelease, and Motion events
e.serial = getint(nsign)
e.num = getint_event(b)
try: e.focus = getboolean(f)
self.configure({key: value})
def keys(self):
"""Return a list of all resource names of this widget."""
- return [x[0][1:] for x in
- self.tk.splitlist(self.tk.call(self._w, 'configure'))]
+ splitlist = self.tk.splitlist
+ return [splitlist(x)[0][1:] for x in
+ splitlist(self.tk.call(self._w, 'configure'))]
def __str__(self):
"""Return the window path name of this widget."""
return self._w
self.tk.call(self._w, 'toggle')
class Entry(Widget, XView):
- """Entry widget which allows to display simple text."""
+ """Entry widget which allows displaying simple text."""
def __init__(self, master=None, cnf={}, **kw):
"""Construct an entry widget with the parent MASTER.
itemconfig = itemconfigure
class Menu(Widget):
- """Menu widget which allows to display menu bars, pull-down menus and pop-up menus."""
+ """Menu widget which allows displaying menu bars, pull-down menus and pop-up menus."""
def __init__(self, master=None, cnf={}, **kw):
"""Construct menu widget with the parent MASTER.
self.deletecommand(c)
self.tk.call(self._w, 'delete', index1, index2)
def entrycget(self, index, option):
- """Return the resource value of an menu item for OPTION at INDEX."""
+ """Return the resource value of a menu item for OPTION at INDEX."""
return self.tk.call(self._w, 'entrycget', index, '-' + option)
def entryconfigure(self, index, cnf=None, **kw):
"""Configure a menu item at INDEX."""
"""Creates a peer text widget with the given newPathName, and any
optional standard configuration options. By default the peer will
have the same start and end line as the parent widget, but
- these can be overriden with the standard configuration options."""
+ these can be overridden with the standard configuration options."""
self.tk.call(self._w, 'peer', 'create', newPathName,
*self._options(cnf, kw))
def peer_names(self): # new in Tk 8.5
destImage = PhotoImage(master=self.tk)
self.tk.call(destImage, 'copy', self.name)
return destImage
- def zoom(self,x,y=''):
+ def zoom(self, x, y=''):
"""Return a new PhotoImage with the same image as this widget
- but zoom it with X and Y."""
+ but zoom it with a factor of x in the X direction and y in the Y
+ direction. If y is not given, the default value is the same as x.
+ """
destImage = PhotoImage(master=self.tk)
if y=='': y=x
self.tk.call(destImage, 'copy', self.name, '-zoom',x,y)
return destImage
- def subsample(self,x,y=''):
+ def subsample(self, x, y=''):
"""Return a new PhotoImage based on the same image as this widget
- but use only every Xth or Yth pixel."""
+ but use only every Xth or Yth pixel. If y is not given, the
+ default value is the same as x.
+ """
destImage = PhotoImage(master=self.tk)
if y=='': y=x
self.tk.call(destImage, 'copy', self.name, '-subsample',x,y)
This is very preliminary. I currently only support dnd *within* one
application, between different windows (or within the same window).
-I an trying to make this as generic as possible -- not dependent on
+I am trying to make this as generic as possible -- not dependent on
the use of a particular widget or icon type, etc. I also hope that
this will work with Pmw.
class PackTest(AbstractWidgetTest, unittest.TestCase):
+ test_keys = None
+
def create2(self):
pack = tkinter.Toplevel(self.root, name='pack')
pack.wm_geometry('300x200+0+0')
class PlaceTest(AbstractWidgetTest, unittest.TestCase):
+ test_keys = None
+
def create2(self):
t = tkinter.Toplevel(self.root, width=300, height=200, bd=0)
t.wm_geometry('300x200+0+0')
class GridTest(AbstractWidgetTest, unittest.TestCase):
+ test_keys = None
+
def tearDown(self):
cols, rows = self.root.grid_size()
for i in range(cols + 1):
'background', 'borderwidth',
'class', 'colormap', 'container', 'cursor', 'height',
'highlightbackground', 'highlightcolor', 'highlightthickness',
- 'relief', 'takefocus', 'visual', 'width',
+ 'padx', 'pady', 'relief', 'takefocus', 'visual', 'width',
)
def create(self, **kwargs):
'highlightbackground', 'highlightcolor', 'highlightthickness',
'insertbackground', 'insertborderwidth',
'insertofftime', 'insertontime', 'insertwidth',
- 'relief', 'scrollregion',
+ 'offset', 'relief', 'scrollregion',
'selectbackground', 'selectborderwidth', 'selectforeground',
'state', 'takefocus',
'xscrollcommand', 'xscrollincrement',
widget = self.create()
self.checkBooleanParam(widget, 'confine')
+ def test_offset(self):
+ widget = self.create()
+ self.assertEqual(widget['offset'], '0,0')
+ self.checkParams(widget, 'offset',
+ 'n', 'ne', 'e', 'se', 's', 'sw', 'w', 'nw', 'center')
+ self.checkParam(widget, 'offset', '10,20')
+ self.checkParam(widget, 'offset', '#5,6')
+ self.checkInvalidParam(widget, 'offset', 'spam')
+
def test_scrollregion(self):
widget = self.create()
self.checkParam(widget, 'scrollregion', '0 0 200 150')
## Testing type = vsapi
# vsapi type expects at least a class name and a part_id, so this
- # should raise an ValueError since it tries to get two elements from
+ # should raise a ValueError since it tries to get two elements from
# an empty tuple
self.assertRaises(ValueError, ttk._format_elemcreate, 'vsapi')
@add_standard_options(StandardTtkOptionsTests)
class LabelTest(AbstractLabelTest, unittest.TestCase):
OPTIONS = (
- 'anchor', 'background',
+ 'anchor', 'background', 'borderwidth',
'class', 'compound', 'cursor', 'font', 'foreground',
'image', 'justify', 'padding', 'relief', 'state', 'style',
'takefocus', 'text', 'textvariable',
class ButtonTest(AbstractLabelTest, unittest.TestCase):
OPTIONS = (
'class', 'command', 'compound', 'cursor', 'default',
- 'image', 'state', 'style', 'takefocus', 'text', 'textvariable',
+ 'image', 'padding', 'state', 'style',
+ 'takefocus', 'text', 'textvariable',
'underline', 'width',
)
'class', 'command', 'compound', 'cursor',
'image',
'offvalue', 'onvalue',
- 'state', 'style',
+ 'padding', 'state', 'style',
'takefocus', 'text', 'textvariable',
'underline', 'variable', 'width',
)
@add_standard_options(IntegerSizeTests, StandardTtkOptionsTests)
-class ComboboxTest(AbstractWidgetTest, unittest.TestCase):
- OPTIONS = (
- 'class', 'cursor', 'exportselection', 'height',
- 'justify', 'postcommand', 'state', 'style',
- 'takefocus', 'textvariable', 'values', 'width',
- )
-
- def setUp(self):
- super().setUp()
- self.combo = self.create()
-
- def create(self, **kwargs):
- return ttk.Combobox(self.root, **kwargs)
-
- def test_height(self):
- widget = self.create()
- self.checkParams(widget, 'height', 100, 101.2, 102.6, -100, 0, '1i')
-
- def test_state(self):
- widget = self.create()
- self.checkParams(widget, 'state', 'active', 'disabled', 'normal')
-
- def _show_drop_down_listbox(self):
- width = self.combo.winfo_width()
- self.combo.event_generate('<ButtonPress-1>', x=width - 5, y=5)
- self.combo.event_generate('<ButtonRelease-1>', x=width - 5, y=5)
- self.combo.update_idletasks()
-
-
- def test_virtual_event(self):
- success = []
-
- self.combo['values'] = [1]
- self.combo.bind('<<ComboboxSelected>>',
- lambda evt: success.append(True))
- self.combo.pack()
- self.combo.wait_visibility()
-
- height = self.combo.winfo_height()
- self._show_drop_down_listbox()
- self.combo.update()
- self.combo.event_generate('<Return>')
- self.combo.update()
-
- self.assertTrue(success)
-
-
- def test_postcommand(self):
- success = []
-
- self.combo['postcommand'] = lambda: success.append(True)
- self.combo.pack()
- self.combo.wait_visibility()
-
- self._show_drop_down_listbox()
- self.assertTrue(success)
-
- # testing postcommand removal
- self.combo['postcommand'] = ''
- self._show_drop_down_listbox()
- self.assertEqual(len(success), 1)
-
-
- def test_values(self):
- def check_get_current(getval, currval):
- self.assertEqual(self.combo.get(), getval)
- self.assertEqual(self.combo.current(), currval)
-
- self.assertEqual(self.combo['values'],
- () if tcl_version < (8, 5) else '')
- check_get_current('', -1)
-
- self.checkParam(self.combo, 'values', 'mon tue wed thur',
- expected=('mon', 'tue', 'wed', 'thur'))
- self.checkParam(self.combo, 'values', ('mon', 'tue', 'wed', 'thur'))
- self.checkParam(self.combo, 'values', (42, 3.14, '', 'any string'))
- self.checkParam(self.combo, 'values', '',
- expected='' if get_tk_patchlevel() < (8, 5, 10) else ())
-
- self.combo['values'] = ['a', 1, 'c']
-
- self.combo.set('c')
- check_get_current('c', 2)
-
- self.combo.current(0)
- check_get_current('a', 0)
-
- self.combo.set('d')
- check_get_current('d', -1)
-
- # testing values with empty string
- self.combo.set('')
- self.combo['values'] = (1, 2, '', 3)
- check_get_current('', 2)
-
- # testing values with empty string set through configure
- self.combo.configure(values=[1, '', 2])
- self.assertEqual(self.combo['values'],
- ('1', '', '2') if self.wantobjects else
- '1 {} 2')
-
- # testing values with spaces
- self.combo['values'] = ['a b', 'a\tb', 'a\nb']
- self.assertEqual(self.combo['values'],
- ('a b', 'a\tb', 'a\nb') if self.wantobjects else
- '{a b} {a\tb} {a\nb}')
-
- # testing values with special characters
- self.combo['values'] = [r'a\tb', '"a"', '} {']
- self.assertEqual(self.combo['values'],
- (r'a\tb', '"a"', '} {') if self.wantobjects else
- r'a\\tb {"a"} \}\ \{')
-
- # out of range
- self.assertRaises(tkinter.TclError, self.combo.current,
- len(self.combo['values']))
- # it expects an integer (or something that can be converted to int)
- self.assertRaises(tkinter.TclError, self.combo.current, '')
-
- # testing creating combobox with empty string in values
- combo2 = ttk.Combobox(self.root, values=[1, 2, ''])
- self.assertEqual(combo2['values'],
- ('1', '2', '') if self.wantobjects else '1 2 {}')
- combo2.destroy()
-
-
-@add_standard_options(IntegerSizeTests, StandardTtkOptionsTests)
class EntryTest(AbstractWidgetTest, unittest.TestCase):
OPTIONS = (
'background', 'class', 'cursor',
- 'exportselection', 'font',
+ 'exportselection', 'font', 'foreground',
'invalidcommand', 'justify',
'show', 'state', 'style', 'takefocus', 'textvariable',
'validate', 'validatecommand', 'width', 'xscrollcommand',
@add_standard_options(IntegerSizeTests, StandardTtkOptionsTests)
+class ComboboxTest(EntryTest, unittest.TestCase):
+ OPTIONS = (
+ 'background', 'class', 'cursor', 'exportselection',
+ 'font', 'foreground', 'height', 'invalidcommand',
+ 'justify', 'postcommand', 'show', 'state', 'style',
+ 'takefocus', 'textvariable',
+ 'validate', 'validatecommand', 'values',
+ 'width', 'xscrollcommand',
+ )
+
+ def setUp(self):
+ super().setUp()
+ self.combo = self.create()
+
+ def create(self, **kwargs):
+ return ttk.Combobox(self.root, **kwargs)
+
+ def test_height(self):
+ widget = self.create()
+ self.checkParams(widget, 'height', 100, 101.2, 102.6, -100, 0, '1i')
+
+ def _show_drop_down_listbox(self):
+ width = self.combo.winfo_width()
+ self.combo.event_generate('<ButtonPress-1>', x=width - 5, y=5)
+ self.combo.event_generate('<ButtonRelease-1>', x=width - 5, y=5)
+ self.combo.update_idletasks()
+
+
+ def test_virtual_event(self):
+ success = []
+
+ self.combo['values'] = [1]
+ self.combo.bind('<<ComboboxSelected>>',
+ lambda evt: success.append(True))
+ self.combo.pack()
+ self.combo.wait_visibility()
+
+ height = self.combo.winfo_height()
+ self._show_drop_down_listbox()
+ self.combo.update()
+ self.combo.event_generate('<Return>')
+ self.combo.update()
+
+ self.assertTrue(success)
+
+
+ def test_postcommand(self):
+ success = []
+
+ self.combo['postcommand'] = lambda: success.append(True)
+ self.combo.pack()
+ self.combo.wait_visibility()
+
+ self._show_drop_down_listbox()
+ self.assertTrue(success)
+
+ # testing postcommand removal
+ self.combo['postcommand'] = ''
+ self._show_drop_down_listbox()
+ self.assertEqual(len(success), 1)
+
+
+ def test_values(self):
+ def check_get_current(getval, currval):
+ self.assertEqual(self.combo.get(), getval)
+ self.assertEqual(self.combo.current(), currval)
+
+ self.assertEqual(self.combo['values'],
+ () if tcl_version < (8, 5) else '')
+ check_get_current('', -1)
+
+ self.checkParam(self.combo, 'values', 'mon tue wed thur',
+ expected=('mon', 'tue', 'wed', 'thur'))
+ self.checkParam(self.combo, 'values', ('mon', 'tue', 'wed', 'thur'))
+ self.checkParam(self.combo, 'values', (42, 3.14, '', 'any string'))
+ self.checkParam(self.combo, 'values', '',
+ expected='' if get_tk_patchlevel() < (8, 5, 10) else ())
+
+ self.combo['values'] = ['a', 1, 'c']
+
+ self.combo.set('c')
+ check_get_current('c', 2)
+
+ self.combo.current(0)
+ check_get_current('a', 0)
+
+ self.combo.set('d')
+ check_get_current('d', -1)
+
+ # testing values with empty string
+ self.combo.set('')
+ self.combo['values'] = (1, 2, '', 3)
+ check_get_current('', 2)
+
+ # testing values with empty string set through configure
+ self.combo.configure(values=[1, '', 2])
+ self.assertEqual(self.combo['values'],
+ ('1', '', '2') if self.wantobjects else
+ '1 {} 2')
+
+ # testing values with spaces
+ self.combo['values'] = ['a b', 'a\tb', 'a\nb']
+ self.assertEqual(self.combo['values'],
+ ('a b', 'a\tb', 'a\nb') if self.wantobjects else
+ '{a b} {a\tb} {a\nb}')
+
+ # testing values with special characters
+ self.combo['values'] = [r'a\tb', '"a"', '} {']
+ self.assertEqual(self.combo['values'],
+ (r'a\tb', '"a"', '} {') if self.wantobjects else
+ r'a\\tb {"a"} \}\ \{')
+
+ # out of range
+ self.assertRaises(tkinter.TclError, self.combo.current,
+ len(self.combo['values']))
+ # it expects an integer (or something that can be converted to int)
+ self.assertRaises(tkinter.TclError, self.combo.current, '')
+
+ # testing creating combobox with empty string in values
+ combo2 = ttk.Combobox(self.root, values=[1, 2, ''])
+ self.assertEqual(combo2['values'],
+ ('1', '2', '') if self.wantobjects else '1 2 {}')
+ combo2.destroy()
+
+
+@add_standard_options(IntegerSizeTests, StandardTtkOptionsTests)
class PanedWindowTest(AbstractWidgetTest, unittest.TestCase):
OPTIONS = (
'class', 'cursor', 'height',
OPTIONS = (
'class', 'command', 'compound', 'cursor',
'image',
- 'state', 'style',
+ 'padding', 'state', 'style',
'takefocus', 'text', 'textvariable',
'underline', 'value', 'variable', 'width',
)
class MenubuttonTest(AbstractLabelTest, unittest.TestCase):
OPTIONS = (
'class', 'compound', 'cursor', 'direction',
- 'image', 'menu', 'state', 'style',
+ 'image', 'menu', 'padding', 'state', 'style',
'takefocus', 'text', 'textvariable',
'underline', 'width',
)
@add_standard_options(IntegerSizeTests, StandardTtkOptionsTests)
class NotebookTest(AbstractWidgetTest, unittest.TestCase):
OPTIONS = (
- 'class', 'cursor', 'height', 'padding', 'style', 'takefocus',
+ 'class', 'cursor', 'height', 'padding', 'style', 'takefocus', 'width',
)
def setUp(self):
break
+ def test_keys(self):
+ widget = self.create()
+ keys = widget.keys()
+ # XXX
+ if not isinstance(widget, Scale):
+ self.assertEqual(sorted(keys), sorted(widget.configure()))
+ for k in keys:
+ widget[k]
+ # Test if OPTIONS contains all keys
+ if test.support.verbose:
+ aliases = {
+ 'bd': 'borderwidth',
+ 'bg': 'background',
+ 'fg': 'foreground',
+ 'invcmd': 'invalidcommand',
+ 'vcmd': 'validatecommand',
+ }
+ keys = set(keys)
+ expected = set(self.OPTIONS)
+ for k in sorted(keys - expected):
+ if not (k in aliases and
+ aliases[k] in keys and
+ aliases[k] in expected):
+ print('%s.OPTIONS doesn\'t contain "%s"' %
+ (self.__class__.__name__, k))
+
+
class StandardOptionsTests:
STANDARD_OPTIONS = (
'activebackground', 'activeborderwidth', 'activeforeground', 'anchor',
self.tk.eval('package require Tix')
def destroy(self):
- # For safety, remove an delete_window binding before destroy
+ # For safety, remove the delete_window binding before destroy
self.protocol("WM_DELETE_WINDOW", "")
tkinter.Tk.destroy(self)
class ExFileSelectBox(TixWidget):
"""ExFileSelectBox - MS Windows style file select box.
- It provides an convenient method for the user to select files.
+ It provides a convenient method for the user to select files.
Subwidget Class
--------- -----
# Should inherit from a Dialog class
class ExFileSelectDialog(TixWidget):
"""ExFileSelectDialog - MS Windows style file select dialog.
- It provides an convenient method for the user to select files.
+ It provides a convenient method for the user to select files.
Subwidgets Class
---------- -----
class LabelEntry(TixWidget):
"""LabelEntry - Entry field with label. Packages an entry widget
- and a label into one mega widget. It can beused be used to simplify
- the creation of ``entry-form'' type of interface.
+ and a label into one mega widget. It can be used to simplify the creation
+ of ``entry-form'' type of interface.
Subwidgets Class
---------- -----
"""Begin autoincrement mode: schedules a recurring timer event
that calls method step every interval milliseconds.
- interval defaults to 50 milliseconds (20 steps/second) if ommited."""
+ interval defaults to 50 milliseconds (20 steps/second) if omitted."""
self.tk.call(self._w, "start", interval)
can be accessed through instance.label"""
def __init__(self, master=None, variable=None, from_=0, to=10, **kw):
- """Construct an horizontal LabeledScale with parent master, a
+ """Construct a horizontal LabeledScale with parent master, a
variable to be associated with the Ttk Scale widget and its range.
If variable is not specified, a tkinter.IntVar is created.
import sys
from token import *
-cookie_re = re.compile(r'^[ \t\f]*#.*coding[:=][ \t]*([-\w.]+)', re.ASCII)
+cookie_re = re.compile(r'^[ \t\f]*#.*?coding[:=][ \t]*([-\w.]+)', re.ASCII)
blank_re = re.compile(br'^[ \t\f]*(?:[#\r\n]|$)', re.ASCII)
import token
Round-trip invariant for full input:
Untokenized source will match input source exactly
- Round-trip invariant for limited intput:
- # Output bytes will tokenize the back to the input
+ Round-trip invariant for limited input:
+ # Output bytes will tokenize back to the input
t1 = [tok[:2] for tok in tokenize(f.readline)]
newcode = untokenize(t1)
readline = BytesIO(newcode).readline
def tokenize(readline):
"""
- The tokenize() generator requires one argment, readline, which
+ The tokenize() generator requires one argument, readline, which
must be a callable object which provides the same interface as the
readline() method of built-in file objects. Each call to the function
- should return one line of input as bytes. Alternately, readline
+ should return one line of input as bytes. Alternatively, readline
can be a callable function terminating with StopIteration:
readline = open(myfile, 'rb').__next__ # Example of alternate readline
return list(TracebackException(etype, value, None).format_exception_only())
-# -- not offical API but folk probably use these two functions.
+# -- not official API but folk probably use these two functions.
def _format_final_exc_line(etype, value):
valuestr = _some_str(value)
- :attr:`stack` A `StackSummary` representing the traceback.
- :attr:`exc_type` The class of the original traceback.
- :attr:`filename` For syntax errors - the filename where the error
- occured.
+ occurred.
- :attr:`lineno` For syntax errors - the linenumber where the error
- occured.
+ occurred.
- :attr:`text` For syntax errors - the text where the error
- occured.
+ occurred.
- :attr:`offset` For syntax errors - the offset into the text where the
- error occured.
+ error occurred.
- :attr:`msg` For syntax errors - the compiler error message.
"""
import os
from tkinter import *
+from idlelib.ColorDelegator import ColorDelegator, color_config
from idlelib.Percolator import Percolator
-from idlelib.ColorDelegator import ColorDelegator
from idlelib.textView import view_text
from turtledemo import __doc__ as about_turtledemo
('About turtle module', turtle.__doc__),
)
+
+
class DemoWindow(object):
def __init__(self, filename=None):
self.text_frame = text_frame = Frame(root)
self.text = text = Text(text_frame, name='text', padx=5,
wrap='none', width=45)
+ color_config(text)
self.vbar = vbar = Scrollbar(text_frame, name='vbar')
vbar['command'] = text.yview
-# TODO nits:
-# Get rid of asserts that are the caller's fault.
-# Docstrings (e.g. ABCs).
-
import abc
from abc import abstractmethod, abstractproperty
import collections
+import contextlib
import functools
import re as stdlib_re # Avoid confusion with the re we export.
import sys
'Callable',
'Generic',
'Optional',
+ 'Tuple',
+ 'Type',
'TypeVar',
'Union',
- 'Tuple',
# ABCs (from collections.abc).
'AbstractSet', # collections.abc.Set.
+ 'Awaitable',
+ 'AsyncIterator',
+ 'AsyncIterable',
'ByteString',
'Container',
'Hashable',
# Concrete collection types.
'Dict',
+ 'DefaultDict',
'List',
'Set',
'NamedTuple', # Not really a type.
'AnyStr',
'cast',
'get_type_hints',
+ 'NewType',
'no_type_check',
'no_type_check_decorator',
'overload',
-
- # Submodules.
- 'io',
- 're',
+ 'Text',
+ 'TYPE_CHECKING',
]
+# The pseudo-submodules 're' and 'io' are part of the public
+# namespace, but excluded from __all__ because they might stomp on
+# legitimate imports of those modules.
+
def _qualname(x):
if sys.version_info[:2] >= (3, 3):
"""
return self
- def _has_type_var(self):
- return False
+ def _get_type_vars(self, tvars):
+ pass
def __repr__(self):
return '%s.%s' % (self.__module__, _qualname(self))
someone tries to subclass a type alias (not a good idea).
"""
if (len(args) == 3 and
- isinstance(args[0], str) and
- isinstance(args[1], tuple)):
+ isinstance(args[0], str) and
+ isinstance(args[1], tuple)):
# Close enough.
raise TypeError("A type alias cannot be subclassed")
return object.__new__(cls)
return issubclass(cls, self.impl_type)
-def _has_type_var(t):
- return t is not None and isinstance(t, TypingMeta) and t._has_type_var()
+def _get_type_vars(types, tvars):
+ for t in types:
+ if isinstance(t, TypingMeta):
+ t._get_type_vars(tvars)
+
+
+def _type_vars(types):
+ tvars = []
+ _get_type_vars(types, tvars)
+ return tuple(tvars)
def _eval_type(t, globalns, localns):
return type(None)
if isinstance(arg, str):
arg = _ForwardRef(arg)
- if not isinstance(arg, (type, _TypeAlias)):
+ if not isinstance(arg, (type, _TypeAlias)) and not callable(arg):
raise TypeError(msg + " Got %.100r." % (arg,))
return arg
At runtime, isinstance(x, T) will raise TypeError. However,
issubclass(C, T) is true for any class C, and issubclass(str, A)
and issubclass(bytes, A) are true, and issubclass(int, A) is
- false.
+ false. (TODO: Why is this needed? This may change. See #136.)
Type variables may be marked covariant or contravariant by passing
covariant=True or contravariant=True. See PEP 484 for more
self.__bound__ = None
return self
- def _has_type_var(self):
- return True
+ def _get_type_vars(self, tvars):
+ if self not in tvars:
+ tvars.append(self)
def __repr__(self):
if self.__covariant__:
# Some unconstrained type variables. These are used by the container types.
+# (These are not for export.)
T = TypeVar('T') # Any type.
KT = TypeVar('KT') # Key type.
VT = TypeVar('VT') # Value type.
T_contra = TypeVar('T_contra', contravariant=True) # Ditto contravariant.
# A useful type variable with constraints. This represents string types.
-# TODO: What about bytearray, memoryview?
+# (This one *is* for export!)
AnyStr = TypeVar('AnyStr', bytes, str)
if isinstance(t1, _TypeAlias):
# _TypeAlias is not a real class.
continue
- if any(issubclass(t1, t2)
+ if not isinstance(t1, type):
+ assert callable(t1) # A callable might sneak through.
+ continue
+ if any(isinstance(t2, type) and issubclass(t1, t2)
for t2 in all_params - {t1} if not isinstance(t2, TypeVar)):
all_params.remove(t1)
# It's not a union if there's only one type left.
return self.__class__(self.__name__, self.__bases__, {},
p, _root=True)
- def _has_type_var(self):
+ def _get_type_vars(self, tvars):
if self.__union_params__:
- for t in self.__union_params__:
- if _has_type_var(t):
- return True
- return False
+ _get_type_vars(self.__union_params__, tvars)
def __repr__(self):
r = super().__repr__()
self.__tuple_use_ellipsis__ = use_ellipsis
return self
- def _has_type_var(self):
+ def _get_type_vars(self, tvars):
if self.__tuple_params__:
- for t in self.__tuple_params__:
- if _has_type_var(t):
- return True
- return False
+ _get_type_vars(self.__tuple_params__, tvars)
def _eval_type(self, globalns, localns):
tp = self.__tuple_params__
params = [_type_repr(p) for p in self.__tuple_params__]
if self.__tuple_use_ellipsis__:
params.append('...')
+ if not params:
+ params.append('()')
r += '[%s]' % (
', '.join(params))
return r
def __eq__(self, other):
if not isinstance(other, TupleMeta):
return NotImplemented
- return self.__tuple_params__ == other.__tuple_params__
+ return (self.__tuple_params__ == other.__tuple_params__ and
+ self.__tuple_use_ellipsis__ == other.__tuple_use_ellipsis__)
def __hash__(self):
return hash(self.__tuple_params__)
self.__result__ = result
return self
- def _has_type_var(self):
+ def _get_type_vars(self, tvars):
if self.__args__:
- for t in self.__args__:
- if _has_type_var(t):
- return True
- return _has_type_var(self.__result__)
+ _get_type_vars(self.__args__, tvars)
def _eval_type(self, globalns, localns):
if self.__args__ is None and self.__result__ is None:
return _gorg(a) is _gorg(b)
-class GenericMeta(TypingMeta, abc.ABCMeta):
- """Metaclass for generic types."""
+def _next_in_mro(cls):
+ """Helper for Generic.__new__.
- # TODO: Constrain more how Generic is used; only a few
- # standard patterns should be allowed.
+ Returns the class after the last occurrence of Generic or
+ Generic[...] in cls.__mro__.
+ """
+ next_in_mro = object
+ # Look for the last occurrence of Generic or Generic[...].
+ for i, c in enumerate(cls.__mro__[:-1]):
+ if isinstance(c, GenericMeta) and _gorg(c) is Generic:
+ next_in_mro = cls.__mro__[i+1]
+ return next_in_mro
- # TODO: Use a more precise rule than matching __name__ to decide
- # whether two classes are the same. Also, save the formal
- # parameters. (These things are related! A solution lies in
- # using origin.)
- __extra__ = None
+class GenericMeta(TypingMeta, abc.ABCMeta):
+ """Metaclass for generic types."""
def __new__(cls, name, bases, namespace,
- parameters=None, origin=None, extra=None):
- if parameters is None:
- # Extract parameters from direct base classes. Only
- # direct bases are considered and only those that are
- # themselves generic, and parameterized with type
- # variables. Don't use bases like Any, Union, Tuple,
- # Callable or type variables.
- params = None
+ tvars=None, args=None, origin=None, extra=None):
+ self = super().__new__(cls, name, bases, namespace, _root=True)
+
+ if tvars is not None:
+ # Called from __getitem__() below.
+ assert origin is not None
+ assert all(isinstance(t, TypeVar) for t in tvars), tvars
+ else:
+ # Called from class statement.
+ assert tvars is None, tvars
+ assert args is None, args
+ assert origin is None, origin
+
+ # Get the full set of tvars from the bases.
+ tvars = _type_vars(bases)
+ # Look for Generic[T1, ..., Tn].
+ # If found, tvars must be a subset of it.
+ # If not found, tvars is it.
+ # Also check for and reject plain Generic,
+ # and reject multiple Generic[...].
+ gvars = None
for base in bases:
- if isinstance(base, TypingMeta):
- if not isinstance(base, GenericMeta):
+ if base is Generic:
+ raise TypeError("Cannot inherit from plain Generic")
+ if (isinstance(base, GenericMeta) and
+ base.__origin__ is Generic):
+ if gvars is not None:
raise TypeError(
- "You cannot inherit from magic class %s" %
- repr(base))
- if base.__parameters__ is None:
- continue # The base is unparameterized.
- for bp in base.__parameters__:
- if _has_type_var(bp) and not isinstance(bp, TypeVar):
- raise TypeError(
- "Cannot inherit from a generic class "
- "parameterized with "
- "non-type-variable %s" % bp)
- if params is None:
- params = []
- if bp not in params:
- params.append(bp)
- if params is not None:
- parameters = tuple(params)
- self = super().__new__(cls, name, bases, namespace, _root=True)
- self.__parameters__ = parameters
- if extra is not None:
- self.__extra__ = extra
- # Else __extra__ is inherited, eventually from the
- # (meta-)class default above.
+ "Cannot inherit from Generic[...] multiple types.")
+ gvars = base.__parameters__
+ if gvars is None:
+ gvars = tvars
+ else:
+ tvarset = set(tvars)
+ gvarset = set(gvars)
+ if not tvarset <= gvarset:
+ raise TypeError(
+ "Some type variables (%s) "
+ "are not listed in Generic[%s]" %
+ (", ".join(str(t) for t in tvars if t not in gvarset),
+ ", ".join(str(g) for g in gvars)))
+ tvars = gvars
+
+ self.__parameters__ = tvars
+ self.__args__ = args
self.__origin__ = origin
+ self.__extra__ = extra
+ # Speed hack (https://github.com/python/typing/issues/196).
+ self.__next_in_mro__ = _next_in_mro(self)
return self
- def _has_type_var(self):
- if self.__parameters__:
- for t in self.__parameters__:
- if _has_type_var(t):
- return True
- return False
+ def _get_type_vars(self, tvars):
+ if self.__origin__ and self.__parameters__:
+ _get_type_vars(self.__parameters__, tvars)
def __repr__(self):
- r = super().__repr__()
- if self.__parameters__ is not None:
+ if self.__origin__ is not None:
+ r = repr(self.__origin__)
+ else:
+ r = super().__repr__()
+ if self.__args__:
r += '[%s]' % (
+ ', '.join(_type_repr(p) for p in self.__args__))
+ if self.__parameters__:
+ r += '<%s>' % (
', '.join(_type_repr(p) for p in self.__parameters__))
return r
def __eq__(self, other):
if not isinstance(other, GenericMeta):
return NotImplemented
- return (_geqv(self, other) and
- self.__parameters__ == other.__parameters__)
+ if self.__origin__ is not None:
+ return (self.__origin__ is other.__origin__ and
+ self.__args__ == other.__args__ and
+ self.__parameters__ == other.__parameters__)
+ else:
+ return self is other
def __hash__(self):
return hash((self.__name__, self.__parameters__))
if not isinstance(params, tuple):
params = (params,)
if not params:
- raise TypeError("Cannot have empty parameter list")
+ raise TypeError(
+ "Parameter list to %s[...] cannot be empty" % _qualname(self))
msg = "Parameters to generic types must be types."
params = tuple(_type_check(p, msg) for p in params)
- if self.__parameters__ is None:
- for p in params:
- if not isinstance(p, TypeVar):
- raise TypeError("Initial parameters must be "
- "type variables; got %s" % p)
+ if self is Generic:
+ # Generic can only be subscripted with unique type variables.
+ if not all(isinstance(p, TypeVar) for p in params):
+ raise TypeError(
+ "Parameters to Generic[...] must all be type variables")
if len(set(params)) != len(params):
raise TypeError(
- "All type variables in Generic[...] must be distinct.")
+ "Parameters to Generic[...] must all be unique")
+ tvars = params
+ args = None
+ elif self is _Protocol:
+ # _Protocol is internal, don't check anything.
+ tvars = params
+ args = None
+ elif self.__origin__ in (Generic, _Protocol):
+ # Can't subscript Generic[...] or _Protocol[...].
+ raise TypeError("Cannot subscript already-subscripted %s" %
+ repr(self))
else:
- if len(params) != len(self.__parameters__):
- raise TypeError("Cannot change parameter count from %d to %d" %
- (len(self.__parameters__), len(params)))
- for new, old in zip(params, self.__parameters__):
- if isinstance(old, TypeVar):
- if not old.__constraints__:
- # Substituting for an unconstrained TypeVar is OK.
- continue
- if issubclass(new, Union[old.__constraints__]):
- # Specializing a constrained type variable is OK.
- continue
- if not issubclass(new, old):
- raise TypeError(
- "Cannot substitute %s for %s in %s" %
- (_type_repr(new), _type_repr(old), self))
-
- return self.__class__(self.__name__, (self,) + self.__bases__,
+ # Subscripting a regular Generic subclass.
+ if not self.__parameters__:
+ raise TypeError("%s is not a generic class" % repr(self))
+ alen = len(params)
+ elen = len(self.__parameters__)
+ if alen != elen:
+ raise TypeError(
+ "Too %s parameters for %s; actual %s, expected %s" %
+ ("many" if alen > elen else "few", repr(self), alen, elen))
+ tvars = _type_vars(params)
+ args = params
+ return self.__class__(self.__name__,
+ (self,) + self.__bases__,
dict(self.__dict__),
- parameters=params,
+ tvars=tvars,
+ args=args,
origin=self,
extra=self.__extra__)
# C[X] is a subclass of C[Y] iff X is a subclass of Y.
origin = self.__origin__
if origin is not None and origin is cls.__origin__:
- assert len(self.__parameters__) == len(origin.__parameters__)
- assert len(cls.__parameters__) == len(origin.__parameters__)
- for p_self, p_cls, p_origin in zip(self.__parameters__,
- cls.__parameters__,
+ assert len(self.__args__) == len(origin.__parameters__)
+ assert len(cls.__args__) == len(origin.__parameters__)
+ for p_self, p_cls, p_origin in zip(self.__args__,
+ cls.__args__,
origin.__parameters__):
if isinstance(p_origin, TypeVar):
if p_origin.__covariant__:
return issubclass(cls, self.__extra__)
+# Prevent checks for Generic to crash when defining Generic.
+Generic = None
+
+
class Generic(metaclass=GenericMeta):
"""Abstract base class for generic types.
This class can then be used as follows::
- def lookup_name(mapping: Mapping, key: KT, default: VT) -> VT:
+ def lookup_name(mapping: Mapping[KT, VT], key: KT, default: VT) -> VT:
try:
return mapping[key]
except KeyError:
return default
-
- For clarity the type variables may be redefined, e.g.::
-
- X = TypeVar('X')
- Y = TypeVar('Y')
- def lookup_name(mapping: Mapping[X, Y], key: X, default: Y) -> Y:
- # Same body as above.
"""
__slots__ = ()
def __new__(cls, *args, **kwds):
- next_in_mro = object
- # Look for the last occurrence of Generic or Generic[...].
- for i, c in enumerate(cls.__mro__[:-1]):
- if isinstance(c, GenericMeta) and _gorg(c) is Generic:
- next_in_mro = cls.__mro__[i+1]
- return next_in_mro.__new__(_gorg(cls))
+ if cls.__origin__ is None:
+ return cls.__next_in_mro__.__new__(cls)
+ else:
+ origin = _gorg(cls)
+ obj = cls.__next_in_mro__.__new__(origin)
+ obj.__init__(*args, **kwds)
+ return obj
def cast(typ, val):
"""Internal helper to extract the default arguments, by name."""
code = func.__code__
pos_count = code.co_argcount
- kw_count = code.co_kwonlyargcount
arg_names = code.co_varnames
- kwarg_names = arg_names[pos_count:pos_count + kw_count]
arg_names = arg_names[:pos_count]
defaults = func.__defaults__ or ()
kwdefaults = func.__kwdefaults__
return hints
-# TODO: Also support this as a class decorator.
def no_type_check(arg):
"""Decorator to indicate that annotations are not type hints.
return wrapped_decorator
+def _overload_dummy(*args, **kwds):
+ """Helper for @overload to raise when called."""
+ raise NotImplementedError(
+ "You should not call an overloaded function. "
+ "A series of @overload-decorated functions "
+ "outside a stub module should always be followed "
+ "by an implementation that is not @overload-ed.")
+
+
def overload(func):
- raise RuntimeError("Overloading is only supported in library stubs")
+ """Decorator for overloaded functions/methods.
+
+ In a stub file, place two or more stub definitions for the same
+ function in a row, each decorated with @overload. For example:
+
+ @overload
+ def utf8(value: None) -> None: ...
+ @overload
+ def utf8(value: bytes) -> bytes: ...
+ @overload
+ def utf8(value: str) -> bytes: ...
+
+ In a non-stub file (i.e. a regular .py file), do the same but
+ follow it with an implementation. The implementation should *not*
+ be decorated with @overload. For example:
+
+ @overload
+ def utf8(value: None) -> None: ...
+ @overload
+ def utf8(value: bytes) -> bytes: ...
+ @overload
+ def utf8(value: str) -> bytes: ...
+ def utf8(value):
+ # implementation goes here
+ """
+ return _overload_dummy
class _ProtocolMeta(GenericMeta):
break
else:
if (not attr.startswith('_abc_') and
- attr != '__abstractmethods__' and
- attr != '_is_protocol' and
- attr != '__dict__' and
- attr != '__slots__' and
- attr != '_get_protocol_attrs' and
- attr != '__parameters__' and
- attr != '__origin__' and
- attr != '__module__'):
+ attr != '__abstractmethods__' and
+ attr != '_is_protocol' and
+ attr != '__dict__' and
+ attr != '__args__' and
+ attr != '__slots__' and
+ attr != '_get_protocol_attrs' and
+ attr != '__next_in_mro__' and
+ attr != '__parameters__' and
+ attr != '__origin__' and
+ attr != '__extra__' and
+ attr != '__module__'):
attrs.add(attr)
return attrs
Hashable = collections_abc.Hashable # Not generic.
+if hasattr(collections_abc, 'Awaitable'):
+ class Awaitable(Generic[T_co], extra=collections_abc.Awaitable):
+ __slots__ = ()
+else:
+ Awaitable = None
+
+
+if hasattr(collections_abc, 'AsyncIterable'):
+
+ class AsyncIterable(Generic[T_co], extra=collections_abc.AsyncIterable):
+ __slots__ = ()
+
+ class AsyncIterator(AsyncIterable[T_co],
+ extra=collections_abc.AsyncIterator):
+ __slots__ = ()
+
+else:
+ AsyncIterable = None
+ AsyncIterator = None
+
+
class Iterable(Generic[T_co], extra=collections_abc.Iterable):
__slots__ = ()
pass
-class Reversible(_Protocol[T_co]):
- __slots__ = ()
+if hasattr(collections_abc, 'Reversible'):
+ class Reversible(Iterable[T_co], extra=collections_abc.Reversible):
+ __slots__ = ()
+else:
+ class Reversible(_Protocol[T_co]):
+ __slots__ = ()
- @abstractmethod
- def __reversed__(self) -> 'Iterator[T_co]':
- pass
+ @abstractmethod
+ def __reversed__(self) -> 'Iterator[T_co]':
+ pass
Sized = collections_abc.Sized # Not generic.
# NOTE: Only the value type is covariant.
-class Mapping(Sized, Iterable[KT], Container[KT], Generic[VT_co],
+class Mapping(Sized, Iterable[KT], Container[KT], Generic[KT, VT_co],
extra=collections_abc.Mapping):
pass
class MutableMapping(Mapping[KT, VT], extra=collections_abc.MutableMapping):
pass
-
-class Sequence(Sized, Iterable[T_co], Container[T_co],
+if hasattr(collections_abc, 'Reversible'):
+ class Sequence(Sized, Reversible[T_co], Container[T_co],
extra=collections_abc.Sequence):
- pass
+ pass
+else:
+ class Sequence(Sized, Iterable[T_co], Container[T_co],
+ extra=collections_abc.Sequence):
+ pass
class MutableSequence(Sequence[T], extra=collections_abc.MutableSequence):
ByteString.register(type(memoryview(b'')))
-class List(list, MutableSequence[T]):
+class List(list, MutableSequence[T], extra=list):
def __new__(cls, *args, **kwds):
if _geqv(cls, List):
return list.__new__(cls, *args, **kwds)
-class Set(set, MutableSet[T]):
+class Set(set, MutableSet[T], extra=set):
def __new__(cls, *args, **kwds):
if _geqv(cls, Set):
return super().__subclasscheck__(cls)
-class FrozenSet(frozenset, AbstractSet[T_co], metaclass=_FrozenSetMeta):
+class FrozenSet(frozenset, AbstractSet[T_co], metaclass=_FrozenSetMeta,
+ extra=frozenset):
__slots__ = ()
def __new__(cls, *args, **kwds):
pass
-# TODO: Enable Set[Tuple[KT, VT_co]] instead of Generic[KT, VT_co].
-class ItemsView(MappingView, Generic[KT, VT_co],
+class ItemsView(MappingView[Tuple[KT, VT_co]],
+ AbstractSet[Tuple[KT, VT_co]],
+ Generic[KT, VT_co],
extra=collections_abc.ItemsView):
pass
pass
-class Dict(dict, MutableMapping[KT, VT]):
+if hasattr(contextlib, 'AbstractContextManager'):
+ class ContextManager(Generic[T_co], extra=contextlib.AbstractContextManager):
+ __slots__ = ()
+ __all__.append('ContextManager')
+
+
+class Dict(dict, MutableMapping[KT, VT], extra=dict):
def __new__(cls, *args, **kwds):
if _geqv(cls, Dict):
"use dict() instead")
return dict.__new__(cls, *args, **kwds)
+class DefaultDict(collections.defaultdict, MutableMapping[KT, VT],
+ extra=collections.defaultdict):
+
+ def __new__(cls, *args, **kwds):
+ if _geqv(cls, DefaultDict):
+ raise TypeError("Type DefaultDict cannot be instantiated; "
+ "use collections.defaultdict() instead")
+ return collections.defaultdict.__new__(cls, *args, **kwds)
# Determine what base class to use for Generator.
if hasattr(collections_abc, 'Generator'):
return super().__new__(cls, *args, **kwds)
+# Internal type variable used for Type[].
+CT = TypeVar('CT', covariant=True, bound=type)
+
+
+# This is not a real generic class. Don't use outside annotations.
+class Type(type, Generic[CT], extra=type):
+ """A special construct usable to annotate class objects.
+
+ For example, suppose we have the following classes::
+
+ class User: ... # Abstract base for User classes
+ class BasicUser(User): ...
+ class ProUser(User): ...
+ class TeamUser(User): ...
+
+ And a function that takes a class argument that's a subclass of
+ User and returns an instance of the corresponding class::
+
+ U = TypeVar('U', bound=User)
+ def new_user(user_class: Type[U]) -> U:
+ user = user_class()
+ # (Here we could write the user object to a database)
+ return user
+
+ joe = new_user(BasicUser)
+
+ At this point the type checker knows that joe has type BasicUser.
+ """
+
+
def NamedTuple(typename, fields):
"""Typed version of namedtuple.
return cls
+def NewType(name, tp):
+ """NewType creates simple unique types with almost zero
+ runtime overhead. NewType(name, tp) is considered a subtype of tp
+ by static type checkers. At runtime, NewType(name, tp) returns
+ a dummy function that simply returns its argument. Usage::
+
+ UserId = NewType('UserId', int)
+
+ def name_by_id(user_id: UserId) -> str:
+ ...
+
+ UserId('user') # Fails type check
+
+ name_by_id(42) # Fails type check
+ name_by_id(UserId(42)) # OK
+
+ num = UserId(5) + 1 # type: int
+ """
+
+ def new_type(x):
+ return x
+
+ new_type.__name__ = name
+ new_type.__supertype__ = tp
+ return new_type
+
+
+# Python-version-specific alias (Python 2: unicode; Python 3: str)
+Text = str
+
+
+# Constant that's True when type checking, but False here.
+TYPE_CHECKING = False
+
+
class IO(Generic[AnyStr]):
"""Generic base class for TextIO and BinaryIO.
"""
Python unit testing framework, based on Erich Gamma's JUnit and Kent Beck's
-Smalltalk testing framework.
+Smalltalk testing framework (used with permission).
This module contains the core framework classes that form the basis of
specific test cases and suites (TestCase, TestSuite etc.), and also a
if item1 != item2:
differing += ('\nFirst differing element %d:\n%s\n%s\n' %
- (i, item1, item2))
+ ((i,) + _common_shorten_repr(item1, item2)))
break
else:
if (len1 == len2 and seq_type is None and
'elements.\n' % (seq_type_name, len1 - len2))
try:
differing += ('First extra element %d:\n%s\n' %
- (len2, seq1[len2]))
+ (len2, safe_repr(seq1[len2])))
except (TypeError, IndexError, NotImplementedError):
differing += ('Unable to index element %d '
'of first %s\n' % (len2, seq_type_name))
'elements.\n' % (seq_type_name, len2 - len1))
try:
differing += ('First extra element %d:\n%s\n' %
- (len1, seq2[len1]))
+ (len1, safe_repr(seq2[len1])))
except (TypeError, IndexError, NotImplementedError):
differing += ('Unable to index element %d '
'of second %s\n' % (len1, seq_type_name))
if tests is not None:
yield tests
if not should_recurse:
- # Either an error occured, or load_tests was used by the
+ # Either an error occurred, or load_tests was used by the
# package.
return
# Handle the contents.
return tests, True
finally:
self._loading_packages.discard(name)
+ else:
+ return None, False
defaultTestLoader = TestLoader()
setattr(self.target, self.attribute, self.temp_original)
else:
delattr(self.target, self.attribute)
- if not self.create and not hasattr(self.target, self.attribute):
+ if not self.create and (not hasattr(self.target, self.attribute) or
+ self.attribute in ('__doc__', '__module__',
+ '__defaults__', '__annotations__',
+ '__kwdefaults__')):
# needed for proxy objects like django settings
setattr(self.target, self.attribute, self.temp_original)
return (other_args, other_kwargs) == (self_args, self_kwargs)
+ __ne__ = object.__ne__
+
+
def __call__(self, *args, **kwargs):
if self.name is None:
return _Call(('', args, kwargs), name='()')
yield handle.readline.return_value
for line in _state[0]:
yield line
+ while True:
+ yield type(read_data)()
global file_spec
self.skipped.append((test, reason))
def addExpectedFailure(self, test, err):
- """Called when an expected failure/error occured."""
+ """Called when an expected failure/error occurred."""
self.expectedFailures.append(
(test, self._exc_info_to_string(err, test)))
try:
test = self._tests[index]
except TypeError:
- # support for suite implementations that have overriden self._tests
+ # support for suite implementations that have overridden self._tests
pass
else:
# Some unittest tests add non TestCase/TestSuite objects to
error = str(e).split('\n', 1)[1]
self.assertEqual(sample_text_error, error)
+ def testEqualityBytesWarning(self):
+ if sys.flags.bytes_warning:
+ def bytes_warning():
+ return self.assertWarnsRegex(BytesWarning,
+ 'Comparison between bytes and string')
+ else:
+ def bytes_warning():
+ return contextlib.ExitStack()
+
+ with bytes_warning(), self.assertRaises(self.failureException):
+ self.assertEqual('a', b'a')
+ with bytes_warning():
+ self.assertNotEqual('a', b'a')
+
+ a = [0, 'a']
+ b = [0, b'a']
+ with bytes_warning(), self.assertRaises(self.failureException):
+ self.assertListEqual(a, b)
+ with bytes_warning(), self.assertRaises(self.failureException):
+ self.assertTupleEqual(tuple(a), tuple(b))
+ with bytes_warning(), self.assertRaises(self.failureException):
+ self.assertSequenceEqual(a, tuple(b))
+ with bytes_warning(), self.assertRaises(self.failureException):
+ self.assertSequenceEqual(tuple(a), b)
+ with bytes_warning(), self.assertRaises(self.failureException):
+ self.assertSequenceEqual('a', b'a')
+ with bytes_warning(), self.assertRaises(self.failureException):
+ self.assertSetEqual(set(a), set(b))
+
+ with self.assertRaises(self.failureException):
+ self.assertListEqual(a, tuple(b))
+ with self.assertRaises(self.failureException):
+ self.assertTupleEqual(tuple(a), b)
+
+ a = [0, b'a']
+ b = [0]
+ with self.assertRaises(self.failureException):
+ self.assertListEqual(a, b)
+ with self.assertRaises(self.failureException):
+ self.assertTupleEqual(tuple(a), tuple(b))
+ with self.assertRaises(self.failureException):
+ self.assertSequenceEqual(a, tuple(b))
+ with self.assertRaises(self.failureException):
+ self.assertSequenceEqual(tuple(a), b)
+ with self.assertRaises(self.failureException):
+ self.assertSetEqual(set(a), set(b))
+
+ a = [0]
+ b = [0, b'a']
+ with self.assertRaises(self.failureException):
+ self.assertListEqual(a, b)
+ with self.assertRaises(self.failureException):
+ self.assertTupleEqual(tuple(a), tuple(b))
+ with self.assertRaises(self.failureException):
+ self.assertSequenceEqual(a, tuple(b))
+ with self.assertRaises(self.failureException):
+ self.assertSequenceEqual(tuple(a), b)
+ with self.assertRaises(self.failureException):
+ self.assertSetEqual(set(a), set(b))
+
+ with bytes_warning(), self.assertRaises(self.failureException):
+ self.assertDictEqual({'a': 0}, {b'a': 0})
+ with self.assertRaises(self.failureException):
+ self.assertDictEqual({}, {b'a': 0})
+ with self.assertRaises(self.failureException):
+ self.assertDictEqual({b'a': 0}, {})
+
+ with self.assertRaises(self.failureException):
+ self.assertCountEqual([b'a', b'a'], [b'a', b'a', b'a'])
+ with bytes_warning():
+ self.assertCountEqual(['a', b'a'], ['a', b'a'])
+ with bytes_warning(), self.assertRaises(self.failureException):
+ self.assertCountEqual(['a', 'a'], [b'a', b'a'])
+ with bytes_warning(), self.assertRaises(self.failureException):
+ self.assertCountEqual(['a', 'a', []], [b'a', b'a', []])
+
def testAssertIsNone(self):
self.assertIsNone(None)
self.assertRaises(self.failureException, self.assertIsNone, False)
('test3', 'test4')])
self.assertEqual(suite, expected)
+ def test_find_tests_socket(self):
+ # A socket is neither a directory nor a regular file.
+ # https://bugs.python.org/issue25320
+ loader = unittest.TestLoader()
+
+ original_listdir = os.listdir
+ def restore_listdir():
+ os.listdir = original_listdir
+ original_isfile = os.path.isfile
+ def restore_isfile():
+ os.path.isfile = original_isfile
+ original_isdir = os.path.isdir
+ def restore_isdir():
+ os.path.isdir = original_isdir
+
+ path_lists = [['socket']]
+ os.listdir = lambda path: path_lists.pop(0)
+ self.addCleanup(restore_listdir)
+
+ os.path.isdir = lambda path: False
+ self.addCleanup(restore_isdir)
+
+ os.path.isfile = lambda path: False
+ self.addCleanup(restore_isfile)
+
+ loader._get_module_from_name = lambda path: path + ' module'
+ orig_load_tests = loader.loadTestsFromModule
+ def loadTestsFromModule(module, pattern=None):
+ # This is where load_tests is called.
+ base = orig_load_tests(module, pattern=pattern)
+ return base + [module + ' tests']
+ loader.loadTestsFromModule = loadTestsFromModule
+ loader.suiteClass = lambda thing: thing
+
+ top_level = os.path.abspath('/foo')
+ loader._top_level_dir = top_level
+ suite = list(loader._find_tests(top_level, 'test*.py'))
+
+ self.assertEqual(suite, [])
+
def test_find_tests_with_package(self):
loader = unittest.TestLoader()
# test isolation and reproducibility.
def warningregistry(func):
def wrapper(*args, **kws):
- missing = object()
+ missing = []
saved = getattr(warnings, '__warningregistry__', missing).copy()
try:
return func(*args, **kws)
pass
else:
warnings.__warningregistry__ = saved
+ return wrapper
class Test_TestLoader(unittest.TestCase):
# ignored (and deprecated).
load_tests_args = []
with warnings.catch_warnings(record=False):
- warnings.simplefilter('never')
+ warnings.simplefilter('ignore')
suite = loader.loadTestsFromModule(m, use_load_tests=False)
- self.assertEqual(load_tests_args, [loader, suite, None])
+ self.assertEqual(load_tests_args, [loader, suite, None])
@warningregistry
def test_loadTestsFromModule__use_load_tests_deprecated_positional(self):
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always')
suite = loader.loadTestsFromModule(m, False)
- self.assertIsInstance(suite, unittest.TestSuite)
- # load_tests was still called because use_load_tests is deprecated
- # and ignored.
- self.assertEqual(load_tests_args, [loader, suite, None])
+ self.assertIsInstance(suite, unittest.TestSuite)
+ # load_tests was still called because use_load_tests is deprecated
+ # and ignored.
+ self.assertEqual(load_tests_args, [loader, suite, None])
# We got a warning.
self.assertIs(w[-1].category, DeprecationWarning)
self.assertEqual(str(w[-1].message),
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always')
suite = loader.loadTestsFromModule(m, use_load_tests=False)
- self.assertIsInstance(suite, unittest.TestSuite)
- # load_tests was still called because use_load_tests is deprecated
- # and ignored.
- self.assertEqual(load_tests_args, [loader, suite, None])
- # We got a warning.
- self.assertIs(w[-1].category, DeprecationWarning)
- self.assertEqual(str(w[-1].message),
- 'use_load_tests is deprecated and ignored')
+ self.assertIsInstance(suite, unittest.TestSuite)
+ # load_tests was still called because use_load_tests is deprecated
+ # and ignored.
+ self.assertEqual(load_tests_args, [loader, suite, None])
+ # We got a warning.
+ self.assertIs(w[-1].category, DeprecationWarning)
+ self.assertEqual(str(w[-1].message),
+ 'use_load_tests is deprecated and ignored')
@warningregistry
def test_loadTestsFromModule__too_many_positional_args(self):
m.load_tests = load_tests
loader = unittest.TestLoader()
with self.assertRaises(TypeError) as cm, \
- warnings.catch_warning(record=True) as w:
+ warnings.catch_warnings(record=True) as w:
+ warnings.simplefilter('always')
loader.loadTestsFromModule(m, False, 'testme.*')
- # We still got the deprecation warning.
- self.assertIs(w[-1].category, DeprecationWarning)
- self.assertEqual(str(w[-1].message),
- 'use_load_tests is deprecated and ignored')
- # We also got a TypeError for too many positional arguments.
- self.assertEqual(type(cm.exception), TypeError)
- self.assertEqual(
- str(cm.exception),
- 'loadTestsFromModule() takes 1 positional argument but 3 were given')
+ # We still got the deprecation warning.
+ self.assertIs(w[-1].category, DeprecationWarning)
+ self.assertEqual(str(w[-1].message),
+ 'use_load_tests is deprecated and ignored')
+ # We also got a TypeError for too many positional arguments.
+ self.assertEqual(type(cm.exception), TypeError)
+ self.assertEqual(
+ str(cm.exception),
+ 'loadTestsFromModule() takes 1 positional argument but 3 were given')
@warningregistry
def test_loadTestsFromModule__use_load_tests_other_bad_keyword(self):
m.load_tests = load_tests
loader = unittest.TestLoader()
with warnings.catch_warnings():
- warnings.simplefilter('never')
+ warnings.simplefilter('ignore')
with self.assertRaises(TypeError) as cm:
loader.loadTestsFromModule(
m, use_load_tests=False, very_bad=True, worse=False)
# no args -> all the warnings are printed, unittest warnings only once
p = subprocess.Popen([sys.executable, '_test_warnings.py'], **opts)
- out, err = get_parse_out_err(p)
+ with p:
+ out, err = get_parse_out_err(p)
self.assertIn(b'OK', err)
# check that the total number of warnings in the output is correct
self.assertEqual(len(out), 12)
# in all these cases no warnings are printed
for args in args_list:
p = subprocess.Popen(args, **opts)
- out, err = get_parse_out_err(p)
+ with p:
+ out, err = get_parse_out_err(p)
self.assertIn(b'OK', err)
self.assertEqual(len(out), 0)
# unittest warnings only once
p = subprocess.Popen([sys.executable, '_test_warnings.py', 'always'],
**opts)
- out, err = get_parse_out_err(p)
+ with p:
+ out, err = get_parse_out_err(p)
self.assertIn(b'OK', err)
self.assertEqual(len(out), 14)
for msg in [b'dw', b'iw', b'uw', b'rw']:
# an exception. See issue 24857.
self.assertFalse(mock.call_args == "a long sequence")
+
+ def test_calls_equal_with_any(self):
+ call1 = mock.call(mock.MagicMock())
+ call2 = mock.call(mock.ANY)
+
+ # Check that equality and non-equality is consistent even when
+ # comparing with mock.ANY
+ self.assertTrue(call1 == call2)
+ self.assertFalse(call1 != call2)
+
+
def test_assert_called_with(self):
mock = Mock()
mock()
mock.assert_called_with(1, 2, 3, a='fish', b='nothing')
+ def test_assert_called_with_any(self):
+ m = MagicMock()
+ m(MagicMock())
+ m.assert_called_with(mock.ANY)
+
+
def test_assert_called_with_function_spec(self):
def f(a, b, c, d=None):
pass
self.assertEqual('abc', first)
self.assertEqual('abc', second)
+ def test_mock_open_after_eof(self):
+ # read, readline and readlines should work after end of file.
+ _open = mock.mock_open(read_data='foo')
+ h = _open('bar')
+ h.read()
+ self.assertEqual('', h.read())
+ self.assertEqual('', h.read())
+ self.assertEqual('', h.readline())
+ self.assertEqual('', h.readline())
+ self.assertEqual([], h.readlines())
+ self.assertEqual([], h.readlines())
+
def test_mock_parents(self):
for Klass in Mock, MagicMock:
m = Klass()
self.assertEqual(stopped, ["three", "two", "one"])
+ def test_special_attrs(self):
+ def foo(x=0):
+ """TEST"""
+ return x
+ with patch.object(foo, '__defaults__', (1, )):
+ self.assertEqual(foo(), 1)
+ self.assertEqual(foo(), 0)
+
+ with patch.object(foo, '__doc__', "FUN"):
+ self.assertEqual(foo.__doc__, "FUN")
+ self.assertEqual(foo.__doc__, "TEST")
+
+ with patch.object(foo, '__module__', "testpatch2"):
+ self.assertEqual(foo.__module__, "testpatch2")
+ self.assertEqual(foo.__module__, 'unittest.test.testmock.testpatch')
+
+ with patch.object(foo, '__annotations__', dict([('s', 1, )])):
+ self.assertEqual(foo.__annotations__, dict([('s', 1, )]))
+ self.assertEqual(foo.__annotations__, dict())
+
+ def foo(*a, x=0):
+ return x
+ with patch.object(foo, '__kwdefaults__', dict([('x', 1, )])):
+ self.assertEqual(foo(), 1)
+ self.assertEqual(foo(), 0)
+
if __name__ == '__main__':
unittest.main()
l.append(k + '=' + elt)
return '&'.join(l)
-# Utilities to parse URLs (most of these return None for missing parts):
-# unwrap('<URL:type://host/path>') --> 'type://host/path'
-# splittype('type:opaquestring') --> 'type', 'opaquestring'
-# splithost('//host[:port]/path') --> 'host[:port]', '/path'
-# splituser('user[:passwd]@host[:port]') --> 'user[:passwd]', 'host[:port]'
-# splitpasswd('user:passwd') -> 'user', 'passwd'
-# splitport('host:port') --> 'host', 'port'
-# splitquery('/path?query') --> '/path', 'query'
-# splittag('/path#tag') --> '/path', 'tag'
-# splitattr('/path;attr1=value1;attr2=value2;...') ->
-# '/path', ['attr1=value1', 'attr2=value2', ...]
-# splitvalue('attr=value') --> 'attr', 'value'
-# urllib.parse.unquote('abc%20def') -> 'abc def'
-# quote('abc def') -> 'abc%20def')
-
def to_bytes(url):
"""to_bytes(u"URL") --> 'URL'."""
# Most URL schemes require ASCII. If that changes, the conversion
import posixpath
import re
import socket
+import string
import sys
import time
import collections
# from the user (of urllib.request, in this case). In practice,
# essentially all clients do redirect in this case, so we do
# the same.
- # be conciliant with URIs containing a space
+
+ # Be conciliant with URIs containing a space. This is mainly
+ # redundant with the more complete encoding done in http_error_302(),
+ # but it is kept for compatibility with other callers.
newurl = newurl.replace(' ', '%20')
+
CONTENT_HEADERS = ("content-length", "content-type")
newheaders = dict((k, v) for k, v in req.headers.items()
if k.lower() not in CONTENT_HEADERS)
"%s - Redirection to url '%s' is not allowed" % (msg, newurl),
headers, fp)
- if not urlparts.path:
+ if not urlparts.path and urlparts.netloc:
urlparts = list(urlparts)
urlparts[2] = "/"
newurl = urlunparse(urlparts)
+ # http.client.parse_headers() decodes as ISO-8859-1. Recover the
+ # original bytes and percent-encode non-ASCII bytes, and any special
+ # characters such as the space.
+ newurl = quote(
+ newurl, encoding="iso-8859-1", safe=string.punctuation)
newurl = urljoin(req.full_url, newurl)
# XXX Probably want to forget about the state of the current
elif algorithm == 'SHA':
H = lambda x: hashlib.sha1(x.encode("ascii")).hexdigest()
# XXX MD5-sess
+ else:
+ raise ValueError("Unsupported digest authentication "
+ "algorithm %r" % algorithm)
KD = lambda s, d: H("%s:%s" % (s, d))
return H, KD
# will parse host:port
h = http_class(host, timeout=req.timeout, **http_conn_args)
+ h.set_debuglevel(self._debuglevel)
headers = dict(req.unredirected_hdrs)
headers.update(dict((k, v) for k, v in req.headers.items()
def http_error_302(self, url, fp, errcode, errmsg, headers, data=None):
"""Error 302 -- relocated (temporarily)."""
self.tries += 1
- if self.maxtries and self.tries >= self.maxtries:
- if hasattr(self, "http_error_500"):
- meth = self.http_error_500
- else:
- meth = self.http_error_default
+ try:
+ if self.maxtries and self.tries >= self.maxtries:
+ if hasattr(self, "http_error_500"):
+ meth = self.http_error_500
+ else:
+ meth = self.http_error_default
+ return meth(url, fp, 500,
+ "Internal Server Error: Redirect Recursion",
+ headers)
+ result = self.redirect_internal(url, fp, errcode, errmsg,
+ headers, data)
+ return result
+ finally:
self.tries = 0
- return meth(url, fp, 500,
- "Internal Server Error: Redirect Recursion", headers)
- result = self.redirect_internal(url, fp, errcode, errmsg, headers,
- data)
- self.tries = 0
- return result
def redirect_internal(self, url, fp, errcode, errmsg, headers, data):
if 'location' in headers:
"""
proxies = {}
+ # in order to prefer lowercase variables, process environment in
+ # two passes: first matches any, second pass matches lowercase only
for name, value in os.environ.items():
name = name.lower()
if value and name[-6:] == '_proxy':
proxies[name[:-6]] = value
+ for name, value in os.environ.items():
+ if name[-6:] == '_proxy':
+ name = name.lower()
+ if value:
+ proxies[name[:-6]] = value
+ else:
+ proxies.pop(name[:-6], None)
return proxies
-def proxy_bypass_environment(host):
+def proxy_bypass_environment(host, proxies=None):
"""Test if proxies should not be used for a particular host.
- Checks the environment for a variable named no_proxy, which should
- be a list of DNS suffixes separated by commas, or '*' for all hosts.
+ Checks the proxy dict for the value of no_proxy, which should
+ be a list of comma separated DNS suffixes, or '*' for all hosts.
+
"""
- no_proxy = os.environ.get('no_proxy', '') or os.environ.get('NO_PROXY', '')
+ if proxies is None:
+ proxies = getproxies_environment()
+ # don't bypass, if no_proxy isn't specified
+ try:
+ no_proxy = proxies['no']
+ except KeyError:
+ return 0
# '*' is special case for always bypass
if no_proxy == '*':
return 1
# check if the host ends with any of the DNS suffixes
no_proxy_list = [proxy.strip() for proxy in no_proxy.split(',')]
for name in no_proxy_list:
- if name and (hostonly.endswith(name) or host.endswith(name)):
- return 1
+ if name:
+ name = re.escape(name)
+ pattern = r'(.+\.)?%s$' % name
+ if (re.match(pattern, hostonly, re.I)
+ or re.match(pattern, host, re.I)):
+ return 1
# otherwise, don't bypass
return 0
def proxy_bypass(host):
- if getproxies_environment():
- return proxy_bypass_environment(host)
+ """Return True, if host should be bypassed.
+
+ Checks proxy settings gathered from the environment, if specified,
+ or from the MacOSX framework SystemConfiguration.
+
+ """
+ proxies = getproxies_environment()
+ if proxies:
+ return proxy_bypass_environment(host, proxies)
else:
return proxy_bypass_macosx_sysconf(host)
return 0
def proxy_bypass(host):
- """Return a dictionary of scheme -> proxy server URL mappings.
+ """Return True, if host should be bypassed.
- Returns settings gathered from the environment, if specified,
+ Checks proxy settings gathered from the environment, if specified,
or the registry.
"""
- if getproxies_environment():
- return proxy_bypass_environment(host)
+ proxies = getproxies_environment()
+ if proxies:
+ return proxy_bypass_environment(host, proxies)
else:
return proxy_bypass_registry(host)
return True
# Until the robots.txt file has been read or found not
# to exist, we must assume that no url is allowable.
- # This prevents false positives when a user erronenously
+ # This prevents false positives when a user erroneously
# calls can_fetch() before calling read().
if not self.last_checked:
return False
"""
if [hex, bytes, bytes_le, fields, int].count(None) != 4:
- raise TypeError('need one of hex, bytes, bytes_le, fields, or int')
+ raise TypeError('one of the hex, bytes, bytes_le, fields, '
+ 'or int arguments must be given')
if hex is not None:
hex = hex.replace('urn:', '').replace('uuid:', '')
hex = hex.strip('{}').replace('-', '')
Give the virtual environment access to the system
site-packages dir.
--symlinks Attempt to symlink rather than copy.
- --clear Delete the environment directory if it already exists.
- If not specified and the directory exists, an error is
- raised.
+ --clear Delete the contents of the environment directory if it
+ already exists, before environment creation.
--upgrade Upgrade the environment directory to use this version
of Python, assuming Python has been upgraded in-place.
--without-pip Skips installing or upgrading pip in the virtual
:param system_site_packages: If True, the system (global) site-packages
dir is available to created environments.
- :param clear: If True and the target directory exists, it is deleted.
- Otherwise, if the target directory exists, an error is
- raised.
+ :param clear: If True, delete the contents of the environment directory if
+ it already exists, before environment creation.
:param symlinks: If True, attempt to symlink rather than copy files into
virtual environment.
:param upgrade: If True, upgrade an existing virtual environment.
:param env_dir: The target directory to create an environment in.
:param system_site_packages: If True, the system (global) site-packages
dir is available to the environment.
- :param clear: If True and the target directory exists, it is deleted.
- Otherwise, if the target directory exists, an error is
- raised.
+ :param clear: If True, delete the contents of the environment directory if
+ it already exists, before environment creation.
:param symlinks: If True, attempt to symlink rather than copy files into
virtual environment.
:param with_pip: If True, ensure pip is installed in the virtual
# with the original prompt function renamed, we can override with our own.
function fish_prompt
# Prompt override?
- if test -n "__VENV_PROMPT__"
- printf "%s%s%s" "__VENV_PROMPT__" (set_color normal) (_old_fish_prompt)
+ if test -n "$__VENV_PROMPT__"
+ printf "%s%s%s" "$__VENV_PROMPT__" (set_color normal) (_old_fish_prompt)
return
end
# ...Otherwise, prepend env
def formatwarning(message, category, filename, lineno, line=None):
"""Function to format a warning the standard way."""
- import linecache
s = "%s:%s: %s: %s\n" % (filename, lineno, category.__name__, message)
- line = linecache.getline(filename, lineno) if line is None else line
+ if line is None:
+ try:
+ import linecache
+ line = linecache.getline(filename, lineno)
+ except Exception:
+ # When a warning is logged during Python shutdown, linecache
+ # and the import machinery don't work anymore
+ line = None
if line:
line = line.strip()
s += " %s\n" % line
assert isinstance(module, str), "module must be a string"
assert isinstance(lineno, int) and lineno >= 0, \
"lineno must be an int >= 0"
- item = (action, re.compile(message, re.I), category,
- re.compile(module), lineno)
- if append:
- filters.append(item)
- else:
- filters.insert(0, item)
- _filters_mutated()
+ _add_filter(action, re.compile(message, re.I), category,
+ re.compile(module), lineno, append=append)
def simplefilter(action, category=Warning, lineno=0, append=False):
"""Insert a simple entry into the list of warnings filters (at the front).
"once"), "invalid action: %r" % (action,)
assert isinstance(lineno, int) and lineno >= 0, \
"lineno must be an int >= 0"
- item = (action, None, category, None, lineno)
- if append:
- filters.append(item)
- else:
+ _add_filter(action, None, category, None, lineno, append=append)
+
+def _add_filter(*item, append):
+ # Remove possible duplicate filters, so new one will be placed
+ # in correct place. If append=True and duplicate exists, do nothing.
+ if not append:
+ try:
+ filters.remove(item)
+ except ValueError:
+ pass
filters.insert(0, item)
+ else:
+ if item not in filters:
+ filters.append(item)
_filters_mutated()
def resetwarnings():
self.headers = self.headers_class(headers)
status = self._convert_string_type(status, "Status")
assert len(status)>=4,"Status must be at least 4 characters"
- assert int(status[:3]),"Status message must begin w/3-digit code"
+ assert status[:3].isdigit(), "Status message must begin w/3-digit code"
assert status[3]==" ", "Status message must have a space after code"
if __debug__:
self.environ.update(self.base_env)
def _write(self,data):
- self.stdout.write(data)
+ result = self.stdout.write(data)
+ if result is None or result == len(data):
+ return
+ from warnings import warn
+ warn("SimpleHandler.stdout.write() should not do partial writes",
+ DeprecationWarning)
+ while True:
+ data = data[result:]
+ if not data:
+ break
+ result = self.stdout.write(data)
def _flush(self):
self.stdout.flush()
Return None if the header is missing instead of raising an exception.
Note that if the header appeared multiple times, the first exactly which
- occurrance gets returned is undefined. Use getall() to get all
+ occurrence gets returned is undefined. Use getall() to get all
the values matching a header field name.
"""
return self.get(name)
"""
from http.server import BaseHTTPRequestHandler, HTTPServer
+from io import BufferedWriter
import sys
import urllib.parse
from wsgiref.handlers import SimpleHandler
else:
path,query = self.path,''
- env['PATH_INFO'] = urllib.parse.unquote_to_bytes(path).decode('iso-8859-1')
+ env['PATH_INFO'] = urllib.parse.unquote(path, 'iso-8859-1')
env['QUERY_STRING'] = query
host = self.address_string()
if not self.parse_request(): # An error code has been sent, just exit
return
- handler = ServerHandler(
- self.rfile, self.wfile, self.get_stderr(), self.get_environ()
- )
- handler.request_handler = self # backpointer for logging
- handler.run(self.server.get_app())
+ # Avoid passing the raw file object wfile, which can do partial
+ # writes (Issue 24291)
+ stdout = BufferedWriter(self.wfile)
+ try:
+ handler = ServerHandler(
+ self.rfile, stdout, self.get_stderr(), self.get_environ()
+ )
+ handler.request_handler = self # backpointer for logging
+ handler.run(self.server.get_app())
+ finally:
+ stdout.detach()
length = property(_get_length, _set_length,
doc="The number of nodes in the NodeList.")
- def __getstate__(self):
- return list(self)
-
+ # For backward compatibility
def __setstate__(self, state):
+ if state is None:
+ state = []
self[:] = state
tag = self.tag
if not isinstance(tag, str) and tag is not None:
return
- if self.text:
- yield self.text
+ t = self.text
+ if t:
+ yield t
for e in self:
yield from e.itertext()
- if e.tail:
- yield e.tail
+ t = e.tail
+ if t:
+ yield t
def SubElement(parent, tag, attrib={}, **extra):
if not hasattr(source, "read"):
source = open(source, "rb")
close_source = True
- return _IterParseIterator(source, events, parser, close_source)
+ try:
+ return _IterParseIterator(source, events, parser, close_source)
+ except:
+ if close_source:
+ source.close()
+ raise
class XMLPullParser:
self.root = self._root = None
def __next__(self):
- while 1:
- for event in self._parser.read_events():
- return event
- if self._parser._parser is None:
- self.root = self._root
- if self._close_file:
- self._file.close()
- raise StopIteration
- # load event buffer
- data = self._file.read(16 * 1024)
- if data:
- self._parser.feed(data)
- else:
- self._root = self._parser._close_and_return_root()
+ try:
+ while 1:
+ for event in self._parser.read_events():
+ return event
+ if self._parser._parser is None:
+ break
+ # load event buffer
+ data = self._file.read(16 * 1024)
+ if data:
+ self._parser.feed(data)
+ else:
+ self._root = self._parser._close_and_return_root()
+ self.root = self._root
+ except:
+ if self._close_file:
+ self._file.close()
+ raise
+ if self._close_file:
+ self._file.close()
+ raise StopIteration
def __iter__(self):
return self
class XMLParser:
"""Element structure builder for XML source data based on the expat parser.
- *html* are predefined HTML entities (not supported currently),
+ *html* are predefined HTML entities (deprecated and not supported),
*target* is an optional target object which defaults to an instance of the
standard TreeBuilder class, *encoding* is an optional encoding string
which if given, overrides the encoding specified in the XML file:
self._stack = []
self._marks = []
self._data = []
+ self._value = False
self._methodname = None
self._encoding = "utf-8"
self.append = self._stack.append
if tag == "array" or tag == "struct":
self._marks.append(len(self._stack))
self._data = []
+ if self._value and tag not in self.dispatch:
+ raise ResponseError("unknown tag %r" % tag)
self._value = (tag == "value")
def data(self, text):
# standard XML-RPC wrappings
if methodname:
# a method call
- if not isinstance(methodname, str):
- methodname = methodname.encode(encoding)
data = (
xmlheader,
"<methodCall>\n"
for i in (0, 1):
try:
return self.single_request(host, handler, request_body, verbose)
+ except http.client.RemoteDisconnected:
+ if i:
+ raise
except OSError as e:
if i or e.errno not in (errno.ECONNRESET, errno.ECONNABORTED,
errno.EPIPE):
raise
- except http.client.RemoteDisconnected:
- if i:
- raise
def single_request(self, host, handler, request_body, verbose=False):
# issue XML-RPC request
# call a method on the remote server
request = dumps(params, methodname, encoding=self.__encoding,
- allow_none=self.__allow_none).encode(self.__encoding)
+ allow_none=self.__allow_none).encode(self.__encoding, 'xmlcharrefreplace')
response = self.__transport.request(
self.__host,
# magic method dispatcher
return _Method(self.__request, name)
- # note: to call a remote object with an non-standard name, use
+ # note: to call a remote object with a non-standard name, use
# result getattr(server, "strange-python-name")(args)
def __call__(self, attr):
encoding=self.encoding, allow_none=self.allow_none,
)
- return response.encode(self.encoding)
+ return response.encode(self.encoding, 'xmlcharrefreplace')
def system_listMethods(self):
"""system.listMethods() => ['add', 'subtract', 'multiple']
response = dumps(
Fault(1, "%s:%s" % (exc_type, exc_value)),
encoding=self.encoding, allow_none=self.allow_none)
- response = response.encode(self.encoding)
+ response = response.encode(self.encoding, 'xmlcharrefreplace')
return response
class CGIXMLRPCRequestHandler(SimpleXMLRPCDispatcher):
The created application archive will have a shebang line specifying
that it should run with INTERPRETER (there will be no shebang line if
INTERPRETER is None), and a __main__.py which runs MAIN (if MAIN is
- not specified, an existing __main__.py will be used). It is an to specify
- MAIN for anything other than a directory source with no __main__.py, and it
- is an error to omit MAIN if the directory has no __main__.py.
+ not specified, an existing __main__.py will be used). It is an error
+ to specify MAIN for anything other than a directory source with no
+ __main__.py, and it is an error to omit MAIN if the directory has no
+ __main__.py.
"""
# Are we copying an existing archive?
source_is_file = False
if hasattr(zipinfo, 'CRC'):
self._expected_crc = zipinfo.CRC
- self._running_crc = crc32(b'') & 0xffffffff
+ self._running_crc = crc32(b'')
else:
self._expected_crc = None
if self._expected_crc is None:
# No need to compute the CRC if we don't have a reference value
return
- self._running_crc = crc32(newdata, self._running_crc) & 0xffffffff
+ self._running_crc = crc32(newdata, self._running_crc)
# Check the CRC if we're at the end of the file
if self._eof and self._running_crc != self._expected_crc:
raise BadZipFile("Bad CRC-32 for file %r" % self.name)
arcname += '/'
zinfo = ZipInfo(arcname, date_time)
zinfo.external_attr = (st[0] & 0xFFFF) << 16 # Unix attributes
- if compress_type is None:
+ if isdir:
+ zinfo.compress_type = ZIP_STORED
+ elif compress_type is None:
zinfo.compress_type = self.compression
else:
zinfo.compress_type = compress_type
if not buf:
break
file_size = file_size + len(buf)
- CRC = crc32(buf, CRC) & 0xffffffff
+ CRC = crc32(buf, CRC)
if cmpr:
buf = cmpr.compress(buf)
compress_size = compress_size + len(buf)
self._writecheck(zinfo)
self._didModify = True
- zinfo.CRC = crc32(data) & 0xffffffff # CRC-32 checksum
+ zinfo.CRC = crc32(data) # CRC-32 checksum
co = _get_compressor(zinfo.compress_type)
if co:
data = co.compress(data) + co.flush()
LT_10_5 = bool(getDeptargetTuple() < (10, 5))
- if getDeptargetTuple() < (10, 6):
+ if not (10, 5) < getDeptargetTuple() < (10, 10):
# The OpenSSL libs shipped with OS X 10.5 and earlier are
# hopelessly out-of-date and do not include Apple's tie-in to
# the root certificates in the user and system keychains via TEA
# now more obvious with cert checking enabled by default in the
# standard library.
#
- # For builds with 10.6+ SDKs, continue to use the deprecated but
+ # For builds with 10.6 through 10.9 SDKs,
+ # continue to use the deprecated but
# less out-of-date Apple 0.9.8 libs for now. While they are less
# secure than using an up-to-date 1.0.1 version, doing so
# avoids the big problems of forcing users to have to manage
# APIs for cert validation from keychains if validation using the
# standard OpenSSL locations (/System/Library/OpenSSL, normally empty)
# fails.
+ #
+ # Since Apple removed the header files for the deprecated system
+ # OpenSSL as of the Xcode 7 release (for OS X 10.10+), we do not
+ # have much choice but to build our own copy here, too.
result.extend([
dict(
- name="OpenSSL 1.0.2d",
- url="https://www.openssl.org/source/openssl-1.0.2d.tar.gz",
- checksum='38dd619b2e77cbac69b99f52a053d25a',
+ name="OpenSSL 1.0.2h",
+ url="https://www.openssl.org/source/openssl-1.0.2h.tar.gz",
+ checksum='9392e65072ce4b614c1392eefc1f23d0',
patches=[
"openssl_sdk_makedepend.patch",
],
# HG changeset patch
-# Parent 25a9af415e8c3faf591c360d5f0e361d049b2b43
+# Parent d377390f787c0739a3e89f669def72d7167e5108
# openssl_sdk_makedepend.patch
#
-# using openssl 1.0.2d
+# using openssl 1.0.2f
#
# - support building with an OS X SDK
-# - allow "make depend" to use compilers with names other than "gcc"
diff Configure
diff --git a/Configure b/Configure
--- a/Configure
+++ b/Configure
-@@ -617,12 +617,12 @@
+@@ -638,12 +638,12 @@
##### MacOS X (a.k.a. Rhapsody or Darwin) setup
"rhapsody-ppc-cc","cc:-O3 -DB_ENDIAN::(unknown):MACOSX_RHAPSODY::BN_LLONG RC4_CHAR RC4_CHUNK DES_UNROLL BF_PTR:${no_asm}::",
"debug-darwin-ppc-cc","cc:-DBN_DEBUG -DREF_CHECK -DCONF_DEBUG -DCRYPTO_MDEBUG -DB_ENDIAN -g -Wall -O::-D_REENTRANT:MACOSX::BN_LLONG RC4_CHAR RC4_CHUNK DES_UNROLL BF_PTR:${ppc32_asm}:osx32:dlfcn:darwin-shared:-fPIC:-dynamiclib:.\$(SHLIB_MAJOR).\$(SHLIB_MINOR).dylib",
# iPhoneOS/iOS
"iphoneos-cross","llvm-gcc:-O3 -isysroot \$(CROSS_TOP)/SDKs/\$(CROSS_SDK) -fomit-frame-pointer -fno-common::-D_REENTRANT:iOS:-Wl,-search_paths_first%:BN_LLONG RC4_CHAR RC4_CHUNK DES_UNROLL BF_PTR:${no_asm}:dlfcn:darwin-shared:-fPIC -fno-common:-dynamiclib:.\$(SHLIB_MAJOR).\$(SHLIB_MINOR).dylib",
-@@ -1685,7 +1685,7 @@
+@@ -1717,8 +1717,7 @@
s/^CC=.*$/CC= $cc/;
s/^AR=\s*ar/AR= $ar/;
s/^RANLIB=.*/RANLIB= $ranlib/;
- s/^MAKEDEPPROG=.*$/MAKEDEPPROG= $cc/ if $cc eq "gcc";
-+ s/^MAKEDEPPROG=.*$/MAKEDEPPROG= $cc/;
+- s/^MAKEDEPPROG=.*$/MAKEDEPPROG= $cc/ if $ecc eq "gcc" || $ecc eq "clang";
++ s/^MAKEDEPPROG=.*$/MAKEDEPPROG= $cc/
}
s/^CFLAG=.*$/CFLAG= $cflags/;
s/^DEPFLAG=.*$/DEPFLAG=$depflags/;
-diff --git a/util/domd b/util/domd
---- a/util/domd
-+++ b/util/domd
-@@ -14,7 +14,7 @@
- cp Makefile Makefile.save
- # fake the presence of Kerberos
- touch $TOP/krb5.h
--if expr "$MAKEDEPEND" : '.*gcc$' > /dev/null; then
-+if true ; then # was: if expr "$MAKEDEPEND" : '.*gcc$' > /dev/null; then
- args=""
- while [ $# -gt 0 ]; do
- if [ "$1" != "--" ]; then args="$args $1"; fi
\b0 \
1. This LICENSE AGREEMENT is between the Python Software Foundation ("PSF"), and the Individual or Organization ("Licensee") accessing and otherwise using this software ("Python") in source or binary form and its associated documentation.\
\
-2. Subject to the terms and conditions of this License Agreement, PSF hereby grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, analyze, test, perform and/or display publicly, prepare derivative works, distribute, and otherwise use Python alone or in any derivative version, provided, however, that PSF's License Agreement and PSF's notice of copyright, i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 Python Software Foundation; All Rights Reserved" are retained in Python alone or in any derivative version prepared by Licensee.\
+2. Subject to the terms and conditions of this License Agreement, PSF hereby grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, analyze, test, perform and/or display publicly, prepare derivative works, distribute, and otherwise use Python alone or in any derivative version, provided, however, that PSF's License Agreement and PSF's notice of copyright, i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Python Software Foundation; All Rights Reserved" are retained in Python alone or in any derivative version prepared by Licensee.\
\
3. In the event Licensee prepares a derivative work that is based on or incorporates Python or any part thereof, and wants to make the derivative work available to others as provided herein, then Licensee hereby agrees to include in any such work a brief summary of the changes made to Python.\
\
fi
echo "" >> "${RC}"
echo "# Setting PATH for Python ${PYVER}" >> "${RC}"
- echo "# The orginal version is saved in .cshrc.pysave" >> "${RC}"
+ echo "# The original version is saved in .cshrc.pysave" >> "${RC}"
echo "set path=(${PYTHON_ROOT}/bin "'$path'")" >> "${RC}"
if [ `id -ur` = 0 ]; then
chown "${USER}" "${RC}"
fi
echo "" >> "${PR}"
echo "# Setting PATH for Python ${PYVER}" >> "${PR}"
-echo "# The orginal version is saved in `basename ${PR}`.pysave" >> "${PR}"
+echo "# The original version is saved in `basename ${PR}`.pysave" >> "${PR}"
echo 'PATH="'"${PYTHON_ROOT}/bin"':${PATH}"' >> "${PR}"
echo 'export PATH' >> "${PR}"
if [ `id -ur` = 0 ]; then
<key>CFBundleExecutable</key>
<string>IDLE</string>
<key>CFBundleGetInfoString</key>
- <string>%version%, © 2001-2015 Python Software Foundation</string>
+ <string>%version%, © 2001-2016 Python Software Foundation</string>
<key>CFBundleIconFile</key>
<string>IDLE.icns</string>
<key>CFBundleIdentifier</key>
<key>CFBundleExecutable</key>
<string>Python Launcher</string>
<key>CFBundleGetInfoString</key>
- <string>%VERSION%, © 2001-2015 Python Software Foundation</string>
+ <string>%VERSION%, © 2001-2016 Python Software Foundation</string>
<key>CFBundleIconFile</key>
<string>PythonLauncher.icns</string>
<key>CFBundleIdentifier</key>
The optional argument specifies which OS X SDK should be used to perform the
build. If xcodebuild is available and configured, this defaults to
the Xcode default MacOS X SDK, otherwise ``/Developer/SDKs/MacOSX.10.4u.sdk``
- if available or ``/`` if not.
+ if available or ``/`` if not. When building on OS X 10.5 or later, you can
+ specify ``/`` to use the installed system headers rather than an SDK. As of
+ OS X 10.9, you should install the optional system headers from the Command
+ Line Tools component using ``xcode-select``::
+
+ $ sudo xcode-select --install
See the section _`Building and using a universal binary of Python on Mac OS X`
for more information.
-* ``--with-univeral-archs=VALUE``
+* ``--with-universal-archs=VALUE``
Specify the kind of universal binary that should be created. This option is
only valid when ``--enable-universalsdk`` is specified. The default is
To build a universal binary that includes a 64-bit architecture, you must build
on a system running OS X 10.5 or later. The ``all`` and ``64-bit`` flavors can
-only be built with an 10.5 SDK because ``ppc64`` support was only included with
+only be built with a 10.5 SDK because ``ppc64`` support was only included with
OS X 10.5. Although legacy ``ppc`` support was included with Xcode 3 on OS X
10.6, it was removed in Xcode 4, versions of which were released on OS X 10.6
and which is the standard for OS X 10.7. To summarize, the
<key>CFBundleExecutable</key>
<string>Python</string>
<key>CFBundleGetInfoString</key>
- <string>%version%, (c) 2001-2015 Python Software Foundation.</string>
+ <string>%version%, (c) 2001-2016 Python Software Foundation.</string>
<key>CFBundleHelpBookFolder</key>
<array>
<string>Documentation</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleLongVersionString</key>
- <string>%version%, (c) 2001-2015 Python Software Foundation.</string>
+ <string>%version%, (c) 2001-2016 Python Software Foundation.</string>
<key>CFBundleName</key>
<string>Python</string>
<key>CFBundlePackageType</key>
<key>NSAppleScriptEnabled</key>
<true/>
<key>NSHumanReadableCopyright</key>
- <string>(c) 2001-2015 Python Software Foundation.</string>
+ <string>(c) 2001-2016 Python Software Foundation.</string>
<key>NSHighResolutionCapable</key>
<true/>
</dict>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
- <string>%VERSION%, (c) 2001-2015 Python Software Foundation.</string>
+ <string>%VERSION%, (c) 2001-2016 Python Software Foundation.</string>
<key>CFBundleLongVersionString</key>
- <string>%VERSION%, (c) 2001-2015 Python Software Foundation.</string>
+ <string>%VERSION%, (c) 2001-2016 Python Software Foundation.</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
PYTHON= python$(EXE)
BUILDPYTHON= python$(BUILDEXE)
+cross_compiling=@cross_compiling@
PYTHON_FOR_BUILD=@PYTHON_FOR_BUILD@
_PYTHON_HOST_PLATFORM=@_PYTHON_HOST_PLATFORM@
BUILD_GNU_TYPE= @build@
TCLTK_INCLUDES= @TCLTK_INCLUDES@
TCLTK_LIBS= @TCLTK_LIBS@
-# The task to run while instrument when building the profile-opt target
-PROFILE_TASK=-m test.regrtest --pgo
+# The task to run while instrumented when building the profile-opt target.
+# We exclude unittests with -x that take a rediculious amount of time to
+# run in the instrumented training build or do not provide much value.
+PROFILE_TASK=-m test.regrtest --pgo -x test_asyncore test_gdb test_multiprocessing_fork test_multiprocessing_forkserver test_multiprocessing_main_handling test_multiprocessing_spawn test_subprocess
# report files for gcov / lcov coverage report
COVERAGE_INFO= $(abs_builddir)/coverage.info
# Compile a binary with profile guided optimization.
profile-opt:
- @if [ $(LLVM_PROF_ERR) == yes ]; then \
+ @if [ $(LLVM_PROF_ERR) = yes ]; then \
echo "Error: Cannot perform PGO build because llvm-profdata was not found in PATH" ;\
echo "Please add it to PATH and run ./configure again" ;\
exit 1;\
$(MAKE) profile-removal
build_all_generate_profile:
- $(MAKE) all CFLAGS_NODIST="$(CFLAGS) $(PGO_PROF_GEN_FLAG)" LDFLAGS="$(LDFLAGS) $(PGO_PROF_GEN_FLAG)" LIBS="$(LIBS)"
+ $(MAKE) all CFLAGS_NODIST="$(CFLAGS) $(PGO_PROF_GEN_FLAG) @LTOFLAGS@" LDFLAGS="$(LDFLAGS) $(PGO_PROF_GEN_FLAG) @LTOFLAGS@" LIBS="$(LIBS)"
run_profile_task:
: # FIXME: can't run for a cross build
$(LLVM_PROF_MERGER)
build_all_use_profile:
- $(MAKE) all CFLAGS_NODIST="$(CFLAGS) $(PGO_PROF_USE_FLAG)"
+ $(MAKE) all CFLAGS_NODIST="$(CFLAGS) $(PGO_PROF_USE_FLAG) @LTOFLAGS@" LDFLAGS="$(LDFLAGS) @LTOFLAGS@"
# Compile and run with gcov
.PHONY=coverage coverage-lcov coverage-report
exit 1 ; \
fi
+# This is shared by the math and cmath modules
+Modules/_math.o: Modules/_math.c Modules/_math.h
+ $(CC) -c $(CCSHARED) $(PY_CORE_CFLAGS) -o $@ $<
+
# Build the shared modules
# Under GNU make, MAKEFLAGS are sorted and normalized; the 's' for
# -s, --silent or --quiet is always the first char.
# Under BSD make, MAKEFLAGS might be " -s -v x=y".
-sharedmods: $(BUILDPYTHON) pybuilddir.txt
+sharedmods: $(BUILDPYTHON) pybuilddir.txt Modules/_math.o
@case "$$MAKEFLAGS" in \
*\ -s*|s*) quiet="-q";; \
*) quiet="";; \
$(LINKCC) $(PY_LDFLAGS) -o $@ Programs/_freeze_importlib.o $(LIBRARY_OBJS_OMIT_FROZEN) $(LIBS) $(MODLIBS) $(SYSLIBS) $(LDLAST)
Python/importlib_external.h: $(srcdir)/Lib/importlib/_bootstrap_external.py Programs/_freeze_importlib
- ./Programs/_freeze_importlib \
- $(srcdir)/Lib/importlib/_bootstrap_external.py Python/importlib_external.h
+ if test "$(cross_compiling)" != "yes"; then \
+ ./Programs/_freeze_importlib \
+ $(srcdir)/Lib/importlib/_bootstrap_external.py Python/importlib_external.h; \
+ fi
Python/importlib.h: $(srcdir)/Lib/importlib/_bootstrap.py Programs/_freeze_importlib
- ./Programs/_freeze_importlib \
- $(srcdir)/Lib/importlib/_bootstrap.py Python/importlib.h
+ if test "$(cross_compiling)" != "yes"; then \
+ ./Programs/_freeze_importlib \
+ $(srcdir)/Lib/importlib/_bootstrap.py Python/importlib.h; \
+ fi
############################################################################
$(IO_OBJS): $(IO_H)
$(GRAMMAR_H): $(GRAMMAR_INPUT) $(PGEN)
- @$(MKDIR_P) Include
- $(PGEN) $(GRAMMAR_INPUT) $(GRAMMAR_H) $(GRAMMAR_C)
+ @$(MKDIR_P) Include
+ # Avoid copying the file onto itself for an in-tree build
+ if test "$(cross_compiling)" != "yes"; then \
+ $(PGEN) $(GRAMMAR_INPUT) $(GRAMMAR_H) $(GRAMMAR_C); \
+ else \
+ cp $(srcdir)/Include/graminit.h $(GRAMMAR_H).tmp; \
+ mv $(GRAMMAR_H).tmp $(GRAMMAR_H); \
+ fi
$(GRAMMAR_C): $(GRAMMAR_H)
- touch $(GRAMMAR_C)
+ if test "$(cross_compiling)" != "yes"; then \
+ touch $(GRAMMAR_C); \
+ else \
+ cp $(srcdir)/Python/graminit.c $(GRAMMAR_C).tmp; \
+ mv $(GRAMMAR_C).tmp $(GRAMMAR_C); \
+ fi
$(PGEN): $(PGENOBJS)
$(CC) $(OPT) $(PY_LDFLAGS) $(PGENOBJS) $(LIBS) -o $(PGEN)
fi
bininstall: altbininstall
+ if test ! -d $(DESTDIR)$(LIBPC); then \
+ echo "Creating directory $(LIBPC)"; \
+ $(INSTALL) -d -m $(DIRMODE) $(DESTDIR)$(LIBPC); \
+ fi
-if test -f $(DESTDIR)$(BINDIR)/python3$(EXE) -o -h $(DESTDIR)$(BINDIR)/python3$(EXE); \
then rm -f $(DESTDIR)$(BINDIR)/python3$(EXE); \
else true; \
# the Makefile in Mac
#
#
-# This target is here for backward compatiblity, previous versions of Python
+# This target is here for backward compatibility, previous versions of Python
# hadn't integrated framework installation in the normal install process.
frameworkinstall: install
profile-removal:
find . -name '*.gc??' -exec rm -f {} ';'
find . -name '*.profclang?' -exec rm -f {} ';'
+ find . -name '*.dyn' -exec rm -f {} ';'
rm -f $(COVERAGE_INFO)
rm -rf $(COVERAGE_REPORT)
Juancarlo Añez
Chris Angelico
Jérémy Anger
-Ankur Ankan
Jon Anglin
+Ankur Ankan
Heidi Annexstad
Ramchandra Apte
Éric Araujo
Richard Barran
Cesar Eduardo Barros
Des Barry
+Emanuel Barry
Ulf Bartelt
Campbell Barton
Don Bashford
Anthony Baxter
Mike Bayer
Samuel L. Bayer
+Tommy Beadle
Donald Beaudry
David Beazley
John Beck
Robin Becker
Torsten Becker
Bill Bedford
+Michał Bednarski
Ian Beer
Stefan Behnel
Reimer Behrends
Georg Brandl
Christopher Brannon
Terrence Brannon
-Germán M. Bravo
+Erin Braswell
Sven Brauch
+Germán M. Bravo
Erik Bray
Brian Brazil
Demian Brecht
Floris Bruynooghe
Matt Bryant
Stan Bubrouski
+Colm Buckley
Erik de Bueger
Jan-Hein Bührman
Lars Buitinck
Lee Busby
Katherine Busch
Ralph Butler
+Laurent De Buyst
Zach Byrne
Nicolas Cadou
Jp Calderone
Jason R. Coombs
Garrett Cooper
Greg Copeland
-Aldo Cortesi
Ian Cordasco
+Aldo Cortesi
David Costanzo
Scott Cotton
Greg Couch
Bruno Dupuis
Andy Dustman
Gary Duzan
-Karmen Dykstra
Eugene Dvurechenski
+Karmen Dykstra
Josip Dzolonga
Maxim Dzumanenko
Walter Dörwald
Daniel Ellis
Phil Elson
David Ely
+Victor van den Elzen
Jeff Epler
Tom Epperly
Gökcen Eraslan
Michael Foord
Amaury Forgeot d'Arc
Doug Fort
+Evens Fortuné
Chris Foster
John Fouhy
Andrew Francis
Martin Franklin
Kent Frazier
Bruce Frederiksen
+Jason Fried
Robin Friedrich
Bradley Froehle
Ivan Frohne
Nitin Ganatra
Fred Gansevles
Lars Marius Garshol
+Jake Garver
Dan Gass
Andrew Gaul
Matthieu Gautier
Stephen M. Gava
Xavier de Gaye
Harry Henry Gebel
+Tamás Bence Gedai
Marius Gedminas
Jan-Philip Gehrcke
Thomas Gellekum
Mihai Ibanescu
Ali Ikinci
Aaron Iles
+Thomas Ilsche
Lars Immisch
Bobby Impollonia
Naoki Inada
Bertrand Janin
Geert Jansen
Jack Jansen
+Hans-Peter Jansen
Bill Janssen
Thomas Jarosch
Juhana Jauhiainen
Philip H. Jensen
Philip Jenvey
MunSic Jeong
-Joe Jevnik
Chris Jerdonek
+Joe Jevnik
Jim Jewett
Pedro Diaz Jimenez
Orjan Johansen
Jeff Knupp
Kubilay Kocak
Greg Kochanski
+Manvisha Kodali
Damon Kohler
Marko Kohtala
Vajrasky Kok
Guido Kollerie
Jacek Konieczny
-Марк Коренберг
Arkady Koplyarov
Peter A. Koren
+Марк Коренберг
Vlad Korolev
+Susumu Koshiba
Joseph Koshy
Daniel Kozan
Jerzy Kozera
Andrew Kuchling
Dave Kuhlman
Jon Kuhn
+Upendra Kumar
Toshio Kuratomi
Ilia Kurenkov
Vladimir Kushnir
Amos Latteier
Piers Lauder
Ben Laurie
+Yoni Lavi
Simon Law
Julia Lawall
Chris Lawrence
Nick Lockwood
Stephanie Lockwood
Hugo Lopes Tavares
+Guillermo López-Anglada
Anne Lord
Tom Loredo
Justin Love
Peter Lovett
Chalmer Lowe
Jason Lowe
+Martin von Löwis
Tony Lownds
Ray Loyzaga
Kang-Hao (Kenny) Lu
Taras Lyapun
Jim Lynch
Mikael Lyngvig
-Martin von Löwis
-Guillermo López-Anglada
Jeff MacDonald
John Machin
Andrew I MacIntyre
Alex Martelli
Anthony Martin
Owen Martin
+Sidney San Martín
Westley Martínez
Sébastien Martini
-Sidney San Martín
Roger Masse
Nick Mathewson
Simon Mathieu
Ezio Melotti
Doug Mennella
Brian Merrell
+Alexis Métaireau
Luke Mewburn
Carl Meyer
Mike Meyer
Piotr Meyer
-Alexis Métaireau
Steven Miale
-Trent Mick
Jason Michalski
Franck Michea
Vincent Michel
+Trent Mick
Tom Middleton
Thomas Miedema
Stan Mihai
Paul Moore
Ross Moore
Ben Morgan
+Emily Morehouse
Derek Morr
James A Morrison
Martin Morrison
R. David Murray
Matti Mäki
Jörg Müller
+Kaushik N
Dale Nagata
John Nagle
Takahiro Nakayama
Mikhail Novikov
Michal Nowikowski
Steffen Daode Nurpmeso
+Thomas Nyberg
Nigel O'Brian
John O'Connor
Kevin O'Connor
Denis S. Otkidach
Peter Otten
Michael Otteneder
-R. M. Oudkerk
+Richard Oudkerk
Russel Owen
Joonas Paalasmaa
Martin Packman
Shriphani Palakodety
+Julien Palard
+Aviv Palivoda
Ondrej Palkovsky
Mike Pall
Todd R. Palmer
Juan David Ibáñez Palomar
+Nicola Palumbo
Jan Palus
Yongzhi Pan
Martin Panter
Peter Parente
Alexandre Parenteau
Dan Parisien
+HyeSoo Park
William Park
Claude Paroz
Heikki Partanen
Tim Peters
Benjamin Peterson
Joe Peterson
+Ulrich Petri
Chris Petrilli
Roumen Petrov
Bjorn Pettersen
Gavrie Philipson
Adrian Phillips
Christopher J. Phoenix
+James Pickering
Neale Pickett
Jim St. Pierre
Dan Pierson
François Pinard
Tom Pinckney
Zach Pincus
-Zero Piraeus
Michael Piotrowski
+Zero Piraeus
Antoine Pitrou
Jean-François Piéronne
Oleg Plakhotnyuk
Amrit Prem
Paul Prescod
Donovan Preston
+Eric Price
Paul Price
Iuliia Proskurnia
Dorian Pula
Steve Purcell
Eduardo Pérez
Fernando Pérez
+Kevin Jing Qiu
Pierre Quentel
Brian Quinlan
-Kevin Jing Qiu
Anders Qvist
Thomas Rachel
Ram Rachum
Abhilash Raj
Shorya Raj
Jeff Ramnani
+Varpu Rantala
Brodie Rao
Senko Rasic
Antti Rasinen
Flávio Ribeiro
Francesco Ricciardi
Tim Rice
+Martin Richard
Jan Pieter Riegel
Armin Rigo
-Martin Richard
Arc Riley
Nicholas Riley
Jean-Claude Rimbault
Mark Roberts
Andy Robinson
Jim Robinson
+Yolanda Robla
+Daniel Rocco
Mark Roddy
Kevin Rodgers
Sean Rodman
Josh Rosenberg
Jim Roskind
Brian Rosner
+Ignacio Rossi
Guido van Rossum
Just van Rossum
Hugo van Rossum
Bob Savage
Dave Sawyer
Ben Sayer
-sbt
Luca Sbardella
Marco Scataglini
Andrew Schaaf
Michael Schneider
Peter Schneider-Kamp
Arvin Schnell
+Nofar Schnider
Scott Schram
Robin Schreiber
Chad J. Schroeder
Denis Severson
Ian Seyer
Dmitry Shachnev
+Anish Shah
Daniel Shahaf
-Ha Shao
Mark Shannon
+Ha Shao
Richard Shapiro
Varun Sharma
+Daniel Shaulov
Vlad Shcherbina
Justin Sheehy
Charlie Shepherd
Paul Sokolovsky
Evgeny Sologubov
Cody Somerville
+Anthony Sottile
Edoardo Spadolini
Geoffrey Spear
Clay Spence
Sebastian Ortiz Vasquez
Alexandre Vassalotti
Nadeem Vawda
+Sye van der Veen
Frank Vercruesse
Mike Verdone
Jaap Vermeulen
Michael Vogt
Radu Voicilas
Alex Volkov
+Guido Vranken
Martijn Vries
Sjoerd de Vries
-Guido Vranken
+Jonas Wagner
Daniel Wagner-Hall
Niki W. Waibel
Wojtek Walczak
Larry Wall
Kevin Walzer
Rodrigo Steinmuller Wanderley
+Dingyuan Wang
Ke Wang
+Liang-Bo Wang
Greg Ward
Tom Wardill
Zachary Ware
-Jonas Wagner
Barry Warsaw
Steve Waterbury
Bob Watson
Gerry Wiener
Frank Wierzbicki
Santoso Wijaya
+Chris Wilcox
Bryce "Zooko" Wilcox-O'Hearn
Timothy Wild
Jakub Wilk
Carol Willing
Steven Willis
Frank Willison
+Alex Willmer
David Wilson
Geoff Wilson
Greg V. Wilson
Xiang Zhang
Robert Xiao
Florent Xicluna
-Hirokazu Yamamoto
Arnon Yaari
+Hirokazu Yamamoto
Ka-Ping Yee
Jason Yeo
EungJun Yi
Gennadiy Zlobin
Doug Zongker
Peter Åstrand
-Ignacio Rossi
-Laurent De Buyst
-Nicola Palumbo
evilzero
- Issue #15777: Fix a refleak in _posixsubprocess.
-- Issue ##665194: Update `email.utils.localtime` to use datetime.astimezone and
+- Issue #665194: Update `email.utils.localtime` to use datetime.astimezone and
correctly handle historic changes in UTC offsets.
- Issue #15199: Fix JavaScript's default MIME type to application/javascript.
- Issue #15008: Implement PEP 362 "Signature Objects".
Patch by Yury Selivanov.
-- Issue: #15138: base64.urlsafe_{en,de}code() are now 3-4x faster.
+- Issue #15138: base64.urlsafe_{en,de}code() are now 3-4x faster.
- Issue #444582: Add shutil.which, for finding programs on the system path.
Original patch by Erik Demaine, with later iterations by Jan Killian
functions to support PEP 3115 compliant dynamic class creation. Patch by
Daniel Urban and Nick Coghlan.
-- Issue #13152: Allow to specify a custom tabsize for expanding tabs in
+- Issue #13152: Allow specifying a custom tabsize for expanding tabs in
textwrap. Patch by John Feuerstein.
- Issue #14721: Send the correct 'Content-length: 0' header when the body is an
objects. Initial patch by Matthias Troffaes.
- Fix OSError.__init__ and OSError.__new__ so that each of them can be
- overriden and take additional arguments (followup to issue #12555).
+ overridden and take additional arguments (followup to issue #12555).
- Fix the fix for issue #12149: it was incorrect, although it had the side
effect of appearing to resolve the issue. Thanks to Mark Shannon for
given, produce an informative error message which includes the name(s) of the
missing arguments.
-- Issue #12370: Fix super with no arguments when __class__ is overriden in the
+- Issue #12370: Fix super with no arguments when __class__ is overridden in the
class body.
- Issue #12084: os.stat on Windows now works properly with relative symbolic
fixed.
- Issue #14166: Pickler objects now have an optional ``dispatch_table``
- attribute which allows to set custom per-pickler reduction functions.
+ attribute which allows setting custom per-pickler reduction functions.
Patch by sbt.
-- Issue #14177: marshal.loads() now raises TypeError when given an unicode
+- Issue #14177: marshal.loads() now raises TypeError when given a unicode
string. Patch by Guilherme Gonçalves.
- Issue #13550: Remove the debug machinery from the threading module: remove
- Issue #13591: A bug in importlib has been fixed that caused import_module
to load a module twice.
-- Issue #13449 sched.scheduler.run() method has a new "blocking" parameter which
+- Issue #13449: sched.scheduler.run() method has a new "blocking" parameter which
when set to False makes run() execute the scheduled events due to expire
soonest (if any) and then return. Patch by Giampaolo Rodolà.
-- Issue #8684 sched.scheduler class can be safely used in multi-threaded
+- Issue #8684: sched.scheduler class can be safely used in multi-threaded
environments. Patch by Josiah Carlson and Giampaolo Rodolà.
- Alias resource.error to OSError ala PEP 3151.
binary mode, but ensure that the shebang is decodable from UTF-8 and from the
encoding of the script.
-- Issue #8498: In socket.accept(), allow to specify 0 as a backlog value in
+- Issue #8498: In socket.accept(), allow specifying 0 as a backlog value in
order to accept exactly one connection. Patch by Daniel Evers.
- Issue #12011: signal.signal() and signal.siginterrupt() raise an OSError,
- Issue #12331: The test suite for lib2to3 can now run from an installed
Python.
-- Issue #12626: In regrtest, allow to filter tests using a glob filter
+- Issue #12626: In regrtest, allow filtering tests using a glob filter
with the ``-m`` (or ``--match``) option. This works with all test cases
using the unittest module. This is useful with long test suites
such as test_io or test_subprocess.
Core and Builtins
-----------------
-- Issue #10451: memoryview objects could allow to mutate a readable buffer.
+- Issue #10451: memoryview objects could allow mutating a readable buffer.
Initial patch by Ross Lagerwall.
Library
- Add the "display" and "undisplay" pdb commands.
-- Issue #7245: Add a SIGINT handler in pdb that allows to break a program again
+- Issue #7245: Add a SIGINT handler in pdb that allows breaking a program again
after a "continue" command.
- Add the "interact" pdb command.
PyErr_Format, on machines with HAVE_LONG_LONG defined.
- Issue #6151: Made PyDescr_COMMON conform to standard C (like PyObject_HEAD in
- PEP 3123). The PyDescr_TYPE and PyDescr_NAME macros should be should used for
+ PEP 3123). The PyDescr_TYPE and PyDescr_NAME macros should be used for
accessing the d_type and d_name members of structures using PyDescr_COMMON.
- Issue #6405: Remove duplicate type declarations in descrobject.h.
correct encoding.
- Issue #4870: Add an `options` attribute to SSL contexts, as well as several
- ``OP_*`` constants to the `ssl` module. This allows to selectively disable
+ ``OP_*`` constants to the `ssl` module. This allows selectively disabling
protocol versions, when used in combination with `PROTOCOL_SSLv23`.
- Issue #8759: Fixed user paths in sysconfig for posix and os2 schemes.
cElementTree module is updated too.
- Issue #7774: Set sys.executable to an empty string if argv[0] has been set to
- an non existent program name and Python is unable to retrieve the real program
+ a non existent program name and Python is unable to retrieve the real program
name.
- Issue #7880: Fix sysconfig when the python executable is a symbolic link.
messages parsed by email.Parser.HeaderParser.
- Issue #7361: Importlib was not properly checking the number of bytes in
- bytecode file when it was less then 8 bytes.
+ bytecode file when it was less than 8 bytes.
- Issue #7633: In the decimal module, Context class methods (with the exception
of canonical and is_canonical) now accept instances of int and long wherever a
- Issue #7900: The getgroups(2) system call on MacOSX behaves rather oddly
compared to other unix systems. In particular, os.getgroups() does not reflect
- any changes made using os.setgroups() but basicly always returns the same
+ any changes made using os.setgroups() but basically always returns the same
information as the id command. os.getgroups() can now return more than 16
groups on MacOSX.
- Issue #1578269: Implement os.symlink for Windows 6.0+. Patch by Jason
R. Coombs.
-- In struct.pack, correctly propogate exceptions from computing the truth of an
+- In struct.pack, correctly propagate exceptions from computing the truth of an
object in the '?' format.
- Issue #9000: datetime.timezone objects now have eval-friendly repr.
added LIBS to OS X framework builds.
- Issue #5809: Specifying both --enable-framework and --enable-shared is
- an error. Configure now explicity tells you about this.
+ an error. Configure now explicitly tells you about this.
- Issue #1664: Make nntplib IPv6-capable. Patch by Derek Morr.
- Issue #5006: Better handling of unicode byte-order marks (BOM) in the io
- library. This means, for example, that opening an UTF-16 text file in
+ library. This means, for example, that opening a UTF-16 text file in
append mode doesn't add a BOM at the end of the file if the file isn't
empty.
been backported to help facilitate transitions from 2.7 to 3.1.
- Issue #1885: distutils. When running sdist with --formats=tar,gztar
- the tar file was overriden by the gztar one.
+ the tar file was overridden by the gztar one.
- Issue #4863: distutils.mwerkscompiler has been removed.
- Issue #4756: zipfile.is_zipfile() now supports file-like objects. Patch by
Gabriel Genellina.
-- Issue #4574: reading an UTF16-encoded text file crashes if \r on 64-char
+- Issue #4574: reading a UTF16-encoded text file crashes if \r on 64-char
boundary.
- Issue #4223: inspect.getsource() will now correctly display source code
- Issue #4051: Prevent conflict of UNICODE macros in cPickle.
-- Issue #4738: Each zlib object now has a separate lock, allowing to compress
- or decompress several streams at once on multi-CPU systems. Also, the GIL
+- Issue #4738: Each zlib object now has a separate lock, allowing several streams
+ to be compressed or decompressed at once on multi-CPU systems. Also, the GIL
is now released when computing the CRC of a large buffer. Patch by ebfe.
- Issue #4228: Pack negative values the same way as 2.4 in struct's L format.
the recursion limit checking code, due to bogus handling of recursion
limit when USE_STACKCHEK was enabled.
-- Issue 3639: The _warnings module could segfault the interpreter when
+- Issue #3639: The _warnings module could segfault the interpreter when
unexpected types were passed in as arguments.
- Issue #3712: The memoryview object had a reference leak and didn't support
It is now maintained outside of the standard library at
http://www.jcea.es/programacion/pybsddb.htm.
-- Issue 600362: Relocated parse_qs() and parse_qsl(), from the cgi module
+- Issue #600362: Relocated parse_qs() and parse_qsl(), from the cgi module
to the urlparse one. Added a DeprecationWarning in the old module, it
will be deprecated in the future.
- Issue #3719: platform.architecture() fails if there are spaces in the
path to the Python binary.
-- Issue 3602: As part of the merge of r66135, make the parameters on
+- Issue #3602: As part of the merge of r66135, make the parameters on
warnings.catch_warnings() keyword-only. Also remove a DeprecationWarning.
- The deprecation warnings for the camelCase threading API names were removed.
exploitation of poor argument checking.
- bsddb code updated to version 4.7.3pre2. This code is the same than
- Python 2.6 one, since the intention is to keep an unified 2.x/3.x codebase.
+ Python 2.6 one, since the intention is to keep a unified 2.x/3.x codebase.
The Python code is automatically translated using "2to3". Please, do not
update this code in Python 3.0 by hand. Update the 2.6 one and then
do "2to3".
as bytes string, please use PyUnicode_AsUTF8String() instead.
- Issue #3460: PyUnicode_Join() implementation is 10% to 80% faster thanks
- to Python 3.0's stricter semantics which allow to avoid successive
+ to Python 3.0's stricter semantics which allow avoiding successive
reallocations of the result string (this also affects str.join()).
certain operations between bytes/buffer and str like str(b'') and
comparison.
-- The standards streams sys.stdin, stdout and stderr may be None when
- the when the C runtime library returns an invalid file descriptor
+- The standard streams sys.stdin, stdout and stderr may be None
+ when the C runtime library returns an invalid file descriptor
for the streams (fileno(stdin) < 0). For now this happens only for
Windows GUI apps and scripts started with `pythonw.exe`.
- Removed the 'new' module.
-- Removed all types from the 'types' module that are easily accessable
+- Removed all types from the 'types' module that are easily accessible
through builtins.
- Patch #1110248: SYNC_FLUSH the zlib buffer for GZipFile.flush.
-- Patch #1107973: Allow to iterate over the lines of a tarfile.ExFileObject.
+- Patch #1107973: Allow iterating over the lines of a tarfile.ExFileObject.
- Patch #1104111: Alter setup.py --help and --help-commands.
same as when the argument is omitted).
[SF bug 658254, patch 663482]
-- nntplib does now allow to ignore a .netrc file.
+- nntplib does now allow ignoring a .netrc file.
- urllib2 now recognizes Basic authentication even if other authentication
schemes are offered.
would not be removed while allocating a new weakref object. Since
GC could be invoked at that time, however, that assumption was
invalid. In a truly obscure case of GC being triggered during
- creation for a new weakref object for an referent which already
+ creation for a new weakref object for a referent which already
has a weakref without a callback which is only referenced from
cyclic trash, a memory error can occur. This consistently created a
segfault in a debug build, but provided less predictable behavior in
- fcntl.ioctl now warns if the mutate flag is not specified.
-- nt now properly allows to refer to UNC roots, e.g. in nt.stat().
+- nt now properly allows referring to UNC roots, e.g. in nt.stat().
- the weakref module now supports additional objects: array.array,
sre.pattern_objects, file objects, and sockets.
- All standard iterators now ensure that, once StopIteration has been
raised, all future calls to next() on the same iterator will also
raise StopIteration. There used to be various counterexamples to
- this behavior, which could caused confusion or subtle program
+ this behavior, which could have caused confusion or subtle program
breakage, without any benefits. (Note that this is still an
iterator's responsibility; the iterator framework does not enforce
this.)
- New functions PyErr_SetExcFromWindowsErr() and
PyErr_SetExcFromWindowsErrWithFilename(). Similar to
PyErr_SetFromWindowsErrWithFilename() and
- PyErr_SetFromWindowsErr(), but they allow to specify
+ PyErr_SetFromWindowsErr(), but they allow specifying
the exception type to raise. Available on Windows.
- Py_FatalError() is now declared as taking a const char* argument. It
- property() now takes 4 keyword arguments: fget, fset, fdel and doc.
These map to read-only attributes 'fget', 'fset', 'fdel', and '__doc__'
in the constructed property object. fget, fset and fdel weren't
- discoverable from Python in 2.2a3. __doc__ is new, and allows to
- associate a docstring with a property.
+ discoverable from Python in 2.2a3. __doc__ is new, and allows
+ associating a docstring with a property.
- Comparison overloading is now more completely implemented. For
example, a str subclass instance can properly be compared to a str
-----
- regrtest.py now knows which tests are expected to be skipped on some
- platforms, allowing to give clearer test result output. regrtest
+ platforms, allowing clearer test result output to be given. regrtest
also has optional --use/-u switch to run normally disabled tests
which require network access or consume significant disk resources.
- xml.dom.minidom offers a toprettyxml method. A number of DOM
conformance issues have been resolved. In particular, Element now
- has an hasAttributes method, and the handling of namespaces was
+ has a hasAttributes method, and the handling of namespaces was
improved.
- Ka-Ping Yee contributed two new modules: inspect.py, a module for
- There is a new Unicode companion to the PyObject_Str() API
called PyObject_Unicode(). It behaves in the same way as the
- former, but assures that the returned value is an Unicode object
+ former, but assures that the returned value is a Unicode object
(applying the usual coercion if necessary).
- The comparison operators support "rich comparison overloading" (PEP
Probably the most pervasive change is the addition of Unicode support.
We've added a new fundamental datatype, the Unicode string, a new
-build-in function unicode(), an numerous C APIs to deal with Unicode
+built-in function unicode(), and numerous C APIs to deal with Unicode
and encodings. See the file Misc/unicode.txt for details, or
http://starship.python.net/crew/lemburg/unicode-proposal.txt.
* Tools/scripts/dutree.py:
During display, if EPIPE is raised, it's probably because a pager was
- killed. Discard the error in that case, but propogate it otherwise.
+ killed. Discard the error in that case, but propagate it otherwise.
Fri Mar 26 16:20:45 1999 Guido van Rossum <guido@eric.cnri.reston.va.us>
- The uu module now deals better with trailing garbage generated by
some broke uuencoders.
-- The telnet module now has an my_interact() method which uses threads
+- The telnet module now has a my_interact() method which uses threads
instead of select. The interact() method uses this by default on
Windows (where the single-threaded version doesn't work).
- New macros to access object members for PyFunction, PyCFunction
objects.
-- New APIs PyImport_AppendInittab() an PyImport_ExtendInittab() to
+- New APIs PyImport_AppendInittab() and PyImport_ExtendInittab() to
dynamically add one or many entries to the table of built-in modules.
- New macro Py_InitModule3(name, methods, doc) which calls
- Changed the checks made in Py_Initialize() and Py_Finalize(). It is
now legal to call these more than once. The first call to
Py_Initialize() initializes, the first call to Py_Finalize()
-finalizes. There's also a new API, Py_IsInitalized() which checks
+finalizes. There's also a new API, Py_IsInitialized() which checks
whether we are already initialized (in case you want to leave things
as they were).
python parser. Corresponding standard library modules token and symbol
defines the numeric values of tokens and non-terminal symbols.
-* The posix module has aquired new functions setuid(), setgid(),
+* The posix module has acquired new functions setuid(), setgid(),
execve(), and exec() has been renamed to execv().
* The array module is extended with 8-byte object swaps, the 'i'
* For select.select(), a timeout (4th) argument of None means the same
as leaving the timeout argument out.
-* Module strop (and hence standard library module string) has aquired
+* Module strop (and hence standard library module string) has acquired
a new function: rindex(). Thanks to Amrit Prem!
* Module regex defines a new function symcomp() which uses an extended
* repr(x) returns the same as `x`. (Some users found it easier to
have this as a function.)
-* round(x) returns the floating point number x rounded to an whole
+* round(x) returns the floating point number x rounded to a whole
number, represented as a floating point number. round(x, n) returns x
rounded to n digits.
to give more useful results for negative operands
- Changed/added range checks for long/plain integer shifts
- Options found after "-c command" are now passed to the command in sys.argv
- (note subtle incompatiblity with "python -c command -- -options"!)
+ (note subtle incompatibility with "python -c command -- -options"!)
- Module stdwin is better protected against touching objects after they've
been closed; menus can now also be closed explicitly
- Stdwin now uses its own exception (stdwin.error)
Python News
+++++++++++
+What's New in Python 3.5.2 final?
+=================================
+
+Release date: 2016-06-26
+
+Core and Builtins
+-----------------
+
+- Issue #26930: Update Windows builds to use OpenSSL 1.0.2h.
+
+Tests
+-----
+
+- Issue #26867: Ubuntu's openssl OP_NO_SSLv3 is forced on by default; fix test.
+
+IDLE
+----
+
+- Issue #27365: Allow non-ascii in idlelib/NEWS.txt - minimal part for 3.5.2.
+
+
+What's New in Python 3.5.2 release candidate 1?
+===============================================
+
+Release date: 2016-06-12
+
+Core and Builtins
+-----------------
+
+- Issue #27066: Fixed SystemError if a custom opener (for open()) returns a
+ negative number without setting an exception.
+
+- Issue #20041: Fixed TypeError when frame.f_trace is set to None.
+ Patch by Xavier de Gaye.
+
+- Issue #26168: Fixed possible refleaks in failing Py_BuildValue() with the "N"
+ format unit.
+
+- Issue #26991: Fix possible refleak when creating a function with annotations.
+
+- Issue #27039: Fixed bytearray.remove() for values greater than 127. Patch by
+ Joe Jevnik.
+
+- Issue #23640: int.from_bytes() no longer bypasses constructors for subclasses.
+
+- Issue #26811: gc.get_objects() no longer contains a broken tuple with NULL
+ pointer.
+
+- Issue #20120: Use RawConfigParser for .pypirc parsing,
+ removing support for interpolation unintentionally added
+ with move to Python 3. Behavior no longer does any
+ interpolation in .pypirc files, matching behavior in Python
+ 2.7 and Setuptools 19.0.
+
+- Issue #26659: Make the builtin slice type support cycle collection.
+
+- Issue #26718: super.__init__ no longer leaks memory if called multiple times.
+ NOTE: A direct call of super.__init__ is not endorsed!
+
+- Issue #25339: PYTHONIOENCODING now has priority over locale in setting the
+ error handler for stdin and stdout.
+
+- Issue #26494: Fixed crash on iterating exhausting iterators.
+ Affected classes are generic sequence iterators, iterators of str, bytes,
+ bytearray, list, tuple, set, frozenset, dict, OrderedDict, corresponding
+ views and os.scandir() iterator.
+
+- Issue #26581: If coding cookie is specified multiple times on a line in
+ Python source code file, only the first one is taken to account.
+
+- Issue #26464: Fix str.translate() when string is ASCII and first replacements
+ removes character, but next replacement uses a non-ASCII character or a
+ string longer than 1 character. Regression introduced in Python 3.5.0.
+
+- Issue #22836: Ensure exception reports from PyErr_Display() and
+ PyErr_WriteUnraisable() are sensible even when formatting them produces
+ secondary errors. This affects the reports produced by
+ sys.__excepthook__() and when __del__() raises an exception.
+
+- Issue #26302: Correct behavior to reject comma as a legal character for
+ cookie names.
+
+- Issue #4806: Avoid masking the original TypeError exception when using star
+ (*) unpacking in function calls. Based on patch by Hagen Fürstenau and
+ Daniel Urban.
+
+- Issue #27138: Fix the doc comment for FileFinder.find_spec().
+
+- Issue #26154: Add a new private _PyThreadState_UncheckedGet() function to get
+ the current Python thread state, but don't issue a fatal error if it is NULL.
+ This new function must be used instead of accessing directly the
+ _PyThreadState_Current variable. The variable is no more exposed since
+ Python 3.5.1 to hide the exact implementation of atomic C types, to avoid
+ compiler issues.
+
+- Issue #26194: Deque.insert() gave odd results for bounded deques that had
+ reached their maximum size. Now an IndexError will be raised when attempting
+ to insert into a full deque.
+
+- Issue #25843: When compiling code, don't merge constants if they are equal
+ but have a different types. For example, ``f1, f2 = lambda: 1, lambda: 1.0``
+ is now correctly compiled to two different functions: ``f1()`` returns ``1``
+ (``int``) and ``f2()`` returns ``1.0`` (``int``), even if ``1`` and ``1.0``
+ are equal.
+
+- Issue #22995: [UPDATE] Comment out the one of the pickleability tests in
+ _PyObject_GetState() due to regressions observed in Cython-based projects.
+
+- Issue #25961: Disallowed null characters in the type name.
+
+- Issue #25973: Fix segfault when an invalid nonlocal statement binds a name
+ starting with two underscores.
+
+- Issue #22995: Instances of extension types with a state that aren't
+ subclasses of list or dict and haven't implemented any pickle-related
+ methods (__reduce__, __reduce_ex__, __getnewargs__, __getnewargs_ex__,
+ or __getstate__), can no longer be pickled. Including memoryview.
+
+- Issue #20440: Massive replacing unsafe attribute setting code with special
+ macro Py_SETREF.
+
+- Issue #25766: Special method __bytes__() now works in str subclasses.
+
+- Issue #25421: __sizeof__ methods of builtin types now use dynamic basic size.
+ This allows sys.getsize() to work correctly with their subclasses with
+ __slots__ defined.
+
+- Issue #25709: Fixed problem with in-place string concatenation and utf-8 cache.
+
+- Issue #27147: Mention PEP 420 in the importlib docs.
+
+- Issue #24097: Fixed crash in object.__reduce__() if slot name is freed inside
+ __getattr__.
+
+- Issue #24731: Fixed crash on converting objects with special methods
+ __bytes__, __trunc__, and __float__ returning instances of subclasses of
+ bytes, int, and float to subclasses of bytes, int, and float correspondingly.
+
+- Issue #26478: Fix semantic bugs when using binary operators with dictionary
+ views and tuples.
+
+- Issue #26171: Fix possible integer overflow and heap corruption in
+ zipimporter.get_data().
+
+- Issue #25660: Fix TAB key behaviour in REPL with readline.
+
+- Issue #25887: Raise a RuntimeError when a coroutine object is awaited
+ more than once.
+
+- Issue #27243: Update the __aiter__ protocol: instead of returning
+ an awaitable that resolves to an asynchronous iterator, the asynchronous
+ iterator should be returned directly. Doing the former will trigger a
+ PendingDeprecationWarning.
+
+
+Library
+-------
+
+- Issue #26556: Update expat to 2.1.1, fixes CVE-2015-1283.
+
+- Fix TLS stripping vulnerability in smptlib, CVE-2016-0772. Reported by Team
+ Oststrom
+
+- Issue #21386: Implement missing IPv4Address.is_global property. It was
+ documented since 07a5610bae9d. Initial patch by Roger Luethi.
+
+- Issue #20900: distutils register command now decodes HTTP responses
+ correctly. Initial patch by ingrid.
+
+- A new version of typing.py provides several new classes and
+ features: @overload outside stubs, Reversible, DefaultDict, Text,
+ ContextManager, Type[], NewType(), TYPE_CHECKING, and numerous bug
+ fixes (note that some of the new features are not yet implemented in
+ mypy or other static analyzers). Also classes for PEP 492
+ (Awaitable, AsyncIterable, AsyncIterator) have been added (in fact
+ they made it into 3.5.1 but were never mentioned).
+
+- Issue #25738: Stop http.server.BaseHTTPRequestHandler.send_error() from
+ sending a message body for 205 Reset Content. Also, don't send Content
+ header fields in responses that don't have a body. Patch by Susumu
+ Koshiba.
+
+- Issue #21313: Fix the "platform" module to tolerate when sys.version
+ contains truncated build information.
+
+- Issue #26839: On Linux, :func:`os.urandom` now calls ``getrandom()`` with
+ ``GRND_NONBLOCK`` to fall back on reading ``/dev/urandom`` if the urandom
+ entropy pool is not initialized yet. Patch written by Colm Buckley.
+
+- Issue #27164: In the zlib module, allow decompressing raw Deflate streams
+ with a predefined zdict. Based on patch by Xiang Zhang.
+
+- Issue #24291: Fix wsgiref.simple_server.WSGIRequestHandler to completely
+ write data to the client. Previously it could do partial writes and
+ truncate data. Also, wsgiref.handler.ServerHandler can now handle stdout
+ doing partial writes, but this is deprecated.
+
+- Issue #26809: Add ``__all__`` to :mod:`string`. Patch by Emanuel Barry.
+
+- Issue #26373: subprocess.Popen.communicate now correctly ignores
+ BrokenPipeError when the child process dies before .communicate()
+ is called in more/all circumstances.
+
+- Issue #21776: distutils.upload now correctly handles HTTPError.
+ Initial patch by Claudiu Popa.
+
+- Issue #27114: Fix SSLContext._load_windows_store_certs fails with
+ PermissionError
+
+- Issue #18383: Avoid creating duplicate filters when using filterwarnings
+ and simplefilter. Based on patch by Alex Shkop.
+
+- Issue #27057: Fix os.set_inheritable() on Android, ioctl() is blocked by
+ SELinux and fails with EACCESS. The function now falls back to fcntl().
+ Patch written by Michał Bednarski.
+
+- Issue #27014: Fix infinite recursion using typing.py. Thanks to Kalle Tuure!
+
+- Issue #14132: Fix urllib.request redirect handling when the target only has
+ a query string. Original fix by Ján Janech.
+
+- Issue #17214: The "urllib.request" module now percent-encodes non-ASCII
+ bytes found in redirect target URLs. Some servers send Location header
+ fields with non-ASCII bytes, but "http.client" requires the request target
+ to be ASCII-encodable, otherwise a UnicodeEncodeError is raised. Based on
+ patch by Christian Heimes.
+
+- Issue #26892: Honor debuglevel flag in urllib.request.HTTPHandler. Patch
+ contributed by Chi Hsuan Yen.
+
+- Issue #22274: In the subprocess module, allow stderr to be redirected to
+ stdout even when stdout is not redirected. Patch by Akira Li.
+
+- Issue #26807: mock_open 'files' no longer error on readline at end of file.
+ Patch from Yolanda Robla.
+
+- Issue #25745: Fixed leaking a userptr in curses panel destructor.
+
+- Issue #26977: Removed unnecessary, and ignored, call to sum of squares helper
+ in statistics.pvariance.
+
+- Issue #26881: The modulefinder module now supports extended opcode arguments.
+
+- Issue #23815: Fixed crashes related to directly created instances of types in
+ _tkinter and curses.panel modules.
+
+- Issue #17765: weakref.ref() no longer silently ignores keyword arguments.
+ Patch by Georg Brandl.
+
+- Issue #26873: xmlrpc now raises ResponseError on unsupported type tags
+ instead of silently return incorrect result.
+
+- Issue #26711: Fixed the comparison of plistlib.Data with other types.
+
+- Issue #24114: Fix an uninitialized variable in `ctypes.util`.
+
+ The bug only occurs on SunOS when the ctypes implementation searches
+ for the `crle` program. Patch by Xiang Zhang. Tested on SunOS by
+ Kees Bos.
+
+- Issue #26864: In urllib.request, change the proxy bypass host checking
+ against no_proxy to be case-insensitive, and to not match unrelated host
+ names that happen to have a bypassed hostname as a suffix. Patch by Xiang
+ Zhang.
+
+- Issue #26634: recursive_repr() now sets __qualname__ of wrapper. Patch by
+ Xiang Zhang.
+
+- Issue #26804: urllib.request will prefer lower_case proxy environment
+ variables over UPPER_CASE or Mixed_Case ones. Patch contributed by Hans-Peter
+ Jansen.
+
+- Issue #26837: assertSequenceEqual() now correctly outputs non-stringified
+ differing items (like bytes in the -b mode). This affects assertListEqual()
+ and assertTupleEqual().
+
+- Issue #26041: Remove "will be removed in Python 3.7" from deprecation
+ messages of platform.dist() and platform.linux_distribution().
+ Patch by Kumaripaba Miyurusara Athukorala.
+
+- Issue #26822: itemgetter, attrgetter and methodcaller objects no longer
+ silently ignore keyword arguments.
+
+- Issue #26733: Disassembling a class now disassembles class and static methods.
+ Patch by Xiang Zhang.
+
+- Issue #26801: Fix error handling in :func:`shutil.get_terminal_size`, catch
+ :exc:`AttributeError` instead of :exc:`NameError`. Patch written by Emanuel
+ Barry.
+
+- Issue #24838: tarfile's ustar and gnu formats now correctly calculate name
+ and link field limits for multibyte character encodings like utf-8.
+
+- Issue #26657: Fix directory traversal vulnerability with http.server on
+ Windows. This fixes a regression that was introduced in 3.3.4rc1 and
+ 3.4.0rc1. Based on patch by Philipp Hagemeister.
+
+- Issue #26717: Stop encoding Latin-1-ized WSGI paths with UTF-8. Patch by
+ Anthony Sottile.
+
+- Issue #26735: Fix :func:`os.urandom` on Solaris 11.3 and newer when reading
+ more than 1,024 bytes: call ``getrandom()`` multiple times with a limit of
+ 1024 bytes per call.
+
+- Issue #16329: Add .webm to mimetypes.types_map. Patch by Giampaolo Rodola'.
+
+- Issue #13952: Add .csv to mimetypes.types_map. Patch by Geoff Wilson.
+
+- Issue #26709: Fixed Y2038 problem in loading binary PLists.
+
+- Issue #23735: Handle terminal resizing with Readline 6.3+ by installing our
+ own SIGWINCH handler. Patch by Eric Price.
+
+- Issue #26586: In http.server, respond with "413 Request header fields too
+ large" if there are too many header fields to parse, rather than killing
+ the connection and raising an unhandled exception. Patch by Xiang Zhang.
+
+- Issue #22854: Change BufferedReader.writable() and
+ BufferedWriter.readable() to always return False.
+
+- Issue #25195: Fix a regression in mock.MagicMock. _Call is a subclass of
+ tuple (changeset 3603bae63c13 only works for classes) so we need to
+ implement __ne__ ourselves. Patch by Andrew Plummer.
+
+- Issue #26644: Raise ValueError rather than SystemError when a negative
+ length is passed to SSLSocket.recv() or read().
+
+- Issue #23804: Fix SSL recv(0) and read(0) methods to return zero bytes
+ instead of up to 1024.
+
+- Issue #26616: Fixed a bug in datetime.astimezone() method.
+
+- Issue #21925: :func:`warnings.formatwarning` now catches exceptions on
+ ``linecache.getline(...)`` to be able to log :exc:`ResourceWarning` emitted
+ late during the Python shutdown process.
+
+- Issue #24266: Ctrl+C during Readline history search now cancels the search
+ mode when compiled with Readline 7.
+
+- Issue #26560: Avoid potential ValueError in BaseHandler.start_response.
+ Initial patch by Peter Inglesby.
+
+- Issue #26313: ssl.py _load_windows_store_certs fails if windows cert store
+ is empty. Patch by Baji.
+
+- Issue #26569: Fix :func:`pyclbr.readmodule` and :func:`pyclbr.readmodule_ex`
+ to support importing packages.
+
+- Issue #26499: Account for remaining Content-Length in
+ HTTPResponse.readline() and read1(). Based on patch by Silent Ghost.
+ Also document that HTTPResponse now supports these methods.
+
+- Issue #25320: Handle sockets in directories unittest discovery is scanning.
+ Patch from Victor van den Elzen.
+
+- Issue #16181: cookiejar.http2time() now returns None if year is higher than
+ datetime.MAXYEAR.
+
+- Issue #26513: Fixes platform module detection of Windows Server
+
+- Issue #23718: Fixed parsing time in week 0 before Jan 1. Original patch by
+ Tamás Bence Gedai.
+
+- Issue #20589: Invoking Path.owner() and Path.group() on Windows now raise
+ NotImplementedError instead of ImportError.
+
+- Issue #26177: Fixed the keys() method for Canvas and Scrollbar widgets.
+
+- Issue #15068: Got rid of excessive buffering in the fileinput module.
+ The bufsize parameter is no longer used.
+
+- Issue #2202: Fix UnboundLocalError in
+ AbstractDigestAuthHandler.get_algorithm_impls. Initial patch by Mathieu Dupuy.
+
+- Issue #25718: Fixed pickling and copying the accumulate() iterator with
+ total is None.
+
+- Issue #26475: Fixed debugging output for regular expressions with the (?x)
+ flag.
+
+- Issue #26457: Fixed the subnets() methods in IP network classes for the case
+ when resulting prefix length is equal to maximal prefix length.
+ Based on patch by Xiang Zhang.
+
+- Issue #26385: Remove the file if the internal open() call in
+ NamedTemporaryFile() fails. Patch by Silent Ghost.
+
+- Issue #26402: Fix XML-RPC client to retry when the server shuts down a
+ persistent connection. This was a regression related to the new
+ http.client.RemoteDisconnected exception in 3.5.0a4.
+
+- Issue #25913: Leading ``<~`` is optional now in base64.a85decode() with
+ adobe=True. Patch by Swati Jaiswal.
+
+- Issue #26186: Remove an invalid type check in importlib.util.LazyLoader.
+
+- Issue #26367: importlib.__import__() raises SystemError like
+ builtins.__import__() when ``level`` is specified but without an accompanying
+ package specified.
+
+- Issue #26309: In the "socketserver" module, shut down the request (closing
+ the connected socket) when verify_request() returns false. Patch by Aviv
+ Palivoda.
+
+- Issue #25939: On Windows open the cert store readonly in ssl.enum_certificates.
+
+- Issue #25995: os.walk() no longer uses FDs proportional to the tree depth.
+
+- Issue #26117: The os.scandir() iterator now closes file descriptor not only
+ when the iteration is finished, but when it was failed with error.
+
+- Issue #25911: Restored support of bytes paths in os.walk() on Windows.
+
+- Issue #26045: Add UTF-8 suggestion to error message when posting a
+ non-Latin-1 string with http.client.
+
+- Issue #12923: Reset FancyURLopener's redirect counter even if there is an
+ exception. Based on patches by Brian Brazil and Daniel Rocco.
+
+- Issue #25945: Fixed a crash when unpickle the functools.partial object with
+ wrong state. Fixed a leak in failed functools.partial constructor.
+ "args" and "keywords" attributes of functools.partial have now always types
+ tuple and dict correspondingly.
+
+- Issue #26202: copy.deepcopy() now correctly copies range() objects with
+ non-atomic attributes.
+
+- Issue #23076: Path.glob() now raises a ValueError if it's called with an
+ invalid pattern. Patch by Thomas Nyberg.
+
+- Issue #19883: Fixed possible integer overflows in zipimport.
+
+- Issue #26227: On Windows, getnameinfo(), gethostbyaddr() and
+ gethostbyname_ex() functions of the socket module now decode the hostname
+ from the ANSI code page rather than UTF-8.
+
+- Issue #26147: xmlrpc now works with strings not encodable with used
+ non-UTF-8 encoding.
+
+- Issue #25935: Garbage collector now breaks reference loops with OrderedDict.
+
+- Issue #16620: Fixed AttributeError in msilib.Directory.glob().
+
+- Issue #26013: Added compatibility with broken protocol 2 pickles created
+ in old Python 3 versions (3.4.3 and lower).
+
+- Issue #25850: Use cross-compilation by default for 64-bit Windows.
+
+- Issue #17633: Improve zipimport's support for namespace packages.
+
+- Issue #24705: Fix sysconfig._parse_makefile not expanding ${} vars
+ appearing before $() vars.
+
+- Issue #22138: Fix mock.patch behavior when patching descriptors. Restore
+ original values after patching. Patch contributed by Sean McCully.
+
+- Issue #25672: In the ssl module, enable the SSL_MODE_RELEASE_BUFFERS mode
+ option if it is safe to do so.
+
+- Issue #26012: Don't traverse into symlinks for ** pattern in
+ pathlib.Path.[r]glob().
+
+- Issue #24120: Ignore PermissionError when traversing a tree with
+ pathlib.Path.[r]glob(). Patch by Ulrich Petri.
+
+- Issue #25447: fileinput now uses sys.stdin as-is if it does not have a
+ buffer attribute (restores backward compatibility).
+
+- Issue #25447: Copying the lru_cache() wrapper object now always works,
+ independedly from the type of the wrapped object (by returning the original
+ object unchanged).
+
+- Issue #24103: Fixed possible use after free in ElementTree.XMLPullParser.
+
+- Issue #25860: os.fwalk() no longer skips remaining directories when error
+ occurs. Original patch by Samson Lee.
+
+- Issue #25914: Fixed and simplified OrderedDict.__sizeof__.
+
+- Issue #25902: Fixed various refcount issues in ElementTree iteration.
+
+- Issue #25717: Restore the previous behaviour of tolerating most fstat()
+ errors when opening files. This was a regression in 3.5a1, and stopped
+ anonymous temporary files from working in special cases.
+
+- Issue #24903: Fix regression in number of arguments compileall accepts when
+ '-d' is specified. The check on the number of arguments has been dropped
+ completely as it never worked correctly anyway.
+
+- Issue #25764: In the subprocess module, preserve any exception caused by
+ fork() failure when preexec_fn is used.
+
+- Issue #6478: _strptime's regexp cache now is reset after changing timezone
+ with time.tzset().
+
+- Issue #14285: When executing a package with the "python -m package" option,
+ and package initialization fails, a proper traceback is now reported. The
+ "runpy" module now lets exceptions from package initialization pass back to
+ the caller, rather than raising ImportError.
+
+- Issue #19771: Also in runpy and the "-m" option, omit the irrelevant
+ message ". . . is a package and cannot be directly executed" if the package
+ could not even be initialized (e.g. due to a bad ``*.pyc`` file).
+
+- Issue #25177: Fixed problem with the mean of very small and very large
+ numbers. As a side effect, statistics.mean and statistics.variance should
+ be significantly faster.
+
+- Issue #25718: Fixed copying object with state with boolean value is false.
+
+- Issue #10131: Fixed deep copying of minidom documents. Based on patch
+ by Marian Ganisin.
+
+- Issue #25725: Fixed a reference leak in pickle.loads() when unpickling
+ invalid data including tuple instructions.
+
+- Issue #25663: In the Readline completer, avoid listing duplicate global
+ names, and search the global namespace before searching builtins.
+
+- Issue #25688: Fixed file leak in ElementTree.iterparse() raising an error.
+
+- Issue #23914: Fixed SystemError raised by unpickler on broken pickle data.
+
+- Issue #25691: Fixed crash on deleting ElementTree.Element attributes.
+
+- Issue #25624: ZipFile now always writes a ZIP_STORED header for directory
+ entries. Patch by Dingyuan Wang.
+
+- Skip getaddrinfo if host is already resolved.
+ Patch by A. Jesse Jiryu Davis.
+
+- Issue #26050: Add asyncio.StreamReader.readuntil() method.
+ Patch by Марк Коренберг.
+
+- Issue #25924: Avoid unnecessary serialization of getaddrinfo(3) calls on
+ OS X versions 10.5 or higher. Original patch by A. Jesse Jiryu Davis.
+
+- Issue #26406: Avoid unnecessary serialization of getaddrinfo(3) calls on
+ current versions of OpenBSD and NetBSD. Patch by A. Jesse Jiryu Davis.
+
+- Issue #26848: Fix asyncio/subprocess.communicate() to handle empty input.
+ Patch by Jack O'Connor.
+
+- Issue #27040: Add loop.get_exception_handler method
+
+- Issue #27041: asyncio: Add loop.create_future method
+
+- Issue #27223: asyncio: Fix _read_ready and _write_ready to respect
+ _conn_lost.
+ Patch by Łukasz Langa.
+
+- Issue #22970: asyncio: Fix inconsistency cancelling Condition.wait.
+ Patch by David Coles.
+
+IDLE
+----
+
+- Issue #5124: Paste with text selected now replaces the selection on X11.
+ This matches how paste works on Windows, Mac, most modern Linux apps,
+ and ttk widgets. Original patch by Serhiy Storchaka.
+
+- Issue #24759: Make clear in idlelib.idle_test.__init__ that the directory
+ is a private implementation of test.test_idle and tool for maintainers.
+
+- Issue #27196: Stop 'ThemeChanged' warnings when running IDLE tests.
+ These persisted after other warnings were suppressed in #20567.
+ Apply Serhiy Storchaka's update_idletasks solution to four test files.
+ Record this additional advice in idle_test/README.txt
+
+- Issue #20567: Revise idle_test/README.txt with advice about avoiding
+ tk warning messages from tests. Apply advice to several IDLE tests.
+
+- Issue #27117: Make colorizer htest and turtledemo work with dark themes.
+ Move code for configuring text widget colors to a new function.
+
+- Issue #26673: When tk reports font size as 0, change to size 10.
+ Such fonts on Linux prevented the configuration dialog from opening.
+
+- Issue #21939: Add test for IDLE's percolator.
+ Original patch by Saimadhav Heblikar.
+
+- Issue #21676: Add test for IDLE's replace dialog.
+ Original patch by Saimadhav Heblikar.
+
+- Issue #18410: Add test for IDLE's search dialog.
+ Original patch by Westley Martínez.
+
+- Issue #21703: Add test for IDLE's undo delegator.
+ Original patch by Saimadhav Heblikar .
+
+- Issue #27044: Add ConfigDialog.remove_var_callbacks to stop memory leaks.
+
+- Issue #23977: Add more asserts to test_delegator.
+
+- Issue #20640: Add tests for idlelib.configHelpSourceEdit.
+ Patch by Saimadhav Heblikar.
+
+- In the 'IDLE-console differences' section of the IDLE doc, clarify
+ how running with IDLE affects sys.modules and the standard streams.
+
+- Issue #25507: fix incorrect change in IOBinding that prevented printing.
+ Augment IOBinding htest to include all major IOBinding functions.
+
+- Issue #25905: Revert unwanted conversion of ' to ’ RIGHT SINGLE QUOTATION
+ MARK in README.txt and open this and NEWS.txt with 'ascii'.
+ Re-encode CREDITS.txt to utf-8 and open it with 'utf-8'.
+
+Documentation
+-------------
+
+- Issue #24136: Document the new PEP 448 unpacking syntax of 3.5.
+
+- Issue #26736: Used HTTPS for external links in the documentation if possible.
+
+- Issue #6953: Rework the Readline module documentation to group related
+ functions together, and add more details such as what underlying Readline
+ functions and variables are accessed.
+
+- Issue #23606: Adds note to ctypes documentation regarding cdll.msvcrt.
+
+- Issue #25500: Fix documentation to not claim that __import__ is searched for
+ in the global scope.
+
+- Issue #26014: Update 3.x packaging documentation:
+ * "See also" links to the new docs are now provided in the legacy pages
+ * links to setuptools documentation have been updated
+
+Tests
+-----
+
+- Issue #21916: Added tests for the turtle module. Patch by ingrid,
+ Gregory Loyse and Jelle Zijlstra.
+
+- Issue #26523: The multiprocessing thread pool (multiprocessing.dummy.Pool)
+ was untested.
+
+- Issue #26015: Added new tests for pickling iterators of mutable sequences.
+
+- Issue #26325: Added test.support.check_no_resource_warning() to check that
+ no ResourceWarning is emitted.
+
+- Issue #25940: Changed test_ssl to use self-signed.pythontest.net. This
+ avoids relying on svn.python.org, which recently changed root certificate.
+
+- Issue #25616: Tests for OrderedDict are extracted from test_collections
+ into separate file test_ordered_dict.
+
+- Issue #26583: Skip test_timestamp_overflow in test_import if bytecode
+ files cannot be written.
+
+Build
+-----
+
+- Issue #26884: Fix linking extension modules for cross builds.
+ Patch by Xavier de Gaye.
+
+- Issue #22359: Disable the rules for running _freeze_importlib and pgen when
+ cross-compiling. The output of these programs is normally saved with the
+ source code anyway, and is still regenerated when doing a native build.
+ Patch by Xavier de Gaye.
+
+- Issue #27229: Fix the cross-compiling pgen rule for in-tree builds. Patch
+ by Xavier de Gaye.
+
+- Issue #21668: Link audioop, _datetime, _ctypes_test modules to libm,
+ except on Mac OS X. Patch written by Xavier de Gaye.
+
+- Issue #25702: A --with-lto configure option has been added that will
+ enable link time optimizations at build time during a make profile-opt.
+ Some compilers and toolchains are known to not produce stable code when
+ using LTO, be sure to test things thoroughly before relying on it.
+ It can provide a few % speed up over profile-opt alone.
+
+- Issue #26624: Adds validation of ucrtbase[d].dll version with warning
+ for old versions.
+
+- Issue #17603: Avoid error about nonexistant fileblocks.o file by using a
+ lower-level check for st_blocks in struct stat.
+
+- Issue #26079: Fixing the build output folder for tix-8.4.3.6. Patch by
+ Bjoern Thiel.
+
+- Issue #26465: Update Windows builds to use OpenSSL 1.0.2g.
+
+- Issue #24421: Compile Modules/_math.c once, before building extensions.
+ Previously it could fail to compile properly if the math and cmath builds
+ were concurrent.
+
+- Issue #25348: Added ``--pgo`` and ``--pgo-job`` arguments to
+ ``PCbuild\build.bat`` for building with Profile-Guided Optimization. The
+ old ``PCbuild\build_pgo.bat`` script is now deprecated, and simply calls
+ ``PCbuild\build.bat --pgo %*``.
+
+- Issue #25827: Add support for building with ICC to ``configure``, including
+ a new ``--with-icc`` flag.
+
+- Issue #25696: Fix installation of Python on UNIX with make -j9.
+
+- Issue #26930: Update OS X 10.5+ 32-bit-only installer to build
+ and link with OpenSSL 1.0.2h.
+
+- Issue #26268: Update Windows builds to use OpenSSL 1.0.2f.
+
+- Issue #25136: Support Apple Xcode 7's new textual SDK stub libraries.
+
+- Issue #24324: Do not enable unreachable code warnings when using
+ gcc as the option does not work correctly in older versions of gcc
+ and has been silently removed as of gcc-4.5.
+
+Windows
+-------
+
+- Issue #27053: Updates make_zip.py to correctly generate library ZIP file.
+
+- Issue #26268: Update the prepare_ssl.py script to handle OpenSSL releases
+ that don't include the contents of the include directory (that is, 1.0.2e
+ and later).
+
+- Issue #26071: bdist_wininst created binaries fail to start and find
+ 32bit Python
+
+- Issue #26073: Update the list of magic numbers in launcher
+
+- Issue #26065: Excludes venv from library when generating embeddable
+ distro.
+
+Tools/Demos
+-----------
+
+- Issue #26799: Fix python-gdb.py: don't get C types once when the Python code
+ is loaded, but get C types on demand. The C types can change if
+ python-gdb.py is loaded before the Python executable. Patch written by Thomas
+ Ilsche.
+
+- Issue #26271: Fix the Freeze tool to properly use flags passed through
+ configure. Patch by Daniel Shaulov.
+
+- Issue #26489: Add dictionary unpacking support to Tools/parser/unparse.py.
+ Patch by Guo Ci Teo.
+
+- Issue #26316: Fix variable name typo in Argument Clinic.
+
+Misc
+----
+
+- Issue #17500, and https://github.com/python/pythondotorg/issues/945: Remove
+ unused and outdated icons.
+
+
What's New in Python 3.5.1 final?
=================================
- Issue #25111: Fixed comparison of traceback.FrameSummary.
-- Issue #25262. Added support for BINBYTES8 opcode in Python implementation of
+- Issue #25262: Added support for BINBYTES8 opcode in Python implementation of
unpickler. Highest 32 bits of 64-bit size for BINUNICODE8 and BINBYTES8
opcodes no longer silently ignored on 32-bit platforms in C implementation.
IDLE
----
-- Issue 15348: Stop the debugger engine (normally in a user process)
+- Issue #15348: Stop the debugger engine (normally in a user process)
before closing the debugger window (running in the IDLE process).
This prevents the RuntimeErrors that were being caught and ignored.
Consistently use the revised idleConf.CurrentTheme everywhere in idlelib.
- Issue #24782: Extension configuration is now a tab in the IDLE Preferences
- dialog rather than a separate dialog. The former tabs are now a sorted
+ dialog rather than a separate dialog. The former tabs are now a sorted
list. Patch by Mark Roseman.
- Issue #22726: Re-activate the config dialog help button with some content
Documentation
-------------
+- Issue #22558: Add remaining doc links to source code for Python-coded modules.
+ Patch by Yoni Lavi.
+
- Issue #12067: Rewrite Comparisons section in the Expressions chapter of the
language reference. Some of the details of comparing mixed types were
incorrect or ambiguous. NotImplemented is only relevant at a lower level
- Issue #24407: Fix crash when dict is mutated while being updated.
- Issue #24619: New approach for tokenizing async/await. As a consequence,
- is is now possible to have one-line 'async def foo(): await ..' functions.
+ it is now possible to have one-line 'async def foo(): await ..' functions.
- Issue #24687: Plug refleak on SyntaxError in function parameters
annotations.
Build
-----
-- Issue #23817: FreeBSD now uses "1.0" the the SOVERSION as other operating
+- Issue #23817: FreeBSD now uses "1.0" in the SOVERSION as other operating
systems, instead of just "1".
- Issue #23501: Argument Clinic now generates code into separate files by default.
and ASCII letter now raise a deprecation warning and will be forbidden in
Python 3.6.
-- Issue #23671: string.Template now allows to specify the "self" parameter as
- keyword argument. string.Formatter now allows to specify the "self" and
+- Issue #23671: string.Template now allows specifying the "self" parameter as
+ a keyword argument. string.Formatter now allows specifying the "self" and
the "format_string" parameters as keyword arguments.
- Issue #23502: The pprint module now supports mapping proxies.
- Issue #23704: collections.deque() objects now support methods for index(),
insert(), and copy(). This allows deques to be registered as a
- MutableSequence and it improves their substitutablity for lists.
+ MutableSequence and it improves their substitutability for lists.
- Issue #23715: :func:`signal.sigwaitinfo` and :func:`signal.sigtimedwait` are
now retried when interrupted by a signal not in the *sigset* parameter, if
static type in some cases.
- Issue #15859: PyUnicode_EncodeFSDefault(), PyUnicode_EncodeMBCS() and
- PyUnicode_EncodeCodePage() now raise an exception if the object is not an
+ PyUnicode_EncodeCodePage() now raise an exception if the object is not a
Unicode object. For PyUnicode_EncodeFSDefault(), it was already the case on
platforms other than Windows. Patch written by Campbell Barton.
is run with pythonw.exe.
- Issue #21775: shutil.copytree(): fix crash when copying to VFAT. An exception
- handler assumed that that OSError objects always have a 'winerror' attribute.
+ handler assumed that OSError objects always have a 'winerror' attribute.
That is not the case, so the exception handler itself raised AttributeError
when run on Linux (and, presumably, any other non-Windows OS).
Patch by Greg Ward.
- Issue #21971: Update turtledemo doc and add module to the index.
-- Issue #21032. Fixed socket leak if HTTPConnection.getresponse() fails.
+- Issue #21032: Fixed socket leak if HTTPConnection.getresponse() fails.
Original patch by Martin Panter.
- Issue #22407: Deprecated the use of re.LOCALE flag with str patterns or
- Issue #22247: Add NNTPError to nntplib.__all__.
- Issue #22366: urllib.request.urlopen will accept a context object
- (SSLContext) as an argument which will then used be for HTTPS connection.
+ (SSLContext) as an argument which will then be used for HTTPS connection.
Patch by Alex Gaynor.
- Issue #4180: The warnings registries are now reset when the filters
- Issue #22085: Dropped support of Tk 8.3 in Tkinter.
- Issue #21580: Now Tkinter correctly handles bytes arguments passed to Tk.
- In particular this allows to initialize images from binary data.
+ In particular this allows initializing images from binary data.
- Issue #22003: When initialized from a bytes object, io.BytesIO() now
defers making a copy until it is mutated, improving performance and
- Issue #21711: support for "site-python" directories has now been removed
from the site module (it was deprecated in 3.4).
-- Issue #17552: new socket.sendfile() method allowing to send a file over a
+- Issue #17552: new socket.sendfile() method allowing a file to be sent over a
socket by using high-performance os.sendfile() on UNIX.
Patch by Giampaolo Rodola'.
- Issue #21226: Set up modules properly in PyImport_ExecCodeModuleObject
(and friends).
-- Issue #21398: Fix an unicode error in the pydoc pager when the documentation
+- Issue #21398: Fix a unicode error in the pydoc pager when the documentation
contains characters not encodable to the stdout encoding.
- Issue #16531: ipaddress.IPv4Network and ipaddress.IPv6Network now accept
- Issue #20968: unittest.mock.MagicMock now supports division.
Patch by Johannes Baiter.
-- Fix arbitrary memory access in JSONDecoder.raw_decode with a negative second
- parameter. Bug reported by Guido Vranken.
+- Issue #21529 (CVE-2014-4616): Fix arbitrary memory access in
+ JSONDecoder.raw_decode with a negative second parameter. Bug reported by Guido
+ Vranken.
- Issue #21169: getpass now handles non-ascii characters that the
input stream encoding cannot encode by re-encoding using the
- Issue #21000: Improve the command-line interface of json.tool.
- Issue #20995: Enhance default ciphers used by the ssl module to enable
- better security an prioritize perfect forward secrecy.
+ better security and prioritize perfect forward secrecy.
- Issue #20884: Don't assume that __file__ is defined on importlib.__init__.
move version to end.
- Issue #14105: Idle debugger breakpoints no longer disappear
- when inseting or deleting lines.
+ when inserting or deleting lines.
- Issue #17172: Turtledemo can now be run from Idle.
Currently, the entry is on the Help menu, but it may move to Run.
- Issue #19448: Add private API to SSL module to lookup ASN.1 objects by OID,
NID, short name and long name.
-- Issue #19282: dbm.open now supports the context management protocol. (Inital
- patch by Claudiu Popa)
+- Issue #19282: dbm.open now supports the context management protocol.
+ (Initial patch by Claudiu Popa)
- Issue #8311: Added support for writing any bytes-like objects in the aifc,
sunau, and wave modules.
- Issue #19227: Remove pthread_atfork() handler. The handler was added to
solve #18747 but has caused issues.
-- Issue #19420: Fix reference leak in module initalization code of
+- Issue #19420: Fix reference leak in module initialization code of
_hashopenssl.c
- Issue #19329: Optimized compiling charsets in regular expressions.
- Issue #17173: Remove uses of locale-dependent C functions (isalpha() etc.)
in the interpreter.
-- Issue #17137: When an Unicode string is resized, the internal wide character
+- Issue #17137: When a Unicode string is resized, the internal wide character
string (wstr) format is now cleared.
- Issue #17043: The unicode-internal decoder no longer read past the end of
Thomas Barlow.
- Issue #17358: Modules loaded by imp.load_source() and load_compiled() (and by
- extention load_module()) now have a better chance of working when reloaded.
+ extension load_module()) now have a better chance of working when reloaded.
- Issue #17804: New function ``struct.iter_unpack`` allows for streaming
struct unpacking.
error message has been removed. Patch by Ram Rachum.
- Issue #18080: When building a C extension module on OS X, if the compiler
- is overriden with the CC environment variable, use the new compiler as
- the default for linking if LDSHARED is not also overriden. This restores
+ is overridden with the CC environment variable, use the new compiler as
+ the default for linking if LDSHARED is not also overridden. This restores
Distutils behavior introduced in 3.2.3 and inadvertently dropped in 3.3.0.
- Issue #18113: Fixed a refcount leak in the curses.panel module's
symlinks on POSIX platforms.
- Issue #13773: sqlite3.connect() gets a new `uri` parameter to pass the
- filename as a URI, allowing to pass custom options.
+ filename as a URI, allowing custom options to be passed.
- Issue #16564: Fixed regression relative to Python2 in the operation of
email.encoders.encode_noop when used with binary data.
internal XML encoding is not UTF-8 or US-ASCII. It also now accepts bytes
and strings larger than 2 GiB.
-- Issue #6083: Fix multiple segmentation faults occured when PyArg_ParseTuple
+- Issue #6083: Fix multiple segmentation faults occurred when PyArg_ParseTuple
parses nested mutating sequence.
- Issue #5289: Fix ctypes.util.find_library on Solaris.
- Issue #7719: Make distutils ignore ``.nfs*`` files instead of choking later
on. Initial patch by SilentGhost and Jeff Ramnani.
-- Issue #13120: Allow to call pdb.set_trace() from thread.
+- Issue #13120: Allow calling pdb.set_trace() from thread.
Patch by Ilya Sandler.
- Issue #16585: Make CJK encoders support error handlers that return bytes per
- Issue #16284: Prevent keeping unnecessary references to worker functions
in concurrent.futures ThreadPoolExecutor.
-- Issue #16230: Fix a crash in select.select() when one the lists changes
+- Issue #16230: Fix a crash in select.select() when one of the lists changes
size while iterated on. Patch by Serhiy Storchaka.
- Issue #16228: Fix a crash in the json module where a list changes size
- Issue #16245: Fix the value of a few entities in html.entities.html5.
-- Issue #16301: Fix the localhost verification in urllib/request.py for file://
+- Issue #16301: Fix the localhost verification in urllib/request.py for ``file://``
urls.
- Issue #16250: Fix the invocations of URLError which had misplaced filename
- Issue #16176: Properly identify Windows 8 via platform.platform()
- Issue #16088: BaseHTTPRequestHandler's send_error method includes a
- Content-Length header in it's response now. Patch by Antoine Pitrou.
+ Content-Length header in its response now. Patch by Antoine Pitrou.
- Issue #16114: The subprocess module no longer provides a misleading error
message stating that args[0] did not exist when either the cwd or executable
-.TH PYTHON "1" "$Date$"
+.TH PYTHON "1"
.\" To view this file while editing, run it through groff:
.\" groff -Tascii -man python.man | less
.TP
.B \-I
Run Python in isolated mode. This also implies \fB\-E\fP and \fB\-s\fP. In
-isolated mode sys.path contains neither the script’s directory nor the user’s
+isolated mode sys.path contains neither the script's directory nor the user's
site-packages directory. All PYTHON* environment variables are ignored, too.
Further restrictions may be imposed to prevent the user from injecting
malicious code.
if (d->eof) {
d->needs_input = 0;
if (d->bzs_avail_in_real > 0) {
- Py_CLEAR(d->unused_data);
- d->unused_data = PyBytes_FromStringAndSize(
- bzs->next_in, d->bzs_avail_in_real);
+ Py_XSETREF(d->unused_data,
+ PyBytes_FromStringAndSize(bzs->next_in, d->bzs_avail_in_real));
if (d->unused_data == NULL)
goto error;
}
/* collections module implementation of a deque() datatype
Written and maintained by Raymond D. Hettinger <python@rcn.com>
- Copyright (c) 2004-2015 Python Software Foundation.
- All rights reserved.
*/
/* The block length may be set to any number over 1. Larger numbers
if (!PyArg_ParseTuple(args, "nO:insert", &index, &value))
return NULL;
+ if (deque->maxlen == Py_SIZE(deque)) {
+ PyErr_SetString(PyExc_IndexError, "deque already at its maximum size");
+ return NULL;
+ }
if (index >= n)
return deque_append(deque, value);
if (index <= -n || index == 0)
Py_ssize_t res;
Py_ssize_t blocks;
- res = sizeof(dequeobject);
+ res = _PyObject_SIZE(Py_TYPE(deque));
blocks = (deque->leftindex + Py_SIZE(deque) + BLOCKLEN - 1) / BLOCKLEN;
assert(deque->leftindex + Py_SIZE(deque) - 1 ==
(blocks - 1) * BLOCKLEN + deque->rightindex);
else {
if (PyUnicode_READY(src) == -1)
return -1;
- Py_XDECREF(*target);
Py_INCREF(src);
- *target = src;
+ Py_XSETREF(*target, src);
}
}
return 0;
break;
case QUOTE_IN_QUOTED_FIELD:
- /* doublequote - seen a quote in an quoted field */
+ /* doublequote - seen a quote in a quoted field */
if (dialect->quoting != QUOTE_NONE &&
c == dialect->quotechar) {
/* save "" as " */
static int
parse_reset(ReaderObj *self)
{
- Py_XDECREF(self->fields);
- self->fields = PyList_New(0);
+ Py_XSETREF(self->fields, PyList_New(0));
if (self->fields == NULL)
return -1;
self->field_len = 0;
from_param(obj)
- typecheck and convert a Python object into a C function call parameter
- the result may be an instance of the type, or an integer or tuple
+ The result may be an instance of the type, or an integer or tuple
(typecode, value[, obj])
instance methods/properties
Py_DECREF((PyObject *)dict);
return NULL;
}
- Py_DECREF(result->tp_dict);
- result->tp_dict = (PyObject *)dict;
+ Py_SETREF(result->tp_dict, (PyObject *)dict);
dict->format = _ctypes_alloc_format_string(NULL, "B");
if (dict->format == NULL) {
Py_DECREF(result);
return -1;
}
Py_INCREF(proto);
- Py_XDECREF(stgdict->proto);
- stgdict->proto = proto;
+ Py_XSETREF(stgdict->proto, proto);
return 0;
}
Py_DECREF((PyObject *)stgdict);
return NULL;
}
- Py_DECREF(result->tp_dict);
- result->tp_dict = (PyObject *)stgdict;
+ Py_SETREF(result->tp_dict, (PyObject *)stgdict);
return (PyObject *)result;
}
/* replace the class dict by our updated spam dict */
if (-1 == PyDict_Update((PyObject *)stgdict, result->tp_dict))
goto error;
- Py_DECREF(result->tp_dict);
- result->tp_dict = (PyObject *)stgdict; /* steal the reference */
+ Py_SETREF(result->tp_dict, (PyObject *)stgdict); /* steal the reference */
stgdict = NULL;
/* Special case for character arrays.
Py_DECREF((PyObject *)stgdict);
return NULL;
}
- Py_DECREF(result->tp_dict);
- result->tp_dict = (PyObject *)stgdict;
+ Py_SETREF(result->tp_dict, (PyObject *)stgdict);
return (PyObject *)result;
}
Py_DECREF((PyObject *)stgdict);
return NULL;
}
- Py_DECREF(result->tp_dict);
- result->tp_dict = (PyObject *)stgdict;
+ Py_SETREF(result->tp_dict, (PyObject *)stgdict);
/* Install from_param class methods in ctypes base classes.
Overrides the PyCSimpleType_from_param generic method.
Py_DECREF((PyObject *)stgdict);
return NULL;
}
- Py_DECREF(result->tp_dict);
- result->tp_dict = (PyObject *)stgdict;
+ Py_SETREF(result->tp_dict, (PyObject *)stgdict);
if (-1 == make_funcptrtype_dict(stgdict)) {
Py_DECREF(result);
return -1;
}
if (ob->b_objects == NULL || !PyDict_CheckExact(ob->b_objects)) {
- Py_XDECREF(ob->b_objects);
- ob->b_objects = keep; /* refcount consumed */
+ Py_XSETREF(ob->b_objects, keep); /* refcount consumed */
return 0;
}
key = unique_key(target, index);
"the errcheck attribute must be callable");
return -1;
}
- Py_XDECREF(self->errcheck);
Py_XINCREF(ob);
- self->errcheck = ob;
+ Py_XSETREF(self->errcheck, ob);
return 0;
}
"restype must be a type, a callable, or None");
return -1;
}
- Py_XDECREF(self->checker);
- Py_XDECREF(self->restype);
Py_INCREF(ob);
- self->restype = ob;
- self->checker = PyObject_GetAttrString(ob, "_check_retval_");
+ Py_XSETREF(self->restype, ob);
+ Py_XSETREF(self->checker, PyObject_GetAttrString(ob, "_check_retval_"));
if (self->checker == NULL)
PyErr_Clear();
return 0;
converters = converters_from_argtypes(ob);
if (!converters)
return -1;
- Py_XDECREF(self->converters);
- self->converters = converters;
- Py_XDECREF(self->argtypes);
+ Py_XSETREF(self->converters, converters);
Py_INCREF(ob);
- self->argtypes = ob;
+ Py_XSETREF(self->argtypes, ob);
}
return 0;
}
return NULL;
}
- /* XXX XXX This would allow to pass additional options. For COM
+ /* XXX XXX This would allow passing additional options. For COM
method *implementations*, we would probably want different
behaviour than in 'normal' callback functions: return a HRESULT if
an exception occurs in the callback, and print the traceback not
return NULL;
}
/* there should be more checks? No, in Python */
- /* First arg is an pointer to an interface instance */
+ /* First arg is a pointer to an interface instance */
if (!this->b_ptr || *(void **)this->b_ptr == NULL) {
PyErr_SetString(PyExc_ValueError,
"NULL COM pointer access");
return -1;
bself = (PyBaseExceptionObject *)self;
- Py_DECREF(bself->args);
- bself->args = args;
- Py_INCREF(bself->args);
+ Py_INCREF(args);
+ Py_SETREF(bself->args, args);
return 0;
}
Py_INCREF(value);
return value;
}
- if (PyLong_Check(value) || PyLong_Check(value)) {
+ if (PyLong_Check(value)) {
#if SIZEOF_VOID_P == SIZEOF_LONG_LONG
*(wchar_t **)ptr = (wchar_t *)PyLong_AsUnsignedLongLongMask(value);
#else
_RET(value);
}
- if (!PyLong_Check(value) && !PyLong_Check(value)) {
+ if (!PyLong_Check(value)) {
PyErr_SetString(PyExc_TypeError,
"cannot be converted to pointer");
return NULL;
-/*****************************************************************
- This file should be kept compatible with Python 2.3, see PEP 291.
- *****************************************************************/
-
#ifndef _CTYPES_DLFCN_H_
#define _CTYPES_DLFCN_H_
# If we don't find anything, use the default library path according
# to the aix ld manual.
# Store the results from the different compilers for each TAGNAME.
-# Allow to override them for all tags through lt_cv_aix_libpath.
+# Allow overriding them for all tags through lt_cv_aix_libpath.
m4_defun([_LT_SYS_MODULE_PATH_AIX],
[m4_require([_LT_DECL_SED])dnl
if test set = "${lt_cv_aix_libpath+set}"; then
static void
PyCursesPanel_Dealloc(PyCursesPanelObject *po)
{
+ PyObject *obj = (PyObject *) panel_userptr(po->pan);
+ if (obj) {
+ (void)set_panel_userptr(po->pan, NULL);
+ Py_DECREF(obj);
+ }
(void)del_panel(po->pan);
if (po->wo != NULL) {
Py_DECREF(po->wo);
PyErr_SetString(_curses_panelstate_global->PyCursesError, "replace_panel() returned ERR");
return NULL;
}
- Py_DECREF(po->wo);
- po->wo = temp;
- Py_INCREF(po->wo);
+ Py_INCREF(temp);
+ Py_SETREF(po->wo, temp);
Py_INCREF(Py_None);
return Py_None;
}
d = PyModule_GetDict(m);
/* Initialize object type */
- _curses_panelstate(m)->PyCursesPanel_Type = \
- PyType_FromSpec(&PyCursesPanel_Type_spec);
- if (_curses_panelstate(m)->PyCursesPanel_Type == NULL)
+ v = PyType_FromSpec(&PyCursesPanel_Type_spec);
+ if (v == NULL)
goto fail;
+ ((PyTypeObject *)v)->tp_new = NULL;
+ _curses_panelstate(m)->PyCursesPanel_Type = v;
import_curses();
if (PyErr_Occurred())
return _days_in_month[month];
}
-/* year, month -> number of days in year preceeding first day of month */
+/* year, month -> number of days in year preceding first day of month */
static int
days_before_month(int year, int month)
{
minutes = divmod(seconds, 60, &seconds);
hours = divmod(minutes, 60, &minutes);
assert(seconds == 0);
- /* XXX ignore sub-minute data, curently not allowed. */
+ /* XXX ignore sub-minute data, currently not allowed. */
PyOS_snprintf(buf, buflen, "%c%02d%s%02d", sign, hours, sep, minutes);
return 0;
Py_DECREF(offset);
minutes = divmod(seconds, 60, &seconds);
hours = divmod(minutes, 60, &minutes);
- /* XXX ignore sub-minute data, curently not allowed. */
+ /* XXX ignore sub-minute data, currently not allowed. */
assert(seconds == 0);
return PyUnicode_FromFormat("UTC%c%02d:%02d", sign, hours, minutes);
}
PyObject *nameo = NULL;
const char *zone = NULL;
- delta = datetime_subtract((PyObject *)utc_time, PyDateTime_Epoch);
+ delta = new_delta(ymd_to_ord(GET_YEAR(utc_time), GET_MONTH(utc_time),
+ GET_DAY(utc_time)) - 719163,
+ 60 * (60 * DATE_GET_HOUR(utc_time) +
+ DATE_GET_MINUTE(utc_time)) +
+ DATE_GET_SECOND(utc_time),
+ 0, 0);
if (delta == NULL)
return NULL;
one_second = new_delta(0, 1, 0, 0);
{
Py_ssize_t res;
- res = sizeof(PyDecObject);
+ res = _PyObject_SIZE(Py_TYPE(v));
if (mpd_isdynamic_data(MPD(v))) {
res += MPD(v)->alloc * sizeof(mpd_uint_t);
}
_elementtree_Element___sizeof___impl(ElementObject *self)
/*[clinic end generated code: output=bf73867721008000 input=70f4b323d55a17c1]*/
{
- Py_ssize_t result = sizeof(ElementObject);
+ Py_ssize_t result = _PyObject_SIZE(Py_TYPE(self));
if (self->extra) {
result += sizeof(ElementObjectExtra);
if (self->extra->children != self->extra->_children)
return NULL;
}
- Py_CLEAR(self->tag);
- self->tag = tag;
- Py_INCREF(self->tag);
+ Py_INCREF(tag);
+ Py_XSETREF(self->tag, tag);
_clear_joined_ptr(&self->text);
self->text = text ? JOIN_SET(text, PyList_CheckExact(text)) : Py_None;
/* Stash attrib. */
if (attrib) {
- Py_CLEAR(self->extra->attrib);
- self->extra->attrib = attrib;
Py_INCREF(attrib);
+ Py_XSETREF(self->extra->attrib, attrib);
}
Py_RETURN_NONE;
_elementtree_Element_iter_impl(ElementObject *self, PyObject *tag)
/*[clinic end generated code: output=3f49f9a862941cc5 input=774d5b12e573aedd]*/
{
+ if (PyUnicode_Check(tag)) {
+ if (PyUnicode_READY(tag) < 0)
+ return NULL;
+ if (PyUnicode_GET_LENGTH(tag) == 1 && PyUnicode_READ_CHAR(tag, 0) == '*')
+ tag = Py_None;
+ }
+ else if (PyBytes_Check(tag)) {
+ if (PyBytes_GET_SIZE(tag) == 1 && *PyBytes_AS_STRING(tag) == '*')
+ tag = Py_None;
+ }
+
return create_elementiter(self, tag, 0);
}
Py_ssize_t start, stop, step, slicelen, newlen, cur, i;
PyObject* recycle = NULL;
- PyObject* seq = NULL;
+ PyObject* seq;
if (!self->extra) {
if (create_extra(self, NULL) < 0)
Py_XDECREF(recycle);
return 0;
}
- else {
- /* A new slice is actually being assigned */
- seq = PySequence_Fast(value, "");
- if (!seq) {
- PyErr_Format(
- PyExc_TypeError,
- "expected sequence, not \"%.200s\"", Py_TYPE(value)->tp_name
- );
- return -1;
- }
- newlen = PySequence_Size(seq);
+
+ /* A new slice is actually being assigned */
+ seq = PySequence_Fast(value, "");
+ if (!seq) {
+ PyErr_Format(
+ PyExc_TypeError,
+ "expected sequence, not \"%.200s\"", Py_TYPE(value)->tp_name
+ );
+ return -1;
}
+ newlen = PySequence_Size(seq);
if (step != 1 && newlen != slicelen)
{
+ Py_DECREF(seq);
PyErr_Format(PyExc_ValueError,
"attempt to assign sequence of size %zd "
"to extended slice of size %zd",
/* Resize before creating the recycle bin, to prevent refleaks. */
if (newlen > slicelen) {
if (element_resize(self, newlen - slicelen) < 0) {
- if (seq) {
- Py_DECREF(seq);
- }
+ Py_DECREF(seq);
return -1;
}
}
we're done modifying the element */
recycle = PyList_New(slicelen);
if (!recycle) {
- if (seq) {
- Py_DECREF(seq);
- }
+ Py_DECREF(seq);
return -1;
}
for (cur = start, i = 0; i < slicelen;
self->extra->length += newlen - slicelen;
- if (seq) {
- Py_DECREF(seq);
- }
+ Py_DECREF(seq);
/* discard the recycle bin, and everything in it */
Py_XDECREF(recycle);
element_setattro(ElementObject* self, PyObject* nameobj, PyObject* value)
{
char *name = "";
+
+ if (value == NULL) {
+ PyErr_SetString(PyExc_AttributeError,
+ "can't delete attribute");
+ return -1;
+ }
if (PyUnicode_Check(nameobj))
name = _PyUnicode_AsString(nameobj);
if (name == NULL)
return -1;
if (strcmp(name, "tag") == 0) {
- Py_DECREF(self->tag);
- self->tag = value;
- Py_INCREF(self->tag);
+ Py_INCREF(value);
+ Py_SETREF(self->tag, value);
} else if (strcmp(name, "text") == 0) {
Py_DECREF(JOIN_OBJ(self->text));
self->text = value;
if (create_extra(self, NULL) < 0)
return -1;
}
- Py_DECREF(self->extra->attrib);
- self->extra->attrib = value;
- Py_INCREF(self->extra->attrib);
+ Py_INCREF(value);
+ Py_SETREF(self->extra->attrib, value);
} else {
PyErr_SetString(PyExc_AttributeError,
"Can't set arbitrary attributes on Element");
ElementObject *cur_parent;
Py_ssize_t child_index;
int rc;
+ ElementObject *elem;
while (1) {
/* Handle the case reached in the beginning and end of iteration, where
PyErr_SetNone(PyExc_StopIteration);
return NULL;
} else {
+ elem = it->root_element;
it->parent_stack = parent_stack_push_new(it->parent_stack,
- it->root_element);
+ elem);
if (!it->parent_stack) {
PyErr_NoMemory();
return NULL;
}
+ Py_INCREF(elem);
it->root_done = 1;
rc = (it->sought_tag == Py_None);
if (!rc) {
- rc = PyObject_RichCompareBool(it->root_element->tag,
+ rc = PyObject_RichCompareBool(elem->tag,
it->sought_tag, Py_EQ);
- if (rc < 0)
+ if (rc < 0) {
+ Py_DECREF(elem);
return NULL;
+ }
}
if (rc) {
if (it->gettext) {
- PyObject *text = element_get_text(it->root_element);
- if (!text)
+ PyObject *text = element_get_text(elem);
+ if (!text) {
+ Py_DECREF(elem);
return NULL;
+ }
+ Py_INCREF(text);
+ Py_DECREF(elem);
rc = PyObject_IsTrue(text);
+ if (rc > 0)
+ return text;
+ Py_DECREF(text);
if (rc < 0)
return NULL;
- if (rc) {
- Py_INCREF(text);
- return text;
- }
} else {
- Py_INCREF(it->root_element);
- return (PyObject *)it->root_element;
+ return (PyObject *)elem;
}
}
+ else {
+ Py_DECREF(elem);
+ }
}
}
cur_parent = it->parent_stack->parent;
child_index = it->parent_stack->child_index;
if (cur_parent->extra && child_index < cur_parent->extra->length) {
- ElementObject *child = (ElementObject *)
- cur_parent->extra->children[child_index];
+ elem = (ElementObject *)cur_parent->extra->children[child_index];
it->parent_stack->child_index++;
it->parent_stack = parent_stack_push_new(it->parent_stack,
- child);
+ elem);
if (!it->parent_stack) {
PyErr_NoMemory();
return NULL;
}
+ Py_INCREF(elem);
if (it->gettext) {
- PyObject *text = element_get_text(child);
- if (!text)
+ PyObject *text = element_get_text(elem);
+ if (!text) {
+ Py_DECREF(elem);
return NULL;
+ }
+ Py_INCREF(text);
+ Py_DECREF(elem);
rc = PyObject_IsTrue(text);
+ if (rc > 0)
+ return text;
+ Py_DECREF(text);
if (rc < 0)
return NULL;
- if (rc) {
- Py_INCREF(text);
- return text;
- }
} else {
rc = (it->sought_tag == Py_None);
if (!rc) {
- rc = PyObject_RichCompareBool(child->tag,
+ rc = PyObject_RichCompareBool(elem->tag,
it->sought_tag, Py_EQ);
- if (rc < 0)
+ if (rc < 0) {
+ Py_DECREF(elem);
return NULL;
+ }
}
if (rc) {
- Py_INCREF(child);
- return (PyObject *)child;
+ return (PyObject *)elem;
}
+ Py_DECREF(elem);
}
}
else {
PyObject *tail;
- ParentLocator *next = it->parent_stack->next;
+ ParentLocator *next;
if (it->gettext) {
+ Py_INCREF(cur_parent);
tail = element_get_tail(cur_parent);
- if (!tail)
+ if (!tail) {
+ Py_DECREF(cur_parent);
return NULL;
+ }
+ Py_INCREF(tail);
+ Py_DECREF(cur_parent);
}
- else
+ else {
tail = Py_None;
- Py_XDECREF(it->parent_stack->parent);
+ Py_INCREF(tail);
+ }
+ next = it->parent_stack->next;
+ cur_parent = it->parent_stack->parent;
PyObject_Free(it->parent_stack);
it->parent_stack = next;
+ Py_XDECREF(cur_parent);
/* Note that extra condition on it->parent_stack->parent here;
* this is because itertext() is supposed to only return *inner*
*/
if (it->parent_stack->parent) {
rc = PyObject_IsTrue(tail);
+ if (rc > 0)
+ return tail;
+ Py_DECREF(tail);
if (rc < 0)
return NULL;
- if (rc) {
- Py_INCREF(tail);
- return tail;
- }
+ }
+ else {
+ Py_DECREF(tail);
}
}
}
if (!it)
return NULL;
- if (PyUnicode_Check(tag)) {
- if (PyUnicode_READY(tag) < 0)
- return NULL;
- if (PyUnicode_GET_LENGTH(tag) == 1 && PyUnicode_READ_CHAR(tag, 0) == '*')
- tag = Py_None;
- }
- else if (PyBytes_Check(tag)) {
- if (PyBytes_GET_SIZE(tag) == 1 && *PyBytes_AS_STRING(tag) == '*')
- tag = Py_None;
- }
-
Py_INCREF(tag);
it->sought_tag = tag;
it->root_done = 0;
}
}
+LOCAL(int)
+treebuilder_append_event(TreeBuilderObject *self, PyObject *action,
+ PyObject *node)
+{
+ if (action != NULL) {
+ PyObject *res = PyTuple_Pack(2, action, node);
+ if (res == NULL)
+ return -1;
+ if (PyList_Append(self->events, res) < 0) {
+ Py_DECREF(res);
+ return -1;
+ }
+ Py_DECREF(res);
+ }
+ return 0;
+}
+
/* -------------------------------------------------------------------- */
/* handlers */
}
self->index++;
- Py_DECREF(this);
Py_INCREF(node);
- self->this = node;
-
- Py_DECREF(self->last);
+ Py_SETREF(self->this, node);
Py_INCREF(node);
- self->last = node;
+ Py_SETREF(self->last, node);
- if (self->start_event_obj) {
- PyObject* res;
- PyObject* action = self->start_event_obj;
- res = PyTuple_Pack(2, action, node);
- if (res) {
- PyList_Append(self->events, res);
- Py_DECREF(res);
- } else
- PyErr_Clear(); /* FIXME: propagate error */
- }
+ if (treebuilder_append_event(self, self->start_event_obj, node) < 0)
+ goto error;
return node;
return NULL;
}
- self->index--;
-
- item = PyList_GET_ITEM(self->stack, self->index);
- Py_INCREF(item);
-
- Py_DECREF(self->last);
-
+ item = self->last;
self->last = self->this;
- self->this = item;
+ self->index--;
+ self->this = PyList_GET_ITEM(self->stack, self->index);
+ Py_INCREF(self->this);
+ Py_DECREF(item);
- if (self->end_event_obj) {
- PyObject* res;
- PyObject* action = self->end_event_obj;
- PyObject* node = (PyObject*) self->last;
- res = PyTuple_Pack(2, action, node);
- if (res) {
- PyList_Append(self->events, res);
- Py_DECREF(res);
- } else
- PyErr_Clear(); /* FIXME: propagate error */
- }
+ if (treebuilder_append_event(self, self->end_event_obj, self->last) < 0)
+ return NULL;
Py_INCREF(self->last);
return (PyObject*) self->last;
}
-LOCAL(void)
-treebuilder_handle_namespace(TreeBuilderObject* self, int start,
- PyObject *prefix, PyObject *uri)
-{
- PyObject* res;
- PyObject* action;
- PyObject* parcel;
-
- if (!self->events)
- return;
-
- if (start) {
- if (!self->start_ns_event_obj)
- return;
- action = self->start_ns_event_obj;
- parcel = Py_BuildValue("OO", prefix, uri);
- if (!parcel)
- return;
- Py_INCREF(action);
- } else {
- if (!self->end_ns_event_obj)
- return;
- action = self->end_ns_event_obj;
- Py_INCREF(action);
- parcel = Py_None;
- Py_INCREF(parcel);
- }
-
- res = PyTuple_New(2);
-
- if (res) {
- PyTuple_SET_ITEM(res, 0, action);
- PyTuple_SET_ITEM(res, 1, parcel);
- PyList_Append(self->events, res);
- Py_DECREF(res);
- }
- else {
- Py_DECREF(action);
- Py_DECREF(parcel);
- PyErr_Clear(); /* FIXME: propagate error */
- }
-}
-
/* -------------------------------------------------------------------- */
/* methods (in alphabetical order) */
/* attributes */
if (attrib_in[0]) {
attrib = PyDict_New();
- if (!attrib)
+ if (!attrib) {
+ Py_DECREF(tag);
return;
+ }
while (attrib_in[0] && attrib_in[1]) {
PyObject* key = makeuniversal(self, attrib_in[0]);
PyObject* value = PyUnicode_DecodeUTF8(attrib_in[1], strlen(attrib_in[1]), "strict");
Py_XDECREF(value);
Py_XDECREF(key);
Py_DECREF(attrib);
+ Py_DECREF(tag);
return;
}
ok = PyDict_SetItem(attrib, key, value);
Py_DECREF(key);
if (ok < 0) {
Py_DECREF(attrib);
+ Py_DECREF(tag);
return;
}
attrib_in += 2;
} else {
/* Pass an empty dictionary on */
attrib = PyDict_New();
- if (!attrib)
+ if (!attrib) {
+ Py_DECREF(tag);
return;
+ }
}
if (TreeBuilder_CheckExact(self->target)) {
expat_start_ns_handler(XMLParserObject* self, const XML_Char* prefix,
const XML_Char *uri)
{
- PyObject* sprefix = NULL;
- PyObject* suri = NULL;
+ TreeBuilderObject *target = (TreeBuilderObject*) self->target;
+ PyObject *parcel;
if (PyErr_Occurred())
return;
- if (uri)
- suri = PyUnicode_DecodeUTF8(uri, strlen(uri), "strict");
- else
- suri = PyUnicode_FromString("");
- if (!suri)
- return;
-
- if (prefix)
- sprefix = PyUnicode_DecodeUTF8(prefix, strlen(prefix), "strict");
- else
- sprefix = PyUnicode_FromString("");
- if (!sprefix) {
- Py_DECREF(suri);
+ if (!target->events || !target->start_ns_event_obj)
return;
- }
- treebuilder_handle_namespace(
- (TreeBuilderObject*) self->target, 1, sprefix, suri
- );
+ if (!uri)
+ uri = "";
+ if (!prefix)
+ prefix = "";
- Py_DECREF(sprefix);
- Py_DECREF(suri);
+ parcel = Py_BuildValue("ss", prefix, uri);
+ if (!parcel)
+ return;
+ treebuilder_append_event(target, target->start_ns_event_obj, parcel);
+ Py_DECREF(parcel);
}
static void
expat_end_ns_handler(XMLParserObject* self, const XML_Char* prefix_in)
{
+ TreeBuilderObject *target = (TreeBuilderObject*) self->target;
+
if (PyErr_Occurred())
return;
- treebuilder_handle_namespace(
- (TreeBuilderObject*) self->target, 0, NULL, NULL
- );
+ if (!target->events)
+ return;
+
+ treebuilder_append_event(target, target->end_ns_event_obj, Py_None);
}
static void
/*[clinic end generated code: output=1440092922b13ed1 input=59db9742910c6174]*/
{
/* activate element event reporting */
- Py_ssize_t i, seqlen;
+ Py_ssize_t i;
TreeBuilderObject *target;
PyObject *events_seq;
target = (TreeBuilderObject*) self->target;
Py_INCREF(events_queue);
- Py_XDECREF(target->events);
- target->events = events_queue;
+ Py_XSETREF(target->events, events_queue);
/* clear out existing events */
Py_CLEAR(target->start_event_obj);
return NULL;
}
- seqlen = PySequence_Size(events_seq);
- for (i = 0; i < seqlen; ++i) {
+ for (i = 0; i < PySequence_Size(events_seq); ++i) {
PyObject *event_name_obj = PySequence_Fast_GET_ITEM(events_seq, i);
char *event_name = NULL;
if (PyUnicode_Check(event_name_obj)) {
- event_name = _PyUnicode_AsString(event_name_obj);
+ event_name = PyUnicode_AsUTF8(event_name_obj);
} else if (PyBytes_Check(event_name_obj)) {
event_name = PyBytes_AS_STRING(event_name_obj);
}
-
if (event_name == NULL) {
Py_DECREF(events_seq);
PyErr_Format(PyExc_ValueError, "invalid events sequence");
return NULL;
- } else if (strcmp(event_name, "start") == 0) {
- Py_INCREF(event_name_obj);
- target->start_event_obj = event_name_obj;
+ }
+
+ Py_INCREF(event_name_obj);
+ if (strcmp(event_name, "start") == 0) {
+ Py_XSETREF(target->start_event_obj, event_name_obj);
} else if (strcmp(event_name, "end") == 0) {
- Py_INCREF(event_name_obj);
- Py_XDECREF(target->end_event_obj);
- target->end_event_obj = event_name_obj;
+ Py_XSETREF(target->end_event_obj, event_name_obj);
} else if (strcmp(event_name, "start-ns") == 0) {
- Py_INCREF(event_name_obj);
- Py_XDECREF(target->start_ns_event_obj);
- target->start_ns_event_obj = event_name_obj;
+ Py_XSETREF(target->start_ns_event_obj, event_name_obj);
EXPAT(SetNamespaceDeclHandler)(
self->parser,
(XML_StartNamespaceDeclHandler) expat_start_ns_handler,
(XML_EndNamespaceDeclHandler) expat_end_ns_handler
);
} else if (strcmp(event_name, "end-ns") == 0) {
- Py_INCREF(event_name_obj);
- Py_XDECREF(target->end_ns_event_obj);
- target->end_ns_event_obj = event_name_obj;
+ Py_XSETREF(target->end_ns_event_obj, event_name_obj);
EXPAT(SetNamespaceDeclHandler)(
self->parser,
(XML_StartNamespaceDeclHandler) expat_start_ns_handler,
(XML_EndNamespaceDeclHandler) expat_end_ns_handler
);
} else {
+ Py_DECREF(event_name_obj);
Py_DECREF(events_seq);
PyErr_Format(PyExc_ValueError, "unknown event '%s'", event_name);
return NULL;
return NULL;
}
- pargs = pkw = Py_None;
+ pargs = pkw = NULL;
func = PyTuple_GET_ITEM(args, 0);
if (Py_TYPE(func) == &partial_type && type == &partial_type) {
partialobject *part = (partialobject *)func;
pargs = part->args;
pkw = part->kw;
func = part->fn;
+ assert(PyTuple_Check(pargs));
+ assert(PyDict_Check(pkw));
}
}
if (!PyCallable_Check(func)) {
nargs = PyTuple_GetSlice(args, 1, PY_SSIZE_T_MAX);
if (nargs == NULL) {
- pto->args = NULL;
- pto->kw = NULL;
Py_DECREF(pto);
return NULL;
}
- if (pargs == Py_None || PyTuple_GET_SIZE(pargs) == 0) {
+ if (pargs == NULL || PyTuple_GET_SIZE(pargs) == 0) {
pto->args = nargs;
Py_INCREF(nargs);
}
else {
pto->args = PySequence_Concat(pargs, nargs);
if (pto->args == NULL) {
- pto->kw = NULL;
+ Py_DECREF(nargs);
Py_DECREF(pto);
return NULL;
}
+ assert(PyTuple_Check(pto->args));
}
Py_DECREF(nargs);
- if (kw != NULL) {
- if (pkw == Py_None) {
- pto->kw = PyDict_Copy(kw);
+ if (pkw == NULL || PyDict_Size(pkw) == 0) {
+ if (kw == NULL) {
+ pto->kw = PyDict_New();
}
else {
- pto->kw = PyDict_Copy(pkw);
- if (pto->kw != NULL) {
- if (PyDict_Merge(pto->kw, kw, 1) != 0) {
- Py_DECREF(pto);
- return NULL;
- }
- }
- }
- if (pto->kw == NULL) {
- Py_DECREF(pto);
- return NULL;
+ Py_INCREF(kw);
+ pto->kw = kw;
}
}
else {
- if (pkw == Py_None) {
- pto->kw = PyDict_New();
- if (pto->kw == NULL) {
+ pto->kw = PyDict_Copy(pkw);
+ if (kw != NULL && pto->kw != NULL) {
+ if (PyDict_Merge(pto->kw, kw, 1) != 0) {
Py_DECREF(pto);
return NULL;
}
}
- else {
- pto->kw = pkw;
- Py_INCREF(pkw);
- }
}
-
- pto->weakreflist = NULL;
- pto->dict = NULL;
+ if (pto->kw == NULL) {
+ Py_DECREF(pto);
+ return NULL;
+ }
return (PyObject *)pto;
}
partial_call(partialobject *pto, PyObject *args, PyObject *kw)
{
PyObject *ret;
- PyObject *argappl = NULL, *kwappl = NULL;
+ PyObject *argappl, *kwappl;
assert (PyCallable_Check(pto->fn));
assert (PyTuple_Check(pto->args));
- assert (pto->kw == Py_None || PyDict_Check(pto->kw));
+ assert (PyDict_Check(pto->kw));
if (PyTuple_GET_SIZE(pto->args) == 0) {
argappl = args;
argappl = PySequence_Concat(pto->args, args);
if (argappl == NULL)
return NULL;
+ assert(PyTuple_Check(argappl));
}
- if (pto->kw == Py_None) {
+ if (PyDict_Size(pto->kw) == 0) {
kwappl = kw;
- Py_XINCREF(kw);
+ Py_XINCREF(kwappl);
} else {
kwappl = PyDict_Copy(pto->kw);
if (kwappl == NULL) {
PyObject *arglist;
PyObject *tmp;
Py_ssize_t i, n;
+ PyObject *key, *value;
arglist = PyUnicode_FromString("");
if (arglist == NULL) {
arglist = tmp;
}
/* Pack keyword arguments */
- assert (pto->kw == Py_None || PyDict_Check(pto->kw));
- if (pto->kw != Py_None) {
- PyObject *key, *value;
- for (i = 0; PyDict_Next(pto->kw, &i, &key, &value);) {
- tmp = PyUnicode_FromFormat("%U, %U=%R", arglist,
- key, value);
- Py_DECREF(arglist);
- if (tmp == NULL)
- return NULL;
- arglist = tmp;
- }
+ assert (PyDict_Check(pto->kw));
+ for (i = 0; PyDict_Next(pto->kw, &i, &key, &value);) {
+ tmp = PyUnicode_FromFormat("%U, %U=%R", arglist,
+ key, value);
+ Py_DECREF(arglist);
+ if (tmp == NULL)
+ return NULL;
+ arglist = tmp;
}
result = PyUnicode_FromFormat("%s(%R%U)", Py_TYPE(pto)->tp_name,
pto->fn, arglist);
partial_setstate(partialobject *pto, PyObject *state)
{
PyObject *fn, *fnargs, *kw, *dict;
- if (!PyArg_ParseTuple(state, "OOOO",
- &fn, &fnargs, &kw, &dict))
+
+ if (!PyTuple_Check(state) ||
+ !PyArg_ParseTuple(state, "OOOO", &fn, &fnargs, &kw, &dict) ||
+ !PyCallable_Check(fn) ||
+ !PyTuple_Check(fnargs) ||
+ (kw != Py_None && !PyDict_Check(kw)))
+ {
+ PyErr_SetString(PyExc_TypeError, "invalid partial state");
+ return NULL;
+ }
+
+ if(!PyTuple_CheckExact(fnargs))
+ fnargs = PySequence_Tuple(fnargs);
+ else
+ Py_INCREF(fnargs);
+ if (fnargs == NULL)
+ return NULL;
+
+ if (kw == Py_None)
+ kw = PyDict_New();
+ else if(!PyDict_CheckExact(kw))
+ kw = PyDict_Copy(kw);
+ else
+ Py_INCREF(kw);
+ if (kw == NULL) {
+ Py_DECREF(fnargs);
return NULL;
- Py_XDECREF(pto->fn);
- Py_XDECREF(pto->args);
- Py_XDECREF(pto->kw);
- Py_XDECREF(pto->dict);
- pto->fn = fn;
- pto->args = fnargs;
- pto->kw = kw;
- if (dict != Py_None) {
- pto->dict = dict;
- Py_INCREF(dict);
- } else {
- pto->dict = NULL;
}
+
Py_INCREF(fn);
- Py_INCREF(fnargs);
- Py_INCREF(kw);
+ if (dict == Py_None)
+ dict = NULL;
+ else
+ Py_INCREF(dict);
+
+ Py_SETREF(pto->fn, fn);
+ Py_SETREF(pto->args, fnargs);
+ Py_SETREF(pto->kw, kw);
+ Py_XSETREF(pto->dict, dict);
Py_RETURN_NONE;
}
return PyObject_GetAttrString(self, "__qualname__");
}
+static PyObject *
+lru_cache_copy(PyObject *self, PyObject *unused)
+{
+ Py_INCREF(self);
+ return self;
+}
+
+static PyObject *
+lru_cache_deepcopy(PyObject *self, PyObject *unused)
+{
+ Py_INCREF(self);
+ return self;
+}
+
static int
lru_cache_tp_traverse(lru_cache_object *self, visitproc visit, void *arg)
{
{"cache_info", (PyCFunction)lru_cache_cache_info, METH_NOARGS},
{"cache_clear", (PyCFunction)lru_cache_cache_clear, METH_NOARGS},
{"__reduce__", (PyCFunction)lru_cache_reduce, METH_NOARGS},
+ {"__copy__", (PyCFunction)lru_cache_copy, METH_VARARGS},
+ {"__deepcopy__", (PyCFunction)lru_cache_deepcopy, METH_VARARGS},
{NULL}
};
\n\
\n\
In the tree above, each cell `k' is topping `2*k+1' and `2*k+2'. In\n\
-an usual binary tournament we see in sports, each cell is the winner\n\
+a usual binary tournament we see in sports, each cell is the winner\n\
over the two cells it tops, and we can trace the winner down the tree\n\
to see all opponents s/he had. However, in many computer applications\n\
of such tournaments, we do not need to trace the history of a winner.\n\
PyDoc_STRVAR(bufferediobase_write_doc,
"Write the given buffer to the IO stream.\n"
"\n"
- "Returns the number of bytes written, which is never less than\n"
- "len(b).\n"
+ "Returns the number of bytes written, which is always the length of b\n"
+ "in bytes.\n"
"\n"
"Raises BlockingIOError if the buffer is full and the\n"
"underlying raw stream cannot accept more data at the moment.\n");
{
Py_ssize_t res;
- res = sizeof(buffered);
+ res = _PyObject_SIZE(Py_TYPE(self));
if (self->buffer)
res += self->buffer_size;
return PyLong_FromSsize_t(res);
Py_CLEAR(res);
goto end;
}
- Py_CLEAR(res);
- res = _PyBytes_Join(_PyIO_empty_bytes, chunks);
+ Py_XSETREF(res, _PyBytes_Join(_PyIO_empty_bytes, chunks));
end:
LEAVE_BUFFERED(self)
if (_PyIOBase_check_readable(raw, Py_True) == NULL)
return -1;
- Py_CLEAR(self->raw);
Py_INCREF(raw);
- self->raw = raw;
+ Py_XSETREF(self->raw, raw);
self->buffer_size = buffer_size;
self->readable = 1;
self->writable = 0;
if (_PyIOBase_check_writable(raw, Py_True) == NULL)
return -1;
- Py_CLEAR(self->raw);
Py_INCREF(raw);
- self->raw = raw;
+ Py_XSETREF(self->raw, raw);
self->readable = 0;
self->writable = 1;
if (_PyIOBase_check_writable(raw, Py_True) == NULL)
return -1;
- Py_CLEAR(self->raw);
Py_INCREF(raw);
- self->raw = raw;
+ Py_XSETREF(self->raw, raw);
self->buffer_size = buffer_size;
self->readable = 1;
self->writable = 1;
{"close", (PyCFunction)buffered_close, METH_NOARGS},
{"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
{"readable", (PyCFunction)buffered_readable, METH_NOARGS},
- {"writable", (PyCFunction)buffered_writable, METH_NOARGS},
{"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
{"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
{"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O},
{"close", (PyCFunction)buffered_close, METH_NOARGS},
{"detach", (PyCFunction)buffered_detach, METH_NOARGS},
{"seekable", (PyCFunction)buffered_seekable, METH_NOARGS},
- {"readable", (PyCFunction)buffered_readable, METH_NOARGS},
{"writable", (PyCFunction)buffered_writable, METH_NOARGS},
{"fileno", (PyCFunction)buffered_fileno, METH_NOARGS},
{"isatty", (PyCFunction)buffered_isatty, METH_NOARGS},
buffer: Py_buffer(accept={rwbuffer})
/
-Read up to len(buffer) bytes into buffer.
+Read bytes into buffer.
Returns number of bytes read (0 for EOF), or None if the object
-is set not to block as has no data to read.
+is set not to block and has no data to read.
[clinic start generated code]*/
static PyObject *
_io_BytesIO_readinto_impl(bytesio *self, Py_buffer *buffer)
-/*[clinic end generated code: output=a5d407217dcf0639 input=71581f32635c3a31]*/
+/*[clinic end generated code: output=a5d407217dcf0639 input=1424d0fdce857919]*/
{
Py_ssize_t len, n;
if (initvalue && initvalue != Py_None) {
if (PyBytes_CheckExact(initvalue)) {
Py_INCREF(initvalue);
- Py_XDECREF(self->buf);
- self->buf = initvalue;
+ Py_XSETREF(self->buf, initvalue);
self->string_size = PyBytes_GET_SIZE(initvalue);
}
else {
{
Py_ssize_t res;
- res = sizeof(bytesio);
+ res = _PyObject_SIZE(Py_TYPE(self));
if (self->buf && !SHARED_BUF(self))
res += _PySys_GetSizeOf(self->buf);
return PyLong_FromSsize_t(res);
"readinto($self, buffer, /)\n"
"--\n"
"\n"
-"Read up to len(buffer) bytes into buffer.\n"
+"Read bytes into buffer.\n"
"\n"
"Returns number of bytes read (0 for EOF), or None if the object\n"
-"is set not to block as has no data to read.");
+"is set not to block and has no data to read.");
#define _IO_BYTESIO_READINTO_METHODDEF \
{"readinto", (PyCFunction)_io_BytesIO_readinto, METH_O, _io_BytesIO_readinto__doc__},
exit:
return return_value;
}
-/*[clinic end generated code: output=500ccc149587fac4 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=60ce2c6272718431 input=a9049054013a1b77]*/
"write($self, b, /)\n"
"--\n"
"\n"
-"Write bytes b to file, return number written.\n"
+"Write buffer b to file, return number of bytes written.\n"
"\n"
"Only makes one system call, so not all of the data may be written.\n"
"The number of bytes actually written is returned. In non-blocking mode,\n"
#ifndef _IO_FILEIO_TRUNCATE_METHODDEF
#define _IO_FILEIO_TRUNCATE_METHODDEF
#endif /* !defined(_IO_FILEIO_TRUNCATE_METHODDEF) */
-/*[clinic end generated code: output=b1a20b10c81add64 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=dcbc39b466598492 input=a9049054013a1b77]*/
"\n"
"Return whether object supports random access.\n"
"\n"
-"If False, seek(), tell() and truncate() will raise UnsupportedOperation.\n"
+"If False, seek(), tell() and truncate() will raise OSError.\n"
"This method may need to do a test seek().");
#define _IO__IOBASE_SEEKABLE_METHODDEF \
"\n"
"Return whether object was opened for reading.\n"
"\n"
-"If False, read() will raise UnsupportedOperation.");
+"If False, read() will raise OSError.");
#define _IO__IOBASE_READABLE_METHODDEF \
{"readable", (PyCFunction)_io__IOBase_readable, METH_NOARGS, _io__IOBase_readable__doc__},
"\n"
"Return whether object was opened for writing.\n"
"\n"
-"If False, write() will raise UnsupportedOperation.");
+"If False, write() will raise OSError.");
#define _IO__IOBASE_WRITABLE_METHODDEF \
{"writable", (PyCFunction)_io__IOBase_writable, METH_NOARGS, _io__IOBase_writable__doc__},
"\n"
"Returns underlying file descriptor if one exists.\n"
"\n"
-"An IOError is raised if the IO object does not use a file descriptor.");
+"OSError is raised if the IO object does not use a file descriptor.");
#define _IO__IOBASE_FILENO_METHODDEF \
{"fileno", (PyCFunction)_io__IOBase_fileno, METH_NOARGS, _io__IOBase_fileno__doc__},
{
return _io__RawIOBase_readall_impl(self);
}
-/*[clinic end generated code: output=fe034152b6884e65 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=b874952f5cc248a4 input=a9049054013a1b77]*/
int *atomic_flag_works = NULL;
#endif
struct _Py_stat_struct fdfstat;
+ int fstat_result;
int async_err = 0;
assert(PyFileIO_Check(self));
self->fd = _PyLong_AsInt(fdobj);
Py_DECREF(fdobj);
- if (self->fd == -1) {
+ if (self->fd < 0) {
+ if (!PyErr_Occurred()) {
+ /* The opener returned a negative but didn't set an
+ exception. See issue #27066 */
+ PyErr_Format(PyExc_ValueError,
+ "opener returned %d", self->fd);
+ }
goto error;
}
}
}
self->blksize = DEFAULT_BUFFER_SIZE;
- if (_Py_fstat(self->fd, &fdfstat) < 0)
- goto error;
-#if defined(S_ISDIR) && defined(EISDIR)
- /* On Unix, open will succeed for directories.
- In Python, there should be no file objects referring to
- directories, so we need a check. */
- if (S_ISDIR(fdfstat.st_mode)) {
- errno = EISDIR;
- PyErr_SetFromErrnoWithFilenameObject(PyExc_IOError, nameobj);
- goto error;
+ Py_BEGIN_ALLOW_THREADS
+ fstat_result = _Py_fstat_noraise(self->fd, &fdfstat);
+ Py_END_ALLOW_THREADS
+ if (fstat_result < 0) {
+ /* Tolerate fstat() errors other than EBADF. See Issue #25717, where
+ an anonymous file on a Virtual Box shared folder filesystem would
+ raise ENOENT. */
+#ifdef MS_WINDOWS
+ if (GetLastError() == ERROR_INVALID_HANDLE) {
+ PyErr_SetFromWindowsErr(0);
+#else
+ if (errno == EBADF) {
+ PyErr_SetFromErrno(PyExc_OSError);
+#endif
+ goto error;
+ }
}
+ else {
+#if defined(S_ISDIR) && defined(EISDIR)
+ /* On Unix, open will succeed for directories.
+ In Python, there should be no file objects referring to
+ directories, so we need a check. */
+ if (S_ISDIR(fdfstat.st_mode)) {
+ errno = EISDIR;
+ PyErr_SetFromErrnoWithFilenameObject(PyExc_IOError, nameobj);
+ goto error;
+ }
#endif /* defined(S_ISDIR) */
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
- if (fdfstat.st_blksize > 1)
- self->blksize = fdfstat.st_blksize;
+ if (fdfstat.st_blksize > 1)
+ self->blksize = fdfstat.st_blksize;
#endif /* HAVE_STRUCT_STAT_ST_BLKSIZE */
+ }
#if defined(MS_WINDOWS) || defined(__CYGWIN__)
/* don't translate newlines (\r\n <=> \n) */
b: Py_buffer
/
-Write bytes b to file, return number written.
+Write buffer b to file, return number of bytes written.
Only makes one system call, so not all of the data may be written.
The number of bytes actually written is returned. In non-blocking mode,
static PyObject *
_io_FileIO_write_impl(fileio *self, Py_buffer *b)
-/*[clinic end generated code: output=b4059db3d363a2f7 input=ffbd8834f447ac31]*/
+/*[clinic end generated code: output=b4059db3d363a2f7 input=6e7908b36f0ce74f]*/
{
Py_ssize_t n;
int err;
"called.\n"
"\n"
"The basic type used for binary data read from or written to a file is\n"
- "bytes. bytearrays are accepted too, and in some cases (such as\n"
- "readinto) needed. Text I/O classes work with str data.\n"
+ "bytes. Other bytes-like objects are accepted as method arguments too.\n"
+ "In some cases (such as readinto), a writable object is required. Text\n"
+ "I/O classes work with str data.\n"
"\n"
"Note that calling any method (except additional calls to close(),\n"
"which are ignored) on a closed stream should raise a ValueError.\n"
Return whether object supports random access.
-If False, seek(), tell() and truncate() will raise UnsupportedOperation.
+If False, seek(), tell() and truncate() will raise OSError.
This method may need to do a test seek().
[clinic start generated code]*/
static PyObject *
_io__IOBase_seekable_impl(PyObject *self)
-/*[clinic end generated code: output=4c24c67f5f32a43d input=22676eebb81dcf1e]*/
+/*[clinic end generated code: output=4c24c67f5f32a43d input=b976622f7fdf3063]*/
{
Py_RETURN_FALSE;
}
Return whether object was opened for reading.
-If False, read() will raise UnsupportedOperation.
+If False, read() will raise OSError.
[clinic start generated code]*/
static PyObject *
_io__IOBase_readable_impl(PyObject *self)
-/*[clinic end generated code: output=e48089250686388b input=12fc3d8f6be46434]*/
+/*[clinic end generated code: output=e48089250686388b input=285b3b866a0ec35f]*/
{
Py_RETURN_FALSE;
}
Return whether object was opened for writing.
-If False, write() will raise UnsupportedOperation.
+If False, write() will raise OSError.
[clinic start generated code]*/
static PyObject *
_io__IOBase_writable_impl(PyObject *self)
-/*[clinic end generated code: output=406001d0985be14f input=c17a0bb6a8dfc590]*/
+/*[clinic end generated code: output=406001d0985be14f input=9dcac18a013a05b5]*/
{
Py_RETURN_FALSE;
}
Returns underlying file descriptor if one exists.
-An IOError is raised if the IO object does not use a file descriptor.
+OSError is raised if the IO object does not use a file descriptor.
[clinic start generated code]*/
static PyObject *
_io__IOBase_fileno_impl(PyObject *self)
-/*[clinic end generated code: output=7cc0973f0f5f3b73 input=32773c5df4b7eede]*/
+/*[clinic end generated code: output=7cc0973f0f5f3b73 input=4e37028947dc1cc8]*/
{
return iobase_unsupported("fileno");
}
Py_DECREF(initarg);
/* Restore the buffer state. Even if __init__ did initialize the buffer,
- we have to initialize it again since __init__ may translates the
- newlines in the inital_value string. We clearly do not want that
+ we have to initialize it again since __init__ may translate the
+ newlines in the initial_value string. We clearly do not want that
because the string value in the state tuple has already been translated
once by __init__. So we do not take any chance and replace object's
buffer completely. */
"Oi", self->decoder, (int)self->readtranslate);
if (incrementalDecoder == NULL)
goto error;
- Py_CLEAR(self->decoder);
- self->decoder = incrementalDecoder;
+ Py_XSETREF(self->decoder, incrementalDecoder);
}
}
static void
textiowrapper_set_decoded_chars(textio *self, PyObject *chars)
{
- Py_CLEAR(self->decoded_chars);
- self->decoded_chars = chars;
+ Py_XSETREF(self->decoded_chars, chars);
self->decoded_chars_used = 0;
}
dec_buffer = NULL; /* Reference lost to PyBytes_Concat */
goto fail;
}
- Py_CLEAR(self->snapshot);
- self->snapshot = Py_BuildValue("NN", dec_flags, next_input);
+ Py_XSETREF(self->snapshot, Py_BuildValue("NN", dec_flags, next_input));
}
Py_DECREF(input_chunk);
if (chunks != NULL) {
if (result != NULL && PyList_Append(chunks, result) < 0)
goto fail;
- Py_CLEAR(result);
- result = PyUnicode_Join(_PyIO_empty_str, chunks);
+ Py_XSETREF(result, PyUnicode_Join(_PyIO_empty_str, chunks));
if (result == NULL)
goto fail;
Py_CLEAR(chunks);
static PyObject *
encoder_encode_string(PyEncoderObject *s, PyObject *obj);
static PyObject *
-encoder_encode_long(PyEncoderObject* s UNUSED, PyObject *obj);
-static PyObject *
encoder_encode_float(PyEncoderObject *s, PyObject *obj);
#define S_CHAR(c) (c >= ' ' && c <= '~' && c != '\\' && c != '"')
}
static PyObject *
-encoder_encode_long(PyEncoderObject* s UNUSED, PyObject *obj)
-{
- /* Return the JSON representation of a PyLong and PyLong subclasses.
- Calls int() on PyLong subclasses in case the str() was changed.
- Added specifically to deal with IntEnum. See Issue18264. */
- PyObject *encoded, *longobj;
- if (PyLong_CheckExact(obj)) {
- encoded = PyObject_Str(obj);
- }
- else {
- longobj = PyNumber_Long(obj);
- if (longobj == NULL) {
- PyErr_SetString(
- PyExc_ValueError,
- "Unable to coerce int subclass to int"
- );
- return NULL;
- }
- encoded = PyObject_Str(longobj);
- Py_DECREF(longobj);
- }
- return encoded;
-}
-
-
-static PyObject *
encoder_encode_float(PyEncoderObject *s, PyObject *obj)
{
- /* Return the JSON representation of a PyFloat.
- Modified to call float() on float subclasses in case the subclass
- changes the repr. See Issue18264. */
- PyObject *encoded, *floatobj;
+ /* Return the JSON representation of a PyFloat. */
double i = PyFloat_AS_DOUBLE(obj);
if (!Py_IS_FINITE(i)) {
if (!s->allow_nan) {
return PyUnicode_FromString("NaN");
}
}
- /* coerce float subclasses to float (primarily for Enum) */
- if (PyFloat_CheckExact(obj)) {
- /* Use a better float format here? */
- encoded = PyObject_Repr(obj);
- }
- else {
- floatobj = PyNumber_Float(obj);
- if (floatobj == NULL) {
- PyErr_SetString(
- PyExc_ValueError,
- "Unable to coerce float subclass to float"
- );
- return NULL;
- }
- encoded = PyObject_Repr(floatobj);
- Py_DECREF(floatobj);
- }
- return encoded;
+ return PyFloat_Type.tp_repr(obj);
}
static PyObject *
return _steal_accumulate(acc, encoded);
}
else if (PyLong_Check(obj)) {
- PyObject *encoded = encoder_encode_long(s, obj);
+ PyObject *encoded = PyLong_Type.tp_str(obj);
if (encoded == NULL)
return -1;
return _steal_accumulate(acc, encoded);
goto bail;
}
else if (PyLong_Check(key)) {
- kstr = encoder_encode_long(s, key);
+ kstr = PyLong_Type.tp_str(key);
if (kstr == NULL) {
goto bail;
}
check: int(c_default="-1") = unspecified
The integrity check to use. For FORMAT_XZ, the default
- is CHECK_CRC64. FORMAT_ALONE and FORMAT_RAW do not suport integrity
+ is CHECK_CRC64. FORMAT_ALONE and FORMAT_RAW do not support integrity
checks; for these formats, check must be omitted, or be CHECK_NONE.
preset: object = None
if (d->eof) {
d->needs_input = 0;
if (lzs->avail_in > 0) {
- Py_CLEAR(d->unused_data);
- d->unused_data = PyBytes_FromStringAndSize(
- (char *)lzs->next_in, lzs->avail_in);
+ Py_XSETREF(d->unused_data,
+ PyBytes_FromStringAndSize((char *)lzs->next_in, lzs->avail_in));
if (d->unused_data == NULL)
goto error;
}
PyObject *obj, *result;
Py_ssize_t i, nitems=ig->nitems;
+ if (kw != NULL && !_PyArg_NoKeywords("itemgetter", kw))
+ return NULL;
if (!PyArg_UnpackTuple(args, "itemgetter", 1, 1, &obj))
return NULL;
if (nitems == 1)
PyObject *obj, *result;
Py_ssize_t i, nattrs=ag->nattrs;
+ if (kw != NULL && !_PyArg_NoKeywords("attrgetter", kw))
+ return NULL;
if (!PyArg_UnpackTuple(args, "attrgetter", 1, 1, &obj))
return NULL;
if (ag->nattrs == 1) /* ag->attr is always a tuple */
{
PyObject *method, *obj, *result;
+ if (kw != NULL && !_PyArg_NoKeywords("methodcaller", kw))
+ return NULL;
if (!PyArg_UnpackTuple(args, "methodcaller", 1, 1, &obj))
return NULL;
method = PyObject_GetAttr(obj, mc->name);
static PyObject *
Pdata_pop(Pdata *self)
{
- PickleState *st = _Pickle_GetGlobalState();
if (Py_SIZE(self) == 0) {
+ PickleState *st = _Pickle_GetGlobalState();
PyErr_SetString(st->UnpicklingError, "bad pickle data");
return NULL;
}
int bin; /* Boolean, true if proto > 0 */
int framing; /* True when framing is enabled, proto >= 4 */
Py_ssize_t frame_start; /* Position in output_buffer where the
- where the current frame begins. -1 if there
+ current frame begins. -1 if there
is no frame currently open. */
Py_ssize_t buf_size; /* Size of the current buffered pickle data */
static int
_Pickler_ClearBuffer(PicklerObject *self)
{
- Py_CLEAR(self->output_buffer);
- self->output_buffer =
- PyBytes_FromStringAndSize(NULL, self->max_output_len);
+ Py_XSETREF(self->output_buffer,
+ PyBytes_FromStringAndSize(NULL, self->max_output_len));
if (self->output_buffer == NULL)
return -1;
self->output_len = 0;
return 0;
assert(self->peek); /* otherwise we did something wrong */
- /* This makes an useless copy... */
+ /* This makes a useless copy... */
r = PyObject_CallFunction(self->read, "n", consumed);
if (r == NULL)
return -1;
Py_TYPE(item)->tp_name);
return -1;
}
- Py_CLEAR(*module_name);
Py_INCREF(item);
- *module_name = item;
+ Py_XSETREF(*module_name, item);
}
else if (PyErr_Occurred()) {
return -1;
{
Py_ssize_t res, s;
- res = sizeof(PicklerObject);
+ res = _PyObject_SIZE(Py_TYPE(self));
if (self->memo != NULL) {
res += sizeof(PyMemoTable);
res += self->memo->mt_allocated * sizeof(PyMemoEntry);
/* s contains x bytes of a little-endian integer. Return its value as a
* C int. Obscure: when x is 1 or 2, this is an unsigned little-endian
- * int, but when x is 4 it's a signed one. This is an historical source
+ * int, but when x is 4 it's a signed one. This is a historical source
* of x-platform bugs.
*/
static long
}
static int
-load_tuple(UnpicklerObject *self)
+load_counted_tuple(UnpicklerObject *self, Py_ssize_t len)
{
PyObject *tuple;
- Py_ssize_t i;
- if ((i = marker(self)) < 0)
- return -1;
+ if (Py_SIZE(self->stack) < len)
+ return stack_underflow();
- tuple = Pdata_poptuple(self->stack, i);
+ tuple = Pdata_poptuple(self->stack, Py_SIZE(self->stack) - len);
if (tuple == NULL)
return -1;
PDATA_PUSH(self->stack, tuple, -1);
}
static int
-load_counted_tuple(UnpicklerObject *self, int len)
+load_tuple(UnpicklerObject *self)
{
- PyObject *tuple;
+ Py_ssize_t i;
- tuple = PyTuple_New(len);
- if (tuple == NULL)
+ if ((i = marker(self)) < 0)
return -1;
- while (--len >= 0) {
- PyObject *item;
-
- PDATA_POP(self->stack, item);
- if (item == NULL)
- return -1;
- PyTuple_SET_ITEM(tuple, len, item);
- }
- PDATA_PUSH(self->stack, tuple, -1);
- return 0;
+ return load_counted_tuple(self, Py_SIZE(self->stack) - i);
}
static int
if ((i = marker(self)) < 0)
return -1;
+ if (Py_SIZE(self->stack) - i < 1)
+ return stack_underflow();
+
args = Pdata_poptuple(self->stack, i + 1);
if (args == NULL)
return -1;
return -1;
if ((len = _Unpickler_Readline(self, &s)) >= 0) {
- if (len < 2)
+ if (len < 2) {
+ Py_DECREF(module_name);
return bad_readline();
+ }
class_name = PyUnicode_DecodeASCII(s, len - 1, "strict");
if (class_name != NULL) {
cls = find_class(self, module_name, class_name);
static int
load_append(UnpicklerObject *self)
{
+ if (Py_SIZE(self->stack) - 1 <= 0)
+ return stack_underflow();
return do_append(self, Py_SIZE(self->stack) - 1);
}
static int
load_appends(UnpicklerObject *self)
{
- return do_append(self, marker(self));
+ Py_ssize_t i = marker(self);
+ if (i < 0)
+ return -1;
+ return do_append(self, i);
}
static int
static int
load_setitems(UnpicklerObject *self)
{
- return do_setitems(self, marker(self));
+ Py_ssize_t i = marker(self);
+ if (i < 0)
+ return -1;
+ return do_setitems(self, i);
}
static int
Py_ssize_t mark, len, i;
mark = marker(self);
+ if (mark < 0)
+ return -1;
len = Py_SIZE(self->stack);
if (mark > len || mark <= 0)
return stack_underflow();
{
Py_ssize_t res;
- res = sizeof(UnpicklerObject);
+ res = _PyObject_SIZE(Py_TYPE(self));
if (self->memo != NULL)
res += self->memo_size * sizeof(PyObject *);
if (self->marks != NULL)
other custom object that meets this interface.
Optional keyword arguments are *fix_imports*, *encoding* and *errors*,
-which are used to control compatiblity support for pickle stream
+which are used to control compatibility support for pickle stream
generated by Python 2. If *fix_imports* is True, pickle will try to
map the old Python 2 names to the new names used in Python 3. The
*encoding* and *errors* tell pickle how to decode 8-bit string
_pickle_Unpickler___init___impl(UnpicklerObject *self, PyObject *file,
int fix_imports, const char *encoding,
const char *errors)
-/*[clinic end generated code: output=e2c8ce748edc57b0 input=04ece661aa884837]*/
+/*[clinic end generated code: output=e2c8ce748edc57b0 input=f9b7da04f5f4f335]*/
{
_Py_IDENTIFIER(persistent_load);
other custom object that meets this interface.
Optional keyword arguments are *fix_imports*, *encoding* and *errors*,
-which are used to control compatiblity support for pickle stream
+which are used to control compatibility support for pickle stream
generated by Python 2. If *fix_imports* is True, pickle will try to
map the old Python 2 names to the new names used in Python 3. The
*encoding* and *errors* tell pickle how to decode 8-bit string
static PyObject *
_pickle_load_impl(PyModuleDef *module, PyObject *file, int fix_imports,
const char *encoding, const char *errors)
-/*[clinic end generated code: output=798f1c57cb2b4eb1 input=2df7c7a1e6742204]*/
+/*[clinic end generated code: output=798f1c57cb2b4eb1 input=01b44dd3fc07afa7]*/
{
PyObject *result;
UnpicklerObject *unpickler = _Unpickler_New();
representation are ignored.
Optional keyword arguments are *fix_imports*, *encoding* and *errors*,
-which are used to control compatiblity support for pickle stream
+which are used to control compatibility support for pickle stream
generated by Python 2. If *fix_imports* is True, pickle will try to
map the old Python 2 names to the new names used in Python 3. The
*encoding* and *errors* tell pickle how to decode 8-bit string
static PyObject *
_pickle_loads_impl(PyModuleDef *module, PyObject *data, int fix_imports,
const char *encoding, const char *errors)
-/*[clinic end generated code: output=61e9cdb01e36a736 input=f57f0fdaa2b4cb8b]*/
+/*[clinic end generated code: output=61e9cdb01e36a736 input=70605948a719feb9]*/
{
PyObject *result;
UnpicklerObject *unpickler = _Unpickler_New();
#define POSIX_CALL(call) do { if ((call) == -1) goto error; } while (0)
-/* Given the gc module call gc.enable() and return 0 on success. */
+/* If gc was disabled, call gc.enable(). Return 0 on success. */
static int
-_enable_gc(PyObject *gc_module)
+_enable_gc(int need_to_reenable_gc, PyObject *gc_module)
{
PyObject *result;
_Py_IDENTIFIER(enable);
+ PyObject *exctype, *val, *tb;
- result = _PyObject_CallMethodId(gc_module, &PyId_enable, NULL);
- if (result == NULL)
- return 1;
- Py_DECREF(result);
+ if (need_to_reenable_gc) {
+ PyErr_Fetch(&exctype, &val, &tb);
+ result = _PyObject_CallMethodId(gc_module, &PyId_enable, NULL);
+ if (exctype != NULL) {
+ PyErr_Restore(exctype, val, tb);
+ }
+ if (result == NULL) {
+ return 1;
+ }
+ Py_DECREF(result);
+ }
return 0;
}
&& _PyImport_ReleaseLock() < 0 && !PyErr_Occurred()) {
PyErr_SetString(PyExc_RuntimeError,
"not holding the import lock");
+ pid = -1;
}
import_lock_held = 0;
#endif
_Py_FreeCharPArray(exec_array);
/* Reenable gc in the parent process (or if fork failed). */
- if (need_to_reenable_gc && _enable_gc(gc_module)) {
- Py_XDECREF(gc_module);
- return NULL;
+ if (_enable_gc(need_to_reenable_gc, gc_module)) {
+ pid = -1;
}
Py_XDECREF(preexec_fn_args_tuple);
Py_XDECREF(gc_module);
Py_XDECREF(converted_args);
Py_XDECREF(fast_args);
Py_XDECREF(preexec_fn_args_tuple);
-
- /* Reenable gc if it was disabled. */
- if (need_to_reenable_gc) {
- PyObject *exctype, *val, *tb;
- PyErr_Fetch(&exctype, &val, &tb);
- _enable_gc(gc_module);
- PyErr_Restore(exctype, val, tb);
- }
+ _enable_gc(need_to_reenable_gc, gc_module);
Py_XDECREF(gc_module);
return NULL;
}
node = node->next;
}
- Py_DECREF(self->statement_cache);
- self->statement_cache = (pysqlite_Cache*)PyObject_CallFunction((PyObject*)&pysqlite_CacheType, "O", self);
+ Py_SETREF(self->statement_cache,
+ (pysqlite_Cache *)PyObject_CallFunction((PyObject *)&pysqlite_CacheType, "O", self));
Py_DECREF(self);
self->statement_cache->decref_factory = 0;
}
_pysqlite_drop_unused_cursor_references(self);
if (cursor && self->row_factory != Py_None) {
- Py_XDECREF(((pysqlite_Cursor*)cursor)->row_factory);
Py_INCREF(self->row_factory);
- ((pysqlite_Cursor*)cursor)->row_factory = self->row_factory;
+ Py_XSETREF(((pysqlite_Cursor *)cursor)->row_factory, self->row_factory);
}
return cursor;
}
}
- Py_DECREF(self->statements);
- self->statements = new_list;
+ Py_SETREF(self->statements, new_list);
}
static void _pysqlite_drop_unused_cursor_references(pysqlite_Connection* self)
}
}
- Py_DECREF(self->cursors);
- self->cursors = new_list;
+ Py_SETREF(self->cursors, new_list);
}
PyObject* pysqlite_connection_create_function(pysqlite_Connection* self, PyObject* args, PyObject* kwargs)
return 0;
}
- Py_XDECREF(self->row_cast_map);
- self->row_cast_map = PyList_New(0);
+ Py_XSETREF(self->row_cast_map, PyList_New(0));
for (i = 0; i < sqlite3_column_count(self->statement->st); i++) {
converter = NULL;
goto error;
/* reset description and rowcount */
- Py_DECREF(self->description);
Py_INCREF(Py_None);
- self->description = Py_None;
+ Py_SETREF(self->description, Py_None);
self->rowcount = -1L;
func_args = PyTuple_New(1);
if (self->statement) {
(void)pysqlite_statement_reset(self->statement);
- Py_DECREF(self->statement);
}
- self->statement = (pysqlite_Statement*)pysqlite_cache_get(self->connection->statement_cache, func_args);
+ Py_XSETREF(self->statement,
+ (pysqlite_Statement *)pysqlite_cache_get(self->connection->statement_cache, func_args));
Py_DECREF(func_args);
if (!self->statement) {
}
if (self->statement->in_use) {
- Py_DECREF(self->statement);
- self->statement = PyObject_New(pysqlite_Statement, &pysqlite_StatementType);
+ Py_SETREF(self->statement,
+ PyObject_New(pysqlite_Statement, &pysqlite_StatementType));
if (!self->statement) {
goto error;
}
numcols = sqlite3_column_count(self->statement->st);
Py_END_ALLOW_THREADS
- Py_DECREF(self->description);
- self->description = PyTuple_New(numcols);
+ Py_SETREF(self->description, PyTuple_New(numcols));
if (!self->description) {
goto error;
}
if (!copy)
return 0;
- Py_DECREF(*object);
- *object = copy;
+ Py_SETREF(*object, copy);
return 1; /* success */
}
return -1;
#else
Py_INCREF(value);
- Py_DECREF(self->ctx);
- self->ctx = (PySSLContext *) value;
+ Py_SETREF(self->ctx, (PySSLContext *)value);
SSL_set_SSL_CTX(self->ssl, self->ctx->ctx);
#endif
} else {
static int
PySSL_set_owner(PySSLSocket *self, PyObject *value, void *c)
{
- Py_XDECREF(self->owner);
- self->owner = PyWeakref_NewRef(value, NULL);
+ Py_XSETREF(self->owner, PyWeakref_NewRef(value, NULL));
if (self->owner == NULL)
return -1;
return 0;
_PyTime_t timeout, deadline = 0;
int has_timeout;
+ if (!group_right_1 && len < 0) {
+ PyErr_SetString(PyExc_ValueError, "size should not be negative");
+ return NULL;
+ }
+
if (sock != NULL) {
if (((PyObject*)sock) == Py_None) {
_setSSLError("Underlying socket connection gone",
PySSLContext *self;
long options;
SSL_CTX *ctx = NULL;
+#if defined(SSL_MODE_RELEASE_BUFFERS)
+ unsigned long libver;
+#endif
PySSL_BEGIN_ALLOW_THREADS
if (proto_version == PY_SSL_VERSION_TLS1)
options |= SSL_OP_NO_SSLv3;
SSL_CTX_set_options(self->ctx, options);
+#if defined(SSL_MODE_RELEASE_BUFFERS)
+ /* Set SSL_MODE_RELEASE_BUFFERS. This potentially greatly reduces memory
+ usage for no cost at all. However, don't do this for OpenSSL versions
+ between 1.0.1 and 1.0.1h or 1.0.0 and 1.0.0m, which are affected by CVE
+ 2014-0198. I can't find exactly which beta fixed this CVE, so be
+ conservative and assume it wasn't fixed until release. We do this check
+ at runtime to avoid problems from the dynamic linker.
+ See #25672 for more on this. */
+ libver = SSLeay();
+ if (!(libver >= 0x10001000UL && libver < 0x1000108fUL) &&
+ !(libver >= 0x10000000UL && libver < 0x100000dfUL)) {
+ SSL_CTX_set_mode(self->ctx, SSL_MODE_RELEASE_BUFFERS);
+ }
+#endif
+
+
#ifndef OPENSSL_NO_ECDH
/* Allow automatic ECDH curve selection (on OpenSSL 1.0.2+), or use
prime256v1 by default. This is Apache mod_ssl's initialization
if (result == NULL) {
return NULL;
}
- hStore = CertOpenSystemStore((HCRYPTPROV)NULL, store_name);
+ hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, (HCRYPTPROV)NULL,
+ CERT_STORE_READONLY_FLAG | CERT_SYSTEM_STORE_LOCAL_MACHINE,
+ store_name);
if (hStore == NULL) {
Py_DECREF(result);
return PyErr_SetFromWindowsErr(GetLastError());
if (result == NULL) {
return NULL;
}
- hStore = CertOpenSystemStore((HCRYPTPROV)NULL, store_name);
+ hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, (HCRYPTPROV)NULL,
+ CERT_STORE_READONLY_FLAG | CERT_SYSTEM_STORE_LOCAL_MACHINE,
+ store_name);
if (hStore == NULL) {
Py_DECREF(result);
return PyErr_SetFromWindowsErr(GetLastError());
return -1;
}
- Py_CLEAR(soself->s_format);
- soself->s_format = o_format;
+ Py_XSETREF(soself->s_format, o_format);
ret = prepare_s(soself);
return ret;
"S.unpack(buffer) -> (v1, v2, ...)\n\
\n\
Return a tuple containing values unpacked according to the format\n\
-string S.format. Requires len(buffer) == S.size. See help(struct)\n\
-for more on format strings.");
+string S.format. The buffer's size in bytes must be S.size. See\n\
+help(struct) for more on format strings.");
static PyObject *
s_unpack(PyObject *self, PyObject *input)
"S.unpack_from(buffer, offset=0) -> (v1, v2, ...)\n\
\n\
Return a tuple containing values unpacked according to the format\n\
-string S.format. Requires len(buffer[offset:]) >= S.size. See\n\
-help(struct) for more on format strings.");
+string S.format. The buffer's size in bytes, minus offset, must be at\n\
+least S.size. See help(struct) for more on format strings.");
static PyObject *
s_unpack_from(PyObject *self, PyObject *args, PyObject *kwds)
Py_ssize_t size;
formatcode *code;
- size = sizeof(PyStructObject) + sizeof(formatcode);
+ size = _PyObject_SIZE(Py_TYPE(self)) + sizeof(formatcode);
for (code = self->s_codes; code->fmtdef != NULL; code++)
size += sizeof(formatcode);
return PyLong_FromSsize_t(size);
"unpack(fmt, buffer) -> (v1, v2, ...)\n\
\n\
Return a tuple containing values unpacked according to the format string\n\
-fmt. Requires len(buffer) == calcsize(fmt). See help(struct) for more\n\
-on format strings.");
+fmt. The buffer's size in bytes must be calcsize(fmt). See help(struct)\n\
+for more on format strings.");
static PyObject *
unpack(PyObject *self, PyObject *args)
"unpack_from(fmt, buffer, offset=0) -> (v1, v2, ...)\n\
\n\
Return a tuple containing values unpacked according to the format string\n\
-fmt. Requires len(buffer[offset:]) >= calcsize(fmt). See help(struct)\n\
-for more on format strings.");
+fmt. The buffer's size, minus offset, must be at least calcsize(fmt).\n\
+See help(struct) for more on format strings.");
static PyObject *
unpack_from(PyObject *self, PyObject *args, PyObject *kwds)
#endif /* ifdef HAVE_LONG_LONG */
+static PyObject *
+return_none(void *unused)
+{
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+raise_error(void *unused)
+{
+ PyErr_SetNone(PyExc_ValueError);
+ return NULL;
+}
+
+static int
+test_buildvalue_N_error(const char *fmt)
+{
+ PyObject *arg, *res;
+
+ arg = PyList_New(0);
+ if (arg == NULL) {
+ return -1;
+ }
+
+ Py_INCREF(arg);
+ res = Py_BuildValue(fmt, return_none, NULL, arg);
+ if (res == NULL) {
+ return -1;
+ }
+ Py_DECREF(res);
+ if (Py_REFCNT(arg) != 1) {
+ PyErr_Format(TestError, "test_buildvalue_N: "
+ "arg was not decrefed in successful "
+ "Py_BuildValue(\"%s\")", fmt);
+ return -1;
+ }
+
+ Py_INCREF(arg);
+ res = Py_BuildValue(fmt, raise_error, NULL, arg);
+ if (res != NULL || !PyErr_Occurred()) {
+ PyErr_Format(TestError, "test_buildvalue_N: "
+ "Py_BuildValue(\"%s\") didn't complain", fmt);
+ return -1;
+ }
+ PyErr_Clear();
+ if (Py_REFCNT(arg) != 1) {
+ PyErr_Format(TestError, "test_buildvalue_N: "
+ "arg was not decrefed in failed "
+ "Py_BuildValue(\"%s\")", fmt);
+ return -1;
+ }
+ Py_DECREF(arg);
+ return 0;
+}
+
+static PyObject *
+test_buildvalue_N(PyObject *self, PyObject *noargs)
+{
+ PyObject *arg, *res;
+
+ arg = PyList_New(0);
+ if (arg == NULL) {
+ return NULL;
+ }
+ Py_INCREF(arg);
+ res = Py_BuildValue("N", arg);
+ if (res == NULL) {
+ return NULL;
+ }
+ if (res != arg) {
+ return raiseTestError("test_buildvalue_N",
+ "Py_BuildValue(\"N\") returned wrong result");
+ }
+ if (Py_REFCNT(arg) != 2) {
+ return raiseTestError("test_buildvalue_N",
+ "arg was not decrefed in Py_BuildValue(\"N\")");
+ }
+ Py_DECREF(res);
+ Py_DECREF(arg);
+
+ if (test_buildvalue_N_error("O&N") < 0)
+ return NULL;
+ if (test_buildvalue_N_error("(O&N)") < 0)
+ return NULL;
+ if (test_buildvalue_N_error("[O&N]") < 0)
+ return NULL;
+ if (test_buildvalue_N_error("{O&N}") < 0)
+ return NULL;
+ if (test_buildvalue_N_error("{()O&(())N}") < 0)
+ return NULL;
+
+ Py_RETURN_NONE;
+}
+
+
+static PyObject *
+get_args(PyObject *self, PyObject *args)
+{
+ if (args == NULL) {
+ args = Py_None;
+ }
+ Py_INCREF(args);
+ return args;
+}
+
+static PyObject *
+get_kwargs(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+ if (kwargs == NULL) {
+ kwargs = Py_None;
+ }
+ Py_INCREF(kwargs);
+ return kwargs;
+}
+
/* Test tuple argument processing */
static PyObject *
getargs_tuple(PyObject *self, PyObject *args)
}
static PyObject *
+getargs_f(PyObject *self, PyObject *args)
+{
+ float f;
+ if (!PyArg_ParseTuple(args, "f", &f))
+ return NULL;
+ return PyFloat_FromDouble(f);
+}
+
+static PyObject *
+getargs_d(PyObject *self, PyObject *args)
+{
+ double d;
+ if (!PyArg_ParseTuple(args, "d", &d))
+ return NULL;
+ return PyFloat_FromDouble(d);
+}
+
+static PyObject *
+getargs_D(PyObject *self, PyObject *args)
+{
+ Py_complex cval;
+ if (!PyArg_ParseTuple(args, "D", &cval))
+ return NULL;
+ return PyComplex_FromCComplex(cval);
+}
+
+static PyObject *
+getargs_S(PyObject *self, PyObject *args)
+{
+ PyObject *obj;
+ if (!PyArg_ParseTuple(args, "S", &obj))
+ return NULL;
+ Py_INCREF(obj);
+ return obj;
+}
+
+static PyObject *
+getargs_Y(PyObject *self, PyObject *args)
+{
+ PyObject *obj;
+ if (!PyArg_ParseTuple(args, "Y", &obj))
+ return NULL;
+ Py_INCREF(obj);
+ return obj;
+}
+
+static PyObject *
+getargs_U(PyObject *self, PyObject *args)
+{
+ PyObject *obj;
+ if (!PyArg_ParseTuple(args, "U", &obj))
+ return NULL;
+ Py_INCREF(obj);
+ return obj;
+}
+
+static PyObject *
getargs_c(PyObject *self, PyObject *args)
{
char c;
if (!PyArg_ParseTuple(args, "c", &c))
return NULL;
- return PyBytes_FromStringAndSize(&c, 1);
+ return PyLong_FromLong((unsigned char)c);
+}
+
+static PyObject *
+getargs_C(PyObject *self, PyObject *args)
+{
+ int c;
+ if (!PyArg_ParseTuple(args, "C", &c))
+ return NULL;
+ return PyLong_FromLong(c);
}
static PyObject *
Py_RETURN_NONE;
}
+static PyObject *
+getargs_es(PyObject *self, PyObject *args)
+{
+ PyObject *arg, *result;
+ const char *encoding = NULL;
+ char *str;
+
+ if (!PyArg_ParseTuple(args, "O|s", &arg, &encoding))
+ return NULL;
+ if (!PyArg_Parse(arg, "es", encoding, &str))
+ return NULL;
+ result = PyBytes_FromString(str);
+ PyMem_Free(str);
+ return result;
+}
+
+static PyObject *
+getargs_et(PyObject *self, PyObject *args)
+{
+ PyObject *arg, *result;
+ const char *encoding = NULL;
+ char *str;
+
+ if (!PyArg_ParseTuple(args, "O|s", &arg, &encoding))
+ return NULL;
+ if (!PyArg_Parse(arg, "et", encoding, &str))
+ return NULL;
+ result = PyBytes_FromString(str);
+ PyMem_Free(str);
+ return result;
+}
+
+static PyObject *
+getargs_es_hash(PyObject *self, PyObject *args)
+{
+ PyObject *arg, *result;
+ const char *encoding = NULL;
+ PyByteArrayObject *buffer = NULL;
+ char *str = NULL;
+ Py_ssize_t size;
+
+ if (!PyArg_ParseTuple(args, "O|sY", &arg, &encoding, &buffer))
+ return NULL;
+ if (buffer != NULL) {
+ str = PyByteArray_AS_STRING(buffer);
+ size = PyByteArray_GET_SIZE(buffer);
+ }
+ if (!PyArg_Parse(arg, "es#", encoding, &str, &size))
+ return NULL;
+ result = PyBytes_FromStringAndSize(str, size);
+ if (buffer == NULL)
+ PyMem_Free(str);
+ return result;
+}
+
+static PyObject *
+getargs_et_hash(PyObject *self, PyObject *args)
+{
+ PyObject *arg, *result;
+ const char *encoding = NULL;
+ PyByteArrayObject *buffer = NULL;
+ char *str = NULL;
+ Py_ssize_t size;
+
+ if (!PyArg_ParseTuple(args, "O|sY", &arg, &encoding, &buffer))
+ return NULL;
+ if (buffer != NULL) {
+ str = PyByteArray_AS_STRING(buffer);
+ size = PyByteArray_GET_SIZE(buffer);
+ }
+ if (!PyArg_Parse(arg, "et#", encoding, &str, &size))
+ return NULL;
+ result = PyBytes_FromStringAndSize(str, size);
+ if (buffer == NULL)
+ PyMem_Free(str);
+ return result;
+}
+
/* Test the s and z codes for PyArg_ParseTuple.
*/
static PyObject *
{"test_pep3118_obsolete_write_locks", (PyCFunction)test_pep3118_obsolete_write_locks, METH_NOARGS},
#endif
{"getbuffer_with_null_view", getbuffer_with_null_view, METH_O},
+ {"test_buildvalue_N", test_buildvalue_N, METH_NOARGS},
+ {"get_args", get_args, METH_VARARGS},
+ {"get_kwargs", (PyCFunction)get_kwargs, METH_VARARGS|METH_KEYWORDS},
{"getargs_tuple", getargs_tuple, METH_VARARGS},
{"getargs_keywords", (PyCFunction)getargs_keywords,
METH_VARARGS|METH_KEYWORDS},
(PyCFunction)test_long_long_and_overflow, METH_NOARGS},
{"test_L_code", (PyCFunction)test_L_code, METH_NOARGS},
#endif
+ {"getargs_f", getargs_f, METH_VARARGS},
+ {"getargs_d", getargs_d, METH_VARARGS},
+ {"getargs_D", getargs_D, METH_VARARGS},
+ {"getargs_S", getargs_S, METH_VARARGS},
+ {"getargs_Y", getargs_Y, METH_VARARGS},
+ {"getargs_U", getargs_U, METH_VARARGS},
{"getargs_c", getargs_c, METH_VARARGS},
+ {"getargs_C", getargs_C, METH_VARARGS},
{"getargs_s", getargs_s, METH_VARARGS},
{"getargs_s_star", getargs_s_star, METH_VARARGS},
{"getargs_s_hash", getargs_s_hash, METH_VARARGS},
{"getargs_Z", getargs_Z, METH_VARARGS},
{"getargs_Z_hash", getargs_Z_hash, METH_VARARGS},
{"getargs_w_star", getargs_w_star, METH_VARARGS},
+ {"getargs_es", getargs_es, METH_VARARGS},
+ {"getargs_et", getargs_et, METH_VARARGS},
+ {"getargs_es_hash", getargs_es_hash, METH_VARARGS},
+ {"getargs_et_hash", getargs_et_hash, METH_VARARGS},
{"codec_incrementalencoder",
(PyCFunction)codec_incrementalencoder, METH_VARARGS},
{"codec_incrementaldecoder",
}
PyDoc_STRVAR(acquire_doc,
-"acquire([wait]) -> bool\n\
+"acquire(blocking=True, timeout=-1) -> bool\n\
(acquire_lock() is an obsolete synonym)\n\
\n\
Lock the lock. Without argument, this blocks if the lock is already\n\
"allocate_lock() -> lock object\n\
(allocate() is an obsolete synonym)\n\
\n\
-Create a new lock object. See help(LockType) for information about locks.");
+Create a new lock object. See help(type(threading.Lock())) for\n\
+information about locks.");
static PyObject *
thread_get_ident(PyObject *self)
PyDoc_STRVAR(lock_doc,
"A lock object is a synchronization primitive. To create a lock,\n\
-call the PyThread_allocate_lock() function. Methods are:\n\
+call threading.Lock(). Methods are:\n\
\n\
acquire() -- lock the lock, possibly blocking until it can be obtained\n\
release() -- unlock of the lock\n\
Py_DECREF(m);
return NULL;
}
+ ((PyTypeObject *)o)->tp_new = NULL;
if (PyModule_AddObject(m, "TkappType", o)) {
Py_DECREF(o);
Py_DECREF(m);
Py_DECREF(m);
return NULL;
}
+ ((PyTypeObject *)o)->tp_new = NULL;
if (PyModule_AddObject(m, "TkttType", o)) {
Py_DECREF(o);
Py_DECREF(m);
Py_DECREF(m);
return NULL;
}
+ ((PyTypeObject *)o)->tp_new = NULL;
if (PyModule_AddObject(m, "Tcl_Obj", o)) {
Py_DECREF(o);
Py_DECREF(m);
#endif
{
PyObject *filename;
- int lineno;
+ unsigned int lineno;
} frame_t;
typedef struct {
static void
set_reentrant(int reentrant)
{
- assert(!reentrant || !get_reentrant());
+ assert(reentrant != tracemalloc_reentrant);
tracemalloc_reentrant = reentrant;
}
#endif
PyCodeObject *code;
PyObject *filename;
_Py_hashtable_entry_t *entry;
+ int lineno;
frame->filename = unknown_filename;
- frame->lineno = PyFrame_GetLineNumber(pyframe);
- assert(frame->lineno >= 0);
- if (frame->lineno < 0)
- frame->lineno = 0;
+ lineno = PyFrame_GetLineNumber(pyframe);
+ if (lineno < 0)
+ lineno = 0;
+ frame->lineno = (unsigned int)lineno;
code = pyframe->f_code;
if (code == NULL) {
if (!PyUnicode_Check(filename)) {
#ifdef TRACE_DEBUG
- tracemalloc_error("filename is not an unicode string");
+ tracemalloc_error("filename is not a unicode string");
#endif
return;
}
for (pyframe = tstate->frame; pyframe != NULL; pyframe = pyframe->f_back) {
tracemalloc_get_frame(pyframe, &traceback->frames[traceback->nframe]);
assert(traceback->frames[traceback->nframe].filename != NULL);
- assert(traceback->frames[traceback->nframe].lineno >= 0);
traceback->nframe++;
if (traceback->nframe == tracemalloc_config.max_nframe)
break;
the caller, because realloc() may already have shrinked the
memory block and so removed bytes.
- This case is very unlikely: an hash entry has just been
+ This case is very unlikely: a hash entry has just been
released, so the hash table should have at least one free entry.
The GIL and the table lock ensures that only one thread is
assert(PyGILState_Check());
#endif
- /* Disable also reentrant calls to tracemalloc_malloc() to not add a new
- trace while we are clearing traces */
- assert(get_reentrant());
-
TABLES_LOCK();
_Py_hashtable_clear(tracemalloc_traces);
tracemalloc_traced_memory = 0;
tracemalloc_empty_traceback.frames[0].lineno = 0;
tracemalloc_empty_traceback.hash = traceback_hash(&tracemalloc_empty_traceback);
- /* Disable tracing allocations until hooks are installed. Set
- also the reentrant flag to detect bugs: fail with an assertion error
- if set_reentrant(1) is called while tracing is disabled. */
- set_reentrant(1);
-
tracemalloc_config.initialized = TRACEMALLOC_INITIALIZED;
return 0;
}
/* everything is ready: start tracing Python memory allocations */
tracemalloc_config.tracing = 1;
- set_reentrant(0);
return 0;
}
/* stop tracing Python memory allocations */
tracemalloc_config.tracing = 0;
- /* set the reentrant flag to detect bugs: fail with an assertion error if
- set_reentrant(1) is called while tracing is disabled. */
- set_reentrant(1);
-
/* unregister the hook on memory allocators */
#ifdef TRACE_RAW_MALLOC
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
tracemalloc_traceback = NULL;
}
-static PyObject*
-lineno_as_obj(int lineno)
-{
- if (lineno >= 0)
- return PyLong_FromLong(lineno);
- else
- Py_RETURN_NONE;
-}
-
PyDoc_STRVAR(tracemalloc_is_tracing_doc,
"is_tracing()->bool\n"
"\n"
Py_INCREF(frame->filename);
PyTuple_SET_ITEM(frame_obj, 0, frame->filename);
- assert(frame->lineno >= 0);
- lineno_obj = lineno_as_obj(frame->lineno);
+ lineno_obj = PyLong_FromUnsignedLong(frame->lineno);
if (lineno_obj == NULL) {
Py_DECREF(frame_obj);
return NULL;
/*[clinic end generated code: output=d8e1c61ebbe3eaed input=805586565bf2b3c6]*/
{
Py_ssize_t res;
- res = sizeof(arrayobject) + self->allocated * self->ob_descr->itemsize;
+ res = _PyObject_SIZE(Py_TYPE(self)) + self->allocated * self->ob_descr->itemsize;
return PyLong_FromSsize_t(res);
}
* that fits better. This may result in an array with narrower
* or wider elements.
*
- * For example, if a 32-bit machine pickles a L-code array of
+ * For example, if a 32-bit machine pickles an L-code array of
* unsigned longs, then the array will be unpickled by 64-bit
* machine as an I-code array of unsigned ints.
*
*/
#define BIAS 0x84 /* define the add-in bias for 16 bit samples */
#define CLIP 32635
-#define SIGN_BIT (0x80) /* Sign bit for a A-law byte. */
+#define SIGN_BIT (0x80) /* Sign bit for an A-law byte. */
#define QUANT_MASK (0xf) /* Quantization field mask. */
#define SEG_SHIFT (4) /* Left shift for segment number. */
#define SEG_MASK (0x70) /* Segment field mask. */
};
/*
- * linear2alaw() accepts an 13-bit signed integer and encodes it as A-law data
+ * linear2alaw() accepts a 13-bit signed integer and encodes it as A-law data
* stored in an unsigned char. This function should only be called with
* the data shifted such that it only contains information in the lower
* 13-bits.
min = 0;
max = haystacksize;
- for (pos = haystacksize >> 1; min != max; pos = (min + max) >> 1)
+ for (pos = haystacksize >> 1; min != max; pos = (min + max) >> 1) {
if (value < haystack[pos].uniseq) {
- if (max == pos) break;
- else max = pos;
+ if (max != pos) {
+ max = pos;
+ continue;
+ }
}
else if (value > haystack[pos].uniseq) {
- if (min == pos) break;
- else min = pos;
+ if (min != pos) {
+ min = pos;
+ continue;
+ }
}
- else
- break;
+ break;
+ }
- if (value == haystack[pos].uniseq)
- return haystack[pos].code;
- else
- return DBCINV;
+ if (value == haystack[pos].uniseq) {
+ return haystack[pos].code;
+ }
+ return DBCINV;
}
#endif
ctx->errors, final ? MBENC_FLUSH | MBENC_RESET : 0);
if (r == NULL) {
/* recover the original pending buffer */
- Py_CLEAR(ctx->pending);
- ctx->pending = origpending;
+ Py_XSETREF(ctx->pending, origpending);
origpending = NULL;
goto errorexit;
}
"other custom object that meets this interface.\n"
"\n"
"Optional keyword arguments are *fix_imports*, *encoding* and *errors*,\n"
-"which are used to control compatiblity support for pickle stream\n"
+"which are used to control compatibility support for pickle stream\n"
"generated by Python 2. If *fix_imports* is True, pickle will try to\n"
"map the old Python 2 names to the new names used in Python 3. The\n"
"*encoding* and *errors* tell pickle how to decode 8-bit string\n"
"other custom object that meets this interface.\n"
"\n"
"Optional keyword arguments are *fix_imports*, *encoding* and *errors*,\n"
-"which are used to control compatiblity support for pickle stream\n"
+"which are used to control compatibility support for pickle stream\n"
"generated by Python 2. If *fix_imports* is True, pickle will try to\n"
"map the old Python 2 names to the new names used in Python 3. The\n"
"*encoding* and *errors* tell pickle how to decode 8-bit string\n"
"representation are ignored.\n"
"\n"
"Optional keyword arguments are *fix_imports*, *encoding* and *errors*,\n"
-"which are used to control compatiblity support for pickle stream\n"
+"which are used to control compatibility support for pickle stream\n"
"generated by Python 2. If *fix_imports* is True, pickle will try to\n"
"map the old Python 2 names to the new names used in Python 3. The\n"
"*encoding* and *errors* tell pickle how to decode 8-bit string\n"
exit:
return return_value;
}
-/*[clinic end generated code: output=aecd61660d1cf31d input=a9049054013a1b77]*/
+/*[clinic end generated code: output=a7169d4fbbeef827 input=a9049054013a1b77]*/
"\n"
"When operation is LOCK_SH or LOCK_EX, it can also be bitwise ORed with\n"
"LOCK_NB to avoid blocking on lock acquisition. If LOCK_NB is used and the\n"
-"lock cannot be acquired, an IOError will be raised and the exception will\n"
+"lock cannot be acquired, an OSError will be raised and the exception will\n"
"have an errno attribute set to EACCES or EAGAIN (depending on the operating\n"
"system -- for portability, check for either value).\n"
"\n"
exit:
return return_value;
}
-/*[clinic end generated code: output=92963b631d00f0fe input=a9049054013a1b77]*/
+/*[clinic end generated code: output=b7d6e8fc2ad09c48 input=a9049054013a1b77]*/
" data\n"
" Compressed data.\n"
" wbits\n"
-" The window buffer size.\n"
+" The window buffer size and container format.\n"
" bufsize\n"
" The initial output buffer size.");
"Return a compressor object.\n"
"\n"
" level\n"
-" The compression level (an integer in the range 0-9; default is 6).\n"
-" Higher compression levels are slower, but produce smaller results.\n"
+" The compression level (an integer in the range 0-9 or -1; default is\n"
+" currently equivalent to 6). Higher compression levels are slower,\n"
+" but produce smaller results.\n"
" method\n"
" The compression algorithm. If given, this must be DEFLATED.\n"
" wbits\n"
-" The base two logarithm of the window size (range: 8..15).\n"
+" +9 to +15: The base-two logarithm of the window size. Include a zlib\n"
+" container.\n"
+" -9 to -15: Generate a raw stream.\n"
+" +25 to +31: Include a gzip container.\n"
" memLevel\n"
" Controls the amount of memory used for internal compression state.\n"
" Valid values range from 1 to 9. Higher values result in higher memory\n"
"Return a decompressor object.\n"
"\n"
" wbits\n"
-" The window buffer size.\n"
+" The window buffer size and container format.\n"
" zdict\n"
" The predefined compression dictionary. This must be the same\n"
" dictionary as used by the compressor that produced the input data.");
#ifndef ZLIB_COMPRESS_COPY_METHODDEF
#define ZLIB_COMPRESS_COPY_METHODDEF
#endif /* !defined(ZLIB_COMPRESS_COPY_METHODDEF) */
-/*[clinic end generated code: output=7734aec079550bc8 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=f31627b314a7bd2f input=a9049054013a1b77]*/
self.declare(data)
data.return_conversion.append("""
PyFPE_END_PROTECT(_return_value);
-if (errno == EDOM) {{
+if (errno == EDOM) {
PyErr_SetString(PyExc_ValueError, "math domain error");
goto exit;
-}}
-else if (errno == ERANGE) {{
+}
+else if (errno == ERANGE) {
PyErr_SetString(PyExc_OverflowError, "math range error");
goto exit;
-}}
-else {{
+}
+else {
return_value = PyComplex_FromCComplex(_return_value);
-}}
+}
""".strip())
[python start generated code]*/
-/*[python end generated code: output=da39a3ee5e6b4b0d input=231019039a6fbb9a]*/
+/*[python end generated code: output=da39a3ee5e6b4b0d input=345daa075b1028e7]*/
#if (FLT_RADIX != 2 && FLT_RADIX != 16)
#error "Modules/cmathmodule.c expects FLT_RADIX to be 2 or 16"
*/
#define XML_MAJOR_VERSION 2
#define XML_MINOR_VERSION 1
-#define XML_MICRO_VERSION 0
+#define XML_MICRO_VERSION 1
#ifdef __cplusplus
}
else if (bufferPtr == bufferEnd) {
const char *end;
int nLeftOver;
- enum XML_Error result;
+ enum XML_Status result;
parseEndByteIndex += len;
positionPtr = s;
ps_finalBuffer = (XML_Bool)isFinal;
void * XMLCALL
XML_GetBuffer(XML_Parser parser, int len)
{
+ if (len < 0) {
+ errorCode = XML_ERROR_NO_MEMORY;
+ return NULL;
+ }
switch (ps_parsing) {
case XML_SUSPENDED:
errorCode = XML_ERROR_SUSPENDED;
}
if (len > bufferLim - bufferEnd) {
- /* FIXME avoid integer overflow */
+#ifdef XML_CONTEXT_BYTES
+ int keep;
+#endif
int neededSize = len + (int)(bufferEnd - bufferPtr);
+ if (neededSize < 0) {
+ errorCode = XML_ERROR_NO_MEMORY;
+ return NULL;
+ }
#ifdef XML_CONTEXT_BYTES
- int keep = (int)(bufferPtr - buffer);
+ keep = (int)(bufferPtr - buffer);
if (keep > XML_CONTEXT_BYTES)
keep = XML_CONTEXT_BYTES;
bufferSize = INIT_BUFFER_SIZE;
do {
bufferSize *= 2;
- } while (bufferSize < neededSize);
+ } while (bufferSize < neededSize && bufferSize > 0);
+ if (bufferSize <= 0) {
+ errorCode = XML_ERROR_NO_MEMORY;
+ return NULL;
+ }
newBuf = (char *)MALLOC(bufferSize);
if (newBuf == 0) {
errorCode = XML_ERROR_NO_MEMORY;
unsigned long uriHash = hash_secret_salt;
((XML_Char *)s)[-1] = 0; /* clear flag */
id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, s, 0);
+ if (!id || !id->prefix)
+ return XML_ERROR_NO_MEMORY;
b = id->prefix->binding;
if (!b)
return XML_ERROR_UNBOUND_PREFIX;
return NULL;
id->prefix = (PREFIX *)lookup(parser, &dtd->prefixes, poolStart(&dtd->pool),
sizeof(PREFIX));
+ if (!id->prefix)
+ return NULL;
if (id->prefix->name == poolStart(&dtd->pool))
poolFinish(&dtd->pool);
else
if (ptr[0] == '\0') {
/* 0 isn't a legal data character. Furthermore a document
entity can only start with ASCII characters. So the only
- way this can fail to be big-endian UTF-16 is if it is an
+ way this can fail to be big-endian UTF-16 if it it's an
external parsed general entity that's labelled as
UTF-16LE.
*/
if (tstate == NULL)
return NULL;
- Py_XDECREF(fatal_error.file);
Py_XINCREF(file);
- fatal_error.file = file;
+ Py_XSETREF(fatal_error.file, file);
fatal_error.fd = fd;
fatal_error.all_threads = all_threads;
fatal_error.interp = tstate->interp;
assert(st == PY_LOCK_FAILURE);
/* get the thread holding the GIL, NULL if no thread hold the GIL */
- current = (PyThreadState*)_Py_atomic_load_relaxed(&_PyThreadState_Current);
+ current = _PyThreadState_UncheckedGet();
_Py_write_noraise(thread.fd, thread.header, (int)thread.header_len);
/* Cancel previous thread, if running */
cancel_dump_traceback_later();
- Py_XDECREF(thread.file);
Py_XINCREF(file);
- thread.file = file;
+ Py_XSETREF(thread.file, file);
thread.fd = fd;
thread.timeout_us = timeout_us;
thread.repeat = repeat;
user->previous = previous;
}
- Py_XDECREF(user->file);
Py_XINCREF(file);
- user->file = file;
+ Py_XSETREF(user->file, file);
user->fd = fd;
user->all_threads = all_threads;
user->chain = chain;
faulthandler_fatal_error_py(PyObject *self, PyObject *args)
{
char *message;
- if (!PyArg_ParseTuple(args, "y:fatal_error", &message))
+ int release_gil = 0;
+ if (!PyArg_ParseTuple(args, "y|i:fatal_error", &message, &release_gil))
return NULL;
faulthandler_suppress_crash_report();
- Py_FatalError(message);
+ if (release_gil) {
+ Py_BEGIN_ALLOW_THREADS
+ Py_FatalError(message);
+ Py_END_ALLOW_THREADS
+ }
+ else {
+ Py_FatalError(message);
+ }
Py_RETURN_NONE;
}
{"register",
(PyCFunction)faulthandler_register_py, METH_VARARGS|METH_KEYWORDS,
PyDoc_STR("register(signum, file=sys.stderr, all_threads=True, chain=False): "
- "register an handler for the signal 'signum': dump the "
+ "register a handler for the signal 'signum': dump the "
"traceback of the current thread, or of all threads if "
"all_threads is True, into file")},
{"unregister",
When operation is LOCK_SH or LOCK_EX, it can also be bitwise ORed with
LOCK_NB to avoid blocking on lock acquisition. If LOCK_NB is used and the
-lock cannot be acquired, an IOError will be raised and the exception will
+lock cannot be acquired, an OSError will be raised and the exception will
have an errno attribute set to EACCES or EAGAIN (depending on the operating
system -- for portability, check for either value).
static PyObject *
fcntl_lockf_impl(PyModuleDef *module, int fd, int code, PyObject *lenobj,
PyObject *startobj, int whence)
-/*[clinic end generated code: output=31af35eba08b9af7 input=9c594391de821f24]*/
+/*[clinic end generated code: output=31af35eba08b9af7 input=3a5dc01b04371f1a]*/
{
int ret;
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
- * GAI_ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
- * FOR GAI_ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON GAI_ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN GAI_ANY WAY
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#endif
-#ifndef VERSION
-#define VERSION "2.1"
-#endif
-
-#ifndef VPATH
-#define VPATH "."
-#endif
-
-#ifndef PREFIX
-# define PREFIX "/usr/local"
-#endif
-
-#ifndef EXEC_PREFIX
-#define EXEC_PREFIX PREFIX
-#endif
-
-#ifndef PYTHONPATH
-#define PYTHONPATH PREFIX "/lib/python" VERSION ":" \
- EXEC_PREFIX "/lib/python" VERSION "/lib-dynload"
+#if !defined(PREFIX) || !defined(EXEC_PREFIX) || !defined(VERSION) || !defined(VPATH)
+#error "PREFIX, EXEC_PREFIX, VERSION, and VPATH must be constant defined"
#endif
#ifndef LANDMARK
/* Itertools module written and maintained
by Raymond D. Hettinger <python@rcn.com>
- Copyright (c) 2003-2013 Python Software Foundation.
- All rights reserved.
*/
PyObject *currkey, *currvalue, *tgtkey;
if (!PyArg_ParseTuple(state, "OOO", &currkey, &currvalue, &tgtkey))
return NULL;
- Py_CLEAR(lz->currkey);
- lz->currkey = currkey;
- Py_INCREF(lz->currkey);
- Py_CLEAR(lz->currvalue);
- lz->currvalue = currvalue;
- Py_INCREF(lz->currvalue);
- Py_CLEAR(lz->tgtkey);
- lz->tgtkey = tgtkey;
- Py_INCREF(lz->tgtkey);
+ Py_INCREF(currkey);
+ Py_XSETREF(lz->currkey, currkey);
+ Py_INCREF(currvalue);
+ Py_XSETREF(lz->currvalue, currvalue);
+ Py_INCREF(tgtkey);
+ Py_XSETREF(lz->tgtkey, tgtkey);
Py_RETURN_NONE;
}
link = teedataobject_jumplink(to->dataobj);
if (link == NULL)
return NULL;
- Py_DECREF(to->dataobj);
- to->dataobj = (teedataobject *)link;
+ Py_SETREF(to->dataobj, (teedataobject *)link);
to->index = 0;
}
value = teedataobject_getitem(to->dataobj, to->index);
PyErr_SetString(PyExc_ValueError, "Index out of range");
return NULL;
}
- Py_CLEAR(to->dataobj);
- to->dataobj = tdo;
- Py_INCREF(to->dataobj);
+ Py_INCREF(tdo);
+ Py_XSETREF(to->dataobj, tdo);
to->index = index;
Py_RETURN_NONE;
}
int firstpass;
if (!PyArg_ParseTuple(state, "Oi", &saved, &firstpass))
return NULL;
- Py_CLEAR(lz->saved);
- lz->saved = saved;
- Py_XINCREF(lz->saved);
+ Py_XINCREF(saved);
+ Py_XSETREF(lz->saved, saved);
lz->firstpass = firstpass != 0;
Py_RETURN_NONE;
}
if (! PyArg_ParseTuple(state, "O|O", &source, &active))
return NULL;
- Py_CLEAR(lz->source);
- lz->source = source;
- Py_INCREF(lz->source);
- Py_CLEAR(lz->active);
- lz->active = active;
- Py_XINCREF(lz->active);
+ Py_INCREF(source);
+ Py_XSETREF(lz->source, source);
+ Py_XINCREF(active);
+ Py_XSETREF(lz->active, active);
Py_RETURN_NONE;
}
{
Py_ssize_t res;
- res = sizeof(productobject);
+ res = _PyObject_SIZE(Py_TYPE(lz));
res += PyTuple_GET_SIZE(lz->pools) * sizeof(Py_ssize_t);
return PyLong_FromSsize_t(res);
}
Py_INCREF(element);
PyTuple_SET_ITEM(result, i, element);
}
- Py_CLEAR(lz->result);
- lz->result = result;
+ Py_XSETREF(lz->result, result);
Py_RETURN_NONE;
}
{
Py_ssize_t res;
- res = sizeof(combinationsobject);
+ res = _PyObject_SIZE(Py_TYPE(co));
res += co->r * sizeof(Py_ssize_t);
return PyLong_FromSsize_t(res);
}
PyTuple_SET_ITEM(result, i, element);
}
- Py_CLEAR(lz->result);
- lz->result = result;
+ Py_XSETREF(lz->result, result);
Py_RETURN_NONE;
}
{
Py_ssize_t res;
- res = sizeof(cwrobject);
+ res = _PyObject_SIZE(Py_TYPE(co));
res += co->r * sizeof(Py_ssize_t);
return PyLong_FromSsize_t(res);
}
Py_INCREF(element);
PyTuple_SET_ITEM(result, i, element);
}
- Py_CLEAR(lz->result);
- lz->result = result;
+ Py_XSETREF(lz->result, result);
Py_RETURN_NONE;
}
{
Py_ssize_t res;
- res = sizeof(permutationsobject);
+ res = _PyObject_SIZE(Py_TYPE(po));
res += PyTuple_GET_SIZE(po->pool) * sizeof(Py_ssize_t);
res += po->r * sizeof(Py_ssize_t);
return PyLong_FromSsize_t(res);
Py_INCREF(element);
PyTuple_SET_ITEM(result, i, element);
}
- Py_CLEAR(po->result);
- po->result = result;
+ Py_XSETREF(po->result, result);
Py_RETURN_NONE;
}
static PyObject *
accumulate_reduce(accumulateobject *lz)
{
+ if (lz->total == Py_None) {
+ PyObject *it;
+
+ if (PyType_Ready(&chain_type) < 0)
+ return NULL;
+ if (PyType_Ready(&islice_type) < 0)
+ return NULL;
+ it = PyObject_CallFunction((PyObject *)&chain_type, "(O)O",
+ lz->total, lz->it);
+ if (it == NULL)
+ return NULL;
+ it = PyObject_CallFunction((PyObject *)Py_TYPE(lz), "NO",
+ it, lz->binop ? lz->binop : Py_None);
+ if (it == NULL)
+ return NULL;
+ return Py_BuildValue("O(NiO)", &islice_type, it, 1, Py_None);
+ }
return Py_BuildValue("O(OO)O", Py_TYPE(lz),
lz->it, lz->binop?lz->binop:Py_None,
lz->total?lz->total:Py_None);
static PyObject *
accumulate_setstate(accumulateobject *lz, PyObject *state)
{
- Py_CLEAR(lz->total);
- lz->total = state;
- Py_INCREF(lz->total);
+ Py_INCREF(state);
+ Py_XSETREF(lz->total, state);
Py_RETURN_NONE;
}
static PyObject *
zip_longest_setstate(ziplongestobject *lz, PyObject *state)
{
- Py_CLEAR(lz->fillvalue);
- lz->fillvalue = state;
- Py_INCREF(lz->fillvalue);
+ Py_INCREF(state);
+ Py_XSETREF(lz->fillvalue, state);
Py_RETURN_NONE;
}
PyDoc_STRVAR(zip_longest_doc,
"zip_longest(iter1 [,iter2 [...]], [fillvalue=None]) --> zip_longest object\n\
\n\
-Return an zip_longest object whose .__next__() method returns a tuple where\n\
+Return a zip_longest object whose .__next__() method returns a tuple where\n\
the i-th element comes from the i-th iterable argument. The .__next__()\n\
method continues until the longest iterable in the argument sequence\n\
is exhausted and then it raises StopIteration. When the shorter iterables\n\
#
# ARGUMENTS: Same as for "ld". The following arguments are processed
# or supplied by this script (those marked with an asterisk
-# can be overriden from command line):
+# can be overridden from command line):
#
# Argument Default value
# (*) -o [OutputFileName] -o shr.o
fi
# Default import file for Python
-# Can be overriden by providing a -bI: argument.
+# Can be overridden by providing a -bI: argument.
impfile="./python.exp"
# Parse arguments
fi
# Default entry symbol for Python modules = init[modulename]
-# Can be overriden by providing a -e argument.
+# Can be overridden by providing a -e argument.
if test -z "$entry"; then
entry=PyInit_`echo $filename | sed "s/module.*//"`
fi
arg ...: arguments passed to program in sys.argv[1:]\n\n\
Other environment variables:\n\
PYTHONSTARTUP: file executed on interactive startup (no default)\n\
-PYTHONPATH : '%c'-separated list of directories prefixed to the\n\
+PYTHONPATH : '%lc'-separated list of directories prefixed to the\n\
default module search path. The result is sys.path.\n\
";
static char *usage_5 =
-"PYTHONHOME : alternate <prefix> directory (or <prefix>%c<exec_prefix>).\n"
+"PYTHONHOME : alternate <prefix> directory (or <prefix>%lc<exec_prefix>).\n"
" The default module search path uses %s.\n"
"PYTHONCASEOK : ignore case in 'import' statements (Windows).\n"
"PYTHONIOENCODING: Encoding[:errors] used for stdin/stdout/stderr.\n"
fputs(usage_1, f);
fputs(usage_2, f);
fputs(usage_3, f);
- fprintf(f, usage_4, DELIM);
- fprintf(f, usage_5, DELIM, PYTHONHOMEHELP);
+ fprintf(f, usage_4, (wint_t)DELIM);
+ fprintf(f, usage_5, (wint_t)DELIM, PYTHONHOMEHELP);
fputs(usage_6, f);
}
return exitcode;
Implementations of the error function erf(x) and the complementary error
function erfc(x).
- Method: following 'Numerical Recipes' by Flannery, Press et. al. (2nd ed.,
- Cambridge University Press), we use a series approximation for erf for
- small x, and a continued fraction approximation for erfc(x) for larger x;
+ Method: we use a series approximation for erf for small x, and a continued
+ fraction approximation for erfc(x) for larger x;
combined with the relations erf(-x) = -erf(x) and erfc(x) = 1.0 - erf(x),
this gives us erf(x) and erfc(x) for all x.
}
PyDoc_STRVAR(math_ceil_doc,
- "ceil(x)\n\nReturn the ceiling of x as an int.\n"
- "This is the smallest integral value >= x.");
+ "ceil(x)\n\nReturn the ceiling of x as an Integral.\n"
+ "This is the smallest integer >= x.");
FUNC2(copysign, copysign,
"copysign(x, y)\n\nReturn a float with the magnitude (absolute value) "
}
PyDoc_STRVAR(math_floor_doc,
- "floor(x)\n\nReturn the floor of x as an int.\n"
- "This is the largest integral value <= x.");
+ "floor(x)\n\nReturn the floor of x as an Integral.\n"
+ "This is the largest integer <= x.");
FUNC1A(gamma, m_tgamma,
"gamma(x)\n\nGamma function at x.")
}
PyDoc_STRVAR(math_isclose_doc,
-"is_close(a, b, *, rel_tol=1e-09, abs_tol=0.0) -> bool\n"
+"isclose(a, b, *, rel_tol=1e-09, abs_tol=0.0) -> bool\n"
"\n"
"Determine whether two floating point numbers are close in value.\n"
"\n"
{
Py_ssize_t res;
- res = sizeof(mmap_object);
+ res = _PyObject_SIZE(Py_TYPE(self));
if (self->tagname)
res += strlen(self->tagname) + 1;
return PyLong_FromSsize_t(res);
# define T_POINTER T_ULONGLONG
#endif
+/* Compatibility with Python 3.3 */
+#if PY_VERSION_HEX < 0x03040000
+# define PyMem_RawMalloc PyMem_Malloc
+# define PyMem_RawFree PyMem_Free
+#endif
+
#define F_HANDLE F_POINTER
#define F_ULONG_PTR F_POINTER
#define F_DWORD "k"
PostQueuedCompletionStatus(p->CompletionPort, TimerOrWaitFired,
0, p->Overlapped);
/* ignore possible error! */
- PyMem_Free(p);
+ PyMem_RawFree(p);
}
PyDoc_STRVAR(
&Milliseconds))
return NULL;
- pdata = PyMem_Malloc(sizeof(struct PostCallbackData));
+ /* Use PyMem_RawMalloc() rather than PyMem_Malloc(), since
+ PostToQueueCallback() will call PyMem_Free() from a new C thread
+ which doesn't hold the GIL. */
+ pdata = PyMem_RawMalloc(sizeof(struct PostCallbackData));
if (pdata == NULL)
return SetFromWindowsErr(0);
pdata, Milliseconds,
WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE))
{
- PyMem_Free(pdata);
+ PyMem_RawFree(pdata);
return SetFromWindowsErr(0);
}
{
Py_ssize_t res;
- res = sizeof(PyST_Object) + _PyNode_SizeOf(st->st_node);
+ res = _PyObject_SIZE(Py_TYPE(st)) + _PyNode_SizeOf(st->st_node);
return PyLong_FromSsize_t(res);
}
#include "winreparse.h"
#endif
+#include <stdio.h> /* needed for ctermid() */
+
#ifdef __cplusplus
extern "C" {
#endif
static BOOL __stdcall
win32_wchdir(LPCWSTR path)
{
- wchar_t _new_path[MAX_PATH], *new_path = _new_path;
+ wchar_t path_buf[MAX_PATH], *new_path = path_buf;
int result;
wchar_t env[4] = L"=x:";
if(!SetCurrentDirectoryW(path))
return FALSE;
- result = GetCurrentDirectoryW(Py_ARRAY_LENGTH(new_path), new_path);
+ result = GetCurrentDirectoryW(Py_ARRAY_LENGTH(path_buf), new_path);
if (!result)
return FALSE;
- if (result > Py_ARRAY_LENGTH(new_path)) {
+ if (result > Py_ARRAY_LENGTH(path_buf)) {
new_path = PyMem_RawMalloc(result * sizeof(wchar_t));
if (!new_path) {
SetLastError(ERROR_OUTOFMEMORY);
return TRUE;
env[1] = new_path[0];
result = SetEnvironmentVariableW(env, new_path);
- if (new_path != _new_path)
+ if (new_path != path_buf)
PyMem_RawFree(new_path);
return result;
}
static void
ScandirIterator_close(ScandirIterator *iterator)
{
- if (iterator->handle == INVALID_HANDLE_VALUE)
+ HANDLE handle = iterator->handle;
+
+ if (handle == INVALID_HANDLE_VALUE)
return;
+ iterator->handle = INVALID_HANDLE_VALUE;
Py_BEGIN_ALLOW_THREADS
- FindClose(iterator->handle);
+ FindClose(handle);
Py_END_ALLOW_THREADS
- iterator->handle = INVALID_HANDLE_VALUE;
}
static PyObject *
{
WIN32_FIND_DATAW *file_data = &iterator->file_data;
BOOL success;
+ PyObject *entry;
/* Happens if the iterator is iterated twice */
- if (iterator->handle == INVALID_HANDLE_VALUE) {
- PyErr_SetNone(PyExc_StopIteration);
+ if (iterator->handle == INVALID_HANDLE_VALUE)
return NULL;
- }
while (1) {
if (!iterator->first_time) {
success = FindNextFileW(iterator->handle, file_data);
Py_END_ALLOW_THREADS
if (!success) {
+ /* Error or no more files */
if (GetLastError() != ERROR_NO_MORE_FILES)
- return path_error(&iterator->path);
- /* No more files found in directory, stop iterating */
+ path_error(&iterator->path);
break;
}
}
/* Skip over . and .. */
if (wcscmp(file_data->cFileName, L".") != 0 &&
- wcscmp(file_data->cFileName, L"..") != 0)
- return DirEntry_from_find_data(&iterator->path, file_data);
+ wcscmp(file_data->cFileName, L"..") != 0) {
+ entry = DirEntry_from_find_data(&iterator->path, file_data);
+ if (!entry)
+ break;
+ return entry;
+ }
/* Loop till we get a non-dot directory or finish iterating */
}
+ /* Error or no more files */
ScandirIterator_close(iterator);
-
- PyErr_SetNone(PyExc_StopIteration);
return NULL;
}
static void
ScandirIterator_close(ScandirIterator *iterator)
{
- if (!iterator->dirp)
+ DIR *dirp = iterator->dirp;
+
+ if (!dirp)
return;
+ iterator->dirp = NULL;
Py_BEGIN_ALLOW_THREADS
- closedir(iterator->dirp);
+ closedir(dirp);
Py_END_ALLOW_THREADS
- iterator->dirp = NULL;
return;
}
struct dirent *direntp;
Py_ssize_t name_len;
int is_dot;
+ PyObject *entry;
/* Happens if the iterator is iterated twice */
- if (!iterator->dirp) {
- PyErr_SetNone(PyExc_StopIteration);
+ if (!iterator->dirp)
return NULL;
- }
while (1) {
errno = 0;
Py_END_ALLOW_THREADS
if (!direntp) {
+ /* Error or no more files */
if (errno != 0)
- return path_error(&iterator->path);
- /* No more files found in directory, stop iterating */
+ path_error(&iterator->path);
break;
}
is_dot = direntp->d_name[0] == '.' &&
(name_len == 1 || (direntp->d_name[1] == '.' && name_len == 2));
if (!is_dot) {
- return DirEntry_from_posix_info(&iterator->path, direntp->d_name,
+ entry = DirEntry_from_posix_info(&iterator->path, direntp->d_name,
name_len, direntp->d_ino
#ifdef HAVE_DIRENT_D_TYPE
, direntp->d_type
#endif
);
+ if (!entry)
+ break;
+ return entry;
}
/* Loop till we get a non-dot directory or finish iterating */
}
+ /* Error or no more files */
ScandirIterator_close(iterator);
-
- PyErr_SetNone(PyExc_StopIteration);
return NULL;
}
static char *completer_word_break_characters;
typedef struct {
+ /* Specify hook functions in Python */
PyObject *completion_display_matches_hook;
PyObject *startup_hook;
PyObject *pre_input_hook;
- PyObject *completer;
+
+ PyObject *completer; /* Specify a word completer in Python */
PyObject *begidx;
PyObject *endidx;
} readlinestate;
PyDoc_STRVAR(doc_parse_and_bind,
"parse_and_bind(string) -> None\n\
-Parse and execute single line of a readline init file.");
+Execute the init line provided in the string argument.");
/* Exported function to parse a readline init file */
PyDoc_STRVAR(doc_read_init_file,
"read_init_file([filename]) -> None\n\
-Parse a readline initialization file.\n\
+Execute a readline initialization file.\n\
The default filename is the last filename used.");
PyDoc_STRVAR(doc_append_history_file,
"append_history_file(nelements[, filename]) -> None\n\
-Append the last nelements of the history list to file.\n\
+Append the last nelements items of the history list to file.\n\
The default filename is ~/.history.");
#endif
PyDoc_STRVAR(set_history_length_doc,
"set_history_length(length) -> None\n\
-set the maximal number of items which will be written to\n\
+set the maximal number of lines which will be written to\n\
the history file. A negative length is used to inhibit\n\
history truncation.");
PyDoc_STRVAR(get_history_length_doc,
"get_history_length() -> int\n\
-return the maximum number of items that will be written to\n\
+return the maximum number of lines that will be written to\n\
the history file.");
}
-/* Exported functions to specify hook functions in Python */
-
-
-#ifdef HAVE_RL_PRE_INPUT_HOOK
-
-#endif
-
static PyObject *
set_completion_display_matches_hook(PyObject *self, PyObject *args)
{
PyDoc_STRVAR(doc_set_startup_hook,
"set_startup_hook([function]) -> None\n\
-Set or remove the startup_hook function.\n\
+Set or remove the function invoked by the rl_startup_hook callback.\n\
The function is called with no arguments just\n\
before readline prints the first prompt.");
PyDoc_STRVAR(doc_set_pre_input_hook,
"set_pre_input_hook([function]) -> None\n\
-Set or remove the pre_input_hook function.\n\
+Set or remove the function invoked by the rl_pre_input_hook callback.\n\
The function is called with no arguments after the first prompt\n\
has been printed and just before readline starts reading input\n\
characters.");
#endif
-/* Exported function to specify a word completer in Python */
-
-
-
-
-
-
-
/* Get the completion type for the scope of the tab-completion */
static PyObject *
get_completion_type(PyObject *self, PyObject *noarg)
PyDoc_STRVAR(doc_get_begidx,
"get_begidx() -> int\n\
-get the beginning index of the readline tab-completion scope");
+get the beginning index of the completion scope");
/* Get the ending index for the scope of the tab-completion */
PyDoc_STRVAR(doc_get_endidx,
"get_endidx() -> int\n\
-get the ending index of the readline tab-completion scope");
+get the ending index of the completion scope");
/* Set the tab-completion word-delimiters that readline uses */
PyDoc_STRVAR(doc_set_completer_delims,
"set_completer_delims(string) -> None\n\
-set the readline word delimiters for tab-completion");
+set the word delimiters for completion");
/* _py_free_history_entry: Utility function to free a history entry. */
int entry_number;
HIST_ENTRY *entry;
- if (!PyArg_ParseTuple(args, "i:remove_history", &entry_number))
+ if (!PyArg_ParseTuple(args, "i:remove_history_item", &entry_number))
return NULL;
if (entry_number < 0) {
PyErr_SetString(PyExc_ValueError,
char *line;
HIST_ENTRY *old_entry;
- if (!PyArg_ParseTuple(args, "is:replace_history", &entry_number,
+ if (!PyArg_ParseTuple(args, "is:replace_history_item", &entry_number,
&line)) {
return NULL;
}
PyDoc_STRVAR(doc_add_history,
"add_history(string) -> None\n\
-add a line to the history buffer");
+add an item to the history buffer");
/* Get the tab-completion word-delimiters that readline uses */
PyDoc_STRVAR(doc_get_completer_delims,
"get_completer_delims() -> string\n\
-get the readline word delimiters for tab-completion");
+get the word delimiters for completion");
/* Set the completer function */
int idx = 0;
HIST_ENTRY *hist_ent;
- if (!PyArg_ParseTuple(args, "i:index", &idx))
+ if (!PyArg_ParseTuple(args, "i:get_history_item", &idx))
return NULL;
#ifdef __APPLE__
if (using_libedit_emulation) {
PyDoc_STRVAR(doc_insert_text,
"insert_text(string) -> None\n\
-Insert text into the command line.");
+Insert text into the line buffer at the cursor position.");
/* Redisplay the line buffer */
#endif
+#ifdef HAVE_RL_RESIZE_TERMINAL
+static volatile sig_atomic_t sigwinch_received;
+static PyOS_sighandler_t sigwinch_ohandler;
+
+static void
+readline_sigwinch_handler(int signum)
+{
+ sigwinch_received = 1;
+ if (sigwinch_ohandler &&
+ sigwinch_ohandler != SIG_IGN && sigwinch_ohandler != SIG_DFL)
+ sigwinch_ohandler(signum);
+
+#ifndef HAVE_SIGACTION
+ /* If the handler was installed with signal() rather than sigaction(),
+ we need to reinstall it. */
+ PyOS_setsig(SIGWINCH, readline_sigwinch_handler);
+#endif
+}
+#endif
+
/* C function to call the Python completer. */
static char *
/* Bind both ESC-TAB and ESC-ESC to the completion function */
rl_bind_key_in_map ('\t', rl_complete, emacs_meta_keymap);
rl_bind_key_in_map ('\033', rl_complete, emacs_meta_keymap);
+#ifdef HAVE_RL_RESIZE_TERMINAL
+ /* Set up signal handler for window resize */
+ sigwinch_ohandler = PyOS_setsig(SIGWINCH, readline_sigwinch_handler);
+#endif
/* Set our hook functions */
rl_startup_hook = on_startup_hook;
#ifdef HAVE_RL_PRE_INPUT_HOOK
#ifndef __APPLE__
if (!isatty(STDOUT_FILENO)) {
- /* Issue #19884: stdout is no a terminal. Disable meta modifier
+ /* Issue #19884: stdout is not a terminal. Disable meta modifier
keys to not write the ANSI sequence "\033[1034h" into stdout. On
terminals supporting 8 bit characters like TERM=xterm-256color
(which is now the default Fedora since Fedora 18), the meta key is
struct timeval *timeoutp = NULL;
if (PyOS_InputHook)
timeoutp = &timeout;
+#ifdef HAVE_RL_RESIZE_TERMINAL
+ /* Update readline's view of the window size after SIGWINCH */
+ if (sigwinch_received) {
+ sigwinch_received = 0;
+ rl_resize_terminal();
+ }
+#endif
FD_SET(fileno(rl_instream), &selectset);
/* select resets selectset if no input was available */
has_input = select(fileno(rl_instream) + 1, &selectset,
#endif
if (s < 0) {
rl_free_line_state();
+#if defined(RL_READLINE_VERSION) && RL_READLINE_VERSION >= 0x0700
+ rl_callback_sigcleanup();
+#endif
rl_cleanup_after_signal();
rl_callback_handler_remove();
*signal = 1;
Registers a new fd or raises an OSError if the fd is already registered.\n\
fd is the target file descriptor of the operation.\n\
events is a bit set composed of the various EPOLL constants; the default\n\
-is EPOLL_IN | EPOLL_OUT | EPOLL_PRI.\n\
+is EPOLLIN | EPOLLOUT | EPOLLPRI.\n\
\n\
The epoll interface supports all file descriptors that support poll.");
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
- * gurantee it works.
+ * guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtom.org
*/
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
- * gurantee it works.
+ * guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtom.org
*/
if (Handlers[SIGINT].func == DefaultHandler) {
/* Install default int handler */
Py_INCREF(IntHandler);
- Py_DECREF(Handlers[SIGINT].func);
- Handlers[SIGINT].func = IntHandler;
+ Py_SETREF(Handlers[SIGINT].func, IntHandler);
old_siginthandler = PyOS_setsig(SIGINT, signal_handler);
}
*/
#ifdef __APPLE__
+#include <AvailabilityMacros.h>
+/* for getaddrinfo thread safety test on old versions of OS X */
+#ifndef MAC_OS_X_VERSION_10_5
+#define MAC_OS_X_VERSION_10_5 1050
+#endif
/*
* inet_aton is not available on OSX 10.3, yet we want to use a binary
* that was build on 10.4 or later to work on that release, weak linking
# define USE_GETHOSTBYNAME_LOCK
#endif
-/* To use __FreeBSD_version */
+/* To use __FreeBSD_version, __OpenBSD__, and __NetBSD_Version__ */
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
/* On systems on which getaddrinfo() is believed to not be thread-safe,
- (this includes the getaddrinfo emulation) protect access with a lock. */
-#if defined(WITH_THREAD) && (defined(__APPLE__) || \
+ (this includes the getaddrinfo emulation) protect access with a lock.
+
+ getaddrinfo is thread-safe on Mac OS X 10.5 and later. Originally it was
+ a mix of code including an unsafe implementation from an old BSD's
+ libresolv. In 10.5 Apple reimplemented it as a safe IPC call to the
+ mDNSResponder process. 10.5 is the first be UNIX '03 certified, which
+ includes the requirement that getaddrinfo be thread-safe. See issue #25924.
+
+ It's thread-safe in OpenBSD starting with 5.4, released Nov 2013:
+ http://www.openbsd.org/plus54.html
+
+ It's thread-safe in NetBSD starting with 4.0, released Dec 2007:
+
+http://cvsweb.netbsd.org/bsdweb.cgi/src/lib/libc/net/getaddrinfo.c.diff?r1=1.82&r2=1.83
+ */
+#if defined(WITH_THREAD) && ( \
+ (defined(__APPLE__) && \
+ MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5) || \
(defined(__FreeBSD__) && __FreeBSD_version+0 < 503000) || \
- defined(__OpenBSD__) || defined(__NetBSD__) || \
+ (defined(__OpenBSD__) && OpenBSD+0 < 201311) || \
+ (defined(__NetBSD__) && __NetBSD_Version__+0 < 400000000) || \
!defined(HAVE_GETADDRINFO))
#define USE_GETADDRINFO_LOCK
#endif
Return the IP address (a string of the form '255.255.255.255') for a host.");
+static PyObject*
+sock_decode_hostname(const char *name)
+{
+#ifdef MS_WINDOWS
+ /* Issue #26227: gethostbyaddr() returns a string encoded
+ * to the ANSI code page */
+ return PyUnicode_DecodeFSDefault(name);
+#else
+ /* Decode from UTF-8 */
+ return PyUnicode_FromString(name);
+#endif
+}
+
/* Convenience function common to gethostbyname_ex and gethostbyaddr */
static PyObject *
PyObject *name_list = (PyObject *)NULL;
PyObject *addr_list = (PyObject *)NULL;
PyObject *tmp;
+ PyObject *name;
if (h == NULL) {
/* Let's get real error message to return */
goto err;
}
- rtn_tuple = Py_BuildValue("sOO", h->h_name, name_list, addr_list);
+ name = sock_decode_hostname(h->h_name);
+ if (name == NULL)
+ goto err;
+ rtn_tuple = Py_BuildValue("NOO", name, name_list, addr_list);
err:
Py_XDECREF(name_list);
struct addrinfo hints, *res = NULL;
int error;
PyObject *ret = (PyObject *)NULL;
+ PyObject *name;
flags = flowinfo = scope_id = 0;
if (!PyArg_ParseTuple(args, "Oi:getnameinfo", &sa, &flags))
set_gaierror(error);
goto fail;
}
- ret = Py_BuildValue("ss", hbuf, pbuf);
+
+ name = sock_decode_hostname(hbuf);
+ if (name == NULL)
+ goto fail;
+ ret = Py_BuildValue("Ns", name, pbuf);
fail:
if (res)
tmp = PyUnicode_FromFormat("%U%c", self->prefix, SEP);
if (tmp == NULL)
goto error;
- Py_DECREF(self->prefix);
- self->prefix = tmp;
+ Py_SETREF(self->prefix, tmp);
}
}
else
}
typedef enum {
- FL_ERROR,
- FL_NOT_FOUND,
- FL_MODULE_FOUND,
- FL_NS_FOUND
+ FL_ERROR = -1, /* error */
+ FL_NOT_FOUND, /* no loader or namespace portions found */
+ FL_MODULE_FOUND, /* module/package found */
+ FL_NS_FOUND /* namespace portion found: */
+ /* *namespace_portion will point to the name */
} find_loader_result;
-/* The guts of "find_loader" and "find_module". Return values:
- -1: error
- 0: no loader or namespace portions found
- 1: module/package found
- 2: namespace portion found: *namespace_portion will point to the name
+/* The guts of "find_loader" and "find_module".
*/
static find_loader_result
find_loader(ZipImporter *self, PyObject *fullname, PyObject **namespace_portion)
if (mi == MI_NOT_FOUND) {
/* Not a module or regular package. See if this is a directory, and
therefore possibly a portion of a namespace package. */
- int is_dir = check_is_directory(self, self->prefix, fullname);
+ find_loader_result result = FL_NOT_FOUND;
+ PyObject *subname;
+ int is_dir;
+
+ /* We're only interested in the last path component of fullname;
+ earlier components are recorded in self->prefix. */
+ subname = get_subname(fullname);
+ if (subname == NULL) {
+ return FL_ERROR;
+ }
+
+ is_dir = check_is_directory(self, self->prefix, subname);
if (is_dir < 0)
- return -1;
- if (is_dir) {
+ result = FL_ERROR;
+ else if (is_dir) {
/* This is possibly a portion of a namespace
package. Return the string representing its path,
without a trailing separator. */
*namespace_portion = PyUnicode_FromFormat("%U%c%U%U",
self->archive, SEP,
- self->prefix, fullname);
+ self->prefix, subname);
if (*namespace_portion == NULL)
- return FL_ERROR;
- return FL_NS_FOUND;
+ result = FL_ERROR;
+ else
+ result = FL_NS_FOUND;
}
- return FL_NOT_FOUND;
+ Py_DECREF(subname);
+ return result;
}
/* This is a module or package. */
return FL_MODULE_FOUND;
case FL_MODULE_FOUND:
result = (PyObject *)self;
break;
+ default:
+ PyErr_BadInternalCall();
+ return NULL;
}
Py_INCREF(result);
return result;
result = Py_BuildValue("O[O]", Py_None, namespace_portion);
Py_DECREF(namespace_portion);
return result;
+ default:
+ PyErr_BadInternalCall();
+ return NULL;
}
return result;
}
/* implementation */
-/* Given a buffer, return the long that is represented by the first
+/* Given a buffer, return the unsigned int that is represented by the first
4 bytes, encoded as little endian. This partially reimplements
marshal.c:r_long() */
-static long
-get_long(unsigned char *buf) {
- long x;
+static unsigned int
+get_uint32(const unsigned char *buf)
+{
+ unsigned int x;
x = buf[0];
- x |= (long)buf[1] << 8;
- x |= (long)buf[2] << 16;
- x |= (long)buf[3] << 24;
-#if SIZEOF_LONG > 4
- /* Sign extension for 64-bit machines */
- x |= -(x & 0x80000000L);
-#endif
+ x |= (unsigned int)buf[1] << 8;
+ x |= (unsigned int)buf[2] << 16;
+ x |= (unsigned int)buf[3] << 24;
+ return x;
+}
+
+/* Given a buffer, return the unsigned int that is represented by the first
+ 2 bytes, encoded as little endian. This partially reimplements
+ marshal.c:r_short() */
+static unsigned short
+get_uint16(const unsigned char *buf)
+{
+ unsigned short x;
+ x = buf[0];
+ x |= (unsigned short)buf[1] << 8;
return x;
}
+static void
+set_file_error(PyObject *archive, int eof)
+{
+ if (eof) {
+ PyErr_SetString(PyExc_EOFError, "EOF read where not expected");
+ }
+ else {
+ PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, archive);
+ }
+}
+
/*
read_directory(archive) -> files dict (new reference)
{
PyObject *files = NULL;
FILE *fp;
- unsigned short flags;
- short compress, time, date, name_size;
- long crc, data_size, file_size, header_size;
- Py_ssize_t file_offset, header_position, header_offset;
- long l, count;
- Py_ssize_t i;
+ unsigned short flags, compress, time, date, name_size;
+ unsigned int crc, data_size, file_size, header_size, header_offset;
+ unsigned long file_offset, header_position;
+ unsigned long arc_offset; /* Absolute offset to start of the zip-archive. */
+ unsigned int count, i;
+ unsigned char buffer[46];
char name[MAXPATHLEN + 5];
- char dummy[8]; /* Buffer to read unused header values into */
PyObject *nameobj = NULL;
- char *p, endof_central_dir[22];
- Py_ssize_t arc_offset; /* Absolute offset to start of the zip-archive. */
PyObject *path;
const char *charset;
int bootstrap;
+ const char *errmsg = NULL;
fp = _Py_fopen_obj(archive, "rb");
if (fp == NULL) {
}
if (fseek(fp, -22, SEEK_END) == -1) {
- fclose(fp);
- PyErr_Format(ZipImportError, "can't read Zip file: %R", archive);
- return NULL;
+ goto file_error;
}
- header_position = ftell(fp);
- if (fread(endof_central_dir, 1, 22, fp) != 22) {
- fclose(fp);
- PyErr_Format(ZipImportError, "can't read Zip file: %R", archive);
- return NULL;
+ header_position = (unsigned long)ftell(fp);
+ if (header_position == (unsigned long)-1) {
+ goto file_error;
+ }
+ assert(header_position <= (unsigned long)LONG_MAX);
+ if (fread(buffer, 1, 22, fp) != 22) {
+ goto file_error;
}
- if (get_long((unsigned char *)endof_central_dir) != 0x06054B50) {
+ if (get_uint32(buffer) != 0x06054B50u) {
/* Bad: End of Central Dir signature */
- fclose(fp);
- PyErr_Format(ZipImportError, "not a Zip file: %R", archive);
- return NULL;
+ errmsg = "not a Zip file";
+ goto invalid_header;
}
- header_size = get_long((unsigned char *)endof_central_dir + 12);
- header_offset = get_long((unsigned char *)endof_central_dir + 16);
- arc_offset = header_position - header_offset - header_size;
- header_offset += arc_offset;
+ header_size = get_uint32(buffer + 12);
+ header_offset = get_uint32(buffer + 16);
+ if (header_position < header_size) {
+ errmsg = "bad central directory size";
+ goto invalid_header;
+ }
+ if (header_position < header_offset) {
+ errmsg = "bad central directory offset";
+ goto invalid_header;
+ }
+ if (header_position - header_size < header_offset) {
+ errmsg = "bad central directory size or offset";
+ goto invalid_header;
+ }
+ header_position -= header_size;
+ arc_offset = header_position - header_offset;
files = PyDict_New();
- if (files == NULL)
+ if (files == NULL) {
goto error;
-
+ }
/* Start of Central Directory */
count = 0;
- if (fseek(fp, header_offset, 0) == -1)
+ if (fseek(fp, (long)header_position, 0) == -1) {
goto file_error;
+ }
for (;;) {
PyObject *t;
+ size_t n;
int err;
+ n = fread(buffer, 1, 46, fp);
+ if (n < 4) {
+ goto eof_error;
+ }
/* Start of file header */
- l = PyMarshal_ReadLongFromFile(fp);
- if (l == -1 && PyErr_Occurred())
- goto error;
- if (l != 0x02014B50)
+ if (get_uint32(buffer) != 0x02014B50u) {
break; /* Bad: Central Dir File Header */
+ }
+ if (n != 46) {
+ goto eof_error;
+ }
+ flags = get_uint16(buffer + 8);
+ compress = get_uint16(buffer + 10);
+ time = get_uint16(buffer + 12);
+ date = get_uint16(buffer + 14);
+ crc = get_uint32(buffer + 16);
+ data_size = get_uint32(buffer + 20);
+ file_size = get_uint32(buffer + 24);
+ name_size = get_uint16(buffer + 28);
+ header_size = (unsigned int)name_size +
+ get_uint16(buffer + 30) /* extra field */ +
+ get_uint16(buffer + 32) /* comment */;
+
+ file_offset = get_uint32(buffer + 42);
+ if (file_offset > header_offset) {
+ errmsg = "bad local header offset";
+ goto invalid_header;
+ }
+ file_offset += arc_offset;
- /* On Windows, calling fseek to skip over the fields we don't use is
- slower than reading the data into a dummy buffer because fseek flushes
- stdio's internal buffers. See issue #8745. */
- if (fread(dummy, 1, 4, fp) != 4) /* Skip unused fields, avoid fseek */
- goto file_error;
-
- flags = (unsigned short)PyMarshal_ReadShortFromFile(fp);
- compress = PyMarshal_ReadShortFromFile(fp);
- time = PyMarshal_ReadShortFromFile(fp);
- date = PyMarshal_ReadShortFromFile(fp);
- crc = PyMarshal_ReadLongFromFile(fp);
- data_size = PyMarshal_ReadLongFromFile(fp);
- file_size = PyMarshal_ReadLongFromFile(fp);
- name_size = PyMarshal_ReadShortFromFile(fp);
- header_size = name_size +
- PyMarshal_ReadShortFromFile(fp) +
- PyMarshal_ReadShortFromFile(fp);
- if (PyErr_Occurred())
- goto error;
-
- if (fread(dummy, 1, 8, fp) != 8) /* Skip unused fields, avoid fseek */
- goto file_error;
- file_offset = PyMarshal_ReadLongFromFile(fp) + arc_offset;
- if (PyErr_Occurred())
- goto error;
-
- if (name_size > MAXPATHLEN)
+ if (name_size > MAXPATHLEN) {
name_size = MAXPATHLEN;
-
- p = name;
- for (i = 0; i < (Py_ssize_t)name_size; i++) {
- *p = (char)getc(fp);
- if (*p == '/')
- *p = SEP;
- p++;
}
- *p = 0; /* Add terminating null byte */
- for (; i < header_size; i++) /* Skip the rest of the header */
- if(getc(fp) == EOF) /* Avoid fseek */
+ if (fread(name, 1, name_size, fp) != name_size) {
+ goto file_error;
+ }
+ name[name_size] = '\0'; /* Add terminating null byte */
+ if (SEP != '/') {
+ for (i = 0; i < name_size; i++) {
+ if (name[i] == '/') {
+ name[i] = SEP;
+ }
+ }
+ }
+ /* Skip the rest of the header.
+ * On Windows, calling fseek to skip over the fields we don't use is
+ * slower than reading the data because fseek flushes stdio's
+ * internal buffers. See issue #8745. */
+ assert(header_size <= 3*0xFFFFu);
+ for (i = name_size; i < header_size; i++) {
+ if (getc(fp) == EOF) {
goto file_error;
+ }
+ }
bootstrap = 0;
- if (flags & 0x0800)
+ if (flags & 0x0800) {
charset = "utf-8";
+ }
else if (!PyThreadState_GET()->interp->codecs_initialized) {
/* During bootstrap, we may need to load the encodings
package from a ZIP file. But the cp437 encoding is implemented
charset = "ascii";
bootstrap = 1;
}
- else
+ else {
charset = "cp437";
+ }
nameobj = PyUnicode_Decode(name, name_size, charset, NULL);
if (nameobj == NULL) {
- if (bootstrap)
+ if (bootstrap) {
PyErr_Format(PyExc_NotImplementedError,
"bootstrap issue: python%i%i.zip contains non-ASCII "
"filenames without the unicode flag",
PY_MAJOR_VERSION, PY_MINOR_VERSION);
+ }
goto error;
}
- if (PyUnicode_READY(nameobj) == -1)
+ if (PyUnicode_READY(nameobj) == -1) {
goto error;
+ }
path = PyUnicode_FromFormat("%U%c%U", archive, SEP, nameobj);
- if (path == NULL)
+ if (path == NULL) {
goto error;
- t = Py_BuildValue("Nhllnhhl", path, compress, data_size,
+ }
+ t = Py_BuildValue("NHIIkHHI", path, compress, data_size,
file_size, file_offset, time, date, crc);
- if (t == NULL)
+ if (t == NULL) {
goto error;
+ }
err = PyDict_SetItem(files, nameobj, t);
Py_CLEAR(nameobj);
Py_DECREF(t);
- if (err != 0)
+ if (err != 0) {
goto error;
+ }
count++;
}
fclose(fp);
- if (Py_VerboseFlag)
- PySys_FormatStderr("# zipimport: found %ld names in %R\n",
+ if (Py_VerboseFlag) {
+ PySys_FormatStderr("# zipimport: found %u names in %R\n",
count, archive);
+ }
return files;
+
+eof_error:
+ set_file_error(archive, !ferror(fp));
+ goto error;
+
file_error:
- fclose(fp);
- Py_XDECREF(files);
- Py_XDECREF(nameobj);
PyErr_Format(ZipImportError, "can't read Zip file: %R", archive);
- return NULL;
+ goto error;
+
+invalid_header:
+ assert(errmsg != NULL);
+ PyErr_Format(ZipImportError, "%s: %R", errmsg, archive);
+ goto error;
+
error:
fclose(fp);
Py_XDECREF(files);
static PyObject *
get_data(PyObject *archive, PyObject *toc_entry)
{
- PyObject *raw_data, *data = NULL, *decompress;
+ PyObject *raw_data = NULL, *data, *decompress;
char *buf;
FILE *fp;
- int err;
- Py_ssize_t bytes_read = 0;
- long l;
PyObject *datapath;
- long compress, data_size, file_size, file_offset, bytes_size;
- long time, date, crc;
-
- if (!PyArg_ParseTuple(toc_entry, "Olllllll", &datapath, &compress,
+ unsigned short compress, time, date;
+ unsigned int crc;
+ Py_ssize_t data_size, file_size, bytes_size;
+ long file_offset, header_size;
+ unsigned char buffer[30];
+ const char *errmsg = NULL;
+
+ if (!PyArg_ParseTuple(toc_entry, "OHnnlHHI", &datapath, &compress,
&data_size, &file_size, &file_offset, &time,
&date, &crc)) {
return NULL;
}
+ if (data_size < 0) {
+ PyErr_Format(ZipImportError, "negative data size");
+ return NULL;
+ }
fp = _Py_fopen_obj(archive, "rb");
- if (!fp)
+ if (!fp) {
return NULL;
-
+ }
/* Check to make sure the local file header is correct */
if (fseek(fp, file_offset, 0) == -1) {
- fclose(fp);
- PyErr_Format(ZipImportError, "can't read Zip file: %R", archive);
- return NULL;
+ goto file_error;
}
-
- l = PyMarshal_ReadLongFromFile(fp);
- if (l != 0x04034B50) {
+ if (fread(buffer, 1, 30, fp) != 30) {
+ goto eof_error;
+ }
+ if (get_uint32(buffer) != 0x04034B50u) {
/* Bad: Local File Header */
- if (!PyErr_Occurred())
- PyErr_Format(ZipImportError,
- "bad local file header in %U",
- archive);
- fclose(fp);
- return NULL;
+ errmsg = "bad local file header";
+ goto invalid_header;
}
- if (fseek(fp, file_offset + 26, 0) == -1) {
- fclose(fp);
- PyErr_Format(ZipImportError, "can't read Zip file: %R", archive);
- return NULL;
+
+ header_size = (unsigned int)30 +
+ get_uint16(buffer + 26) /* file name */ +
+ get_uint16(buffer + 28) /* extra field */;
+ if (file_offset > LONG_MAX - header_size) {
+ errmsg = "bad local file header size";
+ goto invalid_header;
}
+ file_offset += header_size; /* Start of file data */
- l = 30 + PyMarshal_ReadShortFromFile(fp) +
- PyMarshal_ReadShortFromFile(fp); /* local header size */
- if (PyErr_Occurred()) {
+ if (data_size > LONG_MAX - 1) {
fclose(fp);
+ PyErr_NoMemory();
return NULL;
}
- file_offset += l; /* Start of file data */
-
bytes_size = compress == 0 ? data_size : data_size + 1;
- if (bytes_size == 0)
+ if (bytes_size == 0) {
bytes_size++;
+ }
raw_data = PyBytes_FromStringAndSize((char *)NULL, bytes_size);
-
if (raw_data == NULL) {
- fclose(fp);
- return NULL;
+ goto error;
}
buf = PyBytes_AsString(raw_data);
- err = fseek(fp, file_offset, 0);
- if (err == 0) {
- bytes_read = fread(buf, 1, data_size, fp);
- } else {
- fclose(fp);
- PyErr_Format(ZipImportError, "can't read Zip file: %R", archive);
- return NULL;
+ if (fseek(fp, file_offset, 0) == -1) {
+ goto file_error;
}
- fclose(fp);
- if (err || bytes_read != data_size) {
+ if (fread(buf, 1, data_size, fp) != (size_t)data_size) {
PyErr_SetString(PyExc_IOError,
"zipimport: can't read data");
- Py_DECREF(raw_data);
- return NULL;
+ goto error;
}
+ fclose(fp);
+ fp = NULL;
+
if (compress != 0) {
buf[data_size] = 'Z'; /* saw this in zipfile.py */
data_size++;
}
data = PyObject_CallFunction(decompress, "Oi", raw_data, -15);
Py_DECREF(decompress);
-error:
Py_DECREF(raw_data);
return data;
+
+eof_error:
+ set_file_error(archive, !ferror(fp));
+ goto error;
+
+file_error:
+ PyErr_Format(ZipImportError, "can't read Zip file: %R", archive);
+ goto error;
+
+invalid_header:
+ assert(errmsg != NULL);
+ PyErr_Format(ZipImportError, "%s: %R", errmsg, archive);
+ goto error;
+
+error:
+ if (fp != NULL) {
+ fclose(fp);
+ }
+ Py_XDECREF(raw_data);
+ return NULL;
}
/* Lenient date/time comparison function. The precision of the mtime
unmarshal_code(PyObject *pathname, PyObject *data, time_t mtime)
{
PyObject *code;
- char *buf = PyBytes_AsString(data);
+ unsigned char *buf = (unsigned char *)PyBytes_AsString(data);
Py_ssize_t size = PyBytes_Size(data);
- if (size <= 9) {
+ if (size < 12) {
PyErr_SetString(ZipImportError,
"bad pyc data");
return NULL;
}
- if (get_long((unsigned char *)buf) != PyImport_GetMagicNumber()) {
- if (Py_VerboseFlag)
+ if (get_uint32(buf) != (unsigned int)PyImport_GetMagicNumber()) {
+ if (Py_VerboseFlag) {
PySys_FormatStderr("# %R has bad magic\n",
pathname);
+ }
Py_INCREF(Py_None);
return Py_None; /* signal caller to try alternative */
}
- if (mtime != 0 && !eq_mtime(get_long((unsigned char *)buf + 4),
- mtime)) {
- if (Py_VerboseFlag)
+ if (mtime != 0 && !eq_mtime(get_uint32(buf + 4), mtime)) {
+ if (Py_VerboseFlag) {
PySys_FormatStderr("# %R has bad mtime\n",
pathname);
+ }
Py_INCREF(Py_None);
return Py_None; /* signal caller to try alternative */
}
/* XXX the pyc's size field is ignored; timestamp collisions are probably
unimportant with zip files. */
- code = PyMarshal_ReadObjectFromString(buf + 12, size - 12);
- if (code == NULL)
+ code = PyMarshal_ReadObjectFromString((char *)buf + 12, size - 12);
+ if (code == NULL) {
return NULL;
+ }
if (!PyCode_Check(code)) {
Py_DECREF(code);
PyErr_Format(PyExc_TypeError,
#define LEAVE_ZLIB(obj)
#endif
+#if defined(ZLIB_VERNUM) && ZLIB_VERNUM >= 0x1221
+#define AT_LEAST_ZLIB_1_2_2_1
+#endif
+
/* The following parameters are copied from zutil.h, version 0.95 */
#define DEFLATED 8
#if MAX_MEM_LEVEL >= 8
data: Py_buffer
Compressed data.
wbits: int(c_default="MAX_WBITS") = MAX_WBITS
- The window buffer size.
+ The window buffer size and container format.
bufsize: capped_uint(c_default="DEF_BUF_SIZE") = DEF_BUF_SIZE
The initial output buffer size.
/
static PyObject *
zlib_decompress_impl(PyModuleDef *module, Py_buffer *data, int wbits,
unsigned int bufsize)
-/*[clinic end generated code: output=444d0987f3429574 input=da095118b3243b27]*/
+/*[clinic end generated code: output=444d0987f3429574 input=75123b0d4ff0541d]*/
{
PyObject *result_str = NULL;
Byte *input;
zlib.compressobj
level: int(c_default="Z_DEFAULT_COMPRESSION") = Z_DEFAULT_COMPRESSION
- The compression level (an integer in the range 0-9; default is 6).
- Higher compression levels are slower, but produce smaller results.
+ The compression level (an integer in the range 0-9 or -1; default is
+ currently equivalent to 6). Higher compression levels are slower,
+ but produce smaller results.
method: int(c_default="DEFLATED") = DEFLATED
The compression algorithm. If given, this must be DEFLATED.
wbits: int(c_default="MAX_WBITS") = MAX_WBITS
- The base two logarithm of the window size (range: 8..15).
+ +9 to +15: The base-two logarithm of the window size. Include a zlib
+ container.
+ -9 to -15: Generate a raw stream.
+ +25 to +31: Include a gzip container.
memLevel: int(c_default="DEF_MEM_LEVEL") = DEF_MEM_LEVEL
Controls the amount of memory used for internal compression state.
Valid values range from 1 to 9. Higher values result in higher memory
static PyObject *
zlib_compressobj_impl(PyModuleDef *module, int level, int method, int wbits,
int memLevel, int strategy, Py_buffer *zdict)
-/*[clinic end generated code: output=2949bbb9a5723ccd input=b034847f8821f6af]*/
+/*[clinic end generated code: output=2949bbb9a5723ccd input=2fa3d026f90ab8d5]*/
{
compobject *self = NULL;
int err;
return (PyObject*)self;
}
+static int
+set_inflate_zdict(compobject *self)
+{
+ Py_buffer zdict_buf;
+ int err;
+
+ if (PyObject_GetBuffer(self->zdict, &zdict_buf, PyBUF_SIMPLE) == -1) {
+ return -1;
+ }
+ if ((size_t)zdict_buf.len > UINT_MAX) {
+ PyErr_SetString(PyExc_OverflowError,
+ "zdict length does not fit in an unsigned int");
+ PyBuffer_Release(&zdict_buf);
+ return -1;
+ }
+ err = inflateSetDictionary(&(self->zst),
+ zdict_buf.buf, (unsigned int)zdict_buf.len);
+ PyBuffer_Release(&zdict_buf);
+ if (err != Z_OK) {
+ zlib_error(self->zst, err, "while setting zdict");
+ return -1;
+ }
+ return 0;
+}
+
/*[clinic input]
zlib.decompressobj
wbits: int(c_default="MAX_WBITS") = MAX_WBITS
- The window buffer size.
+ The window buffer size and container format.
zdict: object(c_default="NULL") = b''
The predefined compression dictionary. This must be the same
dictionary as used by the compressor that produced the input data.
static PyObject *
zlib_decompressobj_impl(PyModuleDef *module, int wbits, PyObject *zdict)
-/*[clinic end generated code: output=8ccd583fbd631798 input=67f05145a6920127]*/
+/*[clinic end generated code: output=8ccd583fbd631798 input=d3832b8511fc977b]*/
{
int err;
compobject *self;
switch(err) {
case (Z_OK):
self->is_initialised = 1;
+ if (self->zdict != NULL && wbits < 0) {
+#ifdef AT_LEAST_ZLIB_1_2_2_1
+ if (set_inflate_zdict(self) < 0) {
+ Py_DECREF(self);
+ return NULL;
+ }
+#else
+ PyErr_Format(ZlibError,
+ "zlib version %s does not allow raw inflate with dictionary",
+ ZLIB_VERSION);
+ Py_DECREF(self);
+ return NULL;
+#endif
+ }
return (PyObject*)self;
case(Z_STREAM_ERROR):
Py_DECREF(self);
PyBytes_AS_STRING(self->unused_data), old_size);
Py_MEMCPY(PyBytes_AS_STRING(new_data) + old_size,
self->zst.next_in, self->zst.avail_in);
- Py_DECREF(self->unused_data);
- self->unused_data = new_data;
+ Py_SETREF(self->unused_data, new_data);
self->zst.avail_in = 0;
}
}
(char *)self->zst.next_in, self->zst.avail_in);
if (new_data == NULL)
return -1;
- Py_DECREF(self->unconsumed_tail);
- self->unconsumed_tail = new_data;
+ Py_SETREF(self->unconsumed_tail, new_data);
}
return 0;
}
Py_END_ALLOW_THREADS
if (err == Z_NEED_DICT && self->zdict != NULL) {
- Py_buffer zdict_buf;
- if (PyObject_GetBuffer(self->zdict, &zdict_buf, PyBUF_SIMPLE) == -1) {
+ if (set_inflate_zdict(self) < 0) {
Py_DECREF(RetVal);
RetVal = NULL;
goto error;
}
- if ((size_t)zdict_buf.len > UINT_MAX) {
- PyErr_SetString(PyExc_OverflowError,
- "zdict length does not fit in an unsigned int");
- PyBuffer_Release(&zdict_buf);
- Py_CLEAR(RetVal);
- goto error;
- }
-
- err = inflateSetDictionary(&(self->zst),
- zdict_buf.buf, (unsigned int)zdict_buf.len);
- PyBuffer_Release(&zdict_buf);
- if (err != Z_OK) {
- zlib_error(self->zst, err, "while decompressing data");
- Py_CLEAR(RetVal);
- goto error;
- }
/* Repeat the call to inflate. */
Py_BEGIN_ALLOW_THREADS
err = inflate(&(self->zst), Z_SYNC_FLUSH);
goto error;
}
Py_INCREF(self->unused_data);
+ Py_XSETREF(retval->unused_data, self->unused_data);
Py_INCREF(self->unconsumed_tail);
+ Py_XSETREF(retval->unconsumed_tail, self->unconsumed_tail);
Py_XINCREF(self->zdict);
- Py_XDECREF(retval->unused_data);
- Py_XDECREF(retval->unconsumed_tail);
- Py_XDECREF(retval->zdict);
- retval->unused_data = self->unused_data;
- retval->unconsumed_tail = self->unconsumed_tail;
- retval->zdict = self->zdict;
+ Py_XSETREF(retval->zdict, self->zdict);
retval->eof = self->eof;
/* Mark it as being initialized */
}
Py_INCREF(self->unused_data);
+ Py_XSETREF(retval->unused_data, self->unused_data);
Py_INCREF(self->unconsumed_tail);
+ Py_XSETREF(retval->unconsumed_tail, self->unconsumed_tail);
Py_XINCREF(self->zdict);
- Py_XDECREF(retval->unused_data);
- Py_XDECREF(retval->unconsumed_tail);
- Py_XDECREF(retval->zdict);
- retval->unused_data = self->unused_data;
- retval->unconsumed_tail = self->unconsumed_tail;
- retval->zdict = self->zdict;
+ Py_XSETREF(retval->zdict, self->zdict);
retval->eof = self->eof;
/* Mark it as being initialized */
"decompress(string,[wbits],[bufsize]) -- Decompresses a compressed string.\n"
"decompressobj([wbits[, zdict]]]) -- Return a decompressor object.\n"
"\n"
-"'wbits' is window buffer size.\n"
+"'wbits' is window buffer size and container format.\n"
"Compressor objects support compress() and flush() methods; decompressor\n"
"objects support decompress() and flush().");
bytearray_remove_impl(PyByteArrayObject *self, int value)
/*[clinic end generated code: output=d659e37866709c13 input=47560b11fd856c24]*/
{
- Py_ssize_t where, n = Py_SIZE(self);
+ Py_ssize_t n = Py_SIZE(self);
char *buf = PyByteArray_AS_STRING(self);
+ char *where = memchr(buf, value, n);
- for (where = 0; where < n; where++) {
- if (buf[where] == value)
- break;
- }
- if (where == n) {
+ if (!where) {
PyErr_SetString(PyExc_ValueError, "value not found in bytearray");
return NULL;
}
if (!_canresize(self))
return NULL;
- memmove(buf + where, buf + where + 1, n - where);
+ memmove(where, where + 1, buf + n - where);
if (PyByteArray_Resize((PyObject *)self, n - 1) < 0)
return NULL;
{
Py_ssize_t res;
- res = sizeof(PyByteArrayObject) + self->ob_alloc * sizeof(char);
+ res = _PyObject_SIZE(Py_TYPE(self)) + self->ob_alloc * sizeof(char);
return PyLong_FromSsize_t(res);
}
bytearray(int) -> bytes array of size given by the parameter initialized with null bytes\n\
bytearray() -> empty bytes array\n\
\n\
-Construct an mutable bytearray object from:\n\
+Construct a mutable bytearray object from:\n\
- an iterable yielding integers in range(256)\n\
- a text string encoded using the specified encoding\n\
- a bytes or a buffer object\n\
return item;
}
- Py_DECREF(seq);
it->it_seq = NULL;
+ Py_DECREF(seq);
return NULL;
}
For PyBytes_FromString(), the parameter `str' points to a null-terminated
string containing exactly `size' bytes.
- For PyBytes_FromStringAndSize(), the parameter the parameter `str' is
+ For PyBytes_FromStringAndSize(), the parameter `str' is
either NULL or else points to a string containing at least `size' bytes.
For PyBytes_FromStringAndSize(), the string in the `str' parameter does
not have to be null-terminated. (Therefore it is safe to construct a
};
static PyObject *
-str_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
+bytes_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
static PyObject *
bytes_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
_Py_IDENTIFIER(__bytes__);
if (type != &PyBytes_Type)
- return str_subtype_new(type, args, kwds);
+ return bytes_subtype_new(type, args, kwds);
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oss:bytes", kwlist, &x,
&encoding, &errors))
return NULL;
return PyBytes_FromStringAndSize(NULL, 0);
}
- if (PyUnicode_Check(x)) {
+ if (encoding != NULL) {
/* Encode via the codec registry */
- if (encoding == NULL) {
+ if (!PyUnicode_Check(x)) {
PyErr_SetString(PyExc_TypeError,
- "string argument without an encoding");
+ "encoding without a string argument");
return NULL;
}
new = PyUnicode_AsEncodedString(x, encoding, errors);
return new;
}
- /* If it's not unicode, there can't be encoding or errors */
- if (encoding != NULL || errors != NULL) {
+ if (errors != NULL) {
PyErr_SetString(PyExc_TypeError,
- "encoding or errors without a string argument");
+ PyUnicode_Check(x) ?
+ "string argument without an encoding" :
+ "errors without a string argument");
return NULL;
}
else if (PyErr_Occurred())
return NULL;
+ if (PyUnicode_Check(x)) {
+ PyErr_SetString(PyExc_TypeError,
+ "string argument without an encoding");
+ return NULL;
+ }
/* Is it an integer? */
size = PyNumber_AsSsize_t(x, PyExc_OverflowError);
if (size == -1 && PyErr_Occurred()) {
}
static PyObject *
-str_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+bytes_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
PyObject *tmp, *pnew;
Py_ssize_t n;
tmp = bytes_new(&PyBytes_Type, args, kwds);
if (tmp == NULL)
return NULL;
- assert(PyBytes_CheckExact(tmp));
+ assert(PyBytes_Check(tmp));
n = PyBytes_GET_SIZE(tmp);
pnew = type->tp_alloc(type, n);
if (pnew != NULL) {
/* Multiple references, need to create new object */
PyObject *v;
v = bytes_concat(*pv, w);
- Py_DECREF(*pv);
- *pv = v;
+ Py_SETREF(*pv, v);
}
}
return item;
}
- Py_DECREF(seq);
it->it_seq = NULL;
+ Py_DECREF(seq);
return NULL;
}
"cell",
sizeof(PyCellObject),
0,
- (destructor)cell_dealloc, /* tp_dealloc */
- 0, /* tp_print */
+ (destructor)cell_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_reserved */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
0, /* tp_doc */
(traverseproc)cell_traverse, /* tp_traverse */
(inquiry)cell_clear, /* tp_clear */
{
Py_ssize_t res;
- res = sizeof(PyCodeObject);
+ res = _PyObject_SIZE(Py_TYPE(co));
if (co->co_cell2arg != NULL && co->co_cellvars != NULL)
res += PyTuple_GET_SIZE(co->co_cellvars) * sizeof(unsigned char);
return PyLong_FromSsize_t(res);
}
}
+PyObject*
+_PyCode_ConstantKey(PyObject *op)
+{
+ PyObject *key;
+
+ /* Py_None and Py_Ellipsis are singleton */
+ if (op == Py_None || op == Py_Ellipsis
+ || PyLong_CheckExact(op)
+ || PyBool_Check(op)
+ || PyBytes_CheckExact(op)
+ || PyUnicode_CheckExact(op)
+ /* code_richcompare() uses _PyCode_ConstantKey() internally */
+ || PyCode_Check(op)) {
+ key = PyTuple_Pack(2, Py_TYPE(op), op);
+ }
+ else if (PyFloat_CheckExact(op)) {
+ double d = PyFloat_AS_DOUBLE(op);
+ /* all we need is to make the tuple different in either the 0.0
+ * or -0.0 case from all others, just to avoid the "coercion".
+ */
+ if (d == 0.0 && copysign(1.0, d) < 0.0)
+ key = PyTuple_Pack(3, Py_TYPE(op), op, Py_None);
+ else
+ key = PyTuple_Pack(2, Py_TYPE(op), op);
+ }
+ else if (PyComplex_CheckExact(op)) {
+ Py_complex z;
+ int real_negzero, imag_negzero;
+ /* For the complex case we must make complex(x, 0.)
+ different from complex(x, -0.) and complex(0., y)
+ different from complex(-0., y), for any x and y.
+ All four complex zeros must be distinguished.*/
+ z = PyComplex_AsCComplex(op);
+ real_negzero = z.real == 0.0 && copysign(1.0, z.real) < 0.0;
+ imag_negzero = z.imag == 0.0 && copysign(1.0, z.imag) < 0.0;
+ /* use True, False and None singleton as tags for the real and imag
+ * sign, to make tuples different */
+ if (real_negzero && imag_negzero) {
+ key = PyTuple_Pack(3, Py_TYPE(op), op, Py_True);
+ }
+ else if (imag_negzero) {
+ key = PyTuple_Pack(3, Py_TYPE(op), op, Py_False);
+ }
+ else if (real_negzero) {
+ key = PyTuple_Pack(3, Py_TYPE(op), op, Py_None);
+ }
+ else {
+ key = PyTuple_Pack(2, Py_TYPE(op), op);
+ }
+ }
+ else if (PyTuple_CheckExact(op)) {
+ Py_ssize_t i, len;
+ PyObject *tuple;
+
+ len = PyTuple_GET_SIZE(op);
+ tuple = PyTuple_New(len);
+ if (tuple == NULL)
+ return NULL;
+
+ for (i=0; i < len; i++) {
+ PyObject *item, *item_key;
+
+ item = PyTuple_GET_ITEM(op, i);
+ item_key = _PyCode_ConstantKey(item);
+ if (item_key == NULL) {
+ Py_DECREF(tuple);
+ return NULL;
+ }
+
+ PyTuple_SET_ITEM(tuple, i, item_key);
+ }
+
+ key = PyTuple_Pack(3, Py_TYPE(op), op, tuple);
+ Py_DECREF(tuple);
+ }
+ else if (PyFrozenSet_CheckExact(op)) {
+ Py_ssize_t pos = 0;
+ PyObject *item;
+ Py_hash_t hash;
+ Py_ssize_t i, len;
+ PyObject *tuple, *set;
+
+ len = PySet_GET_SIZE(op);
+ tuple = PyTuple_New(len);
+ if (tuple == NULL)
+ return NULL;
+
+ i = 0;
+ while (_PySet_NextEntry(op, &pos, &item, &hash)) {
+ PyObject *item_key;
+
+ item_key = _PyCode_ConstantKey(item);
+ if (item_key == NULL) {
+ Py_DECREF(tuple);
+ return NULL;
+ }
+
+ assert(i < len);
+ PyTuple_SET_ITEM(tuple, i, item_key);
+ i++;
+ }
+ set = PyFrozenSet_New(tuple);
+ Py_DECREF(tuple);
+ if (set == NULL)
+ return NULL;
+
+ key = PyTuple_Pack(3, Py_TYPE(op), op, set);
+ Py_DECREF(set);
+ return key;
+ }
+ else {
+ /* for other types, use the object identifier as a unique identifier
+ * to ensure that they are seen as unequal. */
+ PyObject *obj_id = PyLong_FromVoidPtr(op);
+ if (obj_id == NULL)
+ return NULL;
+
+ key = PyTuple_Pack(3, Py_TYPE(op), op, obj_id);
+ Py_DECREF(obj_id);
+ }
+ return key;
+}
+
static PyObject *
code_richcompare(PyObject *self, PyObject *other, int op)
{
PyCodeObject *co, *cp;
int eq;
+ PyObject *consts1, *consts2;
PyObject *res;
if ((op != Py_EQ && op != Py_NE) ||
if (!eq) goto unequal;
eq = PyObject_RichCompareBool(co->co_code, cp->co_code, Py_EQ);
if (eq <= 0) goto unequal;
- eq = PyObject_RichCompareBool(co->co_consts, cp->co_consts, Py_EQ);
+
+ /* compare constants */
+ consts1 = _PyCode_ConstantKey(co->co_consts);
+ if (!consts1)
+ return NULL;
+ consts2 = _PyCode_ConstantKey(cp->co_consts);
+ if (!consts2) {
+ Py_DECREF(consts1);
+ return NULL;
+ }
+ eq = PyObject_RichCompareBool(consts1, consts2, Py_EQ);
+ Py_DECREF(consts1);
+ Py_DECREF(consts2);
if (eq <= 0) goto unequal;
+
eq = PyObject_RichCompareBool(co->co_names, cp->co_names, Py_EQ);
if (eq <= 0) goto unequal;
eq = PyObject_RichCompareBool(co->co_varnames, cp->co_varnames, Py_EQ);
return NULL;
}
args = cached_args;
- if (!args || Py_REFCNT(args) != 1) {
- Py_CLEAR(cached_args);
- if (!(cached_args = args = PyTuple_New(1)))
+ cached_args = NULL;
+ if (!args) {
+ args = PyTuple_New(1);
+ if (!args)
return NULL;
+ _PyObject_GC_UNTRACK(args);
}
- Py_INCREF(args);
- assert (Py_REFCNT(args) == 2);
Py_INCREF(obj);
PyTuple_SET_ITEM(args, 0, obj);
ret = PyObject_Call(gs->prop_get, args, NULL);
- if (args == cached_args) {
- if (Py_REFCNT(args) == 2) {
- obj = PyTuple_GET_ITEM(args, 0);
- PyTuple_SET_ITEM(args, 0, NULL);
- Py_XDECREF(obj);
- }
- else {
- Py_CLEAR(cached_args);
- }
+ if (cached_args == NULL && Py_REFCNT(args) == 1) {
+ assert(Py_SIZE(args) == 1);
+ assert(PyTuple_GET_ITEM(args, 0) == obj);
+ cached_args = args;
+ Py_DECREF(obj);
+ }
+ else {
+ assert(Py_REFCNT(args) >= 1);
+ _PyObject_GC_TRACK(args);
+ Py_DECREF(args);
}
- Py_DECREF(args);
return ret;
}
PyObject *get_doc = _PyObject_GetAttrId(get, &PyId___doc__);
if (get_doc) {
if (Py_TYPE(self) == &PyProperty_Type) {
- Py_XDECREF(prop->prop_doc);
- prop->prop_doc = get_doc;
+ Py_XSETREF(prop->prop_doc, get_doc);
}
else {
/* If this is a property subclass, put __doc__
Let's just hope that no exception occurs then... This must be
_PyThreadState_Current and not PyThreadState_GET() because in debug
mode, the latter complains if tstate is NULL. */
- tstate = (PyThreadState*)_Py_atomic_load_relaxed(
- &_PyThreadState_Current);
+ tstate = _PyThreadState_UncheckedGet();
if (tstate != NULL && tstate->curexc_type != NULL) {
/* preserve the existing exception */
PyObject *err_type, *err_value, *err_tb;
Let's just hope that no exception occurs then... This must be
_PyThreadState_Current and not PyThreadState_GET() because in debug
mode, the latter complains if tstate is NULL. */
- tstate = (PyThreadState*)_Py_atomic_load_relaxed(
- &_PyThreadState_Current);
+ tstate = _PyThreadState_UncheckedGet();
if (tstate != NULL && tstate->curexc_type != NULL) {
/* preserve the existing exception */
PyObject *err_type, *err_value, *err_tb;
static PyObject *dictiter_new(PyDictObject *, PyTypeObject *);
-PyObject *
+Py_ssize_t
_PyDict_SizeOf(PyDictObject *mp)
{
Py_ssize_t size, res;
size = DK_SIZE(mp->ma_keys);
- res = sizeof(PyDictObject);
+ res = _PyObject_SIZE(Py_TYPE(mp));
if (mp->ma_values)
res += size * sizeof(PyObject*);
/* If the dictionary is split, the keys portion is accounted-for
in the type object. */
if (mp->ma_keys->dk_refcnt == 1)
res += sizeof(PyDictKeysObject) + (size-1) * sizeof(PyDictKeyEntry);
- return PyLong_FromSsize_t(res);
+ return res;
}
Py_ssize_t
return sizeof(PyDictKeysObject) + (DK_SIZE(keys)-1) * sizeof(PyDictKeyEntry);
}
+static PyObject *
+dict_sizeof(PyDictObject *mp)
+{
+ return PyLong_FromSsize_t(_PyDict_SizeOf(mp));
+}
+
PyDoc_STRVAR(getitem__doc__, "x.__getitem__(y) <==> x[y]");
PyDoc_STRVAR(sizeof__doc__,
DICT___CONTAINS___METHODDEF
{"__getitem__", (PyCFunction)dict_subscript, METH_O | METH_COEXIST,
getitem__doc__},
- {"__sizeof__", (PyCFunction)_PyDict_SizeOf, METH_NOARGS,
+ {"__sizeof__", (PyCFunction)dict_sizeof, METH_NOARGS,
sizeof__doc__},
{"get", (PyCFunction)dict_get, METH_VARARGS,
get__doc__},
return key;
fail:
- Py_DECREF(d);
di->di_dict = NULL;
+ Py_DECREF(d);
return NULL;
}
return value;
fail:
- Py_DECREF(d);
di->di_dict = NULL;
+ Py_DECREF(d);
return NULL;
}
return result;
fail:
- Py_DECREF(d);
di->di_dict = NULL;
+ Py_DECREF(d);
return NULL;
}
if (result == NULL)
return NULL;
- tmp = _PyObject_CallMethodId(result, &PyId_difference_update, "O", other);
+ tmp = _PyObject_CallMethodIdObjArgs(result, &PyId_difference_update, other, NULL);
if (tmp == NULL) {
Py_DECREF(result);
return NULL;
if (result == NULL)
return NULL;
- tmp = _PyObject_CallMethodId(result, &PyId_intersection_update, "O", other);
+ tmp = _PyObject_CallMethodIdObjArgs(result, &PyId_intersection_update, other, NULL);
if (tmp == NULL) {
Py_DECREF(result);
return NULL;
if (result == NULL)
return NULL;
- tmp = _PyObject_CallMethodId(result, &PyId_update, "O", other);
+ tmp = _PyObject_CallMethodIdObjArgs(result, &PyId_update, other, NULL);
if (tmp == NULL) {
Py_DECREF(result);
return NULL;
if (result == NULL)
return NULL;
- tmp = _PyObject_CallMethodId(result, &PyId_symmetric_difference_update, "O",
- other);
+ tmp = _PyObject_CallMethodIdObjArgs(result, &PyId_symmetric_difference_update, other, NULL);
if (tmp == NULL) {
Py_DECREF(result);
return NULL;
seq = PySequence_Tuple(val);
if (!seq)
return -1;
- Py_CLEAR(self->args);
- self->args = seq;
+ Py_XSETREF(self->args, seq);
return 0;
}
}
Py_XINCREF(tb);
- Py_XDECREF(self->traceback);
- self->traceback = tb;
+ Py_XSETREF(self->traceback, tb);
return 0;
}
if (size == 0)
return 0;
- Py_CLEAR(self->code);
- if (size == 1)
- self->code = PyTuple_GET_ITEM(args, 0);
- else /* size > 1 */
- self->code = args;
- Py_INCREF(self->code);
+ if (size == 1) {
+ Py_INCREF(PyTuple_GET_ITEM(args, 0));
+ Py_XSETREF(self->code, PyTuple_GET_ITEM(args, 0));
+ }
+ else { /* size > 1 */
+ Py_INCREF(args);
+ Py_XSETREF(self->code, args);
+ }
return 0;
}
#define GET_KWD(kwd) { \
kwd = PyDict_GetItemString(kwds, #kwd); \
if (kwd) { \
- Py_CLEAR(self->kwd); \
- self->kwd = kwd; \
- Py_INCREF(self->kwd);\
+ Py_INCREF(kwd); \
+ Py_XSETREF(self->kwd, kwd); \
if (PyDict_DelItemString(kwds, #kwd)) \
return -1; \
} \
if (!PyArg_UnpackTuple(args, "ImportError", 1, 1, &msg))
return -1;
- Py_CLEAR(self->msg); /* replacing */
- self->msg = msg;
- Py_INCREF(self->msg);
+ Py_INCREF(msg);
+ Py_XSETREF(self->msg, msg);
return 0;
}
#endif
/* Steals the reference to args */
- Py_CLEAR(self->args);
- self->args = args;
+ Py_XSETREF(self->args, args);
*p_args = args = NULL;
return 0;
solution, given __new__ takes a variable number of arguments,
is to defer arg parsing and initialization to __init__.
- But when __new__ is overriden as well, it should call our __new__
+ But when __new__ is overridden as well, it should call our __new__
with the right arguments.
(see http://bugs.python.org/issue12555#msg148829 )
return -1;
if (lenargs >= 1) {
- Py_CLEAR(self->msg);
- self->msg = PyTuple_GET_ITEM(args, 0);
- Py_INCREF(self->msg);
+ Py_INCREF(PyTuple_GET_ITEM(args, 0));
+ Py_XSETREF(self->msg, PyTuple_GET_ITEM(args, 0));
}
if (lenargs == 2) {
info = PyTuple_GET_ITEM(args, 1);
return -1;
}
- Py_CLEAR(self->filename);
- self->filename = PyTuple_GET_ITEM(info, 0);
- Py_INCREF(self->filename);
+ Py_INCREF(PyTuple_GET_ITEM(info, 0));
+ Py_XSETREF(self->filename, PyTuple_GET_ITEM(info, 0));
- Py_CLEAR(self->lineno);
- self->lineno = PyTuple_GET_ITEM(info, 1);
- Py_INCREF(self->lineno);
+ Py_INCREF(PyTuple_GET_ITEM(info, 1));
+ Py_XSETREF(self->lineno, PyTuple_GET_ITEM(info, 1));
- Py_CLEAR(self->offset);
- self->offset = PyTuple_GET_ITEM(info, 2);
- Py_INCREF(self->offset);
+ Py_INCREF(PyTuple_GET_ITEM(info, 2));
+ Py_XSETREF(self->offset, PyTuple_GET_ITEM(info, 2));
- Py_CLEAR(self->text);
- self->text = PyTuple_GET_ITEM(info, 3);
- Py_INCREF(self->text);
+ Py_INCREF(PyTuple_GET_ITEM(info, 3));
+ Py_XSETREF(self->text, PyTuple_GET_ITEM(info, 3));
Py_DECREF(info);
PyObject *obj = PyUnicode_FromString(value);
if (!obj)
return -1;
- Py_CLEAR(*attr);
- *attr = obj;
+ Py_XSETREF(*attr, obj);
return 0;
}
Py_buffer view;
if (PyObject_GetBuffer(ude->object, &view, PyBUF_SIMPLE) != 0)
goto error;
- Py_CLEAR(ude->object);
- ude->object = PyBytes_FromStringAndSize(view.buf, view.len);
+ Py_XSETREF(ude->object, PyBytes_FromStringAndSize(view.buf, view.len));
PyBuffer_Release(&view);
if (!ude->object)
goto error;
}
if (PyUnicode_Tailmatch(self->text, print_prefix,
start, text_len, -1)) {
- Py_CLEAR(self->msg);
- self->msg = PyUnicode_FromString(
- "Missing parentheses in call to 'print'");
+ Py_XSETREF(self->msg,
+ PyUnicode_FromString("Missing parentheses in call to 'print'"));
return 1;
}
}
if (PyUnicode_Tailmatch(self->text, exec_prefix,
start, text_len, -1)) {
- Py_CLEAR(self->msg);
- self->msg = PyUnicode_FromString(
- "Missing parentheses in call to 'exec'");
+ Py_XSETREF(self->msg,
+ PyUnicode_FromString("Missing parentheses in call to 'exec'"));
return 1;
}
/* Fall back to the default error message */
tmp = float_new(&PyFloat_Type, args, kwds);
if (tmp == NULL)
return NULL;
- assert(PyFloat_CheckExact(tmp));
+ assert(PyFloat_Check(tmp));
newobj = type->tp_alloc(type, 0);
if (newobj == NULL) {
Py_DECREF(tmp);
static int
frame_settrace(PyFrameObject *f, PyObject* v, void *closure)
{
- PyObject* old_value;
-
/* We rely on f_lineno being accurate when f_trace is set. */
f->f_lineno = PyFrame_GetLineNumber(f);
- old_value = f->f_trace;
+ if (v == Py_None)
+ v = NULL;
Py_XINCREF(v);
- f->f_trace = v;
- Py_XDECREF(old_value);
+ Py_XSETREF(f->f_trace, v);
return 0;
}
}
} else if (values[j] != value) {
Py_XINCREF(value);
- Py_XDECREF(values[j]);
- values[j] = value;
+ Py_XSETREF(values[j], value);
}
Py_XDECREF(value);
}
PyErr_SetString(PyExc_SystemError, "non-tuple default args");
return -1;
}
- Py_XDECREF(((PyFunctionObject *) op) -> func_defaults);
- ((PyFunctionObject *) op) -> func_defaults = defaults;
+ Py_XSETREF(((PyFunctionObject *)op)->func_defaults, defaults);
return 0;
}
"non-dict keyword only default args");
return -1;
}
- Py_XDECREF(((PyFunctionObject *)op) -> func_kwdefaults);
- ((PyFunctionObject *) op) -> func_kwdefaults = defaults;
+ Py_XSETREF(((PyFunctionObject *)op)->func_kwdefaults, defaults);
return 0;
}
closure->ob_type->tp_name);
return -1;
}
- Py_XDECREF(((PyFunctionObject *) op) -> func_closure);
- ((PyFunctionObject *) op) -> func_closure = closure;
+ Py_XSETREF(((PyFunctionObject *)op)->func_closure, closure);
return 0;
}
"non-dict annotations");
return -1;
}
- Py_XDECREF(((PyFunctionObject *)op) -> func_annotations);
- ((PyFunctionObject *) op) -> func_annotations = annotations;
+ Py_XSETREF(((PyFunctionObject *)op)->func_annotations, annotations);
return 0;
}
if (name != Py_None) {
Py_INCREF(name);
- Py_DECREF(newfunc->func_name);
- newfunc->func_name = name;
+ Py_SETREF(newfunc->func_name, name);
}
if (defaults != Py_None) {
Py_INCREF(defaults);
}
static PyObject *
-gen_send_ex(PyGenObject *gen, PyObject *arg, int exc)
+gen_send_ex(PyGenObject *gen, PyObject *arg, int exc, int closing)
{
PyThreadState *tstate = PyThreadState_GET();
PyFrameObject *f = gen->gi_frame;
return NULL;
}
if (f == NULL || f->f_stacktop == NULL) {
- /* Only set exception if called from send() */
- if (arg && !exc)
+ if (PyCoro_CheckExact(gen) && !closing) {
+ /* `gen` is an exhausted coroutine: raise an error,
+ except when called from gen_close(), which should
+ always be a silent method. */
+ PyErr_SetString(
+ PyExc_RuntimeError,
+ "cannot reuse already awaited coroutine");
+ } else if (arg && !exc) {
+ /* `gen` is an exhausted generator:
+ only set exception if called from send(). */
PyErr_SetNone(PyExc_StopIteration);
+ }
return NULL;
}
PyObject *
_PyGen_Send(PyGenObject *gen, PyObject *arg)
{
- return gen_send_ex(gen, arg, 0);
+ return gen_send_ex(gen, arg, 0, 0);
}
PyDoc_STRVAR(close_doc,
return 0;
}
-static PyObject *
-gen_yf(PyGenObject *gen)
+PyObject *
+_PyGen_yf(PyGenObject *gen)
{
PyObject *yf = NULL;
PyFrameObject *f = gen->gi_frame;
gen_close(PyGenObject *gen, PyObject *args)
{
PyObject *retval;
- PyObject *yf = gen_yf(gen);
+ PyObject *yf = _PyGen_yf(gen);
int err = 0;
if (yf) {
}
if (err == 0)
PyErr_SetNone(PyExc_GeneratorExit);
- retval = gen_send_ex(gen, Py_None, 1);
+ retval = gen_send_ex(gen, Py_None, 1, 1);
if (retval) {
char *msg = "generator ignored GeneratorExit";
if (PyCoro_CheckExact(gen))
PyObject *typ;
PyObject *tb = NULL;
PyObject *val = NULL;
- PyObject *yf = gen_yf(gen);
+ PyObject *yf = _PyGen_yf(gen);
_Py_IDENTIFIER(throw);
if (!PyArg_UnpackTuple(args, "throw", 1, 3, &typ, &val, &tb))
gen->gi_running = 0;
Py_DECREF(yf);
if (err < 0)
- return gen_send_ex(gen, Py_None, 1);
+ return gen_send_ex(gen, Py_None, 1, 0);
goto throw_here;
}
if (PyGen_CheckExact(yf)) {
/* Termination repetition of YIELD_FROM */
gen->gi_frame->f_lasti++;
if (_PyGen_FetchStopIterationValue(&val) == 0) {
- ret = gen_send_ex(gen, val, 0);
+ ret = gen_send_ex(gen, val, 0, 0);
Py_DECREF(val);
} else {
- ret = gen_send_ex(gen, Py_None, 1);
+ ret = gen_send_ex(gen, Py_None, 1, 0);
}
}
return ret;
}
PyErr_Restore(typ, val, tb);
- return gen_send_ex(gen, Py_None, 1);
+ return gen_send_ex(gen, Py_None, 1, 0);
failed_throw:
/* Didn't use our arguments, so restore their original refcounts */
static PyObject *
gen_iternext(PyGenObject *gen)
{
- return gen_send_ex(gen, NULL, 0);
+ return gen_send_ex(gen, NULL, 0, 0);
}
/*
static PyObject *
gen_getyieldfrom(PyGenObject *gen)
{
- PyObject *yf = gen_yf(gen);
+ PyObject *yf = _PyGen_yf(gen);
if (yf == NULL)
Py_RETURN_NONE;
return yf;
static PyObject *
coro_get_cr_await(PyCoroObject *coro)
{
- PyObject *yf = gen_yf((PyGenObject *) coro);
+ PyObject *yf = _PyGen_yf((PyGenObject *) coro);
if (yf == NULL)
Py_RETURN_NONE;
return yf;
static PyObject *
coro_wrapper_iternext(PyCoroWrapper *cw)
{
- return gen_send_ex((PyGenObject *)cw->cw_coroutine, NULL, 0);
+ return gen_send_ex((PyGenObject *)cw->cw_coroutine, NULL, 0, 0);
}
static PyObject *
coro_wrapper_send(PyCoroWrapper *cw, PyObject *arg)
{
- return gen_send_ex((PyGenObject *)cw->cw_coroutine, arg, 0);
+ return gen_send_ex((PyGenObject *)cw->cw_coroutine, arg, 0, 0);
}
static PyObject *
{
return gen_new_with_qualname(&PyCoro_Type, f, name, qualname);
}
+
+
+/* __aiter__ wrapper; see http://bugs.python.org/issue27243 for details. */
+
+typedef struct {
+ PyObject_HEAD
+ PyObject *aw_aiter;
+} PyAIterWrapper;
+
+
+static PyObject *
+aiter_wrapper_iternext(PyAIterWrapper *aw)
+{
+ PyErr_SetObject(PyExc_StopIteration, aw->aw_aiter);
+ return NULL;
+}
+
+static int
+aiter_wrapper_traverse(PyAIterWrapper *aw, visitproc visit, void *arg)
+{
+ Py_VISIT((PyObject *)aw->aw_aiter);
+ return 0;
+}
+
+static void
+aiter_wrapper_dealloc(PyAIterWrapper *aw)
+{
+ _PyObject_GC_UNTRACK((PyObject *)aw);
+ Py_CLEAR(aw->aw_aiter);
+ PyObject_GC_Del(aw);
+}
+
+static PyAsyncMethods aiter_wrapper_as_async = {
+ PyObject_SelfIter, /* am_await */
+ 0, /* am_aiter */
+ 0 /* am_anext */
+};
+
+PyTypeObject _PyAIterWrapper_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "aiter_wrapper",
+ sizeof(PyAIterWrapper), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)aiter_wrapper_dealloc, /* destructor tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ &aiter_wrapper_as_async, /* 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 */
+ "A wrapper object for __aiter__ bakwards compatibility.",
+ (traverseproc)aiter_wrapper_traverse, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ PyObject_SelfIter, /* tp_iter */
+ (iternextfunc)aiter_wrapper_iternext, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+ PyObject_Del, /* tp_free */
+};
+
+
+PyObject *
+_PyAIterWrapper_New(PyObject *aiter)
+{
+ PyAIterWrapper *aw = PyObject_GC_New(PyAIterWrapper,
+ &_PyAIterWrapper_Type);
+ if (aw == NULL) {
+ return NULL;
+ }
+ Py_INCREF(aiter);
+ aw->aw_aiter = aiter;
+ _PyObject_GC_TRACK(aw);
+ return (PyObject *)aw;
+}
PyErr_ExceptionMatches(PyExc_StopIteration))
{
PyErr_Clear();
- Py_DECREF(seq);
it->it_seq = NULL;
+ Py_DECREF(seq);
}
return NULL;
}
{
Py_ssize_t res;
- res = sizeof(PyListObject) + self->allocated * sizeof(void*);
+ res = _PyObject_SIZE(Py_TYPE(self)) + self->allocated * sizeof(void*);
return PyLong_FromSsize_t(res);
}
return item;
}
- Py_DECREF(seq);
it->it_seq = NULL;
+ Py_DECREF(seq);
return NULL;
}
listreviter_next(listreviterobject *it)
{
PyObject *item;
- Py_ssize_t index = it->it_index;
- PyListObject *seq = it->it_seq;
+ Py_ssize_t index;
+ PyListObject *seq;
+
+ assert(it != NULL);
+ seq = it->it_seq;
+ if (seq == NULL) {
+ return NULL;
+ }
+ assert(PyList_Check(seq));
+ index = it->it_index;
if (index>=0 && index < PyList_GET_SIZE(seq)) {
item = PyList_GET_ITEM(seq, index);
it->it_index--;
return item;
}
it->it_index = -1;
- if (seq != NULL) {
- it->it_seq = NULL;
- Py_DECREF(seq);
- }
+ it->it_seq = NULL;
+ Py_DECREF(seq);
return NULL;
}
tmp = (PyLongObject *)long_new(&PyLong_Type, args, kwds);
if (tmp == NULL)
return NULL;
- assert(PyLong_CheckExact(tmp));
+ assert(PyLong_Check(tmp));
n = Py_SIZE(tmp);
if (n < 0)
n = -n;
little_endian, is_signed);
Py_DECREF(bytes);
- /* If from_bytes() was used on subclass, allocate new subclass
- * instance, initialize it with decoded int value and return it.
- */
- if (type != &PyLong_Type && PyType_IsSubtype(type, &PyLong_Type)) {
- PyLongObject *newobj;
- int i;
- Py_ssize_t n = Py_ABS(Py_SIZE(long_obj));
-
- newobj = (PyLongObject *)type->tp_alloc(type, n);
- if (newobj == NULL) {
- Py_DECREF(long_obj);
- return NULL;
- }
- assert(PyLong_Check(newobj));
- Py_SIZE(newobj) = Py_SIZE(long_obj);
- for (i = 0; i < n; i++) {
- newobj->ob_digit[i] =
- ((PyLongObject *)long_obj)->ob_digit[i];
- }
- Py_DECREF(long_obj);
- return (PyObject *)newobj;
+ if (type != &PyLong_Type) {
+ Py_SETREF(long_obj, PyObject_CallFunctionObjArgs((PyObject *)type,
+ long_obj, NULL));
}
return long_obj;
return -1;
if (PyUnicode_CheckExact(name)) {
Py_INCREF(name);
- Py_XDECREF(mod->md_name);
- mod->md_name = name;
+ Py_XSETREF(mod->md_name, name);
}
return 0;
/* These methods are used to control infinite recursion in repr, str, print,
etc. Container objects that may recursively contain themselves,
- e.g. builtin dictionaries and lists, should used Py_ReprEnter() and
+ e.g. builtin dictionaries and lists, should use Py_ReprEnter() and
Py_ReprLeave() to avoid infinite recursion.
Py_ReprEnter() returns 0 the first time it is called for a particular
{
_ODictNode *node, *next;
- if (!_odict_EMPTY(od)) {
- node = _odict_FIRST(od);
- while (node != NULL) {
- next = _odictnode_NEXT(node);
- _odictnode_DEALLOC(node);
- node = next;
- }
- _odict_FIRST(od) = NULL;
- _odict_LAST(od) = NULL;
- }
-
_odict_free_fast_nodes(od);
od->od_fast_nodes = NULL;
+
+ node = _odict_FIRST(od);
+ _odict_FIRST(od) = NULL;
+ _odict_LAST(od) = NULL;
+ while (node != NULL) {
+ next = _odictnode_NEXT(node);
+ _odictnode_DEALLOC(node);
+ node = next;
+ }
}
/* There isn't any memory management of nodes past this point. */
static PyObject *
odict_sizeof(PyODictObject *od)
{
- PyObject *pylong;
- Py_ssize_t res, temp;
-
- pylong = _PyDict_SizeOf((PyDictObject *)od);
- if (pylong == NULL)
- return NULL;
- res = PyLong_AsSsize_t(pylong);
- Py_DECREF(pylong);
- if (res == -1 && PyErr_Occurred())
- return NULL;
-
- res += sizeof(PyODictObject) - sizeof(PyDictObject);
-
- /* instance dict */
- pylong = _PyDict_SizeOf((PyDictObject *)od->od_inst_dict);
- if (pylong == NULL)
- return NULL;
- temp = PyLong_AsSsize_t(pylong);
- Py_DECREF(pylong);
- if (temp == -1 && PyErr_Occurred())
- return NULL;
- res += temp;
-
+ Py_ssize_t res = _PyDict_SizeOf((PyDictObject *)od);
res += sizeof(_ODictNode *) * _odict_FAST_SIZE(od); /* od_fast_nodes */
if (!_odict_EMPTY(od)) {
res += sizeof(_ODictNode) * PyODict_SIZE(od); /* linked-list */
{
PyDict_Clear((PyObject *)od);
_odict_clear_nodes(od);
- _odict_FIRST(od) = NULL;
- _odict_LAST(od) = NULL;
if (_odict_resize(od) < 0)
return NULL;
Py_RETURN_NONE;
static int
odict_traverse(PyODictObject *od, visitproc visit, void *arg)
{
+ _ODictNode *node;
+
Py_VISIT(od->od_inst_dict);
Py_VISIT(od->od_weakreflist);
+ _odict_FOREACH(od, node) {
+ Py_VISIT(_odictnode_KEY(node));
+ }
return PyDict_Type.tp_traverse((PyObject *)od, visit, arg);
}
/* Support objects whose length is > PY_SSIZE_T_MAX.
- This could be sped up for small PyLongs if they fit in an Py_ssize_t.
+ This could be sped up for small PyLongs if they fit in a Py_ssize_t.
This only matters on Win64. Though we could use PY_LONG_LONG which
would presumably help perf.
*/
return NULL;
cmp = PyObject_RichCompareBool(state, zero, Py_LT);
if (cmp > 0) {
- Py_CLEAR(r->index);
- r->index = zero;
+ Py_XSETREF(r->index, zero);
Py_RETURN_NONE;
}
Py_DECREF(zero);
if (cmp > 0)
state = r->len;
- Py_CLEAR(r->index);
- r->index = state;
- Py_INCREF(r->index);
+ Py_INCREF(state);
+ Py_XSETREF(r->index, state);
Py_RETURN_NONE;
}
result = PyNumber_Add(r->start, product);
Py_DECREF(product);
if (result) {
- Py_DECREF(r->index);
- r->index = new_index;
+ Py_SETREF(r->index, new_index);
}
else {
Py_DECREF(new_index);
Written and maintained by Raymond D. Hettinger <python@rcn.com>
Derived from Lib/sets.py and Objects/dictobject.c.
- Copyright (c) 2003-2015 Python Software Foundation.
- All rights reserved.
-
The basic lookup function used by all operations.
This is based on Algorithm D from Knuth Vol. 3, Sec. 6.4.
return key;
fail:
- Py_DECREF(so);
si->si_set = NULL;
+ Py_DECREF(so);
return NULL;
}
{
Py_ssize_t res;
- res = sizeof(PySetObject);
+ res = _PyObject_SIZE(Py_TYPE(so));
if (so->table != so->smalltable)
res = res + (so->mask + 1) * sizeof(setentry);
return PyLong_FromSsize_t(res);
PySliceObject *obj = slice_cache;
if (obj != NULL) {
slice_cache = NULL;
- PyObject_Del(obj);
+ PyObject_GC_Del(obj);
}
}
slice_cache = NULL;
_Py_NewReference((PyObject *)obj);
} else {
- obj = PyObject_New(PySliceObject, &PySlice_Type);
+ obj = PyObject_GC_New(PySliceObject, &PySlice_Type);
if (obj == NULL)
return NULL;
}
obj->start = start;
obj->stop = stop;
+ _PyObject_GC_TRACK(obj);
return (PyObject *) obj;
}
static void
slice_dealloc(PySliceObject *r)
{
+ _PyObject_GC_UNTRACK(r);
Py_DECREF(r->step);
Py_DECREF(r->start);
Py_DECREF(r->stop);
if (slice_cache == NULL)
slice_cache = r;
else
- PyObject_Del(r);
+ PyObject_GC_Del(r);
}
static PyObject *
return res;
}
+static int
+slice_traverse(PySliceObject *v, visitproc visit, void *arg)
+{
+ Py_VISIT(v->start);
+ Py_VISIT(v->stop);
+ Py_VISIT(v->step);
+ return 0;
+}
+
PyTypeObject PySlice_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
"slice", /* Name of this type */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT, /* tp_flags */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
slice_doc, /* tp_doc */
- 0, /* tp_traverse */
+ (traverseproc)slice_traverse, /* tp_traverse */
0, /* tp_clear */
slice_richcompare, /* tp_richcompare */
0, /* tp_weaklistoffset */
0};
/* unicode_formatter_field_name_split is used to implement
- string.Formatter.vformat. it takes an PEP 3101 "field name", and
+ string.Formatter.vformat. it takes a PEP 3101 "field name", and
returns a tuple of (first, rest): "first", the part before the
first '.' or '['; and "rest", an iterator for the rest of the field
name. it's a wrapper around stringlib/string_format.h's
return item;
}
- Py_DECREF(seq);
it->it_seq = NULL;
+ Py_DECREF(seq);
return NULL;
}
are borrowed reference */
for (i = 0; i < (1 << MCACHE_SIZE_EXP); i++) {
method_cache[i].value = NULL;
- Py_XDECREF(method_cache[i].name);
- method_cache[i].name = Py_None;
Py_INCREF(Py_None);
+ Py_XSETREF(method_cache[i].name, Py_None);
}
/* mark all version tags as invalid */
PyType_Modified(&PyBaseObject_Type);
static int
type_set_name(PyTypeObject *type, PyObject *value, void *context)
{
- PyHeapTypeObject* et;
- char *tp_name;
- PyObject *tmp;
+ const char *tp_name;
+ Py_ssize_t name_size;
if (!check_set_special_type_attr(type, value, "__name__"))
return -1;
return -1;
}
- /* Check absence of null characters */
- tmp = PyUnicode_FromStringAndSize("\0", 1);
- if (tmp == NULL)
+ tp_name = PyUnicode_AsUTF8AndSize(value, &name_size);
+ if (tp_name == NULL)
return -1;
- if (PyUnicode_Contains(value, tmp) != 0) {
- Py_DECREF(tmp);
- PyErr_Format(PyExc_ValueError,
- "__name__ must not contain null bytes");
+ if (strlen(tp_name) != (size_t)name_size) {
+ PyErr_SetString(PyExc_ValueError,
+ "type name must not contain null characters");
return -1;
}
- Py_DECREF(tmp);
-
- tp_name = _PyUnicode_AsString(value);
- if (tp_name == NULL)
- return -1;
-
- et = (PyHeapTypeObject*)type;
-
- Py_INCREF(value);
-
- /* Wait until et is a sane state before Py_DECREF'ing the old et->ht_name
- value. (Bug #16447.) */
- tmp = et->ht_name;
- et->ht_name = value;
type->tp_name = tp_name;
- Py_DECREF(tmp);
+ Py_INCREF(value);
+ Py_SETREF(((PyHeapTypeObject*)type)->ht_name, value);
return 0;
}
et = (PyHeapTypeObject*)type;
Py_INCREF(value);
- Py_DECREF(et->ht_qualname);
- et->ht_qualname = value;
+ Py_SETREF(et->ht_qualname, value);
return 0;
}
PyTypeObject *type = NULL, *base, *tmptype, *winner;
PyHeapTypeObject *et;
PyMemberDef *mp;
- Py_ssize_t i, nbases, nslots, slotoffset, add_dict, add_weak;
- int j, may_add_dict, may_add_weak;
+ Py_ssize_t i, nbases, nslots, slotoffset, name_size;
+ int j, may_add_dict, may_add_weak, add_dict, add_weak;
_Py_IDENTIFIER(__qualname__);
_Py_IDENTIFIER(__slots__);
type->tp_as_sequence = &et->as_sequence;
type->tp_as_mapping = &et->as_mapping;
type->tp_as_buffer = &et->as_buffer;
- type->tp_name = _PyUnicode_AsString(name);
+ type->tp_name = PyUnicode_AsUTF8AndSize(name, &name_size);
if (!type->tp_name)
goto error;
+ if (strlen(type->tp_name) != (size_t)name_size) {
+ PyErr_SetString(PyExc_ValueError,
+ "type name must not contain null characters");
+ goto error;
+ }
/* Set tp_base and tp_bases */
type->tp_bases = bases;
tmp = PyStaticMethod_New(tmp);
if (tmp == NULL)
goto error;
- if (_PyDict_SetItemId(dict, &PyId___new__, tmp) < 0)
+ if (_PyDict_SetItemId(dict, &PyId___new__, tmp) < 0) {
+ Py_DECREF(tmp);
goto error;
+ }
Py_DECREF(tmp);
}
else
method_cache_misses++;
#endif
- Py_DECREF(method_cache[h].name);
- method_cache[h].name = name;
+ Py_SETREF(method_cache[h].name, name);
}
return res;
}
}
Py_LOCAL(PyObject *)
-_PyObject_GetState(PyObject *obj)
+_PyObject_GetState(PyObject *obj, int required)
{
PyObject *state;
PyObject *getstate;
}
PyErr_Clear();
+ if (required && obj->ob_type->tp_itemsize) {
+ PyErr_Format(PyExc_TypeError,
+ "can't pickle %.200s objects",
+ Py_TYPE(obj)->tp_name);
+ return NULL;
+ }
+
{
PyObject **dict;
dict = _PyObject_GetDictPtr(obj);
PyObject *name, *value;
name = PyList_GET_ITEM(slotnames, i);
+ Py_INCREF(name);
value = PyObject_GetAttr(obj, name);
if (value == NULL) {
+ Py_DECREF(name);
if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
goto error;
}
}
else {
int err = PyDict_SetItem(slots, name, value);
+ Py_DECREF(name);
Py_DECREF(value);
if (err) {
goto error;
}
}
- /* The list is stored on the class so it may mutates while we
+ /* The list is stored on the class so it may mutate while we
iterate over it */
if (slotnames_size != Py_SIZE(slotnames)) {
PyErr_Format(PyExc_RuntimeError,
}
/* The object does not have __getnewargs_ex__ and __getnewargs__. This may
- means __new__ does not takes any arguments on this object, or that the
+ mean __new__ does not takes any arguments on this object, or that the
object does not implement the reduce protocol for pickling or
copying. */
*args = NULL;
PyObject *copyreg;
PyObject *newobj, *newargs, *state, *listitems, *dictitems;
PyObject *result;
+ int hasargs;
if (Py_TYPE(obj)->tp_new == NULL) {
PyErr_Format(PyExc_TypeError,
- "can't pickle %s objects",
+ "can't pickle %.200s objects",
Py_TYPE(obj)->tp_name);
return NULL;
}
if (_PyObject_GetNewArguments(obj, &args, &kwargs) < 0)
return NULL;
- if (args == NULL) {
- args = PyTuple_New(0);
- if (args == NULL) {
- Py_XDECREF(kwargs);
- return NULL;
- }
- }
copyreg = import_copyreg();
if (copyreg == NULL) {
- Py_DECREF(args);
+ Py_XDECREF(args);
Py_XDECREF(kwargs);
return NULL;
}
+ hasargs = (args != NULL);
if (kwargs == NULL || PyDict_Size(kwargs) == 0) {
_Py_IDENTIFIER(__newobj__);
PyObject *cls;
newobj = _PyObject_GetAttrId(copyreg, &PyId___newobj__);
Py_DECREF(copyreg);
if (newobj == NULL) {
- Py_DECREF(args);
+ Py_XDECREF(args);
return NULL;
}
- n = PyTuple_GET_SIZE(args);
+ n = args ? PyTuple_GET_SIZE(args) : 0;
newargs = PyTuple_New(n+1);
if (newargs == NULL) {
- Py_DECREF(args);
+ Py_XDECREF(args);
Py_DECREF(newobj);
return NULL;
}
Py_INCREF(v);
PyTuple_SET_ITEM(newargs, i+1, v);
}
- Py_DECREF(args);
+ Py_XDECREF(args);
}
else if (proto >= 4) {
_Py_IDENTIFIER(__newobj_ex__);
return NULL;
}
- state = _PyObject_GetState(obj);
+ state = _PyObject_GetState(obj,
+ !hasargs && !PyList_Check(obj) && !PyDict_Check(obj));
if (state == NULL) {
Py_DECREF(newobj);
Py_DECREF(newargs);
Py_INCREF(obj);
}
Py_INCREF(type);
- su->type = type;
- su->obj = obj;
- su->obj_type = obj_type;
+ Py_XSETREF(su->type, type);
+ Py_XSETREF(su->obj, obj);
+ Py_XSETREF(su->obj_type, obj_type);
return 0;
}
}
#ifdef Py_DEBUG
-/* Fill the data of an Unicode string with invalid characters to detect bugs
+/* Fill the data of a Unicode string with invalid characters to detect bugs
earlier.
_PyUnicode_CheckConsistency(str, 1) detects invalid characters, at least for
else if (_PyUnicode_HAS_WSTR_MEMORY(unicode)) {
PyObject_DEL(_PyUnicode_WSTR(unicode));
_PyUnicode_WSTR(unicode) = NULL;
+ if (!PyUnicode_IS_ASCII(unicode))
+ _PyUnicode_WSTR_LENGTH(unicode) = 0;
}
#ifdef Py_DEBUG
unicode_fill_invalid(unicode, old_length);
_Py_INCREF_UNICODE_EMPTY();
if (!unicode_empty)
return -1;
- Py_DECREF(*p_unicode);
- *p_unicode = unicode_empty;
+ Py_SETREF(*p_unicode, unicode_empty);
return 0;
}
PyObject *copy = resize_copy(unicode, length);
if (copy == NULL)
return -1;
- Py_DECREF(*p_unicode);
- *p_unicode = copy;
+ Py_SETREF(*p_unicode, copy);
return 0;
}
translated into writer, raise an exception and return -1 on error. */
static int
unicode_fast_translate(PyObject *input, PyObject *mapping,
- _PyUnicodeWriter *writer, int ignore)
+ _PyUnicodeWriter *writer, int ignore,
+ Py_ssize_t *input_pos)
{
Py_UCS1 ascii_table[128], ch, ch2;
Py_ssize_t len;
Py_UCS1 *in, *end, *out;
int res = 0;
- if (PyUnicode_READY(input) == -1)
- return -1;
- if (!PyUnicode_IS_ASCII(input))
- return 0;
len = PyUnicode_GET_LENGTH(input);
memset(ascii_table, 0xff, 128);
exit:
writer->pos = out - PyUnicode_1BYTE_DATA(writer->buffer);
+ *input_pos = in - PyUnicode_1BYTE_DATA(input);
return res;
}
ignore = (errors != NULL && strcmp(errors, "ignore") == 0);
- res = unicode_fast_translate(input, mapping, &writer, ignore);
- if (res < 0) {
- _PyUnicodeWriter_Dealloc(&writer);
+ if (PyUnicode_READY(input) == -1)
return NULL;
+ if (PyUnicode_IS_ASCII(input)) {
+ res = unicode_fast_translate(input, mapping, &writer, ignore, &i);
+ if (res < 0) {
+ _PyUnicodeWriter_Dealloc(&writer);
+ return NULL;
+ }
+ if (res == 1)
+ return _PyUnicodeWriter_Finish(&writer);
+ }
+ else {
+ i = 0;
}
- if (res == 1)
- return _PyUnicodeWriter_Finish(&writer);
- i = writer.pos;
while (i<size) {
/* try to encode it */
int translate;
PyUnicode_GET_LENGTH(substring) *
PyUnicode_KIND(substring));
}
- /* otherwise we have to compare each character by first accesing it */
+ /* otherwise we have to compare each character by first accessing it */
else {
/* We do not need to compare 0 and len(substring)-1 because
the if statement above ensured already that they are equal
return -1;
_PyUnicode_FastCopyCharacters(newbuffer, 0,
writer->buffer, 0, writer->pos);
- Py_DECREF(writer->buffer);
- writer->buffer = newbuffer;
+ Py_SETREF(writer->buffer, newbuffer);
}
_PyUnicodeWriter_Update(writer);
return 0;
if (key == NULL)
return -1;
if (ctx->args_owned) {
- Py_DECREF(ctx->args);
ctx->args_owned = 0;
+ Py_DECREF(ctx->args);
}
ctx->args = PyObject_GetItem(ctx->dict, key);
Py_DECREF(key);
if (t) {
Py_INCREF(t);
- Py_DECREF(*p);
- *p = t;
+ Py_SETREF(*p, t);
return;
}
return item;
}
- Py_DECREF(seq);
it->it_seq = NULL;
+ Py_DECREF(seq);
return NULL;
}
parse_weakref_init_args(char *funcname, PyObject *args, PyObject *kwargs,
PyObject **obp, PyObject **callbackp)
{
- /* XXX Should check that kwargs == NULL or is empty. */
return PyArg_UnpackTuple(args, funcname, 1, 2, obp, callbackp);
}
{
PyObject *tmp;
+ if (!_PyArg_NoKeywords("ref()", kwargs))
+ return -1;
+
if (parse_weakref_init_args("__init__", args, kwargs, &tmp, &tmp))
return 0;
else
<PropertyGroup Label="Globals">
<ProjectGuid>{EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}</ProjectGuid>
<RootNamespace>wininst</RootNamespace>
- <MakeVersionInfoBeforeTarget>ClCompile</MakeVersionInfoBeforeTarget>
<SupportPGO>false</SupportPGO>
</PropertyGroup>
<Import Project="..\..\PCBuild\python.props" />
<Optimization>MinSpace</Optimization>
<AdditionalIncludeDirectories>$(PySourcePath)Modules\zlib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary Condition="'$(Configuration)'=='Debug'">MultiThreadedDebug</RuntimeLibrary>
+ <RuntimeLibrary Condition="'$(Configuration)'=='Release'">MultiThreaded</RuntimeLibrary>
</ClCompile>
<ResourceCompile>
<AdditionalIncludeDirectories>$(PySourcePath)PC\bdist_wininst;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
HANDLE hBitmap;
char *bitmap_bytes;
+static const char *REGISTRY_SUFFIX_6432 =
+#ifdef MS_WIN64
+ "";
+#else
+ "-32";
+#endif
+
#define WM_NUMFILES WM_USER+1
/* wParam: 0, lParam: total number of files */
if (h)
return h;
wsprintf(subkey_name,
- "SOFTWARE\\Python\\PythonCore\\%d.%d\\InstallPath",
- py_major, py_minor);
+ "SOFTWARE\\Python\\PythonCore\\%d.%d%s\\InstallPath",
+ py_major, py_minor, REGISTRY_SUFFIX_6432);
if (ERROR_SUCCESS != RegQueryValue(HKEY_CURRENT_USER, subkey_name,
fullpath, &size) &&
ERROR_SUCCESS != RegQueryValue(HKEY_LOCAL_MACHINE, subkey_name,
return NULL;
strcat(fullpath, "\\");
strcat(fullpath, fname);
- return LoadLibrary(fullpath);
+ // We use LOAD_WITH_ALTERED_SEARCH_PATH to ensure any dependent DLLs
+ // next to the Python DLL (eg, the CRT DLL) are also loaded.
+ return LoadLibraryEx(fullpath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
}
static int prepare_script_environment(HINSTANCE hPython)
GetPrivateProfileString("Setup", "user_access_control", "",
user_access_control, sizeof(user_access_control), ini_file);
+ strcat(target_version, REGISTRY_SUFFIX_6432);
+
// See if we need to do the Vista UAC magic.
if (strcmp(user_access_control, "force")==0) {
if (!MyIsUserAnAdmin()) {
"ConnectRegistry($module, computer_name, key, /)\n"
"--\n"
"\n"
-"Establishes a connection to the registry on on another computer.\n"
+"Establishes a connection to the registry on another computer.\n"
"\n"
" computer_name\n"
" The name of the remote computer, of the form r\"\\\\computername\". If\n"
" references to environment variables (for example,\n"
" %PATH%).\n"
" REG_LINK -- A Unicode symbolic link.\n"
-" REG_MULTI_SZ -- An sequence of null-terminated strings, terminated\n"
+" REG_MULTI_SZ -- A sequence of null-terminated strings, terminated\n"
" by two null characters. Note that Python handles\n"
" this termination automatically.\n"
" REG_NONE -- No defined value type.\n"
exit:
return return_value;
}
-/*[clinic end generated code: output=71f5bc30b646807b input=a9049054013a1b77]*/
+/*[clinic end generated code: output=5e346dccc296f9f1 input=a9049054013a1b77]*/
dataBuf = PyMem_RawMalloc((dataSize+1) * sizeof(WCHAR));
if (dataBuf) {
WCHAR *szCur = dataBuf;
- DWORD reqdSize = dataSize;
/* Copy our collected strings */
for (index=0;index<numKeys;index++) {
if (index > 0) {
*/
rc = RegQueryValueExW(newKey, NULL, 0, NULL,
(LPBYTE)szCur, &dataSize);
+ if (rc != ERROR_SUCCESS) {
+ PyMem_RawFree(dataBuf);
+ goto done;
+ }
}
/* And set the result - caller must free */
retval = dataBuf;
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<svg version="1.0" width="744.09448" height="1052.3622" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
- <defs>
- <linearGradient id="pyYellowGradient">
- <stop offset="0" style="stop-color:#ffc130;stop-opacity:1"/>
- <stop offset="1" style="stop-color:#ffea5b;stop-opacity:1"/>
- </linearGradient>
- <linearGradient id="pyBlueGradient">
- <stop style="stop-color:#426684;stop-opacity:1" offset="0"/>
- <stop style="stop-color:#357cb5;stop-opacity:1" offset="1"/>
- </linearGradient>
- <linearGradient id="pyYellow" xlink:href="#pyYellowGradient" x1="1108.9739" y1="3365.6448" x2="949.80927" y2="3144.1941" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.317715,0,0,0.317715,-172.579,-583.027)"/>
- <linearGradient id="pyBlue" xlink:href="#pyBlueGradient" x1="607.27795" y1="1841.619" x2="472.67371" y2="1660.6002" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.317715,0,0,0.317715,-71.39343,-151.2348)"/>
- </defs>
-
- <g
- id="layer1">
- <path
- d="M 88.126188,110.89374 C 88.126188,99.932569 97.021954,91.036422 107.98312,91.023301 L 147.69781,91.023301 C 158.65898,91.036435 167.55475,99.932569 167.55475,110.88023 L 167.55475,148.11929 C 167.55475,159.08046 158.65898,167.97661 147.69781,167.97661 L 107.98312,167.97661 C 94.281853,167.97661 83.161955,179.0965 83.161955,192.79777 L 83.161955,210.17955 L 68.268873,210.16643 C 57.307706,210.17955 48.411559,201.27028 48.411559,190.30911 L 48.411559,150.59472 C 48.411559,139.64668 57.307706,130.73741 68.268873,130.73741 L 127.84044,130.75054 L 127.84044,125.78631 L 88.126061,125.78631 L 88.126061,110.89361 L 88.126188,110.89374 z M 105.49443,100.96489 C 109.61173,100.96489 112.94774,104.3009 112.94774,108.40504 C 112.94774,112.52196 109.61173,115.85797 105.49443,115.85797 C 101.39066,115.85797 98.041501,112.52196 98.041501,108.40504 C 98.041501,104.3009 101.39063,100.96489 105.49443,100.96489 z "
- style="fill:#426684;fill-rule:evenodd"
- id="path6" />
- <g
- transform="matrix(0.317715,0,0,0.317715,-71.39343,-151.2348)"
- style="fill-rule:evenodd"
- id="_19410248">
- <g
- id="g9">
- <path
- d="M 1102.42,902.293 C 1160.3365,901.33394 1186.6279,955.8347 1187.0861,1017.668 C 1187.0861,1072.1676 1159.8369,1123.293 1101.4196,1125.21 C 1077.5861,1125.21 1057.1283,1117.9179 1037.17,1105.7513 L 1037.17,1231.8353 L 1002.1279,1219.168 L 1002.6287,939.293 C 1002.1279,939.293 1029.8779,902.7934 1101.9204,901.793 L 1102.42,902.29379 L 1102.42,902.293 z M 1093.6279,1099.917 C 1140.3783,1097.0009 1146.2118,1051.2509 1146.2118,1015.2095 C 1146.2118,980.1674 1140.3783,927.5835 1096.087,925.6678 C 1065.9205,923.70953 1041.5449,937.8343 1036.7118,942.7087 L 1036.7118,1081.4177 C 1048.3787,1088.7098 1071.7527,1101.376 1093.6279,1099.9173 L 1093.6279,1099.917 z "
- style="fill:#6a6a6a"
- id="_19410568" />
-
- <path
- d="M 1261,1051.25 L 1261,901.791 L 1224.9587,913.9587 L 1224.9587,1061.9577 C 1224.9587,1101.3746 1261.4996,1124.249 1293.6244,1124.249 C 1335.4579,1124.249 1359.3327,1112.5833 1370.0405,1107.7077 C 1370.4988,1113.0416 1370.0405,1111.5829 1370.0405,1116.9581 C 1370.0405,1132.5416 1369.5409,1159.2912 1362.2488,1172.9164 C 1347.6244,1200.6664 1308.7071,1204.5416 1281.4579,1208.4581 L 1287.2902,1230.8329 C 1323.2902,1229.875 1373.9158,1216.2498 1391.9162,1182.1668 C 1402.1658,1162.7081 1403.6245,1125.2081 1403.6245,1100.4168 L 1403.6245,907.16579 L 1368.0828,907.16579 L 1368.0828,1080.9168 C 1356.4159,1088.7085 1335.0001,1099.4164 1315.9997,1099.916 C 1284.3745,1100.4168 1261.0005,1083.3747 1261.0005,1050.7491 L 1261.0005,1051.2499 L 1261,1051.25 z "
- style="fill:#6a6a6a"
- id="_19412384" />
-
- <path
- d="M 1463.29,930.043 L 1463.29,1069.751 C 1463.29,1106.2506 1491.5396,1127.6675 1538.7483,1123.2927 L 1538.7483,1104.7931 C 1513.9144,1103.7927 1498.8318,1097.0014 1498.8318,1068.7506 L 1498.8318,930.0436 L 1538.7483,930.0436 L 1538.7483,907.168 L 1498.8318,907.168 L 1498.8318,835.1267 L 1463.2901,847.7928 L 1463.2901,907.168 L 1438.957,907.168 L 1438.957,930.0436 L 1463.2901,930.0436 L 1463.29,930.043 z "
- style="fill:#6a6a6a"
- id="_19413104" />
-
- <path
- d="M 1754.5,1120.33 L 1754.5,971.914 C 1754.5,934.9136 1729.1665,905.7061 1691.2083,905.7061 C 1662.5004,905.7061 1638.1674,914.95531 1616.7504,930.4974 L 1616.7504,781.0804 L 1581.2087,792.2879 L 1581.2087,1120.3299 L 1616.7504,1120.3299 L 1616.7504,955.8309 C 1634.7504,943.1636 1655.2083,930.0392 1677.5831,930.0392 C 1706.2922,930.0392 1718.4587,958.2475 1718.4587,983.0801 L 1718.4587,1120.3301 L 1754.5,1120.3301 L 1754.5,1120.33 z "
- style="fill:#6a6a6a"
- id="_19415136" />
-
- <path
- d="M 1786.29,1009.88 C 1786.29,1068.7544 1817.4569,1124.254 1883.1652,1124.755 C 1949.3731,1124.2542 1981.4991,1068.7542 1981.4991,1009.88 C 1980.9983,952.4217 1944.9983,902.297 1883.6648,901.796 C 1822.8321,902.29679 1786.29,952.4216 1786.29,1009.88 L 1786.29,1009.88 z M 1824.7491,1009.88 C 1824.7491,971.4221 1834.4979,929.0879 1883.1652,926.1304 C 1928.9152,928.58827 1942.5404,971.4221 1942.5404,1009.88 C 1942.5404,1050.7544 1933.7896,1101.38 1884.1231,1102.8387 C 1838.3731,1102.3379 1825.2487,1050.7544 1825.2487,1009.88 L 1824.7491,1009.88 L 1824.7491,1009.88 z "
- style="fill:#6a6a6a"
- id="_19416104" />
-
- <path
- d="M 2184.04,1120.33 L 2184.04,957.288 C 2184.04,928.5801 2161.1644,910.0805 2135.3727,904.2471 C 2110.0392,898.41364 2086.207,903.24671 2068.7066,908.1223 C 2046.2893,913.95576 2030.2475,924.2054 2012.2062,937.3298 L 2012.2062,1120.3298 L 2047.7479,1120.3298 L 2047.7479,941.7058 C 2058.9566,933.91407 2076.9566,925.6641 2095.957,925.1633 C 2127.0814,924.66369 2148.4983,942.705 2148.4983,975.2881 L 2148.4983,1120.3301 L 2184.04,1120.3301 L 2184.04,1120.33 z "
- style="fill:#6a6a6a"
- id="_19416592" />
-
- </g>
-
- </g>
- <path
- d="M 167.55462,230.0232 C 167.55462,240.98437 158.65885,249.88051 147.69769,249.89364 L 107.98299,249.89364 C 97.021827,249.88051 88.126061,240.98437 88.126061,230.0367 L 88.126061,192.79765 C 88.126061,181.83648 97.021827,172.94071 107.98299,172.94071 L 147.69769,172.94071 C 161.39896,172.94071 172.51923,161.82043 172.51923,148.11916 L 172.51923,130.73739 L 187.41193,130.75052 C 198.3731,130.73739 207.26925,139.64667 207.26925,150.60784 L 207.26925,190.3222 C 207.26925,201.27025 198.3731,210.17952 187.41193,210.17952 L 127.84037,210.16639 L 127.84037,215.13063 L 167.55475,215.13063 L 167.55475,230.02333 L 167.55462,230.0232 z M 150.17323,239.95205 C 146.06946,239.95205 142.73345,236.61604 142.73345,232.51227 C 142.73345,228.39497 146.06946,225.05897 150.17323,225.05897 C 154.29015,225.05897 157.62615,228.39497 157.62615,232.51227 C 157.62615,236.61604 154.29015,239.95205 150.17323,239.95205 z "
- style="fill:#d3aa3f;fill-rule:evenodd"
- id="path17" />
- <g
- transform="matrix(0.317715,0,0,0.317715,-71.39343,-151.2348)"
- style="fill-rule:evenodd"
- id="g1699">
- <polygon
- points="335.222,626.069 334.291,620.493 334.291,615.508 338.458,615.508 338.458,620.493 337.486,626.069 335.222,626.069 "
- style="fill:#000000;fill-rule:nonzero"
- id="_19419944" />
- <path
- d="M 341.798,634.527 C 341.798,630.52779 342.90942,627.56204 345.13816,625.6392 C 346.99249,624.04117 349.25666,623.23566 351.9295,623.23566 C 354.90233,623.23566 357.33186,624.20889 359.21454,626.16007 C 361.10312,628.10416 362.04092,630.79117 362.04092,634.22227 C 362.04092,637.00613 361.62399,639.19471 360.79013,640.78447 C 359.95745,642.38132 358.7421,643.61793 357.15233,644.49904 C 355.5543,645.38132 353.81808,645.81951 351.9295,645.81951 C 348.90942,645.81951 346.46454,644.85337 344.59604,642.90927 C 342.72872,640.97226 341.79801,638.18014 341.79801,634.52699 L 341.798,634.527 z M 345.56217,634.527 C 345.56217,637.29787 346.16571,639.36834 347.37398,640.74314 C 348.58225,642.12503 350.10351,642.81243 351.92949,642.81243 C 353.74957,642.81243 355.26256,642.11794 356.47083,640.73605 C 357.67319,639.35416 358.27674,637.24235 358.27674,634.41007 C 358.27674,631.73605 357.6732,629.7081 356.45784,628.3333 C 355.24249,626.9585 353.7354,626.2711 351.92949,626.2711 C 350.10351,626.2711 348.58225,626.9585 347.37398,628.32622 C 346.16571,629.69394 345.56217,631.76323 345.56217,634.52701 L 345.56217,634.527 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path21" />
- <path
- d="M 366.298,645.333 L 366.298,623.7295 L 369.58973,623.7295 L 369.58973,626.99997 C 370.42949,625.4728 371.20784,624.45824 371.92241,623.9728 C 372.63107,623.48619 373.41532,623.23579 374.27044,623.23579 C 375.50587,623.23579 376.75666,623.63264 378.03343,624.41689 L 376.76965,627.81965 C 375.88146,627.28461 374.985,627.02123 374.08973,627.02123 C 373.28422,627.02123 372.56847,627.26453 371.92949,627.74288 C 371.29051,628.2295 370.83933,628.89564 370.56886,629.74957 C 370.15902,631.04878 369.95823,632.47201 369.95823,634.02044 L 369.95823,645.33304 L 366.29799,645.33304 L 366.298,645.333 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path23" />
- <path
- d="M 380.228,619.722 L 380.228,615.50783 L 383.89414,615.50783 L 383.89414,619.722 L 380.228,619.722 z M 380.228,645.333 L 380.228,623.7295 L 383.89414,623.7295 L 383.89414,645.333 L 380.228,645.333 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path25" />
- <path
- d="M 388.796,647.125 L 392.3582,647.65295 C 392.50466,648.75019 392.92041,649.54862 393.59481,650.05531 C 394.50426,650.72854 395.74678,651.0687 397.31646,651.0687 C 399.01843,651.0687 400.32355,650.72855 401.24717,650.05531 C 402.17079,649.375 402.78851,648.42303 403.11449,647.20767 C 403.30937,646.45767 403.39323,644.89625 403.37906,642.50688 C 401.78221,644.38838 399.78851,645.33326 397.40032,645.33326 C 394.42749,645.33326 392.12906,644.26436 390.50386,642.1183 C 388.87984,639.97932 388.06016,637.40334 388.06016,634.41043 C 388.06016,632.34704 388.43457,630.44429 389.17748,628.70216 C 389.92748,626.95885 391.01173,625.61122 392.42787,624.66043 C 393.84401,623.71555 395.51055,623.23602 397.42039,623.23602 C 399.96921,623.23602 402.07393,624.27067 403.7263,626.33405 L 403.7263,623.72972 L 407.1078,623.72972 L 407.1078,642.40292 C 407.1078,645.76434 406.76055,648.15253 406.08024,649.55568 C 405.39283,650.95765 404.30977,652.06907 402.82394,652.88166 C 401.33693,653.69426 399.51095,654.1041 397.33772,654.1041 C 394.76055,654.1041 392.67827,653.52064 391.09441,652.36079 C 389.50465,651.20095 388.74047,649.45764 388.79598,647.12496 L 388.796,647.125 z M 391.82317,634.1459 C 391.82317,636.97936 392.38656,639.04866 393.51805,640.34787 C 394.64364,641.65299 396.0527,642.29905 397.74758,642.29905 C 399.42711,642.29905 400.83734,641.65299 401.97593,640.36086 C 403.11451,639.06283 403.68499,637.03488 403.68499,634.26401 C 403.68499,631.61834 403.10153,629.62582 401.92751,628.28527 C 400.75349,626.94472 399.33735,626.27149 397.68499,626.27149 C 396.05979,626.27149 394.6779,626.93054 393.53223,628.25692 C 392.39365,629.57621 391.82317,631.54157 391.82317,634.1459 L 391.82317,634.1459 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path27" />
- <path
- d="M 412.657,619.722 L 412.657,615.50783 L 416.32314,615.50783 L 416.32314,619.722 L 412.657,619.722 z M 412.657,645.333 L 412.657,623.7295 L 416.32314,623.7295 L 416.32314,645.333 L 412.657,645.333 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path29" />
- <path
- d="M 421.899,645.333 L 421.899,623.7295 L 425.19073,623.7295 L 425.19073,626.79919 C 426.78167,624.42399 429.07301,623.2358 432.06593,623.2358 C 433.37105,623.2358 434.56514,623.47202 435.65648,623.93737 C 436.75372,624.40982 437.56514,625.02045 438.10727,625.78462 C 438.65648,626.5417 439.03089,627.44407 439.25294,628.4858 C 439.38522,629.16729 439.45491,630.3543 439.45491,632.04919 L 439.45491,645.33309 L 435.78759,645.33309 L 435.78759,632.18739 C 435.78759,630.70156 435.6494,629.58306 435.36475,628.84015 C 435.08011,628.10432 434.57223,627.51377 433.85058,627.07676 C 433.12184,626.63266 432.27381,626.40943 431.29467,626.40943 C 429.73207,626.40943 428.3927,626.91022 427.25294,627.89644 C 426.12144,628.88857 425.55924,630.76416 425.55924,633.53502 L 425.55924,645.33302 L 421.899,645.33302 L 421.899,645.333 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path31" />
- <path
- d="M 459.17,642.666 C 457.80819,643.81876 456.50307,644.63135 455.25346,645.11088 C 453.99559,645.58332 452.64913,645.81954 451.21173,645.81954 C 448.83653,645.81954 447.01764,645.24316 445.73968,644.08332 C 444.46881,642.92348 443.82984,641.43765 443.82984,639.63883 C 443.82984,638.57584 444.06606,637.61088 444.55149,636.73568 C 445.03102,635.86048 445.66291,635.16009 446.44125,634.63214 C 447.22551,634.10419 448.1007,633.70143 449.07983,633.43096 C 449.7944,633.24317 450.87865,633.05537 452.32904,632.88175 C 455.2877,632.52742 457.46802,632.11049 458.86408,631.61797 C 458.87826,631.11836 458.88534,630.79828 458.88534,630.666 C 458.88534,629.17309 458.5381,628.11836 457.84361,627.51364 C 456.9129,626.68096 455.51684,626.27112 453.67668,626.27112 C 451.95463,626.27112 450.68377,626.56994 449.85699,627.17348 C 449.03731,627.77821 448.43376,628.8471 448.03809,630.38135 L 444.46171,629.88883 C 444.7877,628.36166 445.32274,627.11796 446.06565,626.18017 C 446.80857,625.23647 447.89163,624.50655 449.30187,623.99986 C 450.71093,623.49317 452.34321,623.23569 454.20463,623.23569 C 456.05187,623.23569 457.54479,623.45892 458.69754,623.88884 C 459.8503,624.32703 460.69715,624.86797 461.24636,625.52821 C 461.78731,626.18726 462.1629,627.01404 462.38494,628.02034 C 462.50305,628.64632 462.56565,629.77073 462.56565,631.39593 L 462.56565,636.27743 C 462.56565,639.68727 462.64124,641.84042 462.80187,642.7357 C 462.95423,643.63806 463.26723,644.50617 463.72549,645.33294 L 459.89872,645.33294 C 459.52432,644.57585 459.27392,643.68766 459.16998,642.66601 L 459.17,642.666 z M 458.86409,634.48569 C 457.53063,635.0349 455.53811,635.49317 452.88535,635.87467 C 451.37826,636.08963 450.30818,636.33294 449.69047,636.60341 C 449.06567,636.87506 448.57905,637.27073 448.24598,637.79869 C 447.90583,638.31956 447.7322,638.89593 447.7322,639.53491 C 447.7322,640.51404 448.1078,641.32664 448.84362,641.97861 C 449.57945,642.62467 450.66252,642.95066 452.08693,642.95066 C 453.49599,642.95066 454.75268,642.64593 455.84992,642.02704 C 456.94716,641.40932 457.75976,640.56247 458.27354,639.49239 C 458.66921,638.66679 458.8641,637.44435 458.8641,635.83333 L 458.8641,634.48569 L 458.86409,634.48569 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path33" />
- <polygon
- points="468.163,645.333 468.163,615.508 471.822,615.508 471.822,645.333 468.163,645.333 "
- style="fill:#000000;fill-rule:nonzero"
- id="polygon35" />
- <polygon
- points="477.516,626.069 476.585,620.493 476.585,615.508 480.752,615.508 480.752,620.493 479.78,626.069 477.516,626.069 "
- style="fill:#000000;fill-rule:nonzero"
- id="polygon37" />
- <polygon
- points="496.954,645.333 496.954,615.508 500.613,615.508 500.613,645.333 496.954,645.333 "
- style="fill:#000000;fill-rule:nonzero"
- id="polygon39" />
- <path
- d="M 504.925,634.527 C 504.925,630.52779 506.03642,627.56204 508.26516,625.6392 C 510.11949,624.04117 512.38366,623.23566 515.0565,623.23566 C 518.02933,623.23566 520.45886,624.20889 522.34154,626.16007 C 524.23012,628.10416 525.16792,630.79117 525.16792,634.22227 C 525.16792,637.00613 524.75099,639.19471 523.91713,640.78447 C 523.08445,642.38132 521.8691,643.61793 520.27933,644.49904 C 518.6813,645.38132 516.94508,645.81951 515.0565,645.81951 C 512.03642,645.81951 509.59154,644.85337 507.72304,642.90927 C 505.85572,640.97226 504.92501,638.18014 504.92501,634.52699 L 504.925,634.527 z M 508.68917,634.527 C 508.68917,637.29787 509.29271,639.36834 510.50098,640.74314 C 511.70925,642.12503 513.23051,642.81243 515.05649,642.81243 C 516.87657,642.81243 518.38956,642.11794 519.59783,640.73605 C 520.80019,639.35416 521.40374,637.24235 521.40374,634.41007 C 521.40374,631.73605 520.8002,629.7081 519.58484,628.3333 C 518.36949,626.9585 516.8624,626.2711 515.05649,626.2711 C 513.23051,626.2711 511.70925,626.9585 510.50098,628.32622 C 509.29271,629.69394 508.68917,631.76323 508.68917,634.52701 L 508.68917,634.527 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path41" />
- <path
- d="M 528.793,647.125 L 532.3552,647.65295 C 532.50166,648.75019 532.9174,649.54862 533.59181,650.05531 C 534.50126,650.72854 535.74378,651.0687 537.31346,651.0687 C 539.01543,651.0687 540.32055,650.72855 541.24417,650.05531 C 542.16779,649.375 542.78551,648.42303 543.11149,647.20767 C 543.30637,646.45767 543.39023,644.89625 543.37606,642.50688 C 541.77921,644.38838 539.78551,645.33326 537.39732,645.33326 C 534.42449,645.33326 532.12606,644.26436 530.50086,642.1183 C 528.87684,639.97932 528.05716,637.40334 528.05716,634.41043 C 528.05716,632.34704 528.43157,630.44429 529.17448,628.70216 C 529.92448,626.95885 531.00873,625.61122 532.42487,624.66043 C 533.84101,623.71555 535.50755,623.23602 537.41739,623.23602 C 539.96621,623.23602 542.07093,624.27067 543.7233,626.33405 L 543.7233,623.72972 L 547.1048,623.72972 L 547.1048,642.40292 C 547.1048,645.76434 546.75755,648.15253 546.07724,649.55568 C 545.38983,650.95765 544.30677,652.06907 542.82094,652.88166 C 541.33393,653.69426 539.50795,654.1041 537.33472,654.1041 C 534.75755,654.1041 532.67527,653.52064 531.09141,652.36079 C 529.50165,651.20095 528.73747,649.45764 528.79298,647.12496 L 528.793,647.125 z M 531.82017,634.1459 C 531.82017,636.97936 532.38356,639.04866 533.51505,640.34787 C 534.64064,641.65299 536.0497,642.29905 537.74458,642.29905 C 539.42411,642.29905 540.83434,641.65299 541.97293,640.36086 C 543.11151,639.06283 543.68199,637.03488 543.68199,634.26401 C 543.68199,631.61834 543.09852,629.62582 541.92451,628.28527 C 540.75049,626.94472 539.33435,626.27149 537.68199,626.27149 C 536.05679,626.27149 534.6749,626.93054 533.52923,628.25692 C 532.39065,629.57621 531.82017,631.54157 531.82017,634.1459 L 531.82017,634.1459 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path43" />
- <path
- d="M 551.271,634.527 C 551.271,630.52779 552.38242,627.56204 554.61116,625.6392 C 556.46549,624.04117 558.72966,623.23566 561.4025,623.23566 C 564.37533,623.23566 566.80486,624.20889 568.68754,626.16007 C 570.57612,628.10416 571.51392,630.79117 571.51392,634.22227 C 571.51392,637.00613 571.09699,639.19471 570.26313,640.78447 C 569.43045,642.38132 568.2151,643.61793 566.62533,644.49904 C 565.0273,645.38132 563.29108,645.81951 561.4025,645.81951 C 558.38242,645.81951 555.93754,644.85337 554.06904,642.90927 C 552.20172,640.97226 551.27101,638.18014 551.27101,634.52699 L 551.271,634.527 z M 555.03517,634.527 C 555.03517,637.29787 555.63871,639.36834 556.84698,640.74314 C 558.05525,642.12503 559.57651,642.81243 561.40249,642.81243 C 563.22257,642.81243 564.73556,642.11794 565.94383,640.73605 C 567.14619,639.35416 567.74974,637.24235 567.74974,634.41007 C 567.74974,631.73605 567.1462,629.7081 565.93084,628.3333 C 564.71549,626.9585 563.2084,626.2711 561.40249,626.2711 C 559.57651,626.2711 558.05525,626.9585 556.84698,628.32622 C 555.63871,629.69394 555.03517,631.76323 555.03517,634.52701 L 555.03517,634.527 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path45" />
- <path
- d="M 588.256,645.333 L 588.256,626.5759 L 585.02687,626.5759 L 585.02687,623.72944 L 588.256,623.72944 L 588.256,621.43101 C 588.256,619.97944 588.38828,618.89636 588.64458,618.19479 C 588.99891,617.24282 589.61781,616.47274 590.506,615.88219 C 591.39537,615.29164 592.63789,614.99991 594.24183,614.99991 C 595.27057,614.99991 596.40915,615.11802 597.65876,615.36841 L 597.11073,618.56329 C 596.35364,618.42392 595.63081,618.35424 594.95049,618.35424 C 593.83907,618.35424 593.05482,618.59046 592.59655,619.06998 C 592.1312,619.54242 591.90206,620.43061 591.90206,621.73573 L 591.90206,623.72943 L 596.11033,623.72943 L 596.11033,626.57589 L 591.90206,626.57589 L 591.90206,645.33299 L 588.256,645.33299 L 588.256,645.333 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path47" />
- <path
- d="M 598.923,645.333 L 598.923,623.7295 L 602.21473,623.7295 L 602.21473,626.99997 C 603.05449,625.4728 603.83284,624.45824 604.54741,623.9728 C 605.25607,623.48619 606.04032,623.23579 606.89544,623.23579 C 608.13087,623.23579 609.38166,623.63264 610.65843,624.41689 L 609.39465,627.81965 C 608.50646,627.28461 607.61,627.02123 606.71473,627.02123 C 605.90922,627.02123 605.19347,627.26453 604.55449,627.74288 C 603.91551,628.2295 603.46433,628.89564 603.19386,629.74957 C 602.78402,631.04878 602.58323,632.47201 602.58323,634.02044 L 602.58323,645.33304 L 598.92299,645.33304 L 598.923,645.333 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path49" />
- <path
- d="M 611.471,634.527 C 611.471,630.52779 612.58242,627.56204 614.81116,625.6392 C 616.66549,624.04117 618.92966,623.23566 621.6025,623.23566 C 624.57533,623.23566 627.00486,624.20889 628.88754,626.16007 C 630.77612,628.10416 631.71392,630.79117 631.71392,634.22227 C 631.71392,637.00613 631.29699,639.19471 630.46313,640.78447 C 629.63045,642.38132 628.4151,643.61793 626.82533,644.49904 C 625.2273,645.38132 623.49108,645.81951 621.6025,645.81951 C 618.58242,645.81951 616.13754,644.85337 614.26904,642.90927 C 612.40172,640.97226 611.47101,638.18014 611.47101,634.52699 L 611.471,634.527 z M 615.23517,634.527 C 615.23517,637.29787 615.83871,639.36834 617.04698,640.74314 C 618.25525,642.12503 619.77651,642.81243 621.60249,642.81243 C 623.42257,642.81243 624.93556,642.11794 626.14383,640.73605 C 627.34619,639.35416 627.94974,637.24235 627.94974,634.41007 C 627.94974,631.73605 627.3462,629.7081 626.13084,628.3333 C 624.91549,626.9585 623.4084,626.2711 621.60249,626.2711 C 619.77651,626.2711 618.25525,626.9585 617.04698,628.32622 C 615.83871,629.69394 615.23517,631.76323 615.23517,634.52701 L 615.23517,634.527 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path51" />
- <path
- d="M 636.012,645.333 L 636.012,623.7295 L 639.28365,623.7295 L 639.28365,626.75667 C 639.96396,625.70195 640.86633,624.84683 641.99192,624.20903 C 643.11633,623.56297 644.40137,623.2358 645.83877,623.2358 C 647.43562,623.2358 648.74783,623.57005 649.76948,624.23619 C 650.79704,624.90351 651.51869,625.82595 651.93562,627.02123 C 653.65058,624.50076 655.87342,623.2358 658.60885,623.2358 C 660.75491,623.2358 662.40019,623.83344 663.55294,625.02045 C 664.7057,626.20864 665.28207,628.03462 665.28207,630.49958 L 665.28207,645.33308 L 661.64427,645.33308 L 661.64427,631.72208 C 661.64427,630.25751 661.52616,629.20161 661.28994,628.55554 C 661.04663,627.91657 660.61553,627.3957 659.99781,627.00003 C 659.37301,626.61145 658.63718,626.40948 657.79624,626.40948 C 656.27616,626.40948 655.01829,626.91735 654.01199,627.93074 C 653.0116,628.93822 652.5049,630.55515 652.5049,632.77798 L 652.5049,645.33308 L 648.84584,645.33308 L 648.84584,631.29918 C 648.84584,629.6669 648.54702,628.44446 647.94938,627.63186 C 647.35293,626.81926 646.37969,626.40942 645.01907,626.40942 C 643.99151,626.40942 643.03954,626.68107 642.16553,627.22911 C 641.29034,627.77123 640.65136,628.56257 640.26277,629.60431 C 639.86592,630.65313 639.67222,632.16022 639.67222,634.12439 L 639.67222,645.33309 L 636.01198,645.33309 L 636.012,645.333 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path53" />
- <path
- d="M 685.671,645.333 L 682.27533,645.333 L 682.27533,615.5078 L 685.93439,615.5078 L 685.93439,626.146 C 687.48282,624.20899 689.45526,623.23576 691.85053,623.23576 C 693.18399,623.23576 694.44187,623.50741 695.62888,624.04127 C 696.81589,624.57631 697.78794,625.3334 698.55919,626.29836 C 699.32336,627.27041 699.92691,628.43734 700.35801,629.81214 C 700.79502,631.18104 701.01116,632.6456 701.01116,634.20112 C 701.01116,637.90978 700.09344,640.77041 698.26037,642.79128 C 696.43439,644.81215 694.23281,645.81963 691.671,645.81963 C 689.12218,645.81963 687.12257,644.75664 685.671,642.62475 L 685.671,645.33302 L 685.671,645.333 z M 685.62848,634.3676 C 685.62848,636.95776 685.98281,638.82626 686.68439,639.97902 C 687.83715,641.8676 689.39974,642.81248 691.3651,642.81248 C 692.96904,642.81248 694.35093,642.11799 695.51786,640.72193 C 696.68479,639.33295 697.26707,637.26366 697.26707,634.50697 C 697.26707,631.68768 696.70487,629.60421 695.58754,628.26366 C 694.46904,626.92311 693.11549,626.24988 691.53163,626.24988 C 689.92769,626.24988 688.5458,626.94437 687.37887,628.33334 C 686.21194,629.72232 685.62848,631.7361 685.62848,634.36759 L 685.62848,634.3676 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path55" />
- <path
- d="M 720.254,638.375 L 724.03825,638.84035 C 723.44061,641.05492 722.33746,642.76988 720.72644,643.99232 C 719.10833,645.20767 717.04494,645.81949 714.53864,645.81949 C 711.37919,645.81949 708.87171,644.84627 707.02447,642.90217 C 705.17014,640.95808 704.24652,638.22855 704.24652,634.71477 C 704.24652,631.07579 705.18431,628.2565 707.05282,626.24981 C 708.92723,624.24312 711.35085,623.23564 714.33668,623.23564 C 717.22566,623.23564 719.58668,624.22186 721.41385,626.18721 C 723.24692,628.15256 724.16346,630.92343 724.16346,634.48564 C 724.16346,634.70769 724.15637,635.03486 724.1422,635.46478 L 708.032,635.46478 C 708.16428,637.83998 708.83751,639.65887 710.04578,640.91675 C 711.25405,642.18053 712.75405,642.81242 714.55995,642.81242 C 715.89932,642.81242 717.04499,642.45809 717.99696,641.74943 C 718.94775,641.04785 719.69775,639.92345 720.25405,638.37502 L 720.254,638.375 z M 708.2327,632.45177 L 720.2953,632.45177 C 720.13585,630.63878 719.6705,629.27106 718.91341,628.36752 C 717.74648,626.95846 716.23349,626.2498 714.37916,626.2498 C 712.69845,626.2498 711.28113,626.81201 710.13546,627.9376 C 708.98979,629.06201 708.3579,630.5691 708.2327,632.45177 L 708.2327,632.45177 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path57" />
- <path
- d="M 736.636,642.056 L 737.16277,645.29222 C 736.13521,645.50718 735.21159,645.6182 734.39899,645.6182 C 733.06671,645.6182 732.03797,645.41033 731.30214,644.98631 C 730.5734,644.56939 730.05962,644.01427 729.7608,643.32686 C 729.46198,642.64655 729.30962,641.20206 729.30962,639.00757 L 729.30962,626.57647 L 726.62143,626.57647 L 726.62143,623.73001 L 729.30962,623.73001 L 729.30962,618.37607 L 732.9545,616.18158 L 732.9545,623.73001 L 736.636,623.73001 L 736.636,626.57647 L 732.9545,626.57647 L 732.9545,639.20837 C 732.9545,640.25719 733.0171,640.92451 733.1423,641.22215 C 733.27458,641.52097 733.48245,641.75719 733.77419,641.9379 C 734.06592,642.11152 734.48285,642.20129 735.02498,642.20129 C 735.43364,642.20129 735.96868,642.15286 736.636,642.05601 L 736.636,642.056 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path59" />
- <path
- d="M 754.316,642.666 C 752.95419,643.81876 751.64907,644.63135 750.39946,645.11088 C 749.14159,645.58332 747.79513,645.81954 746.35773,645.81954 C 743.98253,645.81954 742.16364,645.24316 740.88568,644.08332 C 739.61481,642.92348 738.97584,641.43765 738.97584,639.63883 C 738.97584,638.57584 739.21206,637.61088 739.69749,636.73568 C 740.17702,635.86048 740.80891,635.16009 741.58725,634.63214 C 742.37151,634.10419 743.2467,633.70143 744.22583,633.43096 C 744.9404,633.24317 746.02465,633.05537 747.47504,632.88175 C 750.4337,632.52742 752.61402,632.11049 754.01008,631.61797 C 754.02426,631.11836 754.03134,630.79828 754.03134,630.666 C 754.03134,629.17309 753.6841,628.11836 752.98961,627.51364 C 752.0589,626.68096 750.66284,626.27112 748.82268,626.27112 C 747.10063,626.27112 745.82977,626.56994 745.00299,627.17348 C 744.18331,627.77821 743.57976,628.8471 743.18409,630.38135 L 739.60771,629.88883 C 739.9337,628.36166 740.46874,627.11796 741.21165,626.18017 C 741.95457,625.23647 743.03763,624.50655 744.44787,623.99986 C 745.85693,623.49317 747.48921,623.23569 749.35063,623.23569 C 751.19787,623.23569 752.69079,623.45892 753.84354,623.88884 C 754.9963,624.32703 755.84315,624.86797 756.39236,625.52821 C 756.93331,626.18726 757.3089,627.01404 757.53094,628.02034 C 757.64905,628.64632 757.71165,629.77073 757.71165,631.39593 L 757.71165,636.27743 C 757.71165,639.68727 757.78724,641.84042 757.94787,642.7357 C 758.10023,643.63806 758.41323,644.50617 758.87149,645.33294 L 755.04472,645.33294 C 754.67032,644.57585 754.41992,643.68766 754.31598,642.66601 L 754.316,642.666 z M 754.01009,634.48569 C 752.67663,635.0349 750.68411,635.49317 748.03135,635.87467 C 746.52426,636.08963 745.45418,636.33294 744.83647,636.60341 C 744.21167,636.87506 743.72505,637.27073 743.39198,637.79869 C 743.05183,638.31956 742.8782,638.89593 742.8782,639.53491 C 742.8782,640.51404 743.25379,641.32664 743.98962,641.97861 C 744.72545,642.62467 745.80852,642.95066 747.23293,642.95066 C 748.64199,642.95066 749.89868,642.64593 750.99592,642.02704 C 752.09316,641.40932 752.90576,640.56247 753.41954,639.49239 C 753.81521,638.66679 754.01009,637.44435 754.01009,635.83333 L 754.01009,634.48569 L 754.01009,634.48569 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path61" />
- <polygon
- points="764.426,645.333 764.426,641.159 768.6,641.159 768.6,645.333 764.426,645.333 "
- style="fill:#000000;fill-rule:nonzero"
- id="polygon63" />
- <path
- d="M 774.967,653.61 L 774.967,623.7293 L 778.30007,623.7293 L 778.30007,626.53442 C 779.0855,625.43718 779.97369,624.61159 780.967,624.06237 C 781.95322,623.51434 783.1544,623.2356 784.56464,623.2356 C 786.41188,623.2356 788.03708,623.71513 789.44614,624.66001 C 790.86228,625.61079 791.92527,626.95135 792.64102,628.68048 C 793.36267,630.40961 793.72409,632.30528 793.72409,634.36749 C 793.72409,636.57615 793.32842,638.56867 792.53,640.34032 C 791.73748,642.11079 790.58472,643.46434 789.07173,644.40922 C 787.55756,645.34701 785.96661,645.81946 784.30008,645.81946 C 783.07882,645.81946 781.98748,645.56198 781.01543,645.0482 C 780.04338,644.53442 779.25204,643.88127 778.62724,643.09702 L 778.62724,653.61002 L 774.967,653.61002 L 774.967,653.61 z M 778.27999,634.6521 C 778.27999,637.43005 778.84219,639.48517 779.96779,640.81864 C 781.0922,642.14502 782.45992,642.81234 784.05795,642.81234 C 785.68197,642.81234 787.07803,642.12494 788.23787,640.74305 C 789.39771,639.36825 789.98118,637.23636 789.98118,634.34738 C 789.98118,631.58951 789.41189,629.53439 788.27921,628.15958 C 787.14771,626.79186 785.79299,626.10446 784.22449,626.10446 C 782.66189,626.10446 781.28,626.8332 780.07882,628.29186 C 778.87646,629.74934 778.28,631.87532 778.28,634.6521 L 778.27999,634.6521 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path65" />
- <path
- d="M 797.974,653.653 L 797.56416,650.21481 C 798.36967,650.43095 799.06416,650.54198 799.6618,650.54198 C 800.47439,650.54198 801.12637,650.40261 801.61298,650.13213 C 802.1055,649.86048 802.50235,649.48607 802.81416,648.99237 C 803.05038,648.63214 803.41888,647.72268 803.93266,646.27111 C 804.00234,646.06206 804.11337,645.77033 804.25864,645.37465 L 796.06415,623.72975 L 800.00903,623.72975 L 804.50903,636.23645 C 805.08541,637.82621 805.61336,639.49275 806.07163,641.24315 C 806.49447,639.56244 806.99525,637.92425 807.57872,636.31912 L 812.19565,623.72973 L 815.85589,623.72973 L 807.64014,645.70173 C 806.75904,648.07574 806.07164,649.70803 805.58502,650.60448 C 804.93187,651.81275 804.18896,652.69385 803.34919,653.25724 C 802.50234,653.81945 801.50195,654.10409 800.33502,654.10409 C 799.62636,654.10409 798.84211,653.95055 797.974,653.65291 L 797.974,653.653 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path67" />
- <path
- d="M 826.967,642.056 L 827.49377,645.29222 C 826.46621,645.50718 825.54259,645.6182 824.72999,645.6182 C 823.39771,645.6182 822.36897,645.41033 821.63314,644.98631 C 820.9044,644.56939 820.39062,644.01427 820.0918,643.32686 C 819.79298,642.64655 819.64062,641.20206 819.64062,639.00757 L 819.64062,626.57647 L 816.95243,626.57647 L 816.95243,623.73001 L 819.64062,623.73001 L 819.64062,618.37607 L 823.2855,616.18158 L 823.2855,623.73001 L 826.967,623.73001 L 826.967,626.57647 L 823.2855,626.57647 L 823.2855,639.20837 C 823.2855,640.25719 823.3481,640.92451 823.4733,641.22215 C 823.60558,641.52097 823.81345,641.75719 824.10519,641.9379 C 824.39692,642.11152 824.81385,642.20129 825.35598,642.20129 C 825.76464,642.20129 826.29968,642.15286 826.967,642.05601 L 826.967,642.056 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path69" />
- <path
- d="M 830.549,645.333 L 830.549,615.5078 L 834.20924,615.5078 L 834.20924,626.2086 C 835.91711,624.22907 838.07735,623.23577 840.6805,623.23577 C 842.27853,623.23577 843.66751,623.55585 844.84743,624.18774 C 846.02853,624.81254 846.87538,625.68774 847.38208,626.79916 C 847.88877,627.9094 848.14625,629.52751 848.14625,631.63932 L 848.14625,645.33302 L 844.48011,645.33302 L 844.48011,631.63932 C 844.48011,629.81215 844.08326,628.47869 843.29192,627.64601 C 842.50058,626.81215 841.37499,626.38932 839.9246,626.38932 C 838.84035,626.38932 837.81988,626.67396 836.862,627.23617 C 835.90295,627.79837 835.22263,628.56255 834.81987,629.52751 C 834.41003,630.48656 834.20924,631.81885 834.20924,633.51373 L 834.20924,645.33303 L 830.549,645.33303 L 830.549,645.333 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path71" />
- <path
- d="M 852.354,634.527 C 852.354,630.52779 853.46542,627.56204 855.69416,625.6392 C 857.54849,624.04117 859.81266,623.23566 862.4855,623.23566 C 865.45833,623.23566 867.88786,624.20889 869.77054,626.16007 C 871.65912,628.10416 872.59692,630.79117 872.59692,634.22227 C 872.59692,637.00613 872.17999,639.19471 871.34613,640.78447 C 870.51345,642.38132 869.2981,643.61793 867.70833,644.49904 C 866.1103,645.38132 864.37408,645.81951 862.4855,645.81951 C 859.46542,645.81951 857.02054,644.85337 855.15204,642.90927 C 853.28472,640.97226 852.35401,638.18014 852.35401,634.52699 L 852.354,634.527 z M 856.11817,634.527 C 856.11817,637.29787 856.72171,639.36834 857.92998,640.74314 C 859.13825,642.12503 860.65951,642.81243 862.48549,642.81243 C 864.30557,642.81243 865.81856,642.11794 867.02683,640.73605 C 868.22919,639.35416 868.83274,637.24235 868.83274,634.41007 C 868.83274,631.73605 868.2292,629.7081 867.01384,628.3333 C 865.79849,626.9585 864.2914,626.2711 862.48549,626.2711 C 860.65951,626.2711 859.13825,626.9585 857.92998,628.32622 C 856.72171,629.69394 856.11817,631.76323 856.11817,634.52701 L 856.11817,634.527 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path73" />
- <path
- d="M 876.895,645.333 L 876.895,623.7295 L 880.18673,623.7295 L 880.18673,626.79919 C 881.77767,624.42399 884.06901,623.2358 887.06193,623.2358 C 888.36705,623.2358 889.56114,623.47202 890.65248,623.93737 C 891.74972,624.40982 892.56114,625.02045 893.10327,625.78462 C 893.65248,626.5417 894.02689,627.44407 894.24894,628.4858 C 894.38122,629.16729 894.45091,630.3543 894.45091,632.04919 L 894.45091,645.33309 L 890.78359,645.33309 L 890.78359,632.18739 C 890.78359,630.70156 890.6454,629.58306 890.36075,628.84015 C 890.07611,628.10432 889.56823,627.51377 888.84658,627.07676 C 888.11784,626.63266 887.26981,626.40943 886.29067,626.40943 C 884.72807,626.40943 883.3887,626.91022 882.24894,627.89644 C 881.11744,628.88857 880.55524,630.76416 880.55524,633.53502 L 880.55524,645.33302 L 876.895,645.33302 L 876.895,645.333 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path75" />
- </g>
- <g
- transform="matrix(0.317715,0,0,0.317715,-71.39343,-151.2348)"
- style="fill-rule:evenodd"
- id="_19428312">
- <path
- d="M 341.207,1443.54 L 332.98535,1421.9365 L 336.85346,1421.9365 L 341.49165,1434.8731 C 341.99244,1436.2692 342.4507,1437.7207 342.87354,1439.2278 C 343.2007,1438.0892 343.65189,1436.7203 344.23535,1435.1164 L 349.04007,1421.9365 L 352.80424,1421.9365 L 344.62393,1443.54 L 341.207,1443.54 L 341.207,1443.54 z "
- style="fill:#000000;fill-rule:nonzero"
- id="_19439224" />
-
- <path
- d="M 370.825,1436.58 L 374.60925,1437.0454 C 374.01161,1439.2599 372.90846,1440.9749 371.29744,1442.1973 C 369.67933,1443.4127 367.61594,1444.0245 365.10964,1444.0245 C 361.95019,1444.0245 359.44271,1443.0513 357.59547,1441.1072 C 355.74114,1439.1631 354.81752,1436.4336 354.81752,1432.9198 C 354.81752,1429.2808 355.75532,1426.4615 357.62382,1424.4548 C 359.49823,1422.4481 361.92185,1421.4406 364.90768,1421.4406 C 367.79666,1421.4406 370.15768,1422.4269 371.98485,1424.3922 C 373.81792,1426.3576 374.73446,1429.1284 374.73446,1432.6906 C 374.73446,1432.9127 374.72737,1433.2399 374.7132,1433.6698 L 358.603,1433.6698 C 358.73528,1436.045 359.40851,1437.8639 360.61678,1439.1217 C 361.82505,1440.3855 363.32505,1441.0174 365.13095,1441.0174 C 366.47032,1441.0174 367.61599,1440.6631 368.56796,1439.9544 C 369.51875,1439.2529 370.26875,1438.1284 370.82505,1436.58 L 370.825,1436.58 z M 358.8037,1430.6568 L 370.8663,1430.6568 C 370.70685,1428.8438 370.2415,1427.4761 369.48441,1426.5725 C 368.31748,1425.1635 366.80449,1424.4548 364.95016,1424.4548 C 363.26945,1424.4548 361.85213,1425.017 360.70646,1426.1426 C 359.56079,1427.267 358.9289,1428.7741 358.8037,1430.6568 L 358.8037,1430.6568 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path79" />
-
- <path
- d="M 379.172,1443.54 L 379.172,1421.9365 L 382.46373,1421.9365 L 382.46373,1425.207 C 383.30349,1423.6798 384.08184,1422.6652 384.79641,1422.1798 C 385.50507,1421.6932 386.28932,1421.4428 387.14444,1421.4428 C 388.37987,1421.4428 389.63066,1421.8396 390.90743,1422.6239 L 389.64365,1426.0267 C 388.75546,1425.4916 387.859,1425.2282 386.96373,1425.2282 C 386.15822,1425.2282 385.44247,1425.4715 384.80349,1425.9499 C 384.16451,1426.4365 383.71333,1427.1026 383.44286,1427.9566 C 383.03302,1429.2558 382.83223,1430.679 382.83223,1432.2274 L 382.83223,1443.54 L 379.17199,1443.54 L 379.172,1443.54 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path81" />
-
- <path
- d="M 391.623,1437.09 L 395.24072,1436.5207 C 395.44151,1437.9723 396.01198,1439.0825 396.94151,1439.8609 C 397.86513,1440.6309 399.16434,1441.0207 400.83797,1441.0207 C 402.51868,1441.0207 403.76828,1440.6735 404.58088,1439.9931 C 405.39348,1439.3057 405.80332,1438.4991 405.80332,1437.5825 C 405.80332,1436.7498 405.4419,1436.1038 404.71907,1435.6242 C 404.21946,1435.2983 402.96986,1434.8884 400.97616,1434.3888 C 398.29624,1433.7085 396.42773,1433.125 395.39309,1432.6242 C 394.35844,1432.1317 393.56711,1431.4443 393.03207,1430.5691 C 392.49821,1429.6939 392.22656,1428.729 392.22656,1427.6731 C 392.22656,1426.7081 392.4486,1425.8199 392.89388,1425.0002 C 393.33089,1424.1735 393.93561,1423.4931 394.69152,1422.951 C 395.26199,1422.5353 396.03916,1422.1739 397.01829,1421.8821 C 398.00451,1421.5904 399.06042,1421.4439 400.18483,1421.4439 C 401.87971,1421.4439 403.36554,1421.6943 404.65058,1422.1809 C 405.93444,1422.6664 406.87932,1423.3266 407.48995,1424.1593 C 408.10176,1425.0002 408.51869,1426.1105 408.74782,1427.5065 L 405.17144,1428.0002 C 405.00491,1426.8888 404.53247,1426.0207 403.75412,1425.3959 C 402.97696,1424.7711 401.87262,1424.4581 400.4494,1424.4581 C 398.76869,1424.4581 397.56751,1424.7357 396.85176,1425.292 C 396.13011,1425.8471 395.76869,1426.5002 395.76869,1427.2432 C 395.76869,1427.7215 395.92105,1428.1455 396.21987,1428.5282 C 396.51869,1428.9239 396.98405,1429.2428 397.62302,1429.5073 C 397.99034,1429.6384 399.06751,1429.9514 400.85806,1430.4369 C 403.44822,1431.1313 405.25412,1431.6947 406.2746,1432.1388 C 407.30334,1432.5758 408.10885,1433.2219 408.69232,1434.0617 C 409.27461,1434.9026 409.56634,1435.9443 409.56634,1437.1939 C 409.56634,1438.4164 409.2061,1439.562 408.49744,1440.6451 C 407.78169,1441.7223 406.75413,1442.555 405.41358,1443.1455 C 404.07421,1443.7361 402.55295,1444.0278 400.85807,1444.0278 C 398.04587,1444.0278 395.90689,1443.4443 394.43524,1442.2774 C 392.96241,1441.1105 392.02579,1439.3813 391.62304,1437.09 L 391.623,1437.09 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path83" />
-
- <path
- d="M 413.934,1417.93 L 413.934,1413.7158 L 417.60014,1413.7158 L 417.60014,1417.93 L 413.934,1417.93 z M 413.934,1443.541 L 413.934,1421.9375 L 417.60014,1421.9375 L 417.60014,1443.541 L 413.934,1443.541 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path85" />
-
- <path
- d="M 421.808,1432.74 C 421.808,1428.7408 422.91942,1425.775 425.14816,1423.8522 C 427.00249,1422.2542 429.26666,1421.4487 431.9395,1421.4487 C 434.91233,1421.4487 437.34186,1422.4219 439.22454,1424.3731 C 441.11312,1426.3172 442.05092,1429.0042 442.05092,1432.4353 C 442.05092,1435.2191 441.63399,1437.4077 440.80013,1438.9975 C 439.96745,1440.5943 438.7521,1441.8309 437.16233,1442.712 C 435.5643,1443.5943 433.82808,1444.0325 431.9395,1444.0325 C 428.91942,1444.0325 426.47454,1443.0664 424.60604,1441.1223 C 422.73872,1439.1853 421.80801,1436.3931 421.80801,1432.74 L 421.808,1432.74 z M 425.57217,1432.74 C 425.57217,1435.5109 426.17571,1437.5813 427.38398,1438.9561 C 428.59225,1440.338 430.11351,1441.0254 431.93949,1441.0254 C 433.75957,1441.0254 435.27256,1440.3309 436.48083,1438.949 C 437.68319,1437.5672 438.28674,1435.4554 438.28674,1432.6231 C 438.28674,1429.949 437.6832,1427.9211 436.46784,1426.5463 C 435.25249,1425.1715 433.7454,1424.4841 431.93949,1424.4841 C 430.11351,1424.4841 428.59225,1425.1715 427.38398,1426.5392 C 426.17571,1427.9069 425.57217,1429.9762 425.57217,1432.74 L 425.57217,1432.74 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path87" />
-
- <path
- d="M 446.349,1443.54 L 446.349,1421.9365 L 449.64073,1421.9365 L 449.64073,1425.0062 C 451.23167,1422.631 453.52301,1421.4428 456.51593,1421.4428 C 457.82105,1421.4428 459.01514,1421.679 460.10648,1422.1444 C 461.20372,1422.6168 462.01514,1423.2274 462.55727,1423.9916 C 463.10648,1424.7487 463.48089,1425.6511 463.70294,1426.6928 C 463.83522,1427.3743 463.90491,1428.5613 463.90491,1430.2562 L 463.90491,1443.5401 L 460.23759,1443.5401 L 460.23759,1430.3944 C 460.23759,1428.9086 460.0994,1427.7901 459.81475,1427.0471 C 459.53011,1426.3113 459.02223,1425.7208 458.30058,1425.2838 C 457.57184,1424.8397 456.72381,1424.6164 455.74467,1424.6164 C 454.18207,1424.6164 452.8427,1425.1172 451.70294,1426.1034 C 450.57144,1427.0956 450.00924,1428.9712 450.00924,1431.742 L 450.00924,1443.54 L 446.349,1443.54 L 446.349,1443.54 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path89" />
-
- <path
- d="M 481.113,1417.93 L 481.113,1413.7158 L 484.77914,1413.7158 L 484.77914,1417.93 L 481.113,1417.93 z M 481.113,1443.541 L 481.113,1421.9375 L 484.77914,1421.9375 L 484.77914,1443.541 L 481.113,1443.541 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path91" />
-
- <path
- d="M 490.355,1443.54 L 490.355,1421.9365 L 493.64673,1421.9365 L 493.64673,1425.0062 C 495.23767,1422.631 497.52901,1421.4428 500.52193,1421.4428 C 501.82705,1421.4428 503.02114,1421.679 504.11248,1422.1444 C 505.20972,1422.6168 506.02114,1423.2274 506.56327,1423.9916 C 507.11248,1424.7487 507.48689,1425.6511 507.70894,1426.6928 C 507.84122,1427.3743 507.91091,1428.5613 507.91091,1430.2562 L 507.91091,1443.5401 L 504.24359,1443.5401 L 504.24359,1430.3944 C 504.24359,1428.9086 504.1054,1427.7901 503.82075,1427.0471 C 503.53611,1426.3113 503.02823,1425.7208 502.30658,1425.2838 C 501.57784,1424.8397 500.72981,1424.6164 499.75067,1424.6164 C 498.18807,1424.6164 496.8487,1425.1172 495.70894,1426.1034 C 494.57744,1427.0956 494.01524,1428.9712 494.01524,1431.742 L 494.01524,1443.54 L 490.355,1443.54 L 490.355,1443.54 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path93" />
-
- <path
- d="M 539.264,1443.54 L 539.264,1440.3664 C 537.5762,1442.8113 535.29195,1444.0266 532.40298,1444.0266 C 531.13211,1444.0266 529.93684,1443.7833 528.83369,1443.2967 C 527.72936,1442.8113 526.90967,1442.1924 526.37463,1441.4565 C 525.83368,1440.7136 525.45809,1439.8113 525.24313,1438.7412 C 525.09667,1438.0195 525.02108,1436.8809 525.02108,1435.3184 L 525.02108,1421.9365 L 528.68014,1421.9365 L 528.68014,1433.9152 C 528.68014,1435.8321 528.75691,1437.1159 528.90219,1437.7833 C 529.13841,1438.7482 529.62502,1439.4982 530.36794,1440.0533 C 531.11794,1440.6026 532.04156,1440.873 533.13881,1440.873 C 534.23605,1440.873 535.26361,1440.5955 536.22857,1440.0333 C 537.19353,1439.4711 537.87503,1438.6998 538.2707,1437.7348 C 538.67346,1436.7628 538.87424,1435.3526 538.87424,1433.5124 L 538.87424,1421.9364 L 542.53448,1421.9364 L 542.53448,1443.5399 L 539.26401,1443.5399 L 539.264,1443.54 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path95" />
-
- <path
- d="M 546.813,1437.09 L 550.43072,1436.5207 C 550.63151,1437.9723 551.20198,1439.0825 552.13151,1439.8609 C 553.05513,1440.6309 554.35434,1441.0207 556.02797,1441.0207 C 557.70868,1441.0207 558.95828,1440.6735 559.77088,1439.9931 C 560.58348,1439.3057 560.99332,1438.4991 560.99332,1437.5825 C 560.99332,1436.7498 560.6319,1436.1038 559.90907,1435.6242 C 559.40946,1435.2983 558.15986,1434.8884 556.16616,1434.3888 C 553.48624,1433.7085 551.61773,1433.125 550.58309,1432.6242 C 549.54844,1432.1317 548.75711,1431.4443 548.22207,1430.5691 C 547.68821,1429.6939 547.41656,1428.729 547.41656,1427.6731 C 547.41656,1426.7081 547.6386,1425.8199 548.08388,1425.0002 C 548.52089,1424.1735 549.12561,1423.4931 549.88152,1422.951 C 550.45199,1422.5353 551.22916,1422.1739 552.20829,1421.8821 C 553.19451,1421.5904 554.25042,1421.4439 555.37483,1421.4439 C 557.06971,1421.4439 558.55554,1421.6943 559.84058,1422.1809 C 561.12444,1422.6664 562.06932,1423.3266 562.67995,1424.1593 C 563.29176,1425.0002 563.70869,1426.1105 563.93782,1427.5065 L 560.36144,1428.0002 C 560.19491,1426.8888 559.72247,1426.0207 558.94412,1425.3959 C 558.16696,1424.7711 557.06262,1424.4581 555.6394,1424.4581 C 553.95869,1424.4581 552.75751,1424.7357 552.04176,1425.292 C 551.32011,1425.8471 550.95869,1426.5002 550.95869,1427.2432 C 550.95869,1427.7215 551.11105,1428.1455 551.40987,1428.5282 C 551.70869,1428.9239 552.17405,1429.2428 552.81302,1429.5073 C 553.18035,1429.6384 554.25751,1429.9514 556.04806,1430.4369 C 558.63822,1431.1313 560.44412,1431.6947 561.4646,1432.1388 C 562.49334,1432.5758 563.29885,1433.2219 563.88232,1434.0617 C 564.46461,1434.9026 564.75634,1435.9443 564.75634,1437.1939 C 564.75634,1438.4164 564.3961,1439.562 563.68744,1440.6451 C 562.97169,1441.7223 561.94413,1442.555 560.60358,1443.1455 C 559.26421,1443.7361 557.74295,1444.0278 556.04807,1444.0278 C 553.23587,1444.0278 551.09689,1443.4443 549.62524,1442.2774 C 548.15241,1441.1105 547.21579,1439.3813 546.81304,1437.09 L 546.813,1437.09 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path97" />
-
- <path
- d="M 583.894,1436.58 L 587.67825,1437.0454 C 587.08061,1439.2599 585.97746,1440.9749 584.36644,1442.1973 C 582.74833,1443.4127 580.68494,1444.0245 578.17864,1444.0245 C 575.01919,1444.0245 572.51171,1443.0513 570.66447,1441.1072 C 568.81014,1439.1631 567.88652,1436.4336 567.88652,1432.9198 C 567.88652,1429.2808 568.82431,1426.4615 570.69282,1424.4548 C 572.56723,1422.4481 574.99085,1421.4406 577.97668,1421.4406 C 580.86566,1421.4406 583.22668,1422.4269 585.05385,1424.3922 C 586.88692,1426.3576 587.80346,1429.1284 587.80346,1432.6906 C 587.80346,1432.9127 587.79637,1433.2399 587.7822,1433.6698 L 571.672,1433.6698 C 571.80428,1436.045 572.47751,1437.8639 573.68578,1439.1217 C 574.89405,1440.3855 576.39405,1441.0174 578.19995,1441.0174 C 579.53932,1441.0174 580.68499,1440.6631 581.63696,1439.9544 C 582.58775,1439.2529 583.33775,1438.1284 583.89405,1436.58 L 583.894,1436.58 z M 571.8727,1430.6568 L 583.9353,1430.6568 C 583.77585,1428.8438 583.3105,1427.4761 582.55341,1426.5725 C 581.38648,1425.1635 579.87349,1424.4548 578.01916,1424.4548 C 576.33845,1424.4548 574.92113,1425.017 573.77546,1426.1426 C 572.62979,1427.267 571.9979,1428.7741 571.8727,1430.6568 L 571.8727,1430.6568 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path99" />
-
- <path
- d="M 602.491,1432.74 C 602.491,1428.7408 603.60242,1425.775 605.83116,1423.8522 C 607.68549,1422.2542 609.94966,1421.4487 612.6225,1421.4487 C 615.59533,1421.4487 618.02486,1422.4219 619.90754,1424.3731 C 621.79612,1426.3172 622.73392,1429.0042 622.73392,1432.4353 C 622.73392,1435.2191 622.31699,1437.4077 621.48313,1438.9975 C 620.65045,1440.5943 619.4351,1441.8309 617.84533,1442.712 C 616.2473,1443.5943 614.51108,1444.0325 612.6225,1444.0325 C 609.60242,1444.0325 607.15754,1443.0664 605.28904,1441.1223 C 603.42172,1439.1853 602.49101,1436.3931 602.49101,1432.74 L 602.491,1432.74 z M 606.25517,1432.74 C 606.25517,1435.5109 606.85871,1437.5813 608.06698,1438.9561 C 609.27525,1440.338 610.79651,1441.0254 612.62249,1441.0254 C 614.44257,1441.0254 615.95556,1440.3309 617.16383,1438.949 C 618.36619,1437.5672 618.96974,1435.4554 618.96974,1432.6231 C 618.96974,1429.949 618.3662,1427.9211 617.15084,1426.5463 C 615.93549,1425.1715 614.4284,1424.4841 612.62249,1424.4841 C 610.79651,1424.4841 609.27525,1425.1715 608.06698,1426.5392 C 606.85871,1427.9069 606.25517,1429.9762 606.25517,1432.74 L 606.25517,1432.74 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path101" />
-
- <path
- d="M 627.032,1443.54 L 627.032,1421.9365 L 630.32373,1421.9365 L 630.32373,1425.0062 C 631.91467,1422.631 634.20601,1421.4428 637.19893,1421.4428 C 638.50405,1421.4428 639.69814,1421.679 640.78948,1422.1444 C 641.88672,1422.6168 642.69814,1423.2274 643.24027,1423.9916 C 643.78948,1424.7487 644.16389,1425.6511 644.38594,1426.6928 C 644.51822,1427.3743 644.58791,1428.5613 644.58791,1430.2562 L 644.58791,1443.5401 L 640.92059,1443.5401 L 640.92059,1430.3944 C 640.92059,1428.9086 640.7824,1427.7901 640.49775,1427.0471 C 640.21311,1426.3113 639.70523,1425.7208 638.98358,1425.2838 C 638.25484,1424.8397 637.40681,1424.6164 636.42767,1424.6164 C 634.86507,1424.6164 633.5257,1425.1172 632.38594,1426.1034 C 631.25444,1427.0956 630.69224,1428.9712 630.69224,1431.742 L 630.69224,1443.54 L 627.032,1443.54 L 627.032,1443.54 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path103" />
-
- <path
- d="M 988.517,1440.88 C 987.15519,1442.0328 985.85007,1442.8454 984.60046,1443.3249 C 983.34259,1443.7973 981.99613,1444.0335 980.55873,1444.0335 C 978.18353,1444.0335 976.36464,1443.4572 975.08668,1442.2973 C 973.81581,1441.1375 973.17684,1439.6517 973.17684,1437.8528 C 973.17684,1436.7898 973.41306,1435.8249 973.89849,1434.9497 C 974.37802,1434.0745 975.00991,1433.3741 975.78825,1432.8461 C 976.57251,1432.3182 977.4477,1431.9154 978.42683,1431.645 C 979.1414,1431.4572 980.22565,1431.2694 981.67604,1431.0957 C 984.6347,1430.7414 986.81502,1430.3245 988.21108,1429.832 C 988.22526,1429.3324 988.23234,1429.0123 988.23234,1428.88 C 988.23234,1427.3871 987.8851,1426.3324 987.19061,1425.7276 C 986.2599,1424.895 984.86384,1424.4851 983.02368,1424.4851 C 981.30163,1424.4851 980.03077,1424.7839 979.20399,1425.3875 C 978.38431,1425.9922 977.78076,1427.0611 977.38509,1428.5954 L 973.80871,1428.1028 C 974.1347,1426.5757 974.66974,1425.332 975.41265,1424.3942 C 976.15557,1423.4505 977.23863,1422.7206 978.64887,1422.2139 C 980.05793,1421.7072 981.69021,1421.4497 983.55163,1421.4497 C 985.39887,1421.4497 986.89179,1421.6729 988.04454,1422.1028 C 989.1973,1422.541 990.04415,1423.082 990.59336,1423.7422 C 991.13431,1424.4013 991.5099,1425.228 991.73194,1426.2343 C 991.85005,1426.8603 991.91265,1427.9847 991.91265,1429.6099 L 991.91265,1434.4914 C 991.91265,1437.9013 991.98824,1440.0544 992.14887,1440.9497 C 992.30123,1441.8521 992.61423,1442.7202 993.07249,1443.5469 L 989.24572,1443.5469 C 988.87132,1442.7899 988.62092,1441.9017 988.51698,1440.88 L 988.517,1440.88 z M 988.21109,1432.6997 C 986.87763,1433.2489 984.88511,1433.7072 982.23235,1434.0887 C 980.72526,1434.3036 979.65518,1434.5469 979.03747,1434.8174 C 978.41267,1435.0891 977.92605,1435.4847 977.59298,1436.0127 C 977.25283,1436.5336 977.0792,1437.1099 977.0792,1437.7489 C 977.0792,1438.728 977.45479,1439.5406 978.19062,1440.1926 C 978.92645,1440.8387 980.00952,1441.1647 981.43393,1441.1647 C 982.84299,1441.1647 984.09968,1440.8599 985.19692,1440.241 C 986.29416,1439.6233 987.10676,1438.7765 987.62054,1437.7064 C 988.01621,1436.8808 988.21109,1435.6584 988.21109,1434.0473 L 988.21109,1432.6997 L 988.21109,1432.6997 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path105" />
-
- <path
- d="M 1011.61,1443.54 L 1011.61,1440.8105 C 1010.2423,1442.9565 1008.2285,1444.0266 1005.5687,1444.0266 C 1003.8466,1444.0266 1002.2628,1443.5542 1000.8183,1442.6022 C 999.37378,1441.6585 998.25646,1440.3321 997.45803,1438.6231 C 996.66551,1436.9223 996.26984,1434.9711 996.26984,1432.7553 C 996.26984,1430.6022 996.63126,1428.6439 997.34701,1426.8876 C 998.06866,1425.1302 999.14465,1423.7837 1000.5821,1422.853 C 1002.0206,1421.9152 1003.6317,1421.4427 1005.4092,1421.4427 C 1006.7073,1421.4427 1007.8671,1421.7215 1008.8805,1422.2695 C 1009.9021,1422.8187 1010.7277,1423.5333 1011.3667,1424.4156 L 1011.3667,1413.7148 L 1015.0057,1413.7148 L 1015.0057,1443.54 L 1011.61,1443.54 L 1011.61,1443.54 z M 1000.034,1432.7554 C 1000.034,1435.5263 1000.6175,1437.5956 1001.7844,1438.9633 C 1002.9501,1440.3322 1004.3261,1441.0196 1005.9159,1441.0196 C 1007.5127,1441.0196 1008.8746,1440.3593 1009.9919,1439.0542 C 1011.1104,1437.7479 1011.6726,1435.7483 1011.6726,1433.0613 C 1011.6726,1430.1027 1011.1033,1427.9365 1009.9647,1426.5546 C 1008.8249,1425.1656 1007.423,1424.4782 1005.7494,1424.4782 C 1004.1242,1424.4782 1002.7635,1425.1444 1001.6734,1426.4708 C 1000.582,1427.7971 1000.034,1429.8948 1000.034,1432.7554 L 1000.034,1432.7554 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path107" />
-
- <path
- d="M 1020.78,1417.93 L 1020.78,1413.7158 L 1024.4461,1413.7158 L 1024.4461,1417.93 L 1020.78,1417.93 z M 1020.78,1443.541 L 1020.78,1421.9375 L 1024.4461,1421.9375 L 1024.4461,1443.541 L 1020.78,1443.541 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path109" />
-
- <path
- d="M 1044.81,1436.58 L 1048.5942,1437.0454 C 1047.9966,1439.2599 1046.8935,1440.9749 1045.2824,1442.1973 C 1043.6643,1443.4127 1041.6009,1444.0245 1039.0946,1444.0245 C 1035.9352,1444.0245 1033.4277,1443.0513 1031.5805,1441.1072 C 1029.7261,1439.1631 1028.8025,1436.4336 1028.8025,1432.9198 C 1028.8025,1429.2808 1029.7403,1426.4615 1031.6088,1424.4548 C 1033.4832,1422.4481 1035.9069,1421.4406 1038.8927,1421.4406 C 1041.7817,1421.4406 1044.1427,1422.4269 1045.9699,1424.3922 C 1047.8029,1426.3576 1048.7195,1429.1284 1048.7195,1432.6906 C 1048.7195,1432.9127 1048.7124,1433.2399 1048.6982,1433.6698 L 1032.588,1433.6698 C 1032.7203,1436.045 1033.3935,1437.8639 1034.6018,1439.1217 C 1035.8101,1440.3855 1037.3101,1441.0174 1039.116,1441.0174 C 1040.4553,1441.0174 1041.601,1440.6631 1042.553,1439.9544 C 1043.5037,1439.2529 1044.2538,1438.1284 1044.8101,1436.58 L 1044.81,1436.58 z M 1032.7887,1430.6568 L 1044.8513,1430.6568 C 1044.6919,1428.8438 1044.2265,1427.4761 1043.4694,1426.5725 C 1042.3025,1425.1635 1040.7895,1424.4548 1038.9352,1424.4548 C 1037.2544,1424.4548 1035.8371,1425.017 1034.6915,1426.1426 C 1033.5458,1427.267 1032.9139,1428.7741 1032.7887,1430.6568 L 1032.7887,1430.6568 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path111" />
-
- <path
- d="M 1053.19,1443.54 L 1053.19,1421.9365 L 1056.4817,1421.9365 L 1056.4817,1425.0062 C 1058.0727,1422.631 1060.364,1421.4428 1063.3569,1421.4428 C 1064.662,1421.4428 1065.8561,1421.679 1066.9475,1422.1444 C 1068.0447,1422.6168 1068.8561,1423.2274 1069.3983,1423.9916 C 1069.9475,1424.7487 1070.3219,1425.6511 1070.5439,1426.6928 C 1070.6762,1427.3743 1070.7459,1428.5613 1070.7459,1430.2562 L 1070.7459,1443.5401 L 1067.0786,1443.5401 L 1067.0786,1430.3944 C 1067.0786,1428.9086 1066.9404,1427.7901 1066.6558,1427.0471 C 1066.3711,1426.3113 1065.8632,1425.7208 1065.1416,1425.2838 C 1064.4128,1424.8397 1063.5648,1424.6164 1062.5857,1424.6164 C 1061.0231,1424.6164 1059.6837,1425.1172 1058.5439,1426.1034 C 1057.4124,1427.0956 1056.8502,1428.9712 1056.8502,1431.742 L 1056.8502,1443.54 L 1053.19,1443.54 L 1053.19,1443.54 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path113" />
-
- <path
- d="M 1084.36,1440.26 L 1084.8868,1443.4962 C 1083.8592,1443.7112 1082.9356,1443.8222 1082.123,1443.8222 C 1080.7907,1443.8222 1079.762,1443.6143 1079.0261,1443.1903 C 1078.2974,1442.7734 1077.7836,1442.2183 1077.4848,1441.5309 C 1077.186,1440.8505 1077.0336,1439.4061 1077.0336,1437.2116 L 1077.0336,1424.7805 L 1074.3454,1424.7805 L 1074.3454,1421.934 L 1077.0336,1421.934 L 1077.0336,1416.5801 L 1080.6785,1414.3856 L 1080.6785,1421.934 L 1084.36,1421.934 L 1084.36,1424.7805 L 1080.6785,1424.7805 L 1080.6785,1437.4124 C 1080.6785,1438.4612 1080.7411,1439.1285 1080.8663,1439.4262 C 1080.9986,1439.725 1081.2065,1439.9612 1081.4982,1440.1419 C 1081.7899,1440.3155 1082.2068,1440.4053 1082.749,1440.4053 C 1083.1576,1440.4053 1083.6927,1440.3569 1084.36,1440.26 L 1084.36,1440.26 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path115" />
-
- <polygon
- points="1098.09,1434.59 1098.09,1430.91 1109.35,1430.91 1109.35,1434.59 1098.09,1434.59 "
- style="fill:#000000;fill-rule:nonzero"
- id="polygon117" />
-
- <path
- d="M 1138.98,1443.54 L 1138.98,1440.8105 C 1137.6123,1442.9565 1135.5985,1444.0266 1132.9387,1444.0266 C 1131.2166,1444.0266 1129.6328,1443.5542 1128.1883,1442.6022 C 1126.7438,1441.6585 1125.6265,1440.3321 1124.828,1438.6231 C 1124.0355,1436.9223 1123.6398,1434.9711 1123.6398,1432.7553 C 1123.6398,1430.6022 1124.0013,1428.6439 1124.717,1426.8876 C 1125.4387,1425.1302 1126.5147,1423.7837 1127.9521,1422.853 C 1129.3906,1421.9152 1131.0017,1421.4427 1132.7792,1421.4427 C 1134.0773,1421.4427 1135.2371,1421.7215 1136.2505,1422.2695 C 1137.2721,1422.8187 1138.0977,1423.5333 1138.7367,1424.4156 L 1138.7367,1413.7148 L 1142.3757,1413.7148 L 1142.3757,1443.54 L 1138.98,1443.54 L 1138.98,1443.54 z M 1127.404,1432.7554 C 1127.404,1435.5263 1127.9875,1437.5956 1129.1544,1438.9633 C 1130.3201,1440.3322 1131.6961,1441.0196 1133.2859,1441.0196 C 1134.8827,1441.0196 1136.2445,1440.3593 1137.3619,1439.0542 C 1138.4804,1437.7479 1139.0426,1435.7483 1139.0426,1433.0613 C 1139.0426,1430.1027 1138.4733,1427.9365 1137.3347,1426.5546 C 1136.195,1425.1656 1134.793,1424.4782 1133.1194,1424.4782 C 1131.4942,1424.4782 1130.1335,1425.1444 1129.0434,1426.4708 C 1127.952,1427.7971 1127.404,1429.8948 1127.404,1432.7554 L 1127.404,1432.7554 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path119" />
-
- <path
- d="M 1148.16,1417.93 L 1148.16,1413.7158 L 1151.8261,1413.7158 L 1151.8261,1417.93 L 1148.16,1417.93 z M 1148.16,1443.541 L 1148.16,1421.9375 L 1151.8261,1421.9375 L 1151.8261,1443.541 L 1148.16,1443.541 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path121" />
-
- <path
- d="M 1158.27,1443.54 L 1158.27,1424.7829 L 1155.0409,1424.7829 L 1155.0409,1421.9364 L 1158.27,1421.9364 L 1158.27,1419.638 C 1158.27,1418.1864 1158.4023,1417.1034 1158.6586,1416.4018 C 1159.0129,1415.4498 1159.6318,1414.6797 1160.52,1414.0892 C 1161.4094,1413.4986 1162.6519,1413.2069 1164.2558,1413.2069 C 1165.2846,1413.2069 1166.4232,1413.325 1167.6728,1413.5754 L 1167.1247,1416.7703 C 1166.3676,1416.6309 1165.6448,1416.5612 1164.9645,1416.5612 C 1163.8531,1416.5612 1163.0688,1416.7975 1162.6106,1417.277 C 1162.1452,1417.7494 1161.9161,1418.6376 1161.9161,1419.9427 L 1161.9161,1421.9364 L 1166.1243,1421.9364 L 1166.1243,1424.7829 L 1161.9161,1424.7829 L 1161.9161,1443.54 L 1158.27,1443.54 L 1158.27,1443.54 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path123" />
-
- <path
- d="M 1169.09,1443.54 L 1169.09,1424.7829 L 1165.8609,1424.7829 L 1165.8609,1421.9364 L 1169.09,1421.9364 L 1169.09,1419.638 C 1169.09,1418.1864 1169.2223,1417.1034 1169.4786,1416.4018 C 1169.8329,1415.4498 1170.4518,1414.6797 1171.34,1414.0892 C 1172.2294,1413.4986 1173.4719,1413.2069 1175.0758,1413.2069 C 1176.1046,1413.2069 1177.2432,1413.325 1178.4928,1413.5754 L 1177.9447,1416.7703 C 1177.1876,1416.6309 1176.4648,1416.5612 1175.7845,1416.5612 C 1174.6731,1416.5612 1173.8888,1416.7975 1173.4306,1417.277 C 1172.9652,1417.7494 1172.7361,1418.6376 1172.7361,1419.9427 L 1172.7361,1421.9364 L 1176.9443,1421.9364 L 1176.9443,1424.7829 L 1172.7361,1424.7829 L 1172.7361,1443.54 L 1169.09,1443.54 L 1169.09,1443.54 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path125" />
-
- <path
- d="M 1194.59,1436.58 L 1198.3742,1437.0454 C 1197.7766,1439.2599 1196.6735,1440.9749 1195.0624,1442.1973 C 1193.4443,1443.4127 1191.3809,1444.0245 1188.8746,1444.0245 C 1185.7152,1444.0245 1183.2077,1443.0513 1181.3605,1441.1072 C 1179.5061,1439.1631 1178.5825,1436.4336 1178.5825,1432.9198 C 1178.5825,1429.2808 1179.5203,1426.4615 1181.3888,1424.4548 C 1183.2632,1422.4481 1185.6869,1421.4406 1188.6727,1421.4406 C 1191.5617,1421.4406 1193.9227,1422.4269 1195.7499,1424.3922 C 1197.5829,1426.3576 1198.4995,1429.1284 1198.4995,1432.6906 C 1198.4995,1432.9127 1198.4924,1433.2399 1198.4782,1433.6698 L 1182.368,1433.6698 C 1182.5003,1436.045 1183.1735,1437.8639 1184.3818,1439.1217 C 1185.5901,1440.3855 1187.0901,1441.0174 1188.896,1441.0174 C 1190.2353,1441.0174 1191.381,1440.6631 1192.333,1439.9544 C 1193.2837,1439.2529 1194.0338,1438.1284 1194.5901,1436.58 L 1194.59,1436.58 z M 1182.5687,1430.6568 L 1194.6313,1430.6568 C 1194.4719,1428.8438 1194.0065,1427.4761 1193.2494,1426.5725 C 1192.0825,1425.1635 1190.5695,1424.4548 1188.7152,1424.4548 C 1187.0344,1424.4548 1185.6171,1425.017 1184.4715,1426.1426 C 1183.3258,1427.267 1182.6939,1428.7741 1182.5687,1430.6568 L 1182.5687,1430.6568 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path127" />
-
- <path
- d="M 1202.93,1443.54 L 1202.93,1421.9365 L 1206.2217,1421.9365 L 1206.2217,1425.207 C 1207.0615,1423.6798 1207.8398,1422.6652 1208.5544,1422.1798 C 1209.2631,1421.6932 1210.0473,1421.4428 1210.9024,1421.4428 C 1212.1379,1421.4428 1213.3887,1421.8396 1214.6654,1422.6239 L 1213.4017,1426.0267 C 1212.5135,1425.4916 1211.617,1425.2282 1210.7217,1425.2282 C 1209.9162,1425.2282 1209.2005,1425.4715 1208.5615,1425.9499 C 1207.9225,1426.4365 1207.4713,1427.1026 1207.2009,1427.9566 C 1206.791,1429.2558 1206.5902,1430.679 1206.5902,1432.2274 L 1206.5902,1443.54 L 1202.93,1443.54 L 1202.93,1443.54 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path129" />
-
- <path
- d="M 1231.63,1436.58 L 1235.4143,1437.0454 C 1234.8166,1439.2599 1233.7135,1440.9749 1232.1024,1442.1973 C 1230.4843,1443.4127 1228.4209,1444.0245 1225.9146,1444.0245 C 1222.7552,1444.0245 1220.2477,1443.0513 1218.4005,1441.1072 C 1216.5461,1439.1631 1215.6225,1436.4336 1215.6225,1432.9198 C 1215.6225,1429.2808 1216.5603,1426.4615 1218.4288,1424.4548 C 1220.3032,1422.4481 1222.7269,1421.4406 1225.7127,1421.4406 C 1228.6017,1421.4406 1230.9627,1422.4269 1232.7899,1424.3922 C 1234.6229,1426.3576 1235.5395,1429.1284 1235.5395,1432.6906 C 1235.5395,1432.9127 1235.5324,1433.2399 1235.5182,1433.6698 L 1219.408,1433.6698 C 1219.5403,1436.045 1220.2135,1437.8639 1221.4218,1439.1217 C 1222.6301,1440.3855 1224.1301,1441.0174 1225.936,1441.0174 C 1227.2753,1441.0174 1228.421,1440.6631 1229.373,1439.9544 C 1230.3237,1439.2529 1231.0738,1438.1284 1231.6301,1436.58 L 1231.63,1436.58 z M 1219.6087,1430.6568 L 1231.6713,1430.6568 C 1231.5119,1428.8438 1231.0465,1427.4761 1230.2894,1426.5725 C 1229.1225,1425.1635 1227.6095,1424.4548 1225.7552,1424.4548 C 1224.0744,1424.4548 1222.6571,1425.017 1221.5115,1426.1426 C 1220.3658,1427.267 1219.7339,1428.7741 1219.6087,1430.6568 L 1219.6087,1430.6568 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path131" />
-
- <path
- d="M 1240.02,1443.54 L 1240.02,1421.9365 L 1243.3117,1421.9365 L 1243.3117,1425.0062 C 1244.9027,1422.631 1247.194,1421.4428 1250.1869,1421.4428 C 1251.492,1421.4428 1252.6861,1421.679 1253.7775,1422.1444 C 1254.8747,1422.6168 1255.6861,1423.2274 1256.2283,1423.9916 C 1256.7775,1424.7487 1257.1519,1425.6511 1257.3739,1426.6928 C 1257.5062,1427.3743 1257.5759,1428.5613 1257.5759,1430.2562 L 1257.5759,1443.5401 L 1253.9086,1443.5401 L 1253.9086,1430.3944 C 1253.9086,1428.9086 1253.7704,1427.7901 1253.4858,1427.0471 C 1253.2011,1426.3113 1252.6932,1425.7208 1251.9716,1425.2838 C 1251.2428,1424.8397 1250.3948,1424.6164 1249.4157,1424.6164 C 1247.8531,1424.6164 1246.5137,1425.1172 1245.3739,1426.1034 C 1244.2424,1427.0956 1243.6802,1428.9712 1243.6802,1431.742 L 1243.6802,1443.54 L 1240.02,1443.54 L 1240.02,1443.54 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path133" />
-
- <path
- d="M 1271.19,1440.26 L 1271.7168,1443.4962 C 1270.6892,1443.7112 1269.7656,1443.8222 1268.953,1443.8222 C 1267.6207,1443.8222 1266.592,1443.6143 1265.8561,1443.1903 C 1265.1274,1442.7734 1264.6136,1442.2183 1264.3148,1441.5309 C 1264.016,1440.8505 1263.8636,1439.4061 1263.8636,1437.2116 L 1263.8636,1424.7805 L 1261.1754,1424.7805 L 1261.1754,1421.934 L 1263.8636,1421.934 L 1263.8636,1416.5801 L 1267.5085,1414.3856 L 1267.5085,1421.934 L 1271.19,1421.934 L 1271.19,1424.7805 L 1267.5085,1424.7805 L 1267.5085,1437.4124 C 1267.5085,1438.4612 1267.5711,1439.1285 1267.6963,1439.4262 C 1267.8286,1439.725 1268.0365,1439.9612 1268.3282,1440.1419 C 1268.6199,1440.3155 1269.0368,1440.4053 1269.579,1440.4053 C 1269.9876,1440.4053 1270.5227,1440.3569 1271.19,1440.26 L 1271.19,1440.26 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path135" />
-
- <path
- d="M 1300.45,1435.63 L 1304.0465,1436.1024 C 1303.6579,1438.5816 1302.6504,1440.5257 1301.0264,1441.9288 C 1299.4083,1443.332 1297.4146,1444.0335 1295.0536,1444.0335 C 1292.1032,1444.0335 1289.7209,1443.0674 1287.9291,1441.1375 C 1286.1303,1439.2064 1285.228,1436.4355 1285.228,1432.8249 C 1285.228,1430.4922 1285.6165,1428.4501 1286.3878,1426.6997 C 1287.165,1424.9505 1288.339,1423.6371 1289.9217,1422.7631 C 1291.4984,1421.8879 1293.2205,1421.4497 1295.0748,1421.4497 C 1297.4217,1421.4497 1299.3457,1422.0473 1300.8315,1423.2343 C 1302.3244,1424.4225 1303.2835,1426.1032 1303.7063,1428.2906 L 1300.1441,1428.8387 C 1299.8039,1427.3871 1299.2063,1426.2969 1298.3453,1425.5611 C 1297.4843,1424.8324 1296.4425,1424.4639 1295.2201,1424.4639 C 1293.3728,1424.4639 1291.8728,1425.1241 1290.7201,1426.4505 C 1289.5673,1427.7698 1288.991,1429.8603 1288.991,1432.7209 C 1288.991,1435.6229 1289.5472,1437.7347 1290.6646,1439.054 C 1291.776,1440.3662 1293.2276,1441.0265 1295.0193,1441.0265 C 1296.4567,1441.0265 1297.6508,1440.5812 1298.6158,1439.7001 C 1299.5819,1438.8178 1300.1925,1437.4642 1300.45,1435.63 L 1300.45,1435.63 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path137" />
-
- <path
- d="M 1321.34,1443.54 L 1321.34,1440.3664 C 1319.6522,1442.8113 1317.3679,1444.0266 1314.479,1444.0266 C 1313.2081,1444.0266 1312.0128,1443.7833 1310.9097,1443.2967 C 1309.8054,1442.8113 1308.9857,1442.1924 1308.4506,1441.4565 C 1307.9097,1440.7136 1307.5341,1439.8113 1307.3191,1438.7412 C 1307.1727,1438.0195 1307.0971,1436.8809 1307.0971,1435.3184 L 1307.0971,1421.9365 L 1310.7561,1421.9365 L 1310.7561,1433.9152 C 1310.7561,1435.8321 1310.8329,1437.1159 1310.9782,1437.7833 C 1311.2144,1438.7482 1311.701,1439.4982 1312.4439,1440.0533 C 1313.1939,1440.6026 1314.1176,1440.873 1315.2148,1440.873 C 1316.3121,1440.873 1317.3396,1440.5955 1318.3046,1440.0333 C 1319.2695,1439.4711 1319.951,1438.6998 1320.3467,1437.7348 C 1320.7495,1436.7628 1320.9502,1435.3526 1320.9502,1433.5124 L 1320.9502,1421.9364 L 1324.6105,1421.9364 L 1324.6105,1443.5399 L 1321.34,1443.5399 L 1321.34,1443.54 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path139" />
-
- <path
- d="M 1330.31,1443.54 L 1330.31,1421.9365 L 1333.6017,1421.9365 L 1333.6017,1425.207 C 1334.4415,1423.6798 1335.2198,1422.6652 1335.9344,1422.1798 C 1336.6431,1421.6932 1337.4273,1421.4428 1338.2824,1421.4428 C 1339.5179,1421.4428 1340.7687,1421.8396 1342.0454,1422.6239 L 1340.7816,1426.0267 C 1339.8935,1425.4916 1338.997,1425.2282 1338.1017,1425.2282 C 1337.2962,1425.2282 1336.5805,1425.4715 1335.9415,1425.9499 C 1335.3025,1426.4365 1334.8513,1427.1026 1334.5809,1427.9566 C 1334.171,1429.2558 1333.9702,1430.679 1333.9702,1432.2274 L 1333.9702,1443.54 L 1330.31,1443.54 L 1330.31,1443.54 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path141" />
-
- <path
- d="M 1350.23,1443.54 L 1342.0084,1421.9365 L 1345.8765,1421.9365 L 1350.5146,1434.8731 C 1351.0154,1436.2692 1351.4737,1437.7207 1351.8965,1439.2278 C 1352.2237,1438.0892 1352.6749,1436.7203 1353.2584,1435.1164 L 1358.0631,1421.9365 L 1361.8272,1421.9365 L 1353.6469,1443.54 L 1350.23,1443.54 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path143" />
-
- <path
- d="M 1379.85,1436.58 L 1383.6342,1437.0454 C 1383.0366,1439.2599 1381.9335,1440.9749 1380.3224,1442.1973 C 1378.7043,1443.4127 1376.6409,1444.0245 1374.1346,1444.0245 C 1370.9752,1444.0245 1368.4677,1443.0513 1366.6205,1441.1072 C 1364.7661,1439.1631 1363.8425,1436.4336 1363.8425,1432.9198 C 1363.8425,1429.2808 1364.7803,1426.4615 1366.6488,1424.4548 C 1368.5232,1422.4481 1370.9469,1421.4406 1373.9327,1421.4406 C 1376.8217,1421.4406 1379.1827,1422.4269 1381.0099,1424.3922 C 1382.8429,1426.3576 1383.7595,1429.1284 1383.7595,1432.6906 C 1383.7595,1432.9127 1383.7524,1433.2399 1383.7382,1433.6698 L 1367.628,1433.6698 C 1367.7603,1436.045 1368.4335,1437.8639 1369.6418,1439.1217 C 1370.8501,1440.3855 1372.3501,1441.0174 1374.156,1441.0174 C 1375.4953,1441.0174 1376.641,1440.6631 1377.593,1439.9544 C 1378.5437,1439.2529 1379.2938,1438.1284 1379.8501,1436.58 L 1379.85,1436.58 z M 1367.8287,1430.6568 L 1379.8913,1430.6568 C 1379.7319,1428.8438 1379.2665,1427.4761 1378.5094,1426.5725 C 1377.3425,1425.1635 1375.8295,1424.4548 1373.9752,1424.4548 C 1372.2944,1424.4548 1370.8771,1425.017 1369.7315,1426.1426 C 1368.5858,1427.267 1367.9539,1428.7741 1367.8287,1430.6568 L 1367.8287,1430.6568 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path145" />
-
- <path
- d="M 1386.77,1437.09 L 1390.3877,1436.5207 C 1390.5885,1437.9723 1391.159,1439.0825 1392.0885,1439.8609 C 1393.0121,1440.6309 1394.3113,1441.0207 1395.985,1441.0207 C 1397.6657,1441.0207 1398.9153,1440.6735 1399.7279,1439.9931 C 1400.5405,1439.3057 1400.9503,1438.4991 1400.9503,1437.5825 C 1400.9503,1436.7498 1400.5889,1436.1038 1399.8661,1435.6242 C 1399.3665,1435.2983 1398.1169,1434.8884 1396.1232,1434.3888 C 1393.4432,1433.7085 1391.5747,1433.125 1390.5401,1432.6242 C 1389.5054,1432.1317 1388.7141,1431.4443 1388.1791,1430.5691 C 1387.6452,1429.6939 1387.3736,1428.729 1387.3736,1427.6731 C 1387.3736,1426.7081 1387.5956,1425.8199 1388.0409,1425.0002 C 1388.4779,1424.1735 1389.0826,1423.4931 1389.8385,1422.951 C 1390.409,1422.5353 1391.1862,1422.1739 1392.1653,1421.8821 C 1393.1515,1421.5904 1394.2074,1421.4439 1395.3318,1421.4439 C 1397.0267,1421.4439 1398.5125,1421.6943 1399.7976,1422.1809 C 1401.0814,1422.6664 1402.0263,1423.3266 1402.637,1424.1593 C 1403.2488,1425.0002 1403.6657,1426.1105 1403.8948,1427.5065 L 1400.3184,1428.0002 C 1400.1519,1426.8888 1399.6795,1426.0207 1398.9011,1425.3959 C 1398.124,1424.7711 1397.0196,1424.4581 1395.5964,1424.4581 C 1393.9157,1424.4581 1392.7145,1424.7357 1391.9988,1425.292 C 1391.2771,1425.8471 1390.9157,1426.5002 1390.9157,1427.2432 C 1390.9157,1427.7215 1391.0681,1428.1455 1391.3669,1428.5282 C 1391.6657,1428.9239 1392.131,1429.2428 1392.77,1429.5073 C 1393.1373,1429.6384 1394.2145,1429.9514 1396.0051,1430.4369 C 1398.5952,1431.1313 1400.4011,1431.6947 1401.4216,1432.1388 C 1402.4503,1432.5758 1403.2559,1433.2219 1403.8393,1434.0617 C 1404.4216,1434.9026 1404.7133,1435.9443 1404.7133,1437.1939 C 1404.7133,1438.4164 1404.3531,1439.562 1403.6444,1440.6451 C 1402.9287,1441.7223 1401.9011,1442.555 1400.5606,1443.1455 C 1399.2212,1443.7361 1397.6999,1444.0278 1396.0051,1444.0278 C 1393.1929,1444.0278 1391.0539,1443.4443 1389.5822,1442.2774 C 1388.1094,1441.1105 1387.1728,1439.3813 1386.77,1437.09 L 1386.77,1437.09 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path147" />
-
- <path
- d="M 1410.02,1443.54 L 1410.02,1439.366 L 1414.1928,1439.366 L 1414.1928,1443.54 C 1414.1928,1445.0742 1413.9224,1446.3109 1413.3802,1447.2558 C 1412.8322,1448.1924 1411.9712,1448.9223 1410.7972,1449.4432 L 1409.7767,1447.8735 C 1410.548,1447.5333 1411.1172,1447.0325 1411.4846,1446.3806 C 1411.8531,1445.7203 1412.0539,1444.7766 1412.0964,1443.54 L 1410.02,1443.54 L 1410.02,1443.54 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path149" />
-
- <path
- d="M 1430.75,1437.09 L 1434.3677,1436.5207 C 1434.5685,1437.9723 1435.139,1439.0825 1436.0685,1439.8609 C 1436.9921,1440.6309 1438.2913,1441.0207 1439.965,1441.0207 C 1441.6457,1441.0207 1442.8953,1440.6735 1443.7079,1439.9931 C 1444.5205,1439.3057 1444.9303,1438.4991 1444.9303,1437.5825 C 1444.9303,1436.7498 1444.5689,1436.1038 1443.8461,1435.6242 C 1443.3465,1435.2983 1442.0969,1434.8884 1440.1032,1434.3888 C 1437.4232,1433.7085 1435.5547,1433.125 1434.5201,1432.6242 C 1433.4854,1432.1317 1432.6941,1431.4443 1432.1591,1430.5691 C 1431.6252,1429.6939 1431.3536,1428.729 1431.3536,1427.6731 C 1431.3536,1426.7081 1431.5756,1425.8199 1432.0209,1425.0002 C 1432.4579,1424.1735 1433.0626,1423.4931 1433.8185,1422.951 C 1434.389,1422.5353 1435.1662,1422.1739 1436.1453,1421.8821 C 1437.1315,1421.5904 1438.1874,1421.4439 1439.3118,1421.4439 C 1441.0067,1421.4439 1442.4925,1421.6943 1443.7776,1422.1809 C 1445.0614,1422.6664 1446.0063,1423.3266 1446.617,1424.1593 C 1447.2288,1425.0002 1447.6457,1426.1105 1447.8748,1427.5065 L 1444.2984,1428.0002 C 1444.1319,1426.8888 1443.6595,1426.0207 1442.8811,1425.3959 C 1442.104,1424.7711 1440.9996,1424.4581 1439.5764,1424.4581 C 1437.8957,1424.4581 1436.6945,1424.7357 1435.9788,1425.292 C 1435.2571,1425.8471 1434.8957,1426.5002 1434.8957,1427.2432 C 1434.8957,1427.7215 1435.0481,1428.1455 1435.3469,1428.5282 C 1435.6457,1428.9239 1436.111,1429.2428 1436.75,1429.5073 C 1437.1173,1429.6384 1438.1945,1429.9514 1439.9851,1430.4369 C 1442.5752,1431.1313 1444.3811,1431.6947 1445.4016,1432.1388 C 1446.4303,1432.5758 1447.2359,1433.2219 1447.8193,1434.0617 C 1448.4016,1434.9026 1448.6933,1435.9443 1448.6933,1437.1939 C 1448.6933,1438.4164 1448.3331,1439.562 1447.6244,1440.6451 C 1446.9087,1441.7223 1445.8811,1442.555 1444.5406,1443.1455 C 1443.2012,1443.7361 1441.6799,1444.0278 1439.9851,1444.0278 C 1437.1729,1444.0278 1435.0339,1443.4443 1433.5622,1442.2774 C 1432.0894,1441.1105 1431.1528,1439.3813 1430.75,1437.09 L 1430.75,1437.09 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path151" />
-
- <path
- d="M 1453.05,1451.82 L 1453.05,1421.9393 L 1456.3831,1421.9393 L 1456.3831,1424.7444 C 1457.1685,1423.6472 1458.0567,1422.8216 1459.05,1422.2724 C 1460.0362,1421.7243 1461.2374,1421.4456 1462.6476,1421.4456 C 1464.4949,1421.4456 1466.1201,1421.9251 1467.5291,1422.87 C 1468.9453,1423.8208 1470.0083,1425.1613 1470.724,1426.8905 C 1471.4457,1428.6196 1471.8071,1430.5153 1471.8071,1432.5775 C 1471.8071,1434.7861 1471.4114,1436.7787 1470.613,1438.5503 C 1469.8205,1440.3208 1468.6677,1441.6743 1467.1547,1442.6192 C 1465.6406,1443.557 1464.0496,1444.0295 1462.3831,1444.0295 C 1461.1618,1444.0295 1460.0705,1443.772 1459.0984,1443.2582 C 1458.1264,1442.7444 1457.335,1442.0913 1456.7102,1441.307 L 1456.7102,1451.82 L 1453.05,1451.82 L 1453.05,1451.82 z M 1456.363,1432.8621 C 1456.363,1435.64 1456.9252,1437.6952 1458.0508,1439.0286 C 1459.1752,1440.355 1460.5429,1441.0223 1462.1409,1441.0223 C 1463.765,1441.0223 1465.161,1440.3349 1466.3209,1438.953 C 1467.4807,1437.5782 1468.0642,1435.4464 1468.0642,1432.5574 C 1468.0642,1429.7995 1467.4949,1427.7444 1466.3622,1426.3696 C 1465.2307,1425.0019 1463.876,1424.3145 1462.3075,1424.3145 C 1460.7449,1424.3145 1459.363,1425.0432 1458.1618,1426.5019 C 1456.9595,1427.9593 1456.363,1430.0853 1456.363,1432.8621 L 1456.363,1432.8621 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path153" />
-
- <path
- d="M 1490.32,1440.88 C 1488.9582,1442.0328 1487.6531,1442.8454 1486.4035,1443.3249 C 1485.1456,1443.7973 1483.7991,1444.0335 1482.3617,1444.0335 C 1479.9865,1444.0335 1478.1676,1443.4572 1476.8897,1442.2973 C 1475.6188,1441.1375 1474.9798,1439.6517 1474.9798,1437.8528 C 1474.9798,1436.7898 1475.2161,1435.8249 1475.7015,1434.9497 C 1476.181,1434.0745 1476.8129,1433.3741 1477.5913,1432.8461 C 1478.3755,1432.3182 1479.2507,1431.9154 1480.2298,1431.645 C 1480.9444,1431.4572 1482.0287,1431.2694 1483.479,1431.0957 C 1486.4377,1430.7414 1488.618,1430.3245 1490.0141,1429.832 C 1490.0283,1429.3324 1490.0353,1429.0123 1490.0353,1428.88 C 1490.0353,1427.3871 1489.6881,1426.3324 1488.9936,1425.7276 C 1488.0629,1424.895 1486.6668,1424.4851 1484.8267,1424.4851 C 1483.1046,1424.4851 1481.8338,1424.7839 1481.007,1425.3875 C 1480.1873,1425.9922 1479.5838,1427.0611 1479.1881,1428.5954 L 1475.6117,1428.1028 C 1475.9377,1426.5757 1476.4727,1425.332 1477.2157,1424.3942 C 1477.9586,1423.4505 1479.0416,1422.7206 1480.4519,1422.2139 C 1481.8609,1421.7072 1483.4932,1421.4497 1485.3546,1421.4497 C 1487.2019,1421.4497 1488.6948,1421.6729 1489.8475,1422.1028 C 1491.0003,1422.541 1491.8472,1423.082 1492.3964,1423.7422 C 1492.9373,1424.4013 1493.3129,1425.228 1493.5349,1426.2343 C 1493.6531,1426.8603 1493.7157,1427.9847 1493.7157,1429.6099 L 1493.7157,1434.4914 C 1493.7157,1437.9013 1493.7912,1440.0544 1493.9519,1440.9497 C 1494.1042,1441.8521 1494.4172,1442.7202 1494.8755,1443.5469 L 1491.0487,1443.5469 C 1490.6743,1442.7899 1490.4239,1441.9017 1490.32,1440.88 L 1490.32,1440.88 z M 1490.0141,1432.6997 C 1488.6806,1433.2489 1486.6881,1433.7072 1484.0354,1434.0887 C 1482.5283,1434.3036 1481.4582,1434.5469 1480.8405,1434.8174 C 1480.2157,1435.0891 1479.7291,1435.4847 1479.396,1436.0127 C 1479.0558,1436.5336 1478.8822,1437.1099 1478.8822,1437.7489 C 1478.8822,1438.728 1479.2578,1439.5406 1479.9936,1440.1926 C 1480.7295,1440.8387 1481.8125,1441.1647 1483.2369,1441.1647 C 1484.646,1441.1647 1485.9027,1440.8599 1486.9999,1440.241 C 1488.0972,1439.6233 1488.9098,1438.7765 1489.4235,1437.7064 C 1489.8192,1436.8808 1490.0141,1435.6584 1490.0141,1434.0473 L 1490.0141,1432.6997 L 1490.0141,1432.6997 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path155" />
-
- <path
- d="M 1513.49,1435.63 L 1517.0865,1436.1024 C 1516.6979,1438.5816 1515.6904,1440.5257 1514.0664,1441.9288 C 1512.4483,1443.332 1510.4546,1444.0335 1508.0936,1444.0335 C 1505.1432,1444.0335 1502.7609,1443.0674 1500.9691,1441.1375 C 1499.1703,1439.2064 1498.268,1436.4355 1498.268,1432.8249 C 1498.268,1430.4922 1498.6565,1428.4501 1499.4278,1426.6997 C 1500.205,1424.9505 1501.379,1423.6371 1502.9617,1422.7631 C 1504.5384,1421.8879 1506.2605,1421.4497 1508.1148,1421.4497 C 1510.4617,1421.4497 1512.3857,1422.0473 1513.8715,1423.2343 C 1515.3644,1424.4225 1516.3235,1426.1032 1516.7463,1428.2906 L 1513.1841,1428.8387 C 1512.8439,1427.3871 1512.2463,1426.2969 1511.3853,1425.5611 C 1510.5243,1424.8324 1509.4825,1424.4639 1508.2601,1424.4639 C 1506.4128,1424.4639 1504.9128,1425.1241 1503.7601,1426.4505 C 1502.6073,1427.7698 1502.031,1429.8603 1502.031,1432.7209 C 1502.031,1435.6229 1502.5872,1437.7347 1503.7046,1439.054 C 1504.816,1440.3662 1506.2676,1441.0265 1508.0593,1441.0265 C 1509.4967,1441.0265 1510.6908,1440.5812 1511.6558,1439.7001 C 1512.6219,1438.8178 1513.2325,1437.4642 1513.49,1435.63 L 1513.49,1435.63 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path157" />
-
- <path
- d="M 1520.24,1417.93 L 1520.24,1413.7158 L 1523.9061,1413.7158 L 1523.9061,1417.93 L 1520.24,1417.93 z M 1520.24,1443.541 L 1520.24,1421.9375 L 1523.9061,1421.9375 L 1523.9061,1443.541 L 1520.24,1443.541 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path159" />
-
- <path
- d="M 1529.49,1443.54 L 1529.49,1421.9365 L 1532.7817,1421.9365 L 1532.7817,1425.0062 C 1534.3727,1422.631 1536.664,1421.4428 1539.6569,1421.4428 C 1540.962,1421.4428 1542.1561,1421.679 1543.2475,1422.1444 C 1544.3447,1422.6168 1545.1561,1423.2274 1545.6983,1423.9916 C 1546.2475,1424.7487 1546.6219,1425.6511 1546.8439,1426.6928 C 1546.9762,1427.3743 1547.0459,1428.5613 1547.0459,1430.2562 L 1547.0459,1443.5401 L 1543.3786,1443.5401 L 1543.3786,1430.3944 C 1543.3786,1428.9086 1543.2404,1427.7901 1542.9558,1427.0471 C 1542.6711,1426.3113 1542.1632,1425.7208 1541.4416,1425.2838 C 1540.7128,1424.8397 1539.8648,1424.6164 1538.8857,1424.6164 C 1537.3231,1424.6164 1535.9837,1425.1172 1534.8439,1426.1034 C 1533.7124,1427.0956 1533.1502,1428.9712 1533.1502,1431.742 L 1533.1502,1443.54 L 1529.49,1443.54 L 1529.49,1443.54 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path161" />
-
- <path
- d="M 1551.99,1445.33 L 1555.5522,1445.858 C 1555.6987,1446.9552 1556.1144,1447.7536 1556.7888,1448.2603 C 1557.6983,1448.9335 1558.9408,1449.2737 1560.5105,1449.2737 C 1562.2124,1449.2737 1563.5176,1448.9335 1564.4412,1448.2603 C 1565.3648,1447.58 1565.9825,1446.628 1566.3085,1445.4127 C 1566.5034,1444.6627 1566.5872,1443.1013 1566.5731,1440.7119 C 1564.9762,1442.5934 1562.9825,1443.5383 1560.5943,1443.5383 C 1557.6215,1443.5383 1555.3231,1442.4694 1553.6979,1440.3233 C 1552.0738,1438.1843 1551.2542,1435.6083 1551.2542,1432.6154 C 1551.2542,1430.552 1551.6286,1428.6493 1552.3715,1426.9072 C 1553.1215,1425.1639 1554.2057,1423.8162 1555.6219,1422.8654 C 1557.038,1421.9206 1558.7045,1421.441 1560.6144,1421.441 C 1563.1632,1421.441 1565.2679,1422.4757 1566.9203,1424.5391 L 1566.9203,1421.9347 L 1570.3018,1421.9347 L 1570.3018,1440.6079 C 1570.3018,1443.9693 1569.9546,1446.3575 1569.2742,1447.7607 C 1568.5868,1449.1627 1567.5038,1450.2741 1566.0179,1451.0867 C 1564.5309,1451.8993 1562.7049,1452.3091 1560.5317,1452.3091 C 1557.9545,1452.3091 1555.8723,1451.7256 1554.2884,1450.5658 C 1552.6986,1449.406 1551.9345,1447.6626 1551.99,1445.33 L 1551.99,1445.33 z M 1555.0172,1432.3509 C 1555.0172,1435.1844 1555.5806,1437.2537 1556.7121,1438.5529 C 1557.8376,1439.858 1559.2467,1440.5041 1560.9416,1440.5041 C 1562.6211,1440.5041 1564.0313,1439.858 1565.1699,1438.5659 C 1566.3085,1437.2678 1566.879,1435.2399 1566.879,1432.469 C 1566.879,1429.8233 1566.2955,1427.8308 1565.1215,1426.4903 C 1563.9475,1425.1497 1562.5314,1424.4765 1560.879,1424.4765 C 1559.2538,1424.4765 1557.8719,1425.1355 1556.7262,1426.4619 C 1555.5877,1427.7812 1555.0172,1429.7466 1555.0172,1432.3509 L 1555.0172,1432.3509 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path163" />
-
- <path
- d="M 1576.78,1443.54 L 1576.78,1439.366 L 1580.9528,1439.366 L 1580.9528,1443.54 C 1580.9528,1445.0742 1580.6824,1446.3109 1580.1402,1447.2558 C 1579.5922,1448.1924 1578.7312,1448.9223 1577.5572,1449.4432 L 1576.5367,1447.8735 C 1577.308,1447.5333 1577.8772,1447.0325 1578.2446,1446.3806 C 1578.6131,1445.7203 1578.8139,1444.7766 1578.8564,1443.54 L 1576.78,1443.54 L 1576.78,1443.54 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path165" />
-
- <path
- d="M 669.775,1440.26 L 670.30177,1443.4962 C 669.27421,1443.7112 668.35059,1443.8222 667.53799,1443.8222 C 666.20571,1443.8222 665.17697,1443.6143 664.44114,1443.1903 C 663.7124,1442.7734 663.19862,1442.2183 662.8998,1441.5309 C 662.60098,1440.8505 662.44862,1439.4061 662.44862,1437.2116 L 662.44862,1424.7805 L 659.76043,1424.7805 L 659.76043,1421.934 L 662.44862,1421.934 L 662.44862,1416.5801 L 666.0935,1414.3856 L 666.0935,1421.934 L 669.775,1421.934 L 669.775,1424.7805 L 666.0935,1424.7805 L 666.0935,1437.4124 C 666.0935,1438.4612 666.1561,1439.1285 666.2813,1439.4262 C 666.41358,1439.725 666.62145,1439.9612 666.91319,1440.1419 C 667.20492,1440.3155 667.62185,1440.4053 668.16398,1440.4053 C 668.57264,1440.4053 669.10768,1440.3569 669.775,1440.26 L 669.775,1440.26 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path167" />
-
- <path
- d="M 673.357,1443.54 L 673.357,1413.7148 L 677.01724,1413.7148 L 677.01724,1424.4156 C 678.72511,1422.4361 680.88535,1421.4428 683.4885,1421.4428 C 685.08653,1421.4428 686.47551,1421.7628 687.65543,1422.3947 C 688.83653,1423.0195 689.68338,1423.8947 690.19008,1425.0062 C 690.69677,1426.1164 690.95425,1427.7345 690.95425,1429.8463 L 690.95425,1443.54 L 687.28811,1443.54 L 687.28811,1429.8463 C 687.28811,1428.0191 686.89126,1426.6857 686.09992,1425.853 C 685.30858,1425.0192 684.18299,1424.5963 682.7326,1424.5963 C 681.64835,1424.5963 680.62788,1424.881 679.67,1425.4432 C 678.71095,1426.0054 678.03063,1426.7695 677.62787,1427.7345 C 677.21803,1428.6936 677.01724,1430.0258 677.01724,1431.7207 L 677.01724,1443.54 L 673.357,1443.54 L 673.357,1443.54 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path169" />
-
- <path
- d="M 711.315,1436.58 L 715.09925,1437.0454 C 714.50161,1439.2599 713.39846,1440.9749 711.78744,1442.1973 C 710.16933,1443.4127 708.10594,1444.0245 705.59964,1444.0245 C 702.44019,1444.0245 699.93271,1443.0513 698.08547,1441.1072 C 696.23114,1439.1631 695.30752,1436.4336 695.30752,1432.9198 C 695.30752,1429.2808 696.24532,1426.4615 698.11382,1424.4548 C 699.98823,1422.4481 702.41185,1421.4406 705.39768,1421.4406 C 708.28666,1421.4406 710.64768,1422.4269 712.47485,1424.3922 C 714.30792,1426.3576 715.22446,1429.1284 715.22446,1432.6906 C 715.22446,1432.9127 715.21737,1433.2399 715.2032,1433.6698 L 699.093,1433.6698 C 699.22528,1436.045 699.89851,1437.8639 701.10678,1439.1217 C 702.31505,1440.3855 703.81505,1441.0174 705.62095,1441.0174 C 706.96032,1441.0174 708.10599,1440.6631 709.05796,1439.9544 C 710.00875,1439.2529 710.75875,1438.1284 711.31505,1436.58 L 711.315,1436.58 z M 699.2937,1430.6568 L 711.3563,1430.6568 C 711.19685,1428.8438 710.7315,1427.4761 709.97441,1426.5725 C 708.80748,1425.1635 707.29449,1424.4548 705.44016,1424.4548 C 703.75945,1424.4548 702.34213,1425.017 701.19646,1426.1426 C 700.05079,1427.267 699.4189,1428.7741 699.2937,1430.6568 L 699.2937,1430.6568 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path171" />
-
- <path
- d="M 735.266,1443.54 L 728.65537,1421.9365 L 732.43962,1421.9365 L 735.87781,1434.4078 L 737.15458,1439.0472 C 737.21009,1438.811 737.58568,1437.3251 738.27308,1434.5885 L 741.71009,1421.9365 L 745.47426,1421.9365 L 748.71048,1434.4633 L 749.79355,1438.596 L 751.03016,1434.422 L 754.73055,1421.9366 L 758.29394,1421.9366 L 751.53685,1443.5401 L 747.73842,1443.5401 L 744.30023,1430.6023 L 743.46047,1426.9149 L 739.09275,1443.5401 L 735.26598,1443.5401 L 735.266,1443.54 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path173" />
-
- <path
- d="M 776.154,1436.58 L 779.93825,1437.0454 C 779.34061,1439.2599 778.23746,1440.9749 776.62644,1442.1973 C 775.00833,1443.4127 772.94494,1444.0245 770.43864,1444.0245 C 767.27919,1444.0245 764.77171,1443.0513 762.92447,1441.1072 C 761.07014,1439.1631 760.14652,1436.4336 760.14652,1432.9198 C 760.14652,1429.2808 761.08431,1426.4615 762.95282,1424.4548 C 764.82723,1422.4481 767.25085,1421.4406 770.23668,1421.4406 C 773.12566,1421.4406 775.48668,1422.4269 777.31385,1424.3922 C 779.14692,1426.3576 780.06346,1429.1284 780.06346,1432.6906 C 780.06346,1432.9127 780.05637,1433.2399 780.0422,1433.6698 L 763.932,1433.6698 C 764.06428,1436.045 764.73751,1437.8639 765.94578,1439.1217 C 767.15405,1440.3855 768.65405,1441.0174 770.45995,1441.0174 C 771.79932,1441.0174 772.94499,1440.6631 773.89696,1439.9544 C 774.84775,1439.2529 775.59775,1438.1284 776.15405,1436.58 L 776.154,1436.58 z M 764.1327,1430.6568 L 776.1953,1430.6568 C 776.03585,1428.8438 775.5705,1427.4761 774.81341,1426.5725 C 773.64648,1425.1635 772.13349,1424.4548 770.27916,1424.4548 C 768.59845,1424.4548 767.18113,1425.017 766.03546,1426.1426 C 764.88979,1427.267 764.2579,1428.7741 764.1327,1430.6568 L 764.1327,1430.6568 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path175" />
-
- <path
- d="M 787.918,1443.54 L 784.52233,1443.54 L 784.52233,1413.7148 L 788.18139,1413.7148 L 788.18139,1424.353 C 789.72982,1422.416 791.70226,1421.4428 794.09753,1421.4428 C 795.43099,1421.4428 796.68887,1421.7144 797.87588,1422.2483 C 799.06289,1422.7833 800.03494,1423.5404 800.80619,1424.5054 C 801.57036,1425.4774 802.17391,1426.6443 802.60501,1428.0191 C 803.04202,1429.388 803.25816,1430.8526 803.25816,1432.4081 C 803.25816,1436.1168 802.34044,1438.9774 800.50737,1440.9983 C 798.68139,1443.0192 796.47981,1444.0266 793.918,1444.0266 C 791.36918,1444.0266 789.36957,1442.9636 787.918,1440.8318 L 787.918,1443.54 L 787.918,1443.54 z M 787.87548,1432.5746 C 787.87548,1435.1648 788.22981,1437.0333 788.93139,1438.186 C 790.08415,1440.0746 791.64674,1441.0195 793.6121,1441.0195 C 795.21604,1441.0195 796.59793,1440.325 797.76486,1438.9289 C 798.93179,1437.54 799.51407,1435.4707 799.51407,1432.714 C 799.51407,1429.8947 798.95187,1427.8112 797.83454,1426.4707 C 796.71604,1425.1301 795.36249,1424.4569 793.77863,1424.4569 C 792.17469,1424.4569 790.7928,1425.1514 789.62587,1426.5403 C 788.45894,1427.9293 787.87548,1429.9431 787.87548,1432.5746 L 787.87548,1432.5746 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path177" />
-
- <path
- d="M 817.827,1437.09 L 821.44472,1436.5207 C 821.64551,1437.9723 822.21598,1439.0825 823.14551,1439.8609 C 824.06913,1440.6309 825.36834,1441.0207 827.04197,1441.0207 C 828.72268,1441.0207 829.97228,1440.6735 830.78488,1439.9931 C 831.59748,1439.3057 832.00732,1438.4991 832.00732,1437.5825 C 832.00732,1436.7498 831.6459,1436.1038 830.92307,1435.6242 C 830.42346,1435.2983 829.17386,1434.8884 827.18016,1434.3888 C 824.50024,1433.7085 822.63173,1433.125 821.59709,1432.6242 C 820.56244,1432.1317 819.77111,1431.4443 819.23607,1430.5691 C 818.70221,1429.6939 818.43056,1428.729 818.43056,1427.6731 C 818.43056,1426.7081 818.6526,1425.8199 819.09788,1425.0002 C 819.53489,1424.1735 820.13961,1423.4931 820.89552,1422.951 C 821.46599,1422.5353 822.24316,1422.1739 823.22229,1421.8821 C 824.20851,1421.5904 825.26442,1421.4439 826.38883,1421.4439 C 828.08371,1421.4439 829.56954,1421.6943 830.85458,1422.1809 C 832.13844,1422.6664 833.08332,1423.3266 833.69395,1424.1593 C 834.30576,1425.0002 834.72269,1426.1105 834.95182,1427.5065 L 831.37544,1428.0002 C 831.20891,1426.8888 830.73647,1426.0207 829.95812,1425.3959 C 829.18096,1424.7711 828.07662,1424.4581 826.6534,1424.4581 C 824.97269,1424.4581 823.77151,1424.7357 823.05576,1425.292 C 822.33411,1425.8471 821.97269,1426.5002 821.97269,1427.2432 C 821.97269,1427.7215 822.12505,1428.1455 822.42387,1428.5282 C 822.72269,1428.9239 823.18805,1429.2428 823.82702,1429.5073 C 824.19435,1429.6384 825.27151,1429.9514 827.06206,1430.4369 C 829.65222,1431.1313 831.45812,1431.6947 832.4786,1432.1388 C 833.50734,1432.5758 834.31285,1433.2219 834.89632,1434.0617 C 835.47861,1434.9026 835.77034,1435.9443 835.77034,1437.1939 C 835.77034,1438.4164 835.4101,1439.562 834.70144,1440.6451 C 833.98569,1441.7223 832.95813,1442.555 831.61758,1443.1455 C 830.27821,1443.7361 828.75695,1444.0278 827.06207,1444.0278 C 824.24987,1444.0278 822.11089,1443.4443 820.63924,1442.2774 C 819.16641,1441.1105 818.22979,1439.3813 817.82704,1437.09 L 817.827,1437.09 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path179" />
-
- <path
- d="M 840.138,1417.93 L 840.138,1413.7158 L 843.80414,1413.7158 L 843.80414,1417.93 L 840.138,1417.93 z M 840.138,1443.541 L 840.138,1421.9375 L 843.80414,1421.9375 L 843.80414,1443.541 L 840.138,1443.541 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path181" />
-
- <path
- d="M 857.374,1440.26 L 857.90077,1443.4962 C 856.87321,1443.7112 855.94959,1443.8222 855.13699,1443.8222 C 853.80471,1443.8222 852.77597,1443.6143 852.04014,1443.1903 C 851.3114,1442.7734 850.79762,1442.2183 850.4988,1441.5309 C 850.19998,1440.8505 850.04762,1439.4061 850.04762,1437.2116 L 850.04762,1424.7805 L 847.35943,1424.7805 L 847.35943,1421.934 L 850.04762,1421.934 L 850.04762,1416.5801 L 853.6925,1414.3856 L 853.6925,1421.934 L 857.374,1421.934 L 857.374,1424.7805 L 853.6925,1424.7805 L 853.6925,1437.4124 C 853.6925,1438.4612 853.7551,1439.1285 853.8803,1439.4262 C 854.01258,1439.725 854.22045,1439.9612 854.51219,1440.1419 C 854.80392,1440.3155 855.22085,1440.4053 855.76298,1440.4053 C 856.17164,1440.4053 856.70668,1440.3569 857.374,1440.26 L 857.374,1440.26 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path183" />
-
- <path
- d="M 875.741,1436.58 L 879.52525,1437.0454 C 878.92761,1439.2599 877.82446,1440.9749 876.21344,1442.1973 C 874.59533,1443.4127 872.53194,1444.0245 870.02564,1444.0245 C 866.86619,1444.0245 864.35871,1443.0513 862.51147,1441.1072 C 860.65714,1439.1631 859.73352,1436.4336 859.73352,1432.9198 C 859.73352,1429.2808 860.67131,1426.4615 862.53982,1424.4548 C 864.41423,1422.4481 866.83785,1421.4406 869.82368,1421.4406 C 872.71266,1421.4406 875.07368,1422.4269 876.90085,1424.3922 C 878.73392,1426.3576 879.65046,1429.1284 879.65046,1432.6906 C 879.65046,1432.9127 879.64337,1433.2399 879.6292,1433.6698 L 863.519,1433.6698 C 863.65128,1436.045 864.32451,1437.8639 865.53278,1439.1217 C 866.74105,1440.3855 868.24105,1441.0174 870.04695,1441.0174 C 871.38632,1441.0174 872.53199,1440.6631 873.48396,1439.9544 C 874.43475,1439.2529 875.18475,1438.1284 875.74105,1436.58 L 875.741,1436.58 z M 863.7197,1430.6568 L 875.7823,1430.6568 C 875.62285,1428.8438 875.1575,1427.4761 874.40041,1426.5725 C 873.23348,1425.1635 871.72049,1424.4548 869.86616,1424.4548 C 868.18545,1424.4548 866.76813,1425.017 865.62246,1426.1426 C 864.47679,1427.267 863.8449,1428.7741 863.7197,1430.6568 L 863.7197,1430.6568 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path185" />
-
- <path
- d="M 899.692,1443.54 L 893.08137,1421.9365 L 896.86562,1421.9365 L 900.30381,1434.4078 L 901.58058,1439.0472 C 901.63609,1438.811 902.01168,1437.3251 902.69908,1434.5885 L 906.13609,1421.9365 L 909.90026,1421.9365 L 913.13648,1434.4633 L 914.21955,1438.596 L 915.45616,1434.422 L 919.15655,1421.9366 L 922.71994,1421.9366 L 915.96285,1443.5401 L 912.16442,1443.5401 L 908.72623,1430.6023 L 907.88647,1426.9149 L 903.51875,1443.5401 L 899.69198,1443.5401 L 899.692,1443.54 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path187" />
-
- <polygon
- points="923.046,1444.05 931.691,1413.21 934.622,1413.21 925.997,1444.05 923.046,1444.05 "
- style="fill:#000000;fill-rule:nonzero"
- id="polygon189" />
-
- <path
- d="M 936.698,1445.33 L 940.2602,1445.858 C 940.40666,1446.9552 940.8224,1447.7536 941.49681,1448.2603 C 942.40626,1448.9335 943.64878,1449.2737 945.21846,1449.2737 C 946.92043,1449.2737 948.22555,1448.9335 949.14917,1448.2603 C 950.07279,1447.58 950.69051,1446.628 951.01649,1445.4127 C 951.21137,1444.6627 951.29523,1443.1013 951.28106,1440.7119 C 949.68421,1442.5934 947.69051,1443.5383 945.30232,1443.5383 C 942.32949,1443.5383 940.03106,1442.4694 938.40586,1440.3233 C 936.78184,1438.1843 935.96216,1435.6083 935.96216,1432.6154 C 935.96216,1430.552 936.33657,1428.6493 937.07948,1426.9072 C 937.82948,1425.1639 938.91373,1423.8162 940.32987,1422.8654 C 941.74601,1421.9206 943.41255,1421.441 945.32239,1421.441 C 947.87121,1421.441 949.97593,1422.4757 951.6283,1424.5391 L 951.6283,1421.9347 L 955.0098,1421.9347 L 955.0098,1440.6079 C 955.0098,1443.9693 954.66255,1446.3575 953.98224,1447.7607 C 953.29483,1449.1627 952.21177,1450.2741 950.72594,1451.0867 C 949.23893,1451.8993 947.41295,1452.3091 945.23972,1452.3091 C 942.66255,1452.3091 940.58027,1451.7256 938.99641,1450.5658 C 937.40665,1449.406 936.64247,1447.6626 936.69798,1445.33 L 936.698,1445.33 z M 939.72517,1432.3509 C 939.72517,1435.1844 940.28856,1437.2537 941.42005,1438.5529 C 942.54564,1439.858 943.9547,1440.5041 945.64958,1440.5041 C 947.32911,1440.5041 948.73934,1439.858 949.87793,1438.5659 C 951.01651,1437.2678 951.58699,1435.2399 951.58699,1432.469 C 951.58699,1429.8233 951.00352,1427.8308 949.82951,1426.4903 C 948.65549,1425.1497 947.23935,1424.4765 945.58699,1424.4765 C 943.96179,1424.4765 942.5799,1425.1355 941.43423,1426.4619 C 940.29565,1427.7812 939.72517,1429.7466 939.72517,1432.3509 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path191" />
-
- <path
- d="M 960.503,1443.54 L 960.503,1421.9365 L 963.79473,1421.9365 L 963.79473,1425.207 C 964.63449,1423.6798 965.41284,1422.6652 966.12741,1422.1798 C 966.83607,1421.6932 967.62032,1421.4428 968.47544,1421.4428 C 969.71087,1421.4428 970.96166,1421.8396 972.23843,1422.6239 L 970.97465,1426.0267 C 970.08646,1425.4916 969.19,1425.2282 968.29473,1425.2282 C 967.48922,1425.2282 966.77347,1425.4715 966.13449,1425.9499 C 965.49551,1426.4365 965.04433,1427.1026 964.77386,1427.9566 C 964.36402,1429.2558 964.16323,1430.679 964.16323,1432.2274 L 964.16323,1443.54 L 960.50299,1443.54 L 960.503,1443.54 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path193" />
-
- </g>
- <g
- transform="matrix(0.317715,0,0,0.317715,415.2513,-451.5858)"
- style="fill-rule:evenodd"
- id="_19509096">
- <path
- d="M 75.3272,2384.22 L 75.853972,2387.4562 C 74.826412,2387.6712 73.902792,2387.7822 73.090192,2387.7822 C 71.757912,2387.7822 70.729172,2387.5743 69.993342,2387.1503 C 69.264602,2386.7334 68.750822,2386.1783 68.452002,2385.4909 C 68.153183,2384.8105 68.000821,2383.3661 68.000821,2381.1716 L 68.000821,2368.7405 L 65.312631,2368.7405 L 65.312631,2365.894 L 68.000821,2365.894 L 68.000821,2360.5401 L 71.645701,2358.3456 L 71.645701,2365.894 L 75.327201,2365.894 L 75.327201,2368.7405 L 71.645701,2368.7405 L 71.645701,2381.3724 C 71.645701,2382.4212 71.708299,2383.0885 71.833496,2383.3862 C 71.965779,2383.685 72.173653,2383.9212 72.465386,2384.1019 C 72.757118,2384.2755 73.174047,2384.3653 73.716176,2384.3653 C 74.124837,2384.3653 74.659877,2384.3169 75.327196,2384.22 L 75.3272,2384.22 z "
- style="fill:#000000;fill-rule:nonzero"
- id="_19509000" />
-
- <path
- d="M 93.6945,2380.54 L 97.47875,2381.0054 C 96.881112,2383.2199 95.77796,2384.9349 94.16694,2386.1573 C 92.54883,2387.3727 90.48544,2387.9845 87.97914,2387.9845 C 84.81969,2387.9845 82.31221,2387.0113 80.46497,2385.0672 C 78.61064,2383.1231 77.68702,2380.3936 77.68702,2376.8798 C 77.68702,2373.2408 78.624815,2370.4215 80.49332,2368.4148 C 82.36773,2366.4081 84.79135,2365.4006 87.77718,2365.4006 C 90.66616,2365.4006 93.02718,2366.3869 94.85435,2368.3522 C 96.68742,2370.3176 97.60396,2373.0884 97.60396,2376.6506 C 97.60396,2376.8727 97.596873,2377.1999 97.5827,2377.6298 L 81.4725,2377.6298 C 81.604783,2380.005 82.278012,2381.8239 83.48628,2383.0817 C 84.69455,2384.3455 86.19455,2384.9774 88.00045,2384.9774 C 89.33982,2384.9774 90.48549,2384.6231 91.43746,2383.9144 C 92.388247,2383.2129 93.13825,2382.0884 93.69455,2380.54 L 93.6945,2380.54 z M 81.6732,2374.6168 L 93.7358,2374.6168 C 93.576351,2372.8038 93.110997,2371.4361 92.35391,2370.5325 C 91.18698,2369.1235 89.67399,2368.4148 87.81966,2368.4148 C 86.13895,2368.4148 84.72163,2368.977 83.57596,2370.1026 C 82.43029,2371.227 81.7984,2372.7341 81.6732,2374.6168 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path197" />
-
- <path
- d="M 99.639,2387.5 L 107.53467,2376.2713 L 100.22837,2365.8965 L 104.80514,2365.8965 L 108.12404,2370.9587 C 108.74294,2371.9237 109.24963,2372.7292 109.62404,2373.3823 C 110.22168,2372.487 110.77089,2371.6945 111.27758,2371 L 114.91656,2365.8965 L 119.29136,2365.8965 L 111.82561,2376.0693 L 119.86065,2387.5 L 115.36774,2387.5 L 110.93034,2380.7854 L 109.74924,2378.9724 L 104.07641,2387.5 L 99.63901,2387.5 L 99.639,2387.5 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path199" />
-
- <path
- d="M 130.909,2384.22 L 131.43577,2387.4562 C 130.40821,2387.6712 129.48459,2387.7822 128.67199,2387.7822 C 127.33971,2387.7822 126.31097,2387.5743 125.57514,2387.1503 C 124.8464,2386.7334 124.33262,2386.1783 124.0338,2385.4909 C 123.73498,2384.8105 123.58262,2383.3661 123.58262,2381.1716 L 123.58262,2368.7405 L 120.89443,2368.7405 L 120.89443,2365.894 L 123.58262,2365.894 L 123.58262,2360.5401 L 127.2275,2358.3456 L 127.2275,2365.894 L 130.909,2365.894 L 130.909,2368.7405 L 127.2275,2368.7405 L 127.2275,2381.3724 C 127.2275,2382.4212 127.2901,2383.0885 127.4153,2383.3862 C 127.54758,2383.685 127.75545,2383.9212 128.04719,2384.1019 C 128.33892,2384.2755 128.75585,2384.3653 129.29798,2384.3653 C 129.70664,2384.3653 130.24168,2384.3169 130.909,2384.22 L 130.909,2384.22 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path201" />
-
- <path
- d="M 146.067,2395.78 L 146.067,2365.8993 L 149.40007,2365.8993 L 149.40007,2368.7044 C 150.1855,2367.6072 151.07369,2366.7816 152.067,2366.2324 C 153.05322,2365.6843 154.2544,2365.4056 155.66464,2365.4056 C 157.51188,2365.4056 159.13708,2365.8851 160.54614,2366.83 C 161.96228,2367.7808 163.02527,2369.1213 163.74102,2370.8505 C 164.46267,2372.5796 164.82409,2374.4753 164.82409,2376.5375 C 164.82409,2378.7461 164.42842,2380.7387 163.63,2382.5103 C 162.83748,2384.2808 161.68472,2385.6343 160.17173,2386.5792 C 158.65756,2387.517 157.06661,2387.9895 155.40008,2387.9895 C 154.17882,2387.9895 153.08748,2387.732 152.11543,2387.2182 C 151.14338,2386.7044 150.35204,2386.0513 149.72724,2385.267 L 149.72724,2395.78 L 146.067,2395.78 L 146.067,2395.78 z M 149.37999,2376.8221 C 149.37999,2379.6001 149.9422,2381.6552 151.06779,2382.9886 C 152.1922,2384.315 153.55992,2384.9823 155.15795,2384.9823 C 156.78197,2384.9823 158.17803,2384.2949 159.33787,2382.9131 C 160.49771,2381.5383 161.08118,2379.4064 161.08118,2376.5174 C 161.08118,2373.7595 160.51189,2371.7044 159.37921,2370.3296 C 158.24771,2368.9619 156.89299,2368.2745 155.32449,2368.2745 C 153.76189,2368.2745 152.38,2369.0032 151.17882,2370.4619 C 149.97646,2371.9193 149.38,2374.0453 149.38,2376.8221 L 149.37999,2376.8221 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path203" />
-
- <path
- d="M 169.199,2387.5 L 169.199,2365.8965 L 172.49073,2365.8965 L 172.49073,2369.167 C 173.33049,2367.6398 174.10884,2366.6252 174.82341,2366.1398 C 175.53207,2365.6532 176.31632,2365.4028 177.17144,2365.4028 C 178.40687,2365.4028 179.65766,2365.7996 180.93443,2366.5839 L 179.67065,2369.9867 C 178.78246,2369.4516 177.886,2369.1882 176.99073,2369.1882 C 176.18522,2369.1882 175.46947,2369.4315 174.83049,2369.9099 C 174.19151,2370.3965 173.74033,2371.0626 173.46986,2371.9166 C 173.06002,2373.2158 172.85923,2374.639 172.85923,2376.1874 L 172.85923,2387.5 L 169.19899,2387.5 L 169.199,2387.5 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path205" />
-
- <path
- d="M 181.747,2376.69 C 181.747,2372.6908 182.85842,2369.725 185.08716,2367.8022 C 186.94149,2366.2042 189.20566,2365.3987 191.8785,2365.3987 C 194.85133,2365.3987 197.28086,2366.3719 199.16354,2368.3231 C 201.05212,2370.2672 201.98992,2372.9542 201.98992,2376.3853 C 201.98992,2379.1691 201.57299,2381.3577 200.73913,2382.9475 C 199.90645,2384.5443 198.6911,2385.7809 197.10133,2386.662 C 195.5033,2387.5443 193.76708,2387.9825 191.8785,2387.9825 C 188.85842,2387.9825 186.41354,2387.0164 184.54504,2385.0723 C 182.67772,2383.1353 181.74701,2380.3431 181.74701,2376.69 L 181.747,2376.69 z M 185.51117,2376.69 C 185.51117,2379.4609 186.11471,2381.5313 187.32298,2382.9061 C 188.53125,2384.288 190.05251,2384.9754 191.87849,2384.9754 C 193.69857,2384.9754 195.21156,2384.2809 196.41983,2382.8991 C 197.62219,2381.5172 198.22574,2379.4054 198.22574,2376.5731 C 198.22574,2373.8991 197.6222,2371.8711 196.40684,2370.4963 C 195.19149,2369.1215 193.6844,2368.4341 191.87849,2368.4341 C 190.05251,2368.4341 188.53125,2369.1215 187.32298,2370.4892 C 186.11471,2371.8569 185.51117,2373.9262 185.51117,2376.69 L 185.51117,2376.69 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path207" />
-
- <path
- d="M 206.288,2395.78 L 206.288,2365.8993 L 209.62107,2365.8993 L 209.62107,2368.7044 C 210.4065,2367.6072 211.29469,2366.7816 212.288,2366.2324 C 213.27422,2365.6843 214.4754,2365.4056 215.88564,2365.4056 C 217.73288,2365.4056 219.35808,2365.8851 220.76714,2366.83 C 222.18328,2367.7808 223.24627,2369.1213 223.96202,2370.8505 C 224.68367,2372.5796 225.04509,2374.4753 225.04509,2376.5375 C 225.04509,2378.7461 224.64942,2380.7387 223.851,2382.5103 C 223.05848,2384.2808 221.90572,2385.6343 220.39273,2386.5792 C 218.87856,2387.517 217.28761,2387.9895 215.62108,2387.9895 C 214.39982,2387.9895 213.30848,2387.732 212.33643,2387.2182 C 211.36438,2386.7044 210.57304,2386.0513 209.94824,2385.267 L 209.94824,2395.78 L 206.288,2395.78 L 206.288,2395.78 z M 209.60099,2376.8221 C 209.60099,2379.6001 210.1632,2381.6552 211.28879,2382.9886 C 212.4132,2384.315 213.78092,2384.9823 215.37895,2384.9823 C 217.00297,2384.9823 218.39903,2384.2949 219.55887,2382.9131 C 220.71871,2381.5383 221.30218,2379.4064 221.30218,2376.5174 C 221.30218,2373.7595 220.73289,2371.7044 219.60021,2370.3296 C 218.46871,2368.9619 217.11399,2368.2745 215.54549,2368.2745 C 213.98289,2368.2745 212.601,2369.0032 211.39982,2370.4619 C 210.19746,2371.9193 209.601,2374.0453 209.601,2376.8221 L 209.60099,2376.8221 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path209" />
-
- <path
- d="M 228.093,2376.69 C 228.093,2372.6908 229.20442,2369.725 231.43316,2367.8022 C 233.28749,2366.2042 235.55166,2365.3987 238.2245,2365.3987 C 241.19733,2365.3987 243.62686,2366.3719 245.50954,2368.3231 C 247.39812,2370.2672 248.33592,2372.9542 248.33592,2376.3853 C 248.33592,2379.1691 247.91899,2381.3577 247.08513,2382.9475 C 246.25245,2384.5443 245.0371,2385.7809 243.44733,2386.662 C 241.8493,2387.5443 240.11308,2387.9825 238.2245,2387.9825 C 235.20442,2387.9825 232.75954,2387.0164 230.89104,2385.0723 C 229.02372,2383.1353 228.09301,2380.3431 228.09301,2376.69 L 228.093,2376.69 z M 231.85717,2376.69 C 231.85717,2379.4609 232.46071,2381.5313 233.66898,2382.9061 C 234.87725,2384.288 236.39851,2384.9754 238.22449,2384.9754 C 240.04457,2384.9754 241.55756,2384.2809 242.76583,2382.8991 C 243.96819,2381.5172 244.57174,2379.4054 244.57174,2376.5731 C 244.57174,2373.8991 243.9682,2371.8711 242.75284,2370.4963 C 241.53749,2369.1215 240.0304,2368.4341 238.22449,2368.4341 C 236.39851,2368.4341 234.87725,2369.1215 233.66898,2370.4892 C 232.46071,2371.8569 231.85717,2373.9262 231.85717,2376.69 L 231.85717,2376.69 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path211" />
-
- <path
- d="M 252.593,2387.5 L 252.593,2365.8965 L 255.88473,2365.8965 L 255.88473,2369.167 C 256.72449,2367.6398 257.50284,2366.6252 258.21741,2366.1398 C 258.92607,2365.6532 259.71032,2365.4028 260.56544,2365.4028 C 261.80087,2365.4028 263.05166,2365.7996 264.32843,2366.5839 L 263.06465,2369.9867 C 262.17646,2369.4516 261.28,2369.1882 260.38473,2369.1882 C 259.57922,2369.1882 258.86347,2369.4315 258.22449,2369.9099 C 257.58551,2370.3965 257.13433,2371.0626 256.86386,2371.9166 C 256.45402,2373.2158 256.25323,2374.639 256.25323,2376.1874 L 256.25323,2387.5 L 252.59299,2387.5 L 252.593,2387.5 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path213" />
-
- <path
- d="M 274.502,2384.22 L 275.02877,2387.4562 C 274.00121,2387.6712 273.07759,2387.7822 272.26499,2387.7822 C 270.93271,2387.7822 269.90397,2387.5743 269.16814,2387.1503 C 268.4394,2386.7334 267.92562,2386.1783 267.6268,2385.4909 C 267.32798,2384.8105 267.17562,2383.3661 267.17562,2381.1716 L 267.17562,2368.7405 L 264.48743,2368.7405 L 264.48743,2365.894 L 267.17562,2365.894 L 267.17562,2360.5401 L 270.8205,2358.3456 L 270.8205,2365.894 L 274.502,2365.894 L 274.502,2368.7405 L 270.8205,2368.7405 L 270.8205,2381.3724 C 270.8205,2382.4212 270.8831,2383.0885 271.0083,2383.3862 C 271.14058,2383.685 271.34845,2383.9212 271.64019,2384.1019 C 271.93192,2384.2755 272.34885,2384.3653 272.89098,2384.3653 C 273.29964,2384.3653 273.83468,2384.3169 274.502,2384.22 L 274.502,2384.22 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path215" />
-
- <path
- d="M 278.099,2361.89 L 278.099,2357.6758 L 281.76514,2357.6758 L 281.76514,2361.89 L 278.099,2361.89 z M 278.099,2387.501 L 278.099,2365.8975 L 281.76514,2365.8975 L 281.76514,2387.501 L 278.099,2387.501 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path217" />
-
- <path
- d="M 285.973,2376.69 C 285.973,2372.6908 287.08442,2369.725 289.31316,2367.8022 C 291.16749,2366.2042 293.43166,2365.3987 296.1045,2365.3987 C 299.07733,2365.3987 301.50686,2366.3719 303.38954,2368.3231 C 305.27812,2370.2672 306.21592,2372.9542 306.21592,2376.3853 C 306.21592,2379.1691 305.79899,2381.3577 304.96513,2382.9475 C 304.13245,2384.5443 302.9171,2385.7809 301.32733,2386.662 C 299.7293,2387.5443 297.99308,2387.9825 296.1045,2387.9825 C 293.08442,2387.9825 290.63954,2387.0164 288.77104,2385.0723 C 286.90372,2383.1353 285.97301,2380.3431 285.97301,2376.69 L 285.973,2376.69 z M 289.73717,2376.69 C 289.73717,2379.4609 290.34071,2381.5313 291.54898,2382.9061 C 292.75725,2384.288 294.27851,2384.9754 296.10449,2384.9754 C 297.92457,2384.9754 299.43756,2384.2809 300.64583,2382.8991 C 301.84819,2381.5172 302.45174,2379.4054 302.45174,2376.5731 C 302.45174,2373.8991 301.8482,2371.8711 300.63284,2370.4963 C 299.41749,2369.1215 297.9104,2368.4341 296.10449,2368.4341 C 294.27851,2368.4341 292.75725,2369.1215 291.54898,2370.4892 C 290.34071,2371.8569 289.73717,2373.9262 289.73717,2376.69 L 289.73717,2376.69 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path219" />
-
- <path
- d="M 310.514,2387.5 L 310.514,2365.8965 L 313.80573,2365.8965 L 313.80573,2368.9662 C 315.39667,2366.591 317.68801,2365.4028 320.68093,2365.4028 C 321.98605,2365.4028 323.18014,2365.639 324.27148,2366.1044 C 325.36872,2366.5768 326.18014,2367.1874 326.72227,2367.9516 C 327.27148,2368.7087 327.64589,2369.6111 327.86794,2370.6528 C 328.00022,2371.3343 328.06991,2372.5213 328.06991,2374.2162 L 328.06991,2387.5001 L 324.40259,2387.5001 L 324.40259,2374.3544 C 324.40259,2372.8686 324.2644,2371.7501 323.97975,2371.0071 C 323.69511,2370.2713 323.18723,2369.6808 322.46558,2369.2438 C 321.73684,2368.7997 320.88881,2368.5764 319.90967,2368.5764 C 318.34707,2368.5764 317.0077,2369.0772 315.86794,2370.0634 C 314.73644,2371.0556 314.17424,2372.9312 314.17424,2375.702 L 314.17424,2387.5 L 310.514,2387.5 L 310.514,2387.5 z "
- style="fill:#000000;fill-rule:nonzero"
- id="path221" />
-
- </g>
- <path
- d="M 88.126188,369.03622 C 88.126188,356.61906 103.01889,346.69059 127.84056,346.69059 C 152.66211,346.69059 167.55494,356.61906 167.55494,369.02307 L 167.55494,406.26181 C 167.55494,417.22297 158.65917,426.11874 147.698,426.11874 L 107.98331,426.11874 C 94.282043,426.11874 83.162145,437.23902 83.162145,450.94029 L 83.162145,468.32206 L 68.269064,468.30894 C 55.851904,468.30894 45.923056,453.41586 45.923056,428.59425 C 45.923056,403.7727 55.851904,388.87987 68.269064,388.87987 L 127.84063,388.893 L 127.84063,383.92876 L 88.126252,383.92876 L 88.126252,369.03606 L 88.126188,369.03622 z M 105.49443,359.10775 C 109.61173,359.10775 112.94774,362.44376 112.94774,366.54753 C 112.94774,370.66483 109.61173,374.00045 105.49443,374.00045 C 101.39066,374.00045 98.041501,370.66483 98.041501,366.54753 C 98.041501,362.44376 101.39063,359.10775 105.49443,359.10775 z "
- style="fill:url(#pyBlue);fill-opacity:1;fill-rule:evenodd"
- id="path223" />
- <g
- transform="matrix(0.317715,0,0,0.317715,-71.39343,-151.2348)"
- style="fill-rule:evenodd"
- id="_19487936">
- <g
- id="g226">
- <path
- d="M 1200.75,1694 C 1269.1252,1692.8331 1300.1244,1757.1665 1300.7079,1830.124 C 1300.7079,1894.4575 1268.5418,1954.749 1199.6259,1957.041 C 1171.459,1957.041 1147.3338,1948.4166 1123.792,1934.0827 L 1123.792,2082.8327 L 1082.418,2067.874 L 1083.0003,1737.625 C 1082.418,1737.625 1115.1676,1694.5833 1200.1683,1693.4163 L 1200.7506,1693.9998 L 1200.75,1694 z M 1190.4177,1927.166 C 1245.5421,1923.7491 1252.4586,1869.7503 1252.4586,1827.2495 C 1252.4586,1785.8743 1245.5421,1723.8745 1193.2925,1721.5835 C 1157.6669,1719.2496 1128.959,1735.9162 1123.2094,1741.667 L 1123.2094,1905.375 C 1137,1913.9581 1164.5834,1928.9167 1190.4177,1927.1663 L 1190.4177,1927.166 z "
- style="fill:#6a6a6a"
- id="_19487984" />
-
- <path
- d="M 1387.87,1869.75 L 1387.87,1693.416 L 1345.3704,1707.7912 L 1345.3704,1882.3742 C 1345.3704,1928.9155 1388.4535,1955.9155 1426.3704,1955.9155 C 1475.7452,1955.9155 1503.9121,1942.1238 1516.5369,1936.3742 C 1517.1204,1942.6659 1516.5369,1940.9569 1516.5369,1947.2899 C 1516.5369,1965.6655 1515.9534,1997.2493 1507.3704,2013.3324 C 1490.1204,2046.082 1444.1613,2050.6659 1411.9952,2055.2485 L 1418.9117,2081.665 C 1461.4113,2080.5406 1521.1197,2064.4575 1542.3697,2024.2481 C 1554.4536,2001.2485 1556.1614,1957.0398 1556.1614,1927.7485 L 1556.1614,1699.7485 L 1514.2453,1699.7485 L 1514.2453,1904.7905 C 1500.4536,1913.957 1475.2028,1926.6244 1452.7866,1927.1653 C 1415.4531,1927.7488 1387.8697,1907.6653 1387.8697,1869.1661 L 1387.8697,1869.7496 L 1387.87,1869.75 z "
- style="fill:#6a6a6a"
- id="_19488200" />
-
- <path
- d="M 1626.62,1726.75 L 1626.62,1891.583 C 1626.62,1934.6661 1659.9117,1959.9169 1715.6196,1954.7495 L 1715.6196,1932.9168 C 1686.3283,1931.7912 1668.5361,1923.7491 1668.5361,1890.416 L 1668.5361,1726.749 L 1715.6196,1726.749 L 1715.6196,1699.749 L 1668.5361,1699.749 L 1668.5361,1614.7498 L 1626.62,1629.6671 L 1626.62,1699.749 L 1597.8696,1699.749 L 1597.8696,1726.749 L 1626.62,1726.749 L 1626.62,1726.75 z "
- style="fill:#6a6a6a"
- id="_19488488" />
-
- <path
- d="M 1970.21,1951.29 L 1970.21,1776.123 C 1970.21,1732.4565 1940.3352,1697.999 1895.5431,1697.999 C 1861.6266,1697.999 1832.9187,1708.9147 1807.6691,1727.2903 L 1807.6691,1550.9993 L 1765.7104,1564.2087 L 1765.7104,1951.2897 L 1807.6691,1951.2897 L 1807.6691,1757.1647 C 1828.9183,1742.2474 1853.0435,1726.7478 1879.46,1726.7478 C 1913.3352,1726.7478 1927.7104,1760.0395 1927.7104,1789.3309 L 1927.7104,1951.2899 L 1970.21,1951.2899 L 1970.21,1951.29 z "
- style="fill:#6a6a6a"
- id="_126749024" />
-
- <path
- d="M 2007.75,1820.92 C 2007.75,1890.4196 2044.5,1955.92 2122.041,1956.462 C 2200.1662,1955.9199 2238.042,1890.4195 2238.042,1820.92 C 2237.4999,1753.1696 2195.0003,1694.003 2122.625,1693.42 C 2050.8341,1694.0035 2007.751,1753.1696 2007.751,1820.92 L 2007.75,1820.92 z M 2053.1244,1820.92 C 2053.1244,1775.5444 2064.5823,1725.5861 2122.0405,1722.1279 C 2176.0405,1725.0039 2192.1248,1775.5444 2192.1248,1820.92 C 2192.1248,1869.1704 2181.75,1928.92 2123.1661,1930.628 C 2069.2074,1930.0445 2053.7078,1869.1705 2053.7078,1820.92 L 2053.1243,1820.92 L 2053.1244,1820.92 z "
- style="fill:#6a6a6a"
- id="_126677456" />
-
- <path
- d="M 2477.04,1951.29 L 2477.04,1758.873 C 2477.04,1724.999 2450.0813,1703.1651 2419.6231,1696.2899 C 2389.7483,1689.4147 2361.6239,1695.1655 2340.957,1700.8738 C 2314.4991,1707.7903 2295.5814,1719.8317 2274.3322,1735.3313 L 2274.3322,1951.2903 L 2316.2483,1951.2903 L 2316.2483,1740.4993 C 2329.4566,1731.3327 2350.707,1721.5828 2373.0818,1720.9993 C 2409.8731,1720.4158 2435.1239,1741.6662 2435.1239,1780.1654 L 2435.1239,1951.2904 L 2477.04,1951.2904 L 2477.04,1951.29 z "
- style="fill:#6a6a6a"
- id="_126678176" />
-
- </g>
-
- </g>
- <path
- d="M 167.55462,488.16664 C 167.55462,500.58418 152.66192,510.51265 127.84025,510.51265 C 103.0187,510.51265 88.12587,500.58418 88.12587,488.17979 L 88.12587,450.94105 C 88.12587,439.97988 97.021636,431.08374 107.9828,431.08374 L 147.6975,431.08374 C 161.39877,431.08374 172.51904,419.96384 172.51904,406.26257 L 172.51904,388.8808 L 187.41174,388.89392 C 199.81575,388.89392 209.7446,403.787 209.7446,428.60829 C 209.7446,453.42984 199.81575,468.32298 187.41174,468.32298 L 127.84018,468.30986 L 127.84018,473.2741 L 167.55456,473.2741 L 167.55456,488.1668 L 167.55462,488.16664 z M 150.17323,498.0951 C 146.06946,498.0951 142.73345,494.75948 142.73345,490.65533 C 142.73345,486.53841 146.06946,483.2024 150.17323,483.2024 C 154.29015,483.2024 157.62615,486.53841 157.62615,490.65533 C 157.62615,494.75948 154.29015,498.0951 150.17323,498.0951 z "
- style="fill:url(#pyYellow);fill-opacity:1;fill-rule:evenodd"
- id="path234" />
- </g>
-</svg>
if (result >= BUFSIZE) {
/* Large environment variable. Accept some leakage */
wchar_t *buf2 = (wchar_t*)malloc(sizeof(wchar_t) * (result+1));
- if (buf2 = NULL) {
+ if (buf2 == NULL) {
error(RC_NO_MEMORY, L"Could not allocate environment buffer");
}
GetEnvironmentVariableW(key, buf2, result);
L"\\",
L"\\PCBuild\\win32\\",
L"\\PCBuild\\amd64\\",
+ // To support early 32bit versions of Python that stuck the build binaries
+ // directly in PCBuild...
+ L"\\PCBuild\\",
NULL
};
*/
static BOM BOMs[] = {
{ 3, { 0xEF, 0xBB, 0xBF }, CP_UTF8 }, /* UTF-8 - keep first */
- { 2, { 0xFF, 0xFE }, CP_UTF16LE }, /* UTF-16LE */
- { 2, { 0xFE, 0xFF }, CP_UTF16BE }, /* UTF-16BE */
+ /* Test UTF-32LE before UTF-16LE since UTF-16LE BOM is a prefix
+ * of UTF-32LE BOM. */
{ 4, { 0xFF, 0xFE, 0x00, 0x00 }, CP_UTF32LE }, /* UTF-32LE */
{ 4, { 0x00, 0x00, 0xFE, 0xFF }, CP_UTF32BE }, /* UTF-32BE */
+ { 2, { 0xFF, 0xFE }, CP_UTF16LE }, /* UTF-16LE */
+ { 2, { 0xFE, 0xFF }, CP_UTF16BE }, /* UTF-16BE */
{ 0 } /* sentinel */
};
} PYC_MAGIC;
static PYC_MAGIC magic_values[] = {
- { 0xc687, 0xc687, L"2.0" },
- { 0xeb2a, 0xeb2a, L"2.1" },
- { 0xed2d, 0xed2d, L"2.2" },
- { 0xf23b, 0xf245, L"2.3" },
- { 0xf259, 0xf26d, L"2.4" },
- { 0xf277, 0xf2b3, L"2.5" },
- { 0xf2c7, 0xf2d1, L"2.6" },
- { 0xf2db, 0xf303, L"2.7" },
- { 0x0bb8, 0x0c3b, L"3.0" },
- { 0x0c45, 0x0c4f, L"3.1" },
- { 0x0c58, 0x0c6c, L"3.2" },
- { 0x0c76, 0x0c76, L"3.3" },
+ { 50823, 50823, L"2.0" },
+ { 60202, 60202, L"2.1" },
+ { 60717, 60717, L"2.2" },
+ { 62011, 62021, L"2.3" },
+ { 62041, 62061, L"2.4" },
+ { 62071, 62131, L"2.5" },
+ { 62151, 62161, L"2.6" },
+ { 62171, 62211, L"2.7" },
+ { 3000, 3131, L"3.0" },
+ { 3141, 3151, L"3.1" },
+ { 3160, 3180, L"3.2" },
+ { 3190, 3230, L"3.3" },
+ { 3250, 3310, L"3.4" },
+ { 3320, 3350, L"3.5" },
+ { 3360, 3361, L"3.6" },
{ 0 }
};
* is no version specification.
*/
debug(L"searching PATH for python executable\n");
- cmd = find_on_path(L"python");
+ cmd = find_on_path(PYTHON_EXECUTABLE);
debug(L"Python on path: %ls\n", cmd ? cmd->value : L"<not found>");
if (cmd) {
debug(L"located python on PATH: %ls\n", cmd->value);
# define SIZEOF_FPOS_T 8
# define SIZEOF_HKEY 4
# define SIZEOF_SIZE_T 4
- /* MS VS2005 changes time_t to an 64-bit type on all platforms */
+ /* MS VS2005 changes time_t to a 64-bit type on all platforms */
# if defined(_MSC_VER) && _MSC_VER >= 1400
# define SIZEOF_TIME_T 8
# else
#include "winver.h"
#define PYTHON_COMPANY "Python Software Foundation"
-#define PYTHON_COPYRIGHT "Copyright \xA9 2001-2015 Python Software Foundation. Copyright \xA9 2000 BeOpen.com. Copyright \xA9 1995-2001 CNRI. Copyright \xA9 1991-1995 SMC."
+#define PYTHON_COPYRIGHT "Copyright \xA9 2001-2016 Python Software Foundation. Copyright \xA9 2000 BeOpen.com. Copyright \xA9 1995-2001 CNRI. Copyright \xA9 1991-1995 SMC."
#define MS_WINDOWS
#include "modsupport.h"
#include "patchlevel.h"
+#include <pythonnt_rc.h>
#ifdef _DEBUG
-# include "pythonnt_rc_d.h"
# define PYTHON_DEBUG_EXT "_d"
#else
-# include "pythonnt_rc.h"
# define PYTHON_DEBUG_EXT
#endif
--- /dev/null
+// Resource script for Sqlite DLL.
+
+#include <winver.h>
+
+// Include the manifest file that indicates we support all
+// current versions of Windows.
+#include <winuser.h>
+2 RT_MANIFEST "python.manifest"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+#define _S(x) #x
+#define S(x) _S(x)
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION SQLITE_MAJOR_VERSION, SQLITE_MINOR_VERSION, SQLITE_MICRO_VERSION, SQLITE_PATCH_VERSION
+ PRODUCTVERSION SQLITE_MAJOR_VERSION, SQLITE_MINOR_VERSION, SQLITE_MICRO_VERSION, SQLITE_PATCH_VERSION
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS VS_FF_DEBUG
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS VOS__WINDOWS32
+ FILETYPE VFT_DLL
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "000004b0"
+ BEGIN
+ VALUE "CompanyName", "SQLite3\0"
+ VALUE "FileDescription", "SQLite3\0"
+ VALUE "FileVersion", S(SQLITE_VERSION) "\0"
+ VALUE "InternalName", "SQLite3 DLL\0"
+ VALUE "LegalCopyright", "Unspecified\0"
+ VALUE "OriginalFilename", "sqlite3.dll\0"
+ VALUE "ProductName", "SQLite3\0"
+ VALUE "ProductVersion", S(SQLITE_VERSION) "\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x0, 1200
+ END
+END
--- /dev/null
+'''
+This script gets the version number from ucrtbased.dll and checks
+whether it is a version with a known issue.
+'''
+
+import sys
+
+from ctypes import (c_buffer, POINTER, byref, create_unicode_buffer,
+ Structure, WinDLL)
+from ctypes.wintypes import DWORD, HANDLE
+
+class VS_FIXEDFILEINFO(Structure):
+ _fields_ = [
+ ("dwSignature", DWORD),
+ ("dwStrucVersion", DWORD),
+ ("dwFileVersionMS", DWORD),
+ ("dwFileVersionLS", DWORD),
+ ("dwProductVersionMS", DWORD),
+ ("dwProductVersionLS", DWORD),
+ ("dwFileFlagsMask", DWORD),
+ ("dwFileFlags", DWORD),
+ ("dwFileOS", DWORD),
+ ("dwFileType", DWORD),
+ ("dwFileSubtype", DWORD),
+ ("dwFileDateMS", DWORD),
+ ("dwFileDateLS", DWORD),
+ ]
+
+kernel32 = WinDLL('kernel32')
+version = WinDLL('version')
+
+if len(sys.argv) < 2:
+ print('Usage: validate_ucrtbase.py <ucrtbase|ucrtbased>')
+ sys.exit(2)
+
+try:
+ ucrtbased = WinDLL(sys.argv[1])
+except OSError:
+ print('Cannot find ucrtbased.dll')
+ # This likely means that VS is not installed, but that is an
+ # obvious enough problem if you're trying to produce a debug
+ # build that we don't need to fail here.
+ sys.exit(0)
+
+# We will immediately double the length up to MAX_PATH, but the
+# path may be longer, so we retry until the returned string is
+# shorter than our buffer.
+name_len = actual_len = 130
+while actual_len == name_len:
+ name_len *= 2
+ name = create_unicode_buffer(name_len)
+ actual_len = kernel32.GetModuleFileNameW(HANDLE(ucrtbased._handle),
+ name, len(name))
+ if not actual_len:
+ print('Failed to get full module name.')
+ sys.exit(2)
+
+size = version.GetFileVersionInfoSizeW(name, None)
+if not size:
+ print('Failed to get size of version info.')
+ sys.exit(2)
+
+ver_block = c_buffer(size)
+if (not version.GetFileVersionInfoW(name, None, size, ver_block) or
+ not ver_block):
+ print('Failed to get version info.')
+ sys.exit(2)
+
+pvi = POINTER(VS_FIXEDFILEINFO)()
+if not version.VerQueryValueW(ver_block, "", byref(pvi), byref(DWORD())):
+ print('Failed to get version value from info.')
+ sys.exit(2)
+
+ver = (
+ pvi.contents.dwProductVersionMS >> 16,
+ pvi.contents.dwProductVersionMS & 0xFFFF,
+ pvi.contents.dwProductVersionLS >> 16,
+ pvi.contents.dwProductVersionLS & 0xFFFF,
+)
+
+print('{} is version {}.{}.{}.{}'.format(name.value, *ver))
+
+if ver < (10, 0, 10586):
+ print('WARN: ucrtbased contains known issues. '
+ 'Please update Visual Studio or the Windows SDK.')
+ print('See:')
+ print(' http://bugs.python.org/issue26624')
+ sys.exit(1)
The predefined key to connect to.
/
-Establishes a connection to the registry on on another computer.
+Establishes a connection to the registry on another computer.
The return value is the handle of the opened key.
If the function fails, an OSError exception is raised.
static HKEY
winreg_ConnectRegistry_impl(PyModuleDef *module, Py_UNICODE *computer_name,
HKEY key)
-/*[clinic end generated code: output=5c52f6f7ba6e7b46 input=9a056558ce318433]*/
+/*[clinic end generated code: output=5c52f6f7ba6e7b46 input=5f98a891a347e68e]*/
{
HKEY retKey;
long rc;
references to environment variables (for example,
%PATH%).
REG_LINK -- A Unicode symbolic link.
- REG_MULTI_SZ -- An sequence of null-terminated strings, terminated
+ REG_MULTI_SZ -- A sequence of null-terminated strings, terminated
by two null characters. Note that Python handles
this termination automatically.
REG_NONE -- No defined value type.
static PyObject *
winreg_SetValueEx_impl(PyModuleDef *module, HKEY key, Py_UNICODE *value_name,
PyObject *reserved, DWORD type, PyObject *value)
-/*[clinic end generated code: output=ea092a935c361582 input=e73dec535ebeea7d]*/
+/*[clinic end generated code: output=ea092a935c361582 input=f1b16cbcc3ed4101]*/
{
BYTE *data;
DWORD len;
<ClInclude Include="$(bz2Dir)\bzlib_private.h" />
</ItemGroup>
<ItemGroup>
+ <ResourceCompile Include="..\PC\python_nt.rc" />
+ </ItemGroup>
+ <ItemGroup>
<ProjectReference Include="pythoncore.vcxproj">
<Project>{cf7ac3d1-e2df-41d2-bea6-1e2556cdea26}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</CustomBuild>
</ItemGroup>
<ItemGroup>
+ <ResourceCompile Include="..\PC\python_nt.rc" />
+ </ItemGroup>
+ <ItemGroup>
<ProjectReference Include="pythoncore.vcxproj">
<Project>{cf7ac3d1-e2df-41d2-bea6-1e2556cdea26}</Project>
</ProjectReference>
<ClCompile Include="..\Modules\_ctypes\_ctypes_test.c" />
</ItemGroup>
<ItemGroup>
+ <ResourceCompile Include="..\PC\python_nt.rc" />
+ </ItemGroup>
+ <ItemGroup>
<ProjectReference Include="pythoncore.vcxproj">
<Project>{cf7ac3d1-e2df-41d2-bea6-1e2556cdea26}</Project>
</ProjectReference>
</CustomBuild>
</ItemGroup>
<ItemGroup>
+ <ResourceCompile Include="..\PC\python_nt.rc" />
+ </ItemGroup>
+ <ItemGroup>
<ProjectReference Include="pythoncore.vcxproj">
<Project>{cf7ac3d1-e2df-41d2-bea6-1e2556cdea26}</Project>
</ProjectReference>
<ClCompile Include="..\Modules\expat\xmltok.c" />
</ItemGroup>
<ItemGroup>
+ <ResourceCompile Include="..\PC\python_nt.rc" />
+ </ItemGroup>
+ <ItemGroup>
<ProjectReference Include="pythoncore.vcxproj">
<Project>{cf7ac3d1-e2df-41d2-bea6-1e2556cdea26}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
- <AdditionalIncludeDirectories>$(opensslDir)include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>$(opensslIncludeDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalDependencies>ws2_32.lib;$(OutDir)libeay$(PyDebugExt).lib;$(OutDir)ssleay$(PyDebugExt).lib;%(AdditionalDependencies)</AdditionalDependencies>
<ClCompile Include="..\Modules\_hashopenssl.c" />
</ItemGroup>
<ItemGroup>
+ <ResourceCompile Include="..\PC\python_nt.rc" />
+ </ItemGroup>
+ <ItemGroup>
<ProjectReference Include="pythoncore.vcxproj">
<Project>{cf7ac3d1-e2df-41d2-bea6-1e2556cdea26}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
-</Project>
\ No newline at end of file
+</Project>
<ClCompile Include="..\Modules\_lzmamodule.c" />
</ItemGroup>
<ItemGroup>
+ <ResourceCompile Include="..\PC\python_nt.rc" />
+ </ItemGroup>
+ <ItemGroup>
<ProjectReference Include="pythoncore.vcxproj">
<Project>{cf7ac3d1-e2df-41d2-bea6-1e2556cdea26}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
<ClCompile Include="..\PC\_msi.c" />
</ItemGroup>
<ItemGroup>
+ <ResourceCompile Include="..\PC\python_nt.rc" />
+ </ItemGroup>
+ <ItemGroup>
<ProjectReference Include="pythoncore.vcxproj">
<Project>{cf7ac3d1-e2df-41d2-bea6-1e2556cdea26}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
<ClCompile Include="..\Modules\_multiprocessing\semaphore.c" />
</ItemGroup>
<ItemGroup>
+ <ResourceCompile Include="..\PC\python_nt.rc" />
+ </ItemGroup>
+ <ItemGroup>
<ProjectReference Include="pythoncore.vcxproj">
<Project>{cf7ac3d1-e2df-41d2-bea6-1e2556cdea26}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
<ClCompile Include="..\Modules\overlapped.c" />
</ItemGroup>
<ItemGroup>
+ <ResourceCompile Include="..\PC\python_nt.rc" />
+ </ItemGroup>
+ <ItemGroup>
<ProjectReference Include="pythoncore.vcxproj">
<Project>{cf7ac3d1-e2df-41d2-bea6-1e2556cdea26}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
<ClCompile Include="..\Modules\socketmodule.c" />
</ItemGroup>
<ItemGroup>
+ <ResourceCompile Include="..\PC\python_nt.rc" />
+ </ItemGroup>
+ <ItemGroup>
<ProjectReference Include="pythoncore.vcxproj">
<Project>{cf7ac3d1-e2df-41d2-bea6-1e2556cdea26}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
<ClCompile Include="..\Modules\_sqlite\util.c" />
</ItemGroup>
<ItemGroup>
+ <ResourceCompile Include="..\PC\python_nt.rc" />
+ </ItemGroup>
+ <ItemGroup>
<ProjectReference Include="pythoncore.vcxproj">
<Project>{cf7ac3d1-e2df-41d2-bea6-1e2556cdea26}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
- <AdditionalIncludeDirectories>$(opensslDir)include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>$(opensslIncludeDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalDependencies>ws2_32.lib;crypt32.lib;$(OutDir)libeay$(PyDebugExt).lib;$(OutDir)ssleay$(PyDebugExt).lib;%(AdditionalDependencies)</AdditionalDependencies>
<ClCompile Include="..\Modules\_ssl.c" />
</ItemGroup>
<ItemGroup>
+ <ResourceCompile Include="..\PC\python_nt.rc" />
+ </ItemGroup>
+ <ItemGroup>
<ProjectReference Include="pythoncore.vcxproj">
<Project>{cf7ac3d1-e2df-41d2-bea6-1e2556cdea26}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
-</Project>
\ No newline at end of file
+</Project>
<ClCompile Include="..\Modules\_testbuffer.c" />
</ItemGroup>
<ItemGroup>
+ <ResourceCompile Include="..\PC\python_nt.rc" />
+ </ItemGroup>
+ <ItemGroup>
<ProjectReference Include="pythoncore.vcxproj">
<Project>{cf7ac3d1-e2df-41d2-bea6-1e2556cdea26}</Project>
</ProjectReference>
<ClCompile Include="..\Modules\_testcapimodule.c" />
</ItemGroup>
<ItemGroup>
+ <ResourceCompile Include="..\PC\python_nt.rc" />
+ </ItemGroup>
+ <ItemGroup>
<ProjectReference Include="pythoncore.vcxproj">
<Project>{cf7ac3d1-e2df-41d2-bea6-1e2556cdea26}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
<ClCompile Include="..\Programs\_testembed.c" />
</ItemGroup>
<ItemGroup>
+ <ResourceCompile Include="..\PC\python_nt.rc" />
+ </ItemGroup>
+ <ItemGroup>
<ProjectReference Include="pythoncore.vcxproj">
<Project>{cf7ac3d1-e2df-41d2-bea6-1e2556cdea26}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
<ClCompile Include="..\Modules\_testimportmultiple.c" />
</ItemGroup>
<ItemGroup>
+ <ResourceCompile Include="..\PC\python_nt.rc" />
+ </ItemGroup>
+ <ItemGroup>
<ProjectReference Include="pythoncore.vcxproj">
<Project>{cf7ac3d1-e2df-41d2-bea6-1e2556cdea26}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
<ClCompile Include="..\Modules\_testmultiphase.c" />
</ItemGroup>
<ItemGroup>
+ <ResourceCompile Include="..\PC\python_nt.rc" />
+ </ItemGroup>
+ <ItemGroup>
<ProjectReference Include="pythoncore.vcxproj">
<Project>{cf7ac3d1-e2df-41d2-bea6-1e2556cdea26}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
<ClCompile Include="..\Modules\tkappinit.c" />
</ItemGroup>
<ItemGroup>
+ <ResourceCompile Include="..\PC\python_nt.rc" />
+ </ItemGroup>
+ <ItemGroup>
<ProjectReference Include="pythoncore.vcxproj">
<Project>{cf7ac3d1-e2df-41d2-bea6-1e2556cdea26}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
echo. -v Increased output messages\r
echo. -k Attempt to kill any running Pythons before building (usually done\r
echo. automatically by the pythoncore project)\r
+echo. --pgo Build with Profile-Guided Optimization. This flag\r
+echo. overrides -c and -d\r
+echo. --test-marker Enable the test marker within the build.\r
echo.\r
echo.Available flags to avoid building certain modules.\r
echo.These flags have no effect if '-e' is not given:\r
echo. Set the platform (default: Win32)\r
echo. -t Build ^| Rebuild ^| Clean ^| CleanAll\r
echo. Set the target manually\r
-echo. --test-marker Enable the test marker within the build.\r
+echo. --pgo-job The job to use for PGO training; implies --pgo\r
+echo. (default: "-m test --pgo")\r
exit /b 127\r
\r
:Run\r
set parallel=/m\r
set verbose=/nologo /v:m\r
set kill=\r
+set do_pgo=\r
+set pgo_job=-m test --pgo\r
+set on_64_bit=true\r
+\r
+rem This may not be 100% accurate, but close enough.\r
+if "%ProgramFiles(x86)%"=="" (set on_64_bit=false)\r
\r
:CheckOpts\r
if "%~1"=="-h" goto Usage\r
if "%~1"=="-M" (set parallel=) & shift & goto CheckOpts\r
if "%~1"=="-v" (set verbose=/v:n) & shift & goto CheckOpts\r
if "%~1"=="-k" (set kill=true) & shift & goto CheckOpts\r
+if "%~1"=="--pgo" (set do_pgo=true) & shift & goto CheckOpts\r
+if "%~1"=="--pgo-job" (set do_pgo=true) & (set pgo_job=%~2) & shift & shift & goto CheckOpts\r
if "%~1"=="--test-marker" (set UseTestMarker=true) & shift & goto CheckOpts\r
if "%~1"=="-V" shift & goto Version\r
rem These use the actual property names used by MSBuild. We could just let\r
\r
if "%IncludeExternals%"=="true" call "%dir%get_externals.bat"\r
\r
-if "%platf%"=="x64" (set vs_platf=x86_amd64)\r
+if "%platf%"=="x64" (\r
+ if "%on_64_bit%"=="true" (\r
+ rem This ought to always be correct these days...\r
+ set vs_platf=amd64\r
+ ) else (\r
+ if "%do_pgo%"=="true" (\r
+ echo.ERROR: Cannot cross-compile with PGO\r
+ echo. 32bit operating system detected, if this is incorrect,\r
+ echo. make sure the ProgramFiles(x86^) environment variable is set\r
+ exit /b 1\r
+ )\r
+ set vs_platf=x86_amd64\r
+ )\r
+)\r
\r
rem Setup the environment\r
call "%dir%env.bat" %vs_platf% >nul\r
\r
-if "%kill%"=="true" (\r
- msbuild /v:m /nologo /target:KillPython "%dir%\pythoncore.vcxproj" /p:Configuration=%conf% /p:Platform=%platf% /p:KillPython=true\r
+if "%kill%"=="true" call :Kill\r
+\r
+if "%do_pgo%"=="true" (\r
+ set conf=PGInstrument\r
+ call :Build\r
+ del /s "%dir%\*.pgc"\r
+ del /s "%dir%\..\Lib\*.pyc"\r
+ echo on\r
+ call "%dir%\..\python.bat" %pgo_job%\r
+ @echo off\r
+ call :Kill\r
+ set conf=PGUpdate\r
)\r
+goto Build\r
\r
+:Kill\r
+echo on\r
+msbuild "%dir%\pythoncore.vcxproj" /t:KillPython %verbose%^\r
+ /p:Configuration=%conf% /p:Platform=%platf%^\r
+ /p:KillPython=true\r
+\r
+@echo off\r
+goto :eof\r
+\r
+:Build\r
rem Call on MSBuild to do the work, echo the command.\r
rem Passing %1-9 is not the preferred option, but argument parsing in\r
rem batch is, shall we say, "lackluster"\r
/p:UseTestMarker=%UseTestMarker%^\r
%1 %2 %3 %4 %5 %6 %7 %8 %9\r
\r
-@goto :eof\r
+@echo off\r
+goto :eof\r
\r
:Version\r
rem Display the current build version information\r
@echo off\r
-rem A batch program to build PGO (Profile guided optimization) by first\r
-rem building instrumented binaries, then running the testsuite, and\r
-rem finally building the optimized code.\r
-rem Note, after the first instrumented run, one can just keep on\r
-rem building the PGUpdate configuration while developing.\r
+echo.DeprecationWarning:\r
+echo. This script is deprecated, use `build.bat --pgo` instead.\r
+echo.\r
\r
-setlocal\r
-set platf=Win32\r
-set parallel=/m\r
-set dir=%~dp0\r
-\r
-rem use the performance testsuite. This is quick and simple\r
-set job1="%dir%..\tools\pybench\pybench.py" -n 1 -C 1 --with-gc\r
-set path1="%dir%..\tools\pybench"\r
-\r
-rem or the whole testsuite for more thorough testing\r
-set job2="%dir%..\lib\test\regrtest.py"\r
-set path2="%dir%..\lib"\r
-\r
-set job=%job1%\r
-set clrpath=%path1%\r
-\r
-:CheckOpts\r
-if "%1"=="-p" (set platf=%2) & shift & shift & goto CheckOpts\r
-if "%1"=="-2" (set job=%job2%) & (set clrpath=%path2%) & shift & goto CheckOpts\r
-if "%1"=="-M" (set parallel=) & shift & goto CheckOpts\r
-\r
-\r
-rem We cannot cross compile PGO builds, as the optimization needs to be run natively\r
-set vs_platf=x86\r
-set PGO=%dir%win32-pgo\r
-\r
-if "%platf%"=="x64" (set vs_platf=amd64) & (set PGO=%dir%amd64-pgo)\r
-rem Setup the environment\r
-call "%dir%env.bat" %vs_platf%\r
-\r
-\r
-rem build the instrumented version\r
-msbuild "%dir%pcbuild.proj" %parallel% /t:Build /p:Configuration=PGInstrument /p:Platform=%platf% %1 %2 %3 %4 %5 %6 %7 %8 %9\r
-\r
-rem remove .pyc files, .pgc files and execute the job\r
-"%PGO%\python.exe" "%dir%rmpyc.py" %clrpath%\r
-del "%PGO%\*.pgc"\r
-"%PGO%\python.exe" %job%\r
-\r
-rem build optimized version\r
-msbuild "%dir%pcbuild.proj" %parallel% /t:Build /p:Configuration=PGUpdate /p:Platform=%platf% %1 %2 %3 %4 %5 %6 %7 %8 %9\r
+call "%~dp0build.bat" --pgo %*\r
set libraries=\r
set libraries=%libraries% bzip2-1.0.6\r
if NOT "%IncludeSSL%"=="false" set libraries=%libraries% nasm-2.11.06\r
-if NOT "%IncludeSSL%"=="false" set libraries=%libraries% openssl-1.0.2d\r
+if NOT "%IncludeSSL%"=="false" set libraries=%libraries% openssl-1.0.2h\r
set libraries=%libraries% sqlite-3.8.11.0\r
if NOT "%IncludeTkinter%"=="false" set libraries=%libraries% tcl-core-8.6.4.2\r
if NOT "%IncludeTkinter%"=="false" set libraries=%libraries% tk-8.6.4.2\r
<PreprocessorDefinitions Include="_CRT_SECURE_NO_WARNINGS" />
<PreprocessorDefinitions Include="_CRT_SECURE_NO_DEPRECATE" />
<PreprocessorDefinitions Include="OPENSSL_THREADS" />
- <PreprocessorDefinitions Include="OPENSSL_SYSNAME_WIN32" />
+ <!-- <PreprocessorDefinitions Include="OPENSSL_SYSNAME_WIN32" /> -->
<PreprocessorDefinitions Include="OPENSSL_IA32_SSE2" />
- <PreprocessorDefinitions Include="OPENSSL_CPUID_OBJ" />
<PreprocessorDefinitions Include="SHA1_ASM" />
<PreprocessorDefinitions Include="SHA256_ASM" />
<PreprocessorDefinitions Include="SHA512_ASM" />
<ClCompile>
<!-- Suppress 64-bit truncation warnings - they aren't ours to worry about -->
<DisableSpecificWarnings>4244;4267</DisableSpecificWarnings>
- <AdditionalIncludeDirectories>$(opensslDir);$(opensslDir)include;$(opensslDir)crypto;$(opensslDir)crypto\asn1;$(opensslDir)crypto\evp;$(opensslDir)crypto\modes</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>$(opensslDir);$(opensslIncludeDir);$(opensslDir)crypto;$(opensslDir)crypto\asn1;$(opensslDir)crypto\evp;$(opensslDir)crypto\modes</AdditionalIncludeDirectories>
<PreprocessorDefinitions>$(_PreprocessorDefinitionList);%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
</ItemDefinitionGroup>
<Lib Include="$(IntDir)%(NasmCompile.Filename).obj" />
</ItemGroup>
</Target>
-</Project>
\ No newline at end of file
+</Project>
@echo off\r
if not defined HOST_PYTHON (\r
- if %1 EQU Debug (\r
+ if "%1" EQU "Debug" (\r
shift\r
set HOST_PYTHON=python_d.exe\r
if not exist python35_d.dll exit 1\r
if not exist python35.dll exit 1\r
)\r
)\r
-%HOST_PYTHON% prepare_ssl.py %1\r
+%HOST_PYTHON% "%~dp0prepare_ssl.py" %1\r
import os
import re
import sys
-import shutil
import subprocess
+from shutil import copy
# Find all "foo.exe" files on the PATH.
-def find_all_on_path(filename, extras = None):
+def find_all_on_path(filename, extras=None):
entries = os.environ["PATH"].split(os.pathsep)
ret = []
for p in entries:
ret.append(fname)
return ret
+
# Find a suitable Perl installation for OpenSSL.
# cygwin perl does *not* work. ActivePerl does.
# Being a Perl dummy, the simplest way I can check is if the "Win32" package
print("NO perl interpreters were found on this machine at all!")
print(" Please install ActivePerl and ensure it appears on your path")
-def create_makefile64(makefile, m32):
- """Create and fix makefile for 64bit
-
- Replace 32 with 64bit directories
- """
- if not os.path.isfile(m32):
- return
- with open(m32) as fin:
- with open(makefile, 'w') as fout:
- for line in fin:
- line = line.replace("=tmp32", "=tmp64")
- line = line.replace("=out32", "=out64")
- line = line.replace("=inc32", "=inc64")
- # force 64 bit machine
- line = line.replace("MKLIB=lib", "MKLIB=lib /MACHINE:X64")
- line = line.replace("LFLAGS=", "LFLAGS=/MACHINE:X64 ")
- # don't link against the lib on 64bit systems
- line = line.replace("bufferoverflowu.lib", "")
- fout.write(line)
- os.unlink(m32)
-
-def create_asms(makefile):
+
+def create_asms(makefile, tmp_d):
#create a custom makefile out of the provided one
asm_makefile = os.path.splitext(makefile)[0] + '.asm.mak'
- with open(makefile) as fin:
- with open(asm_makefile, 'w') as fout:
- for line in fin:
- # Keep everything up to the install target (it's convenient)
- if line.startswith('install: all'):
- break
- else:
+ with open(makefile) as fin, open(asm_makefile, 'w') as fout:
+ for line in fin:
+ # Keep everything up to the install target (it's convenient)
+ if line.startswith('install: all'):
+ break
+ fout.write(line)
+ asms = []
+ for line in fin:
+ if '.asm' in line and line.strip().endswith('.pl'):
+ asms.append(line.split(':')[0])
+ while line.strip():
fout.write(line)
- asms = []
- for line in fin:
- if '.asm' in line and line.strip().endswith('.pl'):
- asms.append(line.split(':')[0])
- while line.strip():
- fout.write(line)
- line = next(fin)
- fout.write('\n')
+ line = next(fin)
+ fout.write('\n')
- fout.write('asms: $(TMP_D) ')
- fout.write(' '.join(asms))
- fout.write('\n')
+ fout.write('asms: $(TMP_D) ')
+ fout.write(' '.join(asms))
+ fout.write('\n')
+ os.system('nmake /f {} PERL=perl TMP_D={} asms'.format(asm_makefile, tmp_d))
- os.system('nmake /f {} PERL=perl asms'.format(asm_makefile))
- os.unlink(asm_makefile)
-
-
-def fix_makefile(makefile):
- """Fix some stuff in all makefiles
- """
- if not os.path.isfile(makefile):
- return
+def copy_includes(makefile, suffix):
+ dir = 'include'+suffix+'\\openssl'
+ os.makedirs(dir, exist_ok=True)
copy_if_different = r'$(PERL) $(SRC_D)\util\copy-if-different.pl'
with open(makefile) as fin:
- lines = fin.readlines()
- with open(makefile, 'w') as fout:
- for line in lines:
- if line.startswith("PERL="):
- continue
- if line.startswith("CP="):
- line = "CP=copy\n"
- if line.startswith("MKDIR="):
- line = "MKDIR=mkdir\n"
- if line.startswith("CFLAG="):
- line = line.strip()
- for algo in ("RC5", "MDC2", "IDEA"):
- noalgo = " -DOPENSSL_NO_%s" % algo
- if noalgo not in line:
- line = line + noalgo
- line = line + '\n'
+ for line in fin:
if copy_if_different in line:
- line = line.replace(copy_if_different, 'copy /Y')
- fout.write(line)
+ perl, script, src, dest = line.split()
+ if not '$(INCO_D)' in dest:
+ continue
+ # We're in the root of the source tree
+ src = src.replace('$(SRC_D)', '.').strip('"')
+ dest = dest.strip('"').replace('$(INCO_D)', dir)
+ print('copying', src, 'to', dest)
+ copy(src, dest)
+
def run_configure(configure, do_script):
print("perl Configure "+configure+" no-idea no-mdc2")
print(do_script)
os.system(do_script)
-def cmp(f1, f2):
- bufsize = 1024 * 8
- with open(f1, 'rb') as fp1, open(f2, 'rb') as fp2:
- while True:
- b1 = fp1.read(bufsize)
- b2 = fp2.read(bufsize)
- if b1 != b2:
- return False
- if not b1:
- return True
-
-def copy(src, dst):
- if os.path.isfile(dst) and cmp(src, dst):
- return
- shutil.copy(src, dst)
def prep(arch):
+ makefile_template = "ms\\nt{}.mak"
+ generated_makefile = makefile_template.format('')
if arch == "x86":
configure = "VC-WIN32"
do_script = "ms\\do_nasm"
- makefile="ms\\nt.mak"
- m32 = makefile
- dirsuffix = "32"
+ suffix = "32"
elif arch == "amd64":
configure = "VC-WIN64A"
do_script = "ms\\do_win64a"
- makefile = "ms\\nt64.mak"
- m32 = makefile.replace('64', '')
- dirsuffix = "64"
+ suffix = "64"
#os.environ["VSEXTCOMP_USECL"] = "MS_OPTERON"
else:
raise ValueError('Unrecognized platform: %s' % arch)
- # rebuild makefile when we do the role over from 32 to 64 build
- if arch == "amd64" and os.path.isfile(m32) and not os.path.isfile(makefile):
- os.unlink(m32)
-
- # If the ssl makefiles do not exist, we invoke Perl to generate them.
- # Due to a bug in this script, the makefile sometimes ended up empty
- # Force a regeneration if it is.
- if not os.path.isfile(makefile) or os.path.getsize(makefile)==0:
- print("Creating the makefiles...")
- sys.stdout.flush()
- run_configure(configure, do_script)
-
- if arch == "amd64":
- create_makefile64(makefile, m32)
- fix_makefile(makefile)
- copy(r"crypto\buildinf.h", r"crypto\buildinf_%s.h" % arch)
- copy(r"crypto\opensslconf.h", r"crypto\opensslconf_%s.h" % arch)
- else:
- print(makefile, 'already exists!')
+ print("Creating the makefiles...")
+ sys.stdout.flush()
+ # run configure, copy includes, create asms
+ run_configure(configure, do_script)
+ makefile = makefile_template.format(suffix)
+ try:
+ os.unlink(makefile)
+ except FileNotFoundError:
+ pass
+ os.rename(generated_makefile, makefile)
+ copy_includes(makefile, suffix)
print('creating asms...')
- create_asms(makefile)
+ create_asms(makefile, 'tmp'+suffix)
+
def main():
if len(sys.argv) == 1:
print("Found a working perl at '%s'" % (perl,))
else:
sys.exit(1)
+ if not find_all_on_path('nmake.exe'):
+ print('Could not find nmake.exe, try running env.bat')
+ sys.exit(1)
+ if not find_all_on_path('nasm.exe'):
+ print('Could not find nasm.exe, please add to PATH')
+ sys.exit(1)
sys.stdout.flush()
# Put our working Perl at the front of our path
<ClCompile Include="..\Modules\expat\xmltok.c" />
</ItemGroup>
<ItemGroup>
+ <ResourceCompile Include="..\PC\python_nt.rc" />
+ </ItemGroup>
+ <ItemGroup>
<ProjectReference Include="pythoncore.vcxproj">
<Project>{cf7ac3d1-e2df-41d2-bea6-1e2556cdea26}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
<ProjectGuid>{7B2727B5-5A3F-40EE-A866-43A13CD31446}</ProjectGuid>
<RootNamespace>pylauncher</RootNamespace>
<TargetName>py</TargetName>
- <MakeVersionInfoBeforeTarget>ClCompile</MakeVersionInfoBeforeTarget>
<SupportPGO>false</SupportPGO>
</PropertyGroup>
<Import Project="python.props" />
<WholeProgramOptimization>false</WholeProgramOptimization>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
</ClCompile>
+ <ClCompile Condition="$(ICCBuild) == 'true'">
+ <FloatingPointModel>Strict</FloatingPointModel>
+ </ClCompile>
<Link>
<AdditionalLibraryDirectories>$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
<LinkTimeCodeGeneration Condition="$(SupportPGO) and $(Configuration) == 'PGUpdate'">true</LinkTimeCodeGeneration>
</Lib>
<ResourceCompile>
- <AdditionalIncludeDirectories>$(PySourcePath)PC;$(PySourcePath)Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>$(PySourcePath)PC;$(PySourcePath)Include;$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>$(_DebugPreprocessorDefinition)%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Culture>0x0409</Culture>
</ResourceCompile>
</ItemDefinitionGroup>
<Target Name="GeneratePythonNtRcH"
- BeforeTargets="$(MakeVersionInfoBeforeTarget)"
+ BeforeTargets="ClCompile"
Inputs="$(PySourcePath)Include\patchlevel.h"
- Outputs="$(PySourcePath)PC\pythonnt_rc$(PyDebugExt).h">
- <WriteLinesToFile File="$(PySourcePath)PC\pythonnt_rc$(PyDebugExt).h" Overwrite="true" Encoding="ascii"
- Lines='/* This file created by python.props /t:GeneratePythonNtRcH */
+ Outputs="$(IntDir)pythonnt_rc.h">
+ <WriteLinesToFile File="$(IntDir)pythonnt_rc.h" Overwrite="true" Encoding="ascii"
+ Lines='/* This file created by pyproject.props /t:GeneratePythonNtRcH */
#define FIELD3 $(Field3Value)
#define MS_DLL_ID "$(SysWinVer)"
-#define PYTHON_DLL_NAME "$(PyDllName).dll"
+#define PYTHON_DLL_NAME "$(TargetName)$(TargetExt)"
' />
<ItemGroup>
- <FileWrites Include="$(PySourcePath)PC\pythonnt_rc$(PyDebugExt).h" />
+ <FileWrites Include="$(IntDir)pythonnt_rc.h" />
</ItemGroup>
</Target>
<SignToolPath Condition="'$(SignToolPath)' == '' or !Exists($(SignToolPath))">$(registry:HKEY_LOCAL_MACHINE\Software\Microsoft\Windows Kits\Installed Roots@KitsRoot81)\bin\x86\signtool.exe</SignToolPath>
<SignToolPath Condition="!Exists($(SignToolPath))">$(registry:HKEY_LOCAL_MACHINE\Software\Microsoft\Windows Kits\Installed Roots@KitsRoot)\bin\x86\signtool.exe</SignToolPath>
<SignToolPath Condition="!Exists($(SignToolPath))">$(registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.1A@InstallationFolder)\Bin\signtool.exe</SignToolPath>
- <_SignCommand Condition="Exists($(SignToolPath))">"$(SignToolPath)" sign /q /n "$(SigningCertificate)" /t http://timestamp.verisign.com/scripts/timestamp.dll /d "Python $(PythonVersion)"</_SignCommand>
+ <_SignCommand Condition="Exists($(SignToolPath))">"$(SignToolPath)" sign /q /n "$(SigningCertificate)" /fd sha256 /t http://timestamp.verisign.com/scripts/timestamp.dll /d "Python $(PythonVersion)"</_SignCommand>
</PropertyGroup>
<Target Name="_SignBuild" AfterTargets="AfterBuild" Condition="'$(SigningCertificate)' != '' and $(SupportSigning)">
Use the latest available version of Visual Studio to build. To override
this and build with an earlier version, pass "/p:PlatformToolset=v100"
(for example) when building.
+
+ We set BasePlatformToolset for ICC's benefit, it's otherwise ignored.
-->
- <PlatformToolset Condition="'$(PlatformToolset)' == '' and '$(VCTargetsPath14)' != ''">v140</PlatformToolset>
- <PlatformToolset Condition="'$(PlatformToolset)' == '' and '$(VCTargetsPath12)' != ''">v120</PlatformToolset>
- <PlatformToolset Condition="'$(PlatformToolset)' == '' and '$(VCTargetsPath11)' != ''">v110</PlatformToolset>
- <PlatformToolset Condition="'$(PlatformToolset)' == '' and '$(VCTargetsPath10)' != ''">v100</PlatformToolset>
-
+ <BasePlatformToolset Condition="'$(BasePlatformToolset)' == '' and '$(VCTargetsPath14)' != ''">v140</BasePlatformToolset>
+ <BasePlatformToolset Condition="'$(BasePlatformToolset)' == '' and '$(VCTargetsPath12)' != ''">v120</BasePlatformToolset>
+ <BasePlatformToolset Condition="'$(BasePlatformToolset)' == '' and '$(VCTargetsPath11)' != ''">v110</BasePlatformToolset>
+ <BasePlatformToolset Condition="'$(BasePlatformToolset)' == '' and '$(VCTargetsPath10)' != ''">v100</BasePlatformToolset>
+
+ <PlatformToolset Condition="'$(PlatformToolset)' == ''">$(BasePlatformToolset)</PlatformToolset>
+ <ICCBuild>false</ICCBuild>
+ <ICCBuild Condition="$(PlatformToolset.StartsWith(`Intel C++ Compiler`))">true</ICCBuild>
+
<!--
Convincing MSVC/MSBuild to prefer our platform names is too difficult,
so we define our own constant ArchName and use wherever we need it.
<sqlite3Dir>$(ExternalsDir)sqlite-3.8.11.0\</sqlite3Dir>
<bz2Dir>$(ExternalsDir)bzip2-1.0.6\</bz2Dir>
<lzmaDir>$(ExternalsDir)xz-5.0.5\</lzmaDir>
- <opensslDir>$(ExternalsDir)openssl-1.0.2d\</opensslDir>
+ <opensslDir>$(ExternalsDir)openssl-1.0.2h\</opensslDir>
+ <opensslIncludeDir>$(opensslDir)include32</opensslIncludeDir>
+ <opensslIncludeDir Condition="'$(ArchName)' == 'amd64'">$(opensslDir)include64</opensslIncludeDir>
<nasmDir>$(ExternalsDir)\nasm-2.11.06\</nasmDir>
<!-- Suffix for all binaries when building for debug -->
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{B11D750F-CD1F-4A96-85CE-E69A5C5259F9}</ProjectGuid>
- <MakeVersionInfoBeforeTarget>ClCompile</MakeVersionInfoBeforeTarget>
</PropertyGroup>
<Import Project="python.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
+ <Target Name="ValidateUcrtbase" AfterTargets="AfterBuild">
+ <PropertyGroup>
+ <UcrtName>ucrtbase</UcrtName>
+ <UcrtName Condition="'$(Configuration)' == 'Debug'">ucrtbased</UcrtName>
+ </PropertyGroup>
+ <Exec Command='"$(OutDir)python$(PyDebugExt).exe" "$(PySourcePath)PC\validate_ucrtbase.py" $(UcrtName)' ContinueOnError="true" />
+ </Target>
<Target Name="GeneratePythonBat" AfterTargets="AfterBuild">
<PropertyGroup>
<_Content>@rem This script invokes the most recently built Python with all arguments
<RootNamespace>python3dll</RootNamespace>
<Keyword>Win32Proj</Keyword>
<TargetName>python3</TargetName>
- <MakeVersionInfoBeforeTarget>ClCompile</MakeVersionInfoBeforeTarget>
<SupportPGO>false</SupportPGO>
</PropertyGroup>
<Import Project="python.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<PropertyGroup>
- <MakeVersionInfoBeforeTarget>ClCompile</MakeVersionInfoBeforeTarget>
<KillPython>true</KillPython>
</PropertyGroup>
<ImportGroup Label="PropertySheets">
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{F4229CC3-873C-49AE-9729-DD308ED4CD4A}</ProjectGuid>
- <MakeVersionInfoBeforeTarget>ClCompile</MakeVersionInfoBeforeTarget>
<SupportPGO>false</SupportPGO>
</PropertyGroup>
<Import Project="python.props" />
<ProjectGuid>{1D4B18D3-7C12-4ECB-9179-8531FF876CE6}</ProjectGuid>
<RootNamespace>pywlauncher</RootNamespace>
<TargetName>pyw</TargetName>
- <MakeVersionInfoBeforeTarget>ClCompile</MakeVersionInfoBeforeTarget>
<SupportPGO>false</SupportPGO>
</PropertyGroup>
<Import Project="python.props" />
Homepage:\r
http://tukaani.org/xz/\r
_ssl\r
- Python wrapper for version 1.0.2d of the OpenSSL secure sockets\r
+ Python wrapper for version 1.0.2h of the OpenSSL secure sockets\r
library, which is built by ssl.vcxproj\r
Homepage:\r
http://www.openssl.org/\r
<ClCompile Include="..\Modules\selectmodule.c" />
</ItemGroup>
<ItemGroup>
+ <ResourceCompile Include="..\PC\python_nt.rc" />
+ </ItemGroup>
+ <ItemGroup>
<ProjectReference Include="pythoncore.vcxproj">
<Project>{cf7ac3d1-e2df-41d2-bea6-1e2556cdea26}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
+ <_SqliteVersion>$([System.Text.RegularExpressions.Regex]::Match(`$(sqlite3Dir)`, `((\d+)\.(\d+)\.(\d+)\.(\d+))\\?$`).Groups)</_SqliteVersion>
+ <SqliteVersion>$(_SqliteVersion.Split(`;`)[1])</SqliteVersion>
+ <SqliteMajorVersion>$(_SqliteVersion.Split(`;`)[2])</SqliteMajorVersion>
+ <SqliteMinorVersion>$(_SqliteVersion.Split(`;`)[3])</SqliteMinorVersion>
+ <SqliteMicroVersion>$(_SqliteVersion.Split(`;`)[4])</SqliteMicroVersion>
+ <SqlitePatchVersion>$(_SqliteVersion.Split(`;`)[5])</SqlitePatchVersion>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<PreprocessorDefinitions>SQLITE_API=__declspec(dllexport);%(PreprocessorDefinitions)</PreprocessorDefinitions>
<WarningLevel>Level1</WarningLevel>
</ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>SQLITE_VERSION=$(SqliteVersion);SQLITE_MAJOR_VERSION=$(SqliteMajorVersion);SQLITE_MINOR_VERSION=$(SqliteMinorVersion);SQLITE_MICRO_VERSION=$(SqliteMicroVersion);SQLITE_PATCH_VERSION=$(SqlitePatchVersion);%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="$(sqlite3Dir)\sqlite3.h" />
<ItemGroup>
<ClCompile Include="$(sqlite3Dir)\sqlite3.c" />
</ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="..\PC\sqlite3.rc" />
+ </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
<BuildDirTop>Release</BuildDirTop>
<BuildDirTop Condition="$(Configuration) == 'Debug'">Debug</BuildDirTop>
<BuildDirTop Condition="$(TclMachine) != 'IX86'">$(BuildDirTop)_$(TclMachine)</BuildDirTop>
- <BuildDirTop Condition="$(VisualStudioVersion) == '14.0'">$(BuildDirTop)_VC13</BuildDirTop>
- <BuildDirTop Condition="$(VisualStudioVersion) == '12.0'">$(BuildDirTop)_VC12</BuildDirTop>
- <BuildDirTop Condition="$(VisualStudioVersion) == '11.0'">$(BuildDirTop)_VC11</BuildDirTop>
- <BuildDirTop Condition="$(VisualStudioVersion) == '10.0'">$(BuildDirTop)_VC10</BuildDirTop>
+ <BuildDirTop Condition="$(PlatformToolset) == 'v140'">$(BuildDirTop)_VC13</BuildDirTop>
+ <BuildDirTop Condition="$(PlatformToolset) == 'v120'">$(BuildDirTop)_VC12</BuildDirTop>
+ <BuildDirTop Condition="$(PlatformToolset) == 'v110'">$(BuildDirTop)_VC11</BuildDirTop>
+ <BuildDirTop Condition="$(PlatformToolset) == 'v100'">$(BuildDirTop)_VC10</BuildDirTop>
</PropertyGroup>
</Project>
\ No newline at end of file
<ClCompile Include="..\Modules\unicodedata.c" />
</ItemGroup>
<ItemGroup>
+ <ResourceCompile Include="..\PC\python_nt.rc" />
+ </ItemGroup>
+ <ItemGroup>
<ProjectReference Include="pythoncore.vcxproj">
<Project>{cf7ac3d1-e2df-41d2-bea6-1e2556cdea26}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
<ClCompile Include="..\PC\winsound.c" />
</ItemGroup>
<ItemGroup>
+ <ResourceCompile Include="..\PC\python_nt.rc" />
+ </ItemGroup>
+ <ItemGroup>
<ProjectReference Include="pythoncore.vcxproj">
<Project>{cf7ac3d1-e2df-41d2-bea6-1e2556cdea26}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
return 0;
}
*spec = r;
+ break;
}
}
}
if (stream == NULL)
goto cleanup;
- Py_XDECREF(tok->decoding_readline);
readline = _PyObject_GetAttrId(stream, &PyId_readline);
- tok->decoding_readline = readline;
+ Py_XSETREF(tok->decoding_readline, readline);
if (pos > 0) {
if (PyObject_CallObject(readline, NULL) == NULL) {
readline = NULL;
/*****************************************************
- * Test repeated initalisation and subinterpreters
+ * Test repeated initialisation and subinterpreters
*****************************************************/
static void print_subinterp(void)
#include <locale.h>
#ifdef __FreeBSD__
-#include <floatingpoint.h>
+#include <fenv.h>
#endif
#ifdef MS_WINDOWS
wchar_t **argv_copy2;
int i, res;
char *oldloc;
-#ifdef __FreeBSD__
- fp_except_t m;
-#endif
argv_copy = (wchar_t **)PyMem_RawMalloc(sizeof(wchar_t*) * (argc+1));
argv_copy2 = (wchar_t **)PyMem_RawMalloc(sizeof(wchar_t*) * (argc+1));
* exceptions by default. Here we disable them.
*/
#ifdef __FreeBSD__
- m = fpgetmask();
- fpsetmask(m & ~FP_X_OFL);
+ fedisableexcept(FE_OVERFLOW);
#endif
oldloc = _PyMem_RawStrdup(setlocale(LC_ALL, NULL));
goto handle_error;
}
else if (!is_true) {
- Py_DECREF(*filename);
- *filename = PyUnicode_FromString("__main__");
+ Py_SETREF(*filename, PyUnicode_FromString("__main__"));
if (*filename == NULL)
goto handle_error;
}
y: object
/
-Return the tuple ((x-x%y)/y, x%y). Invariant: div*y + mod == x.
+Return the tuple (x//y, x%y). Invariant: div*y + mod == x.
[clinic start generated code]*/
static PyObject *
builtin_divmod_impl(PyModuleDef *module, PyObject *x, PyObject *y)
-/*[clinic end generated code: output=9ad0076120ebf9ac input=7fdb15f8a97a5fe7]*/
+/*[clinic end generated code: output=9ad0076120ebf9ac input=175ad9c84ff41a85]*/
{
return PyNumber_Divmod(x, y);
}
PyObject *obj = TOP();
PyTypeObject *type = Py_TYPE(obj);
- if (type->tp_as_async != NULL)
+ if (type->tp_as_async != NULL) {
getter = type->tp_as_async->am_aiter;
+ }
if (getter != NULL) {
iter = (*getter)(obj);
goto error;
}
+ if (Py_TYPE(iter)->tp_as_async != NULL &&
+ Py_TYPE(iter)->tp_as_async->am_anext != NULL) {
+
+ /* Starting with CPython 3.5.2 __aiter__ should return
+ asynchronous iterators directly (not awaitables that
+ resolve to asynchronous iterators.)
+
+ Therefore, we check if the object that was returned
+ from __aiter__ has an __anext__ method. If it does,
+ we wrap it in an awaitable that resolves to `iter`.
+
+ See http://bugs.python.org/issue27243 for more
+ details.
+ */
+
+ PyObject *wrapper = _PyAIterWrapper_New(iter);
+ Py_DECREF(iter);
+ SET_TOP(wrapper);
+ DISPATCH();
+ }
+
awaitable = _PyCoro_GetAwaitableIter(iter);
if (awaitable == NULL) {
SET_TOP(NULL);
Py_DECREF(iter);
goto error;
- } else
+ } else {
Py_DECREF(iter);
+ if (PyErr_WarnFormat(
+ PyExc_PendingDeprecationWarning, 1,
+ "'%.100s' implements legacy __aiter__ protocol; "
+ "__aiter__ should return an asynchronous "
+ "iterator, not awaitable",
+ type->tp_name))
+ {
+ /* Warning was converted to an error. */
+ Py_DECREF(awaitable);
+ SET_TOP(NULL);
+ goto error;
+ }
+ }
+
SET_TOP(awaitable);
DISPATCH();
}
Py_DECREF(iterable);
+ if (iter != NULL && PyCoro_CheckExact(iter)) {
+ PyObject *yf = _PyGen_yf((PyGenObject*)iter);
+ if (yf != NULL) {
+ /* `iter` is a coroutine object that is being
+ awaited, `yf` is a pointer to the current awaitable
+ being awaited on. */
+ Py_DECREF(yf);
+ Py_CLEAR(iter);
+ PyErr_SetString(
+ PyExc_RuntimeError,
+ "coroutine is being awaited already");
+ /* The code below jumps to `error` if `iter` is NULL. */
+ }
+ }
+
SET_TOP(iter); /* Even if it's NULL */
if (iter == NULL) {
Py_INCREF(self);
func = PyMethod_GET_FUNCTION(func);
Py_INCREF(func);
- Py_DECREF(*pfunc);
- *pfunc = self;
+ Py_SETREF(*pfunc, self);
na++;
/* n++; */
} else
PyObject *anns = PyDict_New();
if (anns == NULL) {
Py_DECREF(func);
+ Py_DECREF(names);
goto error;
}
name_ix = PyTuple_Size(names);
if (err != 0) {
Py_DECREF(anns);
Py_DECREF(func);
+ Py_DECREF(names);
goto error;
}
}
+ Py_DECREF(names);
if (PyFunction_SetAnnotations(func, anns) != 0) {
/* Can't happen unless
goto error;
}
Py_DECREF(anns);
- Py_DECREF(names);
}
/* XXX Maybe this should be a separate opcode? */
{
PyThreadState *tstate = PyThreadState_GET();
- Py_CLEAR(tstate->coroutine_wrapper);
-
Py_XINCREF(wrapper);
- tstate->coroutine_wrapper = wrapper;
+ Py_XSETREF(tstate->coroutine_wrapper, wrapper);
}
PyObject *
Py_INCREF(self);
func = PyMethod_GET_FUNCTION(func);
Py_INCREF(func);
- Py_DECREF(*pfunc);
- *pfunc = self;
+ Py_SETREF(*pfunc, self);
na++;
n++;
} else
stararg = EXT_POP(*pp_stack);
if (!PyTuple_Check(stararg)) {
PyObject *t = NULL;
+ if (Py_TYPE(stararg)->tp_iter == NULL &&
+ !PySequence_Check(stararg)) {
+ PyErr_Format(PyExc_TypeError,
+ "%.200s%.200s argument after * "
+ "must be an iterable, not %.200s",
+ PyEval_GetFuncName(func),
+ PyEval_GetFuncDesc(func),
+ stararg->ob_type->tp_name);
+ goto ext_call_fail;
+ }
t = PySequence_Tuple(stararg);
if (t == NULL) {
- if (PyErr_ExceptionMatches(PyExc_TypeError)) {
- PyErr_Format(PyExc_TypeError,
- "%.200s%.200s argument after * "
- "must be a sequence, not %.200s",
- PyEval_GetFuncName(func),
- PyEval_GetFuncDesc(func),
- stararg->ob_type->tp_name);
- }
goto ext_call_fail;
}
Py_DECREF(stararg);
static unsigned long gil_switch_number = 0;
/* Last PyThreadState holding / having held the GIL. This helps us know
whether anyone else was scheduled after we dropped the GIL. */
-static _Py_atomic_address gil_last_holder = {NULL};
+static _Py_atomic_address gil_last_holder = {0};
/* This condition variable allows one or several threads to wait until
the GIL is released. In addition, the mutex also protects the above
#ifdef FORCE_SWITCHING
COND_INIT(switch_cond);
#endif
- _Py_atomic_store_relaxed(&gil_last_holder, NULL);
+ _Py_atomic_store_relaxed(&gil_last_holder, 0);
_Py_ANNOTATE_RWLOCK_CREATE(&gil_locked);
_Py_atomic_store_explicit(&gil_locked, 0, _Py_memory_order_release);
}
/* Sub-interpreter support: threads might have been switched
under our feet using PyThreadState_Swap(). Fix the GIL last
holder variable so that our heuristics work. */
- _Py_atomic_store_relaxed(&gil_last_holder, tstate);
+ _Py_atomic_store_relaxed(&gil_last_holder, (Py_uintptr_t)tstate);
}
MUTEX_LOCK(gil_mutex);
_Py_ANNOTATE_RWLOCK_ACQUIRED(&gil_locked, /*is_write=*/1);
if (tstate != (PyThreadState*)_Py_atomic_load_relaxed(&gil_last_holder)) {
- _Py_atomic_store_relaxed(&gil_last_holder, tstate);
+ _Py_atomic_store_relaxed(&gil_last_holder, (Py_uintptr_t)tstate);
++gil_switch_number;
}
"divmod($module, x, y, /)\n"
"--\n"
"\n"
-"Return the tuple ((x-x%y)/y, x%y). Invariant: div*y + mod == x.");
+"Return the tuple (x//y, x%y). Invariant: div*y + mod == x.");
#define BUILTIN_DIVMOD_METHODDEF \
{"divmod", (PyCFunction)builtin_divmod, METH_VARARGS, builtin_divmod__doc__},
exit:
return return_value;
}
-/*[clinic end generated code: output=bec3399c0aee98d7 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=4bef16b6aa432879 input=a9049054013a1b77]*/
operation, encoding);
}
-/* Encode an object (e.g. an Unicode object) using the given encoding
+/* Encode an object (e.g. a Unicode object) using the given encoding
and return the resulting encoded object (usually a Python string).
errors is passed to the encoder factory as argument if non-NULL. */
}
/* Decode an object (usually a Python string) using the given encoding
- and return an equivalent object (e.g. an Unicode object).
+ and return an equivalent object (e.g. a Unicode object).
errors is passed to the decoder factory as argument if non-NULL. */
return NULL;
}
k = PyList_GET_ITEM(list, i);
- k = PyTuple_Pack(2, k, k->ob_type);
+ k = _PyCode_ConstantKey(k);
if (k == NULL || PyDict_SetItem(dict, k, v) < 0) {
Py_XDECREF(k);
Py_DECREF(v);
return NULL;
}
i++;
- tuple = PyTuple_Pack(2, k, k->ob_type);
+ tuple = _PyCode_ConstantKey(k);
if (!tuple || PyDict_SetItem(dest, tuple, item) < 0) {
Py_DECREF(sorted_keys);
Py_DECREF(item);
compiler_unit_free(u);
return 0;
}
- tuple = PyTuple_Pack(2, name, Py_TYPE(name));
+ tuple = _PyCode_ConstantKey(name);
if (!tuple) {
compiler_unit_free(u);
return 0;
{
PyObject *t, *v;
Py_ssize_t arg;
- double d;
-
- /* necessary to make sure types aren't coerced (e.g., float and complex) */
- /* _and_ to distinguish 0.0 from -0.0 e.g. on IEEE platforms */
- if (PyFloat_Check(o)) {
- d = PyFloat_AS_DOUBLE(o);
- /* all we need is to make the tuple different in either the 0.0
- * or -0.0 case from all others, just to avoid the "coercion".
- */
- if (d == 0.0 && copysign(1.0, d) < 0.0)
- t = PyTuple_Pack(3, o, o->ob_type, Py_None);
- else
- t = PyTuple_Pack(2, o, o->ob_type);
- }
- else if (PyComplex_Check(o)) {
- Py_complex z;
- int real_negzero, imag_negzero;
- /* For the complex case we must make complex(x, 0.)
- different from complex(x, -0.) and complex(0., y)
- different from complex(-0., y), for any x and y.
- All four complex zeros must be distinguished.*/
- z = PyComplex_AsCComplex(o);
- real_negzero = z.real == 0.0 && copysign(1.0, z.real) < 0.0;
- imag_negzero = z.imag == 0.0 && copysign(1.0, z.imag) < 0.0;
- if (real_negzero && imag_negzero) {
- t = PyTuple_Pack(5, o, o->ob_type,
- Py_None, Py_None, Py_None);
- }
- else if (imag_negzero) {
- t = PyTuple_Pack(4, o, o->ob_type, Py_None, Py_None);
- }
- else if (real_negzero) {
- t = PyTuple_Pack(3, o, o->ob_type, Py_None);
- }
- else {
- t = PyTuple_Pack(2, o, o->ob_type);
- }
- }
- else {
- t = PyTuple_Pack(2, o, o->ob_type);
- }
+
+ t = _PyCode_ConstantKey(o);
if (t == NULL)
return -1;
compiler_lookup_arg(PyObject *dict, PyObject *name)
{
PyObject *k, *v;
- k = PyTuple_Pack(2, name, name->ob_type);
+ k = _PyCode_ConstantKey(name);
if (k == NULL)
return -1;
v = PyDict_GetItem(dict, k);
{
/* use the class name for name mangling */
Py_INCREF(s->v.ClassDef.name);
- Py_XDECREF(c->u->u_private);
- c->u->u_private = s->v.ClassDef.name;
+ Py_XSETREF(c->u->u_private, s->v.ClassDef.name);
/* load (global) __name__ ... */
str = PyUnicode_InternFromString("__name__");
if (!str || !compiler_nameop(c, str, Load)) {
return NULL;
while (PyDict_Next(dict, &pos, &k, &v)) {
i = PyLong_AS_LONG(v);
- /* The keys of the dictionary are tuples. (see compiler_add_o)
- The object we want is always first, though. */
- k = PyTuple_GET_ITEM(k, 0);
+ /* The keys of the dictionary are tuples. (see compiler_add_o
+ * and _PyCode_ConstantKey). The object we want is always second,
+ * though. */
+ k = PyTuple_GET_ITEM(k, 1);
Py_INCREF(k);
assert((i - offset) < size);
assert((i - offset) >= 0);
PyObject *
PyErr_Occurred(void)
{
- /* If there is no thread state, PyThreadState_GET calls
- Py_FatalError, which calls PyErr_Occurred. To avoid the
- resulting infinite loop, we inline PyThreadState_GET here and
- treat no thread as no error. */
- PyThreadState *tstate =
- ((PyThreadState*)_Py_atomic_load_relaxed(&_PyThreadState_Current));
-
+ PyThreadState *tstate = _PyThreadState_UncheckedGet();
return tstate == NULL ? NULL : tstate->curexc_type;
}
tstate = PyThreadState_GET();
if (++tstate->recursion_depth > Py_GetRecursionLimit()) {
--tstate->recursion_depth;
- /* throw away the old exception... */
- Py_DECREF(*exc);
- Py_DECREF(*val);
- /* ... and use the recursion error instead */
- *exc = PyExc_RecursionError;
- *val = PyExc_RecursionErrorInst;
- Py_INCREF(*exc);
- Py_INCREF(*val);
+ /* throw away the old exception and use the recursion error instead */
+ Py_INCREF(PyExc_RecursionError);
+ Py_SETREF(*exc, PyExc_RecursionError);
+ Py_INCREF(PyExc_RecursionErrorInst);
+ Py_SETREF(*val, PyExc_RecursionErrorInst);
/* just keeping the old traceback */
return;
}
PyTuple_SET_ITEM(args, 0, msg);
if (PyDict_SetItemString(kwargs, "name", name) < 0)
- return NULL;
+ goto done;
if (PyDict_SetItemString(kwargs, "path", path) < 0)
- return NULL;
+ goto done;
error = PyObject_Call(PyExc_ImportError, args, kwargs);
if (error != NULL) {
Py_DECREF(error);
}
+done:
Py_DECREF(args);
Py_DECREF(kwargs);
-
return NULL;
}
if (obj) {
if (PyFile_WriteString("Exception ignored in: ", f) < 0)
goto done;
- if (PyFile_WriteObject(obj, f, 0) < 0)
- goto done;
+ if (PyFile_WriteObject(obj, f, 0) < 0) {
+ PyErr_Clear();
+ if (PyFile_WriteString("<object repr() failed>", f) < 0) {
+ goto done;
+ }
+ }
if (PyFile_WriteString("\n", f) < 0)
goto done;
}
if (v && v != Py_None) {
if (PyFile_WriteString(": ", f) < 0)
goto done;
- if (PyFile_WriteObject(v, f, Py_PRINT_RAW) < 0)
- goto done;
+ if (PyFile_WriteObject(v, f, Py_PRINT_RAW) < 0) {
+ PyErr_Clear();
+ if (PyFile_WriteString("<exception str() failed>", f) < 0) {
+ goto done;
+ }
+ }
}
if (PyFile_WriteString("\n", f) < 0)
goto done;
#endif
error:
- /* if an error occured, force the ASCII encoding */
+ /* if an error occurred, force the ASCII encoding */
return 1;
}
On Windows, use GetFileType() and GetFileInformationByHandle() which support
files larger than 2 GB. fstat() may fail with EOVERFLOW on files larger
- than 2 GB because the file size type is an signed 32-bit integer: see issue
+ than 2 GB because the file size type is a signed 32-bit integer: see issue
#23152.
On Windows, set the last Windows error and return nonzero on error. On
On Windows, use GetFileType() and GetFileInformationByHandle() which support
files larger than 2 GB. fstat() may fail with EOVERFLOW on files larger
- than 2 GB because the file size type is an signed 32-bit integer: see issue
+ than 2 GB because the file size type is a signed 32-bit integer: see issue
#23152.
Raise an exception and return -1 on error. On Windows, set the last Windows
return 0;
}
- if (errno != ENOTTY) {
+ if (errno != ENOTTY && errno != EACCES) {
if (raise)
PyErr_SetFromErrno(PyExc_OSError);
return -1;
/* Issue #22258: Here, ENOTTY means "Inappropriate ioctl for
device". The ioctl is declared but not supported by the kernel.
Remember that ioctl() doesn't work. It is the case on
- Illumos-based OS for example. */
+ Illumos-based OS for example.
+
+ Issue #27057: When SELinux policy disallows ioctl it will fail
+ with EACCES. While FIOCLEX is safe operation it may be
+ unavailable because ioctl was denied altogether.
+ This can be the case on Android. */
ioctl_works = 0;
}
/* fallback to fcntl() if ioctl() does not work */
else if (type == 'r')
type = 'g';
- /* Cast "type", because if we're in unicode we need to pass a
+ /* Cast "type", because if we're in unicode we need to pass an
8-bit char. This is safe, because we've restricted what "type"
can be. */
buf = PyOS_double_to_string(val, (char)type, precision, flags,
else if (type == 'r')
type = 'g';
- /* Cast "type", because if we're in unicode we need to pass a
+ /* Cast "type", because if we're in unicode we need to pass an
8-bit char. This is safe, because we've restricted what "type"
can be. */
re_buf = PyOS_double_to_string(re, (char)type, precision, flags,
flags, levels, msgbuf,
sizeof(msgbuf), &freelist);
if (msg) {
- seterror(i+1, msg, levels, fname, msg);
+ seterror(i+1, msg, levels, fname, message);
return cleanreturn(0, &freelist);
}
}
{
assert(expected != NULL);
assert(arg != NULL);
- PyOS_snprintf(msgbuf, bufsize,
- "must be %.50s, not %.50s", expected,
- arg == Py_None ? "None" : arg->ob_type->tp_name);
+ if (expected[0] == '(') {
+ PyOS_snprintf(msgbuf, bufsize,
+ "%.100s", expected);
+ }
+ else {
+ PyOS_snprintf(msgbuf, bufsize,
+ "must be %.50s, not %.50s", expected,
+ arg == Py_None ? "None" : arg->ob_type->tp_name);
+ }
return msgbuf;
}
if (PyLong_Check(arg))
ival = PyLong_AsUnsignedLongMask(arg);
else
- return converterr("integer<k>", arg, msgbuf, bufsize);
+ return converterr("int", arg, msgbuf, bufsize);
*p = ival;
break;
}
if (PyLong_Check(arg))
ival = PyLong_AsUnsignedLongLongMask(arg);
else
- return converterr("integer<K>", arg, msgbuf, bufsize);
+ return converterr("int", arg, msgbuf, bufsize);
*p = ival;
break;
}
} else {
if (size + 1 > BUFFER_LEN) {
Py_DECREF(s);
- return converterr(
- "(buffer overflow)",
- arg, msgbuf, bufsize);
+ PyErr_Format(PyExc_TypeError,
+ "encoded string too long "
+ "(%zd, maximum length %zd)",
+ (Py_ssize_t)size, (Py_ssize_t)(BUFFER_LEN-1));
+ RETURN_ERR_OCCURRED;
}
}
memcpy(*buffer, ptr, size+1);
if ((Py_ssize_t)strlen(ptr) != size) {
Py_DECREF(s);
return converterr(
- "encoded string without NULL bytes",
+ "encoded string without null bytes",
arg, msgbuf, bufsize);
}
*buffer = PyMem_NEW(char, size + 1);
if (*format != '*')
return converterr(
- "invalid use of 'w' format character",
+ "(invalid use of 'w' format character)",
arg, msgbuf, bufsize);
format++;
}
default:
- return converterr("impossible<bad format char>", arg, msgbuf, bufsize);
+ return converterr("(impossible<bad format char>)", arg, msgbuf, bufsize);
}
static const char cprt[] =
"\
-Copyright (c) 2001-2015 Python Software Foundation.\n\
+Copyright (c) 2001-2016 Python Software Foundation.\n\
All Rights Reserved.\n\
\n\
Copyright (c) 2000 BeOpen.com.\n\
PyObject *modules = PyImport_GetModuleDict();
PyObject *m;
- if ((m = PyDict_GetItem(modules, name)) != NULL &&
- PyModule_Check(m))
+ if ((m = PyDict_GetItemWithError(modules, name)) != NULL &&
+ PyModule_Check(m)) {
return m;
+ }
+ if (PyErr_Occurred()) {
+ return NULL;
+ }
m = PyModule_NewObject(name);
if (m == NULL)
return NULL;
1,12,2,22,1,13,1,3,1,13,1,13,4,9,2,12,
1,4,2,7,2,8,2,114,176,0,0,0,99,3,0,0,
0,0,0,0,0,4,0,0,0,4,0,0,0,67,0,0,
- 0,115,179,0,0,0,116,0,0,124,0,0,116,1,0,131,
+ 0,115,185,0,0,0,116,0,0,124,0,0,116,1,0,131,
2,0,115,42,0,116,2,0,100,1,0,106,3,0,116,4,
0,124,0,0,131,1,0,131,1,0,131,1,0,130,1,0,
124,2,0,100,2,0,107,0,0,114,66,0,116,5,0,100,
- 3,0,131,1,0,130,1,0,124,1,0,114,144,0,116,0,
- 0,124,1,0,116,1,0,131,2,0,115,102,0,116,2,0,
- 100,4,0,131,1,0,130,1,0,110,42,0,124,1,0,116,
- 6,0,106,7,0,107,7,0,114,144,0,100,5,0,125,3,
- 0,116,8,0,124,3,0,106,3,0,124,1,0,131,1,0,
- 131,1,0,130,1,0,124,0,0,12,114,175,0,124,2,0,
- 100,2,0,107,2,0,114,175,0,116,5,0,100,6,0,131,
- 1,0,130,1,0,100,7,0,83,41,8,122,28,86,101,114,
- 105,102,121,32,97,114,103,117,109,101,110,116,115,32,97,114,
- 101,32,34,115,97,110,101,34,46,122,31,109,111,100,117,108,
- 101,32,110,97,109,101,32,109,117,115,116,32,98,101,32,115,
- 116,114,44,32,110,111,116,32,123,125,114,33,0,0,0,122,
- 18,108,101,118,101,108,32,109,117,115,116,32,98,101,32,62,
- 61,32,48,122,31,95,95,112,97,99,107,97,103,101,95,95,
- 32,110,111,116,32,115,101,116,32,116,111,32,97,32,115,116,
- 114,105,110,103,122,61,80,97,114,101,110,116,32,109,111,100,
- 117,108,101,32,123,33,114,125,32,110,111,116,32,108,111,97,
- 100,101,100,44,32,99,97,110,110,111,116,32,112,101,114,102,
- 111,114,109,32,114,101,108,97,116,105,118,101,32,105,109,112,
- 111,114,116,122,17,69,109,112,116,121,32,109,111,100,117,108,
- 101,32,110,97,109,101,78,41,9,218,10,105,115,105,110,115,
- 116,97,110,99,101,218,3,115,116,114,218,9,84,121,112,101,
- 69,114,114,111,114,114,50,0,0,0,114,13,0,0,0,114,
- 168,0,0,0,114,14,0,0,0,114,21,0,0,0,218,11,
- 83,121,115,116,101,109,69,114,114,111,114,41,4,114,15,0,
- 0,0,114,169,0,0,0,114,170,0,0,0,114,147,0,0,
- 0,114,10,0,0,0,114,10,0,0,0,114,11,0,0,0,
- 218,13,95,115,97,110,105,116,121,95,99,104,101,99,107,151,
- 3,0,0,115,24,0,0,0,0,2,15,1,27,1,12,1,
- 12,1,6,1,15,1,15,1,15,1,6,2,21,1,19,1,
- 114,181,0,0,0,122,16,78,111,32,109,111,100,117,108,101,
- 32,110,97,109,101,100,32,122,4,123,33,114,125,99,2,0,
- 0,0,0,0,0,0,8,0,0,0,12,0,0,0,67,0,
- 0,0,115,40,1,0,0,100,0,0,125,2,0,124,0,0,
- 106,0,0,100,1,0,131,1,0,100,2,0,25,125,3,0,
- 124,3,0,114,175,0,124,3,0,116,1,0,106,2,0,107,
- 7,0,114,59,0,116,3,0,124,1,0,124,3,0,131,2,
- 0,1,124,0,0,116,1,0,106,2,0,107,6,0,114,85,
- 0,116,1,0,106,2,0,124,0,0,25,83,116,1,0,106,
- 2,0,124,3,0,25,125,4,0,121,13,0,124,4,0,106,
- 4,0,125,2,0,87,110,61,0,4,116,5,0,107,10,0,
- 114,174,0,1,1,1,116,6,0,100,3,0,23,106,7,0,
- 124,0,0,124,3,0,131,2,0,125,5,0,116,8,0,124,
- 5,0,100,4,0,124,0,0,131,1,1,100,0,0,130,2,
- 0,89,110,1,0,88,116,9,0,124,0,0,124,2,0,131,
- 2,0,125,6,0,124,6,0,100,0,0,107,8,0,114,232,
- 0,116,8,0,116,6,0,106,7,0,124,0,0,131,1,0,
- 100,4,0,124,0,0,131,1,1,130,1,0,110,12,0,116,
- 10,0,124,6,0,131,1,0,125,7,0,124,3,0,114,36,
- 1,116,1,0,106,2,0,124,3,0,25,125,4,0,116,11,
- 0,124,4,0,124,0,0,106,0,0,100,1,0,131,1,0,
- 100,5,0,25,124,7,0,131,3,0,1,124,7,0,83,41,
- 6,78,114,121,0,0,0,114,33,0,0,0,122,23,59,32,
- 123,33,114,125,32,105,115,32,110,111,116,32,97,32,112,97,
- 99,107,97,103,101,114,15,0,0,0,114,140,0,0,0,41,
- 12,114,122,0,0,0,114,14,0,0,0,114,21,0,0,0,
- 114,65,0,0,0,114,131,0,0,0,114,96,0,0,0,218,
- 8,95,69,82,82,95,77,83,71,114,50,0,0,0,114,77,
- 0,0,0,114,176,0,0,0,114,149,0,0,0,114,5,0,
- 0,0,41,8,114,15,0,0,0,218,7,105,109,112,111,114,
- 116,95,114,152,0,0,0,114,123,0,0,0,90,13,112,97,
- 114,101,110,116,95,109,111,100,117,108,101,114,147,0,0,0,
- 114,88,0,0,0,114,89,0,0,0,114,10,0,0,0,114,
- 10,0,0,0,114,11,0,0,0,218,23,95,102,105,110,100,
- 95,97,110,100,95,108,111,97,100,95,117,110,108,111,99,107,
- 101,100,171,3,0,0,115,42,0,0,0,0,1,6,1,19,
- 1,6,1,15,1,13,2,15,1,11,1,13,1,3,1,13,
- 1,13,1,22,1,26,1,15,1,12,1,30,2,12,1,6,
- 2,13,1,29,1,114,184,0,0,0,99,2,0,0,0,0,
- 0,0,0,2,0,0,0,10,0,0,0,67,0,0,0,115,
- 37,0,0,0,116,0,0,124,0,0,131,1,0,143,18,0,
- 1,116,1,0,124,0,0,124,1,0,131,2,0,83,87,100,
- 1,0,81,82,88,100,1,0,83,41,2,122,54,70,105,110,
- 100,32,97,110,100,32,108,111,97,100,32,116,104,101,32,109,
- 111,100,117,108,101,44,32,97,110,100,32,114,101,108,101,97,
- 115,101,32,116,104,101,32,105,109,112,111,114,116,32,108,111,
- 99,107,46,78,41,2,114,54,0,0,0,114,184,0,0,0,
- 41,2,114,15,0,0,0,114,183,0,0,0,114,10,0,0,
- 0,114,10,0,0,0,114,11,0,0,0,218,14,95,102,105,
- 110,100,95,97,110,100,95,108,111,97,100,198,3,0,0,115,
- 4,0,0,0,0,2,13,1,114,185,0,0,0,114,33,0,
- 0,0,99,3,0,0,0,0,0,0,0,5,0,0,0,4,
- 0,0,0,67,0,0,0,115,166,0,0,0,116,0,0,124,
- 0,0,124,1,0,124,2,0,131,3,0,1,124,2,0,100,
- 1,0,107,4,0,114,46,0,116,1,0,124,0,0,124,1,
- 0,124,2,0,131,3,0,125,0,0,116,2,0,106,3,0,
- 131,0,0,1,124,0,0,116,4,0,106,5,0,107,7,0,
- 114,84,0,116,6,0,124,0,0,116,7,0,131,2,0,83,
- 116,4,0,106,5,0,124,0,0,25,125,3,0,124,3,0,
- 100,2,0,107,8,0,114,152,0,116,2,0,106,8,0,131,
- 0,0,1,100,3,0,106,9,0,124,0,0,131,1,0,125,
- 4,0,116,10,0,124,4,0,100,4,0,124,0,0,131,1,
- 1,130,1,0,116,11,0,124,0,0,131,1,0,1,124,3,
- 0,83,41,5,97,50,1,0,0,73,109,112,111,114,116,32,
- 97,110,100,32,114,101,116,117,114,110,32,116,104,101,32,109,
- 111,100,117,108,101,32,98,97,115,101,100,32,111,110,32,105,
- 116,115,32,110,97,109,101,44,32,116,104,101,32,112,97,99,
- 107,97,103,101,32,116,104,101,32,99,97,108,108,32,105,115,
- 10,32,32,32,32,98,101,105,110,103,32,109,97,100,101,32,
- 102,114,111,109,44,32,97,110,100,32,116,104,101,32,108,101,
- 118,101,108,32,97,100,106,117,115,116,109,101,110,116,46,10,
- 10,32,32,32,32,84,104,105,115,32,102,117,110,99,116,105,
- 111,110,32,114,101,112,114,101,115,101,110,116,115,32,116,104,
- 101,32,103,114,101,97,116,101,115,116,32,99,111,109,109,111,
- 110,32,100,101,110,111,109,105,110,97,116,111,114,32,111,102,
- 32,102,117,110,99,116,105,111,110,97,108,105,116,121,10,32,
- 32,32,32,98,101,116,119,101,101,110,32,105,109,112,111,114,
- 116,95,109,111,100,117,108,101,32,97,110,100,32,95,95,105,
- 109,112,111,114,116,95,95,46,32,84,104,105,115,32,105,110,
- 99,108,117,100,101,115,32,115,101,116,116,105,110,103,32,95,
- 95,112,97,99,107,97,103,101,95,95,32,105,102,10,32,32,
- 32,32,116,104,101,32,108,111,97,100,101,114,32,100,105,100,
- 32,110,111,116,46,10,10,32,32,32,32,114,33,0,0,0,
- 78,122,40,105,109,112,111,114,116,32,111,102,32,123,125,32,
- 104,97,108,116,101,100,59,32,78,111,110,101,32,105,110,32,
- 115,121,115,46,109,111,100,117,108,101,115,114,15,0,0,0,
- 41,12,114,181,0,0,0,114,171,0,0,0,114,57,0,0,
- 0,114,145,0,0,0,114,14,0,0,0,114,21,0,0,0,
- 114,185,0,0,0,218,11,95,103,99,100,95,105,109,112,111,
- 114,116,114,58,0,0,0,114,50,0,0,0,114,77,0,0,
- 0,114,63,0,0,0,41,5,114,15,0,0,0,114,169,0,
- 0,0,114,170,0,0,0,114,89,0,0,0,114,74,0,0,
- 0,114,10,0,0,0,114,10,0,0,0,114,11,0,0,0,
- 114,186,0,0,0,204,3,0,0,115,28,0,0,0,0,9,
- 16,1,12,1,18,1,10,1,15,1,13,1,13,1,12,1,
- 10,1,6,1,9,1,18,1,10,1,114,186,0,0,0,99,
- 3,0,0,0,0,0,0,0,6,0,0,0,17,0,0,0,
- 67,0,0,0,115,239,0,0,0,116,0,0,124,0,0,100,
- 1,0,131,2,0,114,235,0,100,2,0,124,1,0,107,6,
- 0,114,83,0,116,1,0,124,1,0,131,1,0,125,1,0,
- 124,1,0,106,2,0,100,2,0,131,1,0,1,116,0,0,
- 124,0,0,100,3,0,131,2,0,114,83,0,124,1,0,106,
- 3,0,124,0,0,106,4,0,131,1,0,1,120,149,0,124,
- 1,0,68,93,141,0,125,3,0,116,0,0,124,0,0,124,
- 3,0,131,2,0,115,90,0,100,4,0,106,5,0,124,0,
- 0,106,6,0,124,3,0,131,2,0,125,4,0,121,17,0,
- 116,7,0,124,2,0,124,4,0,131,2,0,1,87,113,90,
- 0,4,116,8,0,107,10,0,114,230,0,1,125,5,0,1,
- 122,47,0,116,9,0,124,5,0,131,1,0,106,10,0,116,
- 11,0,131,1,0,114,209,0,124,5,0,106,12,0,124,4,
- 0,107,2,0,114,209,0,119,90,0,130,0,0,87,89,100,
- 5,0,100,5,0,125,5,0,126,5,0,88,113,90,0,88,
- 113,90,0,87,124,0,0,83,41,6,122,238,70,105,103,117,
- 114,101,32,111,117,116,32,119,104,97,116,32,95,95,105,109,
- 112,111,114,116,95,95,32,115,104,111,117,108,100,32,114,101,
- 116,117,114,110,46,10,10,32,32,32,32,84,104,101,32,105,
- 109,112,111,114,116,95,32,112,97,114,97,109,101,116,101,114,
- 32,105,115,32,97,32,99,97,108,108,97,98,108,101,32,119,
- 104,105,99,104,32,116,97,107,101,115,32,116,104,101,32,110,
- 97,109,101,32,111,102,32,109,111,100,117,108,101,32,116,111,
- 10,32,32,32,32,105,109,112,111,114,116,46,32,73,116,32,
- 105,115,32,114,101,113,117,105,114,101,100,32,116,111,32,100,
- 101,99,111,117,112,108,101,32,116,104,101,32,102,117,110,99,
- 116,105,111,110,32,102,114,111,109,32,97,115,115,117,109,105,
- 110,103,32,105,109,112,111,114,116,108,105,98,39,115,10,32,
- 32,32,32,105,109,112,111,114,116,32,105,109,112,108,101,109,
- 101,110,116,97,116,105,111,110,32,105,115,32,100,101,115,105,
- 114,101,100,46,10,10,32,32,32,32,114,131,0,0,0,250,
- 1,42,218,7,95,95,97,108,108,95,95,122,5,123,125,46,
- 123,125,78,41,13,114,4,0,0,0,114,130,0,0,0,218,
- 6,114,101,109,111,118,101,218,6,101,120,116,101,110,100,114,
- 188,0,0,0,114,50,0,0,0,114,1,0,0,0,114,65,
- 0,0,0,114,77,0,0,0,114,178,0,0,0,114,71,0,
- 0,0,218,15,95,69,82,82,95,77,83,71,95,80,82,69,
- 70,73,88,114,15,0,0,0,41,6,114,89,0,0,0,218,
- 8,102,114,111,109,108,105,115,116,114,183,0,0,0,218,1,
- 120,90,9,102,114,111,109,95,110,97,109,101,90,3,101,120,
- 99,114,10,0,0,0,114,10,0,0,0,114,11,0,0,0,
- 218,16,95,104,97,110,100,108,101,95,102,114,111,109,108,105,
- 115,116,228,3,0,0,115,34,0,0,0,0,10,15,1,12,
- 1,12,1,13,1,15,1,16,1,13,1,15,1,21,1,3,
- 1,17,1,18,4,21,1,15,1,3,1,26,1,114,194,0,
- 0,0,99,1,0,0,0,0,0,0,0,2,0,0,0,2,
- 0,0,0,67,0,0,0,115,72,0,0,0,124,0,0,106,
- 0,0,100,1,0,131,1,0,125,1,0,124,1,0,100,2,
- 0,107,8,0,114,68,0,124,0,0,100,3,0,25,125,1,
- 0,100,4,0,124,0,0,107,7,0,114,68,0,124,1,0,
- 106,1,0,100,5,0,131,1,0,100,6,0,25,125,1,0,
- 124,1,0,83,41,7,122,167,67,97,108,99,117,108,97,116,
- 101,32,119,104,97,116,32,95,95,112,97,99,107,97,103,101,
- 95,95,32,115,104,111,117,108,100,32,98,101,46,10,10,32,
- 32,32,32,95,95,112,97,99,107,97,103,101,95,95,32,105,
- 115,32,110,111,116,32,103,117,97,114,97,110,116,101,101,100,
- 32,116,111,32,98,101,32,100,101,102,105,110,101,100,32,111,
- 114,32,99,111,117,108,100,32,98,101,32,115,101,116,32,116,
- 111,32,78,111,110,101,10,32,32,32,32,116,111,32,114,101,
- 112,114,101,115,101,110,116,32,116,104,97,116,32,105,116,115,
- 32,112,114,111,112,101,114,32,118,97,108,117,101,32,105,115,
- 32,117,110,107,110,111,119,110,46,10,10,32,32,32,32,114,
- 134,0,0,0,78,114,1,0,0,0,114,131,0,0,0,114,
- 121,0,0,0,114,33,0,0,0,41,2,114,42,0,0,0,
- 114,122,0,0,0,41,2,218,7,103,108,111,98,97,108,115,
- 114,169,0,0,0,114,10,0,0,0,114,10,0,0,0,114,
- 11,0,0,0,218,17,95,99,97,108,99,95,95,95,112,97,
- 99,107,97,103,101,95,95,4,4,0,0,115,12,0,0,0,
- 0,7,15,1,12,1,10,1,12,1,19,1,114,196,0,0,
- 0,99,5,0,0,0,0,0,0,0,9,0,0,0,5,0,
- 0,0,67,0,0,0,115,227,0,0,0,124,4,0,100,1,
- 0,107,2,0,114,27,0,116,0,0,124,0,0,131,1,0,
- 125,5,0,110,54,0,124,1,0,100,2,0,107,9,0,114,
- 45,0,124,1,0,110,3,0,105,0,0,125,6,0,116,1,
- 0,124,6,0,131,1,0,125,7,0,116,0,0,124,0,0,
- 124,7,0,124,4,0,131,3,0,125,5,0,124,3,0,115,
- 207,0,124,4,0,100,1,0,107,2,0,114,122,0,116,0,
+ 3,0,131,1,0,130,1,0,124,2,0,100,2,0,107,4,
+ 0,114,150,0,116,0,0,124,1,0,116,1,0,131,2,0,
+ 115,108,0,116,2,0,100,4,0,131,1,0,130,1,0,110,
+ 42,0,124,1,0,116,6,0,106,7,0,107,7,0,114,150,
+ 0,100,5,0,125,3,0,116,8,0,124,3,0,106,3,0,
+ 124,1,0,131,1,0,131,1,0,130,1,0,124,0,0,12,
+ 114,181,0,124,2,0,100,2,0,107,2,0,114,181,0,116,
+ 5,0,100,6,0,131,1,0,130,1,0,100,7,0,83,41,
+ 8,122,28,86,101,114,105,102,121,32,97,114,103,117,109,101,
+ 110,116,115,32,97,114,101,32,34,115,97,110,101,34,46,122,
+ 31,109,111,100,117,108,101,32,110,97,109,101,32,109,117,115,
+ 116,32,98,101,32,115,116,114,44,32,110,111,116,32,123,125,
+ 114,33,0,0,0,122,18,108,101,118,101,108,32,109,117,115,
+ 116,32,98,101,32,62,61,32,48,122,31,95,95,112,97,99,
+ 107,97,103,101,95,95,32,110,111,116,32,115,101,116,32,116,
+ 111,32,97,32,115,116,114,105,110,103,122,61,80,97,114,101,
+ 110,116,32,109,111,100,117,108,101,32,123,33,114,125,32,110,
+ 111,116,32,108,111,97,100,101,100,44,32,99,97,110,110,111,
+ 116,32,112,101,114,102,111,114,109,32,114,101,108,97,116,105,
+ 118,101,32,105,109,112,111,114,116,122,17,69,109,112,116,121,
+ 32,109,111,100,117,108,101,32,110,97,109,101,78,41,9,218,
+ 10,105,115,105,110,115,116,97,110,99,101,218,3,115,116,114,
+ 218,9,84,121,112,101,69,114,114,111,114,114,50,0,0,0,
+ 114,13,0,0,0,114,168,0,0,0,114,14,0,0,0,114,
+ 21,0,0,0,218,11,83,121,115,116,101,109,69,114,114,111,
+ 114,41,4,114,15,0,0,0,114,169,0,0,0,114,170,0,
+ 0,0,114,147,0,0,0,114,10,0,0,0,114,10,0,0,
+ 0,114,11,0,0,0,218,13,95,115,97,110,105,116,121,95,
+ 99,104,101,99,107,151,3,0,0,115,24,0,0,0,0,2,
+ 15,1,27,1,12,1,12,1,12,1,15,1,15,1,15,1,
+ 6,2,21,1,19,1,114,181,0,0,0,122,16,78,111,32,
+ 109,111,100,117,108,101,32,110,97,109,101,100,32,122,4,123,
+ 33,114,125,99,2,0,0,0,0,0,0,0,8,0,0,0,
+ 12,0,0,0,67,0,0,0,115,40,1,0,0,100,0,0,
+ 125,2,0,124,0,0,106,0,0,100,1,0,131,1,0,100,
+ 2,0,25,125,3,0,124,3,0,114,175,0,124,3,0,116,
+ 1,0,106,2,0,107,7,0,114,59,0,116,3,0,124,1,
+ 0,124,3,0,131,2,0,1,124,0,0,116,1,0,106,2,
+ 0,107,6,0,114,85,0,116,1,0,106,2,0,124,0,0,
+ 25,83,116,1,0,106,2,0,124,3,0,25,125,4,0,121,
+ 13,0,124,4,0,106,4,0,125,2,0,87,110,61,0,4,
+ 116,5,0,107,10,0,114,174,0,1,1,1,116,6,0,100,
+ 3,0,23,106,7,0,124,0,0,124,3,0,131,2,0,125,
+ 5,0,116,8,0,124,5,0,100,4,0,124,0,0,131,1,
+ 1,100,0,0,130,2,0,89,110,1,0,88,116,9,0,124,
+ 0,0,124,2,0,131,2,0,125,6,0,124,6,0,100,0,
+ 0,107,8,0,114,232,0,116,8,0,116,6,0,106,7,0,
+ 124,0,0,131,1,0,100,4,0,124,0,0,131,1,1,130,
+ 1,0,110,12,0,116,10,0,124,6,0,131,1,0,125,7,
+ 0,124,3,0,114,36,1,116,1,0,106,2,0,124,3,0,
+ 25,125,4,0,116,11,0,124,4,0,124,0,0,106,0,0,
+ 100,1,0,131,1,0,100,5,0,25,124,7,0,131,3,0,
+ 1,124,7,0,83,41,6,78,114,121,0,0,0,114,33,0,
+ 0,0,122,23,59,32,123,33,114,125,32,105,115,32,110,111,
+ 116,32,97,32,112,97,99,107,97,103,101,114,15,0,0,0,
+ 114,140,0,0,0,41,12,114,122,0,0,0,114,14,0,0,
+ 0,114,21,0,0,0,114,65,0,0,0,114,131,0,0,0,
+ 114,96,0,0,0,218,8,95,69,82,82,95,77,83,71,114,
+ 50,0,0,0,114,77,0,0,0,114,176,0,0,0,114,149,
+ 0,0,0,114,5,0,0,0,41,8,114,15,0,0,0,218,
+ 7,105,109,112,111,114,116,95,114,152,0,0,0,114,123,0,
+ 0,0,90,13,112,97,114,101,110,116,95,109,111,100,117,108,
+ 101,114,147,0,0,0,114,88,0,0,0,114,89,0,0,0,
+ 114,10,0,0,0,114,10,0,0,0,114,11,0,0,0,218,
+ 23,95,102,105,110,100,95,97,110,100,95,108,111,97,100,95,
+ 117,110,108,111,99,107,101,100,171,3,0,0,115,42,0,0,
+ 0,0,1,6,1,19,1,6,1,15,1,13,2,15,1,11,
+ 1,13,1,3,1,13,1,13,1,22,1,26,1,15,1,12,
+ 1,30,2,12,1,6,2,13,1,29,1,114,184,0,0,0,
+ 99,2,0,0,0,0,0,0,0,2,0,0,0,10,0,0,
+ 0,67,0,0,0,115,37,0,0,0,116,0,0,124,0,0,
+ 131,1,0,143,18,0,1,116,1,0,124,0,0,124,1,0,
+ 131,2,0,83,87,100,1,0,81,82,88,100,1,0,83,41,
+ 2,122,54,70,105,110,100,32,97,110,100,32,108,111,97,100,
+ 32,116,104,101,32,109,111,100,117,108,101,44,32,97,110,100,
+ 32,114,101,108,101,97,115,101,32,116,104,101,32,105,109,112,
+ 111,114,116,32,108,111,99,107,46,78,41,2,114,54,0,0,
+ 0,114,184,0,0,0,41,2,114,15,0,0,0,114,183,0,
+ 0,0,114,10,0,0,0,114,10,0,0,0,114,11,0,0,
+ 0,218,14,95,102,105,110,100,95,97,110,100,95,108,111,97,
+ 100,198,3,0,0,115,4,0,0,0,0,2,13,1,114,185,
+ 0,0,0,114,33,0,0,0,99,3,0,0,0,0,0,0,
+ 0,5,0,0,0,4,0,0,0,67,0,0,0,115,166,0,
+ 0,0,116,0,0,124,0,0,124,1,0,124,2,0,131,3,
+ 0,1,124,2,0,100,1,0,107,4,0,114,46,0,116,1,
+ 0,124,0,0,124,1,0,124,2,0,131,3,0,125,0,0,
+ 116,2,0,106,3,0,131,0,0,1,124,0,0,116,4,0,
+ 106,5,0,107,7,0,114,84,0,116,6,0,124,0,0,116,
+ 7,0,131,2,0,83,116,4,0,106,5,0,124,0,0,25,
+ 125,3,0,124,3,0,100,2,0,107,8,0,114,152,0,116,
+ 2,0,106,8,0,131,0,0,1,100,3,0,106,9,0,124,
+ 0,0,131,1,0,125,4,0,116,10,0,124,4,0,100,4,
+ 0,124,0,0,131,1,1,130,1,0,116,11,0,124,0,0,
+ 131,1,0,1,124,3,0,83,41,5,97,50,1,0,0,73,
+ 109,112,111,114,116,32,97,110,100,32,114,101,116,117,114,110,
+ 32,116,104,101,32,109,111,100,117,108,101,32,98,97,115,101,
+ 100,32,111,110,32,105,116,115,32,110,97,109,101,44,32,116,
+ 104,101,32,112,97,99,107,97,103,101,32,116,104,101,32,99,
+ 97,108,108,32,105,115,10,32,32,32,32,98,101,105,110,103,
+ 32,109,97,100,101,32,102,114,111,109,44,32,97,110,100,32,
+ 116,104,101,32,108,101,118,101,108,32,97,100,106,117,115,116,
+ 109,101,110,116,46,10,10,32,32,32,32,84,104,105,115,32,
+ 102,117,110,99,116,105,111,110,32,114,101,112,114,101,115,101,
+ 110,116,115,32,116,104,101,32,103,114,101,97,116,101,115,116,
+ 32,99,111,109,109,111,110,32,100,101,110,111,109,105,110,97,
+ 116,111,114,32,111,102,32,102,117,110,99,116,105,111,110,97,
+ 108,105,116,121,10,32,32,32,32,98,101,116,119,101,101,110,
+ 32,105,109,112,111,114,116,95,109,111,100,117,108,101,32,97,
+ 110,100,32,95,95,105,109,112,111,114,116,95,95,46,32,84,
+ 104,105,115,32,105,110,99,108,117,100,101,115,32,115,101,116,
+ 116,105,110,103,32,95,95,112,97,99,107,97,103,101,95,95,
+ 32,105,102,10,32,32,32,32,116,104,101,32,108,111,97,100,
+ 101,114,32,100,105,100,32,110,111,116,46,10,10,32,32,32,
+ 32,114,33,0,0,0,78,122,40,105,109,112,111,114,116,32,
+ 111,102,32,123,125,32,104,97,108,116,101,100,59,32,78,111,
+ 110,101,32,105,110,32,115,121,115,46,109,111,100,117,108,101,
+ 115,114,15,0,0,0,41,12,114,181,0,0,0,114,171,0,
+ 0,0,114,57,0,0,0,114,145,0,0,0,114,14,0,0,
+ 0,114,21,0,0,0,114,185,0,0,0,218,11,95,103,99,
+ 100,95,105,109,112,111,114,116,114,58,0,0,0,114,50,0,
+ 0,0,114,77,0,0,0,114,63,0,0,0,41,5,114,15,
+ 0,0,0,114,169,0,0,0,114,170,0,0,0,114,89,0,
+ 0,0,114,74,0,0,0,114,10,0,0,0,114,10,0,0,
+ 0,114,11,0,0,0,114,186,0,0,0,204,3,0,0,115,
+ 28,0,0,0,0,9,16,1,12,1,18,1,10,1,15,1,
+ 13,1,13,1,12,1,10,1,6,1,9,1,18,1,10,1,
+ 114,186,0,0,0,99,3,0,0,0,0,0,0,0,6,0,
+ 0,0,17,0,0,0,67,0,0,0,115,239,0,0,0,116,
+ 0,0,124,0,0,100,1,0,131,2,0,114,235,0,100,2,
+ 0,124,1,0,107,6,0,114,83,0,116,1,0,124,1,0,
+ 131,1,0,125,1,0,124,1,0,106,2,0,100,2,0,131,
+ 1,0,1,116,0,0,124,0,0,100,3,0,131,2,0,114,
+ 83,0,124,1,0,106,3,0,124,0,0,106,4,0,131,1,
+ 0,1,120,149,0,124,1,0,68,93,141,0,125,3,0,116,
+ 0,0,124,0,0,124,3,0,131,2,0,115,90,0,100,4,
+ 0,106,5,0,124,0,0,106,6,0,124,3,0,131,2,0,
+ 125,4,0,121,17,0,116,7,0,124,2,0,124,4,0,131,
+ 2,0,1,87,113,90,0,4,116,8,0,107,10,0,114,230,
+ 0,1,125,5,0,1,122,47,0,116,9,0,124,5,0,131,
+ 1,0,106,10,0,116,11,0,131,1,0,114,209,0,124,5,
+ 0,106,12,0,124,4,0,107,2,0,114,209,0,119,90,0,
+ 130,0,0,87,89,100,5,0,100,5,0,125,5,0,126,5,
+ 0,88,113,90,0,88,113,90,0,87,124,0,0,83,41,6,
+ 122,238,70,105,103,117,114,101,32,111,117,116,32,119,104,97,
+ 116,32,95,95,105,109,112,111,114,116,95,95,32,115,104,111,
+ 117,108,100,32,114,101,116,117,114,110,46,10,10,32,32,32,
+ 32,84,104,101,32,105,109,112,111,114,116,95,32,112,97,114,
+ 97,109,101,116,101,114,32,105,115,32,97,32,99,97,108,108,
+ 97,98,108,101,32,119,104,105,99,104,32,116,97,107,101,115,
+ 32,116,104,101,32,110,97,109,101,32,111,102,32,109,111,100,
+ 117,108,101,32,116,111,10,32,32,32,32,105,109,112,111,114,
+ 116,46,32,73,116,32,105,115,32,114,101,113,117,105,114,101,
+ 100,32,116,111,32,100,101,99,111,117,112,108,101,32,116,104,
+ 101,32,102,117,110,99,116,105,111,110,32,102,114,111,109,32,
+ 97,115,115,117,109,105,110,103,32,105,109,112,111,114,116,108,
+ 105,98,39,115,10,32,32,32,32,105,109,112,111,114,116,32,
+ 105,109,112,108,101,109,101,110,116,97,116,105,111,110,32,105,
+ 115,32,100,101,115,105,114,101,100,46,10,10,32,32,32,32,
+ 114,131,0,0,0,250,1,42,218,7,95,95,97,108,108,95,
+ 95,122,5,123,125,46,123,125,78,41,13,114,4,0,0,0,
+ 114,130,0,0,0,218,6,114,101,109,111,118,101,218,6,101,
+ 120,116,101,110,100,114,188,0,0,0,114,50,0,0,0,114,
+ 1,0,0,0,114,65,0,0,0,114,77,0,0,0,114,178,
+ 0,0,0,114,71,0,0,0,218,15,95,69,82,82,95,77,
+ 83,71,95,80,82,69,70,73,88,114,15,0,0,0,41,6,
+ 114,89,0,0,0,218,8,102,114,111,109,108,105,115,116,114,
+ 183,0,0,0,218,1,120,90,9,102,114,111,109,95,110,97,
+ 109,101,90,3,101,120,99,114,10,0,0,0,114,10,0,0,
+ 0,114,11,0,0,0,218,16,95,104,97,110,100,108,101,95,
+ 102,114,111,109,108,105,115,116,228,3,0,0,115,34,0,0,
+ 0,0,10,15,1,12,1,12,1,13,1,15,1,16,1,13,
+ 1,15,1,21,1,3,1,17,1,18,4,21,1,15,1,3,
+ 1,26,1,114,194,0,0,0,99,1,0,0,0,0,0,0,
+ 0,2,0,0,0,2,0,0,0,67,0,0,0,115,72,0,
+ 0,0,124,0,0,106,0,0,100,1,0,131,1,0,125,1,
+ 0,124,1,0,100,2,0,107,8,0,114,68,0,124,0,0,
+ 100,3,0,25,125,1,0,100,4,0,124,0,0,107,7,0,
+ 114,68,0,124,1,0,106,1,0,100,5,0,131,1,0,100,
+ 6,0,25,125,1,0,124,1,0,83,41,7,122,167,67,97,
+ 108,99,117,108,97,116,101,32,119,104,97,116,32,95,95,112,
+ 97,99,107,97,103,101,95,95,32,115,104,111,117,108,100,32,
+ 98,101,46,10,10,32,32,32,32,95,95,112,97,99,107,97,
+ 103,101,95,95,32,105,115,32,110,111,116,32,103,117,97,114,
+ 97,110,116,101,101,100,32,116,111,32,98,101,32,100,101,102,
+ 105,110,101,100,32,111,114,32,99,111,117,108,100,32,98,101,
+ 32,115,101,116,32,116,111,32,78,111,110,101,10,32,32,32,
+ 32,116,111,32,114,101,112,114,101,115,101,110,116,32,116,104,
+ 97,116,32,105,116,115,32,112,114,111,112,101,114,32,118,97,
+ 108,117,101,32,105,115,32,117,110,107,110,111,119,110,46,10,
+ 10,32,32,32,32,114,134,0,0,0,78,114,1,0,0,0,
+ 114,131,0,0,0,114,121,0,0,0,114,33,0,0,0,41,
+ 2,114,42,0,0,0,114,122,0,0,0,41,2,218,7,103,
+ 108,111,98,97,108,115,114,169,0,0,0,114,10,0,0,0,
+ 114,10,0,0,0,114,11,0,0,0,218,17,95,99,97,108,
+ 99,95,95,95,112,97,99,107,97,103,101,95,95,4,4,0,
+ 0,115,12,0,0,0,0,7,15,1,12,1,10,1,12,1,
+ 19,1,114,196,0,0,0,99,5,0,0,0,0,0,0,0,
+ 9,0,0,0,5,0,0,0,67,0,0,0,115,227,0,0,
+ 0,124,4,0,100,1,0,107,2,0,114,27,0,116,0,0,
+ 124,0,0,131,1,0,125,5,0,110,54,0,124,1,0,100,
+ 2,0,107,9,0,114,45,0,124,1,0,110,3,0,105,0,
+ 0,125,6,0,116,1,0,124,6,0,131,1,0,125,7,0,
+ 116,0,0,124,0,0,124,7,0,124,4,0,131,3,0,125,
+ 5,0,124,3,0,115,207,0,124,4,0,100,1,0,107,2,
+ 0,114,122,0,116,0,0,124,0,0,106,2,0,100,3,0,
+ 131,1,0,100,1,0,25,131,1,0,83,124,0,0,115,132,
+ 0,124,5,0,83,116,3,0,124,0,0,131,1,0,116,3,
0,124,0,0,106,2,0,100,3,0,131,1,0,100,1,0,
- 25,131,1,0,83,124,0,0,115,132,0,124,5,0,83,116,
- 3,0,124,0,0,131,1,0,116,3,0,124,0,0,106,2,
- 0,100,3,0,131,1,0,100,1,0,25,131,1,0,24,125,
- 8,0,116,4,0,106,5,0,124,5,0,106,6,0,100,2,
- 0,116,3,0,124,5,0,106,6,0,131,1,0,124,8,0,
- 24,133,2,0,25,25,83,110,16,0,116,7,0,124,5,0,
- 124,3,0,116,0,0,131,3,0,83,100,2,0,83,41,4,
- 97,214,1,0,0,73,109,112,111,114,116,32,97,32,109,111,
- 100,117,108,101,46,10,10,32,32,32,32,84,104,101,32,39,
- 103,108,111,98,97,108,115,39,32,97,114,103,117,109,101,110,
- 116,32,105,115,32,117,115,101,100,32,116,111,32,105,110,102,
- 101,114,32,119,104,101,114,101,32,116,104,101,32,105,109,112,
- 111,114,116,32,105,115,32,111,99,99,117,114,105,110,103,32,
- 102,114,111,109,10,32,32,32,32,116,111,32,104,97,110,100,
- 108,101,32,114,101,108,97,116,105,118,101,32,105,109,112,111,
- 114,116,115,46,32,84,104,101,32,39,108,111,99,97,108,115,
- 39,32,97,114,103,117,109,101,110,116,32,105,115,32,105,103,
- 110,111,114,101,100,46,32,84,104,101,10,32,32,32,32,39,
- 102,114,111,109,108,105,115,116,39,32,97,114,103,117,109,101,
- 110,116,32,115,112,101,99,105,102,105,101,115,32,119,104,97,
- 116,32,115,104,111,117,108,100,32,101,120,105,115,116,32,97,
- 115,32,97,116,116,114,105,98,117,116,101,115,32,111,110,32,
- 116,104,101,32,109,111,100,117,108,101,10,32,32,32,32,98,
- 101,105,110,103,32,105,109,112,111,114,116,101,100,32,40,101,
- 46,103,46,32,96,96,102,114,111,109,32,109,111,100,117,108,
- 101,32,105,109,112,111,114,116,32,60,102,114,111,109,108,105,
- 115,116,62,96,96,41,46,32,32,84,104,101,32,39,108,101,
- 118,101,108,39,10,32,32,32,32,97,114,103,117,109,101,110,
- 116,32,114,101,112,114,101,115,101,110,116,115,32,116,104,101,
- 32,112,97,99,107,97,103,101,32,108,111,99,97,116,105,111,
- 110,32,116,111,32,105,109,112,111,114,116,32,102,114,111,109,
- 32,105,110,32,97,32,114,101,108,97,116,105,118,101,10,32,
- 32,32,32,105,109,112,111,114,116,32,40,101,46,103,46,32,
- 96,96,102,114,111,109,32,46,46,112,107,103,32,105,109,112,
- 111,114,116,32,109,111,100,96,96,32,119,111,117,108,100,32,
- 104,97,118,101,32,97,32,39,108,101,118,101,108,39,32,111,
- 102,32,50,41,46,10,10,32,32,32,32,114,33,0,0,0,
- 78,114,121,0,0,0,41,8,114,186,0,0,0,114,196,0,
- 0,0,218,9,112,97,114,116,105,116,105,111,110,114,167,0,
- 0,0,114,14,0,0,0,114,21,0,0,0,114,1,0,0,
- 0,114,194,0,0,0,41,9,114,15,0,0,0,114,195,0,
- 0,0,218,6,108,111,99,97,108,115,114,192,0,0,0,114,
- 170,0,0,0,114,89,0,0,0,90,8,103,108,111,98,97,
- 108,115,95,114,169,0,0,0,90,7,99,117,116,95,111,102,
- 102,114,10,0,0,0,114,10,0,0,0,114,11,0,0,0,
- 218,10,95,95,105,109,112,111,114,116,95,95,19,4,0,0,
- 115,26,0,0,0,0,11,12,1,15,2,24,1,12,1,18,
- 1,6,3,12,1,23,1,6,1,4,4,35,3,40,2,114,
- 199,0,0,0,99,1,0,0,0,0,0,0,0,2,0,0,
- 0,3,0,0,0,67,0,0,0,115,53,0,0,0,116,0,
- 0,106,1,0,124,0,0,131,1,0,125,1,0,124,1,0,
- 100,0,0,107,8,0,114,43,0,116,2,0,100,1,0,124,
- 0,0,23,131,1,0,130,1,0,116,3,0,124,1,0,131,
- 1,0,83,41,2,78,122,25,110,111,32,98,117,105,108,116,
- 45,105,110,32,109,111,100,117,108,101,32,110,97,109,101,100,
- 32,41,4,114,150,0,0,0,114,154,0,0,0,114,77,0,
- 0,0,114,149,0,0,0,41,2,114,15,0,0,0,114,88,
+ 25,131,1,0,24,125,8,0,116,4,0,106,5,0,124,5,
+ 0,106,6,0,100,2,0,116,3,0,124,5,0,106,6,0,
+ 131,1,0,124,8,0,24,133,2,0,25,25,83,110,16,0,
+ 116,7,0,124,5,0,124,3,0,116,0,0,131,3,0,83,
+ 100,2,0,83,41,4,97,215,1,0,0,73,109,112,111,114,
+ 116,32,97,32,109,111,100,117,108,101,46,10,10,32,32,32,
+ 32,84,104,101,32,39,103,108,111,98,97,108,115,39,32,97,
+ 114,103,117,109,101,110,116,32,105,115,32,117,115,101,100,32,
+ 116,111,32,105,110,102,101,114,32,119,104,101,114,101,32,116,
+ 104,101,32,105,109,112,111,114,116,32,105,115,32,111,99,99,
+ 117,114,114,105,110,103,32,102,114,111,109,10,32,32,32,32,
+ 116,111,32,104,97,110,100,108,101,32,114,101,108,97,116,105,
+ 118,101,32,105,109,112,111,114,116,115,46,32,84,104,101,32,
+ 39,108,111,99,97,108,115,39,32,97,114,103,117,109,101,110,
+ 116,32,105,115,32,105,103,110,111,114,101,100,46,32,84,104,
+ 101,10,32,32,32,32,39,102,114,111,109,108,105,115,116,39,
+ 32,97,114,103,117,109,101,110,116,32,115,112,101,99,105,102,
+ 105,101,115,32,119,104,97,116,32,115,104,111,117,108,100,32,
+ 101,120,105,115,116,32,97,115,32,97,116,116,114,105,98,117,
+ 116,101,115,32,111,110,32,116,104,101,32,109,111,100,117,108,
+ 101,10,32,32,32,32,98,101,105,110,103,32,105,109,112,111,
+ 114,116,101,100,32,40,101,46,103,46,32,96,96,102,114,111,
+ 109,32,109,111,100,117,108,101,32,105,109,112,111,114,116,32,
+ 60,102,114,111,109,108,105,115,116,62,96,96,41,46,32,32,
+ 84,104,101,32,39,108,101,118,101,108,39,10,32,32,32,32,
+ 97,114,103,117,109,101,110,116,32,114,101,112,114,101,115,101,
+ 110,116,115,32,116,104,101,32,112,97,99,107,97,103,101,32,
+ 108,111,99,97,116,105,111,110,32,116,111,32,105,109,112,111,
+ 114,116,32,102,114,111,109,32,105,110,32,97,32,114,101,108,
+ 97,116,105,118,101,10,32,32,32,32,105,109,112,111,114,116,
+ 32,40,101,46,103,46,32,96,96,102,114,111,109,32,46,46,
+ 112,107,103,32,105,109,112,111,114,116,32,109,111,100,96,96,
+ 32,119,111,117,108,100,32,104,97,118,101,32,97,32,39,108,
+ 101,118,101,108,39,32,111,102,32,50,41,46,10,10,32,32,
+ 32,32,114,33,0,0,0,78,114,121,0,0,0,41,8,114,
+ 186,0,0,0,114,196,0,0,0,218,9,112,97,114,116,105,
+ 116,105,111,110,114,167,0,0,0,114,14,0,0,0,114,21,
+ 0,0,0,114,1,0,0,0,114,194,0,0,0,41,9,114,
+ 15,0,0,0,114,195,0,0,0,218,6,108,111,99,97,108,
+ 115,114,192,0,0,0,114,170,0,0,0,114,89,0,0,0,
+ 90,8,103,108,111,98,97,108,115,95,114,169,0,0,0,90,
+ 7,99,117,116,95,111,102,102,114,10,0,0,0,114,10,0,
+ 0,0,114,11,0,0,0,218,10,95,95,105,109,112,111,114,
+ 116,95,95,19,4,0,0,115,26,0,0,0,0,11,12,1,
+ 15,2,24,1,12,1,18,1,6,3,12,1,23,1,6,1,
+ 4,4,35,3,40,2,114,199,0,0,0,99,1,0,0,0,
+ 0,0,0,0,2,0,0,0,3,0,0,0,67,0,0,0,
+ 115,53,0,0,0,116,0,0,106,1,0,124,0,0,131,1,
+ 0,125,1,0,124,1,0,100,0,0,107,8,0,114,43,0,
+ 116,2,0,100,1,0,124,0,0,23,131,1,0,130,1,0,
+ 116,3,0,124,1,0,131,1,0,83,41,2,78,122,25,110,
+ 111,32,98,117,105,108,116,45,105,110,32,109,111,100,117,108,
+ 101,32,110,97,109,101,100,32,41,4,114,150,0,0,0,114,
+ 154,0,0,0,114,77,0,0,0,114,149,0,0,0,41,2,
+ 114,15,0,0,0,114,88,0,0,0,114,10,0,0,0,114,
+ 10,0,0,0,114,11,0,0,0,218,18,95,98,117,105,108,
+ 116,105,110,95,102,114,111,109,95,110,97,109,101,54,4,0,
+ 0,115,8,0,0,0,0,1,15,1,12,1,16,1,114,200,
+ 0,0,0,99,2,0,0,0,0,0,0,0,12,0,0,0,
+ 12,0,0,0,67,0,0,0,115,74,1,0,0,124,1,0,
+ 97,0,0,124,0,0,97,1,0,116,2,0,116,1,0,131,
+ 1,0,125,2,0,120,123,0,116,1,0,106,3,0,106,4,
+ 0,131,0,0,68,93,106,0,92,2,0,125,3,0,125,4,
+ 0,116,5,0,124,4,0,124,2,0,131,2,0,114,40,0,
+ 124,3,0,116,1,0,106,6,0,107,6,0,114,91,0,116,
+ 7,0,125,5,0,110,27,0,116,0,0,106,8,0,124,3,
+ 0,131,1,0,114,40,0,116,9,0,125,5,0,110,3,0,
+ 113,40,0,116,10,0,124,4,0,124,5,0,131,2,0,125,
+ 6,0,116,11,0,124,6,0,124,4,0,131,2,0,1,113,
+ 40,0,87,116,1,0,106,3,0,116,12,0,25,125,7,0,
+ 120,73,0,100,5,0,68,93,65,0,125,8,0,124,8,0,
+ 116,1,0,106,3,0,107,7,0,114,206,0,116,13,0,124,
+ 8,0,131,1,0,125,9,0,110,13,0,116,1,0,106,3,
+ 0,124,8,0,25,125,9,0,116,14,0,124,7,0,124,8,
+ 0,124,9,0,131,3,0,1,113,170,0,87,121,16,0,116,
+ 13,0,100,2,0,131,1,0,125,10,0,87,110,24,0,4,
+ 116,15,0,107,10,0,114,25,1,1,1,1,100,3,0,125,
+ 10,0,89,110,1,0,88,116,14,0,124,7,0,100,2,0,
+ 124,10,0,131,3,0,1,116,13,0,100,4,0,131,1,0,
+ 125,11,0,116,14,0,124,7,0,100,4,0,124,11,0,131,
+ 3,0,1,100,3,0,83,41,6,122,250,83,101,116,117,112,
+ 32,105,109,112,111,114,116,108,105,98,32,98,121,32,105,109,
+ 112,111,114,116,105,110,103,32,110,101,101,100,101,100,32,98,
+ 117,105,108,116,45,105,110,32,109,111,100,117,108,101,115,32,
+ 97,110,100,32,105,110,106,101,99,116,105,110,103,32,116,104,
+ 101,109,10,32,32,32,32,105,110,116,111,32,116,104,101,32,
+ 103,108,111,98,97,108,32,110,97,109,101,115,112,97,99,101,
+ 46,10,10,32,32,32,32,65,115,32,115,121,115,32,105,115,
+ 32,110,101,101,100,101,100,32,102,111,114,32,115,121,115,46,
+ 109,111,100,117,108,101,115,32,97,99,99,101,115,115,32,97,
+ 110,100,32,95,105,109,112,32,105,115,32,110,101,101,100,101,
+ 100,32,116,111,32,108,111,97,100,32,98,117,105,108,116,45,
+ 105,110,10,32,32,32,32,109,111,100,117,108,101,115,44,32,
+ 116,104,111,115,101,32,116,119,111,32,109,111,100,117,108,101,
+ 115,32,109,117,115,116,32,98,101,32,101,120,112,108,105,99,
+ 105,116,108,121,32,112,97,115,115,101,100,32,105,110,46,10,
+ 10,32,32,32,32,114,141,0,0,0,114,34,0,0,0,78,
+ 114,62,0,0,0,41,1,122,9,95,119,97,114,110,105,110,
+ 103,115,41,16,114,57,0,0,0,114,14,0,0,0,114,13,
+ 0,0,0,114,21,0,0,0,218,5,105,116,101,109,115,114,
+ 177,0,0,0,114,76,0,0,0,114,150,0,0,0,114,82,
+ 0,0,0,114,160,0,0,0,114,132,0,0,0,114,137,0,
+ 0,0,114,1,0,0,0,114,200,0,0,0,114,5,0,0,
+ 0,114,77,0,0,0,41,12,218,10,115,121,115,95,109,111,
+ 100,117,108,101,218,11,95,105,109,112,95,109,111,100,117,108,
+ 101,90,11,109,111,100,117,108,101,95,116,121,112,101,114,15,
+ 0,0,0,114,89,0,0,0,114,99,0,0,0,114,88,0,
+ 0,0,90,11,115,101,108,102,95,109,111,100,117,108,101,90,
+ 12,98,117,105,108,116,105,110,95,110,97,109,101,90,14,98,
+ 117,105,108,116,105,110,95,109,111,100,117,108,101,90,13,116,
+ 104,114,101,97,100,95,109,111,100,117,108,101,90,14,119,101,
+ 97,107,114,101,102,95,109,111,100,117,108,101,114,10,0,0,
+ 0,114,10,0,0,0,114,11,0,0,0,218,6,95,115,101,
+ 116,117,112,61,4,0,0,115,50,0,0,0,0,9,6,1,
+ 6,3,12,1,28,1,15,1,15,1,9,1,15,1,9,2,
+ 3,1,15,1,17,3,13,1,13,1,15,1,15,2,13,1,
+ 20,3,3,1,16,1,13,2,11,1,16,3,12,1,114,204,
+ 0,0,0,99,2,0,0,0,0,0,0,0,3,0,0,0,
+ 3,0,0,0,67,0,0,0,115,87,0,0,0,116,0,0,
+ 124,0,0,124,1,0,131,2,0,1,116,1,0,106,2,0,
+ 106,3,0,116,4,0,131,1,0,1,116,1,0,106,2,0,
+ 106,3,0,116,5,0,131,1,0,1,100,1,0,100,2,0,
+ 108,6,0,125,2,0,124,2,0,97,7,0,124,2,0,106,
+ 8,0,116,1,0,106,9,0,116,10,0,25,131,1,0,1,
+ 100,2,0,83,41,3,122,50,73,110,115,116,97,108,108,32,
+ 105,109,112,111,114,116,108,105,98,32,97,115,32,116,104,101,
+ 32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,32,
+ 111,102,32,105,109,112,111,114,116,46,114,33,0,0,0,78,
+ 41,11,114,204,0,0,0,114,14,0,0,0,114,174,0,0,
+ 0,114,113,0,0,0,114,150,0,0,0,114,160,0,0,0,
+ 218,26,95,102,114,111,122,101,110,95,105,109,112,111,114,116,
+ 108,105,98,95,101,120,116,101,114,110,97,108,114,119,0,0,
+ 0,218,8,95,105,110,115,116,97,108,108,114,21,0,0,0,
+ 114,1,0,0,0,41,3,114,202,0,0,0,114,203,0,0,
+ 0,114,205,0,0,0,114,10,0,0,0,114,10,0,0,0,
+ 114,11,0,0,0,114,206,0,0,0,108,4,0,0,115,12,
+ 0,0,0,0,2,13,2,16,1,16,3,12,1,6,1,114,
+ 206,0,0,0,41,51,114,3,0,0,0,114,119,0,0,0,
+ 114,12,0,0,0,114,16,0,0,0,114,17,0,0,0,114,
+ 59,0,0,0,114,41,0,0,0,114,48,0,0,0,114,31,
+ 0,0,0,114,32,0,0,0,114,53,0,0,0,114,54,0,
+ 0,0,114,56,0,0,0,114,63,0,0,0,114,65,0,0,
+ 0,114,75,0,0,0,114,81,0,0,0,114,84,0,0,0,
+ 114,90,0,0,0,114,101,0,0,0,114,102,0,0,0,114,
+ 106,0,0,0,114,85,0,0,0,218,6,111,98,106,101,99,
+ 116,90,9,95,80,79,80,85,76,65,84,69,114,132,0,0,
+ 0,114,137,0,0,0,114,144,0,0,0,114,97,0,0,0,
+ 114,86,0,0,0,114,148,0,0,0,114,149,0,0,0,114,
+ 87,0,0,0,114,150,0,0,0,114,160,0,0,0,114,165,
+ 0,0,0,114,171,0,0,0,114,173,0,0,0,114,176,0,
+ 0,0,114,181,0,0,0,114,191,0,0,0,114,182,0,0,
+ 0,114,184,0,0,0,114,185,0,0,0,114,186,0,0,0,
+ 114,194,0,0,0,114,196,0,0,0,114,199,0,0,0,114,
+ 200,0,0,0,114,204,0,0,0,114,206,0,0,0,114,10,
0,0,0,114,10,0,0,0,114,10,0,0,0,114,11,0,
- 0,0,218,18,95,98,117,105,108,116,105,110,95,102,114,111,
- 109,95,110,97,109,101,54,4,0,0,115,8,0,0,0,0,
- 1,15,1,12,1,16,1,114,200,0,0,0,99,2,0,0,
- 0,0,0,0,0,12,0,0,0,12,0,0,0,67,0,0,
- 0,115,74,1,0,0,124,1,0,97,0,0,124,0,0,97,
- 1,0,116,2,0,116,1,0,131,1,0,125,2,0,120,123,
- 0,116,1,0,106,3,0,106,4,0,131,0,0,68,93,106,
- 0,92,2,0,125,3,0,125,4,0,116,5,0,124,4,0,
- 124,2,0,131,2,0,114,40,0,124,3,0,116,1,0,106,
- 6,0,107,6,0,114,91,0,116,7,0,125,5,0,110,27,
- 0,116,0,0,106,8,0,124,3,0,131,1,0,114,40,0,
- 116,9,0,125,5,0,110,3,0,113,40,0,116,10,0,124,
- 4,0,124,5,0,131,2,0,125,6,0,116,11,0,124,6,
- 0,124,4,0,131,2,0,1,113,40,0,87,116,1,0,106,
- 3,0,116,12,0,25,125,7,0,120,73,0,100,5,0,68,
- 93,65,0,125,8,0,124,8,0,116,1,0,106,3,0,107,
- 7,0,114,206,0,116,13,0,124,8,0,131,1,0,125,9,
- 0,110,13,0,116,1,0,106,3,0,124,8,0,25,125,9,
- 0,116,14,0,124,7,0,124,8,0,124,9,0,131,3,0,
- 1,113,170,0,87,121,16,0,116,13,0,100,2,0,131,1,
- 0,125,10,0,87,110,24,0,4,116,15,0,107,10,0,114,
- 25,1,1,1,1,100,3,0,125,10,0,89,110,1,0,88,
- 116,14,0,124,7,0,100,2,0,124,10,0,131,3,0,1,
- 116,13,0,100,4,0,131,1,0,125,11,0,116,14,0,124,
- 7,0,100,4,0,124,11,0,131,3,0,1,100,3,0,83,
- 41,6,122,250,83,101,116,117,112,32,105,109,112,111,114,116,
- 108,105,98,32,98,121,32,105,109,112,111,114,116,105,110,103,
- 32,110,101,101,100,101,100,32,98,117,105,108,116,45,105,110,
- 32,109,111,100,117,108,101,115,32,97,110,100,32,105,110,106,
- 101,99,116,105,110,103,32,116,104,101,109,10,32,32,32,32,
- 105,110,116,111,32,116,104,101,32,103,108,111,98,97,108,32,
- 110,97,109,101,115,112,97,99,101,46,10,10,32,32,32,32,
- 65,115,32,115,121,115,32,105,115,32,110,101,101,100,101,100,
- 32,102,111,114,32,115,121,115,46,109,111,100,117,108,101,115,
- 32,97,99,99,101,115,115,32,97,110,100,32,95,105,109,112,
- 32,105,115,32,110,101,101,100,101,100,32,116,111,32,108,111,
- 97,100,32,98,117,105,108,116,45,105,110,10,32,32,32,32,
- 109,111,100,117,108,101,115,44,32,116,104,111,115,101,32,116,
- 119,111,32,109,111,100,117,108,101,115,32,109,117,115,116,32,
- 98,101,32,101,120,112,108,105,99,105,116,108,121,32,112,97,
- 115,115,101,100,32,105,110,46,10,10,32,32,32,32,114,141,
- 0,0,0,114,34,0,0,0,78,114,62,0,0,0,41,1,
- 122,9,95,119,97,114,110,105,110,103,115,41,16,114,57,0,
- 0,0,114,14,0,0,0,114,13,0,0,0,114,21,0,0,
- 0,218,5,105,116,101,109,115,114,177,0,0,0,114,76,0,
- 0,0,114,150,0,0,0,114,82,0,0,0,114,160,0,0,
- 0,114,132,0,0,0,114,137,0,0,0,114,1,0,0,0,
- 114,200,0,0,0,114,5,0,0,0,114,77,0,0,0,41,
- 12,218,10,115,121,115,95,109,111,100,117,108,101,218,11,95,
- 105,109,112,95,109,111,100,117,108,101,90,11,109,111,100,117,
- 108,101,95,116,121,112,101,114,15,0,0,0,114,89,0,0,
- 0,114,99,0,0,0,114,88,0,0,0,90,11,115,101,108,
- 102,95,109,111,100,117,108,101,90,12,98,117,105,108,116,105,
- 110,95,110,97,109,101,90,14,98,117,105,108,116,105,110,95,
- 109,111,100,117,108,101,90,13,116,104,114,101,97,100,95,109,
- 111,100,117,108,101,90,14,119,101,97,107,114,101,102,95,109,
- 111,100,117,108,101,114,10,0,0,0,114,10,0,0,0,114,
- 11,0,0,0,218,6,95,115,101,116,117,112,61,4,0,0,
- 115,50,0,0,0,0,9,6,1,6,3,12,1,28,1,15,
- 1,15,1,9,1,15,1,9,2,3,1,15,1,17,3,13,
- 1,13,1,15,1,15,2,13,1,20,3,3,1,16,1,13,
- 2,11,1,16,3,12,1,114,204,0,0,0,99,2,0,0,
- 0,0,0,0,0,3,0,0,0,3,0,0,0,67,0,0,
- 0,115,87,0,0,0,116,0,0,124,0,0,124,1,0,131,
- 2,0,1,116,1,0,106,2,0,106,3,0,116,4,0,131,
- 1,0,1,116,1,0,106,2,0,106,3,0,116,5,0,131,
- 1,0,1,100,1,0,100,2,0,108,6,0,125,2,0,124,
- 2,0,97,7,0,124,2,0,106,8,0,116,1,0,106,9,
- 0,116,10,0,25,131,1,0,1,100,2,0,83,41,3,122,
- 50,73,110,115,116,97,108,108,32,105,109,112,111,114,116,108,
- 105,98,32,97,115,32,116,104,101,32,105,109,112,108,101,109,
- 101,110,116,97,116,105,111,110,32,111,102,32,105,109,112,111,
- 114,116,46,114,33,0,0,0,78,41,11,114,204,0,0,0,
- 114,14,0,0,0,114,174,0,0,0,114,113,0,0,0,114,
- 150,0,0,0,114,160,0,0,0,218,26,95,102,114,111,122,
- 101,110,95,105,109,112,111,114,116,108,105,98,95,101,120,116,
- 101,114,110,97,108,114,119,0,0,0,218,8,95,105,110,115,
- 116,97,108,108,114,21,0,0,0,114,1,0,0,0,41,3,
- 114,202,0,0,0,114,203,0,0,0,114,205,0,0,0,114,
- 10,0,0,0,114,10,0,0,0,114,11,0,0,0,114,206,
- 0,0,0,108,4,0,0,115,12,0,0,0,0,2,13,2,
- 16,1,16,3,12,1,6,1,114,206,0,0,0,41,51,114,
- 3,0,0,0,114,119,0,0,0,114,12,0,0,0,114,16,
- 0,0,0,114,17,0,0,0,114,59,0,0,0,114,41,0,
- 0,0,114,48,0,0,0,114,31,0,0,0,114,32,0,0,
- 0,114,53,0,0,0,114,54,0,0,0,114,56,0,0,0,
- 114,63,0,0,0,114,65,0,0,0,114,75,0,0,0,114,
- 81,0,0,0,114,84,0,0,0,114,90,0,0,0,114,101,
- 0,0,0,114,102,0,0,0,114,106,0,0,0,114,85,0,
- 0,0,218,6,111,98,106,101,99,116,90,9,95,80,79,80,
- 85,76,65,84,69,114,132,0,0,0,114,137,0,0,0,114,
- 144,0,0,0,114,97,0,0,0,114,86,0,0,0,114,148,
- 0,0,0,114,149,0,0,0,114,87,0,0,0,114,150,0,
- 0,0,114,160,0,0,0,114,165,0,0,0,114,171,0,0,
- 0,114,173,0,0,0,114,176,0,0,0,114,181,0,0,0,
- 114,191,0,0,0,114,182,0,0,0,114,184,0,0,0,114,
- 185,0,0,0,114,186,0,0,0,114,194,0,0,0,114,196,
- 0,0,0,114,199,0,0,0,114,200,0,0,0,114,204,0,
- 0,0,114,206,0,0,0,114,10,0,0,0,114,10,0,0,
- 0,114,10,0,0,0,114,11,0,0,0,218,8,60,109,111,
- 100,117,108,101,62,8,0,0,0,115,96,0,0,0,6,17,
- 6,2,12,8,12,4,19,20,6,2,6,3,22,4,19,68,
- 19,21,19,19,12,19,12,19,12,11,18,8,12,11,12,12,
- 12,16,12,36,19,27,19,101,24,26,9,3,18,45,18,60,
- 12,18,12,17,12,25,12,29,12,23,12,16,19,73,19,77,
- 19,13,12,9,12,9,15,40,12,17,6,1,10,2,12,27,
- 12,6,18,24,12,32,12,15,24,35,12,7,12,47,
+ 0,0,218,8,60,109,111,100,117,108,101,62,8,0,0,0,
+ 115,96,0,0,0,6,17,6,2,12,8,12,4,19,20,6,
+ 2,6,3,22,4,19,68,19,21,19,19,12,19,12,19,12,
+ 11,18,8,12,11,12,12,12,16,12,36,19,27,19,101,24,
+ 26,9,3,18,45,18,60,12,18,12,17,12,25,12,29,12,
+ 23,12,16,19,73,19,77,19,13,12,9,12,9,15,40,12,
+ 17,6,1,10,2,12,27,12,6,18,24,12,32,12,15,24,
+ 35,12,7,12,47,
};
116,97,103,90,15,97,108,109,111,115,116,95,102,105,108,101,
110,97,109,101,114,4,0,0,0,114,4,0,0,0,114,5,
0,0,0,218,17,99,97,99,104,101,95,102,114,111,109,95,
- 115,111,117,114,99,101,243,0,0,0,115,46,0,0,0,0,
+ 115,111,117,114,99,101,246,0,0,0,115,46,0,0,0,0,
18,12,1,9,1,7,1,12,1,6,1,12,1,18,1,18,
1,24,1,12,1,12,1,12,1,36,1,12,1,18,1,9,
2,12,1,12,1,12,1,12,1,21,1,21,1,114,79,0,
95,108,101,118,101,108,90,13,98,97,115,101,95,102,105,108,
101,110,97,109,101,114,4,0,0,0,114,4,0,0,0,114,
5,0,0,0,218,17,115,111,117,114,99,101,95,102,114,111,
- 109,95,99,97,99,104,101,31,1,0,0,115,44,0,0,0,
+ 109,95,99,97,99,104,101,34,1,0,0,115,44,0,0,0,
0,9,18,1,12,1,18,1,18,1,12,1,9,1,15,1,
15,1,12,1,9,1,15,1,12,1,22,1,15,1,9,1,
12,1,22,1,12,1,9,1,12,1,19,1,114,85,0,0,
115,105,111,110,218,11,115,111,117,114,99,101,95,112,97,116,
104,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,
218,15,95,103,101,116,95,115,111,117,114,99,101,102,105,108,
- 101,64,1,0,0,115,20,0,0,0,0,7,18,1,4,1,
+ 101,67,1,0,0,115,20,0,0,0,0,7,18,1,4,1,
24,1,35,1,4,1,3,1,16,1,19,1,21,1,114,91,
0,0,0,99,1,0,0,0,0,0,0,0,1,0,0,0,
11,0,0,0,67,0,0,0,115,92,0,0,0,124,0,0,
84,0,0,0,114,79,0,0,0,114,66,0,0,0,114,74,
0,0,0,41,1,218,8,102,105,108,101,110,97,109,101,114,
4,0,0,0,114,4,0,0,0,114,5,0,0,0,218,11,
- 95,103,101,116,95,99,97,99,104,101,100,83,1,0,0,115,
+ 95,103,101,116,95,99,97,99,104,101,100,86,1,0,0,115,
16,0,0,0,0,1,21,1,3,1,14,1,13,1,8,1,
21,1,4,2,114,95,0,0,0,99,1,0,0,0,0,0,
0,0,2,0,0,0,11,0,0,0,67,0,0,0,115,60,
41,3,114,39,0,0,0,114,41,0,0,0,114,40,0,0,
0,41,2,114,35,0,0,0,114,42,0,0,0,114,4,0,
0,0,114,4,0,0,0,114,5,0,0,0,218,10,95,99,
- 97,108,99,95,109,111,100,101,95,1,0,0,115,12,0,0,
+ 97,108,99,95,109,111,100,101,98,1,0,0,115,12,0,0,
0,0,2,3,1,19,1,13,1,11,3,10,1,114,97,0,
0,0,218,9,118,101,114,98,111,115,105,116,121,114,29,0,
0,0,99,1,0,0,0,1,0,0,0,3,0,0,0,4,
218,6,115,116,100,101,114,114,41,3,114,75,0,0,0,114,
98,0,0,0,218,4,97,114,103,115,114,4,0,0,0,114,
4,0,0,0,114,5,0,0,0,218,16,95,118,101,114,98,
- 111,115,101,95,109,101,115,115,97,103,101,107,1,0,0,115,
+ 111,115,101,95,109,101,115,115,97,103,101,110,1,0,0,115,
8,0,0,0,0,2,18,1,15,1,10,1,114,105,0,0,
0,99,1,0,0,0,0,0,0,0,3,0,0,0,11,0,
0,0,3,0,0,0,115,84,0,0,0,100,1,0,135,0,
0,0,90,6,107,119,97,114,103,115,41,1,218,6,109,101,
116,104,111,100,114,4,0,0,0,114,5,0,0,0,218,19,
95,99,104,101,99,107,95,110,97,109,101,95,119,114,97,112,
- 112,101,114,123,1,0,0,115,12,0,0,0,0,1,12,1,
+ 112,101,114,126,1,0,0,115,12,0,0,0,0,1,12,1,
12,1,15,1,6,1,25,1,122,40,95,99,104,101,99,107,
95,110,97,109,101,46,60,108,111,99,97,108,115,62,46,95,
99,104,101,99,107,95,110,97,109,101,95,119,114,97,112,112,
116,97,116,116,114,218,8,95,95,100,105,99,116,95,95,218,
6,117,112,100,97,116,101,41,3,90,3,110,101,119,90,3,
111,108,100,114,52,0,0,0,114,4,0,0,0,114,4,0,
- 0,0,114,5,0,0,0,218,5,95,119,114,97,112,134,1,
+ 0,0,114,5,0,0,0,218,5,95,119,114,97,112,137,1,
0,0,115,8,0,0,0,0,1,25,1,15,1,29,1,122,
26,95,99,104,101,99,107,95,110,97,109,101,46,60,108,111,
99,97,108,115,62,46,95,119,114,97,112,41,3,218,10,95,
78,97,109,101,69,114,114,111,114,41,3,114,109,0,0,0,
114,110,0,0,0,114,120,0,0,0,114,4,0,0,0,41,
1,114,109,0,0,0,114,5,0,0,0,218,11,95,99,104,
- 101,99,107,95,110,97,109,101,115,1,0,0,115,14,0,0,
+ 101,99,107,95,110,97,109,101,118,1,0,0,115,14,0,0,
0,0,8,21,7,3,1,13,1,13,2,17,5,13,1,114,
123,0,0,0,99,2,0,0,0,0,0,0,0,5,0,0,
0,4,0,0,0,67,0,0,0,115,84,0,0,0,124,0,
218,8,112,111,114,116,105,111,110,115,218,3,109,115,103,114,
4,0,0,0,114,4,0,0,0,114,5,0,0,0,218,17,
95,102,105,110,100,95,109,111,100,117,108,101,95,115,104,105,
- 109,143,1,0,0,115,10,0,0,0,0,10,21,1,24,1,
+ 109,146,1,0,0,115,10,0,0,0,0,10,21,1,24,1,
6,1,29,1,114,130,0,0,0,99,4,0,0,0,0,0,
0,0,11,0,0,0,19,0,0,0,67,0,0,0,115,240,
1,0,0,105,0,0,125,4,0,124,2,0,100,1,0,107,
109,101,218,11,115,111,117,114,99,101,95,115,105,122,101,114,
4,0,0,0,114,4,0,0,0,114,5,0,0,0,218,25,
95,118,97,108,105,100,97,116,101,95,98,121,116,101,99,111,
- 100,101,95,104,101,97,100,101,114,160,1,0,0,115,76,0,
+ 100,101,95,104,101,97,100,101,114,163,1,0,0,115,76,0,
0,0,0,11,6,1,12,1,13,3,6,1,12,1,10,1,
16,1,16,1,16,1,12,1,18,1,13,1,18,1,18,1,
15,1,13,1,15,1,18,1,15,1,13,1,12,1,12,1,
114,106,0,0,0,114,89,0,0,0,114,90,0,0,0,218,
4,99,111,100,101,114,4,0,0,0,114,4,0,0,0,114,
5,0,0,0,218,17,95,99,111,109,112,105,108,101,95,98,
- 121,116,101,99,111,100,101,215,1,0,0,115,16,0,0,0,
+ 121,116,101,99,111,100,101,218,1,0,0,115,16,0,0,0,
0,2,15,1,15,1,13,1,12,1,16,1,4,2,18,1,
114,147,0,0,0,114,59,0,0,0,99,3,0,0,0,0,
0,0,0,4,0,0,0,3,0,0,0,67,0,0,0,115,
4,114,146,0,0,0,114,133,0,0,0,114,140,0,0,0,
114,53,0,0,0,114,4,0,0,0,114,4,0,0,0,114,
5,0,0,0,218,17,95,99,111,100,101,95,116,111,95,98,
- 121,116,101,99,111,100,101,227,1,0,0,115,10,0,0,0,
+ 121,116,101,99,111,100,101,230,1,0,0,115,10,0,0,0,
0,3,12,1,19,1,19,1,22,1,114,150,0,0,0,99,
1,0,0,0,0,0,0,0,5,0,0,0,4,0,0,0,
67,0,0,0,115,89,0,0,0,100,1,0,100,2,0,108,
100,105,110,103,90,15,110,101,119,108,105,110,101,95,100,101,
99,111,100,101,114,114,4,0,0,0,114,4,0,0,0,114,
5,0,0,0,218,13,100,101,99,111,100,101,95,115,111,117,
- 114,99,101,237,1,0,0,115,10,0,0,0,0,5,12,1,
+ 114,99,101,240,1,0,0,115,10,0,0,0,0,5,12,1,
18,1,15,1,18,1,114,155,0,0,0,114,127,0,0,0,
218,26,115,117,98,109,111,100,117,108,101,95,115,101,97,114,
99,104,95,108,111,99,97,116,105,111,110,115,99,2,0,0,
159,0,0,0,90,7,100,105,114,110,97,109,101,114,4,0,
0,0,114,4,0,0,0,114,5,0,0,0,218,23,115,112,
101,99,95,102,114,111,109,95,102,105,108,101,95,108,111,99,
- 97,116,105,111,110,254,1,0,0,115,60,0,0,0,0,12,
+ 97,116,105,111,110,1,2,0,0,115,60,0,0,0,0,12,
12,4,6,1,15,2,3,1,19,1,13,1,5,8,24,1,
9,3,12,1,22,1,21,1,15,1,9,1,5,2,4,3,
12,2,15,1,3,1,19,1,13,1,5,2,6,1,12,2,
79,67,65,76,95,77,65,67,72,73,78,69,41,2,218,3,
99,108,115,218,3,107,101,121,114,4,0,0,0,114,4,0,
0,0,114,5,0,0,0,218,14,95,111,112,101,110,95,114,
- 101,103,105,115,116,114,121,76,2,0,0,115,8,0,0,0,
+ 101,103,105,115,116,114,121,79,2,0,0,115,8,0,0,0,
0,2,3,1,23,1,13,1,122,36,87,105,110,100,111,119,
115,82,101,103,105,115,116,114,121,70,105,110,100,101,114,46,
95,111,112,101,110,95,114,101,103,105,115,116,114,121,99,2,
171,0,0,0,90,4,104,107,101,121,218,8,102,105,108,101,
112,97,116,104,114,4,0,0,0,114,4,0,0,0,114,5,
0,0,0,218,16,95,115,101,97,114,99,104,95,114,101,103,
- 105,115,116,114,121,83,2,0,0,115,22,0,0,0,0,2,
+ 105,115,116,114,121,86,2,0,0,115,22,0,0,0,0,2,
9,1,12,2,9,1,15,1,22,1,3,1,18,1,29,1,
13,1,9,1,122,38,87,105,110,100,111,119,115,82,101,103,
105,115,116,114,121,70,105,110,100,101,114,46,95,115,101,97,
114,35,0,0,0,218,6,116,97,114,103,101,116,114,177,0,
0,0,114,127,0,0,0,114,166,0,0,0,114,164,0,0,
0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,
- 218,9,102,105,110,100,95,115,112,101,99,98,2,0,0,115,
+ 218,9,102,105,110,100,95,115,112,101,99,101,2,0,0,115,
26,0,0,0,0,2,15,1,12,1,4,1,3,1,14,1,
13,1,9,1,22,1,21,1,9,1,15,1,9,1,122,31,
87,105,110,100,111,119,115,82,101,103,105,115,116,114,121,70,
0,0,0,41,4,114,170,0,0,0,114,126,0,0,0,114,
35,0,0,0,114,164,0,0,0,114,4,0,0,0,114,4,
0,0,0,114,5,0,0,0,218,11,102,105,110,100,95,109,
- 111,100,117,108,101,114,2,0,0,115,8,0,0,0,0,7,
+ 111,100,117,108,101,117,2,0,0,115,8,0,0,0,0,7,
18,1,12,1,7,2,122,33,87,105,110,100,111,119,115,82,
101,103,105,115,116,114,121,70,105,110,100,101,114,46,102,105,
110,100,95,109,111,100,117,108,101,41,12,114,112,0,0,0,
99,108,97,115,115,109,101,116,104,111,100,114,172,0,0,0,
114,178,0,0,0,114,181,0,0,0,114,182,0,0,0,114,
4,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5,
- 0,0,0,114,168,0,0,0,64,2,0,0,115,20,0,0,
+ 0,0,0,114,168,0,0,0,67,2,0,0,115,20,0,0,
0,12,2,6,3,6,3,6,2,6,2,18,7,18,15,3,
1,21,15,3,1,114,168,0,0,0,99,0,0,0,0,0,
0,0,0,0,0,0,0,2,0,0,0,64,0,0,0,115,
0,0,0,114,94,0,0,0,90,13,102,105,108,101,110,97,
109,101,95,98,97,115,101,90,9,116,97,105,108,95,110,97,
109,101,114,4,0,0,0,114,4,0,0,0,114,5,0,0,
- 0,114,159,0,0,0,133,2,0,0,115,8,0,0,0,0,
+ 0,114,159,0,0,0,136,2,0,0,115,8,0,0,0,0,
3,25,1,22,1,19,1,122,24,95,76,111,97,100,101,114,
66,97,115,105,99,115,46,105,115,95,112,97,99,107,97,103,
101,99,2,0,0,0,0,0,0,0,2,0,0,0,1,0,
117,108,101,32,99,114,101,97,116,105,111,110,46,78,114,4,
0,0,0,41,2,114,108,0,0,0,114,164,0,0,0,114,
4,0,0,0,114,4,0,0,0,114,5,0,0,0,218,13,
- 99,114,101,97,116,101,95,109,111,100,117,108,101,141,2,0,
+ 99,114,101,97,116,101,95,109,111,100,117,108,101,144,2,0,
0,115,0,0,0,0,122,27,95,76,111,97,100,101,114,66,
97,115,105,99,115,46,99,114,101,97,116,101,95,109,111,100,
117,108,101,99,2,0,0,0,0,0,0,0,3,0,0,0,
0,41,3,114,108,0,0,0,218,6,109,111,100,117,108,101,
114,146,0,0,0,114,4,0,0,0,114,4,0,0,0,114,
5,0,0,0,218,11,101,120,101,99,95,109,111,100,117,108,
- 101,144,2,0,0,115,10,0,0,0,0,2,18,1,12,1,
+ 101,147,2,0,0,115,10,0,0,0,0,2,18,1,12,1,
9,1,15,1,122,25,95,76,111,97,100,101,114,66,97,115,
105,99,115,46,101,120,101,99,95,109,111,100,117,108,101,99,
2,0,0,0,0,0,0,0,2,0,0,0,3,0,0,0,
0,0,0,218,17,95,108,111,97,100,95,109,111,100,117,108,
101,95,115,104,105,109,41,2,114,108,0,0,0,114,126,0,
0,0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,
- 0,218,11,108,111,97,100,95,109,111,100,117,108,101,152,2,
+ 0,218,11,108,111,97,100,95,109,111,100,117,108,101,155,2,
0,0,115,2,0,0,0,0,1,122,25,95,76,111,97,100,
101,114,66,97,115,105,99,115,46,108,111,97,100,95,109,111,
100,117,108,101,78,41,8,114,112,0,0,0,114,111,0,0,
0,114,113,0,0,0,114,114,0,0,0,114,159,0,0,0,
114,186,0,0,0,114,191,0,0,0,114,193,0,0,0,114,
4,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5,
- 0,0,0,114,184,0,0,0,128,2,0,0,115,10,0,0,
+ 0,0,0,114,184,0,0,0,131,2,0,0,115,10,0,0,
0,12,3,6,2,12,8,12,3,12,8,114,184,0,0,0,
99,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,
0,64,0,0,0,115,106,0,0,0,101,0,0,90,1,0,
1,218,7,73,79,69,114,114,111,114,41,2,114,108,0,0,
0,114,35,0,0,0,114,4,0,0,0,114,4,0,0,0,
114,5,0,0,0,218,10,112,97,116,104,95,109,116,105,109,
- 101,158,2,0,0,115,2,0,0,0,0,6,122,23,83,111,
+ 101,161,2,0,0,115,2,0,0,0,0,6,122,23,83,111,
117,114,99,101,76,111,97,100,101,114,46,112,97,116,104,95,
109,116,105,109,101,99,2,0,0,0,0,0,0,0,2,0,
0,0,3,0,0,0,67,0,0,0,115,19,0,0,0,100,
32,32,32,114,133,0,0,0,41,1,114,196,0,0,0,41,
2,114,108,0,0,0,114,35,0,0,0,114,4,0,0,0,
114,4,0,0,0,114,5,0,0,0,218,10,112,97,116,104,
- 95,115,116,97,116,115,166,2,0,0,115,2,0,0,0,0,
+ 95,115,116,97,116,115,169,2,0,0,115,2,0,0,0,0,
11,122,23,83,111,117,114,99,101,76,111,97,100,101,114,46,
112,97,116,104,95,115,116,97,116,115,99,4,0,0,0,0,
0,0,0,4,0,0,0,3,0,0,0,67,0,0,0,115,
90,0,0,0,90,10,99,97,99,104,101,95,112,97,116,104,
114,53,0,0,0,114,4,0,0,0,114,4,0,0,0,114,
5,0,0,0,218,15,95,99,97,99,104,101,95,98,121,116,
- 101,99,111,100,101,179,2,0,0,115,2,0,0,0,0,8,
+ 101,99,111,100,101,182,2,0,0,115,2,0,0,0,0,8,
122,28,83,111,117,114,99,101,76,111,97,100,101,114,46,95,
99,97,99,104,101,95,98,121,116,101,99,111,100,101,99,3,
0,0,0,0,0,0,0,3,0,0,0,1,0,0,0,67,
32,32,32,32,32,32,78,114,4,0,0,0,41,3,114,108,
0,0,0,114,35,0,0,0,114,53,0,0,0,114,4,0,
0,0,114,4,0,0,0,114,5,0,0,0,114,198,0,0,
- 0,189,2,0,0,115,0,0,0,0,122,21,83,111,117,114,
+ 0,192,2,0,0,115,0,0,0,0,122,21,83,111,117,114,
99,101,76,111,97,100,101,114,46,115,101,116,95,100,97,116,
97,99,2,0,0,0,0,0,0,0,5,0,0,0,16,0,
0,0,67,0,0,0,115,105,0,0,0,124,0,0,106,0,
0,0,114,126,0,0,0,114,35,0,0,0,114,153,0,0,
0,218,3,101,120,99,114,4,0,0,0,114,4,0,0,0,
114,5,0,0,0,218,10,103,101,116,95,115,111,117,114,99,
- 101,196,2,0,0,115,14,0,0,0,0,2,15,1,3,1,
+ 101,199,2,0,0,115,14,0,0,0,0,2,15,1,3,1,
19,1,18,1,9,1,31,1,122,23,83,111,117,114,99,101,
76,111,97,100,101,114,46,103,101,116,95,115,111,117,114,99,
101,218,9,95,111,112,116,105,109,105,122,101,114,29,0,0,
101,41,4,114,108,0,0,0,114,53,0,0,0,114,35,0,
0,0,114,203,0,0,0,114,4,0,0,0,114,4,0,0,
0,114,5,0,0,0,218,14,115,111,117,114,99,101,95,116,
- 111,95,99,111,100,101,206,2,0,0,115,4,0,0,0,0,
+ 111,95,99,111,100,101,209,2,0,0,115,4,0,0,0,0,
5,21,1,122,27,83,111,117,114,99,101,76,111,97,100,101,
114,46,115,111,117,114,99,101,95,116,111,95,99,111,100,101,
99,2,0,0,0,0,0,0,0,10,0,0,0,43,0,0,
98,121,116,101,115,95,100,97,116,97,114,153,0,0,0,90,
11,99,111,100,101,95,111,98,106,101,99,116,114,4,0,0,
0,114,4,0,0,0,114,5,0,0,0,114,187,0,0,0,
- 214,2,0,0,115,78,0,0,0,0,7,15,1,6,1,3,
+ 217,2,0,0,115,78,0,0,0,0,7,15,1,6,1,3,
1,16,1,13,1,11,2,3,1,19,1,13,1,5,2,16,
1,3,1,19,1,13,1,5,2,3,1,9,1,12,1,13,
1,19,1,5,2,9,1,7,1,15,1,6,1,7,1,15,
199,0,0,0,114,198,0,0,0,114,202,0,0,0,114,206,
0,0,0,114,187,0,0,0,114,4,0,0,0,114,4,0,
0,0,114,4,0,0,0,114,5,0,0,0,114,194,0,0,
- 0,156,2,0,0,115,14,0,0,0,12,2,12,8,12,13,
+ 0,159,2,0,0,115,14,0,0,0,12,2,12,8,12,13,
12,10,12,7,12,10,18,8,114,194,0,0,0,99,0,0,
0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,
0,0,115,112,0,0,0,101,0,0,90,1,0,100,0,0,
32,32,32,32,32,32,102,105,110,100,101,114,46,78,41,2,
114,106,0,0,0,114,35,0,0,0,41,3,114,108,0,0,
0,114,126,0,0,0,114,35,0,0,0,114,4,0,0,0,
- 114,4,0,0,0,114,5,0,0,0,114,185,0,0,0,15,
+ 114,4,0,0,0,114,5,0,0,0,114,185,0,0,0,18,
3,0,0,115,4,0,0,0,0,3,9,1,122,19,70,105,
108,101,76,111,97,100,101,114,46,95,95,105,110,105,116,95,
95,99,2,0,0,0,0,0,0,0,2,0,0,0,2,0,
41,2,218,9,95,95,99,108,97,115,115,95,95,114,118,0,
0,0,41,2,114,108,0,0,0,218,5,111,116,104,101,114,
114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,218,
- 6,95,95,101,113,95,95,21,3,0,0,115,4,0,0,0,
+ 6,95,95,101,113,95,95,24,3,0,0,115,4,0,0,0,
0,1,18,1,122,17,70,105,108,101,76,111,97,100,101,114,
46,95,95,101,113,95,95,99,1,0,0,0,0,0,0,0,
1,0,0,0,3,0,0,0,67,0,0,0,115,26,0,0,
218,4,104,97,115,104,114,106,0,0,0,114,35,0,0,0,
41,1,114,108,0,0,0,114,4,0,0,0,114,4,0,0,
0,114,5,0,0,0,218,8,95,95,104,97,115,104,95,95,
- 25,3,0,0,115,2,0,0,0,0,1,122,19,70,105,108,
+ 28,3,0,0,115,2,0,0,0,0,1,122,19,70,105,108,
101,76,111,97,100,101,114,46,95,95,104,97,115,104,95,95,
99,2,0,0,0,0,0,0,0,2,0,0,0,3,0,0,
0,3,0,0,0,115,22,0,0,0,116,0,0,116,1,0,
32,32,32,32,32,32,32,32,41,3,218,5,115,117,112,101,
114,114,210,0,0,0,114,193,0,0,0,41,2,114,108,0,
0,0,114,126,0,0,0,41,1,114,211,0,0,0,114,4,
- 0,0,0,114,5,0,0,0,114,193,0,0,0,28,3,0,
+ 0,0,0,114,5,0,0,0,114,193,0,0,0,31,3,0,
0,115,2,0,0,0,0,10,122,22,70,105,108,101,76,111,
97,100,101,114,46,108,111,97,100,95,109,111,100,117,108,101,
99,2,0,0,0,0,0,0,0,2,0,0,0,1,0,0,
32,98,121,32,116,104,101,32,102,105,110,100,101,114,46,41,
1,114,35,0,0,0,41,2,114,108,0,0,0,114,126,0,
0,0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,
- 0,114,157,0,0,0,40,3,0,0,115,2,0,0,0,0,
+ 0,114,157,0,0,0,43,3,0,0,115,2,0,0,0,0,
3,122,23,70,105,108,101,76,111,97,100,101,114,46,103,101,
116,95,102,105,108,101,110,97,109,101,99,2,0,0,0,0,
0,0,0,3,0,0,0,9,0,0,0,67,0,0,0,115,
49,0,0,0,114,50,0,0,0,90,4,114,101,97,100,41,
3,114,108,0,0,0,114,35,0,0,0,114,54,0,0,0,
114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,114,
- 200,0,0,0,45,3,0,0,115,4,0,0,0,0,2,21,
+ 200,0,0,0,48,3,0,0,115,4,0,0,0,0,2,21,
1,122,19,70,105,108,101,76,111,97,100,101,114,46,103,101,
116,95,100,97,116,97,41,11,114,112,0,0,0,114,111,0,
0,0,114,113,0,0,0,114,114,0,0,0,114,185,0,0,
0,114,213,0,0,0,114,215,0,0,0,114,123,0,0,0,
114,193,0,0,0,114,157,0,0,0,114,200,0,0,0,114,
4,0,0,0,114,4,0,0,0,41,1,114,211,0,0,0,
- 114,5,0,0,0,114,210,0,0,0,10,3,0,0,115,14,
+ 114,5,0,0,0,114,210,0,0,0,13,3,0,0,115,14,
0,0,0,12,3,6,2,12,6,12,4,12,3,24,12,18,
5,114,210,0,0,0,99,0,0,0,0,0,0,0,0,0,
0,0,0,4,0,0,0,64,0,0,0,115,64,0,0,0,
3,114,39,0,0,0,218,8,115,116,95,109,116,105,109,101,
90,7,115,116,95,115,105,122,101,41,3,114,108,0,0,0,
114,35,0,0,0,114,208,0,0,0,114,4,0,0,0,114,
- 4,0,0,0,114,5,0,0,0,114,197,0,0,0,55,3,
+ 4,0,0,0,114,5,0,0,0,114,197,0,0,0,58,3,
0,0,115,4,0,0,0,0,2,12,1,122,27,83,111,117,
114,99,101,70,105,108,101,76,111,97,100,101,114,46,112,97,
116,104,95,115,116,97,116,115,99,4,0,0,0,0,0,0,
114,97,0,0,0,114,198,0,0,0,41,5,114,108,0,0,
0,114,90,0,0,0,114,89,0,0,0,114,53,0,0,0,
114,42,0,0,0,114,4,0,0,0,114,4,0,0,0,114,
- 5,0,0,0,114,199,0,0,0,60,3,0,0,115,4,0,
+ 5,0,0,0,114,199,0,0,0,63,3,0,0,115,4,0,
0,0,0,2,12,1,122,32,83,111,117,114,99,101,70,105,
108,101,76,111,97,100,101,114,46,95,99,97,99,104,101,95,
98,121,116,101,99,111,100,101,114,220,0,0,0,105,182,1,
53,0,0,0,114,220,0,0,0,218,6,112,97,114,101,110,
116,114,94,0,0,0,114,27,0,0,0,114,23,0,0,0,
114,201,0,0,0,114,4,0,0,0,114,4,0,0,0,114,
- 5,0,0,0,114,198,0,0,0,65,3,0,0,115,38,0,
+ 5,0,0,0,114,198,0,0,0,68,3,0,0,115,38,0,
0,0,0,2,18,1,6,2,22,1,18,1,17,2,19,1,
15,1,3,1,17,1,13,2,7,1,18,3,16,1,27,1,
3,1,16,1,17,1,18,2,122,25,83,111,117,114,99,101,
114,113,0,0,0,114,114,0,0,0,114,197,0,0,0,114,
199,0,0,0,114,198,0,0,0,114,4,0,0,0,114,4,
0,0,0,114,4,0,0,0,114,5,0,0,0,114,218,0,
- 0,0,51,3,0,0,115,8,0,0,0,12,2,6,2,12,
+ 0,0,54,3,0,0,115,8,0,0,0,12,2,6,2,12,
5,12,5,114,218,0,0,0,99,0,0,0,0,0,0,0,
0,0,0,0,0,2,0,0,0,64,0,0,0,115,46,0,
0,0,101,0,0,90,1,0,100,0,0,90,2,0,100,1,
114,147,0,0,0,41,5,114,108,0,0,0,114,126,0,0,
0,114,35,0,0,0,114,53,0,0,0,114,209,0,0,0,
114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,114,
- 187,0,0,0,98,3,0,0,115,8,0,0,0,0,1,15,
+ 187,0,0,0,101,3,0,0,115,8,0,0,0,0,1,15,
1,15,1,24,1,122,29,83,111,117,114,99,101,108,101,115,
115,70,105,108,101,76,111,97,100,101,114,46,103,101,116,95,
99,111,100,101,99,2,0,0,0,0,0,0,0,2,0,0,
32,115,111,117,114,99,101,32,99,111,100,101,46,78,114,4,
0,0,0,41,2,114,108,0,0,0,114,126,0,0,0,114,
4,0,0,0,114,4,0,0,0,114,5,0,0,0,114,202,
- 0,0,0,104,3,0,0,115,2,0,0,0,0,2,122,31,
+ 0,0,0,107,3,0,0,115,2,0,0,0,0,2,122,31,
83,111,117,114,99,101,108,101,115,115,70,105,108,101,76,111,
97,100,101,114,46,103,101,116,95,115,111,117,114,99,101,78,
41,6,114,112,0,0,0,114,111,0,0,0,114,113,0,0,
0,114,114,0,0,0,114,187,0,0,0,114,202,0,0,0,
114,4,0,0,0,114,4,0,0,0,114,4,0,0,0,114,
- 5,0,0,0,114,223,0,0,0,94,3,0,0,115,6,0,
+ 5,0,0,0,114,223,0,0,0,97,3,0,0,115,6,0,
0,0,12,2,6,2,12,6,114,223,0,0,0,99,0,0,
0,0,0,0,0,0,0,0,0,0,3,0,0,0,64,0,
0,0,115,136,0,0,0,101,0,0,90,1,0,100,0,0,
0,100,0,0,83,41,1,78,41,2,114,106,0,0,0,114,
35,0,0,0,41,3,114,108,0,0,0,114,106,0,0,0,
114,35,0,0,0,114,4,0,0,0,114,4,0,0,0,114,
- 5,0,0,0,114,185,0,0,0,121,3,0,0,115,4,0,
+ 5,0,0,0,114,185,0,0,0,124,3,0,0,115,4,0,
0,0,0,1,9,1,122,28,69,120,116,101,110,115,105,111,
110,70,105,108,101,76,111,97,100,101,114,46,95,95,105,110,
105,116,95,95,99,2,0,0,0,0,0,0,0,2,0,0,
124,0,0,106,1,0,124,1,0,106,1,0,107,2,0,83,
41,1,78,41,2,114,211,0,0,0,114,118,0,0,0,41,
2,114,108,0,0,0,114,212,0,0,0,114,4,0,0,0,
- 114,4,0,0,0,114,5,0,0,0,114,213,0,0,0,125,
+ 114,4,0,0,0,114,5,0,0,0,114,213,0,0,0,128,
3,0,0,115,4,0,0,0,0,1,18,1,122,26,69,120,
116,101,110,115,105,111,110,70,105,108,101,76,111,97,100,101,
114,46,95,95,101,113,95,95,99,1,0,0,0,0,0,0,
0,124,0,0,106,2,0,131,1,0,65,83,41,1,78,41,
3,114,214,0,0,0,114,106,0,0,0,114,35,0,0,0,
41,1,114,108,0,0,0,114,4,0,0,0,114,4,0,0,
- 0,114,5,0,0,0,114,215,0,0,0,129,3,0,0,115,
+ 0,114,5,0,0,0,114,215,0,0,0,132,3,0,0,115,
2,0,0,0,0,1,122,28,69,120,116,101,110,115,105,111,
110,70,105,108,101,76,111,97,100,101,114,46,95,95,104,97,
115,104,95,95,99,2,0,0,0,0,0,0,0,3,0,0,
114,105,0,0,0,114,106,0,0,0,114,35,0,0,0,41,
3,114,108,0,0,0,114,164,0,0,0,114,190,0,0,0,
114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,114,
- 186,0,0,0,132,3,0,0,115,10,0,0,0,0,2,6,
+ 186,0,0,0,135,3,0,0,115,10,0,0,0,0,2,6,
1,15,1,6,1,16,1,122,33,69,120,116,101,110,115,105,
111,110,70,105,108,101,76,111,97,100,101,114,46,99,114,101,
97,116,101,95,109,111,100,117,108,101,99,2,0,0,0,0,
12,101,120,101,99,95,100,121,110,97,109,105,99,114,105,0,
0,0,114,106,0,0,0,114,35,0,0,0,41,2,114,108,
0,0,0,114,190,0,0,0,114,4,0,0,0,114,4,0,
- 0,0,114,5,0,0,0,114,191,0,0,0,140,3,0,0,
+ 0,0,114,5,0,0,0,114,191,0,0,0,143,3,0,0,
115,6,0,0,0,0,2,19,1,6,1,122,31,69,120,116,
101,110,115,105,111,110,70,105,108,101,76,111,97,100,101,114,
46,101,120,101,99,95,109,111,100,117,108,101,99,2,0,0,
78,114,4,0,0,0,41,2,114,22,0,0,0,218,6,115,
117,102,102,105,120,41,1,218,9,102,105,108,101,95,110,97,
109,101,114,4,0,0,0,114,5,0,0,0,250,9,60,103,
- 101,110,101,120,112,114,62,149,3,0,0,115,2,0,0,0,
+ 101,110,101,120,112,114,62,152,3,0,0,115,2,0,0,0,
6,1,122,49,69,120,116,101,110,115,105,111,110,70,105,108,
101,76,111,97,100,101,114,46,105,115,95,112,97,99,107,97,
103,101,46,60,108,111,99,97,108,115,62,46,60,103,101,110,
0,218,3,97,110,121,218,18,69,88,84,69,78,83,73,79,
78,95,83,85,70,70,73,88,69,83,41,2,114,108,0,0,
0,114,126,0,0,0,114,4,0,0,0,41,1,114,226,0,
- 0,0,114,5,0,0,0,114,159,0,0,0,146,3,0,0,
+ 0,0,114,5,0,0,0,114,159,0,0,0,149,3,0,0,
115,6,0,0,0,0,2,19,1,18,1,122,30,69,120,116,
101,110,115,105,111,110,70,105,108,101,76,111,97,100,101,114,
46,105,115,95,112,97,99,107,97,103,101,99,2,0,0,0,
99,111,100,101,32,111,98,106,101,99,116,46,78,114,4,0,
0,0,41,2,114,108,0,0,0,114,126,0,0,0,114,4,
0,0,0,114,4,0,0,0,114,5,0,0,0,114,187,0,
- 0,0,152,3,0,0,115,2,0,0,0,0,2,122,28,69,
+ 0,0,155,3,0,0,115,2,0,0,0,0,2,122,28,69,
120,116,101,110,115,105,111,110,70,105,108,101,76,111,97,100,
101,114,46,103,101,116,95,99,111,100,101,99,2,0,0,0,
0,0,0,0,2,0,0,0,1,0,0,0,67,0,0,0,
118,101,32,110,111,32,115,111,117,114,99,101,32,99,111,100,
101,46,78,114,4,0,0,0,41,2,114,108,0,0,0,114,
126,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5,
- 0,0,0,114,202,0,0,0,156,3,0,0,115,2,0,0,
+ 0,0,0,114,202,0,0,0,159,3,0,0,115,2,0,0,
0,0,2,122,30,69,120,116,101,110,115,105,111,110,70,105,
108,101,76,111,97,100,101,114,46,103,101,116,95,115,111,117,
114,99,101,99,2,0,0,0,0,0,0,0,2,0,0,0,
117,110,100,32,98,121,32,116,104,101,32,102,105,110,100,101,
114,46,41,1,114,35,0,0,0,41,2,114,108,0,0,0,
114,126,0,0,0,114,4,0,0,0,114,4,0,0,0,114,
- 5,0,0,0,114,157,0,0,0,160,3,0,0,115,2,0,
+ 5,0,0,0,114,157,0,0,0,163,3,0,0,115,2,0,
0,0,0,3,122,32,69,120,116,101,110,115,105,111,110,70,
105,108,101,76,111,97,100,101,114,46,103,101,116,95,102,105,
108,101,110,97,109,101,78,41,14,114,112,0,0,0,114,111,
0,114,191,0,0,0,114,159,0,0,0,114,187,0,0,0,
114,202,0,0,0,114,123,0,0,0,114,157,0,0,0,114,
4,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5,
- 0,0,0,114,224,0,0,0,113,3,0,0,115,20,0,0,
+ 0,0,0,114,224,0,0,0,116,3,0,0,115,20,0,0,
0,12,6,6,2,12,4,12,4,12,3,12,8,12,6,12,
6,12,4,12,4,114,224,0,0,0,99,0,0,0,0,0,
0,0,0,0,0,0,0,2,0,0,0,64,0,0,0,115,
95,112,97,116,104,95,102,105,110,100,101,114,41,4,114,108,
0,0,0,114,106,0,0,0,114,35,0,0,0,218,11,112,
97,116,104,95,102,105,110,100,101,114,114,4,0,0,0,114,
- 4,0,0,0,114,5,0,0,0,114,185,0,0,0,173,3,
+ 4,0,0,0,114,5,0,0,0,114,185,0,0,0,176,3,
0,0,115,8,0,0,0,0,1,9,1,9,1,21,1,122,
23,95,78,97,109,101,115,112,97,99,101,80,97,116,104,46,
95,95,105,110,105,116,95,95,99,1,0,0,0,0,0,0,
41,4,114,108,0,0,0,114,222,0,0,0,218,3,100,111,
116,90,2,109,101,114,4,0,0,0,114,4,0,0,0,114,
5,0,0,0,218,23,95,102,105,110,100,95,112,97,114,101,
- 110,116,95,112,97,116,104,95,110,97,109,101,115,179,3,0,
+ 110,116,95,112,97,116,104,95,110,97,109,101,115,182,3,0,
0,115,8,0,0,0,0,2,27,1,12,2,4,3,122,38,
95,78,97,109,101,115,112,97,99,101,80,97,116,104,46,95,
102,105,110,100,95,112,97,114,101,110,116,95,112,97,116,104,
110,116,95,109,111,100,117,108,101,95,110,97,109,101,90,14,
112,97,116,104,95,97,116,116,114,95,110,97,109,101,114,4,
0,0,0,114,4,0,0,0,114,5,0,0,0,114,233,0,
- 0,0,189,3,0,0,115,4,0,0,0,0,1,18,1,122,
+ 0,0,192,3,0,0,115,4,0,0,0,0,1,18,1,122,
31,95,78,97,109,101,115,112,97,99,101,80,97,116,104,46,
95,103,101,116,95,112,97,114,101,110,116,95,112,97,116,104,
99,1,0,0,0,0,0,0,0,3,0,0,0,3,0,0,
108,0,0,0,90,11,112,97,114,101,110,116,95,112,97,116,
104,114,164,0,0,0,114,4,0,0,0,114,4,0,0,0,
114,5,0,0,0,218,12,95,114,101,99,97,108,99,117,108,
- 97,116,101,193,3,0,0,115,16,0,0,0,0,2,18,1,
+ 97,116,101,196,3,0,0,115,16,0,0,0,0,2,18,1,
15,1,21,3,27,1,9,1,12,1,9,1,122,27,95,78,
97,109,101,115,112,97,99,101,80,97,116,104,46,95,114,101,
99,97,108,99,117,108,97,116,101,99,1,0,0,0,0,0,
1,0,83,41,1,78,41,2,218,4,105,116,101,114,114,240,
0,0,0,41,1,114,108,0,0,0,114,4,0,0,0,114,
4,0,0,0,114,5,0,0,0,218,8,95,95,105,116,101,
- 114,95,95,206,3,0,0,115,2,0,0,0,0,1,122,23,
+ 114,95,95,209,3,0,0,115,2,0,0,0,0,1,122,23,
95,78,97,109,101,115,112,97,99,101,80,97,116,104,46,95,
95,105,116,101,114,95,95,99,1,0,0,0,0,0,0,0,
1,0,0,0,2,0,0,0,67,0,0,0,115,16,0,0,
0,116,0,0,124,0,0,106,1,0,131,0,0,131,1,0,
83,41,1,78,41,2,114,31,0,0,0,114,240,0,0,0,
41,1,114,108,0,0,0,114,4,0,0,0,114,4,0,0,
- 0,114,5,0,0,0,218,7,95,95,108,101,110,95,95,209,
+ 0,114,5,0,0,0,218,7,95,95,108,101,110,95,95,212,
3,0,0,115,2,0,0,0,0,1,122,22,95,78,97,109,
101,115,112,97,99,101,80,97,116,104,46,95,95,108,101,110,
95,95,99,1,0,0,0,0,0,0,0,1,0,0,0,2,
123,33,114,125,41,41,2,114,47,0,0,0,114,232,0,0,
0,41,1,114,108,0,0,0,114,4,0,0,0,114,4,0,
0,0,114,5,0,0,0,218,8,95,95,114,101,112,114,95,
- 95,212,3,0,0,115,2,0,0,0,0,1,122,23,95,78,
+ 95,215,3,0,0,115,2,0,0,0,0,1,122,23,95,78,
97,109,101,115,112,97,99,101,80,97,116,104,46,95,95,114,
101,112,114,95,95,99,2,0,0,0,0,0,0,0,2,0,
0,0,2,0,0,0,67,0,0,0,115,16,0,0,0,124,
1,78,41,1,114,240,0,0,0,41,2,114,108,0,0,0,
218,4,105,116,101,109,114,4,0,0,0,114,4,0,0,0,
114,5,0,0,0,218,12,95,95,99,111,110,116,97,105,110,
- 115,95,95,215,3,0,0,115,2,0,0,0,0,1,122,27,
+ 115,95,95,218,3,0,0,115,2,0,0,0,0,1,122,27,
95,78,97,109,101,115,112,97,99,101,80,97,116,104,46,95,
95,99,111,110,116,97,105,110,115,95,95,99,2,0,0,0,
0,0,0,0,2,0,0,0,2,0,0,0,67,0,0,0,
0,131,1,0,1,100,0,0,83,41,1,78,41,2,114,232,
0,0,0,114,163,0,0,0,41,2,114,108,0,0,0,114,
245,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5,
- 0,0,0,114,163,0,0,0,218,3,0,0,115,2,0,0,
+ 0,0,0,114,163,0,0,0,221,3,0,0,115,2,0,0,
0,0,1,122,21,95,78,97,109,101,115,112,97,99,101,80,
97,116,104,46,97,112,112,101,110,100,78,41,13,114,112,0,
0,0,114,111,0,0,0,114,113,0,0,0,114,114,0,0,
114,240,0,0,0,114,242,0,0,0,114,243,0,0,0,114,
244,0,0,0,114,246,0,0,0,114,163,0,0,0,114,4,
0,0,0,114,4,0,0,0,114,4,0,0,0,114,5,0,
- 0,0,114,230,0,0,0,166,3,0,0,115,20,0,0,0,
+ 0,0,114,230,0,0,0,169,3,0,0,115,20,0,0,0,
12,5,6,2,12,6,12,10,12,4,12,13,12,3,12,3,
12,3,12,3,114,230,0,0,0,99,0,0,0,0,0,0,
0,0,0,0,0,0,3,0,0,0,64,0,0,0,115,118,
41,1,78,41,2,114,230,0,0,0,114,232,0,0,0,41,
4,114,108,0,0,0,114,106,0,0,0,114,35,0,0,0,
114,236,0,0,0,114,4,0,0,0,114,4,0,0,0,114,
- 5,0,0,0,114,185,0,0,0,224,3,0,0,115,2,0,
+ 5,0,0,0,114,185,0,0,0,227,3,0,0,115,2,0,
0,0,0,1,122,25,95,78,97,109,101,115,112,97,99,101,
76,111,97,100,101,114,46,95,95,105,110,105,116,95,95,99,
2,0,0,0,0,0,0,0,2,0,0,0,2,0,0,0,
110,97,109,101,115,112,97,99,101,41,62,41,2,114,47,0,
0,0,114,112,0,0,0,41,2,114,170,0,0,0,114,190,
0,0,0,114,4,0,0,0,114,4,0,0,0,114,5,0,
- 0,0,218,11,109,111,100,117,108,101,95,114,101,112,114,227,
+ 0,0,218,11,109,111,100,117,108,101,95,114,101,112,114,230,
3,0,0,115,2,0,0,0,0,7,122,28,95,78,97,109,
101,115,112,97,99,101,76,111,97,100,101,114,46,109,111,100,
117,108,101,95,114,101,112,114,99,2,0,0,0,0,0,0,
0,2,0,0,0,1,0,0,0,67,0,0,0,115,4,0,
0,0,100,1,0,83,41,2,78,84,114,4,0,0,0,41,
2,114,108,0,0,0,114,126,0,0,0,114,4,0,0,0,
- 114,4,0,0,0,114,5,0,0,0,114,159,0,0,0,236,
+ 114,4,0,0,0,114,5,0,0,0,114,159,0,0,0,239,
3,0,0,115,2,0,0,0,0,1,122,27,95,78,97,109,
101,115,112,97,99,101,76,111,97,100,101,114,46,105,115,95,
112,97,99,107,97,103,101,99,2,0,0,0,0,0,0,0,
0,100,1,0,83,41,2,78,114,30,0,0,0,114,4,0,
0,0,41,2,114,108,0,0,0,114,126,0,0,0,114,4,
0,0,0,114,4,0,0,0,114,5,0,0,0,114,202,0,
- 0,0,239,3,0,0,115,2,0,0,0,0,1,122,27,95,
+ 0,0,242,3,0,0,115,2,0,0,0,0,1,122,27,95,
78,97,109,101,115,112,97,99,101,76,111,97,100,101,114,46,
103,101,116,95,115,111,117,114,99,101,99,2,0,0,0,0,
0,0,0,2,0,0,0,6,0,0,0,67,0,0,0,115,
0,0,122,8,60,115,116,114,105,110,103,62,114,189,0,0,
0,114,204,0,0,0,84,41,1,114,205,0,0,0,41,2,
114,108,0,0,0,114,126,0,0,0,114,4,0,0,0,114,
- 4,0,0,0,114,5,0,0,0,114,187,0,0,0,242,3,
+ 4,0,0,0,114,5,0,0,0,114,187,0,0,0,245,3,
0,0,115,2,0,0,0,0,1,122,25,95,78,97,109,101,
115,112,97,99,101,76,111,97,100,101,114,46,103,101,116,95,
99,111,100,101,99,2,0,0,0,0,0,0,0,2,0,0,
109,111,100,117,108,101,32,99,114,101,97,116,105,111,110,46,
78,114,4,0,0,0,41,2,114,108,0,0,0,114,164,0,
0,0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,
- 0,114,186,0,0,0,245,3,0,0,115,0,0,0,0,122,
+ 0,114,186,0,0,0,248,3,0,0,115,0,0,0,0,122,
30,95,78,97,109,101,115,112,97,99,101,76,111,97,100,101,
114,46,99,114,101,97,116,101,95,109,111,100,117,108,101,99,
2,0,0,0,0,0,0,0,2,0,0,0,1,0,0,0,
67,0,0,0,115,4,0,0,0,100,0,0,83,41,1,78,
114,4,0,0,0,41,2,114,108,0,0,0,114,190,0,0,
0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,
- 114,191,0,0,0,248,3,0,0,115,2,0,0,0,0,1,
+ 114,191,0,0,0,251,3,0,0,115,2,0,0,0,0,1,
122,28,95,78,97,109,101,115,112,97,99,101,76,111,97,100,
101,114,46,101,120,101,99,95,109,111,100,117,108,101,99,2,
0,0,0,0,0,0,0,2,0,0,0,3,0,0,0,67,
104,32,123,33,114,125,41,4,114,105,0,0,0,114,232,0,
0,0,114,121,0,0,0,114,192,0,0,0,41,2,114,108,
0,0,0,114,126,0,0,0,114,4,0,0,0,114,4,0,
- 0,0,114,5,0,0,0,114,193,0,0,0,251,3,0,0,
+ 0,0,114,5,0,0,0,114,193,0,0,0,254,3,0,0,
115,4,0,0,0,0,7,16,1,122,28,95,78,97,109,101,
115,112,97,99,101,76,111,97,100,101,114,46,108,111,97,100,
95,109,111,100,117,108,101,78,41,12,114,112,0,0,0,114,
0,0,0,114,248,0,0,0,114,159,0,0,0,114,202,0,
0,0,114,187,0,0,0,114,186,0,0,0,114,191,0,0,
0,114,193,0,0,0,114,4,0,0,0,114,4,0,0,0,
- 114,4,0,0,0,114,5,0,0,0,114,247,0,0,0,223,
+ 114,4,0,0,0,114,5,0,0,0,114,247,0,0,0,226,
3,0,0,115,16,0,0,0,12,1,12,3,18,9,12,3,
12,3,12,3,12,3,12,3,114,247,0,0,0,99,0,0,
0,0,0,0,0,0,0,0,0,0,5,0,0,0,64,0,
114,95,99,97,99,104,101,218,6,118,97,108,117,101,115,114,
115,0,0,0,114,250,0,0,0,41,2,114,170,0,0,0,
218,6,102,105,110,100,101,114,114,4,0,0,0,114,4,0,
- 0,0,114,5,0,0,0,114,250,0,0,0,12,4,0,0,
+ 0,0,114,5,0,0,0,114,250,0,0,0,15,4,0,0,
115,6,0,0,0,0,4,22,1,15,1,122,28,80,97,116,
104,70,105,110,100,101,114,46,105,110,118,97,108,105,100,97,
116,101,95,99,97,99,104,101,115,99,2,0,0,0,0,0,
107,0,0,0,41,3,114,170,0,0,0,114,35,0,0,0,
90,4,104,111,111,107,114,4,0,0,0,114,4,0,0,0,
114,5,0,0,0,218,11,95,112,97,116,104,95,104,111,111,
- 107,115,20,4,0,0,115,16,0,0,0,0,7,25,1,16,
+ 107,115,23,4,0,0,115,16,0,0,0,0,7,25,1,16,
1,16,1,3,1,14,1,13,1,12,2,122,22,80,97,116,
104,70,105,110,100,101,114,46,95,112,97,116,104,95,104,111,
111,107,115,99,2,0,0,0,0,0,0,0,3,0,0,0,
0,0,114,255,0,0,0,41,3,114,170,0,0,0,114,35,
0,0,0,114,253,0,0,0,114,4,0,0,0,114,4,0,
0,0,114,5,0,0,0,218,20,95,112,97,116,104,95,105,
- 109,112,111,114,116,101,114,95,99,97,99,104,101,37,4,0,
+ 109,112,111,114,116,101,114,95,99,97,99,104,101,40,4,0,
0,115,22,0,0,0,0,8,12,1,3,1,16,1,13,3,
9,1,3,1,17,1,13,1,15,1,18,1,122,31,80,97,
116,104,70,105,110,100,101,114,46,95,112,97,116,104,95,105,
0,0,114,126,0,0,0,114,253,0,0,0,114,127,0,0,
0,114,128,0,0,0,114,164,0,0,0,114,4,0,0,0,
114,4,0,0,0,114,5,0,0,0,218,16,95,108,101,103,
- 97,99,121,95,103,101,116,95,115,112,101,99,59,4,0,0,
+ 97,99,121,95,103,101,116,95,115,112,101,99,62,4,0,0,
115,18,0,0,0,0,4,15,1,24,2,15,1,6,1,12,
1,16,1,18,1,9,1,122,27,80,97,116,104,70,105,110,
100,101,114,46,95,108,101,103,97,99,121,95,103,101,116,95,
101,115,112,97,99,101,95,112,97,116,104,90,5,101,110,116,
114,121,114,253,0,0,0,114,164,0,0,0,114,128,0,0,
0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,
- 218,9,95,103,101,116,95,115,112,101,99,74,4,0,0,115,
+ 218,9,95,103,101,116,95,115,112,101,99,77,4,0,0,115,
40,0,0,0,0,5,6,1,13,1,21,1,3,1,15,1,
12,1,15,1,21,2,18,1,12,1,3,1,15,1,4,1,
9,1,12,1,12,5,17,2,18,1,9,1,122,20,80,97,
6,114,170,0,0,0,114,126,0,0,0,114,35,0,0,0,
114,180,0,0,0,114,164,0,0,0,114,4,1,0,0,114,
4,0,0,0,114,4,0,0,0,114,5,0,0,0,114,181,
- 0,0,0,106,4,0,0,115,26,0,0,0,0,4,12,1,
+ 0,0,0,109,4,0,0,115,26,0,0,0,0,4,12,1,
9,1,21,1,12,1,4,1,15,1,9,1,6,3,9,1,
24,1,4,2,7,2,122,20,80,97,116,104,70,105,110,100,
101,114,46,102,105,110,100,95,115,112,101,99,99,3,0,0,
114,181,0,0,0,114,127,0,0,0,41,4,114,170,0,0,
0,114,126,0,0,0,114,35,0,0,0,114,164,0,0,0,
114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,114,
- 182,0,0,0,128,4,0,0,115,8,0,0,0,0,8,18,
+ 182,0,0,0,131,4,0,0,115,8,0,0,0,0,8,18,
1,12,1,4,1,122,22,80,97,116,104,70,105,110,100,101,
114,46,102,105,110,100,95,109,111,100,117,108,101,41,12,114,
112,0,0,0,114,111,0,0,0,114,113,0,0,0,114,114,
0,0,114,1,1,0,0,114,2,1,0,0,114,5,1,0,
0,114,181,0,0,0,114,182,0,0,0,114,4,0,0,0,
114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,114,
- 249,0,0,0,8,4,0,0,115,22,0,0,0,12,2,6,
+ 249,0,0,0,11,4,0,0,115,22,0,0,0,12,2,6,
2,18,8,18,17,18,22,18,15,3,1,18,31,3,1,21,
21,3,1,114,249,0,0,0,99,0,0,0,0,0,0,0,
0,0,0,0,0,3,0,0,0,64,0,0,0,115,133,0,
0,86,1,113,3,0,100,0,0,83,41,1,78,114,4,0,
0,0,41,2,114,22,0,0,0,114,225,0,0,0,41,1,
114,127,0,0,0,114,4,0,0,0,114,5,0,0,0,114,
- 227,0,0,0,157,4,0,0,115,2,0,0,0,6,0,122,
+ 227,0,0,0,160,4,0,0,115,2,0,0,0,6,0,122,
38,70,105,108,101,70,105,110,100,101,114,46,95,95,105,110,
105,116,95,95,46,60,108,111,99,97,108,115,62,46,60,103,
101,110,101,120,112,114,62,114,58,0,0,0,114,29,0,0,
111,97,100,101,114,95,100,101,116,97,105,108,115,90,7,108,
111,97,100,101,114,115,114,166,0,0,0,114,4,0,0,0,
41,1,114,127,0,0,0,114,5,0,0,0,114,185,0,0,
- 0,151,4,0,0,115,16,0,0,0,0,4,6,1,19,1,
+ 0,154,4,0,0,115,16,0,0,0,0,4,6,1,19,1,
36,1,9,2,15,1,9,1,12,1,122,19,70,105,108,101,
70,105,110,100,101,114,46,95,95,105,110,105,116,95,95,99,
1,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,
114,121,32,109,116,105,109,101,46,114,29,0,0,0,78,114,
87,0,0,0,41,1,114,8,1,0,0,41,1,114,108,0,
0,0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,
- 0,114,250,0,0,0,165,4,0,0,115,2,0,0,0,0,
+ 0,114,250,0,0,0,168,4,0,0,115,2,0,0,0,0,
2,122,28,70,105,108,101,70,105,110,100,101,114,46,105,110,
118,97,108,105,100,97,116,101,95,99,97,99,104,101,115,99,
2,0,0,0,0,0,0,0,3,0,0,0,2,0,0,0,
114,181,0,0,0,114,127,0,0,0,114,156,0,0,0,41,
3,114,108,0,0,0,114,126,0,0,0,114,164,0,0,0,
114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,114,
- 124,0,0,0,171,4,0,0,115,8,0,0,0,0,7,15,
+ 124,0,0,0,174,4,0,0,115,8,0,0,0,0,7,15,
1,12,1,10,1,122,22,70,105,108,101,70,105,110,100,101,
114,46,102,105,110,100,95,108,111,97,100,101,114,99,6,0,
0,0,0,0,0,0,7,0,0,0,7,0,0,0,67,0,
0,0,0,41,7,114,108,0,0,0,114,165,0,0,0,114,
126,0,0,0,114,35,0,0,0,90,4,115,109,115,108,114,
180,0,0,0,114,127,0,0,0,114,4,0,0,0,114,4,
- 0,0,0,114,5,0,0,0,114,5,1,0,0,183,4,0,
+ 0,0,0,114,5,0,0,0,114,5,1,0,0,186,4,0,
0,115,6,0,0,0,0,1,15,1,18,1,122,20,70,105,
108,101,70,105,110,100,101,114,46,95,103,101,116,95,115,112,
101,99,78,99,3,0,0,0,0,0,0,0,14,0,0,0,
0,100,9,0,106,19,0,124,8,0,131,1,0,131,1,0,
1,116,20,0,106,21,0,124,1,0,100,8,0,131,2,0,
125,13,0,124,8,0,103,1,0,124,13,0,95,22,0,124,
- 13,0,83,100,8,0,83,41,11,122,125,84,114,121,32,116,
- 111,32,102,105,110,100,32,97,32,108,111,97,100,101,114,32,
- 102,111,114,32,116,104,101,32,115,112,101,99,105,102,105,101,
- 100,32,109,111,100,117,108,101,44,32,111,114,32,116,104,101,
- 32,110,97,109,101,115,112,97,99,101,10,32,32,32,32,32,
- 32,32,32,112,97,99,107,97,103,101,32,112,111,114,116,105,
- 111,110,115,46,32,82,101,116,117,114,110,115,32,40,108,111,
- 97,100,101,114,44,32,108,105,115,116,45,111,102,45,112,111,
- 114,116,105,111,110,115,41,46,70,114,58,0,0,0,114,56,
- 0,0,0,114,29,0,0,0,114,185,0,0,0,122,9,116,
- 114,121,105,110,103,32,123,125,114,98,0,0,0,78,122,25,
- 112,111,115,115,105,98,108,101,32,110,97,109,101,115,112,97,
- 99,101,32,102,111,114,32,123,125,114,87,0,0,0,41,23,
- 114,32,0,0,0,114,39,0,0,0,114,35,0,0,0,114,
- 3,0,0,0,114,45,0,0,0,114,219,0,0,0,114,40,
- 0,0,0,114,8,1,0,0,218,11,95,102,105,108,108,95,
- 99,97,99,104,101,114,6,0,0,0,114,11,1,0,0,114,
- 88,0,0,0,114,10,1,0,0,114,28,0,0,0,114,7,
- 1,0,0,114,44,0,0,0,114,5,1,0,0,114,46,0,
- 0,0,114,105,0,0,0,114,47,0,0,0,114,121,0,0,
- 0,114,160,0,0,0,114,156,0,0,0,41,14,114,108,0,
- 0,0,114,126,0,0,0,114,180,0,0,0,90,12,105,115,
- 95,110,97,109,101,115,112,97,99,101,90,11,116,97,105,108,
- 95,109,111,100,117,108,101,114,133,0,0,0,90,5,99,97,
- 99,104,101,90,12,99,97,99,104,101,95,109,111,100,117,108,
- 101,90,9,98,97,115,101,95,112,97,116,104,114,225,0,0,
- 0,114,165,0,0,0,90,13,105,110,105,116,95,102,105,108,
- 101,110,97,109,101,90,9,102,117,108,108,95,112,97,116,104,
- 114,164,0,0,0,114,4,0,0,0,114,4,0,0,0,114,
- 5,0,0,0,114,181,0,0,0,188,4,0,0,115,68,0,
- 0,0,0,3,6,1,19,1,3,1,34,1,13,1,11,1,
- 15,1,10,1,9,2,9,1,9,1,15,2,9,1,6,2,
- 12,1,18,1,22,1,10,1,15,1,12,1,32,4,12,2,
- 22,1,22,1,25,1,16,1,12,1,29,1,6,1,19,1,
- 18,1,12,1,4,1,122,20,70,105,108,101,70,105,110,100,
- 101,114,46,102,105,110,100,95,115,112,101,99,99,1,0,0,
- 0,0,0,0,0,9,0,0,0,13,0,0,0,67,0,0,
- 0,115,11,1,0,0,124,0,0,106,0,0,125,1,0,121,
- 31,0,116,1,0,106,2,0,124,1,0,112,33,0,116,1,
- 0,106,3,0,131,0,0,131,1,0,125,2,0,87,110,33,
- 0,4,116,4,0,116,5,0,116,6,0,102,3,0,107,10,
- 0,114,75,0,1,1,1,103,0,0,125,2,0,89,110,1,
- 0,88,116,7,0,106,8,0,106,9,0,100,1,0,131,1,
- 0,115,112,0,116,10,0,124,2,0,131,1,0,124,0,0,
- 95,11,0,110,111,0,116,10,0,131,0,0,125,3,0,120,
- 90,0,124,2,0,68,93,82,0,125,4,0,124,4,0,106,
- 12,0,100,2,0,131,1,0,92,3,0,125,5,0,125,6,
- 0,125,7,0,124,6,0,114,191,0,100,3,0,106,13,0,
- 124,5,0,124,7,0,106,14,0,131,0,0,131,2,0,125,
- 8,0,110,6,0,124,5,0,125,8,0,124,3,0,106,15,
- 0,124,8,0,131,1,0,1,113,128,0,87,124,3,0,124,
- 0,0,95,11,0,116,7,0,106,8,0,106,9,0,116,16,
- 0,131,1,0,114,7,1,100,4,0,100,5,0,132,0,0,
- 124,2,0,68,131,1,0,124,0,0,95,17,0,100,6,0,
- 83,41,7,122,68,70,105,108,108,32,116,104,101,32,99,97,
- 99,104,101,32,111,102,32,112,111,116,101,110,116,105,97,108,
- 32,109,111,100,117,108,101,115,32,97,110,100,32,112,97,99,
- 107,97,103,101,115,32,102,111,114,32,116,104,105,115,32,100,
- 105,114,101,99,116,111,114,121,46,114,0,0,0,0,114,58,
- 0,0,0,122,5,123,125,46,123,125,99,1,0,0,0,0,
- 0,0,0,2,0,0,0,3,0,0,0,83,0,0,0,115,
- 28,0,0,0,104,0,0,124,0,0,93,18,0,125,1,0,
- 124,1,0,106,0,0,131,0,0,146,2,0,113,6,0,83,
- 114,4,0,0,0,41,1,114,88,0,0,0,41,2,114,22,
- 0,0,0,90,2,102,110,114,4,0,0,0,114,4,0,0,
- 0,114,5,0,0,0,250,9,60,115,101,116,99,111,109,112,
- 62,6,5,0,0,115,2,0,0,0,9,0,122,41,70,105,
- 108,101,70,105,110,100,101,114,46,95,102,105,108,108,95,99,
- 97,99,104,101,46,60,108,111,99,97,108,115,62,46,60,115,
- 101,116,99,111,109,112,62,78,41,18,114,35,0,0,0,114,
- 3,0,0,0,90,7,108,105,115,116,100,105,114,114,45,0,
- 0,0,114,0,1,0,0,218,15,80,101,114,109,105,115,115,
- 105,111,110,69,114,114,111,114,218,18,78,111,116,65,68,105,
- 114,101,99,116,111,114,121,69,114,114,111,114,114,7,0,0,
- 0,114,8,0,0,0,114,9,0,0,0,114,9,1,0,0,
- 114,10,1,0,0,114,83,0,0,0,114,47,0,0,0,114,
- 88,0,0,0,218,3,97,100,100,114,10,0,0,0,114,11,
- 1,0,0,41,9,114,108,0,0,0,114,35,0,0,0,90,
- 8,99,111,110,116,101,110,116,115,90,21,108,111,119,101,114,
- 95,115,117,102,102,105,120,95,99,111,110,116,101,110,116,115,
- 114,245,0,0,0,114,106,0,0,0,114,237,0,0,0,114,
- 225,0,0,0,90,8,110,101,119,95,110,97,109,101,114,4,
- 0,0,0,114,4,0,0,0,114,5,0,0,0,114,13,1,
- 0,0,233,4,0,0,115,34,0,0,0,0,2,9,1,3,
- 1,31,1,22,3,11,3,18,1,18,7,9,1,13,1,24,
- 1,6,1,27,2,6,1,17,1,9,1,18,1,122,22,70,
- 105,108,101,70,105,110,100,101,114,46,95,102,105,108,108,95,
- 99,97,99,104,101,99,1,0,0,0,0,0,0,0,3,0,
- 0,0,3,0,0,0,7,0,0,0,115,25,0,0,0,135,
- 0,0,135,1,0,102,2,0,100,1,0,100,2,0,134,0,
- 0,125,2,0,124,2,0,83,41,3,97,20,1,0,0,65,
- 32,99,108,97,115,115,32,109,101,116,104,111,100,32,119,104,
- 105,99,104,32,114,101,116,117,114,110,115,32,97,32,99,108,
- 111,115,117,114,101,32,116,111,32,117,115,101,32,111,110,32,
- 115,121,115,46,112,97,116,104,95,104,111,111,107,10,32,32,
- 32,32,32,32,32,32,119,104,105,99,104,32,119,105,108,108,
- 32,114,101,116,117,114,110,32,97,110,32,105,110,115,116,97,
- 110,99,101,32,117,115,105,110,103,32,116,104,101,32,115,112,
- 101,99,105,102,105,101,100,32,108,111,97,100,101,114,115,32,
- 97,110,100,32,116,104,101,32,112,97,116,104,10,32,32,32,
- 32,32,32,32,32,99,97,108,108,101,100,32,111,110,32,116,
- 104,101,32,99,108,111,115,117,114,101,46,10,10,32,32,32,
- 32,32,32,32,32,73,102,32,116,104,101,32,112,97,116,104,
- 32,99,97,108,108,101,100,32,111,110,32,116,104,101,32,99,
- 108,111,115,117,114,101,32,105,115,32,110,111,116,32,97,32,
- 100,105,114,101,99,116,111,114,121,44,32,73,109,112,111,114,
- 116,69,114,114,111,114,32,105,115,10,32,32,32,32,32,32,
- 32,32,114,97,105,115,101,100,46,10,10,32,32,32,32,32,
- 32,32,32,99,1,0,0,0,0,0,0,0,1,0,0,0,
- 4,0,0,0,19,0,0,0,115,43,0,0,0,116,0,0,
- 124,0,0,131,1,0,115,30,0,116,1,0,100,1,0,100,
- 2,0,124,0,0,131,1,1,130,1,0,136,0,0,124,0,
- 0,136,1,0,140,1,0,83,41,3,122,45,80,97,116,104,
- 32,104,111,111,107,32,102,111,114,32,105,109,112,111,114,116,
- 108,105,98,46,109,97,99,104,105,110,101,114,121,46,70,105,
- 108,101,70,105,110,100,101,114,46,122,30,111,110,108,121,32,
- 100,105,114,101,99,116,111,114,105,101,115,32,97,114,101,32,
- 115,117,112,112,111,114,116,101,100,114,35,0,0,0,41,2,
- 114,46,0,0,0,114,107,0,0,0,41,1,114,35,0,0,
- 0,41,2,114,170,0,0,0,114,12,1,0,0,114,4,0,
- 0,0,114,5,0,0,0,218,24,112,97,116,104,95,104,111,
+ 13,0,83,100,8,0,83,41,11,122,102,84,114,121,32,116,
+ 111,32,102,105,110,100,32,97,32,115,112,101,99,32,102,111,
+ 114,32,116,104,101,32,115,112,101,99,105,102,105,101,100,32,
+ 109,111,100,117,108,101,46,32,32,82,101,116,117,114,110,115,
+ 32,116,104,101,10,32,32,32,32,32,32,32,32,109,97,116,
+ 99,104,105,110,103,32,115,112,101,99,44,32,111,114,32,78,
+ 111,110,101,32,105,102,32,110,111,116,32,102,111,117,110,100,
+ 46,70,114,58,0,0,0,114,56,0,0,0,114,29,0,0,
+ 0,114,185,0,0,0,122,9,116,114,121,105,110,103,32,123,
+ 125,114,98,0,0,0,78,122,25,112,111,115,115,105,98,108,
+ 101,32,110,97,109,101,115,112,97,99,101,32,102,111,114,32,
+ 123,125,114,87,0,0,0,41,23,114,32,0,0,0,114,39,
+ 0,0,0,114,35,0,0,0,114,3,0,0,0,114,45,0,
+ 0,0,114,219,0,0,0,114,40,0,0,0,114,8,1,0,
+ 0,218,11,95,102,105,108,108,95,99,97,99,104,101,114,6,
+ 0,0,0,114,11,1,0,0,114,88,0,0,0,114,10,1,
+ 0,0,114,28,0,0,0,114,7,1,0,0,114,44,0,0,
+ 0,114,5,1,0,0,114,46,0,0,0,114,105,0,0,0,
+ 114,47,0,0,0,114,121,0,0,0,114,160,0,0,0,114,
+ 156,0,0,0,41,14,114,108,0,0,0,114,126,0,0,0,
+ 114,180,0,0,0,90,12,105,115,95,110,97,109,101,115,112,
+ 97,99,101,90,11,116,97,105,108,95,109,111,100,117,108,101,
+ 114,133,0,0,0,90,5,99,97,99,104,101,90,12,99,97,
+ 99,104,101,95,109,111,100,117,108,101,90,9,98,97,115,101,
+ 95,112,97,116,104,114,225,0,0,0,114,165,0,0,0,90,
+ 13,105,110,105,116,95,102,105,108,101,110,97,109,101,90,9,
+ 102,117,108,108,95,112,97,116,104,114,164,0,0,0,114,4,
+ 0,0,0,114,4,0,0,0,114,5,0,0,0,114,181,0,
+ 0,0,191,4,0,0,115,68,0,0,0,0,3,6,1,19,
+ 1,3,1,34,1,13,1,11,1,15,1,10,1,9,2,9,
+ 1,9,1,15,2,9,1,6,2,12,1,18,1,22,1,10,
+ 1,15,1,12,1,32,4,12,2,22,1,22,1,25,1,16,
+ 1,12,1,29,1,6,1,19,1,18,1,12,1,4,1,122,
+ 20,70,105,108,101,70,105,110,100,101,114,46,102,105,110,100,
+ 95,115,112,101,99,99,1,0,0,0,0,0,0,0,9,0,
+ 0,0,13,0,0,0,67,0,0,0,115,11,1,0,0,124,
+ 0,0,106,0,0,125,1,0,121,31,0,116,1,0,106,2,
+ 0,124,1,0,112,33,0,116,1,0,106,3,0,131,0,0,
+ 131,1,0,125,2,0,87,110,33,0,4,116,4,0,116,5,
+ 0,116,6,0,102,3,0,107,10,0,114,75,0,1,1,1,
+ 103,0,0,125,2,0,89,110,1,0,88,116,7,0,106,8,
+ 0,106,9,0,100,1,0,131,1,0,115,112,0,116,10,0,
+ 124,2,0,131,1,0,124,0,0,95,11,0,110,111,0,116,
+ 10,0,131,0,0,125,3,0,120,90,0,124,2,0,68,93,
+ 82,0,125,4,0,124,4,0,106,12,0,100,2,0,131,1,
+ 0,92,3,0,125,5,0,125,6,0,125,7,0,124,6,0,
+ 114,191,0,100,3,0,106,13,0,124,5,0,124,7,0,106,
+ 14,0,131,0,0,131,2,0,125,8,0,110,6,0,124,5,
+ 0,125,8,0,124,3,0,106,15,0,124,8,0,131,1,0,
+ 1,113,128,0,87,124,3,0,124,0,0,95,11,0,116,7,
+ 0,106,8,0,106,9,0,116,16,0,131,1,0,114,7,1,
+ 100,4,0,100,5,0,132,0,0,124,2,0,68,131,1,0,
+ 124,0,0,95,17,0,100,6,0,83,41,7,122,68,70,105,
+ 108,108,32,116,104,101,32,99,97,99,104,101,32,111,102,32,
+ 112,111,116,101,110,116,105,97,108,32,109,111,100,117,108,101,
+ 115,32,97,110,100,32,112,97,99,107,97,103,101,115,32,102,
+ 111,114,32,116,104,105,115,32,100,105,114,101,99,116,111,114,
+ 121,46,114,0,0,0,0,114,58,0,0,0,122,5,123,125,
+ 46,123,125,99,1,0,0,0,0,0,0,0,2,0,0,0,
+ 3,0,0,0,83,0,0,0,115,28,0,0,0,104,0,0,
+ 124,0,0,93,18,0,125,1,0,124,1,0,106,0,0,131,
+ 0,0,146,2,0,113,6,0,83,114,4,0,0,0,41,1,
+ 114,88,0,0,0,41,2,114,22,0,0,0,90,2,102,110,
+ 114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,250,
+ 9,60,115,101,116,99,111,109,112,62,9,5,0,0,115,2,
+ 0,0,0,9,0,122,41,70,105,108,101,70,105,110,100,101,
+ 114,46,95,102,105,108,108,95,99,97,99,104,101,46,60,108,
+ 111,99,97,108,115,62,46,60,115,101,116,99,111,109,112,62,
+ 78,41,18,114,35,0,0,0,114,3,0,0,0,90,7,108,
+ 105,115,116,100,105,114,114,45,0,0,0,114,0,1,0,0,
+ 218,15,80,101,114,109,105,115,115,105,111,110,69,114,114,111,
+ 114,218,18,78,111,116,65,68,105,114,101,99,116,111,114,121,
+ 69,114,114,111,114,114,7,0,0,0,114,8,0,0,0,114,
+ 9,0,0,0,114,9,1,0,0,114,10,1,0,0,114,83,
+ 0,0,0,114,47,0,0,0,114,88,0,0,0,218,3,97,
+ 100,100,114,10,0,0,0,114,11,1,0,0,41,9,114,108,
+ 0,0,0,114,35,0,0,0,90,8,99,111,110,116,101,110,
+ 116,115,90,21,108,111,119,101,114,95,115,117,102,102,105,120,
+ 95,99,111,110,116,101,110,116,115,114,245,0,0,0,114,106,
+ 0,0,0,114,237,0,0,0,114,225,0,0,0,90,8,110,
+ 101,119,95,110,97,109,101,114,4,0,0,0,114,4,0,0,
+ 0,114,5,0,0,0,114,13,1,0,0,236,4,0,0,115,
+ 34,0,0,0,0,2,9,1,3,1,31,1,22,3,11,3,
+ 18,1,18,7,9,1,13,1,24,1,6,1,27,2,6,1,
+ 17,1,9,1,18,1,122,22,70,105,108,101,70,105,110,100,
+ 101,114,46,95,102,105,108,108,95,99,97,99,104,101,99,1,
+ 0,0,0,0,0,0,0,3,0,0,0,3,0,0,0,7,
+ 0,0,0,115,25,0,0,0,135,0,0,135,1,0,102,2,
+ 0,100,1,0,100,2,0,134,0,0,125,2,0,124,2,0,
+ 83,41,3,97,20,1,0,0,65,32,99,108,97,115,115,32,
+ 109,101,116,104,111,100,32,119,104,105,99,104,32,114,101,116,
+ 117,114,110,115,32,97,32,99,108,111,115,117,114,101,32,116,
+ 111,32,117,115,101,32,111,110,32,115,121,115,46,112,97,116,
+ 104,95,104,111,111,107,10,32,32,32,32,32,32,32,32,119,
+ 104,105,99,104,32,119,105,108,108,32,114,101,116,117,114,110,
+ 32,97,110,32,105,110,115,116,97,110,99,101,32,117,115,105,
+ 110,103,32,116,104,101,32,115,112,101,99,105,102,105,101,100,
+ 32,108,111,97,100,101,114,115,32,97,110,100,32,116,104,101,
+ 32,112,97,116,104,10,32,32,32,32,32,32,32,32,99,97,
+ 108,108,101,100,32,111,110,32,116,104,101,32,99,108,111,115,
+ 117,114,101,46,10,10,32,32,32,32,32,32,32,32,73,102,
+ 32,116,104,101,32,112,97,116,104,32,99,97,108,108,101,100,
+ 32,111,110,32,116,104,101,32,99,108,111,115,117,114,101,32,
+ 105,115,32,110,111,116,32,97,32,100,105,114,101,99,116,111,
+ 114,121,44,32,73,109,112,111,114,116,69,114,114,111,114,32,
+ 105,115,10,32,32,32,32,32,32,32,32,114,97,105,115,101,
+ 100,46,10,10,32,32,32,32,32,32,32,32,99,1,0,0,
+ 0,0,0,0,0,1,0,0,0,4,0,0,0,19,0,0,
+ 0,115,43,0,0,0,116,0,0,124,0,0,131,1,0,115,
+ 30,0,116,1,0,100,1,0,100,2,0,124,0,0,131,1,
+ 1,130,1,0,136,0,0,124,0,0,136,1,0,140,1,0,
+ 83,41,3,122,45,80,97,116,104,32,104,111,111,107,32,102,
+ 111,114,32,105,109,112,111,114,116,108,105,98,46,109,97,99,
+ 104,105,110,101,114,121,46,70,105,108,101,70,105,110,100,101,
+ 114,46,122,30,111,110,108,121,32,100,105,114,101,99,116,111,
+ 114,105,101,115,32,97,114,101,32,115,117,112,112,111,114,116,
+ 101,100,114,35,0,0,0,41,2,114,46,0,0,0,114,107,
+ 0,0,0,41,1,114,35,0,0,0,41,2,114,170,0,0,
+ 0,114,12,1,0,0,114,4,0,0,0,114,5,0,0,0,
+ 218,24,112,97,116,104,95,104,111,111,107,95,102,111,114,95,
+ 70,105,108,101,70,105,110,100,101,114,21,5,0,0,115,6,
+ 0,0,0,0,2,12,1,18,1,122,54,70,105,108,101,70,
+ 105,110,100,101,114,46,112,97,116,104,95,104,111,111,107,46,
+ 60,108,111,99,97,108,115,62,46,112,97,116,104,95,104,111,
111,107,95,102,111,114,95,70,105,108,101,70,105,110,100,101,
- 114,18,5,0,0,115,6,0,0,0,0,2,12,1,18,1,
- 122,54,70,105,108,101,70,105,110,100,101,114,46,112,97,116,
- 104,95,104,111,111,107,46,60,108,111,99,97,108,115,62,46,
- 112,97,116,104,95,104,111,111,107,95,102,111,114,95,70,105,
- 108,101,70,105,110,100,101,114,114,4,0,0,0,41,3,114,
- 170,0,0,0,114,12,1,0,0,114,18,1,0,0,114,4,
- 0,0,0,41,2,114,170,0,0,0,114,12,1,0,0,114,
- 5,0,0,0,218,9,112,97,116,104,95,104,111,111,107,8,
- 5,0,0,115,4,0,0,0,0,10,21,6,122,20,70,105,
- 108,101,70,105,110,100,101,114,46,112,97,116,104,95,104,111,
- 111,107,99,1,0,0,0,0,0,0,0,1,0,0,0,2,
- 0,0,0,67,0,0,0,115,16,0,0,0,100,1,0,106,
- 0,0,124,0,0,106,1,0,131,1,0,83,41,2,78,122,
- 16,70,105,108,101,70,105,110,100,101,114,40,123,33,114,125,
- 41,41,2,114,47,0,0,0,114,35,0,0,0,41,1,114,
- 108,0,0,0,114,4,0,0,0,114,4,0,0,0,114,5,
- 0,0,0,114,244,0,0,0,26,5,0,0,115,2,0,0,
- 0,0,1,122,19,70,105,108,101,70,105,110,100,101,114,46,
- 95,95,114,101,112,114,95,95,41,15,114,112,0,0,0,114,
- 111,0,0,0,114,113,0,0,0,114,114,0,0,0,114,185,
- 0,0,0,114,250,0,0,0,114,130,0,0,0,114,182,0,
- 0,0,114,124,0,0,0,114,5,1,0,0,114,181,0,0,
- 0,114,13,1,0,0,114,183,0,0,0,114,19,1,0,0,
- 114,244,0,0,0,114,4,0,0,0,114,4,0,0,0,114,
- 4,0,0,0,114,5,0,0,0,114,6,1,0,0,142,4,
- 0,0,115,20,0,0,0,12,7,6,2,12,14,12,4,6,
- 2,12,12,12,5,15,45,12,31,18,18,114,6,1,0,0,
- 99,4,0,0,0,0,0,0,0,6,0,0,0,11,0,0,
- 0,67,0,0,0,115,195,0,0,0,124,0,0,106,0,0,
- 100,1,0,131,1,0,125,4,0,124,0,0,106,0,0,100,
- 2,0,131,1,0,125,5,0,124,4,0,115,99,0,124,5,
- 0,114,54,0,124,5,0,106,1,0,125,4,0,110,45,0,
- 124,2,0,124,3,0,107,2,0,114,84,0,116,2,0,124,
- 1,0,124,2,0,131,2,0,125,4,0,110,15,0,116,3,
- 0,124,1,0,124,2,0,131,2,0,125,4,0,124,5,0,
- 115,126,0,116,4,0,124,1,0,124,2,0,100,3,0,124,
- 4,0,131,2,1,125,5,0,121,44,0,124,5,0,124,0,
- 0,100,2,0,60,124,4,0,124,0,0,100,1,0,60,124,
- 2,0,124,0,0,100,4,0,60,124,3,0,124,0,0,100,
- 5,0,60,87,110,18,0,4,116,5,0,107,10,0,114,190,
- 0,1,1,1,89,110,1,0,88,100,0,0,83,41,6,78,
- 218,10,95,95,108,111,97,100,101,114,95,95,218,8,95,95,
- 115,112,101,99,95,95,114,127,0,0,0,90,8,95,95,102,
- 105,108,101,95,95,90,10,95,95,99,97,99,104,101,100,95,
- 95,41,6,218,3,103,101,116,114,127,0,0,0,114,223,0,
- 0,0,114,218,0,0,0,114,167,0,0,0,218,9,69,120,
- 99,101,112,116,105,111,110,41,6,90,2,110,115,114,106,0,
- 0,0,90,8,112,97,116,104,110,97,109,101,90,9,99,112,
- 97,116,104,110,97,109,101,114,127,0,0,0,114,164,0,0,
- 0,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,
- 218,14,95,102,105,120,95,117,112,95,109,111,100,117,108,101,
- 32,5,0,0,115,34,0,0,0,0,2,15,1,15,1,6,
- 1,6,1,12,1,12,1,18,2,15,1,6,1,21,1,3,
- 1,10,1,10,1,10,1,14,1,13,2,114,24,1,0,0,
- 99,0,0,0,0,0,0,0,0,3,0,0,0,3,0,0,
- 0,67,0,0,0,115,55,0,0,0,116,0,0,116,1,0,
- 106,2,0,131,0,0,102,2,0,125,0,0,116,3,0,116,
- 4,0,102,2,0,125,1,0,116,5,0,116,6,0,102,2,
- 0,125,2,0,124,0,0,124,1,0,124,2,0,103,3,0,
- 83,41,1,122,95,82,101,116,117,114,110,115,32,97,32,108,
- 105,115,116,32,111,102,32,102,105,108,101,45,98,97,115,101,
- 100,32,109,111,100,117,108,101,32,108,111,97,100,101,114,115,
- 46,10,10,32,32,32,32,69,97,99,104,32,105,116,101,109,
- 32,105,115,32,97,32,116,117,112,108,101,32,40,108,111,97,
- 100,101,114,44,32,115,117,102,102,105,120,101,115,41,46,10,
- 32,32,32,32,41,7,114,224,0,0,0,114,145,0,0,0,
- 218,18,101,120,116,101,110,115,105,111,110,95,115,117,102,102,
- 105,120,101,115,114,218,0,0,0,114,84,0,0,0,114,223,
- 0,0,0,114,74,0,0,0,41,3,90,10,101,120,116,101,
- 110,115,105,111,110,115,90,6,115,111,117,114,99,101,90,8,
- 98,121,116,101,99,111,100,101,114,4,0,0,0,114,4,0,
- 0,0,114,5,0,0,0,114,161,0,0,0,55,5,0,0,
- 115,8,0,0,0,0,5,18,1,12,1,12,1,114,161,0,
- 0,0,99,1,0,0,0,0,0,0,0,12,0,0,0,12,
- 0,0,0,67,0,0,0,115,70,2,0,0,124,0,0,97,
- 0,0,116,0,0,106,1,0,97,1,0,116,0,0,106,2,
- 0,97,2,0,116,1,0,106,3,0,116,4,0,25,125,1,
- 0,120,76,0,100,26,0,68,93,68,0,125,2,0,124,2,
- 0,116,1,0,106,3,0,107,7,0,114,83,0,116,0,0,
- 106,5,0,124,2,0,131,1,0,125,3,0,110,13,0,116,
- 1,0,106,3,0,124,2,0,25,125,3,0,116,6,0,124,
- 1,0,124,2,0,124,3,0,131,3,0,1,113,44,0,87,
- 100,5,0,100,6,0,103,1,0,102,2,0,100,7,0,100,
- 8,0,100,6,0,103,2,0,102,2,0,102,2,0,125,4,
- 0,120,149,0,124,4,0,68,93,129,0,92,2,0,125,5,
- 0,125,6,0,116,7,0,100,9,0,100,10,0,132,0,0,
- 124,6,0,68,131,1,0,131,1,0,115,199,0,116,8,0,
- 130,1,0,124,6,0,100,11,0,25,125,7,0,124,5,0,
- 116,1,0,106,3,0,107,6,0,114,241,0,116,1,0,106,
- 3,0,124,5,0,25,125,8,0,80,113,156,0,121,20,0,
- 116,0,0,106,5,0,124,5,0,131,1,0,125,8,0,80,
- 87,113,156,0,4,116,9,0,107,10,0,114,28,1,1,1,
- 1,119,156,0,89,113,156,0,88,113,156,0,87,116,9,0,
- 100,12,0,131,1,0,130,1,0,116,6,0,124,1,0,100,
- 13,0,124,8,0,131,3,0,1,116,6,0,124,1,0,100,
- 14,0,124,7,0,131,3,0,1,116,6,0,124,1,0,100,
- 15,0,100,16,0,106,10,0,124,6,0,131,1,0,131,3,
- 0,1,121,19,0,116,0,0,106,5,0,100,17,0,131,1,
- 0,125,9,0,87,110,24,0,4,116,9,0,107,10,0,114,
- 147,1,1,1,1,100,18,0,125,9,0,89,110,1,0,88,
- 116,6,0,124,1,0,100,17,0,124,9,0,131,3,0,1,
- 116,0,0,106,5,0,100,19,0,131,1,0,125,10,0,116,
- 6,0,124,1,0,100,19,0,124,10,0,131,3,0,1,124,
- 5,0,100,7,0,107,2,0,114,238,1,116,0,0,106,5,
- 0,100,20,0,131,1,0,125,11,0,116,6,0,124,1,0,
- 100,21,0,124,11,0,131,3,0,1,116,6,0,124,1,0,
- 100,22,0,116,11,0,131,0,0,131,3,0,1,116,12,0,
- 106,13,0,116,2,0,106,14,0,131,0,0,131,1,0,1,
- 124,5,0,100,7,0,107,2,0,114,66,2,116,15,0,106,
- 16,0,100,23,0,131,1,0,1,100,24,0,116,12,0,107,
- 6,0,114,66,2,100,25,0,116,17,0,95,18,0,100,18,
- 0,83,41,27,122,205,83,101,116,117,112,32,116,104,101,32,
- 112,97,116,104,45,98,97,115,101,100,32,105,109,112,111,114,
- 116,101,114,115,32,102,111,114,32,105,109,112,111,114,116,108,
- 105,98,32,98,121,32,105,109,112,111,114,116,105,110,103,32,
- 110,101,101,100,101,100,10,32,32,32,32,98,117,105,108,116,
- 45,105,110,32,109,111,100,117,108,101,115,32,97,110,100,32,
- 105,110,106,101,99,116,105,110,103,32,116,104,101,109,32,105,
- 110,116,111,32,116,104,101,32,103,108,111,98,97,108,32,110,
- 97,109,101,115,112,97,99,101,46,10,10,32,32,32,32,79,
- 116,104,101,114,32,99,111,109,112,111,110,101,110,116,115,32,
- 97,114,101,32,101,120,116,114,97,99,116,101,100,32,102,114,
- 111,109,32,116,104,101,32,99,111,114,101,32,98,111,111,116,
- 115,116,114,97,112,32,109,111,100,117,108,101,46,10,10,32,
- 32,32,32,114,49,0,0,0,114,60,0,0,0,218,8,98,
- 117,105,108,116,105,110,115,114,142,0,0,0,90,5,112,111,
- 115,105,120,250,1,47,218,2,110,116,250,1,92,99,1,0,
- 0,0,0,0,0,0,2,0,0,0,3,0,0,0,115,0,
- 0,0,115,33,0,0,0,124,0,0,93,23,0,125,1,0,
- 116,0,0,124,1,0,131,1,0,100,0,0,107,2,0,86,
- 1,113,3,0,100,1,0,83,41,2,114,29,0,0,0,78,
- 41,1,114,31,0,0,0,41,2,114,22,0,0,0,114,77,
+ 114,114,4,0,0,0,41,3,114,170,0,0,0,114,12,1,
+ 0,0,114,18,1,0,0,114,4,0,0,0,41,2,114,170,
+ 0,0,0,114,12,1,0,0,114,5,0,0,0,218,9,112,
+ 97,116,104,95,104,111,111,107,11,5,0,0,115,4,0,0,
+ 0,0,10,21,6,122,20,70,105,108,101,70,105,110,100,101,
+ 114,46,112,97,116,104,95,104,111,111,107,99,1,0,0,0,
+ 0,0,0,0,1,0,0,0,2,0,0,0,67,0,0,0,
+ 115,16,0,0,0,100,1,0,106,0,0,124,0,0,106,1,
+ 0,131,1,0,83,41,2,78,122,16,70,105,108,101,70,105,
+ 110,100,101,114,40,123,33,114,125,41,41,2,114,47,0,0,
+ 0,114,35,0,0,0,41,1,114,108,0,0,0,114,4,0,
+ 0,0,114,4,0,0,0,114,5,0,0,0,114,244,0,0,
+ 0,29,5,0,0,115,2,0,0,0,0,1,122,19,70,105,
+ 108,101,70,105,110,100,101,114,46,95,95,114,101,112,114,95,
+ 95,41,15,114,112,0,0,0,114,111,0,0,0,114,113,0,
+ 0,0,114,114,0,0,0,114,185,0,0,0,114,250,0,0,
+ 0,114,130,0,0,0,114,182,0,0,0,114,124,0,0,0,
+ 114,5,1,0,0,114,181,0,0,0,114,13,1,0,0,114,
+ 183,0,0,0,114,19,1,0,0,114,244,0,0,0,114,4,
0,0,0,114,4,0,0,0,114,4,0,0,0,114,5,0,
- 0,0,114,227,0,0,0,91,5,0,0,115,2,0,0,0,
- 6,0,122,25,95,115,101,116,117,112,46,60,108,111,99,97,
- 108,115,62,46,60,103,101,110,101,120,112,114,62,114,59,0,
- 0,0,122,30,105,109,112,111,114,116,108,105,98,32,114,101,
- 113,117,105,114,101,115,32,112,111,115,105,120,32,111,114,32,
- 110,116,114,3,0,0,0,114,25,0,0,0,114,21,0,0,
- 0,114,30,0,0,0,90,7,95,116,104,114,101,97,100,78,
- 90,8,95,119,101,97,107,114,101,102,90,6,119,105,110,114,
- 101,103,114,169,0,0,0,114,6,0,0,0,122,4,46,112,
- 121,119,122,6,95,100,46,112,121,100,84,41,4,122,3,95,
- 105,111,122,9,95,119,97,114,110,105,110,103,115,122,8,98,
- 117,105,108,116,105,110,115,122,7,109,97,114,115,104,97,108,
- 41,19,114,121,0,0,0,114,7,0,0,0,114,145,0,0,
- 0,114,239,0,0,0,114,112,0,0,0,90,18,95,98,117,
- 105,108,116,105,110,95,102,114,111,109,95,110,97,109,101,114,
- 116,0,0,0,218,3,97,108,108,218,14,65,115,115,101,114,
- 116,105,111,110,69,114,114,111,114,114,107,0,0,0,114,26,
- 0,0,0,114,11,0,0,0,114,229,0,0,0,114,149,0,
- 0,0,114,25,1,0,0,114,84,0,0,0,114,163,0,0,
- 0,114,168,0,0,0,114,173,0,0,0,41,12,218,17,95,
- 98,111,111,116,115,116,114,97,112,95,109,111,100,117,108,101,
- 90,11,115,101,108,102,95,109,111,100,117,108,101,90,12,98,
- 117,105,108,116,105,110,95,110,97,109,101,90,14,98,117,105,
- 108,116,105,110,95,109,111,100,117,108,101,90,10,111,115,95,
- 100,101,116,97,105,108,115,90,10,98,117,105,108,116,105,110,
- 95,111,115,114,21,0,0,0,114,25,0,0,0,90,9,111,
- 115,95,109,111,100,117,108,101,90,13,116,104,114,101,97,100,
- 95,109,111,100,117,108,101,90,14,119,101,97,107,114,101,102,
- 95,109,111,100,117,108,101,90,13,119,105,110,114,101,103,95,
- 109,111,100,117,108,101,114,4,0,0,0,114,4,0,0,0,
- 114,5,0,0,0,218,6,95,115,101,116,117,112,66,5,0,
- 0,115,82,0,0,0,0,8,6,1,9,1,9,3,13,1,
- 13,1,15,1,18,2,13,1,20,3,33,1,19,2,31,1,
- 10,1,15,1,13,1,4,2,3,1,15,1,5,1,13,1,
- 12,2,12,1,16,1,16,1,25,3,3,1,19,1,13,2,
- 11,1,16,3,15,1,16,3,12,1,15,1,16,3,19,1,
- 19,1,12,1,13,1,12,1,114,33,1,0,0,99,1,0,
- 0,0,0,0,0,0,2,0,0,0,3,0,0,0,67,0,
- 0,0,115,116,0,0,0,116,0,0,124,0,0,131,1,0,
- 1,116,1,0,131,0,0,125,1,0,116,2,0,106,3,0,
- 106,4,0,116,5,0,106,6,0,124,1,0,140,0,0,103,
- 1,0,131,1,0,1,116,7,0,106,8,0,100,1,0,107,
- 2,0,114,78,0,116,2,0,106,9,0,106,10,0,116,11,
- 0,131,1,0,1,116,2,0,106,9,0,106,10,0,116,12,
- 0,131,1,0,1,116,5,0,124,0,0,95,5,0,116,13,
- 0,124,0,0,95,13,0,100,2,0,83,41,3,122,41,73,
- 110,115,116,97,108,108,32,116,104,101,32,112,97,116,104,45,
- 98,97,115,101,100,32,105,109,112,111,114,116,32,99,111,109,
- 112,111,110,101,110,116,115,46,114,28,1,0,0,78,41,14,
- 114,33,1,0,0,114,161,0,0,0,114,7,0,0,0,114,
- 254,0,0,0,114,149,0,0,0,114,6,1,0,0,114,19,
- 1,0,0,114,3,0,0,0,114,112,0,0,0,218,9,109,
- 101,116,97,95,112,97,116,104,114,163,0,0,0,114,168,0,
- 0,0,114,249,0,0,0,114,218,0,0,0,41,2,114,32,
- 1,0,0,90,17,115,117,112,112,111,114,116,101,100,95,108,
- 111,97,100,101,114,115,114,4,0,0,0,114,4,0,0,0,
- 114,5,0,0,0,218,8,95,105,110,115,116,97,108,108,134,
- 5,0,0,115,16,0,0,0,0,2,10,1,9,1,28,1,
- 15,1,16,1,16,4,9,1,114,35,1,0,0,41,3,122,
- 3,119,105,110,114,1,0,0,0,114,2,0,0,0,41,57,
- 114,114,0,0,0,114,10,0,0,0,114,11,0,0,0,114,
- 17,0,0,0,114,19,0,0,0,114,28,0,0,0,114,38,
- 0,0,0,114,39,0,0,0,114,43,0,0,0,114,44,0,
- 0,0,114,46,0,0,0,114,55,0,0,0,218,4,116,121,
- 112,101,218,8,95,95,99,111,100,101,95,95,114,144,0,0,
- 0,114,15,0,0,0,114,135,0,0,0,114,14,0,0,0,
- 114,18,0,0,0,90,17,95,82,65,87,95,77,65,71,73,
- 67,95,78,85,77,66,69,82,114,73,0,0,0,114,72,0,
- 0,0,114,84,0,0,0,114,74,0,0,0,90,23,68,69,
- 66,85,71,95,66,89,84,69,67,79,68,69,95,83,85,70,
- 70,73,88,69,83,90,27,79,80,84,73,77,73,90,69,68,
- 95,66,89,84,69,67,79,68,69,95,83,85,70,70,73,88,
- 69,83,114,79,0,0,0,114,85,0,0,0,114,91,0,0,
- 0,114,95,0,0,0,114,97,0,0,0,114,105,0,0,0,
- 114,123,0,0,0,114,130,0,0,0,114,141,0,0,0,114,
- 147,0,0,0,114,150,0,0,0,114,155,0,0,0,218,6,
- 111,98,106,101,99,116,114,162,0,0,0,114,167,0,0,0,
- 114,168,0,0,0,114,184,0,0,0,114,194,0,0,0,114,
- 210,0,0,0,114,218,0,0,0,114,223,0,0,0,114,229,
- 0,0,0,114,224,0,0,0,114,230,0,0,0,114,247,0,
- 0,0,114,249,0,0,0,114,6,1,0,0,114,24,1,0,
- 0,114,161,0,0,0,114,33,1,0,0,114,35,1,0,0,
- 114,4,0,0,0,114,4,0,0,0,114,4,0,0,0,114,
- 5,0,0,0,218,8,60,109,111,100,117,108,101,62,8,0,
- 0,0,115,100,0,0,0,6,17,6,3,12,12,12,5,12,
- 5,12,6,12,12,12,10,12,9,12,5,12,7,15,22,15,
- 110,22,1,18,2,6,1,6,2,9,2,9,2,10,2,21,
- 44,12,33,12,19,12,12,12,12,18,8,12,28,12,17,21,
- 55,21,12,18,10,12,14,9,3,12,1,15,65,19,64,19,
- 28,22,110,19,41,25,43,25,16,6,3,25,53,19,57,19,
- 41,19,134,19,146,15,23,12,11,12,68,
+ 0,0,114,6,1,0,0,145,4,0,0,115,20,0,0,0,
+ 12,7,6,2,12,14,12,4,6,2,12,12,12,5,15,45,
+ 12,31,18,18,114,6,1,0,0,99,4,0,0,0,0,0,
+ 0,0,6,0,0,0,11,0,0,0,67,0,0,0,115,195,
+ 0,0,0,124,0,0,106,0,0,100,1,0,131,1,0,125,
+ 4,0,124,0,0,106,0,0,100,2,0,131,1,0,125,5,
+ 0,124,4,0,115,99,0,124,5,0,114,54,0,124,5,0,
+ 106,1,0,125,4,0,110,45,0,124,2,0,124,3,0,107,
+ 2,0,114,84,0,116,2,0,124,1,0,124,2,0,131,2,
+ 0,125,4,0,110,15,0,116,3,0,124,1,0,124,2,0,
+ 131,2,0,125,4,0,124,5,0,115,126,0,116,4,0,124,
+ 1,0,124,2,0,100,3,0,124,4,0,131,2,1,125,5,
+ 0,121,44,0,124,5,0,124,0,0,100,2,0,60,124,4,
+ 0,124,0,0,100,1,0,60,124,2,0,124,0,0,100,4,
+ 0,60,124,3,0,124,0,0,100,5,0,60,87,110,18,0,
+ 4,116,5,0,107,10,0,114,190,0,1,1,1,89,110,1,
+ 0,88,100,0,0,83,41,6,78,218,10,95,95,108,111,97,
+ 100,101,114,95,95,218,8,95,95,115,112,101,99,95,95,114,
+ 127,0,0,0,90,8,95,95,102,105,108,101,95,95,90,10,
+ 95,95,99,97,99,104,101,100,95,95,41,6,218,3,103,101,
+ 116,114,127,0,0,0,114,223,0,0,0,114,218,0,0,0,
+ 114,167,0,0,0,218,9,69,120,99,101,112,116,105,111,110,
+ 41,6,90,2,110,115,114,106,0,0,0,90,8,112,97,116,
+ 104,110,97,109,101,90,9,99,112,97,116,104,110,97,109,101,
+ 114,127,0,0,0,114,164,0,0,0,114,4,0,0,0,114,
+ 4,0,0,0,114,5,0,0,0,218,14,95,102,105,120,95,
+ 117,112,95,109,111,100,117,108,101,35,5,0,0,115,34,0,
+ 0,0,0,2,15,1,15,1,6,1,6,1,12,1,12,1,
+ 18,2,15,1,6,1,21,1,3,1,10,1,10,1,10,1,
+ 14,1,13,2,114,24,1,0,0,99,0,0,0,0,0,0,
+ 0,0,3,0,0,0,3,0,0,0,67,0,0,0,115,55,
+ 0,0,0,116,0,0,116,1,0,106,2,0,131,0,0,102,
+ 2,0,125,0,0,116,3,0,116,4,0,102,2,0,125,1,
+ 0,116,5,0,116,6,0,102,2,0,125,2,0,124,0,0,
+ 124,1,0,124,2,0,103,3,0,83,41,1,122,95,82,101,
+ 116,117,114,110,115,32,97,32,108,105,115,116,32,111,102,32,
+ 102,105,108,101,45,98,97,115,101,100,32,109,111,100,117,108,
+ 101,32,108,111,97,100,101,114,115,46,10,10,32,32,32,32,
+ 69,97,99,104,32,105,116,101,109,32,105,115,32,97,32,116,
+ 117,112,108,101,32,40,108,111,97,100,101,114,44,32,115,117,
+ 102,102,105,120,101,115,41,46,10,32,32,32,32,41,7,114,
+ 224,0,0,0,114,145,0,0,0,218,18,101,120,116,101,110,
+ 115,105,111,110,95,115,117,102,102,105,120,101,115,114,218,0,
+ 0,0,114,84,0,0,0,114,223,0,0,0,114,74,0,0,
+ 0,41,3,90,10,101,120,116,101,110,115,105,111,110,115,90,
+ 6,115,111,117,114,99,101,90,8,98,121,116,101,99,111,100,
+ 101,114,4,0,0,0,114,4,0,0,0,114,5,0,0,0,
+ 114,161,0,0,0,58,5,0,0,115,8,0,0,0,0,5,
+ 18,1,12,1,12,1,114,161,0,0,0,99,1,0,0,0,
+ 0,0,0,0,12,0,0,0,12,0,0,0,67,0,0,0,
+ 115,70,2,0,0,124,0,0,97,0,0,116,0,0,106,1,
+ 0,97,1,0,116,0,0,106,2,0,97,2,0,116,1,0,
+ 106,3,0,116,4,0,25,125,1,0,120,76,0,100,26,0,
+ 68,93,68,0,125,2,0,124,2,0,116,1,0,106,3,0,
+ 107,7,0,114,83,0,116,0,0,106,5,0,124,2,0,131,
+ 1,0,125,3,0,110,13,0,116,1,0,106,3,0,124,2,
+ 0,25,125,3,0,116,6,0,124,1,0,124,2,0,124,3,
+ 0,131,3,0,1,113,44,0,87,100,5,0,100,6,0,103,
+ 1,0,102,2,0,100,7,0,100,8,0,100,6,0,103,2,
+ 0,102,2,0,102,2,0,125,4,0,120,149,0,124,4,0,
+ 68,93,129,0,92,2,0,125,5,0,125,6,0,116,7,0,
+ 100,9,0,100,10,0,132,0,0,124,6,0,68,131,1,0,
+ 131,1,0,115,199,0,116,8,0,130,1,0,124,6,0,100,
+ 11,0,25,125,7,0,124,5,0,116,1,0,106,3,0,107,
+ 6,0,114,241,0,116,1,0,106,3,0,124,5,0,25,125,
+ 8,0,80,113,156,0,121,20,0,116,0,0,106,5,0,124,
+ 5,0,131,1,0,125,8,0,80,87,113,156,0,4,116,9,
+ 0,107,10,0,114,28,1,1,1,1,119,156,0,89,113,156,
+ 0,88,113,156,0,87,116,9,0,100,12,0,131,1,0,130,
+ 1,0,116,6,0,124,1,0,100,13,0,124,8,0,131,3,
+ 0,1,116,6,0,124,1,0,100,14,0,124,7,0,131,3,
+ 0,1,116,6,0,124,1,0,100,15,0,100,16,0,106,10,
+ 0,124,6,0,131,1,0,131,3,0,1,121,19,0,116,0,
+ 0,106,5,0,100,17,0,131,1,0,125,9,0,87,110,24,
+ 0,4,116,9,0,107,10,0,114,147,1,1,1,1,100,18,
+ 0,125,9,0,89,110,1,0,88,116,6,0,124,1,0,100,
+ 17,0,124,9,0,131,3,0,1,116,0,0,106,5,0,100,
+ 19,0,131,1,0,125,10,0,116,6,0,124,1,0,100,19,
+ 0,124,10,0,131,3,0,1,124,5,0,100,7,0,107,2,
+ 0,114,238,1,116,0,0,106,5,0,100,20,0,131,1,0,
+ 125,11,0,116,6,0,124,1,0,100,21,0,124,11,0,131,
+ 3,0,1,116,6,0,124,1,0,100,22,0,116,11,0,131,
+ 0,0,131,3,0,1,116,12,0,106,13,0,116,2,0,106,
+ 14,0,131,0,0,131,1,0,1,124,5,0,100,7,0,107,
+ 2,0,114,66,2,116,15,0,106,16,0,100,23,0,131,1,
+ 0,1,100,24,0,116,12,0,107,6,0,114,66,2,100,25,
+ 0,116,17,0,95,18,0,100,18,0,83,41,27,122,205,83,
+ 101,116,117,112,32,116,104,101,32,112,97,116,104,45,98,97,
+ 115,101,100,32,105,109,112,111,114,116,101,114,115,32,102,111,
+ 114,32,105,109,112,111,114,116,108,105,98,32,98,121,32,105,
+ 109,112,111,114,116,105,110,103,32,110,101,101,100,101,100,10,
+ 32,32,32,32,98,117,105,108,116,45,105,110,32,109,111,100,
+ 117,108,101,115,32,97,110,100,32,105,110,106,101,99,116,105,
+ 110,103,32,116,104,101,109,32,105,110,116,111,32,116,104,101,
+ 32,103,108,111,98,97,108,32,110,97,109,101,115,112,97,99,
+ 101,46,10,10,32,32,32,32,79,116,104,101,114,32,99,111,
+ 109,112,111,110,101,110,116,115,32,97,114,101,32,101,120,116,
+ 114,97,99,116,101,100,32,102,114,111,109,32,116,104,101,32,
+ 99,111,114,101,32,98,111,111,116,115,116,114,97,112,32,109,
+ 111,100,117,108,101,46,10,10,32,32,32,32,114,49,0,0,
+ 0,114,60,0,0,0,218,8,98,117,105,108,116,105,110,115,
+ 114,142,0,0,0,90,5,112,111,115,105,120,250,1,47,218,
+ 2,110,116,250,1,92,99,1,0,0,0,0,0,0,0,2,
+ 0,0,0,3,0,0,0,115,0,0,0,115,33,0,0,0,
+ 124,0,0,93,23,0,125,1,0,116,0,0,124,1,0,131,
+ 1,0,100,0,0,107,2,0,86,1,113,3,0,100,1,0,
+ 83,41,2,114,29,0,0,0,78,41,1,114,31,0,0,0,
+ 41,2,114,22,0,0,0,114,77,0,0,0,114,4,0,0,
+ 0,114,4,0,0,0,114,5,0,0,0,114,227,0,0,0,
+ 94,5,0,0,115,2,0,0,0,6,0,122,25,95,115,101,
+ 116,117,112,46,60,108,111,99,97,108,115,62,46,60,103,101,
+ 110,101,120,112,114,62,114,59,0,0,0,122,30,105,109,112,
+ 111,114,116,108,105,98,32,114,101,113,117,105,114,101,115,32,
+ 112,111,115,105,120,32,111,114,32,110,116,114,3,0,0,0,
+ 114,25,0,0,0,114,21,0,0,0,114,30,0,0,0,90,
+ 7,95,116,104,114,101,97,100,78,90,8,95,119,101,97,107,
+ 114,101,102,90,6,119,105,110,114,101,103,114,169,0,0,0,
+ 114,6,0,0,0,122,4,46,112,121,119,122,6,95,100,46,
+ 112,121,100,84,41,4,122,3,95,105,111,122,9,95,119,97,
+ 114,110,105,110,103,115,122,8,98,117,105,108,116,105,110,115,
+ 122,7,109,97,114,115,104,97,108,41,19,114,121,0,0,0,
+ 114,7,0,0,0,114,145,0,0,0,114,239,0,0,0,114,
+ 112,0,0,0,90,18,95,98,117,105,108,116,105,110,95,102,
+ 114,111,109,95,110,97,109,101,114,116,0,0,0,218,3,97,
+ 108,108,218,14,65,115,115,101,114,116,105,111,110,69,114,114,
+ 111,114,114,107,0,0,0,114,26,0,0,0,114,11,0,0,
+ 0,114,229,0,0,0,114,149,0,0,0,114,25,1,0,0,
+ 114,84,0,0,0,114,163,0,0,0,114,168,0,0,0,114,
+ 173,0,0,0,41,12,218,17,95,98,111,111,116,115,116,114,
+ 97,112,95,109,111,100,117,108,101,90,11,115,101,108,102,95,
+ 109,111,100,117,108,101,90,12,98,117,105,108,116,105,110,95,
+ 110,97,109,101,90,14,98,117,105,108,116,105,110,95,109,111,
+ 100,117,108,101,90,10,111,115,95,100,101,116,97,105,108,115,
+ 90,10,98,117,105,108,116,105,110,95,111,115,114,21,0,0,
+ 0,114,25,0,0,0,90,9,111,115,95,109,111,100,117,108,
+ 101,90,13,116,104,114,101,97,100,95,109,111,100,117,108,101,
+ 90,14,119,101,97,107,114,101,102,95,109,111,100,117,108,101,
+ 90,13,119,105,110,114,101,103,95,109,111,100,117,108,101,114,
+ 4,0,0,0,114,4,0,0,0,114,5,0,0,0,218,6,
+ 95,115,101,116,117,112,69,5,0,0,115,82,0,0,0,0,
+ 8,6,1,9,1,9,3,13,1,13,1,15,1,18,2,13,
+ 1,20,3,33,1,19,2,31,1,10,1,15,1,13,1,4,
+ 2,3,1,15,1,5,1,13,1,12,2,12,1,16,1,16,
+ 1,25,3,3,1,19,1,13,2,11,1,16,3,15,1,16,
+ 3,12,1,15,1,16,3,19,1,19,1,12,1,13,1,12,
+ 1,114,33,1,0,0,99,1,0,0,0,0,0,0,0,2,
+ 0,0,0,3,0,0,0,67,0,0,0,115,116,0,0,0,
+ 116,0,0,124,0,0,131,1,0,1,116,1,0,131,0,0,
+ 125,1,0,116,2,0,106,3,0,106,4,0,116,5,0,106,
+ 6,0,124,1,0,140,0,0,103,1,0,131,1,0,1,116,
+ 7,0,106,8,0,100,1,0,107,2,0,114,78,0,116,2,
+ 0,106,9,0,106,10,0,116,11,0,131,1,0,1,116,2,
+ 0,106,9,0,106,10,0,116,12,0,131,1,0,1,116,5,
+ 0,124,0,0,95,5,0,116,13,0,124,0,0,95,13,0,
+ 100,2,0,83,41,3,122,41,73,110,115,116,97,108,108,32,
+ 116,104,101,32,112,97,116,104,45,98,97,115,101,100,32,105,
+ 109,112,111,114,116,32,99,111,109,112,111,110,101,110,116,115,
+ 46,114,28,1,0,0,78,41,14,114,33,1,0,0,114,161,
+ 0,0,0,114,7,0,0,0,114,254,0,0,0,114,149,0,
+ 0,0,114,6,1,0,0,114,19,1,0,0,114,3,0,0,
+ 0,114,112,0,0,0,218,9,109,101,116,97,95,112,97,116,
+ 104,114,163,0,0,0,114,168,0,0,0,114,249,0,0,0,
+ 114,218,0,0,0,41,2,114,32,1,0,0,90,17,115,117,
+ 112,112,111,114,116,101,100,95,108,111,97,100,101,114,115,114,
+ 4,0,0,0,114,4,0,0,0,114,5,0,0,0,218,8,
+ 95,105,110,115,116,97,108,108,137,5,0,0,115,16,0,0,
+ 0,0,2,10,1,9,1,28,1,15,1,16,1,16,4,9,
+ 1,114,35,1,0,0,41,3,122,3,119,105,110,114,1,0,
+ 0,0,114,2,0,0,0,41,57,114,114,0,0,0,114,10,
+ 0,0,0,114,11,0,0,0,114,17,0,0,0,114,19,0,
+ 0,0,114,28,0,0,0,114,38,0,0,0,114,39,0,0,
+ 0,114,43,0,0,0,114,44,0,0,0,114,46,0,0,0,
+ 114,55,0,0,0,218,4,116,121,112,101,218,8,95,95,99,
+ 111,100,101,95,95,114,144,0,0,0,114,15,0,0,0,114,
+ 135,0,0,0,114,14,0,0,0,114,18,0,0,0,90,17,
+ 95,82,65,87,95,77,65,71,73,67,95,78,85,77,66,69,
+ 82,114,73,0,0,0,114,72,0,0,0,114,84,0,0,0,
+ 114,74,0,0,0,90,23,68,69,66,85,71,95,66,89,84,
+ 69,67,79,68,69,95,83,85,70,70,73,88,69,83,90,27,
+ 79,80,84,73,77,73,90,69,68,95,66,89,84,69,67,79,
+ 68,69,95,83,85,70,70,73,88,69,83,114,79,0,0,0,
+ 114,85,0,0,0,114,91,0,0,0,114,95,0,0,0,114,
+ 97,0,0,0,114,105,0,0,0,114,123,0,0,0,114,130,
+ 0,0,0,114,141,0,0,0,114,147,0,0,0,114,150,0,
+ 0,0,114,155,0,0,0,218,6,111,98,106,101,99,116,114,
+ 162,0,0,0,114,167,0,0,0,114,168,0,0,0,114,184,
+ 0,0,0,114,194,0,0,0,114,210,0,0,0,114,218,0,
+ 0,0,114,223,0,0,0,114,229,0,0,0,114,224,0,0,
+ 0,114,230,0,0,0,114,247,0,0,0,114,249,0,0,0,
+ 114,6,1,0,0,114,24,1,0,0,114,161,0,0,0,114,
+ 33,1,0,0,114,35,1,0,0,114,4,0,0,0,114,4,
+ 0,0,0,114,4,0,0,0,114,5,0,0,0,218,8,60,
+ 109,111,100,117,108,101,62,8,0,0,0,115,100,0,0,0,
+ 6,17,6,3,12,12,12,5,12,5,12,6,12,12,12,10,
+ 12,9,12,5,12,7,15,22,15,113,22,1,18,2,6,1,
+ 6,2,9,2,9,2,10,2,21,44,12,33,12,19,12,12,
+ 12,12,18,8,12,28,12,17,21,55,21,12,18,10,12,14,
+ 9,3,12,1,15,65,19,64,19,28,22,110,19,41,25,43,
+ 25,16,6,3,25,53,19,57,19,41,19,134,19,146,15,23,
+ 12,11,12,68,
};
open() or os.popen(). It must be opened in binary mode ('wb' or 'w+b').\n\
\n\
If the value has (or contains an object that has) an unsupported type, a\n\
-ValueError exception is raised — but garbage data will also be written\n\
+ValueError exception is raised - but garbage data will also be written\n\
to the file. The object will not be properly read back by load()\n\
\n\
The version argument indicates the data format that dump should use.");
"load(file)\n\
\n\
Read one value from the open file and return it. If no valid value is\n\
-read (e.g. because the data has a different Python version’s\n\
+read (e.g. because the data has a different Python version's\n\
incompatible marshal format), raise EOFError, ValueError or TypeError.\n\
The file must be an open file object opened in binary mode ('rb' or\n\
'r+b').\n\
static PyObject *do_mkvalue(const char**, va_list *, int);
+static void
+do_ignore(const char **p_format, va_list *p_va, int endchar, int n, int flags)
+{
+ PyObject *v;
+ int i;
+ assert(PyErr_Occurred());
+ v = PyTuple_New(n);
+ for (i = 0; i < n; i++) {
+ PyObject *exception, *value, *tb, *w;
+
+ PyErr_Fetch(&exception, &value, &tb);
+ w = do_mkvalue(p_format, p_va, flags);
+ PyErr_Restore(exception, value, tb);
+ if (w != NULL) {
+ if (v != NULL) {
+ PyTuple_SET_ITEM(v, i, w);
+ }
+ else {
+ Py_DECREF(w);
+ }
+ }
+ }
+ Py_XDECREF(v);
+ if (**p_format != endchar) {
+ PyErr_SetString(PyExc_SystemError,
+ "Unmatched paren in format");
+ return;
+ }
+ if (endchar)
+ ++*p_format;
+}
+
static PyObject *
do_mkdict(const char **p_format, va_list *p_va, int endchar, int n, int flags)
{
PyObject *d;
int i;
- int itemfailed = 0;
if (n < 0)
return NULL;
- if ((d = PyDict_New()) == NULL)
+ if (n % 2) {
+ PyErr_SetString(PyExc_SystemError,
+ "Bad dict format");
+ do_ignore(p_format, p_va, endchar, n, flags);
return NULL;
+ }
/* Note that we can't bail immediately on error as this will leak
refcounts on any 'N' arguments. */
+ if ((d = PyDict_New()) == NULL) {
+ do_ignore(p_format, p_va, endchar, n, flags);
+ return NULL;
+ }
for (i = 0; i < n; i+= 2) {
PyObject *k, *v;
- int err;
+
k = do_mkvalue(p_format, p_va, flags);
if (k == NULL) {
- itemfailed = 1;
- Py_INCREF(Py_None);
- k = Py_None;
+ do_ignore(p_format, p_va, endchar, n - i - 1, flags);
+ Py_DECREF(d);
+ return NULL;
}
v = do_mkvalue(p_format, p_va, flags);
- if (v == NULL) {
- itemfailed = 1;
- Py_INCREF(Py_None);
- v = Py_None;
- }
- err = PyDict_SetItem(d, k, v);
- Py_DECREF(k);
- Py_DECREF(v);
- if (err < 0 || itemfailed) {
+ if (v == NULL || PyDict_SetItem(d, k, v) < 0) {
+ do_ignore(p_format, p_va, endchar, n - i - 2, flags);
+ Py_DECREF(k);
+ Py_XDECREF(v);
Py_DECREF(d);
return NULL;
}
+ Py_DECREF(k);
+ Py_DECREF(v);
}
- if (d != NULL && **p_format != endchar) {
+ if (**p_format != endchar) {
Py_DECREF(d);
- d = NULL;
PyErr_SetString(PyExc_SystemError,
"Unmatched paren in format");
+ return NULL;
}
- else if (endchar)
+ if (endchar)
++*p_format;
return d;
}
{
PyObject *v;
int i;
- int itemfailed = 0;
if (n < 0)
return NULL;
- v = PyList_New(n);
- if (v == NULL)
- return NULL;
/* Note that we can't bail immediately on error as this will leak
refcounts on any 'N' arguments. */
+ v = PyList_New(n);
+ if (v == NULL) {
+ do_ignore(p_format, p_va, endchar, n, flags);
+ return NULL;
+ }
for (i = 0; i < n; i++) {
PyObject *w = do_mkvalue(p_format, p_va, flags);
if (w == NULL) {
- itemfailed = 1;
- Py_INCREF(Py_None);
- w = Py_None;
+ do_ignore(p_format, p_va, endchar, n - i - 1, flags);
+ Py_DECREF(v);
+ return NULL;
}
PyList_SET_ITEM(v, i, w);
}
-
- if (itemfailed) {
- /* do_mkvalue() should have already set an error */
- Py_DECREF(v);
- return NULL;
- }
if (**p_format != endchar) {
Py_DECREF(v);
PyErr_SetString(PyExc_SystemError,
{
PyObject *v;
int i;
- int itemfailed = 0;
if (n < 0)
return NULL;
- if ((v = PyTuple_New(n)) == NULL)
- return NULL;
/* Note that we can't bail immediately on error as this will leak
refcounts on any 'N' arguments. */
+ if ((v = PyTuple_New(n)) == NULL) {
+ do_ignore(p_format, p_va, endchar, n, flags);
+ return NULL;
+ }
for (i = 0; i < n; i++) {
- PyObject *w;
-
- if (itemfailed) {
- PyObject *exception, *value, *tb;
- PyErr_Fetch(&exception, &value, &tb);
- w = do_mkvalue(p_format, p_va, flags);
- PyErr_Restore(exception, value, tb);
- }
- else {
- w = do_mkvalue(p_format, p_va, flags);
- }
+ PyObject *w = do_mkvalue(p_format, p_va, flags);
if (w == NULL) {
- itemfailed = 1;
- Py_INCREF(Py_None);
- w = Py_None;
+ do_ignore(p_format, p_va, endchar, n - i - 1, flags);
+ Py_DECREF(v);
+ return NULL;
}
PyTuple_SET_ITEM(v, i, w);
}
- if (itemfailed) {
- /* do_mkvalue() should have already set an error */
- Py_DECREF(v);
- return NULL;
- }
if (**p_format != endchar) {
Py_DECREF(v);
PyErr_SetString(PyExc_SystemError,
appear before MAKE_FUNCTION; in this case both opcodes are skipped.
EXTENDED_ARG preceding any other opcode causes the optimizer to bail.
- Optimizations are restricted to simple transformations occuring within a
+ Optimizations are restricted to simple transformations occurring within a
single basic block. All transformations keep the code size the same or
smaller. For those that reduce size, the gaps are initially filled with
NOPs. Later those NOPs are removed and the jump addresses retargeted in
encoding = _Py_StandardStreamEncoding;
errors = _Py_StandardStreamErrors;
if (!encoding || !errors) {
- if (!errors) {
- /* When the LC_CTYPE locale is the POSIX locale ("C locale"),
- stdin and stdout use the surrogateescape error handler by
- default, instead of the strict error handler. */
- char *loc = setlocale(LC_CTYPE, NULL);
- if (loc != NULL && strcmp(loc, "C") == 0)
- errors = "surrogateescape";
- }
-
pythonioencoding = Py_GETENV("PYTHONIOENCODING");
if (pythonioencoding) {
char *err;
if (err) {
*err = '\0';
err++;
- if (*err && !_Py_StandardStreamErrors) {
+ if (*err && !errors) {
errors = err;
}
}
encoding = pythonioencoding;
}
}
+ if (!errors && !(pythonioencoding && *pythonioencoding)) {
+ /* When the LC_CTYPE locale is the POSIX locale ("C locale"),
+ stdin and stdout use the surrogateescape error handler by
+ default, instead of the strict error handler. */
+ char *loc = setlocale(LC_CTYPE, NULL);
+ if (loc != NULL && strcmp(loc, "C") == 0)
+ errors = "surrogateescape";
+ }
}
/* Set sys.stdin */
}
+static void
+_Py_FatalError_DumpTracebacks(int fd)
+{
+ PyThreadState *tstate;
+
+#ifdef WITH_THREAD
+ /* PyGILState_GetThisThreadState() works even if the GIL was released */
+ tstate = PyGILState_GetThisThreadState();
+#else
+ tstate = PyThreadState_GET();
+#endif
+ if (tstate == NULL) {
+ /* _Py_DumpTracebackThreads() requires the thread state to display
+ * frames */
+ return;
+ }
+
+ fputc('\n', stderr);
+ fflush(stderr);
+
+ /* display the current Python stack */
+ _Py_DumpTracebackThreads(fd, tstate->interp, tstate);
+}
+
/* Print the current exception (if an exception is set) with its traceback,
- * or display the current Python stack.
- *
- * Don't call PyErr_PrintEx() and the except hook, because Py_FatalError() is
- * called on catastrophic cases. */
+ or display the current Python stack.
-static void
-_Py_PrintFatalError(int fd)
+ Don't call PyErr_PrintEx() and the except hook, because Py_FatalError() is
+ called on catastrophic cases.
+
+ Return 1 if the traceback was displayed, 0 otherwise. */
+
+static int
+_Py_FatalError_PrintExc(int fd)
{
PyObject *ferr, *res;
PyObject *exception, *v, *tb;
int has_tb;
- PyThreadState *tstate;
+
+ if (PyThreadState_GET() == NULL) {
+ /* The GIL is released: trying to acquire it is likely to deadlock,
+ just give up. */
+ return 0;
+ }
PyErr_Fetch(&exception, &v, &tb);
if (exception == NULL) {
/* No current exception */
- goto display_stack;
+ return 0;
}
ferr = _PySys_GetObjectId(&PyId_stderr);
if (ferr == NULL || ferr == Py_None) {
/* sys.stderr is not set yet or set to None,
no need to try to display the exception */
- goto display_stack;
+ return 0;
}
PyErr_NormalizeException(&exception, &v, &tb);
PyException_SetTraceback(v, tb);
if (exception == NULL) {
/* PyErr_NormalizeException() failed */
- goto display_stack;
+ return 0;
}
has_tb = (tb != Py_None);
else
Py_DECREF(res);
- if (has_tb)
- return;
-
-display_stack:
-#ifdef WITH_THREAD
- /* PyGILState_GetThisThreadState() works even if the GIL was released */
- tstate = PyGILState_GetThisThreadState();
-#else
- tstate = PyThreadState_GET();
-#endif
- if (tstate == NULL) {
- /* _Py_DumpTracebackThreads() requires the thread state to display
- * frames */
- return;
- }
-
- fputc('\n', stderr);
- fflush(stderr);
-
- /* display the current Python stack */
- _Py_DumpTracebackThreads(fd, tstate->interp, tstate);
+ return has_tb;
}
+
/* Print fatal error message and abort */
void
/* Print the exception (if an exception is set) with its traceback,
* or display the current Python stack. */
- _Py_PrintFatalError(fd);
-
- /* Flush sys.stdout and sys.stderr */
- flush_std_files();
+ if (!_Py_FatalError_PrintExc(fd))
+ _Py_FatalError_DumpTracebacks(fd);
/* The main purpose of faulthandler is to display the traceback. We already
* did our best to display it. So faulthandler can now be disabled.
* (Don't trigger it on abort().) */
_PyFaulthandler_Fini();
+ /* Check if the current Python thread hold the GIL */
+ if (PyThreadState_GET() != NULL) {
+ /* Flush sys.stdout and sys.stderr */
+ flush_std_files();
+ }
+
#ifdef MS_WINDOWS
len = strlen(msg);
#include "Python.h"
+#define GET_TSTATE() \
+ ((PyThreadState*)_Py_atomic_load_relaxed(&_PyThreadState_Current))
+#define SET_TSTATE(value) \
+ _Py_atomic_store_relaxed(&_PyThreadState_Current, (Py_uintptr_t)(value))
+#define GET_INTERP_STATE() \
+ (GET_TSTATE()->interp)
+
+
/* --------------------------------------------------------------------------
CAUTION
/* Assuming the current thread holds the GIL, this is the
PyThreadState for the current thread. */
-_Py_atomic_address _PyThreadState_Current = {NULL};
+_Py_atomic_address _PyThreadState_Current = {0};
PyThreadFrameGetter _PyThreadState_GetFrame = NULL;
#ifdef WITH_THREAD
PyState_FindModule(struct PyModuleDef* module)
{
Py_ssize_t index = module->m_base.m_index;
- PyInterpreterState *state = PyThreadState_GET()->interp;
+ PyInterpreterState *state = GET_INTERP_STATE();
PyObject *res;
if (module->m_slots) {
return NULL;
"PyState_AddModule called on module with slots");
return -1;
}
- state = PyThreadState_GET()->interp;
+ state = GET_INTERP_STATE();
if (!def)
return -1;
if (!state->modules_by_index) {
PyState_AddModule(PyObject* module, struct PyModuleDef* def)
{
Py_ssize_t index;
- PyInterpreterState *state = PyThreadState_GET()->interp;
+ PyInterpreterState *state = GET_INTERP_STATE();
if (!def) {
Py_FatalError("PyState_AddModule: Module Definition is NULL");
return -1;
"PyState_RemoveModule called on module with slots");
return -1;
}
- state = PyThreadState_GET()->interp;
+ state = GET_INTERP_STATE();
if (index == 0) {
Py_FatalError("PyState_RemoveModule: Module index invalid.");
return -1;
void
_PyState_ClearModules(void)
{
- PyInterpreterState *state = PyThreadState_GET()->interp;
+ PyInterpreterState *state = GET_INTERP_STATE();
if (state->modules_by_index) {
Py_ssize_t i;
for (i = 0; i < PyList_GET_SIZE(state->modules_by_index); i++) {
void
PyThreadState_Delete(PyThreadState *tstate)
{
- if (tstate == (PyThreadState*)_Py_atomic_load_relaxed(&_PyThreadState_Current))
+ if (tstate == GET_TSTATE())
Py_FatalError("PyThreadState_Delete: tstate is still current");
#ifdef WITH_THREAD
if (autoInterpreterState && PyThread_get_key_value(autoTLSkey) == tstate)
void
PyThreadState_DeleteCurrent()
{
- PyThreadState *tstate = (PyThreadState*)_Py_atomic_load_relaxed(
- &_PyThreadState_Current);
+ PyThreadState *tstate = GET_TSTATE();
if (tstate == NULL)
Py_FatalError(
"PyThreadState_DeleteCurrent: no current tstate");
- _Py_atomic_store_relaxed(&_PyThreadState_Current, NULL);
+ SET_TSTATE(NULL);
if (autoInterpreterState && PyThread_get_key_value(autoTLSkey) == tstate)
PyThread_delete_key_value(autoTLSkey);
tstate_delete_common(tstate);
PyThreadState *
+_PyThreadState_UncheckedGet(void)
+{
+ return GET_TSTATE();
+}
+
+
+PyThreadState *
PyThreadState_Get(void)
{
- PyThreadState *tstate = (PyThreadState*)_Py_atomic_load_relaxed(
- &_PyThreadState_Current);
+ PyThreadState *tstate = GET_TSTATE();
if (tstate == NULL)
Py_FatalError("PyThreadState_Get: no current thread");
PyThreadState *
PyThreadState_Swap(PyThreadState *newts)
{
- PyThreadState *oldts = (PyThreadState*)_Py_atomic_load_relaxed(
- &_PyThreadState_Current);
+ PyThreadState *oldts = GET_TSTATE();
- _Py_atomic_store_relaxed(&_PyThreadState_Current, newts);
+ SET_TSTATE(newts);
/* It should not be possible for more than one thread state
to be used for a thread. Check this the best we can in debug
builds.
PyObject *
PyThreadState_GetDict(void)
{
- PyThreadState *tstate = (PyThreadState*)_Py_atomic_load_relaxed(
- &_PyThreadState_Current);
+ PyThreadState *tstate = GET_TSTATE();
if (tstate == NULL)
return NULL;
int
PyThreadState_SetAsyncExc(long id, PyObject *exc) {
- PyThreadState *tstate = PyThreadState_GET();
- PyInterpreterState *interp = tstate->interp;
+ PyInterpreterState *interp = GET_INTERP_STATE();
PyThreadState *p;
/* Although the GIL is held, a few C API functions can be called
{
/* Must be the tstate for this thread */
assert(PyGILState_GetThisThreadState()==tstate);
- return tstate == (PyThreadState*)_Py_atomic_load_relaxed(&_PyThreadState_Current);
+ return tstate == GET_TSTATE();
}
/* Internal initialization/finalization functions called by
int
PyGILState_Check(void)
{
- /* can't use PyThreadState_Get() since it will assert that it has the GIL */
- PyThreadState *tstate = (PyThreadState*)_Py_atomic_load_relaxed(
- &_PyThreadState_Current);
+ PyThreadState *tstate = GET_TSTATE();
return tstate && (tstate == PyGILState_GetThisThreadState());
}
/* only print colon if the str() of the
object is not the empty string
*/
- if (s == NULL)
+ if (s == NULL) {
+ PyErr_Clear();
err = -1;
+ PyFile_WriteString(": <exception str() failed>", f);
+ }
else if (!PyUnicode_Check(s) ||
PyUnicode_GetLength(s) != 0)
err = PyFile_WriteString(": ", f);
Py_XDECREF(s);
}
/* try to write a newline in any case */
+ if (err < 0) {
+ PyErr_Clear();
+ }
err += PyFile_WriteString("\n", f);
Py_XDECREF(tb);
Py_DECREF(value);
#endif /* USE_STACKCHECK */
-/* Deprecated C API functions still provided for binary compatiblity */
+/* Deprecated C API functions still provided for binary compatibility */
#undef PyParser_SimpleParseFile
PyAPI_FUNC(node *)
# ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
# endif
+# ifdef HAVE_LINUX_RANDOM_H
+# include <linux/random.h>
+# endif
# ifdef HAVE_GETRANDOM
# include <sys/random.h>
# elif defined(HAVE_GETRANDOM_SYSCALL)
return 0;
}
+/* Issue #25003: Don't use getentropy() on Solaris (available since
+ * Solaris 11.3), it is blocking whereas os.urandom() should not block. */
#elif defined(HAVE_GETENTROPY) && !defined(sun)
#define PY_GETENTROPY 1
#else
-/* Issue #25003: Don' use getentropy() on Solaris (available since
- * Solaris 11.3), it is blocking whereas os.urandom() should not block. */
#if defined(HAVE_GETRANDOM) || defined(HAVE_GETRANDOM_SYSCALL)
#define PY_GETRANDOM 1
/* Is getrandom() supported by the running kernel?
* Need Linux kernel 3.17 or newer, or Solaris 11.3 or newer */
static int getrandom_works = 1;
- /* Use non-blocking /dev/urandom device. On Linux at boot, the getrandom()
- * syscall blocks until /dev/urandom is initialized with enough entropy. */
- const int flags = 0;
+
+ /* getrandom() on Linux will block if called before the kernel has
+ * initialized the urandom entropy pool. This will cause Python
+ * to hang on startup if called very early in the boot process -
+ * see https://bugs.python.org/issue26839. To avoid this, use the
+ * GRND_NONBLOCK flag. */
+ const int flags = GRND_NONBLOCK;
int n;
if (!getrandom_works)
return 0;
while (0 < size) {
- errno = 0;
+#ifdef sun
+ /* Issue #26735: On Solaris, getrandom() is limited to returning up
+ to 1024 bytes */
+ n = Py_MIN(size, 1024);
+#else
+ n = size;
+#endif
+ errno = 0;
#ifdef HAVE_GETRANDOM
if (raise) {
Py_BEGIN_ALLOW_THREADS
- n = getrandom(buffer, size, flags);
+ n = getrandom(buffer, n, flags);
Py_END_ALLOW_THREADS
}
else {
- n = getrandom(buffer, size, flags);
+ n = getrandom(buffer, n, flags);
}
#else
/* On Linux, use the syscall() function because the GNU libc doesn't
* https://sourceware.org/bugzilla/show_bug.cgi?id=17252 */
if (raise) {
Py_BEGIN_ALLOW_THREADS
- n = syscall(SYS_getrandom, buffer, size, flags);
+ n = syscall(SYS_getrandom, buffer, n, flags);
Py_END_ALLOW_THREADS
}
else {
- n = syscall(SYS_getrandom, buffer, size, flags);
+ n = syscall(SYS_getrandom, buffer, n, flags);
}
#endif
getrandom_works = 0;
return 0;
}
+ if (errno == EAGAIN) {
+ /* If we failed with EAGAIN, the entropy pool was
+ * uninitialized. In this case, we return failure to fall
+ * back to reading from /dev/urandom.
+ *
+ * Note: In this case the data read will not be random so
+ * should not be used for cryptographic purposes. Retaining
+ * the existing semantics for practical purposes. */
+ getrandom_works = 0;
+ return 0;
+ }
if (errno == EINTR) {
if (PyErr_CheckSignals()) {
Py_ssize_t i;
PyObject *data;
assert(ste->ste_directives);
- for (i = 0; ; i++) {
+ for (i = 0; i < PyList_GET_SIZE(ste->ste_directives); i++) {
data = PyList_GET_ITEM(ste->ste_directives, i);
assert(PyTuple_CheckExact(data));
- if (PyTuple_GET_ITEM(data, 0) == name)
- break;
+ assert(PyUnicode_CheckExact(PyTuple_GET_ITEM(data, 0)));
+ if (PyUnicode_Compare(PyTuple_GET_ITEM(data, 0), name) == 0) {
+ PyErr_SyntaxLocationObject(ste->ste_table->st_filename,
+ PyLong_AsLong(PyTuple_GET_ITEM(data, 1)),
+ PyLong_AsLong(PyTuple_GET_ITEM(data, 2)));
+
+ return 0;
+ }
}
- PyErr_SyntaxLocationObject(ste->ste_table->st_filename,
- PyLong_AsLong(PyTuple_GET_ITEM(data, 1)),
- PyLong_AsLong(PyTuple_GET_ITEM(data, 2)));
+ PyErr_SetString(PyExc_RuntimeError,
+ "BUG: internal directive bookkeeping broken");
return 0;
}
/* Copy the bound and global dictionaries.
- These dictionary are used by all blocks enclosed by the
+ These dictionaries are used by all blocks enclosed by the
current block. The analyze_block() call modifies these
dictionaries.
static int
symtable_record_directive(struct symtable *st, identifier name, stmt_ty s)
{
- PyObject *data;
+ PyObject *data, *mangled;
int res;
if (!st->st_cur->ste_directives) {
st->st_cur->ste_directives = PyList_New(0);
if (!st->st_cur->ste_directives)
return 0;
}
- data = Py_BuildValue("(Oii)", name, s->lineno, s->col_offset);
+ mangled = _Py_Mangle(st->st_private, name);
+ if (!mangled)
+ return 0;
+ data = Py_BuildValue("(Nii)", mangled, s->lineno, s->col_offset);
if (!data)
return 0;
res = PyList_Append(st->st_cur->ste_directives, data);
Py_XDECREF(name);
Py_XDECREF(value);
/* No return value, therefore clear error state if possible */
- if (_Py_atomic_load_relaxed(&_PyThreadState_Current))
+ if (_PyThreadState_UncheckedGet())
PyErr_Clear();
}
}
/*
- * Return the thread Id instead of an handle. The Id is said to uniquely identify the
+ * Return the thread Id instead of a handle. The Id is said to uniquely identify the
* thread in the system
*/
long
-This is Python version 3.5.1
+This is Python version 3.5.2
============================
Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011,
-2012, 2013, 2014, 2015 Python Software Foundation. All rights reserved.
+2012, 2013, 2014, 2015, 2016 Python Software Foundation. All rights reserved.
Python 3.x is a new version of the language, which is incompatible with the
2.x line of releases. The language is mostly the same, but many details,
If ran, the "profile-opt" rule will do several steps.
First, the entire Python directory is cleaned of temporary files that
-may resulted in a previous compilation.
+may have resulted in a previous compilation.
Then, an instrumented version of the interpreter is built, using suitable
compiler flags for each flavour. Note that this is just an intermediary
and stderr, that may appear at this step is supressed.
Finally, the last step is to rebuild the interpreter, using the information
-collected in the previous one. The end result will be a the Python binary
+collected in the previous one. The end result will be a Python binary
that is optimized and suitable for distribution or production installation.
---------------------------------
Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011,
-2012, 2013, 2014, 2015 Python Software Foundation. All rights reserved.
+2012, 2013, 2014, 2015, 2016 Python Software Foundation. All rights reserved.
Copyright (c) 2000 BeOpen.com. All rights reserved.
text.pop()
return output()
+def format_escape(s):
+ # double up curly-braces, this string will be used
+ # as part of a format_map() template later
+ s = s.replace('{', '{{')
+ s = s.replace('}', '}}')
+ return s
+
def linear_format(s, **kwargs):
"""
Perform str.format-like substitution, except:
add('\n')
continue
- name, curl, trailing = trailing.partition('}')
+ name, curly, trailing = trailing.partition('}')
if not curly or name not in kwargs:
add(line)
add('\n')
count_min = sys.maxsize
count_max = -1
- add("switch (PyTuple_GET_SIZE(args)) {{\n")
+ add("switch (PyTuple_GET_SIZE(args)) {\n")
for subset in permute_optional_groups(left, required, right):
count = len(subset)
count_min = min(count_min, count)
d = {}
d['count'] = count
d['name'] = f.name
- d['groups'] = sorted(group_ids)
d['format_units'] = "".join(p.converter.format_unit for p in subset)
parse_arguments = []
s = ' PyErr_SetString(PyExc_TypeError, "{} requires {} to {} arguments");\n'
add(s.format(f.full_name, count_min, count_max))
add(' goto exit;\n')
- add("}}")
- template_dict['option_group_parsing'] = output()
+ add("}")
+ template_dict['option_group_parsing'] = format_escape(output())
def render_function(self, clinic, f):
if not f:
f.return_converter.render(f, data)
template_dict['impl_return_type'] = f.return_converter.type
- template_dict['declarations'] = "\n".join(data.declarations)
+ template_dict['declarations'] = format_escape("\n".join(data.declarations))
template_dict['initializers'] = "\n\n".join(data.initializers)
template_dict['modifications'] = '\n\n'.join(data.modifications)
template_dict['keywords'] = '"' + '", "'.join(data.keywords) + '"'
template_dict['parse_arguments'] = ', '.join(data.parse_arguments)
template_dict['impl_parameters'] = ", ".join(data.impl_parameters)
template_dict['impl_arguments'] = ", ".join(data.impl_arguments)
- template_dict['return_conversion'] = "".join(data.return_conversion).rstrip()
- template_dict['cleanup'] = "".join(data.cleanup)
+ template_dict['return_conversion'] = format_escape("".join(data.return_conversion).rstrip())
+ template_dict['cleanup'] = format_escape("".join(data.cleanup))
template_dict['return_value'] = data.return_value
# used by unpack tuple code generator
declaration.append('\nPy_ssize_clean_t ')
declaration.append(self.length_name())
declaration.append(';')
- s = "".join(declaration)
- # double up curly-braces, this string will be used
- # as part of a format_map() template later
- s = s.replace("{", "{{")
- s = s.replace("}", "}}")
- return s
+ return "".join(declaration)
def initialize(self):
"""
# Licensed to the PSF under a contributor agreement.
#
-import builtins
import clinic
from clinic import DSLParser
import collections
Nested docstring here, goeth.
""".strip(), function.docstring)
- def test_parser_regression_special_character_in_parameter_column_of_docstring_first_line(self):
- function = self.parse_function("""
-module os
-os.stat
- path: str
-This/used to break Clinic!
-""")
- self.assertEqual("stat($module, /, path)\n--\n\nThis/used to break Clinic!", function.docstring)
-
def test_directive(self):
c = FakeClinic()
parser = DSLParser(c)
base = os.path.basename(file)
dest = base[:-2] + '.o'
outfp.write("%s: %s\n" % (dest, file))
- outfp.write("\t$(CC) $(CFLAGS) $(CPPFLAGS) -c %s\n" % file)
+ outfp.write("\t$(CC) $(PY_CFLAGS) $(PY_CPPFLAGS) -c %s\n" % file)
files[i] = dest
deps.append(dest)
outfp.write("\n%s: %s\n" % (target, ' '.join(deps)))
- outfp.write("\t$(LINKCC) $(LDFLAGS) $(LINKFORSHARED) %s -o %s $(LDLAST)\n" %
+ outfp.write("\t$(LINKCC) $(PY_LDFLAGS) $(LINKFORSHARED) %s -o %s $(LDLAST)\n" %
(' '.join(files), target))
outfp.write("\nclean:\n\t-rm -f *.o %s\n" % target)
long = int
# Look up the gdb.Type for some standard types:
-_type_char_ptr = gdb.lookup_type('char').pointer() # char*
-_type_unsigned_char_ptr = gdb.lookup_type('unsigned char').pointer() # unsigned char*
-_type_void_ptr = gdb.lookup_type('void').pointer() # void*
-_type_unsigned_short_ptr = gdb.lookup_type('unsigned short').pointer()
-_type_unsigned_int_ptr = gdb.lookup_type('unsigned int').pointer()
+# Those need to be refreshed as types (pointer sizes) may change when
+# gdb loads different executables
-# value computed later, see PyUnicodeObjectPtr.proxy()
-_is_pep393 = None
+def _type_char_ptr():
+ return gdb.lookup_type('char').pointer() # char*
-SIZEOF_VOID_P = _type_void_ptr.sizeof
+def _type_unsigned_char_ptr():
+ return gdb.lookup_type('unsigned char').pointer() # unsigned char*
+
+
+def _type_unsigned_short_ptr():
+ return gdb.lookup_type('unsigned short').pointer()
+
+
+def _type_unsigned_int_ptr():
+ return gdb.lookup_type('unsigned int').pointer()
-Py_TPFLAGS_HEAPTYPE = (1 << 9)
+def _sizeof_void_p():
+ return gdb.lookup_type('void').pointer().sizeof
+
+
+# value computed later, see PyUnicodeObjectPtr.proxy()
+_is_pep393 = None
+
+Py_TPFLAGS_HEAPTYPE = (1 << 9)
Py_TPFLAGS_LONG_SUBCLASS = (1 << 24)
Py_TPFLAGS_LIST_SUBCLASS = (1 << 25)
Py_TPFLAGS_TUPLE_SUBCLASS = (1 << 26)
return ( ( typeobj.field('tp_basicsize') +
nitems * typeobj.field('tp_itemsize') +
- (SIZEOF_VOID_P - 1)
- ) & ~(SIZEOF_VOID_P - 1)
+ (_sizeof_void_p() - 1)
+ ) & ~(_sizeof_void_p() - 1)
).cast(_PyObject_VAR_SIZE._type_size_t)
_PyObject_VAR_SIZE._type_size_t = None
size = _PyObject_VAR_SIZE(typeobj, tsize)
dictoffset += size
assert dictoffset > 0
- assert dictoffset % SIZEOF_VOID_P == 0
+ assert dictoffset % _sizeof_void_p() == 0
- dictptr = self._gdbval.cast(_type_char_ptr) + dictoffset
+ dictptr = self._gdbval.cast(_type_char_ptr()) + dictoffset
PyObjectPtrPtr = PyObjectPtr.get_gdb_type().pointer()
dictptr = dictptr.cast(PyObjectPtrPtr)
return PyObjectPtr.from_pyobject_ptr(dictptr.dereference())
def __str__(self):
field_ob_size = self.field('ob_size')
field_ob_sval = self.field('ob_sval')
- char_ptr = field_ob_sval.address.cast(_type_unsigned_char_ptr)
+ char_ptr = field_ob_sval.address.cast(_type_unsigned_char_ptr())
return ''.join([chr(char_ptr[i]) for i in safe_range(field_ob_size)])
def proxyval(self, visited):
field_str = self.field('data')['any']
repr_kind = int(state['kind'])
if repr_kind == 1:
- field_str = field_str.cast(_type_unsigned_char_ptr)
+ field_str = field_str.cast(_type_unsigned_char_ptr())
elif repr_kind == 2:
- field_str = field_str.cast(_type_unsigned_short_ptr)
+ field_str = field_str.cast(_type_unsigned_short_ptr())
elif repr_kind == 4:
- field_str = field_str.cast(_type_unsigned_int_ptr)
+ field_str = field_str.cast(_type_unsigned_int_ptr())
else:
# Python 3.2 and earlier
field_length = long(self.field('length'))
"%BUILD%python.exe" %PGO%\r
)\r
\r
- @call "%PCBUILD%build.bat" -e -p %BUILD_PLAT% -c PGUpdate -t %TARGET% %CERTOPTS%\r
+ @call "%PCBUILD%build.bat" -e -p %BUILD_PLAT% -c PGUpdate -t Build %CERTOPTS%\r
)\r
@if errorlevel 1 exit /B\r
@echo off\r
<Checkbox Name="Include_launcher" X="185" Y="251" Width="100" Height="24" TabStop="yes" FontId="3" HideWhenDisabled="no">#(loc.Include_launcherLabel)</Checkbox>
<Checkbox Name="CustomInstallLauncherAllUsers" X="285" Y="251" Width="-11" Height="24" TabStop="yes" FontId="3">#(loc.InstallLauncherAllUsersLabel)</Checkbox>
- <Text X="205" Y="276" Width="-11" Height="24" TabStop="no" FontId="5">#(loc.Include_launcherHelpLabel)</Text>
+ <Text Name="Include_launcherHelp" X="205" Y="276" Width="-11" Height="24" TabStop="no" FontId="5"></Text>
<Button Name="Custom1BackButton" X="185" Y="-11" Width="85" Height="27" TabStop="yes" FontId="0">#(loc.CustomBackButton)</Button>
<Button Name="CustomNextButton" X="-101" Y="-11" Width="85" Height="27" TabStop="yes" FontId="0">#(loc.CustomNextButton)</Button>
<String Id="Include_testLabel">Python &test suite</String>
<String Id="Include_testHelpLabel">Installs the standard library test suite.</String>
<String Id="Include_launcherLabel">py &launcher</String>
- <String Id="Include_launcherHelpLabel">Installs the global 'py' launcher to make it easier to start Python.</String>
+ <String Id="Include_launcherHelp">Installs the global 'py' launcher to make it easier to start Python.</String>
+ <String Id="Include_launcherRemove">Use Programs and Features to remove the 'py' launcher.</String>
+ <String Id="Include_launcherUpgrade">Upgrades the global 'py' launcher from the previous version.</String>
<String Id="AssociateFilesLabel">Associate &files with Python (requires the py launcher)</String>
<String Id="ShortcutsLabel">Create shortcuts for installed applications</String>
ID_CUSTOM_ASSOCIATE_FILES_CHECKBOX,
ID_CUSTOM_INSTALL_ALL_USERS_CHECKBOX,
ID_CUSTOM_INSTALL_LAUNCHER_ALL_USERS_CHECKBOX,
+ ID_CUSTOM_INCLUDE_LAUNCHER_HELP_LABEL,
ID_CUSTOM_COMPILE_ALL_CHECKBOX,
ID_CUSTOM_BROWSE_BUTTON,
ID_CUSTOM_BROWSE_BUTTON_LABEL,
{ ID_CUSTOM_ASSOCIATE_FILES_CHECKBOX, L"AssociateFiles" },
{ ID_CUSTOM_INSTALL_ALL_USERS_CHECKBOX, L"InstallAllUsers" },
{ ID_CUSTOM_INSTALL_LAUNCHER_ALL_USERS_CHECKBOX, L"CustomInstallLauncherAllUsers" },
+ { ID_CUSTOM_INCLUDE_LAUNCHER_HELP_LABEL, L"Include_launcherHelp" },
{ ID_CUSTOM_COMPILE_ALL_CHECKBOX, L"CompileAll" },
{ ID_CUSTOM_BROWSE_BUTTON, L"CustomBrowseButton" },
{ ID_CUSTOM_BROWSE_BUTTON_LABEL, L"CustomBrowseButtonLabel" },
ThemeSendControlMessage(_theme, ID_CUSTOM_INSTALL_LAUNCHER_ALL_USERS_CHECKBOX, BM_SETCHECK,
installLauncherAllUsers ? BST_CHECKED : BST_UNCHECKED, 0);
+
+ LOC_STRING *pLocString = nullptr;
+ LPCWSTR locKey = L"#(loc.Include_launcherHelp)";
+ LONGLONG detectedLauncher;
+
+ if (SUCCEEDED(BalGetNumericVariable(L"DetectedLauncher", &detectedLauncher)) && detectedLauncher) {
+ locKey = L"#(loc.Include_launcherRemove)";
+ } else if (SUCCEEDED(BalGetNumericVariable(L"DetectedOldLauncher", &detectedLauncher)) && detectedLauncher) {
+ locKey = L"#(loc.Include_launcherUpgrade)";
+ }
+
+ if (SUCCEEDED(LocGetString(_wixLoc, locKey, &pLocString)) && pLocString) {
+ ThemeSetTextControl(_theme, ID_CUSTOM_INCLUDE_LAUNCHER_HELP_LABEL, pLocString->wzText);
+ }
}
void Custom2Page_Show() {
return nResult;
}
+ virtual STDMETHODIMP_(int) OnDetectRelatedMsiPackage(
+ __in_z LPCWSTR wzPackageId,
+ __in_z LPCWSTR /*wzProductCode*/,
+ __in BOOL fPerMachine,
+ __in DWORD64 /*dw64Version*/,
+ __in BOOTSTRAPPER_RELATED_OPERATION operation
+ ) {
+ if (BOOTSTRAPPER_RELATED_OPERATION_MAJOR_UPGRADE == operation &&
+ (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, wzPackageId, -1, L"launcher_AllUsers", -1) ||
+ CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, wzPackageId, -1, L"launcher_JustForMe", -1))) {
+ auto hr = LoadAssociateFilesStateFromKey(_engine, fPerMachine ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER);
+ if (hr == S_OK) {
+ _engine->SetVariableNumeric(L"AssociateFiles", 1);
+ } else if (FAILED(hr)) {
+ BalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, "Failed to load AssociateFiles state: error code 0x%08X", hr);
+ }
+
+ _engine->SetVariableNumeric(L"Include_launcher", 1);
+ _engine->SetVariableNumeric(L"DetectedOldLauncher", 1);
+ _engine->SetVariableNumeric(L"InstallLauncherAllUsers", fPerMachine ? 1 : 0);
+ }
+ return CheckCanceled() ? IDCANCEL : IDNOACTION;
+ }
virtual STDMETHODIMP_(int) OnDetectRelatedBundle(
__in LPCWSTR wzBundleId,
if (BOOTSTRAPPER_RELATED_OPERATION_DOWNGRADE == operation) {
_downgradingOtherVersion = TRUE;
} else if (BOOTSTRAPPER_RELATED_OPERATION_MAJOR_UPGRADE == operation) {
- _upgradingOldVersion = TRUE;
-
- // Assume we don't want the launcher or file associations, and if
- // they have already been installed then loading the state will
- // reactivate these settings.
- _engine->SetVariableNumeric(L"Include_launcher", 0);
- _engine->SetVariableNumeric(L"AssociateFiles", 0);
- auto hr = LoadLauncherStateFromKey(_engine, HKEY_CURRENT_USER);
- if (hr == S_FALSE) {
- hr = LoadLauncherStateFromKey(_engine, HKEY_LOCAL_MACHINE);
- }
- if (FAILED(hr)) {
- BalLog(
- BOOTSTRAPPER_LOG_LEVEL_ERROR,
- "Failed to load launcher state: error code 0x%08X",
- hr
- );
- }
+ BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Detected previous version - planning upgrade");
+ _upgrading = TRUE;
LoadOptionalFeatureStates(_engine);
} else if (BOOTSTRAPPER_RELATED_OPERATION_NONE == operation) {
virtual STDMETHODIMP_(void) OnDetectPackageComplete(
__in LPCWSTR wzPackageId,
- __in HRESULT /*hrStatus*/,
+ __in HRESULT hrStatus,
__in BOOTSTRAPPER_PACKAGE_STATE state
- ) { }
+ ) {
+ if (FAILED(hrStatus)) {
+ return;
+ }
+
+ BOOL detectedLauncher = FALSE;
+ HKEY hkey = HKEY_LOCAL_MACHINE;
+ if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, wzPackageId, -1, L"launcher_AllUsers", -1)) {
+ if (BOOTSTRAPPER_PACKAGE_STATE_PRESENT == state || BOOTSTRAPPER_PACKAGE_STATE_OBSOLETE == state) {
+ detectedLauncher = TRUE;
+ _engine->SetVariableNumeric(L"InstallLauncherAllUsers", 1);
+ }
+ } else if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, wzPackageId, -1, L"launcher_JustForMe", -1)) {
+ if (BOOTSTRAPPER_PACKAGE_STATE_PRESENT == state || BOOTSTRAPPER_PACKAGE_STATE_OBSOLETE == state) {
+ detectedLauncher = TRUE;
+ _engine->SetVariableNumeric(L"InstallLauncherAllUsers", 0);
+ }
+ }
+
+ if (detectedLauncher) {
+ /* When we detect the current version of the launcher. */
+ _engine->SetVariableNumeric(L"Include_launcher", 1);
+ _engine->SetVariableNumeric(L"DetectedLauncher", 1);
+ _engine->SetVariableString(L"Include_launcherState", L"disable");
+ _engine->SetVariableString(L"InstallLauncherAllUsersState", L"disable");
+
+ auto hr = LoadAssociateFilesStateFromKey(_engine, hkey);
+ if (hr == S_OK) {
+ _engine->SetVariableNumeric(L"AssociateFiles", 1);
+ } else if (FAILED(hr)) {
+ BalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, "Failed to load AssociateFiles state: error code 0x%08X", hr);
+ }
+ }
+ }
virtual STDMETHODIMP_(void) OnDetectComplete(__in HRESULT hrStatus) {
if (SUCCEEDED(hrStatus)) {
// Ensure the default path has been set
- LONGLONG installAll;
- LPWSTR targetDir = nullptr;
- LPWSTR defaultTargetDir = nullptr;
-
- hrStatus = BalGetStringVariable(L"TargetDir", &targetDir);
- if (FAILED(hrStatus) || !targetDir || !targetDir[0]) {
- ReleaseStr(targetDir);
- targetDir = nullptr;
-
- if (FAILED(BalGetNumericVariable(L"InstallAllUsers", &installAll))) {
- installAll = 0;
- }
-
- hrStatus = BalGetStringVariable(
- installAll ? L"DefaultAllUsersTargetDir" : L"DefaultJustForMeTargetDir",
- &defaultTargetDir
- );
-
- if (SUCCEEDED(hrStatus) && defaultTargetDir) {
- if (defaultTargetDir[0] && SUCCEEDED(BalFormatString(defaultTargetDir, &targetDir))) {
- hrStatus = _engine->SetVariableString(L"TargetDir", targetDir);
- ReleaseStr(targetDir);
- }
- ReleaseStr(defaultTargetDir);
- }
- }
+ hrStatus = EnsureTargetDir();
}
SetState(PYBA_STATE_DETECTED, hrStatus);
hr = LoadBootstrapperBAFunctions();
BalExitOnFailure(hr, "Failed to load bootstrapper functions.");
+
hr = UpdateUIStrings(_command.action);
BalExitOnFailure(hr, "Failed to load UI strings.");
+ if (_command.action == BOOTSTRAPPER_ACTION_MODIFY) {
+ LoadOptionalFeatureStates(_engine);
+ }
+
GetBundleFileVersion();
// don't fail if we couldn't get the version info; best-effort only
LExit:
for (DWORD i = 0; i < _theme->cControls; ++i) {
THEME_CONTROL* pControl = _theme->rgControls + i;
LPWSTR text = nullptr;
- LPWSTR name = nullptr;
- LOC_STRING *locText = nullptr;
-
- // If a command link has a note, then add it.
- if ((pControl->dwStyle & BS_TYPEMASK) == BS_COMMANDLINK ||
- (pControl->dwStyle & BS_TYPEMASK) == BS_DEFCOMMANDLINK) {
- hr = StrAllocFormatted(&name, L"#(loc.%lsNote)", pControl->sczName);
- if (SUCCEEDED(hr)) {
- hr = LocGetString(_wixLoc, name, &locText);
- ReleaseStr(name);
- if (SUCCEEDED(hr) && locText && locText->wzText && locText->wzText[0]) {
- hr = BalFormatString(locText->wzText, &text);
- if (SUCCEEDED(hr) && text && text[0]) {
- ThemeSendControlMessage(_theme, pControl->wId, BCM_SETNOTE, 0, (LPARAM)text);
- ReleaseStr(text);
- text = nullptr;
- }
- }
- }
- hr = S_OK;
- }
if (!pControl->wPageId && pControl->sczText && *pControl->sczText) {
HRESULT hrFormat;
return;
}
+
HRESULT UpdateUIStrings(__in BOOTSTRAPPER_ACTION action) {
HRESULT hr = S_OK;
LPCWSTR likeInstalling = nullptr;
StrFree(controlState);
}
StrFree(controlName);
+ controlName = nullptr;
+
+
+ // If a command link has a note, then add it.
+ if ((pControl->dwStyle & BS_TYPEMASK) == BS_COMMANDLINK ||
+ (pControl->dwStyle & BS_TYPEMASK) == BS_DEFCOMMANDLINK) {
+ hr = StrAllocFormatted(&controlName, L"#(loc.%lsNote)", pControl->sczName);
+ if (SUCCEEDED(hr)) {
+ LOC_STRING *locText = nullptr;
+ hr = LocGetString(_wixLoc, controlName, &locText);
+ if (SUCCEEDED(hr) && locText && locText->wzText && locText->wzText[0]) {
+ LPWSTR text = nullptr;
+ hr = BalFormatString(locText->wzText, &text);
+ if (SUCCEEDED(hr) && text && text[0]) {
+ ThemeSendControlMessage(_theme, pControl->wId, BCM_SETNOTE, 0, (LPARAM)text);
+ ReleaseStr(text);
+ text = nullptr;
+ }
+ }
+ ReleaseStr(controlName);
+ controlName = nullptr;
+ }
+ hr = S_OK;
+ }
}
ThemeControlEnable(_theme, pControl->wId, enableControl);
if (_installPage == PAGE_LOADING) {
switch (_command.action) {
case BOOTSTRAPPER_ACTION_INSTALL:
- if (_upgradingOldVersion) {
+ if (_upgrading) {
_installPage = PAGE_UPGRADE;
- _upgrading = TRUE;
} else if (SUCCEEDED(BalGetNumericVariable(L"SimpleInstall", &simple)) && simple) {
_installPage = PAGE_SIMPLE_INSTALL;
} else {
static BAL_CONDITION WILL_ELEVATE_CONDITION = {
L"not WixBundleElevated and ("
/*Elevate when installing for all users*/
- L"InstallAllUsers or"
+ L"InstallAllUsers or "
/*Elevate when installing the launcher for all users and it was not detected*/
- L"(InstallLauncherAllUsers and Include_launcher and not DetectedLauncher) or"
- /*Elevate when the launcher was installed for all users and it is being removed*/
- L"(DetectedLauncher and DetectedLauncherAllUsers and not Include_launcher)"
+ L"(Include_launcher and InstallLauncherAllUsers and not DetectedLauncher)"
L")",
L""
};
return HRESULT_FROM_WIN32(res);
}
- static HRESULT LoadLauncherStateFromKey(
+ static HRESULT LoadAssociateFilesStateFromKey(
__in IBootstrapperEngine* pEngine,
__in HKEY hkHive
) {
const LPCWSTR subkey = L"Software\\Python\\PyLauncher";
HKEY hKey;
LRESULT res;
+ HRESULT hr;
- if (IsTargetPlatformx64(pEngine)) {
- res = RegOpenKeyExW(hkHive, subkey, 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
- } else {
- res = RegOpenKeyExW(hkHive, subkey, 0, KEY_READ | KEY_WOW64_32KEY, &hKey);
- }
+ res = RegOpenKeyExW(hkHive, subkey, 0, KEY_READ | KEY_WOW64_32KEY, &hKey);
if (res == ERROR_FILE_NOT_FOUND) {
return S_FALSE;
return HRESULT_FROM_WIN32(res);
}
- res = RegQueryValueExW(hKey, nullptr, nullptr, nullptr, nullptr, nullptr);
- if (res == ERROR_FILE_NOT_FOUND) {
- pEngine->SetVariableNumeric(L"Include_launcher", 0);
- } else if (res == ERROR_SUCCESS) {
- pEngine->SetVariableNumeric(L"Include_launcher", 1);
- pEngine->SetVariableNumeric(L"DetectedLauncher", 1);
- pEngine->SetVariableNumeric(L"InstallLauncherAllUsers", (hkHive == HKEY_LOCAL_MACHINE) ? 1 : 0);
- pEngine->SetVariableNumeric(L"DetectedLauncherAllUsers", (hkHive == HKEY_LOCAL_MACHINE) ? 1 : 0);
- pEngine->SetVariableString(L"InstallLauncherAllUsersState", L"disable");
- }
-
res = RegQueryValueExW(hKey, L"AssociateFiles", nullptr, nullptr, nullptr, nullptr);
if (res == ERROR_FILE_NOT_FOUND) {
- pEngine->SetVariableNumeric(L"AssociateFiles", 0);
+ hr = S_FALSE;
} else if (res == ERROR_SUCCESS) {
- pEngine->SetVariableNumeric(L"AssociateFiles", 1);
+ hr = S_OK;
+ } else {
+ hr = HRESULT_FROM_WIN32(res);
}
RegCloseKey(hKey);
- return S_OK;
+ return hr;
}
static void LoadOptionalFeatureStates(__in IBootstrapperEngine* pEngine) {
HKEY hkHive;
// The launcher installation is separate from the Python install, so we
- // check its state later. This also checks the file association option.
+ // check its state later. For now, assume we don't want the launcher or
+ // file associations, and if they have already been installed then
+ // loading the state will reactivate these settings.
+ pEngine->SetVariableNumeric(L"Include_launcher", 0);
+ pEngine->SetVariableNumeric(L"AssociateFiles", 0);
// Get the registry key from the bundle, to save having to duplicate it
// in multiple places.
_hrFinal = hrHostInitialization;
_downgradingOtherVersion = FALSE;
- _upgradingOldVersion = FALSE;
_restartResult = BOOTSTRAPPER_APPLY_RESTART_NONE;
_restartRequired = FALSE;
_allowRestart = FALSE;
_hBAFModule = nullptr;
_baFunction = nullptr;
-
- EnsureTargetDir();
}
DWORD _calculatedExecuteProgress;
BOOL _downgradingOtherVersion;
- BOOL _upgradingOldVersion;
BOOTSTRAPPER_APPLY_RESTART _restartResult;
BOOL _restartRequired;
BOOL _allowRestart;
-->
<Variable Name="DefaultCustomTargetDir" Value="" bal:Overridable="yes" />
- <Variable Name="InstallAllUsersState" Value="enabled" />
+ <Variable Name="InstallAllUsersState" Value="enabled" bal:Overridable="yes" />
<?if "$(var.PyTestExt)"="" ?>
<Variable Name="InstallLauncherAllUsersState" Value="enabled" bal:Overridable="yes" />
<?else ?>
<Variable Name="Include_pip" Value="1" bal:Overridable="yes" />
<?if "$(var.PyTestExt)"="" ?>
<Variable Name="Include_launcher" Value="1" bal:Overridable="yes" />
+ <Variable Name="Include_launcherState" Value="enabled" bal:Overridable="yes" />
<?else ?>
<Variable Name="Include_launcher" Value="0" />
<Variable Name="Include_launcherState" Value="disable" />
<Variable Name="LauncherOnly" Value="0" bal:Overridable="yes" />
<Variable Name="DetectedLauncher" Value="0" />
+ <Variable Name="DetectedOldLauncher" Value="0" />
<Variable Name="AssociateFiles" Value="1" bal:Overridable="yes" />
<Variable Name="Shortcuts" Value="1" bal:Overridable="yes" />
EnableFeatureSelection="yes"
Permanent="yes"
Visible="yes"
- InstallCondition="(InstallAllUsers or InstallLauncherAllUsers) and Include_launcher" />
+ InstallCondition="(InstallAllUsers or InstallLauncherAllUsers) and Include_launcher and not DetectedLauncher" />
<MsiPackage Id="launcher_JustForMe"
SourceFile="launcher.msi"
EnableFeatureSelection="yes"
Permanent="yes"
Visible="yes"
- InstallCondition="not (InstallAllUsers or InstallLauncherAllUsers) and Include_launcher" />
+ InstallCondition="not (InstallAllUsers or InstallLauncherAllUsers) and Include_launcher and not DetectedLauncher" />
</PackageGroup>
</Fragment>
</Wix>
\ No newline at end of file
<UpgradeVersion Property="UPGRADE" Minimum="$(var.UpgradeMinimumVersion)" IncludeMinimum="yes" Maximum="$(var.Version)" IncludeMaximum="no" />
</Upgrade>
+ <?ifdef CoreUpgradeCode ?>
<?if $(var.UpgradeCode)!=$(var.CoreUpgradeCode) ?>
- <?ifndef SkipMissingCore ?>
<Upgrade Id="$(var.CoreUpgradeCode)">
<UpgradeVersion Property="MISSING_CORE" Minimum="$(var.Version)" IncludeMinimum="yes" Maximum="$(var.Version)" IncludeMaximum="yes" OnlyDetect="yes" />
</Upgrade>
</Fragment>
<Fragment>
+ <?ifdef InstallDirectoryGuidSeed ?>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="InstallDirectory" ComponentGuidGenerationSeed="$(var.InstallDirectoryGuidSeed)" />
</Directory>
+ <?endif ?>
</Fragment>
<!-- Top-level directories -->
<SchemaVersion>2.0</SchemaVersion>
<OutputName>launcher</OutputName>
<OutputType>Package</OutputType>
- <DefineConstants>SkipMissingCore=1;$(DefineConstants)</DefineConstants>
+ <DefineConstants>UpgradeCode=1B68A0EC-4DD3-5134-840E-73854B0863F1;$(DefineConstants)</DefineConstants>
+ <IgnoreCommonWxlTemplates>true</IgnoreCommonWxlTemplates>
</PropertyGroup>
<Import Project="..\msi.props" />
<ItemGroup>
<MediaTemplate EmbedCab="yes" CompressionLevel="high" />
<Property Id="Suppress_TARGETDIR_Check" Value="1" />
- <PropertyRef Id="UpgradeTable" />
<PropertyRef Id="ARPPRODUCTICON" />
<Feature Id="DefaultFeature" AllowAdvertise="no" Title="!(loc.Title)" Description="!(loc.Description)">
<Custom Before="SetLauncherInstallDirectoryLM" Action="SetLauncherInstallDirectoryCU">NOT Installed AND NOT ALLUSERS=1</Custom>
<Custom Before="CostFinalize" Action="SetLauncherInstallDirectoryLM">NOT Installed AND ALLUSERS=1</Custom>
- <RemoveExistingProducts After="InstallInitialize">UPGRADE or REMOVE_OLD_LAUNCHER</RemoveExistingProducts>
+ <RemoveExistingProducts After="InstallValidate">UPGRADE or REMOVE_350_LAUNCHER</RemoveExistingProducts>
</InstallExecuteSequence>
- <!-- Python 3.5.0 shipped with an incorrect UpgradeCode -->
+ <!-- Python 3.5.0 shipped with a different UpgradeCode -->
<Upgrade Id="A71530B9-E89D-53DB-9C2D-C6D7551876D8">
- <UpgradeVersion Maximum="$(var.Version)" Property="REMOVE_OLD_LAUNCHER" />
+ <UpgradeVersion Minimum="0.0.0.0" Property="REMOVE_350_LAUNCHER" />
</Upgrade>
+ <!-- Python 3.6.0a1 shipped with a different UpgradeCode -->
+ <Upgrade Id="394750C0-7880-5A8F-999F-933965FBCFB4">
+ <UpgradeVersion Maximum="$(var.Version)" Property="REMOVE_360A1_LAUNCHER" />
+ <UpgradeVersion Minimum="$(var.Version)" Property="BLOCK_360A1_LAUNCHER" />
+ </Upgrade>
+ <Condition Message="!(loc.NoDowngrade)">Installed OR NOT BLOCK_360A1_LAUNCHER</Condition>
</Product>
</Wix>
<?xml version="1.0" encoding="utf-8"?>
<WixLocalization Culture="en-us" xmlns="http://schemas.microsoft.com/wix/2006/localization">
- <String Id="Descriptor">Launcher</String>
- <String Id="ShortDescriptor">launcher</String>
+ <String Id="LCID">1033</String>
+ <String Id="Culture">en-us</String>
+ <String Id="ProductName">Python Launcher</String>
+ <String Id="Title">Python Launcher</String>
+ <String Id="Description">Python Launcher</String>
+ <String Id="Manufacturer">Python Software Foundation</String>
+ <String Id="NoDowngrade">A newer version of the Python launcher is already installed.</String>
+ <String Id="NoTargetDir">The TARGETDIR variable must be provided when invoking this installer.</String>
<String Id="PythonFileDescription">Python File</String>
<String Id="PythonNoConFileDescription">Python File (no console)</String>
<String Id="PythonCompiledFileDescription">Compiled Python File</String>
'site-packages',
'tkinter',
'turtledemo',
+ 'venv',
}
EXCLUDE_FILE_FROM_LIBRARY = {
('/', 'PCBuild/$arch', 'python*.exe', is_not_debug),
('/', 'PCBuild/$arch', '*.pyd', is_not_debug),
('/', 'PCBuild/$arch', '*.dll', is_not_debug),
- ('python35.zip', 'Lib', '**/*', include_in_lib),
+ ('python{0.major}{0.minor}.zip'.format(sys.version_info), 'Lib', '**/*', include_in_lib),
]
if os.getenv('DOC_FILENAME'):
<ItemGroup>
<Compile Include="$(MSBuildThisFileDirectory)common.wxs" />
- <WxlTemplate Include="$(MSBuildThisFileDirectory)\*.wxl_template" />
+ <WxlTemplate Include="$(MSBuildThisFileDirectory)\*.wxl_template" Condition="$(IgnoreCommonWxlTemplates) != 'true'" />
<WixExtension Include="WixUtilExtension">
<HintPath>WixUtilExtension</HintPath>
<Name>WixUtilExtension</Name>
<Uri>lib2to3/pickles</Uri>
</_Uuid>
</ItemGroup>
- <Target Name="_GenerateGuids" AfterTargets="PrepareForBuild">
+ <Target Name="_GenerateGuids" AfterTargets="PrepareForBuild" Condition="$(TargetName) != 'launcher'">
<PropertyGroup>
<_Uuids>@(_Uuid->'("%(Identity)", "$(MajorVersionNumber).$(MinorVersionNumber)/%(Uri)")',',')</_Uuids>
<_GenerateCommand>import uuid; print('\n'.join('{}={}'.format(i, uuid.uuid5(uuid.UUID('c8d9733e-a70c-43ff-ab0c-e26456f11083'), '$(ReleaseUri.Replace(`{arch}`, `$(ArchName)`))' + j)) for i,j in [$(_Uuids.Replace(`"`,`'`))]))</_GenerateCommand>
</Target>
<Target Name="_TransformWxlTemplates" AfterTargets="PrepareForBuild" Inputs="@(WxlTemplate);$(PySourcePath)include\patchlevel.h" Outputs="$(IntermediateOutputPath)%(Filename).wxl">
- <PropertyGroup>
+ <PropertyGroup Condition="'@(WxlTemplate)' != ''">
<_Content>$([System.IO.File]::ReadAllText(%(WxlTemplate.FullPath)).Replace(`{{ShortVersion}}`, `$(MajorVersionNumber).$(MinorVersionNumber)$(PyTestExt)`).Replace(`{{LongVersion}}`, `$(PythonVersion)$(PyTestExt)`).Replace(`{{Bitness}}`, `$(Bitness)`))</_Content>
<_ExistingContent Condition="Exists('$(IntermediateOutputPath)%(WxlTemplate.Filename).wxl')">$([System.IO.File]::ReadAllText($(IntermediateOutputPath)%(WxlTemplate.Filename).wxl))</_ExistingContent>
</PropertyGroup>
Overwrite="true"
Condition="$(_Content) != $(_ExistingContent)" />
- <ItemGroup>
+ <ItemGroup Condition="'@(WxlTemplate)' != ''">
<EmbeddedResource Include="$(IntermediateOutputPath)%(WxlTemplate.Filename).wxl" />
<FileWrites Include="$(IntermediateOutputPath)%(WxlTemplate.Filename).wxl" />
</ItemGroup>
def _Dict(self, t):
self.write("{")
- def write_pair(pair):
- (k, v) = pair
+ def write_key_value_pair(k, v):
self.dispatch(k)
self.write(": ")
self.dispatch(v)
- interleave(lambda: self.write(", "), write_pair, zip(t.keys, t.values))
+
+ def write_item(item):
+ k, v = item
+ if k is None:
+ # for dictionary unpacking operator in dicts {**{'y': 2}}
+ # see PEP 448 for details
+ self.write("**")
+ self.dispatch(v)
+ else:
+ write_key_value_pair(k, v)
+ interleave(lambda: self.write(", "), write_item, zip(t.keys, t.values))
self.write("}")
def _Tuple(self, t):
"no sophisticated Python source file search will be done.", file=sys.stderr)
-decl_re = re.compile(rb'^[ \t\f]*#.*coding[:=][ \t]*([-\w.]+)')
+decl_re = re.compile(rb'^[ \t\f]*#.*?coding[:=][ \t]*([-\w.]+)')
blank_re = re.compile(rb'^[ \t\f]*(?:[#\r\n]|$)')
def get_declaration(line):
-# generated automatically by aclocal 1.14.1 -*- Autoconf -*-
+# generated automatically by aclocal 1.15 -*- Autoconf -*-
-# Copyright (C) 1996-2013 Free Software Foundation, Inc.
+# Copyright (C) 1996-2014 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
LLVM_PROF_MERGER
PGO_PROF_USE_FLAG
PGO_PROF_GEN_FLAG
+LTOFLAGS
ABIFLAGS
LN
MKDIR_P
build_vendor
build_cpu
build
+cross_compiling
HAS_HG
HGBRANCH
HGTAG
with_framework_name
enable_framework
with_gcc
+with_icc
with_cxx_main
with_suffix
enable_shared
enable_profiling
with_pydebug
+with_lto
with_hash_algorithm
with_address_sanitizer
with_libs
specify an alternate name of the framework built
with --enable-framework
--without-gcc never use gcc
+ --with-icc build with icc
--with-cxx-main=<compiler>
compile main() and link python executable with C++
compiler
--with-suffix=.exe set executable suffix
--with-pydebug build with Py_DEBUG defined
+ --with-lto Enable Link Time Optimization in PGO builds.
+ Disabled by default.
--with-hash-algorithm=[fnv|siphash24]
select hash algorithm
--with-address-sanitizer
ac_config_headers="$ac_config_headers pyconfig.h"
+
ac_aux_dir=
for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
if test -f "$ac_dir/install-sh"; then
#
# SGI compilers allow the specification of the both the ABI and the
# ISA on the command line. Depending on the values of these switches,
-# different and often incompatable code will be generated.
+# different and often incompatible code will be generated.
#
# The SGI_ABI variable can be used to modify the CC and LDFLAGS and
# thus supply support for various ABI/ISA combinations. The MACHDEP
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $without_gcc" >&5
$as_echo "$without_gcc" >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-icc" >&5
+$as_echo_n "checking for --with-icc... " >&6; }
+
+# Check whether --with-icc was given.
+if test "${with_icc+set}" = set; then :
+ withval=$with_icc;
+ case $withval in
+ no) CC=${CC:-cc}
+ with_icc=no;;
+ yes) CC=icc
+ CXX=icpc
+ with_icc=yes;;
+ *) CC=$withval
+ with_icc=$withval;;
+ esac
+else
+
+ with_icc=no
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_icc" >&5
+$as_echo "$with_icc" >&6; }
+
# If the user switches compilers, we can't believe the cache
if test ! -z "$ac_cv_prog_CC" -a ! -z "$CC" -a "$CC" != "$ac_cv_prog_CC"
then
CXX="$ac_cv_path_CXX"
fi
;;
+ icc|*/icc) if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}icpc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}icpc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_CXX+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $CXX in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_CXX="$CXX" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in notfound
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_CXX="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+CXX=$ac_cv_path_CXX
+if test -n "$CXX"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5
+$as_echo "$CXX" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_path_CXX"; then
+ ac_pt_CXX=$CXX
+ # Extract the first word of "icpc", so it can be a program name with args.
+set dummy icpc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_ac_pt_CXX+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $ac_pt_CXX in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_ac_pt_CXX="$ac_pt_CXX" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in notfound
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_ac_pt_CXX="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+ac_pt_CXX=$ac_cv_path_ac_pt_CXX
+if test -n "$ac_pt_CXX"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_CXX" >&5
+$as_echo "$ac_pt_CXX" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_pt_CXX" = x; then
+ CXX="icpc"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CXX=$ac_pt_CXX
+ fi
+else
+ CXX="$ac_cv_path_CXX"
+fi
+ ;;
esac
if test "$CXX" = "notfound"
then
fi
+# Enable LTO flags
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-lto" >&5
+$as_echo_n "checking for --with-lto... " >&6; }
+
+# Check whether --with-lto was given.
+if test "${with_lto+set}" = set; then :
+ withval=$with_lto;
+if test "$withval" != no
+then
+ Py_LTO='true'
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; };
+else
+ Py_LTO='false'
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; };
+fi
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+if test "$Py_LTO" = 'true' ; then
+ case $CC in
+ *clang*)
+ # Any changes made here should be reflected in the GCC+Darwin case below
+ LTOFLAGS="-flto"
+ ;;
+ *gcc*)
+ case $ac_sys_system in
+ Darwin*)
+ LTOFLAGS="-flto"
+ ;;
+ *)
+ LTOFLAGS="-flto -fuse-linker-plugin -ffat-lto-objects -flto-partition=none"
+ ;;
+ esac
+ ;;
+ esac
+fi
+
# Enable PGO flags.
+
+
+
+
+
+
# Extract the first word of "llvm-profdata", so it can be a program name with args.
set dummy llvm-profdata; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
;;
esac
;;
+ *icc*)
+ PGO_PROF_GEN_FLAG="-prof-gen"
+ PGO_PROF_USE_FLAG="-prof-use"
+ LLVM_PROF_MERGER="true"
+ LLVM_PROF_FILE=""
+ ;;
esac
# XXX Shouldn't the code above that fiddles with BASECFLAGS and OPT be
BASECFLAGS="$BASECFLAGS -fno-strict-aliasing"
fi
+ # ICC doesn't recognize the option, but only emits a warning
+ ## XXX does it emit an unused result warning and can it be disabled?
+ case "$CC" in
+ *icc*)
+ ac_cv_disable_unused_result_warning=no
+ ;;
+ *)
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can turn off $CC unused result warning" >&5
$as_echo_n "checking if we can turn off $CC unused result warning... " >&6; }
ac_save_cc="$CC"
CC="$ac_save_cc"
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_disable_unused_result_warning" >&5
$as_echo "$ac_cv_disable_unused_result_warning" >&6; }
+ ;;
+ esac
if test $ac_cv_disable_unused_result_warning = yes
then
CFLAGS="$save_CFLAGS"
CC="$ac_save_cc"
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_enable_unreachable_code_warning" >&5
-$as_echo "$ac_cv_enable_unreachable_code_warning" >&6; }
# Don't enable unreachable code warning in debug mode, since it usually
# results in non-standard code paths.
- if test $ac_cv_enable_unreachable_code_warning = yes && test "$Py_DEBUG" != "true"
+ # Issue #24324: Unfortunately, the unreachable code warning does not work
+ # correctly on gcc and has been silently removed from the compiler.
+ # It is supported on clang but on OS X systems gcc may be an alias
+ # for clang. Try to determine if the compiler is not really gcc and,
+ # if so, only then enable the warning.
+ if test $ac_cv_enable_unreachable_code_warning = yes && \
+ test "$Py_DEBUG" != "true" && \
+ test -z "`$CC --version 2>/dev/null | grep 'Free Software Foundation'`"
then
BASECFLAGS="$BASECFLAGS -Wunreachable-code"
+ else
+ ac_cv_enable_unreachable_code_warning=no
fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_enable_unreachable_code_warning" >&5
+$as_echo "$ac_cv_enable_unreachable_code_warning" >&6; }
# if using gcc on alpha, use -mieee to get (near) full IEEE 754
# support. Without this, treatment of subnormals doesn't follow
;;
esac
+# ICC needs -fp-model strict or floats behave badly
+case "$CC" in
+*icc*)
+ CFLAGS_NODIST="$CFLAGS_NODIST -fp-model strict"
+ ;;
+esac
+
if test "$Py_DEBUG" = 'true'; then
:
else
sys/stat.h sys/syscall.h sys/sys_domain.h sys/termio.h sys/time.h \
sys/times.h sys/types.h sys/uio.h sys/un.h sys/utsname.h sys/wait.h pty.h \
libutil.h sys/resource.h netpacket/packet.h sysexits.h bluetooth.h \
-bluetooth/bluetooth.h linux/tipc.h spawn.h util.h alloca.h endian.h \
+bluetooth/bluetooth.h linux/tipc.h linux/random.h spawn.h util.h alloca.h endian.h \
sys/endian.h
do :
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
_ACEOF
-$as_echo "#define HAVE_ST_BLOCKS 1" >>confdefs.h
-
-else
- case " $LIBOBJS " in
- *" fileblocks.$ac_objext "* ) ;;
- *) LIBOBJS="$LIBOBJS fileblocks.$ac_objext"
- ;;
-esac
-
fi
-
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for time.h that defines altzone" >&5
$as_echo_n "checking for time.h that defines altzone... " >&6; }
if ${ac_cv_header_time_altzone+:} false; then :
fi
+# also in 4.0, but not in editline
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for rl_resize_terminal in -lreadline" >&5
+$as_echo_n "checking for rl_resize_terminal in -lreadline... " >&6; }
+if ${ac_cv_lib_readline_rl_resize_terminal+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lreadline $READLINE_LIBS $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char rl_resize_terminal ();
+int
+main ()
+{
+return rl_resize_terminal ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_readline_rl_resize_terminal=yes
+else
+ ac_cv_lib_readline_rl_resize_terminal=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_readline_rl_resize_terminal" >&5
+$as_echo "$ac_cv_lib_readline_rl_resize_terminal" >&6; }
+if test "x$ac_cv_lib_readline_rl_resize_terminal" = xyes; then :
+
+$as_echo "#define HAVE_RL_RESIZE_TERMINAL 1" >>confdefs.h
+
+fi
+
+
# check for readline 4.2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for rl_completion_matches in -lreadline" >&5
$as_echo_n "checking for rl_completion_matches in -lreadline... " >&6; }
/* end confdefs.h. */
+ #include <unistd.h>
#include <sys/syscall.h>
+ #include <linux/random.h>
int main() {
char buffer[1];
const size_t buflen = sizeof(buffer);
- const int flags = 0;
- /* ignore the result, Python checks for ENOSYS at runtime */
+ const int flags = GRND_NONBLOCK;
+ /* ignore the result, Python checks for ENOSYS and EAGAIN at runtime */
(void)syscall(SYS_getrandom, buffer, buflen, flags);
return 0;
}
AC_CONFIG_SRCDIR([Include/object.h])
AC_CONFIG_HEADER(pyconfig.h)
+AC_SUBST(cross_compiling)
AC_CANONICAL_HOST
AC_SUBST(build)
AC_SUBST(host)
dnl Last slash shouldn't be stripped if prefix=/
if test "$prefix" != "/"; then
prefix=`echo "$prefix" | sed -e 's/\/$//g'`
-fi
+fi
dnl This is for stuff that absolutely must end up in pyconfig.h.
dnl Please use pyport.h instead, if possible.
fi
;;
esac
-
+
],[
UNIVERSALSDK=
enable_universalsdk=
AS_HELP_STRING([--enable-framework@<:@=INSTALLDIR@:>@], [Build (MacOSX|Darwin) framework]),
[
case $enableval in
- yes)
+ yes)
enableval=/Library/Frameworks
esac
case $enableval in
FRAMEWORKINSTALLAPPSPREFIX="${MDIR}/Applications"
if test "${prefix}" = "NONE"; then
- # User hasn't specified the
+ # User hasn't specified the
# --prefix option, but wants to install
# the framework in a non-default location,
# ensure that the compatibility links get
# Reconfirmed for OpenBSD 3.3 by Zachary Hamm, for 3.4 by Jason Ish.
# In addition, Stefan Krah confirms that issue #1244610 exists through
# OpenBSD 4.6, but is fixed in 4.7.
- OpenBSD/2.* | OpenBSD/3.* | OpenBSD/4.@<:@0123456@:>@)
+ OpenBSD/2.* | OpenBSD/3.* | OpenBSD/4.@<:@0123456@:>@)
define_xopen_source=no
# OpenBSD undoes our definition of __BSD_VISIBLE if _XOPEN_SOURCE is
# also defined. This can be overridden by defining _BSD_SOURCE
# with _XOPEN_SOURCE and __BSD_VISIBLE does not re-enable them.
FreeBSD/4.*)
define_xopen_source=no;;
- # On MacOS X 10.2, a bug in ncurses.h means that it craps out if
+ # On MacOS X 10.2, a bug in ncurses.h means that it craps out if
# _XOPEN_EXTENDED_SOURCE is defined. Apparently, this is fixed in 10.3, which
# identifies itself as Darwin/7.*
# On Mac OS X 10.4, defining _POSIX_C_SOURCE or _XOPEN_SOURCE
# disables platform specific features beyond repair.
- # On Mac OS X 10.3, defining _POSIX_C_SOURCE or _XOPEN_SOURCE
+ # On Mac OS X 10.3, defining _POSIX_C_SOURCE or _XOPEN_SOURCE
# has no effect, don't bother defining them
Darwin/@<:@6789@:>@.*)
define_xopen_source=no;;
#
# SGI compilers allow the specification of the both the ABI and the
# ISA on the command line. Depending on the values of these switches,
-# different and often incompatable code will be generated.
+# different and often incompatible code will be generated.
#
# The SGI_ABI variable can be used to modify the CC and LDFLAGS and
# thus supply support for various ABI/ISA combinations. The MACHDEP
esac])
AC_MSG_RESULT($without_gcc)
+AC_MSG_CHECKING(for --with-icc)
+AC_ARG_WITH(icc,
+ AS_HELP_STRING([--with-icc], [build with icc]),
+[
+ case $withval in
+ no) CC=${CC:-cc}
+ with_icc=no;;
+ yes) CC=icc
+ CXX=icpc
+ with_icc=yes;;
+ *) CC=$withval
+ with_icc=$withval;;
+ esac], [
+ with_icc=no])
+AC_MSG_RESULT($with_icc)
+
# If the user switches compilers, we can't believe the cache
if test ! -z "$ac_cv_prog_CC" -a ! -z "$CC" -a "$CC" != "$ac_cv_prog_CC"
then
AS_HELP_STRING([--with-cxx-main=<compiler>],
[compile main() and link python executable with C++ compiler]),
[
-
+
case $withval in
no) with_cxx_main=no
MAINCC='$(CC)';;
gcc) AC_PATH_TOOL(CXX, [g++], [g++], [notfound]) ;;
cc) AC_PATH_TOOL(CXX, [c++], [c++], [notfound]) ;;
clang|*/clang) AC_PATH_TOOL(CXX, [clang++], [clang++], [notfound]) ;;
+ icc|*/icc) AC_PATH_TOOL(CXX, [icpc], [icpc], [notfound]) ;;
esac
if test "$CXX" = "notfound"
then
if test x$PLATFORM_TRIPLET != x$MULTIARCH; then
AC_MSG_ERROR([internal configure error for the platform triplet, please file a bug report])
fi
-fi
+fi
PLATDIR=plat-$MACHDEP
AC_SUBST(PLATDIR)
AC_SUBST(PLATFORM_TRIPLET)
# systems without shared libraries, LDLIBRARY is the same as LIBRARY
# (defined in the Makefiles). On Cygwin LDLIBRARY is the import library,
# DLLLIBRARY is the shared (i.e., DLL) library.
-#
+#
# RUNSHARED is used to run shared python without installed libraries
#
# INSTSONAME is the name of the shared library that will be use to install
# If CXX is set, and if it is needed to link a main function that was
# compiled with CXX, LINKCC is CXX instead. Always using CXX is undesirable:
# python might then depend on the C++ runtime
-# This is altered for AIX in order to build the export list before
+# This is altered for AIX in order to build the export list before
# linking.
AC_SUBST(LINKCC)
AC_MSG_CHECKING(LINKCC)
AS_HELP_STRING([--enable-shared], [disable/enable building shared python library]))
if test -z "$enable_shared"
-then
+then
case $ac_sys_system in
CYGWIN*)
enable_shared="yes";;
BLDLIBRARY=''
else
BLDLIBRARY='$(LDLIBRARY)'
-fi
+fi
# Other platforms follow
if test $enable_shared = "yes"; then
# Check for --with-pydebug
AC_MSG_CHECKING(for --with-pydebug)
-AC_ARG_WITH(pydebug,
+AC_ARG_WITH(pydebug,
AS_HELP_STRING([--with-pydebug], [build with Py_DEBUG defined]),
[
if test "$withval" != no
-then
- AC_DEFINE(Py_DEBUG, 1,
- [Define if you want to build an interpreter with many run-time checks.])
- AC_MSG_RESULT(yes);
+then
+ AC_DEFINE(Py_DEBUG, 1,
+ [Define if you want to build an interpreter with many run-time checks.])
+ AC_MSG_RESULT(yes);
Py_DEBUG='true'
ABIFLAGS="${ABIFLAGS}d"
else AC_MSG_RESULT(no); Py_DEBUG='false'
fi],
[AC_MSG_RESULT(no)])
+# Enable LTO flags
+AC_SUBST(LTOFLAGS)
+AC_MSG_CHECKING(for --with-lto)
+AC_ARG_WITH(lto, AS_HELP_STRING([--with-lto], [Enable Link Time Optimization in PGO builds. Disabled by default.]),
+[
+if test "$withval" != no
+then
+ Py_LTO='true'
+ AC_MSG_RESULT(yes);
+else
+ Py_LTO='false'
+ AC_MSG_RESULT(no);
+fi],
+[AC_MSG_RESULT(no)])
+if test "$Py_LTO" = 'true' ; then
+ case $CC in
+ *clang*)
+ # Any changes made here should be reflected in the GCC+Darwin case below
+ LTOFLAGS="-flto"
+ ;;
+ *gcc*)
+ case $ac_sys_system in
+ Darwin*)
+ LTOFLAGS="-flto"
+ ;;
+ *)
+ LTOFLAGS="-flto -fuse-linker-plugin -ffat-lto-objects -flto-partition=none"
+ ;;
+ esac
+ ;;
+ esac
+fi
+
# Enable PGO flags.
AC_SUBST(PGO_PROF_GEN_FLAG)
AC_SUBST(PGO_PROF_USE_FLAG)
;;
esac
;;
+ *icc*)
+ PGO_PROF_GEN_FLAG="-prof-gen"
+ PGO_PROF_USE_FLAG="-prof-use"
+ LLVM_PROF_MERGER="true"
+ LLVM_PROF_FILE=""
+ ;;
esac
# XXX Shouldn't the code above that fiddles with BASECFLAGS and OPT be
BASECFLAGS="$BASECFLAGS -fno-strict-aliasing"
fi
+ # ICC doesn't recognize the option, but only emits a warning
+ ## XXX does it emit an unused result warning and can it be disabled?
+ case "$CC" in
+ *icc*)
+ ac_cv_disable_unused_result_warning=no
+ ;;
+ *)
AC_MSG_CHECKING(if we can turn off $CC unused result warning)
ac_save_cc="$CC"
CC="$CC -Wunused-result -Werror"
CFLAGS="$save_CFLAGS"
CC="$ac_save_cc"
AC_MSG_RESULT($ac_cv_disable_unused_result_warning)
+ ;;
+ esac
if test $ac_cv_disable_unused_result_warning = yes
then
]))
CFLAGS="$save_CFLAGS"
CC="$ac_save_cc"
- AC_MSG_RESULT($ac_cv_enable_unreachable_code_warning)
# Don't enable unreachable code warning in debug mode, since it usually
# results in non-standard code paths.
- if test $ac_cv_enable_unreachable_code_warning = yes && test "$Py_DEBUG" != "true"
+ # Issue #24324: Unfortunately, the unreachable code warning does not work
+ # correctly on gcc and has been silently removed from the compiler.
+ # It is supported on clang but on OS X systems gcc may be an alias
+ # for clang. Try to determine if the compiler is not really gcc and,
+ # if so, only then enable the warning.
+ if test $ac_cv_enable_unreachable_code_warning = yes && \
+ test "$Py_DEBUG" != "true" && \
+ test -z "`$CC --version 2>/dev/null | grep 'Free Software Foundation'`"
then
BASECFLAGS="$BASECFLAGS -Wunreachable-code"
+ else
+ ac_cv_enable_unreachable_code_warning=no
fi
+ AC_MSG_RESULT($ac_cv_enable_unreachable_code_warning)
# if using gcc on alpha, use -mieee to get (near) full IEEE 754
# support. Without this, treatment of subnormals doesn't follow
;;
esac
+# ICC needs -fp-model strict or floats behave badly
+case "$CC" in
+*icc*)
+ CFLAGS_NODIST="$CFLAGS_NODIST -fp-model strict"
+ ;;
+esac
+
if test "$Py_DEBUG" = 'true'; then
:
else
AC_MSG_RESULT($ac_cv_pthread_is_default)
-if test $ac_cv_pthread_is_default = yes
+if test $ac_cv_pthread_is_default = yes
then
ac_cv_kpthread=no
else
if test "$ac_cv_kpthread" = "yes"
then
- CXX="$CXX -Kpthread"
+ CXX="$CXX -Kpthread"
ac_cv_cxx_thread=yes
elif test "$ac_cv_kthread" = "yes"
then
CXX="$CXX -Kthread"
ac_cv_cxx_thread=yes
elif test "$ac_cv_pthread" = "yes"
-then
+then
CXX="$CXX -pthread"
ac_cv_cxx_thread=yes
fi
sys/stat.h sys/syscall.h sys/sys_domain.h sys/termio.h sys/time.h \
sys/times.h sys/types.h sys/uio.h sys/un.h sys/utsname.h sys/wait.h pty.h \
libutil.h sys/resource.h netpacket/packet.h sysexits.h bluetooth.h \
-bluetooth/bluetooth.h linux/tipc.h spawn.h util.h alloca.h endian.h \
+bluetooth/bluetooth.h linux/tipc.h linux/random.h spawn.h util.h alloca.h endian.h \
sys/endian.h)
AC_HEADER_DIRENT
AC_HEADER_MAJOR
# These may affect some typedefs
case $ac_sys_system/$ac_sys_release in
AIX*)
- AC_DEFINE(_LARGE_FILES, 1,
+ AC_DEFINE(_LARGE_FILES, 1,
[This must be defined on AIX systems to enable large file support.])
;;
esac
-AC_DEFINE(_LARGEFILE_SOURCE, 1,
+AC_DEFINE(_LARGEFILE_SOURCE, 1,
[This must be defined on some systems to enable large file support.])
AC_DEFINE(_FILE_OFFSET_BITS, 64,
[This must be set to 64 on some systems to enable large file support.])
AC_MSG_CHECKING(for long long support)
have_long_long=no
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[long long x; x = (long long)0;]])],[
- AC_DEFINE(HAVE_LONG_LONG, 1, [Define this if you have the type long long.])
+ AC_DEFINE(HAVE_LONG_LONG, 1, [Define this if you have the type long long.])
have_long_long=yes
],[])
AC_MSG_RESULT($have_long_long)
AC_MSG_CHECKING(for long double support)
have_long_double=no
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[long double x; x = (long double)0;]])],[
- AC_DEFINE(HAVE_LONG_DOUBLE, 1, [Define this if you have the type long double.])
+ AC_DEFINE(HAVE_LONG_DOUBLE, 1, [Define this if you have the type long double.])
have_long_double=yes
],[])
AC_MSG_RESULT($have_long_double)
AC_MSG_CHECKING(for _Bool support)
have_c99_bool=no
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[_Bool x; x = (_Bool)0;]])],[
- AC_DEFINE(HAVE_C99_BOOL, 1, [Define this if you have the type _Bool.])
+ AC_DEFINE(HAVE_C99_BOOL, 1, [Define this if you have the type _Bool.])
have_c99_bool=yes
],[])
AC_MSG_RESULT($have_c99_bool)
AC_CHECK_SIZEOF(_Bool, 1)
fi
-AC_CHECK_TYPES(uintptr_t,
- [AC_CHECK_SIZEOF(uintptr_t, 4)],
+AC_CHECK_TYPES(uintptr_t,
+ [AC_CHECK_SIZEOF(uintptr_t, 4)],
[], [#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif
then
if test "$ac_cv_sizeof_off_t" -gt "$ac_cv_sizeof_long" -a \
"$ac_cv_sizeof_long_long" -ge "$ac_cv_sizeof_off_t"; then
- AC_DEFINE(HAVE_LARGEFILE_SUPPORT, 1,
+ AC_DEFINE(HAVE_LARGEFILE_SUPPORT, 1,
[Defined to enable large file support when an off_t is bigger than a long
and long long is available and at least as big as an off_t. You may need
to add some flags for configuration and compilation to enable this mode.
AC_SUBST(OTHER_LIBTOOL_OPT)
case $ac_sys_system/$ac_sys_release in
- Darwin/@<:@01567@:>@\..*)
+ Darwin/@<:@01567@:>@\..*)
OTHER_LIBTOOL_OPT="-prebind -seg1addr 0x10000000"
;;
Darwin/*)
AC_SUBST(LIBTOOL_CRUFT)
case $ac_sys_system/$ac_sys_release in
- Darwin/@<:@01567@:>@\..*)
+ Darwin/@<:@01567@:>@\..*)
LIBTOOL_CRUFT="-framework System -lcc_dynamic"
if test "${enable_universalsdk}"; then
:
if test ${gcc_version} '<' 4.0
then
LIBTOOL_CRUFT="-lcc_dynamic"
- else
+ else
LIBTOOL_CRUFT=""
fi
AC_RUN_IFELSE([AC_LANG_SOURCE([[
}
}
]])],[ac_osx_32bit=yes],[ac_osx_32bit=no],[ac_osx_32bit=yes])
-
+
if test "${ac_osx_32bit}" = "yes"; then
case `/usr/bin/arch` in
- i386)
- MACOSX_DEFAULT_ARCH="i386"
+ i386)
+ MACOSX_DEFAULT_ARCH="i386"
;;
- ppc)
- MACOSX_DEFAULT_ARCH="ppc"
+ ppc)
+ MACOSX_DEFAULT_ARCH="ppc"
;;
*)
AC_MSG_ERROR([Unexpected output of 'arch' on OSX])
esac
else
case `/usr/bin/arch` in
- i386)
- MACOSX_DEFAULT_ARCH="x86_64"
+ i386)
+ MACOSX_DEFAULT_ARCH="x86_64"
;;
- ppc)
- MACOSX_DEFAULT_ARCH="ppc64"
+ ppc)
+ MACOSX_DEFAULT_ARCH="ppc64"
;;
*)
AC_MSG_ERROR([Unexpected output of 'arch' on OSX])
if test "$enable_framework"
then
BASECFLAGS="$BASECFLAGS -fno-common -dynamic"
- # -F. is needed to allow linking to the framework while
+ # -F. is needed to allow linking to the framework while
# in the build location.
- AC_DEFINE(WITH_NEXT_FRAMEWORK, 1,
+ AC_DEFINE(WITH_NEXT_FRAMEWORK, 1,
[Define if you want to produce an OpenStep/Rhapsody framework
(shared library plus accessory files).])
AC_MSG_RESULT(yes)
AC_MSG_CHECKING(for dyld)
case $ac_sys_system/$ac_sys_release in
Darwin/*)
- AC_DEFINE(WITH_DYLD, 1,
+ AC_DEFINE(WITH_DYLD, 1,
[Define if you want to use the new-style (Openstep, Rhapsody, MacOS)
dynamic linker (dyld) instead of the old-style (NextStep) dynamic
linker (rld). Dyld is necessary to support frameworks.])
;;
IRIX/5*) LDSHARED="ld -shared";;
IRIX*/6*) LDSHARED="ld ${SGI_ABI} -shared -all";;
- SunOS/5*)
+ SunOS/5*)
if test "$GCC" = "yes" ; then
LDSHARED='$(CC) -shared'
LDCXXSHARED='$(CXX) -shared'
BSD/OS/4*) LINKFORSHARED="-Xlinker -export-dynamic";;
Linux*|GNU*) LINKFORSHARED="-Xlinker -export-dynamic";;
# -u libsys_s pulls in all symbols in libsys
- Darwin/*)
+ Darwin/*)
LINKFORSHARED="$extra_undefs -framework CoreFoundation"
# Issue #18075: the default maximum stack size (8MBytes) is too
OpenUNIX*|UnixWare*) LINKFORSHARED="-Wl,-Bexport";;
SCO_SV*) LINKFORSHARED="-Wl,-Bexport";;
ReliantUNIX*) LINKFORSHARED="-W1 -Blargedynsym";;
- FreeBSD*|NetBSD*|OpenBSD*|DragonFly*)
+ FreeBSD*|NetBSD*|OpenBSD*|DragonFly*)
if [[ "`$CC -dM -E - </dev/null | grep __ELF__`" != "" ]]
then
LINKFORSHARED="-Wl,--export-dynamic"
# Defining _REENTRANT on system with POSIX threads should not hurt.
AC_DEFINE(_REENTRANT)
posix_threads=yes
- THREADOBJ="Python/thread.o"
+ THREADOBJ="Python/thread.o"
elif test "$ac_cv_kpthread" = "yes"
then
CC="$CC -Kpthread"
THREADOBJ="Python/thread.o"
USE_THREAD_MODULE=""])
- if test "$posix_threads" != "yes"; then
+ if test "$posix_threads" != "yes"; then
AC_CHECK_LIB(thread, thr_create, [AC_DEFINE(WITH_THREAD)
LIBS="$LIBS -lthread"
THREADOBJ="Python/thread.o"
if test "$posix_threads" = "yes"; then
if test "$unistd_defines_pthreads" = "no"; then
AC_DEFINE(_POSIX_THREADS, 1,
- [Define if you have POSIX threads,
+ [Define if you have POSIX threads,
and your system does not define that.])
fi
AC_ARG_WITH(tsc,
AS_HELP_STRING([--with(out)-tsc],[enable/disable timestamp counter profile]),[
if test "$withval" != no
-then
- AC_DEFINE(WITH_TSC, 1,
- [Define to profile with the Pentium timestamp counter])
+then
+ AC_DEFINE(WITH_TSC, 1,
+ [Define to profile with the Pentium timestamp counter])
AC_MSG_RESULT(yes)
else AC_MSG_RESULT(no)
fi],
fi
if test "$with_pymalloc" != "no"
then
- AC_DEFINE(WITH_PYMALLOC, 1,
+ AC_DEFINE(WITH_PYMALLOC, 1,
[Define if you want to compile in Python-specific mallocs])
ABIFLAGS="${ABIFLAGS}m"
fi
dnl to revert to a more traditional unix behaviour and make it possible to
dnl override the system libz with a local static library of libz. Temporarily
dnl add that flag to our CFLAGS as well to ensure that we check the version
-dnl of libz that will be used by setup.py.
-dnl The -L/usr/local/lib is needed as wel to get the same compilation
+dnl of libz that will be used by setup.py.
+dnl The -L/usr/local/lib is needed as wel to get the same compilation
dnl environment as setup.py (and leaving it out can cause configure to use the
dnl wrong version of the library)
case $ac_sys_system/$ac_sys_release in
-Darwin/*)
+Darwin/*)
_CUR_CFLAGS="${CFLAGS}"
_CUR_LDFLAGS="${LDFLAGS}"
CFLAGS="${CFLAGS} -Wl,-search_paths_first"
AC_CHECK_LIB(z, inflateCopy, AC_DEFINE(HAVE_ZLIB_COPY, 1, [Define if the zlib library has inflateCopy]))
case $ac_sys_system/$ac_sys_release in
-Darwin/*)
+Darwin/*)
CFLAGS="${_CUR_CFLAGS}"
LDFLAGS="${_CUR_LDFLAGS}"
;;
# check for openpty and forkpty
-AC_CHECK_FUNCS(openpty,,
+AC_CHECK_FUNCS(openpty,,
AC_CHECK_LIB(util,openpty,
[AC_DEFINE(HAVE_OPENPTY) LIBS="$LIBS -lutil"],
AC_CHECK_LIB(bsd,openpty, [AC_DEFINE(HAVE_OPENPTY) LIBS="$LIBS -lbsd"])
)
)
-AC_CHECK_FUNCS(forkpty,,
- AC_CHECK_LIB(util,forkpty,
+AC_CHECK_FUNCS(forkpty,,
+ AC_CHECK_LIB(util,forkpty,
[AC_DEFINE(HAVE_FORKPTY) LIBS="$LIBS -lutil"],
AC_CHECK_LIB(bsd,forkpty, [AC_DEFINE(HAVE_FORKPTY) LIBS="$LIBS -lbsd"])
)
AC_CHECK_FUNCS(fseek64 fseeko fstatvfs ftell64 ftello statvfs)
AC_REPLACE_FUNCS(dup2 strdup)
-AC_CHECK_FUNCS(getpgrp,
+AC_CHECK_FUNCS(getpgrp,
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <unistd.h>]], [[getpgrp(0);]])],
[AC_DEFINE(GETPGRP_HAVE_ARG, 1, [Define if getpgrp() must be called as getpgrp(0).])],
[])
[AC_DEFINE(SETPGRP_HAVE_ARG, 1, [Define if setpgrp() must be called as setpgrp(0, 0).])],
[])
)
-AC_CHECK_FUNCS(gettimeofday,
+AC_CHECK_FUNCS(gettimeofday,
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/time.h>]],
[[gettimeofday((struct timeval*)0,(struct timezone*)0);]])],
[],
])
# On OSF/1 V5.1, getaddrinfo is available, but a define
-# for [no]getaddrinfo in netdb.h.
+# for [no]getaddrinfo in netdb.h.
AC_MSG_CHECKING(for getaddrinfo)
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#include <sys/types.h>
AC_CHECK_MEMBERS([struct stat.st_flags])
AC_CHECK_MEMBERS([struct stat.st_gen])
AC_CHECK_MEMBERS([struct stat.st_birthtime])
-AC_STRUCT_ST_BLOCKS
+AC_CHECK_MEMBERS([struct stat.st_blocks])
AC_MSG_CHECKING(for time.h that defines altzone)
AC_CACHE_VAL(ac_cv_header_time_altzone,[
]], [[;]])],[
AC_DEFINE(SYS_SELECT_WITH_SYS_TIME, 1,
[Define if you can safely include both <sys/select.h> and <sys/time.h>
- (which you can't on SCO ODT 3.0).])
+ (which you can't on SCO ODT 3.0).])
was_it_defined=yes
],[])
AC_MSG_RESULT($was_it_defined)
have_prototypes=no
AC_MSG_CHECKING(for prototypes)
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[int foo(int x) { return 0; }]], [[return foo(10);]])],
- [AC_DEFINE(HAVE_PROTOTYPES, 1,
- [Define if your compiler supports function prototype])
+ [AC_DEFINE(HAVE_PROTOTYPES, 1,
+ [Define if your compiler supports function prototype])
have_prototypes=yes],
[]
)
]], [[return foo(10, "", 3.14);]])],[
AC_DEFINE(HAVE_STDARG_PROTOTYPES, 1,
[Define if your compiler supports variable length function prototypes
- (e.g. void fprintf(FILE *, char *, ...);) *and* <stdarg.h>])
+ (e.g. void fprintf(FILE *, char *, ...);) *and* <stdarg.h>])
works=yes
],[])
AC_MSG_RESULT($works)
#include <varargs.h>
#endif
]], [[va_list list1, list2; list1 = list2;]])],[],[
- AC_DEFINE(VA_LIST_IS_ARRAY, 1, [Define if a va_list is an array of some kind])
+ AC_DEFINE(VA_LIST_IS_ARRAY, 1, [Define if a va_list is an array of some kind])
va_list_is_array=yes
])
AC_MSG_RESULT($va_list_is_array)
AS_HELP_STRING([--with-fpectl], [enable SIGFPE catching]),
[
if test "$withval" != no
-then
+then
AC_DEFINE(WANT_SIGFPE_HANDLER, 1,
- [Define if you want SIGFPE handled (see Include/pyfpe.h).])
+ [Define if you want SIGFPE handled (see Include/pyfpe.h).])
AC_MSG_RESULT(yes)
else AC_MSG_RESULT(no)
fi],
# check for wchar.h
AC_CHECK_HEADER(wchar.h, [
- AC_DEFINE(HAVE_WCHAR_H, 1,
- [Define if the compiler provides a wchar.h header file.])
+ AC_DEFINE(HAVE_WCHAR_H, 1,
+ [Define if the compiler provides a wchar.h header file.])
wchar_h="yes"
],
wchar_h="no"
AC_DEFINE(HAVE_RL_COMPLETION_DISPLAY_MATCHES_HOOK, 1,
[Define if you have readline 4.0]), ,$READLINE_LIBS)
+# also in 4.0, but not in editline
+AC_CHECK_LIB(readline, rl_resize_terminal,
+ AC_DEFINE(HAVE_RL_RESIZE_TERMINAL, 1,
+ [Define if you have readline 4.0]), ,$READLINE_LIBS)
+
# check for readline 4.2
AC_CHECK_LIB(readline, rl_completion_matches,
AC_DEFINE(HAVE_RL_COMPLETION_MATCHES, 1,
[Define if poll() sets errno on invalid file descriptors.])
fi
-# Before we can test tzset, we need to check if struct tm has a tm_zone
+# Before we can test tzset, we need to check if struct tm has a tm_zone
# (which is not required by ISO C or UNIX spec) and/or if we support
# tzname[]
AC_STRUCT_TIMEZONE
tm->tm_zone does not exist since it is the alternative way
of getting timezone info.
- Red Hat 6.2 doesn't understand the southern hemisphere
+ Red Hat 6.2 doesn't understand the southern hemisphere
after New Year's Day.
*/
exit(1);
#if HAVE_TZNAME
/* For UTC, tzname[1] is sometimes "", sometimes " " */
- if (strcmp(tzname[0], "UTC") ||
+ if (strcmp(tzname[0], "UTC") ||
(tzname[1][0] != 0 && tzname[1][0] != ' '))
exit(1);
#endif
if test "$ac_cv_window_has_flags" = yes
then
- AC_DEFINE(WINDOW_HAS_FLAGS, 1,
+ AC_DEFINE(WINDOW_HAS_FLAGS, 1,
[Define if WINDOW in curses.h offers a field _flags.])
fi
if test "$ac_cv_broken_mbstowcs" = yes
then
AC_DEFINE(HAVE_BROKEN_MBSTOWCS, 1,
- [Define if mbstowcs(NULL, "text", 0) does not return the number of
+ [Define if mbstowcs(NULL, "text", 0) does not return the number of
wide chars that would be converted.])
fi
[Use computed gotos in evaluation loop (enabled by default on supported compilers)]),
[
if test "$withval" = yes
-then
+then
AC_DEFINE(USE_COMPUTED_GOTOS, 1,
- [Define if you want to use computed gotos in ceval.c.])
+ [Define if you want to use computed gotos in ceval.c.])
AC_MSG_RESULT(yes)
fi
if test "$withval" = no
-then
+then
AC_DEFINE(USE_COMPUTED_GOTOS, 0,
- [Define if you want to use computed gotos in ceval.c.])
+ [Define if you want to use computed gotos in ceval.c.])
AC_MSG_RESULT(no)
fi
],
esac
case $ac_sys_system in
-AIX*)
+AIX*)
AC_DEFINE(HAVE_BROKEN_PIPE_BUF, 1, [Define if the system reports an invalid PIPE_BUF value.]) ;;
esac
AC_LINK_IFELSE(
[
AC_LANG_SOURCE([[
+ #include <unistd.h>
#include <sys/syscall.h>
+ #include <linux/random.h>
int main() {
char buffer[1];
const size_t buflen = sizeof(buffer);
- const int flags = 0;
- /* ignore the result, Python checks for ENOSYS at runtime */
+ const int flags = GRND_NONBLOCK;
+ /* ignore the result, Python checks for ENOSYS and EAGAIN at runtime */
(void)syscall(SYS_getrandom, buffer, buflen, flags);
return 0;
}
/* Define to 1 if you have the <linux/tipc.h> header file. */
#undef HAVE_LINUX_TIPC_H
+/* Define to 1 if you have the <linux/random.h> header file. */
+#undef HAVE_LINUX_RANDOM_H
+
/* Define to 1 if you have the `lockf' function. */
#undef HAVE_LOCKF
/* Define if you have readline 4.0 */
#undef HAVE_RL_PRE_INPUT_HOOK
+/* Define if you have readline 4.0 */
+#undef HAVE_RL_RESIZE_TERMINAL
+
/* Define to 1 if you have the `round' function. */
#undef HAVE_ROUND
/* Define to 1 if `tm_zone' is a member of `struct tm'. */
#undef HAVE_STRUCT_TM_TM_ZONE
-/* Define to 1 if your `struct stat' has `st_blocks'. Deprecated, use
- `HAVE_STRUCT_STAT_ST_BLOCKS' instead. */
-#undef HAVE_ST_BLOCKS
-
/* Define if you have the 'symlink' function. */
#undef HAVE_SYMLINK
p = p.rstrip(os.sep)
if host_platform == 'darwin' and is_macosx_sdk_path(p):
+ # Note that, as of Xcode 7, Apple SDKs may contain textual stub
+ # libraries with .tbd extensions rather than the normal .dylib
+ # shared libraries installed in /. The Apple compiler tool
+ # chain handles this transparently but it can cause problems
+ # for programs that are being built with an SDK and searching
+ # for specific libraries. Distutils find_library_file() now
+ # knows to also search for and return .tbd files. But callers
+ # of find_library_file need to keep in mind that the base filename
+ # of the returned SDK library file might have a different extension
+ # from that of the library file installed on the running system,
+ # for example:
+ # /Applications/Xcode.app/Contents/Developer/Platforms/
+ # MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/
+ # usr/lib/libedit.tbd
+ # vs
+ # /usr/lib/libedit.dylib
if os.path.join(sysroot, p[1:]) == dirname:
return [ ]
finally:
os.unlink(tmpfile)
+ def detect_math_libs(self):
+ # Check for MacOS X, which doesn't need libm.a at all
+ if host_platform == 'darwin':
+ return []
+ else:
+ return ['m']
+
def detect_modules(self):
# Ensure that /usr/local is always used, but the local build
# directories (i.e. '.' and 'Include') must be first. See issue
if item.startswith('-L'):
lib_dirs.append(item[2:])
- # Check for MacOS X, which doesn't need libm.a at all
- math_libs = ['m']
- if host_platform == 'darwin':
- math_libs = []
+ math_libs = self.detect_math_libs()
# XXX Omitted modules: gl, pure, dl, SGI-specific modules
# array objects
exts.append( Extension('array', ['arraymodule.c']) )
+
+ shared_math = 'Modules/_math.o'
# complex math library functions
- exts.append( Extension('cmath', ['cmathmodule.c', '_math.c'],
- depends=['_math.h'],
+ exts.append( Extension('cmath', ['cmathmodule.c'],
+ extra_objects=[shared_math],
+ depends=['_math.h', shared_math],
libraries=math_libs) )
# math library functions, e.g. sin()
- exts.append( Extension('math', ['mathmodule.c', '_math.c'],
- depends=['_math.h'],
+ exts.append( Extension('math', ['mathmodule.c'],
+ extra_objects=[shared_math],
+ depends=['_math.h', shared_math],
libraries=math_libs) )
# time libraries: librt may be needed for clock_gettime()
# time operations and variables
exts.append( Extension('time', ['timemodule.c'],
libraries=time_libs) )
- exts.append( Extension('_datetime', ['_datetimemodule.c']) )
+ # math_libs is needed by delta_new() that uses round() and by accum()
+ # that uses modf().
+ exts.append( Extension('_datetime', ['_datetimemodule.c'],
+ libraries=math_libs) )
# random number generator implemented in C
exts.append( Extension("_random", ["_randommodule.c"]) )
# bisect
# Multimedia modules
# These don't work for 64-bit platforms!!!
# These represent audio samples or images as strings:
-
+ #
# Operations on audio samples
# According to #993173, this one should actually work fine on
# 64-bit platforms.
- exts.append( Extension('audioop', ['audioop.c']) )
+ #
+ # audioop needs math_libs for floor() in multiple functions.
+ exts.append( Extension('audioop', ['audioop.c'],
+ libraries=math_libs) )
# readline
do_readline = self.compiler.find_library_file(lib_dirs, 'readline')
# In every directory on the search path search for a dynamic
# library and then a static library, instead of first looking
# for dynamic libraries on the entire path.
- # This way a staticly linked custom readline gets picked up
+ # This way a statically linked custom readline gets picked up
# before the (possibly broken) dynamic library in /usr/lib.
readline_extra_link_args = ('-Wl,-search_paths_first',)
else:
# --with-tcltk-libs="-L/path/to/tcllibs -ltclm.n \
# -L/path/to/tklibs -ltkm.n"
#
- # These values can also be specified or overriden via make:
+ # These values can also be specified or overridden via make:
# make TCLTK_INCLUDES="..." TCLTK_LIBS="..."
#
# This can be useful for building and testing tkinter with multiple
'_ctypes/stgdict.c',
'_ctypes/cfield.c']
depends = ['_ctypes/ctypes.h']
+ math_libs = self.detect_math_libs()
if host_platform == 'darwin':
sources.append('_ctypes/malloc_closure.c')
libraries=[],
sources=sources,
depends=depends)
+ # function my_sqrt() needs math library for sqrt()
ext_test = Extension('_ctypes_test',
- sources=['_ctypes/_ctypes_test.c'])
+ sources=['_ctypes/_ctypes_test.c'],
+ libraries=math_libs)
self.extensions.extend([ext, ext_test])
if not '--with-system-ffi' in sysconfig.get_config_var("CONFIG_ARGS"):