From 4f8aaf644095fef61ba1104af0f07efe2a099079 Mon Sep 17 00:00:00 2001 From: Martin Panter Date: Sun, 12 Jun 2016 04:24:06 +0000 Subject: Issue #16484: Fix pydoc link and test on Windows, by Kaushik Nadikuditi --- Lib/pydoc.py | 5 +++-- Lib/test/test_pydoc.py | 2 +- Misc/NEWS | 4 ++++ 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/Lib/pydoc.py b/Lib/pydoc.py index 3ca08c9..0d0d0ab 100755 --- a/Lib/pydoc.py +++ b/Lib/pydoc.py @@ -28,7 +28,7 @@ to a file named ".html". Module docs for core modules are assumed to be in - http://docs.python.org/X.Y/library/ + https://docs.python.org/X.Y/library/ This can be overridden by setting the PYTHONDOCS environment variable to a different URL or to a local directory containing the Library @@ -395,6 +395,7 @@ class Doc: docloc = os.environ.get("PYTHONDOCS", self.PYTHONDOCS) + basedir = os.path.normcase(basedir) if (isinstance(object, type(os)) and (object.__name__ in ('errno', 'exceptions', 'gc', 'imp', 'marshal', 'posix', 'signal', 'sys', @@ -402,7 +403,7 @@ class Doc: (file.startswith(basedir) and not file.startswith(os.path.join(basedir, 'site-packages')))) and object.__name__ not in ('xml.etree', 'test.pydoc_mod')): - if docloc.startswith("http://"): + if docloc.startswith(("http://", "https://")): docloc = "%s/%s" % (docloc.rstrip("/"), object.__name__.lower()) else: docloc = os.path.join(docloc, object.__name__.lower() + ".html") diff --git a/Lib/test/test_pydoc.py b/Lib/test/test_pydoc.py index 59aa715..aee979b 100644 --- a/Lib/test/test_pydoc.py +++ b/Lib/test/test_pydoc.py @@ -356,7 +356,7 @@ def get_pydoc_html(module): def get_pydoc_link(module): "Returns a documentation web link of a module" dirname = os.path.dirname - basedir = os.path.join(dirname(dirname(__file__))) + basedir = dirname(dirname(__file__)) doc = pydoc.TextDoc() loc = doc.getdocloc(module, basedir=basedir) return loc diff --git a/Misc/NEWS b/Misc/NEWS index bde2dbc..8a39c08 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -591,6 +591,10 @@ IDLE Documentation ------------- +- Issue #16484: Change the default PYTHONDOCS URL to "https:", and fix the + resulting links to use lowercase. Patch by Sean Rodman, test by Kaushik + Nadikuditi. + - Issue #24136: Document the new PEP 448 unpacking syntax of 3.5. - Issue #26736: Used HTTPS for external links in the documentation if possible. -- cgit v0.12 From 6e77ebe6e902259babb28a978f92e0c2e956d4f1 Mon Sep 17 00:00:00 2001 From: Larry Hastings Date: Sat, 11 Jun 2016 22:22:07 -0700 Subject: Regenerate pydoc topics for 3.4.5rc1. --- Lib/pydoc_data/topics.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/pydoc_data/topics.py b/Lib/pydoc_data/topics.py index 8c55777..5230cca 100644 --- a/Lib/pydoc_data/topics.py +++ b/Lib/pydoc_data/topics.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Autogenerated by Sphinx on Sat Dec 19 19:27:32 2015 +# Autogenerated by Sphinx on Sat Jun 11 22:20:49 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 "=")+ (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', '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', @@ -61,7 +61,7 @@ topics = {'assert': u'\nThe "assert" statement\n**********************\n\nAssert '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 []\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: "xy" 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.__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.__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()", "pow()",\n "**", "<<", ">>", "&", "^", "|"). For instance, to evaluate the\n expression "x + y", where *x* is an instance of a class that has an\n "__add__()" method, "x.__add__(y)" is called. The "__divmod__()"\n method should be the equivalent to using "__floordiv__()" and\n "__mod__()"; it should not be related to "__truediv__()". Note\n that "__pow__()" should be defined to accept an optional third\n argument if the ternary version of the built-in "pow()" function is\n 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.__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()", "pow()",\n "**", "<<", ">>", "&", "^", "|") with reflected (swapped) operands.\n These functions are only called if the left operand does not\n 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.__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 do the\n operation in-place (modifying *self*) and return the result (which\n could be, but does not have to be, *self*). If a specific method\n is not defined, the augmented assignment falls back to the normal\n methods. For instance, if *x* is an instance of a class with an\n "__iadd__()" method, "x += y" is equivalent to "x = x.__iadd__(y)"\n . Otherwise, "x.__add__(y)" and "y.__radd__(x)" are considered, as\n with the evaluation of "x + y". In certain situations, augmented\n assignment can result in unexpected errors (see *Why does\n a_tuple[i] += [\'item\'] raise an exception when the addition\n works?*), but this behavior is in fact part of the data 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 "", line 1, in \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 "", line 1, in \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\n-[ Footnotes ]-\n\n[1] It *is* possible in some cases to change an object\'s type,\n under certain controlled conditions. It generally isn\'t a good\n idea though, since it can lead to some very strange behaviour if\n it is handled incorrectly.\n\n[2] For operands of the same type, it is assumed that if the non-\n reflected method (such as "__add__()") fails the operation is not\n supported, which is why the reflected method is not called.\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\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', + '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 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\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 ::= \n longstringchar ::= \n stringescapeseq ::= "\\" \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 ::= \n longbyteschar ::= \n bytesescapeseq ::= "\\" \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', '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', -- cgit v0.12 From 463c3f3eefbb706f4da1f17eb25a83968b636094 Mon Sep 17 00:00:00 2001 From: Larry Hastings Date: Sat, 11 Jun 2016 22:24:03 -0700 Subject: Release bump for 3.4.5rc1. --- Include/patchlevel.h | 8 ++++---- Misc/NEWS | 6 +++--- README | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Include/patchlevel.h b/Include/patchlevel.h index e1a147b..9026a4e 100644 --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -18,12 +18,12 @@ /*--start constants--*/ #define PY_MAJOR_VERSION 3 #define PY_MINOR_VERSION 4 -#define PY_MICRO_VERSION 4 -#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_FINAL -#define PY_RELEASE_SERIAL 0 +#define PY_MICRO_VERSION 5 +#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_GAMMA +#define PY_RELEASE_SERIAL 1 /* Version as a string */ -#define PY_VERSION "3.4.4+" +#define PY_VERSION "3.4.5rc1" /*--end constants--*/ /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2. diff --git a/Misc/NEWS b/Misc/NEWS index cb74a78..f8c8640 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -2,10 +2,10 @@ Python News +++++++++++ -What's New in Python 3.4.5? -=========================== +What's New in Python 3.4.5rc1? +============================== -Release date: tba +Release date: 2016-06-11 Core and Builtins ----------------- diff --git a/README b/README index 9190c5c..73cf419 100644 --- a/README +++ b/README @@ -1,5 +1,5 @@ -This is Python version 3.4.4 -============================ +This is Python version 3.4.5 release candidate 1 +================================================ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Python Software Foundation. All rights reserved. -- cgit v0.12 From 393c75932463cc06c9fd9fa41bfe7369c1139f5f Mon Sep 17 00:00:00 2001 From: Larry Hastings Date: Sat, 11 Jun 2016 22:25:43 -0700 Subject: Added tag v3.4.5rc1 for changeset 3631bb4a2490 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 4c71479..a84319c 100644 --- a/.hgtags +++ b/.hgtags @@ -146,3 +146,4 @@ ab2c023a9432f16652e89c404bbc84aa91bf55af v3.4.2 b4cbecbc0781e89a309d03b60a1f75f8499250e6 v3.4.3 04f3f725896c6961212c3a12e8ac25be6958f4fa v3.4.4rc1 737efcadf5a678b184e0fa431aae11276bf06648 v3.4.4 +3631bb4a2490292ebf81d3e947ae36da145da564 v3.4.5rc1 -- cgit v0.12 From d4704803b95efea847cd0a9065818d771c9941fb Mon Sep 17 00:00:00 2001 From: Martin Panter Date: Sun, 12 Jun 2016 06:07:35 +0000 Subject: =?UTF-8?q?Fix=20buggy=20RE=20=E2=80=9C\parrot=5Fexample.py?= =?UTF-8?q?=E2=80=9D,=20uncovered=20by=20Issue=20#27030?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Lib/lib2to3/tests/test_refactor.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Lib/lib2to3/tests/test_refactor.py b/Lib/lib2to3/tests/test_refactor.py index f30c1e8..8563001 100644 --- a/Lib/lib2to3/tests/test_refactor.py +++ b/Lib/lib2to3/tests/test_refactor.py @@ -9,6 +9,7 @@ import os import codecs import operator import io +import re import tempfile import shutil import unittest @@ -226,8 +227,8 @@ from __future__ import print_function""" actually_write=False) # Testing that it logged this message when write=False was passed is # sufficient to see that it did not bail early after "No changes". - message_regex = r"Not writing changes to .*%s%s" % ( - os.sep, os.path.basename(test_file)) + message_regex = r"Not writing changes to .*%s" % \ + re.escape(os.sep + os.path.basename(test_file)) for message in debug_messages: if "Not writing changes" in message: self.assertRegex(message, message_regex) -- cgit v0.12 From 70c502aacf629bd470a88dc5f139937d62376143 Mon Sep 17 00:00:00 2001 From: Martin Panter Date: Sun, 12 Jun 2016 06:14:03 +0000 Subject: Fix typos and English grammar in documentation and code comment --- Doc/whatsnew/2.0.rst | 2 +- Lib/test/test_coroutines.py | 2 +- Misc/NEWS | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Doc/whatsnew/2.0.rst b/Doc/whatsnew/2.0.rst index 87462f3..4d49af1 100644 --- a/Doc/whatsnew/2.0.rst +++ b/Doc/whatsnew/2.0.rst @@ -506,7 +506,7 @@ arguments and/or a dictionary of keyword arguments. In Python 1.5 and earlier, you'd use the :func:`apply` built-in function: ``apply(f, args, kw)`` calls the function :func:`f` with the argument tuple *args* and the keyword arguments in the dictionary *kw*. :func:`apply` is the same in 2.0, but thanks to a patch -from Greg Ewing, ``f(*args, **kw)`` as a shorter and clearer way to achieve the +from Greg Ewing, ``f(*args, **kw)`` is a shorter and clearer way to achieve the same effect. This syntax is symmetrical with the syntax for defining functions:: diff --git a/Lib/test/test_coroutines.py b/Lib/test/test_coroutines.py index 4f725ae..d0cefb0 100644 --- a/Lib/test/test_coroutines.py +++ b/Lib/test/test_coroutines.py @@ -1423,7 +1423,7 @@ class CoroutineTest(unittest.TestCase): with warnings.catch_warnings(): warnings.simplefilter("error") - # Test that __aiter__ that returns an asyncronous iterator + # Test that __aiter__ that returns an asynchronous iterator # directly does not throw any warnings. run_async(main()) self.assertEqual(I, 111011) diff --git a/Misc/NEWS b/Misc/NEWS index 8a39c08..ddcde75 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -2215,8 +2215,8 @@ Library writer failed in BufferedRWPair.close(). - Issue #23622: Unknown escapes in regular expressions that consist of ``'\'`` - and ASCII letter now raise a deprecation warning and will be forbidden in - Python 3.6. + and an ASCII letter now raise a deprecation warning and will be forbidden + in Python 3.6. - Issue #23671: string.Template now allows specifying the "self" parameter as a keyword argument. string.Formatter now allows specifying the "self" and -- cgit v0.12 From 3c317e76a2fe78896b546e08fa753075463e7d41 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sun, 12 Jun 2016 09:22:01 +0300 Subject: Issue #27286: Fixed compiling BUILD_MAP_UNPACK_WITH_CALL opcode. Calling function with generalized unpacking (PEP 448) and conflicting keyword names could cause undefined behavior. --- Lib/importlib/_bootstrap_external.py | 3 +- Lib/test/test_extcall.py | 4 + Lib/test/test_unpack_ex.py | 5 + Misc/NEWS | 4 + PC/launcher.c | 2 +- Python/compile.c | 2 +- Python/importlib_external.h | 208 +++++++++++++++++------------------ 7 files changed, 121 insertions(+), 107 deletions(-) diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py index 9788828..08ddb2b 100644 --- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -223,6 +223,7 @@ _code_type = type(_write_atomic.__code__) # Python 3.5b1 3330 (PEP 448: Additional Unpacking Generalizations) # Python 3.5b2 3340 (fix dictionary display evaluation order #11205) # Python 3.5b2 3350 (add GET_YIELD_FROM_ITER opcode #24400) +# Python 3.5.2 3351 (fix BUILD_MAP_UNPACK_WITH_CALL opcode #27286) # # MAGIC must change whenever the bytecode emitted by the compiler may no # longer be understood by older implementations of the eval loop (usually @@ -231,7 +232,7 @@ _code_type = type(_write_atomic.__code__) # 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' +MAGIC_NUMBER = (3351).to_bytes(2, 'little') + b'\r\n' _RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c _PYCACHE = '__pycache__' diff --git a/Lib/test/test_extcall.py b/Lib/test/test_extcall.py index d526b5f..5eea379 100644 --- a/Lib/test/test_extcall.py +++ b/Lib/test/test_extcall.py @@ -57,6 +57,10 @@ Here we add keyword arguments Traceback (most recent call last): ... TypeError: f() got multiple values for keyword argument 'a' + >>> f(1, 2, a=3, **{'a': 4}, **{'a': 5}) + Traceback (most recent call last): + ... + TypeError: f() got multiple values for keyword argument 'a' >>> f(1, 2, 3, *[4, 5], **{'a':6, 'b':7}) (1, 2, 3, 4, 5) {'a': 6, 'b': 7} >>> f(1, 2, 3, x=4, y=5, *(6, 7), **{'a':8, 'b': 9}) diff --git a/Lib/test/test_unpack_ex.py b/Lib/test/test_unpack_ex.py index d27eef0..74346b4 100644 --- a/Lib/test/test_unpack_ex.py +++ b/Lib/test/test_unpack_ex.py @@ -248,6 +248,11 @@ Overridden parameters ... TypeError: f() got multiple values for keyword argument 'x' + >>> f(x=5, **{'x': 3}, **{'x': 2}) + Traceback (most recent call last): + ... + TypeError: f() got multiple values for keyword argument 'x' + >>> f(**{1: 3}, **{1: 5}) Traceback (most recent call last): ... diff --git a/Misc/NEWS b/Misc/NEWS index 8a39c08..9d82626 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,10 @@ Release date: tba Core and Builtins ----------------- +- Issue #27286: Fixed compiling BUILD_MAP_UNPACK_WITH_CALL opcode. Calling + function with generalized unpacking (PEP 448) and conflicting keyword names + could cause undefined behavior. + - Issue #27066: Fixed SystemError if a custom opener (for open()) returns a negative number without setting an exception. diff --git a/PC/launcher.c b/PC/launcher.c index db5226e..40d4cb5 100644 --- a/PC/launcher.c +++ b/PC/launcher.c @@ -1081,7 +1081,7 @@ static PYC_MAGIC magic_values[] = { { 3160, 3180, L"3.2" }, { 3190, 3230, L"3.3" }, { 3250, 3310, L"3.4" }, - { 3320, 3350, L"3.5" }, + { 3320, 3351, L"3.5" }, { 3360, 3361, L"3.6" }, { 0 } }; diff --git a/Python/compile.c b/Python/compile.c index 1e720ea..0c4a6c8 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -3262,7 +3262,7 @@ compiler_call_helper(struct compiler *c, code |= 2; if (nsubkwargs > 1) { /* Pack it all up */ - int function_pos = n + (code & 1) + nkw + 1; + int function_pos = n + (code & 1) + 2 * nkw + 1; ADDOP_I(c, BUILD_MAP_UNPACK_WITH_CALL, nsubkwargs | (function_pos << 8)); } } diff --git a/Python/importlib_external.h b/Python/importlib_external.h index 47f5c62..a871f54 100644 --- a/Python/importlib_external.h +++ b/Python/importlib_external.h @@ -259,7 +259,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,0,114,5,0,0,0,218,13,95,119,114,105,116,101,95, 97,116,111,109,105,99,99,0,0,0,115,26,0,0,0,0, 5,24,1,9,1,33,1,3,3,21,1,20,1,20,1,13, - 1,3,1,17,1,13,1,5,1,114,55,0,0,0,105,22, + 1,3,1,17,1,13,1,5,1,114,55,0,0,0,105,23, 13,0,0,233,2,0,0,0,114,13,0,0,0,115,2,0, 0,0,13,10,90,11,95,95,112,121,99,97,99,104,101,95, 95,122,4,111,112,116,45,122,3,46,112,121,122,4,46,112, @@ -369,7 +369,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,246,0,0,0,115,46,0,0,0,0, + 115,111,117,114,99,101,247,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, @@ -448,7 +448,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,34,1,0,0,115,44,0,0,0, + 109,95,99,97,99,104,101,35,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, @@ -486,7 +486,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,67,1,0,0,115,20,0,0,0,0,7,18,1,4,1, + 101,68,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, @@ -500,7 +500,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,86,1,0,0,115, + 95,103,101,116,95,99,97,99,104,101,100,87,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, @@ -515,7 +515,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,98,1,0,0,115,12,0,0, + 97,108,99,95,109,111,100,101,99,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, @@ -536,7 +536,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,110,1,0,0,115, + 111,115,101,95,109,101,115,115,97,103,101,111,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, @@ -576,7 +576,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,126,1,0,0,115,12,0,0,0,0,1,12,1, + 112,101,114,127,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, @@ -595,7 +595,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,137,1, + 0,0,114,5,0,0,0,218,5,95,119,114,97,112,138,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, @@ -603,7 +603,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,118,1,0,0,115,14,0,0, + 101,99,107,95,110,97,109,101,119,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, @@ -633,7 +633,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,146,1,0,0,115,10,0,0,0,0,10,21,1,24,1, + 109,147,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, @@ -718,7 +718,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,163,1,0,0,115,76,0, + 100,101,95,104,101,97,100,101,114,164,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, @@ -749,7 +749,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,218,1,0,0,115,16,0,0,0, + 121,116,101,99,111,100,101,219,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, @@ -769,7 +769,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,230,1,0,0,115,10,0,0,0, + 121,116,101,99,111,100,101,231,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, @@ -798,7 +798,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,240,1,0,0,115,10,0,0,0,0,5,12,1, + 114,99,101,241,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, @@ -863,7 +863,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,1,2,0,0,115,60,0,0,0,0,12, + 97,116,105,111,110,2,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, @@ -903,7 +903,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,79,2,0,0,115,8,0,0,0, + 101,103,105,115,116,114,121,80,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, @@ -930,7 +930,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,86,2,0,0,115,22,0,0,0,0,2, + 105,115,116,114,121,87,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, @@ -954,7 +954,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,101,2,0,0,115, + 218,9,102,105,110,100,95,115,112,101,99,102,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, @@ -974,7 +974,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,117,2,0,0,115,8,0,0,0,0,7, + 111,100,117,108,101,118,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, @@ -983,7 +983,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,67,2,0,0,115,20,0,0, + 0,0,0,114,168,0,0,0,68,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, @@ -1021,7 +1021,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,136,2,0,0,115,8,0,0,0,0, + 0,114,159,0,0,0,137,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, @@ -1031,7 +1031,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,144,2,0, + 99,114,101,97,116,101,95,109,111,100,117,108,101,145,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, @@ -1053,7 +1053,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,147,2,0,0,115,10,0,0,0,0,2,18,1,12,1, + 101,148,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, @@ -1062,14 +1062,14 @@ const unsigned char _Py_M__importlib_external[] = { 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,155,2, + 0,218,11,108,111,97,100,95,109,111,100,117,108,101,156,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,131,2,0,0,115,10,0,0, + 0,0,0,114,184,0,0,0,132,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, @@ -1097,7 +1097,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,161,2,0,0,115,2,0,0,0,0,6,122,23,83,111, + 101,162,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, @@ -1132,7 +1132,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,169,2,0,0,115,2,0,0,0,0, + 95,115,116,97,116,115,170,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, @@ -1156,7 +1156,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,182,2,0,0,115,2,0,0,0,0,8, + 101,99,111,100,101,183,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, @@ -1173,7 +1173,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,192,2,0,0,115,0,0,0,0,122,21,83,111,117,114, + 0,193,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, @@ -1195,7 +1195,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,199,2,0,0,115,14,0,0,0,0,2,15,1,3,1, + 101,200,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, @@ -1217,7 +1217,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,209,2,0,0,115,4,0,0,0,0, + 111,95,99,111,100,101,210,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, @@ -1278,7 +1278,7 @@ const unsigned char _Py_M__importlib_external[] = { 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, - 217,2,0,0,115,78,0,0,0,0,7,15,1,6,1,3, + 218,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, @@ -1290,7 +1290,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,159,2,0,0,115,14,0,0,0,12,2,12,8,12,13, + 0,160,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, @@ -1318,7 +1318,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,18, + 114,4,0,0,0,114,5,0,0,0,114,185,0,0,0,19, 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, @@ -1328,7 +1328,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,24,3,0,0,115,4,0,0,0, + 6,95,95,101,113,95,95,25,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, @@ -1337,7 +1337,7 @@ const unsigned char _Py_M__importlib_external[] = { 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, - 28,3,0,0,115,2,0,0,0,0,1,122,19,70,105,108, + 29,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, @@ -1351,7 +1351,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,31,3,0, + 0,0,0,114,5,0,0,0,114,193,0,0,0,32,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, @@ -1362,7 +1362,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,43,3,0,0,115,2,0,0,0,0, + 0,114,157,0,0,0,44,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, @@ -1375,14 +1375,14 @@ const unsigned char _Py_M__importlib_external[] = { 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,48,3,0,0,115,4,0,0,0,0,2,21, + 200,0,0,0,49,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,13,3,0,0,115,14, + 114,5,0,0,0,114,210,0,0,0,14,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, @@ -1405,7 +1405,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,58,3, + 4,0,0,0,114,5,0,0,0,114,197,0,0,0,59,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, @@ -1416,7 +1416,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,63,3,0,0,115,4,0, + 5,0,0,0,114,199,0,0,0,64,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, @@ -1454,7 +1454,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,68,3,0,0,115,38,0, + 5,0,0,0,114,198,0,0,0,69,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, @@ -1463,7 +1463,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,54,3,0,0,115,8,0,0,0,12,2,6,2,12, + 0,0,55,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, @@ -1485,7 +1485,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,101,3,0,0,115,8,0,0,0,0,1,15, + 187,0,0,0,102,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, @@ -1495,13 +1495,13 @@ const unsigned char _Py_M__importlib_external[] = { 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,107,3,0,0,115,2,0,0,0,0,2,122,31, + 0,0,0,108,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,97,3,0,0,115,6,0, + 5,0,0,0,114,223,0,0,0,98,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, @@ -1526,7 +1526,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,124,3,0,0,115,4,0, + 5,0,0,0,114,185,0,0,0,125,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, @@ -1535,7 +1535,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,128, + 114,4,0,0,0,114,5,0,0,0,114,213,0,0,0,129, 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, @@ -1544,7 +1544,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,132,3,0,0,115, + 0,114,5,0,0,0,114,215,0,0,0,133,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, @@ -1562,7 +1562,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,135,3,0,0,115,10,0,0,0,0,2,6, + 186,0,0,0,136,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, @@ -1579,7 +1579,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,143,3,0,0, + 0,0,114,5,0,0,0,114,191,0,0,0,144,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, @@ -1598,7 +1598,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,152,3,0,0,115,2,0,0,0, + 101,110,101,120,112,114,62,153,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, @@ -1606,7 +1606,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,149,3,0,0, + 0,0,114,5,0,0,0,114,159,0,0,0,150,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, @@ -1618,7 +1618,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,155,3,0,0,115,2,0,0,0,0,2,122,28,69, + 0,0,156,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, @@ -1628,7 +1628,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,159,3,0,0,115,2,0,0, + 0,0,0,114,202,0,0,0,160,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, @@ -1639,7 +1639,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,163,3,0,0,115,2,0, + 5,0,0,0,114,157,0,0,0,164,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, @@ -1648,7 +1648,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,116,3,0,0,115,20,0,0, + 0,0,0,114,224,0,0,0,117,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, @@ -1692,7 +1692,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,176,3, + 4,0,0,0,114,5,0,0,0,114,185,0,0,0,177,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, @@ -1711,7 +1711,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,182,3,0, + 110,116,95,112,97,116,104,95,110,97,109,101,115,183,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, @@ -1725,7 +1725,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,192,3,0,0,115,4,0,0,0,0,1,18,1,122, + 0,0,193,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, @@ -1743,7 +1743,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,196,3,0,0,115,16,0,0,0,0,2,18,1, + 97,116,101,197,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, @@ -1752,14 +1752,14 @@ const unsigned char _Py_M__importlib_external[] = { 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,209,3,0,0,115,2,0,0,0,0,1,122,23, + 114,95,95,210,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,212, + 0,114,5,0,0,0,218,7,95,95,108,101,110,95,95,213, 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, @@ -1769,7 +1769,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,215,3,0,0,115,2,0,0,0,0,1,122,23,95,78, + 95,216,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, @@ -1777,7 +1777,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,218,3,0,0,115,2,0,0,0,0,1,122,27, + 115,95,95,219,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, @@ -1785,7 +1785,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,221,3,0,0,115,2,0,0, + 0,0,0,114,163,0,0,0,222,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, @@ -1793,7 +1793,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,169,3,0,0,115,20,0,0,0, + 0,0,114,230,0,0,0,170,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, @@ -1812,7 +1812,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,227,3,0,0,115,2,0, + 5,0,0,0,114,185,0,0,0,228,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, @@ -1829,14 +1829,14 @@ const unsigned char _Py_M__importlib_external[] = { 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,230, + 0,0,218,11,109,111,100,117,108,101,95,114,101,112,114,231, 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,239, + 114,4,0,0,0,114,5,0,0,0,114,159,0,0,0,240, 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, @@ -1844,7 +1844,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,242,3,0,0,115,2,0,0,0,0,1,122,27,95, + 0,0,243,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, @@ -1853,7 +1853,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,245,3, + 4,0,0,0,114,5,0,0,0,114,187,0,0,0,246,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, @@ -1863,14 +1863,14 @@ const unsigned char _Py_M__importlib_external[] = { 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,248,3,0,0,115,0,0,0,0,122, + 0,114,186,0,0,0,249,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,251,3,0,0,115,2,0,0,0,0,1, + 114,191,0,0,0,252,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, @@ -1888,7 +1888,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,254,3,0,0, + 0,0,114,5,0,0,0,114,193,0,0,0,255,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, @@ -1896,7 +1896,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,226, + 114,4,0,0,0,114,5,0,0,0,114,247,0,0,0,227, 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, @@ -1934,7 +1934,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,15,4,0,0, + 0,0,114,5,0,0,0,114,250,0,0,0,16,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, @@ -1960,7 +1960,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,23,4,0,0,115,16,0,0,0,0,7,25,1,16, + 107,115,24,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, @@ -1992,7 +1992,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,40,4,0, + 109,112,111,114,116,101,114,95,99,97,99,104,101,41,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, @@ -2012,7 +2012,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,62,4,0,0, + 97,99,121,95,103,101,116,95,115,112,101,99,63,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, @@ -2048,7 +2048,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,77,4,0,0,115, + 218,9,95,103,101,116,95,115,112,101,99,78,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, @@ -2076,7 +2076,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,109,4,0,0,115,26,0,0,0,0,4,12,1, + 0,0,0,110,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, @@ -2098,7 +2098,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,131,4,0,0,115,8,0,0,0,0,8,18, + 182,0,0,0,132,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, @@ -2106,7 +2106,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,11,4,0,0,115,22,0,0,0,12,2,6, + 249,0,0,0,12,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, @@ -2155,7 +2155,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,160,4,0,0,115,2,0,0,0,6,0,122, + 227,0,0,0,161,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, @@ -2168,7 +2168,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,154,4,0,0,115,16,0,0,0,0,4,6,1,19,1, + 0,155,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, @@ -2178,7 +2178,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,168,4,0,0,115,2,0,0,0,0, + 0,114,250,0,0,0,169,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, @@ -2202,7 +2202,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,174,4,0,0,115,8,0,0,0,0,7,15, + 124,0,0,0,175,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, @@ -2213,7 +2213,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,186,4,0, + 0,0,0,114,5,0,0,0,114,5,1,0,0,187,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, @@ -2276,7 +2276,7 @@ const unsigned char _Py_M__importlib_external[] = { 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, + 0,0,192,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, @@ -2312,7 +2312,7 @@ const unsigned char _Py_M__importlib_external[] = { 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, + 9,60,115,101,116,99,111,109,112,62,10,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, @@ -2329,7 +2329,7 @@ const unsigned char _Py_M__importlib_external[] = { 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, + 0,114,5,0,0,0,114,13,1,0,0,237,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, @@ -2368,7 +2368,7 @@ const unsigned char _Py_M__importlib_external[] = { 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, + 70,105,108,101,70,105,110,100,101,114,22,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, @@ -2376,7 +2376,7 @@ const unsigned char _Py_M__importlib_external[] = { 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, + 97,116,104,95,104,111,111,107,12,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, @@ -2385,7 +2385,7 @@ const unsigned char _Py_M__importlib_external[] = { 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, + 0,30,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, @@ -2393,7 +2393,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,145,4,0,0,115,20,0,0,0, + 0,0,114,6,1,0,0,146,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, @@ -2419,7 +2419,7 @@ const unsigned char _Py_M__importlib_external[] = { 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, + 117,112,95,109,111,100,117,108,101,36,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, @@ -2440,7 +2440,7 @@ const unsigned char _Py_M__importlib_external[] = { 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, + 114,161,0,0,0,59,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, @@ -2502,7 +2502,7 @@ const unsigned char _Py_M__importlib_external[] = { 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, + 95,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, @@ -2532,7 +2532,7 @@ const unsigned char _Py_M__importlib_external[] = { 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, + 95,115,101,116,117,112,70,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, @@ -2558,7 +2558,7 @@ const unsigned char _Py_M__importlib_external[] = { 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, + 95,105,110,115,116,97,108,108,138,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, @@ -2587,7 +2587,7 @@ const unsigned char _Py_M__importlib_external[] = { 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, + 12,9,12,5,12,7,15,22,15,114,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, -- cgit v0.12 From 9062c261a4f9268f4621548ec205c80411f75b6e Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sun, 12 Jun 2016 09:43:55 +0300 Subject: Issue #25455: Fixed a crash in repr of ElementTree.Element with recursive tag. --- Lib/test/test_xml_etree.py | 8 +++++++- Misc/NEWS | 2 ++ Modules/_elementtree.c | 19 ++++++++++++++++--- 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py index 44e3142..bc1dd14 100644 --- a/Lib/test/test_xml_etree.py +++ b/Lib/test/test_xml_etree.py @@ -18,7 +18,7 @@ import weakref from itertools import product from test import support -from test.support import TESTFN, findfile, import_fresh_module, gc_collect +from test.support import TESTFN, findfile, import_fresh_module, gc_collect, swap_attr # pyET is the pure-Python implementation. # @@ -1860,6 +1860,12 @@ class BadElementTest(ElementTestCase, unittest.TestCase): e.extend([ET.Element('bar')]) self.assertRaises(ValueError, e.remove, X('baz')) + def test_recursive_repr(self): + # Issue #25455 + e = ET.Element('foo') + with swap_attr(e, 'tag', e): + with self.assertRaises(RuntimeError): + repr(e) # Should not crash class MutatingElementPath(str): def __new__(cls, elem, *args): diff --git a/Misc/NEWS b/Misc/NEWS index 9d82626..19cb832 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -143,6 +143,8 @@ Core and Builtins Library ------- +- Issue #25455: Fixed a crash in repr of ElementTree.Element with recursive tag. + - Issue #26556: Update expat to 2.1.1, fixes CVE-2015-1283. - Fix TLS stripping vulnerability in smptlib, CVE-2016-0772. Reported by Team diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index 0f1d6a1..85ffca2 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -1582,10 +1582,23 @@ _elementtree_Element_remove_impl(ElementObject *self, PyObject *subelement) static PyObject* element_repr(ElementObject* self) { - if (self->tag) - return PyUnicode_FromFormat("", self->tag, self); - else + int status; + + if (self->tag == NULL) return PyUnicode_FromFormat("", self); + + status = Py_ReprEnter((PyObject *)self); + if (status == 0) { + PyObject *res; + res = PyUnicode_FromFormat("", self->tag, self); + Py_ReprLeave((PyObject *)self); + return res; + } + if (status > 0) + PyErr_Format(PyExc_RuntimeError, + "reentrant call inside %s.__repr__", + Py_TYPE(self)->tp_name); + return NULL; } /*[clinic input] -- cgit v0.12 From 179f960d47dc9f2c18e5b535db63fb70b21fc3ea Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sun, 12 Jun 2016 11:44:06 +0300 Subject: Issue #25455: Fixed a crash in repr of recursive functools.partial objects. --- Lib/test/test_functools.py | 37 +++++++++++++++++++++++++++++++++++++ Misc/NEWS | 3 ++- Modules/_functoolsmodule.c | 39 ++++++++++++++++++++++----------------- 3 files changed, 61 insertions(+), 18 deletions(-) diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py index 9abe984..3cb2827 100644 --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -217,6 +217,24 @@ class TestPartialC(TestPartial, unittest.TestCase): ['{}({!r}, {}, {})'.format(name, capture, args_repr, kwargs_repr) for kwargs_repr in kwargs_reprs]) + def test_recursive_repr(self): + if self.partial is c_functools.partial: + name = 'functools.partial' + else: + name = self.partial.__name__ + + f = self.partial(capture) + f.__setstate__((f, (), {}, {})) + self.assertEqual(repr(f), '%s(%s(...))' % (name, name)) + + f = self.partial(capture) + f.__setstate__((capture, (f,), {}, {})) + self.assertEqual(repr(f), '%s(%r, %s(...))' % (name, capture, name)) + + f = self.partial(capture) + f.__setstate__((capture, (), {'a': f}, {})) + self.assertEqual(repr(f), '%s(%r, a=%s(...))' % (name, capture, name)) + def test_pickle(self): f = self.partial(signature, ['asdf'], bar=[True]) f.attr = [] @@ -297,6 +315,25 @@ class TestPartialC(TestPartial, unittest.TestCase): self.assertEqual(r, ((1, 2), {})) self.assertIs(type(r[0]), tuple) + def test_recursive_pickle(self): + f = self.partial(capture) + f.__setstate__((f, (), {}, {})) + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + with self.assertRaises(RecursionError): + pickle.dumps(f, proto) + + f = self.partial(capture) + f.__setstate__((capture, (f,), {}, {})) + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + f_copy = pickle.loads(pickle.dumps(f, proto)) + self.assertIs(f_copy.args[0], f_copy) + + f = self.partial(capture) + f.__setstate__((capture, (), {'a': f}, {})) + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + f_copy = pickle.loads(pickle.dumps(f, proto)) + self.assertIs(f_copy.keywords['a'], f_copy) + # Issue 6083: Reference counting bug def test_setstate_refcount(self): class BadSequence: diff --git a/Misc/NEWS b/Misc/NEWS index a504ce1..3189824 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -143,7 +143,8 @@ Core and Builtins Library ------- -- Issue #25455: Fixed a crash in repr of ElementTree.Element with recursive tag. +- Issue #25455: Fixed crashes in repr of recursive ElementTree.Element and + functools.partial objects. - Issue #26556: Update expat to 2.1.1, fixes CVE-2015-1283. diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c index 1aa4571..d785c49 100644 --- a/Modules/_functoolsmodule.c +++ b/Modules/_functoolsmodule.c @@ -203,40 +203,45 @@ static PyGetSetDef partial_getsetlist[] = { static PyObject * partial_repr(partialobject *pto) { - PyObject *result; + PyObject *result = NULL; PyObject *arglist; - PyObject *tmp; Py_ssize_t i, n; PyObject *key, *value; + int status; - arglist = PyUnicode_FromString(""); - if (arglist == NULL) { - return NULL; + status = Py_ReprEnter((PyObject *)pto); + if (status != 0) { + if (status < 0) + return NULL; + return PyUnicode_FromFormat("%s(...)", Py_TYPE(pto)->tp_name); } + + arglist = PyUnicode_FromString(""); + if (arglist == NULL) + goto done; /* Pack positional arguments */ assert (PyTuple_Check(pto->args)); n = PyTuple_GET_SIZE(pto->args); for (i = 0; i < n; i++) { - tmp = PyUnicode_FromFormat("%U, %R", arglist, - PyTuple_GET_ITEM(pto->args, i)); - Py_DECREF(arglist); - if (tmp == NULL) - return NULL; - arglist = tmp; + Py_SETREF(arglist, PyUnicode_FromFormat("%U, %R", arglist, + PyTuple_GET_ITEM(pto->args, i))); + if (arglist == NULL) + goto done; } /* Pack keyword arguments */ 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; + Py_SETREF(arglist, PyUnicode_FromFormat("%U, %U=%R", arglist, + key, value)); + if (arglist == NULL) + goto done; } result = PyUnicode_FromFormat("%s(%R%U)", Py_TYPE(pto)->tp_name, pto->fn, arglist); Py_DECREF(arglist); + + done: + Py_ReprLeave((PyObject *)pto); return result; } -- cgit v0.12 From 0b19e1e72cd4c76946cece13cf194ac50ccf8487 Mon Sep 17 00:00:00 2001 From: Berker Peksag Date: Sun, 12 Jun 2016 12:19:13 +0300 Subject: Issue #27221: Delete an outdated paragraph about pickle support of Process Initial patch by Jelle Zijlstra. --- Doc/library/multiprocessing.rst | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/Doc/library/multiprocessing.rst b/Doc/library/multiprocessing.rst index c5c092c..216a092 100644 --- a/Doc/library/multiprocessing.rst +++ b/Doc/library/multiprocessing.rst @@ -2723,12 +2723,7 @@ start method. More picklability - Ensure that all arguments to :meth:`Process.__init__` are - picklable. This means, in particular, that bound or unbound - methods cannot be used directly as the ``target`` (unless you use - the *fork* start method) --- just define a function and use that - instead. - + Ensure that all arguments to :meth:`Process.__init__` are picklable. Also, if you subclass :class:`~multiprocessing.Process` then make sure that instances will be picklable when the :meth:`Process.start ` method is called. -- cgit v0.12 From 00eaa8a53b72d511ba50dbeec739d46b0ce187fd Mon Sep 17 00:00:00 2001 From: Berker Peksag Date: Sun, 12 Jun 2016 12:25:43 +0300 Subject: Use exc role for ValueError in multiprocessing.rst --- Doc/library/multiprocessing.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/multiprocessing.rst b/Doc/library/multiprocessing.rst index 216a092..d20098f 100644 --- a/Doc/library/multiprocessing.rst +++ b/Doc/library/multiprocessing.rst @@ -1010,7 +1010,7 @@ Connection objects are usually created using :func:`Pipe` -- see also using :meth:`recv`. The object must be picklable. Very large pickles (approximately 32 MB+, - though it depends on the OS) may raise a ValueError exception. + though it depends on the OS) may raise a :exc:`ValueError` exception. .. method:: recv() -- cgit v0.12 From c415440faa67c488fd2a5d8fc0977cbd660c4a90 Mon Sep 17 00:00:00 2001 From: Berker Peksag Date: Sun, 12 Jun 2016 13:41:47 +0300 Subject: Issue #27188: Fix various sqlite3 documentation errors * Connection.execute* methods don't create intermediate cursor objects * Fix description of seq_of_parameters parameter * Clarify that Warning is sqlite3.Warning * sql_script parameter of Cursor.executescript() doesn't accept bytes * Add missing tests * Fix various markup errors Initial patch by Dave Sawyer. --- Doc/library/sqlite3.rst | 37 +++++++++++++++++++------------------ Lib/sqlite3/test/dbapi.py | 12 ++++++++++++ 2 files changed, 31 insertions(+), 18 deletions(-) diff --git a/Doc/library/sqlite3.rst b/Doc/library/sqlite3.rst index 3bba935..ae4c7c4 100644 --- a/Doc/library/sqlite3.rst +++ b/Doc/library/sqlite3.rst @@ -309,25 +309,26 @@ Connection Objects call :meth:`commit`. If you just close your database connection without calling :meth:`commit` first, your changes will be lost! - .. method:: execute(sql, [parameters]) + .. method:: execute(sql[, parameters]) - This is a nonstandard shortcut that creates an intermediate cursor object by - calling the cursor method, then calls the cursor's :meth:`execute - ` method with the parameters given. + This is a nonstandard shortcut that creates a cursor object by calling + the :meth:`~Connection.cursor` method, calls the cursor's + :meth:`~Cursor.execute` method with the *parameters* given, and returns + the cursor. + .. method:: executemany(sql[, parameters]) - .. method:: executemany(sql, [parameters]) - - This is a nonstandard shortcut that creates an intermediate cursor object by - calling the cursor method, then calls the cursor's :meth:`executemany - ` method with the parameters given. + This is a nonstandard shortcut that creates a cursor object by + calling the :meth:`~Connection.cursor` method, calls the cursor's + :meth:`~Cursor.executemany` method with the *parameters* given, and + returns the cursor. .. method:: executescript(sql_script) - This is a nonstandard shortcut that creates an intermediate cursor object by - calling the cursor method, then calls the cursor's :meth:`executescript - ` method with the parameters given. - + This is a nonstandard shortcut that creates a cursor object by + calling the :meth:`~Connection.cursor` method, calls the cursor's + :meth:`~Cursor.executescript` method with the given *sql_script*, and + returns the cursor. .. method:: create_function(name, num_params, func) @@ -533,7 +534,7 @@ Cursor Objects A :class:`Cursor` instance has the following attributes and methods. - .. method:: execute(sql, [parameters]) + .. method:: execute(sql[, parameters]) Executes an SQL statement. The SQL statement may be parameterized (i. e. placeholders instead of SQL literals). The :mod:`sqlite3` module supports two @@ -545,7 +546,7 @@ Cursor Objects .. literalinclude:: ../includes/sqlite3/execute_1.py :meth:`execute` will only execute a single SQL statement. If you try to execute - more than one statement with it, it will raise a Warning. Use + more than one statement with it, it will raise an ``sqlite3.Warning``. Use :meth:`executescript` if you want to execute multiple SQL statements with one call. @@ -553,8 +554,8 @@ Cursor Objects .. method:: executemany(sql, seq_of_parameters) Executes an SQL command against all parameter sequences or mappings found in - the sequence *sql*. The :mod:`sqlite3` module also allows using an - :term:`iterator` yielding parameters instead of a sequence. + the sequence *seq_of_parameters*. The :mod:`sqlite3` module also allows + using an :term:`iterator` yielding parameters instead of a sequence. .. literalinclude:: ../includes/sqlite3/executemany_1.py @@ -569,7 +570,7 @@ Cursor Objects at once. It issues a ``COMMIT`` statement first, then executes the SQL script it gets as a parameter. - *sql_script* can be an instance of :class:`str` or :class:`bytes`. + *sql_script* can be an instance of :class:`str`. Example: diff --git a/Lib/sqlite3/test/dbapi.py b/Lib/sqlite3/test/dbapi.py index 04649fc..04d0479 100644 --- a/Lib/sqlite3/test/dbapi.py +++ b/Lib/sqlite3/test/dbapi.py @@ -250,6 +250,11 @@ class CursorTests(unittest.TestCase): row = self.cu.fetchone() self.assertEqual(row[0], "Hu\x00go") + def CheckExecuteNonIterable(self): + with self.assertRaises(ValueError) as cm: + self.cu.execute("insert into test(id) values (?)", 42) + self.assertEqual(str(cm.exception), 'parameters are of unsupported type') + def CheckExecuteWrongNoOfArgs1(self): # too many parameters try: @@ -725,6 +730,13 @@ class ExtensionTests(unittest.TestCase): raised = True self.assertEqual(raised, True, "should have raised an exception") + def CheckCursorExecutescriptAsBytes(self): + con = sqlite.connect(":memory:") + cur = con.cursor() + with self.assertRaises(ValueError) as cm: + cur.executescript(b"create table test(foo); insert into test(foo) values (5);") + self.assertEqual(str(cm.exception), 'script argument must be unicode.') + def CheckConnectionExecute(self): con = sqlite.connect(":memory:") result = con.execute("select 5").fetchone()[0] -- cgit v0.12 From 7bea2347c7e8af2c6b59e541c4039c34c7a8f6b2 Mon Sep 17 00:00:00 2001 From: Berker Peksag Date: Sun, 12 Jun 2016 14:09:51 +0300 Subject: Issue #27190: Raise NotSupportedError if sqlite3 is older than 3.3.1 Patch by Dave Sawyer. --- Lib/sqlite3/test/dbapi.py | 6 ++++++ Misc/NEWS | 3 +++ Modules/_sqlite/connection.c | 4 ++++ 3 files changed, 13 insertions(+) diff --git a/Lib/sqlite3/test/dbapi.py b/Lib/sqlite3/test/dbapi.py index 04d0479..78c27d7 100644 --- a/Lib/sqlite3/test/dbapi.py +++ b/Lib/sqlite3/test/dbapi.py @@ -180,6 +180,12 @@ class ConnectionTests(unittest.TestCase): with self.assertRaises(sqlite.OperationalError): cx.execute('insert into test(id) values(1)') + def CheckSameThreadErrorOnOldVersion(self): + if sqlite.sqlite_version_info >= (3, 3, 1): + self.skipTest('test needs sqlite3 versions older than 3.3.1') + with self.assertRaises(sqlite.NotSupportedError) as cm: + sqlite.connect(':memory:', check_same_thread=False) + self.assertEqual(str(cm.exception), 'shared connections not available') class CursorTests(unittest.TestCase): def setUp(self): diff --git a/Misc/NEWS b/Misc/NEWS index 3189824..3e374f8 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Release date: tba Core and Builtins ----------------- +- Issue #27190: Raise NotSupportedError if sqlite3 is older than 3.3.1. + Patch by Dave Sawyer. + - Issue #27286: Fixed compiling BUILD_MAP_UNPACK_WITH_CALL opcode. Calling function with generalized unpacking (PEP 448) and conflicting keyword names could cause undefined behavior. diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c index 7570624..6aa4764 100644 --- a/Modules/_sqlite/connection.c +++ b/Modules/_sqlite/connection.c @@ -164,6 +164,10 @@ int pysqlite_connection_init(pysqlite_Connection* self, PyObject* args, PyObject #ifdef WITH_THREAD self->thread_ident = PyThread_get_thread_ident(); #endif + if (!check_same_thread && sqlite3_libversion_number() < 3003001) { + PyErr_SetString(pysqlite_NotSupportedError, "shared connections not available"); + return -1; + } self->check_same_thread = check_same_thread; self->function_pinboard = PyDict_New(); -- cgit v0.12 From 46fe29de318c628309c2f12bec3a32f7e15ba844 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sun, 12 Jun 2016 15:45:14 +0300 Subject: Issue #25455: Clean up reference loops created in tests for recursive functools.partial objects. --- Lib/test/test_functools.py | 48 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py index 3cb2827..ab51a35 100644 --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -225,15 +225,24 @@ class TestPartialC(TestPartial, unittest.TestCase): f = self.partial(capture) f.__setstate__((f, (), {}, {})) - self.assertEqual(repr(f), '%s(%s(...))' % (name, name)) + try: + self.assertEqual(repr(f), '%s(%s(...))' % (name, name)) + finally: + f.__setstate__((capture, (), {}, {})) f = self.partial(capture) f.__setstate__((capture, (f,), {}, {})) - self.assertEqual(repr(f), '%s(%r, %s(...))' % (name, capture, name)) + try: + self.assertEqual(repr(f), '%s(%r, %s(...))' % (name, capture, name)) + finally: + f.__setstate__((capture, (), {}, {})) f = self.partial(capture) f.__setstate__((capture, (), {'a': f}, {})) - self.assertEqual(repr(f), '%s(%r, a=%s(...))' % (name, capture, name)) + try: + self.assertEqual(repr(f), '%s(%r, a=%s(...))' % (name, capture, name)) + finally: + f.__setstate__((capture, (), {}, {})) def test_pickle(self): f = self.partial(signature, ['asdf'], bar=[True]) @@ -318,21 +327,36 @@ class TestPartialC(TestPartial, unittest.TestCase): def test_recursive_pickle(self): f = self.partial(capture) f.__setstate__((f, (), {}, {})) - for proto in range(pickle.HIGHEST_PROTOCOL + 1): - with self.assertRaises(RecursionError): - pickle.dumps(f, proto) + try: + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + with self.assertRaises(RecursionError): + pickle.dumps(f, proto) + finally: + f.__setstate__((capture, (), {}, {})) f = self.partial(capture) f.__setstate__((capture, (f,), {}, {})) - for proto in range(pickle.HIGHEST_PROTOCOL + 1): - f_copy = pickle.loads(pickle.dumps(f, proto)) - self.assertIs(f_copy.args[0], f_copy) + try: + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + f_copy = pickle.loads(pickle.dumps(f, proto)) + try: + self.assertIs(f_copy.args[0], f_copy) + finally: + f_copy.__setstate__((capture, (), {}, {})) + finally: + f.__setstate__((capture, (), {}, {})) f = self.partial(capture) f.__setstate__((capture, (), {'a': f}, {})) - for proto in range(pickle.HIGHEST_PROTOCOL + 1): - f_copy = pickle.loads(pickle.dumps(f, proto)) - self.assertIs(f_copy.keywords['a'], f_copy) + try: + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + f_copy = pickle.loads(pickle.dumps(f, proto)) + try: + self.assertIs(f_copy.keywords['a'], f_copy) + finally: + f_copy.__setstate__((capture, (), {}, {})) + finally: + f.__setstate__((capture, (), {}, {})) # Issue 6083: Reference counting bug def test_setstate_refcount(self): -- cgit v0.12 From c74cdc71705f7d936dfd51b68c26a6eadc2367d1 Mon Sep 17 00:00:00 2001 From: Berker Peksag Date: Sun, 12 Jun 2016 16:27:48 +0300 Subject: Issue #27289: Prevent test_urllib2net failures due to EOFError raised by ftplib --- Lib/test/support/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index e124fab..c9e36fb 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -1349,7 +1349,8 @@ def transient_internet(resource_name, *, timeout=30.0, errnos=()): 500 <= err.code <= 599) or (isinstance(err, urllib.error.URLError) and (("ConnectionRefusedError" in err.reason) or - ("TimeoutError" in err.reason))) or + ("TimeoutError" in err.reason) or + ("EOFError" in err.reason))) or n in captured_errnos): if not verbose: sys.stderr.write(denied.args[0] + "\n") -- cgit v0.12 From 8f95e65e5d6fc95cb08fc900802e724f0f58c278 Mon Sep 17 00:00:00 2001 From: Berker Peksag Date: Sun, 12 Jun 2016 16:34:38 +0300 Subject: Issue #15657: Delete incorrect statement from PyMethodDef documentation --- Doc/c-api/structures.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Doc/c-api/structures.rst b/Doc/c-api/structures.rst index e9e8add..cc84314 100644 --- a/Doc/c-api/structures.rst +++ b/Doc/c-api/structures.rst @@ -150,9 +150,8 @@ specific C type of the *self* object. The :attr:`ml_flags` field is a bitfield which can include the following flags. The individual flags indicate either a calling convention or a binding convention. Of the calling convention flags, only :const:`METH_VARARGS` and -:const:`METH_KEYWORDS` can be combined (but note that :const:`METH_KEYWORDS` -alone is equivalent to ``METH_VARARGS | METH_KEYWORDS``). Any of the calling -convention flags can be combined with a binding flag. +:const:`METH_KEYWORDS` can be combined. Any of the calling convention flags +can be combined with a binding flag. .. data:: METH_VARARGS -- cgit v0.12 From 0e1d6802ff03666bced6548e75b8459c88c2b720 Mon Sep 17 00:00:00 2001 From: Berker Peksag Date: Sun, 12 Jun 2016 19:17:49 +0300 Subject: Fix typo in _sqlite/module.h --- Modules/_sqlite/module.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/_sqlite/module.h b/Modules/_sqlite/module.h index b51724b..0fb5a55 100644 --- a/Modules/_sqlite/module.h +++ b/Modules/_sqlite/module.h @@ -42,7 +42,7 @@ extern PyObject* pysqlite_NotSupportedError; extern PyObject* time_time; extern PyObject* time_sleep; -/* A dictionary, mapping colum types (INTEGER, VARCHAR, etc.) to converter +/* A dictionary, mapping column types (INTEGER, VARCHAR, etc.) to converter * functions, that convert the SQL value to the appropriate Python value. * The key is uppercase. */ -- cgit v0.12 From 1003b34c71d53ccb88ae2768aaba503ae6b5bc16 Mon Sep 17 00:00:00 2001 From: Berker Peksag Date: Sun, 12 Jun 2016 22:34:49 +0300 Subject: Modernize sqlite3 tests Update current tests that use old pattern with assertRaises to make them more maintainable. --- Lib/sqlite3/test/dbapi.py | 172 ++++++-------------------------------- Lib/sqlite3/test/hooks.py | 28 ++----- Lib/sqlite3/test/regression.py | 22 +---- Lib/sqlite3/test/transactions.py | 21 +---- Lib/sqlite3/test/types.py | 14 +--- Lib/sqlite3/test/userfunctions.py | 62 ++++---------- 6 files changed, 62 insertions(+), 257 deletions(-) diff --git a/Lib/sqlite3/test/dbapi.py b/Lib/sqlite3/test/dbapi.py index 78c27d7..6057805 100644 --- a/Lib/sqlite3/test/dbapi.py +++ b/Lib/sqlite3/test/dbapi.py @@ -122,11 +122,8 @@ class ConnectionTests(unittest.TestCase): def CheckFailedOpen(self): YOU_CANNOT_OPEN_THIS = "/foo/bar/bla/23534/mydb.db" - try: + with self.assertRaises(sqlite.OperationalError): con = sqlite.connect(YOU_CANNOT_OPEN_THIS) - except sqlite.OperationalError: - return - self.fail("should have raised an OperationalError") def CheckClose(self): self.cx.close() @@ -202,22 +199,12 @@ class CursorTests(unittest.TestCase): self.cu.execute("delete from test") def CheckExecuteIllegalSql(self): - try: + with self.assertRaises(sqlite.OperationalError): self.cu.execute("select asdf") - self.fail("should have raised an OperationalError") - except sqlite.OperationalError: - return - except: - self.fail("raised wrong exception") def CheckExecuteTooMuchSql(self): - try: + with self.assertRaises(sqlite.Warning): self.cu.execute("select 5+4; select 4+5") - self.fail("should have raised a Warning") - except sqlite.Warning: - return - except: - self.fail("raised wrong exception") def CheckExecuteTooMuchSql2(self): self.cu.execute("select 5+4; -- foo bar") @@ -232,13 +219,8 @@ class CursorTests(unittest.TestCase): """) def CheckExecuteWrongSqlArg(self): - try: + with self.assertRaises(ValueError): self.cu.execute(42) - self.fail("should have raised a ValueError") - except ValueError: - return - except: - self.fail("raised wrong exception.") def CheckExecuteArgInt(self): self.cu.execute("insert into test(id) values (?)", (42,)) @@ -263,27 +245,18 @@ class CursorTests(unittest.TestCase): def CheckExecuteWrongNoOfArgs1(self): # too many parameters - try: + with self.assertRaises(sqlite.ProgrammingError): self.cu.execute("insert into test(id) values (?)", (17, "Egon")) - self.fail("should have raised ProgrammingError") - except sqlite.ProgrammingError: - pass def CheckExecuteWrongNoOfArgs2(self): # too little parameters - try: + with self.assertRaises(sqlite.ProgrammingError): self.cu.execute("insert into test(id) values (?)") - self.fail("should have raised ProgrammingError") - except sqlite.ProgrammingError: - pass def CheckExecuteWrongNoOfArgs3(self): # no parameters, parameters are needed - try: + with self.assertRaises(sqlite.ProgrammingError): self.cu.execute("insert into test(id) values (?)") - self.fail("should have raised ProgrammingError") - except sqlite.ProgrammingError: - pass def CheckExecuteParamList(self): self.cu.execute("insert into test(name) values ('foo')") @@ -322,27 +295,18 @@ class CursorTests(unittest.TestCase): def CheckExecuteDictMappingTooLittleArgs(self): self.cu.execute("insert into test(name) values ('foo')") - try: + with self.assertRaises(sqlite.ProgrammingError): self.cu.execute("select name from test where name=:name and id=:id", {"name": "foo"}) - self.fail("should have raised ProgrammingError") - except sqlite.ProgrammingError: - pass def CheckExecuteDictMappingNoArgs(self): self.cu.execute("insert into test(name) values ('foo')") - try: + with self.assertRaises(sqlite.ProgrammingError): self.cu.execute("select name from test where name=:name") - self.fail("should have raised ProgrammingError") - except sqlite.ProgrammingError: - pass def CheckExecuteDictMappingUnnamed(self): self.cu.execute("insert into test(name) values ('foo')") - try: + with self.assertRaises(sqlite.ProgrammingError): self.cu.execute("select name from test where name=?", {"name": "foo"}) - self.fail("should have raised ProgrammingError") - except sqlite.ProgrammingError: - pass def CheckClose(self): self.cu.close() @@ -403,32 +367,16 @@ class CursorTests(unittest.TestCase): self.cu.executemany("insert into test(income) values (?)", mygen()) def CheckExecuteManyWrongSqlArg(self): - try: + with self.assertRaises(ValueError): self.cu.executemany(42, [(3,)]) - self.fail("should have raised a ValueError") - except ValueError: - return - except: - self.fail("raised wrong exception.") def CheckExecuteManySelect(self): - try: + with self.assertRaises(sqlite.ProgrammingError): self.cu.executemany("select ?", [(3,)]) - self.fail("should have raised a ProgrammingError") - except sqlite.ProgrammingError: - return - except: - self.fail("raised wrong exception.") def CheckExecuteManyNotIterable(self): - try: + with self.assertRaises(TypeError): self.cu.executemany("insert into test(income) values (?)", 42) - self.fail("should have raised a TypeError") - except TypeError: - return - except Exception as e: - print("raised", e.__class__) - self.fail("raised wrong exception.") def CheckFetchIter(self): # Optional DB-API extension. @@ -505,22 +453,15 @@ class CursorTests(unittest.TestCase): self.assertEqual(self.cu.connection, self.cx) def CheckWrongCursorCallable(self): - try: + with self.assertRaises(TypeError): def f(): pass cur = self.cx.cursor(f) - self.fail("should have raised a TypeError") - except TypeError: - return - self.fail("should have raised a ValueError") def CheckCursorWrongClass(self): class Foo: pass foo = Foo() - try: + with self.assertRaises(TypeError): cur = sqlite.Cursor(foo) - self.fail("should have raised a ValueError") - except TypeError: - pass @unittest.skipUnless(threading, 'This test requires threading.') class ThreadTests(unittest.TestCase): @@ -719,22 +660,14 @@ class ExtensionTests(unittest.TestCase): def CheckScriptSyntaxError(self): con = sqlite.connect(":memory:") cur = con.cursor() - raised = False - try: + with self.assertRaises(sqlite.OperationalError): cur.executescript("create table test(x); asdf; create table test2(x)") - except sqlite.OperationalError: - raised = True - self.assertEqual(raised, True, "should have raised an exception") def CheckScriptErrorNormal(self): con = sqlite.connect(":memory:") cur = con.cursor() - raised = False - try: + with self.assertRaises(sqlite.OperationalError): cur.executescript("create table test(sadfsadfdsa); select foo from hurz;") - except sqlite.OperationalError: - raised = True - self.assertEqual(raised, True, "should have raised an exception") def CheckCursorExecutescriptAsBytes(self): con = sqlite.connect(":memory:") @@ -772,59 +705,34 @@ class ClosedConTests(unittest.TestCase): def CheckClosedConCursor(self): con = sqlite.connect(":memory:") con.close() - try: + with self.assertRaises(sqlite.ProgrammingError): cur = con.cursor() - self.fail("Should have raised a ProgrammingError") - except sqlite.ProgrammingError: - pass - except: - self.fail("Should have raised a ProgrammingError") def CheckClosedConCommit(self): con = sqlite.connect(":memory:") con.close() - try: + with self.assertRaises(sqlite.ProgrammingError): con.commit() - self.fail("Should have raised a ProgrammingError") - except sqlite.ProgrammingError: - pass - except: - self.fail("Should have raised a ProgrammingError") def CheckClosedConRollback(self): con = sqlite.connect(":memory:") con.close() - try: + with self.assertRaises(sqlite.ProgrammingError): con.rollback() - self.fail("Should have raised a ProgrammingError") - except sqlite.ProgrammingError: - pass - except: - self.fail("Should have raised a ProgrammingError") def CheckClosedCurExecute(self): con = sqlite.connect(":memory:") cur = con.cursor() con.close() - try: + with self.assertRaises(sqlite.ProgrammingError): cur.execute("select 4") - self.fail("Should have raised a ProgrammingError") - except sqlite.ProgrammingError: - pass - except: - self.fail("Should have raised a ProgrammingError") def CheckClosedCreateFunction(self): con = sqlite.connect(":memory:") con.close() def f(x): return 17 - try: + with self.assertRaises(sqlite.ProgrammingError): con.create_function("foo", 1, f) - self.fail("Should have raised a ProgrammingError") - except sqlite.ProgrammingError: - pass - except: - self.fail("Should have raised a ProgrammingError") def CheckClosedCreateAggregate(self): con = sqlite.connect(":memory:") @@ -836,49 +744,29 @@ class ClosedConTests(unittest.TestCase): pass def finalize(self): return 17 - try: + with self.assertRaises(sqlite.ProgrammingError): con.create_aggregate("foo", 1, Agg) - self.fail("Should have raised a ProgrammingError") - except sqlite.ProgrammingError: - pass - except: - self.fail("Should have raised a ProgrammingError") def CheckClosedSetAuthorizer(self): con = sqlite.connect(":memory:") con.close() def authorizer(*args): return sqlite.DENY - try: + with self.assertRaises(sqlite.ProgrammingError): con.set_authorizer(authorizer) - self.fail("Should have raised a ProgrammingError") - except sqlite.ProgrammingError: - pass - except: - self.fail("Should have raised a ProgrammingError") def CheckClosedSetProgressCallback(self): con = sqlite.connect(":memory:") con.close() def progress(): pass - try: + with self.assertRaises(sqlite.ProgrammingError): con.set_progress_handler(progress, 100) - self.fail("Should have raised a ProgrammingError") - except sqlite.ProgrammingError: - pass - except: - self.fail("Should have raised a ProgrammingError") def CheckClosedCall(self): con = sqlite.connect(":memory:") con.close() - try: + with self.assertRaises(sqlite.ProgrammingError): con() - self.fail("Should have raised a ProgrammingError") - except sqlite.ProgrammingError: - pass - except: - self.fail("Should have raised a ProgrammingError") class ClosedCurTests(unittest.TestCase): def setUp(self): @@ -900,15 +788,9 @@ class ClosedCurTests(unittest.TestCase): else: params = [] - try: + with self.assertRaises(sqlite.ProgrammingError): method = getattr(cur, method_name) - method(*params) - self.fail("Should have raised a ProgrammingError: method " + method_name) - except sqlite.ProgrammingError: - pass - except: - self.fail("Should have raised a ProgrammingError: " + method_name) def suite(): module_suite = unittest.makeSuite(ModuleTests, "Check") diff --git a/Lib/sqlite3/test/hooks.py b/Lib/sqlite3/test/hooks.py index ede0bec..67653ae 100644 --- a/Lib/sqlite3/test/hooks.py +++ b/Lib/sqlite3/test/hooks.py @@ -33,19 +33,14 @@ class CollationTests(unittest.TestCase): def CheckCreateCollationNotCallable(self): con = sqlite.connect(":memory:") - try: + with self.assertRaises(TypeError) as cm: con.create_collation("X", 42) - self.fail("should have raised a TypeError") - except TypeError as e: - self.assertEqual(e.args[0], "parameter must be callable") + self.assertEqual(str(cm.exception), 'parameter must be callable') def CheckCreateCollationNotAscii(self): con = sqlite.connect(":memory:") - try: + with self.assertRaises(sqlite.ProgrammingError): con.create_collation("coll", lambda x, y: (x > y) - (x < y)) - self.fail("should have raised a ProgrammingError") - except sqlite.ProgrammingError as e: - pass @unittest.skipIf(sqlite.sqlite_version_info < (3, 2, 1), 'old SQLite versions crash on this test') @@ -70,11 +65,9 @@ class CollationTests(unittest.TestCase): self.fail("the expected order was not returned") con.create_collation("mycoll", None) - try: + with self.assertRaises(sqlite.OperationalError) as cm: result = con.execute(sql).fetchall() - self.fail("should have raised an OperationalError") - except sqlite.OperationalError as e: - self.assertEqual(e.args[0].lower(), "no such collation sequence: mycoll") + self.assertEqual(str(cm.exception), 'no such collation sequence: mycoll') def CheckCollationReturnsLargeInteger(self): def mycoll(x, y): @@ -106,8 +99,8 @@ class CollationTests(unittest.TestCase): result = con.execute(""" select x from (select 'a' as x union select 'b' as x) order by x collate mycoll """).fetchall() - if result[0][0] != 'b' or result[1][0] != 'a': - self.fail("wrong collation function is used") + self.assertEqual(result[0][0], 'b') + self.assertEqual(result[1][0], 'a') def CheckDeregisterCollation(self): """ @@ -117,12 +110,9 @@ class CollationTests(unittest.TestCase): con = sqlite.connect(":memory:") con.create_collation("mycoll", lambda x, y: (x > y) - (x < y)) con.create_collation("mycoll", None) - try: + with self.assertRaises(sqlite.OperationalError) as cm: con.execute("select 'a' as x union select 'b' as x order by x collate mycoll") - self.fail("should have raised an OperationalError") - except sqlite.OperationalError as e: - if not e.args[0].startswith("no such collation sequence"): - self.fail("wrong OperationalError raised") + self.assertEqual(str(cm.exception), 'no such collation sequence: mycoll') class ProgressTests(unittest.TestCase): def CheckProgressHandlerUsed(self): diff --git a/Lib/sqlite3/test/regression.py b/Lib/sqlite3/test/regression.py index 11adb30..85ace84 100644 --- a/Lib/sqlite3/test/regression.py +++ b/Lib/sqlite3/test/regression.py @@ -170,14 +170,8 @@ class RegressionTests(unittest.TestCase): con = sqlite.connect(":memory:") cur = Cursor(con) - try: + with self.assertRaises(sqlite.ProgrammingError): cur.execute("select 4+5").fetchall() - self.fail("should have raised ProgrammingError") - except sqlite.ProgrammingError: - pass - except: - self.fail("should have raised ProgrammingError") - def CheckStrSubclass(self): """ @@ -196,13 +190,8 @@ class RegressionTests(unittest.TestCase): pass con = Connection(":memory:") - try: + with self.assertRaises(sqlite.ProgrammingError): cur = con.cursor() - self.fail("should have raised ProgrammingError") - except sqlite.ProgrammingError: - pass - except: - self.fail("should have raised ProgrammingError") def CheckCursorRegistration(self): """ @@ -223,13 +212,8 @@ class RegressionTests(unittest.TestCase): cur.executemany("insert into foo(x) values (?)", [(3,), (4,), (5,)]) cur.execute("select x from foo") con.rollback() - try: + with self.assertRaises(sqlite.InterfaceError): cur.fetchall() - self.fail("should have raised InterfaceError") - except sqlite.InterfaceError: - pass - except: - self.fail("should have raised InterfaceError") def CheckAutoCommit(self): """ diff --git a/Lib/sqlite3/test/transactions.py b/Lib/sqlite3/test/transactions.py index feb4fa1..eae26c4 100644 --- a/Lib/sqlite3/test/transactions.py +++ b/Lib/sqlite3/test/transactions.py @@ -118,13 +118,8 @@ class TransactionTests(unittest.TestCase): return self.cur1.execute("create table test(i)") self.cur1.execute("insert into test(i) values (5)") - try: + with self.assertRaises(sqlite.OperationalError): self.cur2.execute("insert into test(i) values (5)") - self.fail("should have raised an OperationalError") - except sqlite.OperationalError: - pass - except: - self.fail("should have raised an OperationalError") def CheckLocking(self): """ @@ -137,13 +132,8 @@ class TransactionTests(unittest.TestCase): return self.cur1.execute("create table test(i)") self.cur1.execute("insert into test(i) values (5)") - try: + with self.assertRaises(sqlite.OperationalError): self.cur2.execute("insert into test(i) values (5)") - self.fail("should have raised an OperationalError") - except sqlite.OperationalError: - pass - except: - self.fail("should have raised an OperationalError") # NO self.con2.rollback() HERE!!! self.con1.commit() @@ -159,13 +149,8 @@ class TransactionTests(unittest.TestCase): cur.execute("select 1 union select 2 union select 3") con.rollback() - try: + with self.assertRaises(sqlite.InterfaceError): cur.fetchall() - self.fail("InterfaceError should have been raised") - except sqlite.InterfaceError as e: - pass - except: - self.fail("InterfaceError should have been raised") class SpecialCommandTests(unittest.TestCase): def setUp(self): diff --git a/Lib/sqlite3/test/types.py b/Lib/sqlite3/test/types.py index adad571..f7c8f9c 100644 --- a/Lib/sqlite3/test/types.py +++ b/Lib/sqlite3/test/types.py @@ -185,24 +185,14 @@ class DeclTypesTests(unittest.TestCase): def CheckUnsupportedSeq(self): class Bar: pass val = Bar() - try: + with self.assertRaises(sqlite.InterfaceError): self.cur.execute("insert into test(f) values (?)", (val,)) - self.fail("should have raised an InterfaceError") - except sqlite.InterfaceError: - pass - except: - self.fail("should have raised an InterfaceError") def CheckUnsupportedDict(self): class Bar: pass val = Bar() - try: + with self.assertRaises(sqlite.InterfaceError): self.cur.execute("insert into test(f) values (:val)", {"val": val}) - self.fail("should have raised an InterfaceError") - except sqlite.InterfaceError: - pass - except: - self.fail("should have raised an InterfaceError") def CheckBlob(self): # default diff --git a/Lib/sqlite3/test/userfunctions.py b/Lib/sqlite3/test/userfunctions.py index 8a4bbab..4075045 100644 --- a/Lib/sqlite3/test/userfunctions.py +++ b/Lib/sqlite3/test/userfunctions.py @@ -162,11 +162,8 @@ class FunctionTests(unittest.TestCase): self.con.close() def CheckFuncErrorOnCreate(self): - try: + with self.assertRaises(sqlite.OperationalError): self.con.create_function("bla", -100, lambda x: 2*x) - self.fail("should have raised an OperationalError") - except sqlite.OperationalError: - pass def CheckFuncRefCount(self): def getfunc(): @@ -231,12 +228,10 @@ class FunctionTests(unittest.TestCase): def CheckFuncException(self): cur = self.con.cursor() - try: + with self.assertRaises(sqlite.OperationalError) as cm: cur.execute("select raiseexception()") cur.fetchone() - self.fail("should have raised OperationalError") - except sqlite.OperationalError as e: - self.assertEqual(e.args[0], 'user-defined function raised exception') + self.assertEqual(str(cm.exception), 'user-defined function raised exception') def CheckParamString(self): cur = self.con.cursor() @@ -312,55 +307,42 @@ class AggregateTests(unittest.TestCase): pass def CheckAggrErrorOnCreate(self): - try: + with self.assertRaises(sqlite.OperationalError): self.con.create_function("bla", -100, AggrSum) - self.fail("should have raised an OperationalError") - except sqlite.OperationalError: - pass def CheckAggrNoStep(self): cur = self.con.cursor() - try: + with self.assertRaises(AttributeError) as cm: cur.execute("select nostep(t) from test") - self.fail("should have raised an AttributeError") - except AttributeError as e: - self.assertEqual(e.args[0], "'AggrNoStep' object has no attribute 'step'") + self.assertEqual(str(cm.exception), "'AggrNoStep' object has no attribute 'step'") def CheckAggrNoFinalize(self): cur = self.con.cursor() - try: + with self.assertRaises(sqlite.OperationalError) as cm: cur.execute("select nofinalize(t) from test") val = cur.fetchone()[0] - self.fail("should have raised an OperationalError") - except sqlite.OperationalError as e: - self.assertEqual(e.args[0], "user-defined aggregate's 'finalize' method raised error") + self.assertEqual(str(cm.exception), "user-defined aggregate's 'finalize' method raised error") def CheckAggrExceptionInInit(self): cur = self.con.cursor() - try: + with self.assertRaises(sqlite.OperationalError) as cm: cur.execute("select excInit(t) from test") val = cur.fetchone()[0] - self.fail("should have raised an OperationalError") - except sqlite.OperationalError as e: - self.assertEqual(e.args[0], "user-defined aggregate's '__init__' method raised error") + self.assertEqual(str(cm.exception), "user-defined aggregate's '__init__' method raised error") def CheckAggrExceptionInStep(self): cur = self.con.cursor() - try: + with self.assertRaises(sqlite.OperationalError) as cm: cur.execute("select excStep(t) from test") val = cur.fetchone()[0] - self.fail("should have raised an OperationalError") - except sqlite.OperationalError as e: - self.assertEqual(e.args[0], "user-defined aggregate's 'step' method raised error") + self.assertEqual(str(cm.exception), "user-defined aggregate's 'step' method raised error") def CheckAggrExceptionInFinalize(self): cur = self.con.cursor() - try: + with self.assertRaises(sqlite.OperationalError) as cm: cur.execute("select excFinalize(t) from test") val = cur.fetchone()[0] - self.fail("should have raised an OperationalError") - except sqlite.OperationalError as e: - self.assertEqual(e.args[0], "user-defined aggregate's 'finalize' method raised error") + self.assertEqual(str(cm.exception), "user-defined aggregate's 'finalize' method raised error") def CheckAggrCheckParamStr(self): cur = self.con.cursor() @@ -433,22 +415,14 @@ class AuthorizerTests(unittest.TestCase): pass def test_table_access(self): - try: + with self.assertRaises(sqlite.DatabaseError) as cm: self.con.execute("select * from t2") - except sqlite.DatabaseError as e: - if not e.args[0].endswith("prohibited"): - self.fail("wrong exception text: %s" % e.args[0]) - return - self.fail("should have raised an exception due to missing privileges") + self.assertIn('prohibited', str(cm.exception)) def test_column_access(self): - try: + with self.assertRaises(sqlite.DatabaseError) as cm: self.con.execute("select c2 from t1") - except sqlite.DatabaseError as e: - if not e.args[0].endswith("prohibited"): - self.fail("wrong exception text: %s" % e.args[0]) - return - self.fail("should have raised an exception due to missing privileges") + self.assertIn('prohibited', str(cm.exception)) class AuthorizerRaiseExceptionTests(AuthorizerTests): @staticmethod -- cgit v0.12 From 48b5c98e6e0139c24298f6ed7962da29d0f9cb89 Mon Sep 17 00:00:00 2001 From: Berker Peksag Date: Tue, 14 Jun 2016 00:42:50 +0300 Subject: Replace more boilerplate code with modern unittest features in sqlite3 tests --- Lib/sqlite3/test/dbapi.py | 3 +-- Lib/sqlite3/test/hooks.py | 4 ++-- Lib/sqlite3/test/regression.py | 12 +++--------- 3 files changed, 6 insertions(+), 13 deletions(-) diff --git a/Lib/sqlite3/test/dbapi.py b/Lib/sqlite3/test/dbapi.py index 6057805..903e599 100644 --- a/Lib/sqlite3/test/dbapi.py +++ b/Lib/sqlite3/test/dbapi.py @@ -335,8 +335,7 @@ class CursorTests(unittest.TestCase): def CheckTotalChanges(self): self.cu.execute("insert into test(name) values ('foo')") self.cu.execute("insert into test(name) values ('foo')") - if self.cx.total_changes < 2: - self.fail("total changes reported wrong value") + self.assertLess(2, self.cx.total_changes, msg='total changes reported wrong value') # Checks for executemany: # Sequences are required by the DB-API, iterators diff --git a/Lib/sqlite3/test/hooks.py b/Lib/sqlite3/test/hooks.py index 67653ae..de69569 100644 --- a/Lib/sqlite3/test/hooks.py +++ b/Lib/sqlite3/test/hooks.py @@ -61,8 +61,8 @@ class CollationTests(unittest.TestCase): ) order by x collate mycoll """ result = con.execute(sql).fetchall() - if result[0][0] != "c" or result[1][0] != "b" or result[2][0] != "a": - self.fail("the expected order was not returned") + self.assertEqual(result, [('c',), ('b',), ('a',)], + msg='the expected order was not returned') con.create_collation("mycoll", None) with self.assertRaises(sqlite.OperationalError) as cm: diff --git a/Lib/sqlite3/test/regression.py b/Lib/sqlite3/test/regression.py index 85ace84..0cf9002 100644 --- a/Lib/sqlite3/test/regression.py +++ b/Lib/sqlite3/test/regression.py @@ -134,17 +134,11 @@ class RegressionTests(unittest.TestCase): def CheckErrorMsgDecodeError(self): # When porting the module to Python 3.0, the error message about # decoding errors disappeared. This verifies they're back again. - failure = None - try: + with self.assertRaises(sqlite.OperationalError) as cm: self.con.execute("select 'xxx' || ? || 'yyy' colname", (bytes(bytearray([250])),)).fetchone() - failure = "should have raised an OperationalError with detailed description" - except sqlite.OperationalError as e: - msg = e.args[0] - if not msg.startswith("Could not decode to UTF-8 column 'colname' with text 'xxx"): - failure = "OperationalError did not have expected description text" - if failure: - self.fail(failure) + msg = "Could not decode to UTF-8 column 'colname' with text 'xxx" + self.assertIn(msg, str(cm.exception)) def CheckRegisterAdapter(self): """ -- cgit v0.12 From 97484780863a94a33ac82c63a6c6ab0a53485277 Mon Sep 17 00:00:00 2001 From: Berker Peksag Date: Tue, 14 Jun 2016 00:48:35 +0300 Subject: Issue #27306: Fix typo in tarfile documentation Patch by Gareth Rees. --- Doc/library/tarfile.rst | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Doc/library/tarfile.rst b/Doc/library/tarfile.rst index 32d69bf..90a5852 100644 --- a/Doc/library/tarfile.rst +++ b/Doc/library/tarfile.rst @@ -64,19 +64,19 @@ Some facts and figures: | ``'x'`` or | Create a tarfile exclusively without | | ``'x:'`` | compression. | | | Raise an :exc:`FileExistsError` exception | - | | if it is already exists. | + | | if it already exists. | +------------------+---------------------------------------------+ | ``'x:gz'`` | Create a tarfile with gzip compression. | | | Raise an :exc:`FileExistsError` exception | - | | if it is already exists. | + | | if it already exists. | +------------------+---------------------------------------------+ | ``'x:bz2'`` | Create a tarfile with bzip2 compression. | | | Raise an :exc:`FileExistsError` exception | - | | if it is already exists. | + | | if it already exists. | +------------------+---------------------------------------------+ | ``'x:xz'`` | Create a tarfile with lzma compression. | | | Raise an :exc:`FileExistsError` exception | - | | if it is already exists. | + | | if it already exists. | +------------------+---------------------------------------------+ | ``'a' or 'a:'`` | Open for appending with no compression. The | | | file is created if it does not exist. | @@ -148,8 +148,8 @@ Some facts and figures: .. class:: TarFile - Class for reading and writing tar archives. Do not use this class directly, - better use :func:`tarfile.open` instead. See :ref:`tarfile-objects`. + Class for reading and writing tar archives. Do not use this class directly: + use :func:`tarfile.open` instead. See :ref:`tarfile-objects`. .. function:: is_tarfile(name) @@ -271,7 +271,7 @@ be finalized; only the internally used file object will be closed. See the *mode* is either ``'r'`` to read from an existing archive, ``'a'`` to append data to an existing file, ``'w'`` to create a new file overwriting an existing - one or ``'x'`` to create a new file only if it's not exists. + one, or ``'x'`` to create a new file only if it does not already exist. If *fileobj* is given, it is used for reading or writing data. If it can be determined, *mode* is overridden by *fileobj*'s mode. *fileobj* will be used -- cgit v0.12 From 5fc7c4dce18f332343bb6999477a18791a25b69e Mon Sep 17 00:00:00 2001 From: Martin Panter Date: Mon, 13 Jun 2016 03:17:47 +0000 Subject: Issue #27136: Change test to use ::1 for better OS X Tiger compatibility --- Lib/test/test_asyncio/test_base_events.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py index 0807dfb..206ebc6 100644 --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -1185,14 +1185,14 @@ class BaseEventLoopWithSelectorTests(test_utils.TestCase): test_utils.run_briefly(self.loop) # allow transport to close sock.family = socket.AF_INET6 - coro = self.loop.create_connection(asyncio.Protocol, '::2', 80) + coro = self.loop.create_connection(asyncio.Protocol, '::1', 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. + # Without inet_pton we use getaddrinfo, which transforms ('::1', 80) + # to ('::1', 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.assertRegex(host, r'::(0\.)*1') self.assertEqual(port, 80) _, kwargs = m_socket.socket.call_args self.assertEqual(kwargs['family'], m_socket.AF_INET6) -- cgit v0.12 From 19e21e4948c182edc130eb58ea8d1c14cd6d3173 Mon Sep 17 00:00:00 2001 From: Ned Deily Date: Mon, 13 Jun 2016 20:22:53 -0400 Subject: Issue #27310: remove vestigial import in IDLE.app --- Mac/IDLE/IDLE.app/Contents/Resources/idlemain.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/Mac/IDLE/IDLE.app/Contents/Resources/idlemain.py b/Mac/IDLE/IDLE.app/Contents/Resources/idlemain.py index 8b8beb9..986760d 100644 --- a/Mac/IDLE/IDLE.app/Contents/Resources/idlemain.py +++ b/Mac/IDLE/IDLE.app/Contents/Resources/idlemain.py @@ -68,8 +68,6 @@ for idx, value in enumerate(sys.argv): break # Now it is safe to import idlelib. -from idlelib import macosxSupport -macosxSupport._appbundle = True from idlelib.PyShell import main if __name__ == '__main__': main() -- cgit v0.12 From f00c49df10f04bf3b40c7d91efb8204068524d8f Mon Sep 17 00:00:00 2001 From: Martin Panter Date: Tue, 14 Jun 2016 01:16:16 +0000 Subject: Issue #16182: Fix readline begidx, endidx, and use locale encoding Based on patch by Serhiy Storchaka. --- Lib/test/test_readline.py | 141 ++++++++++++++++++++++++++++++++++++++++++++-- Misc/NEWS | 4 ++ Modules/readline.c | 132 ++++++++++++++++++++++++++++++------------- 3 files changed, 235 insertions(+), 42 deletions(-) diff --git a/Lib/test/test_readline.py b/Lib/test/test_readline.py index 35330ab..34a55b2 100644 --- a/Lib/test/test_readline.py +++ b/Lib/test/test_readline.py @@ -1,15 +1,23 @@ """ Very minimal unittests for parts of the readline module. """ +from contextlib import ExitStack +from errno import EIO import os +import selectors +import subprocess +import sys import tempfile import unittest -from test.support import import_module, unlink +from test.support import import_module, unlink, TESTFN from test.support.script_helper import assert_python_ok # Skip tests if there is no readline module readline = import_module('readline') +@unittest.skipUnless(hasattr(readline, "clear_history"), + "The history update test cannot be run because the " + "clear_history method is not available.") class TestHistoryManipulation (unittest.TestCase): """ These tests were added to check that the libedit emulation on OSX and the @@ -17,9 +25,6 @@ class TestHistoryManipulation (unittest.TestCase): why the tests cover only a small subset of the interface. """ - @unittest.skipUnless(hasattr(readline, "clear_history"), - "The history update test cannot be run because the " - "clear_history method is not available.") def testHistoryUpdates(self): readline.clear_history() @@ -82,6 +87,21 @@ class TestHistoryManipulation (unittest.TestCase): # write_history_file can create the target readline.write_history_file(hfilename) + def test_nonascii_history(self): + readline.clear_history() + try: + readline.add_history("entrée 1") + except UnicodeEncodeError as err: + self.skipTest("Locale cannot encode test data: " + format(err)) + readline.add_history("entrée 2") + readline.replace_history_item(1, "entrée 22") + readline.write_history_file(TESTFN) + self.addCleanup(os.remove, TESTFN) + readline.clear_history() + readline.read_history_file(TESTFN) + self.assertEqual(readline.get_history_item(1), "entrée 1") + self.assertEqual(readline.get_history_item(2), "entrée 22") + class TestReadline(unittest.TestCase): @@ -96,6 +116,119 @@ class TestReadline(unittest.TestCase): TERM='xterm-256color') self.assertEqual(stdout, b'') + def test_nonascii(self): + try: + readline.add_history("\xEB\xEF") + except UnicodeEncodeError as err: + self.skipTest("Locale cannot encode test data: " + format(err)) + + script = r"""import readline + +if readline.__doc__ and "libedit" in readline.__doc__: + readline.parse_and_bind(r'bind ^B ed-prev-char') + readline.parse_and_bind(r'bind "\t" rl_complete') + readline.parse_and_bind('bind -s ^A "|t\xEB[after]"') +else: + readline.parse_and_bind(r'Control-b: backward-char') + readline.parse_and_bind(r'"\t": complete') + readline.parse_and_bind(r'set disable-completion off') + readline.parse_and_bind(r'set show-all-if-ambiguous off') + readline.parse_and_bind(r'set show-all-if-unmodified off') + readline.parse_and_bind('Control-a: "|t\xEB[after]"') + +def pre_input_hook(): + readline.insert_text("[\xEFnserted]") + readline.redisplay() +readline.set_pre_input_hook(pre_input_hook) + +def completer(text, state): + if text == "t\xEB": + if state == 0: + print("text", ascii(text)) + print("line", ascii(readline.get_line_buffer())) + print("indexes", readline.get_begidx(), readline.get_endidx()) + return "t\xEBnt" + if state == 1: + return "t\xEBxt" + if text == "t\xEBx" and state == 0: + return "t\xEBxt" + return None +readline.set_completer(completer) + +def display(substitution, matches, longest_match_length): + print("substitution", ascii(substitution)) + print("matches", ascii(matches)) +readline.set_completion_display_matches_hook(display) + +print("result", ascii(input())) +print("history", ascii(readline.get_history_item(1))) +""" + + input = b"\x01" # Ctrl-A, expands to "|t\xEB[after]" + input += b"\x02" * len("[after]") # Move cursor back + input += b"\t\t" # Display possible completions + input += b"x\t" # Complete "t\xEBx" -> "t\xEBxt" + input += b"\r" + output = run_pty(script, input) + self.assertIn(b"text 't\\xeb'\r\n", output) + self.assertIn(b"line '[\\xefnserted]|t\\xeb[after]'\r\n", output) + self.assertIn(b"indexes 11 13\r\n", output) + self.assertIn(b"substitution 't\\xeb'\r\n", output) + self.assertIn(b"matches ['t\\xebnt', 't\\xebxt']\r\n", output) + expected = br"'[\xefnserted]|t\xebxt[after]'" + self.assertIn(b"result " + expected + b"\r\n", output) + self.assertIn(b"history " + expected + b"\r\n", output) + + +def run_pty(script, input=b"dummy input\r"): + pty = import_module('pty') + output = bytearray() + [master, slave] = pty.openpty() + args = (sys.executable, '-c', script) + proc = subprocess.Popen(args, stdin=slave, stdout=slave, stderr=slave) + os.close(slave) + with ExitStack() as cleanup: + cleanup.enter_context(proc) + def terminate(proc): + try: + proc.terminate() + except ProcessLookupError: + # Workaround for Open/Net BSD bug (Issue 16762) + pass + cleanup.callback(terminate, proc) + cleanup.callback(os.close, master) + # Avoid using DefaultSelector and PollSelector. Kqueue() does not + # work with pseudo-terminals on OS X < 10.9 (Issue 20365) and Open + # BSD (Issue 20667). Poll() does not work with OS X 10.6 or 10.4 + # either (Issue 20472). Hopefully the file descriptor is low enough + # to use with select(). + sel = cleanup.enter_context(selectors.SelectSelector()) + sel.register(master, selectors.EVENT_READ | selectors.EVENT_WRITE) + os.set_blocking(master, False) + while True: + for [_, events] in sel.select(): + if events & selectors.EVENT_READ: + try: + chunk = os.read(master, 0x10000) + except OSError as err: + # Linux raises EIO when slave is closed (Issue 5380) + if err.errno != EIO: + raise + chunk = b"" + if not chunk: + return output + output.extend(chunk) + if events & selectors.EVENT_WRITE: + try: + input = input[os.write(master, input):] + except OSError as err: + # Apparently EIO means the slave was closed + if err.errno != EIO: + raise + input = b"" # Stop writing + if not input: + sel.modify(master, selectors.EVENT_READ) + if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS b/Misc/NEWS index 1e06ea8..3398a86 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,10 @@ Core and Builtins Library ------- +- Issue #16182: Fix various functions in the "readline" module to use the + locale encoding, and fix get_begidx() and get_endidx() to return code point + indexes. + What's New in Python 3.5.2 final? ================================= diff --git a/Modules/readline.c b/Modules/readline.c index 8c00dec..91f7cca 100644 --- a/Modules/readline.c +++ b/Modules/readline.c @@ -128,20 +128,40 @@ static PyModuleDef readlinemodule; #define readlinestate_global ((readlinestate *)PyModule_GetState(PyState_FindModule(&readlinemodule))) +/* Convert to/from multibyte C strings */ + +static PyObject * +encode(PyObject *b) +{ + return PyUnicode_EncodeLocale(b, "surrogateescape"); +} + +static PyObject * +decode(const char *s) +{ + return PyUnicode_DecodeLocale(s, "surrogateescape"); +} + + /* Exported function to send one line to readline's init file parser */ static PyObject * -parse_and_bind(PyObject *self, PyObject *args) +parse_and_bind(PyObject *self, PyObject *string) { - char *s, *copy; - if (!PyArg_ParseTuple(args, "s:parse_and_bind", &s)) + char *copy; + PyObject *encoded = encode(string); + if (encoded == NULL) { return NULL; + } /* Make a copy -- rl_parse_and_bind() modifies its argument */ /* Bernard Herzog */ - copy = PyMem_Malloc(1 + strlen(s)); - if (copy == NULL) + copy = PyMem_Malloc(1 + PyBytes_GET_SIZE(encoded)); + if (copy == NULL) { + Py_DECREF(encoded); return PyErr_NoMemory(); - strcpy(copy, s); + } + strcpy(copy, PyBytes_AS_STRING(encoded)); + Py_DECREF(encoded); rl_parse_and_bind(copy); PyMem_Free(copy); /* Free the copy */ Py_RETURN_NONE; @@ -441,17 +461,18 @@ get the ending index of the completion scope"); /* Set the tab-completion word-delimiters that readline uses */ static PyObject * -set_completer_delims(PyObject *self, PyObject *args) +set_completer_delims(PyObject *self, PyObject *string) { char *break_chars; - - if (!PyArg_ParseTuple(args, "s:set_completer_delims", &break_chars)) { + PyObject *encoded = encode(string); + if (encoded == NULL) { return NULL; } /* Keep a reference to the allocated memory in the module state in case some other module modifies rl_completer_word_break_characters (see issue #17289). */ - break_chars = strdup(break_chars); + break_chars = strdup(PyBytes_AS_STRING(encoded)); + Py_DECREF(encoded); if (break_chars) { free(completer_word_break_characters); completer_word_break_characters = break_chars; @@ -531,10 +552,11 @@ static PyObject * py_replace_history(PyObject *self, PyObject *args) { int entry_number; - char *line; + PyObject *line; + PyObject *encoded; HIST_ENTRY *old_entry; - if (!PyArg_ParseTuple(args, "is:replace_history_item", &entry_number, + if (!PyArg_ParseTuple(args, "iU:replace_history_item", &entry_number, &line)) { return NULL; } @@ -543,7 +565,12 @@ py_replace_history(PyObject *self, PyObject *args) "History index cannot be negative"); return NULL; } - old_entry = replace_history_entry(entry_number, line, (void *)NULL); + encoded = encode(line); + if (encoded == NULL) { + return NULL; + } + old_entry = replace_history_entry(entry_number, PyBytes_AS_STRING(encoded), (void *)NULL); + Py_DECREF(encoded); if (!old_entry) { PyErr_Format(PyExc_ValueError, "No history item at position %d", @@ -562,14 +589,14 @@ replaces history item given by its position with contents of line"); /* Add a line to the history buffer */ static PyObject * -py_add_history(PyObject *self, PyObject *args) +py_add_history(PyObject *self, PyObject *string) { - char *line; - - if(!PyArg_ParseTuple(args, "s:add_history", &line)) { + PyObject *encoded = encode(string); + if (encoded == NULL) { return NULL; } - add_history(line); + add_history(PyBytes_AS_STRING(encoded)); + Py_DECREF(encoded); Py_RETURN_NONE; } @@ -583,7 +610,7 @@ add an item to the history buffer"); static PyObject * get_completer_delims(PyObject *self, PyObject *noarg) { - return PyUnicode_FromString(rl_completer_word_break_characters); + return decode(rl_completer_word_break_characters); } PyDoc_STRVAR(doc_get_completer_delims, @@ -673,7 +700,7 @@ get_history_item(PyObject *self, PyObject *args) } #endif /* __APPLE__ */ if ((hist_ent = history_get(idx))) - return PyUnicode_FromString(hist_ent->line); + return decode(hist_ent->line); else { Py_RETURN_NONE; } @@ -702,7 +729,7 @@ return the current (not the maximum) length of history."); static PyObject * get_line_buffer(PyObject *self, PyObject *noarg) { - return PyUnicode_FromString(rl_line_buffer); + return decode(rl_line_buffer); } PyDoc_STRVAR(doc_get_line_buffer, @@ -730,12 +757,14 @@ Clear the current readline history."); /* Exported function to insert text into the line buffer */ static PyObject * -insert_text(PyObject *self, PyObject *args) +insert_text(PyObject *self, PyObject *string) { - char *s; - if (!PyArg_ParseTuple(args, "s:insert_text", &s)) + PyObject *encoded = encode(string); + if (encoded == NULL) { return NULL; - rl_insert_text(s); + } + rl_insert_text(PyBytes_AS_STRING(encoded)); + Py_DECREF(encoded); Py_RETURN_NONE; } @@ -763,9 +792,9 @@ contents of the line buffer."); static struct PyMethodDef readline_methods[] = { - {"parse_and_bind", parse_and_bind, METH_VARARGS, doc_parse_and_bind}, + {"parse_and_bind", parse_and_bind, METH_O, doc_parse_and_bind}, {"get_line_buffer", get_line_buffer, METH_NOARGS, doc_get_line_buffer}, - {"insert_text", insert_text, METH_VARARGS, doc_insert_text}, + {"insert_text", insert_text, METH_O, doc_insert_text}, {"redisplay", redisplay, METH_NOARGS, doc_redisplay}, {"read_init_file", read_init_file, METH_VARARGS, doc_read_init_file}, {"read_history_file", read_history_file, @@ -792,8 +821,8 @@ static struct PyMethodDef readline_methods[] = {"get_endidx", get_endidx, METH_NOARGS, doc_get_endidx}, {"set_completer_delims", set_completer_delims, - METH_VARARGS, doc_set_completer_delims}, - {"add_history", py_add_history, METH_VARARGS, doc_add_history}, + METH_O, doc_set_completer_delims}, + {"add_history", py_add_history, METH_O, doc_add_history}, {"remove_history_item", py_remove_history, METH_VARARGS, doc_remove_history}, {"replace_history_item", py_replace_history, METH_VARARGS, doc_replace_history}, {"get_completer_delims", get_completer_delims, @@ -890,7 +919,7 @@ on_completion_display_matches_hook(char **matches, int num_matches, int max_length) { int i; - PyObject *m=NULL, *s=NULL, *r=NULL; + PyObject *sub, *m=NULL, *s=NULL, *r=NULL; #ifdef WITH_THREAD PyGILState_STATE gilstate = PyGILState_Ensure(); #endif @@ -898,16 +927,17 @@ on_completion_display_matches_hook(char **matches, if (m == NULL) goto error; for (i = 0; i < num_matches; i++) { - s = PyUnicode_FromString(matches[i+1]); + s = decode(matches[i+1]); if (s == NULL) goto error; if (PyList_SetItem(m, i, s) == -1) goto error; } + sub = decode(matches[0]); r = PyObject_CallFunction(readlinestate_global->completion_display_matches_hook, - "sOi", matches[0], m, max_length); + "NNi", sub, m, max_length); - Py_DECREF(m); m=NULL; + m=NULL; if (r == NULL || (r != Py_None && PyLong_AsLong(r) == -1 && PyErr_Occurred())) { @@ -955,22 +985,24 @@ on_completion(const char *text, int state) { char *result = NULL; if (readlinestate_global->completer != NULL) { - PyObject *r; + PyObject *r = NULL, *t; #ifdef WITH_THREAD PyGILState_STATE gilstate = PyGILState_Ensure(); #endif rl_attempted_completion_over = 1; - r = PyObject_CallFunction(readlinestate_global->completer, "si", text, state); + t = decode(text); + r = PyObject_CallFunction(readlinestate_global->completer, "Ni", t, state); if (r == NULL) goto error; if (r == Py_None) { result = NULL; } else { - char *s = _PyUnicode_AsString(r); - if (s == NULL) + PyObject *encoded = encode(r); + if (encoded == NULL) goto error; - result = strdup(s); + result = strdup(PyBytes_AS_STRING(encoded)); + Py_DECREF(encoded); } Py_DECREF(r); goto done; @@ -994,6 +1026,9 @@ static char ** flex_complete(const char *text, int start, int end) { char **result; + char saved; + size_t start_size, end_size; + wchar_t *s; #ifdef WITH_THREAD PyGILState_STATE gilstate = PyGILState_Ensure(); #endif @@ -1003,6 +1038,27 @@ flex_complete(const char *text, int start, int end) #ifdef HAVE_RL_COMPLETION_SUPPRESS_APPEND rl_completion_suppress_append = 0; #endif + + saved = rl_line_buffer[start]; + rl_line_buffer[start] = 0; + s = Py_DecodeLocale(rl_line_buffer, &start_size); + rl_line_buffer[start] = saved; + if (s == NULL) { + goto done; + } + PyMem_RawFree(s); + saved = rl_line_buffer[end]; + rl_line_buffer[end] = 0; + s = Py_DecodeLocale(rl_line_buffer + start, &end_size); + rl_line_buffer[end] = saved; + if (s == NULL) { + goto done; + } + PyMem_RawFree(s); + start = (int)start_size; + end = start + (int)end_size; + +done: Py_XDECREF(readlinestate_global->begidx); Py_XDECREF(readlinestate_global->endidx); readlinestate_global->begidx = PyLong_FromLong((long) start); -- cgit v0.12 From bfb15ab71165ccdf65ed1243e80e7e293999f034 Mon Sep 17 00:00:00 2001 From: Martin Panter Date: Tue, 14 Jun 2016 01:27:11 +0000 Subject: Issue #22636: avoid using a shell in the ctypes.util module Replace os.popen() with subprocess.Popen. Based on patch by Victor Stinner. If the "gcc", "cc" or "objdump" command is not available, the code was supposed to raise an OSError exception. But there was a bug in the code. The shell code returns the exit code 10 if the required command is missing, and the code tries to check for the status 10. The problem is that os.popen() doesn't return the exit code directly, but a status which should be processed by os.WIFEXITED() and os.WEXITSTATUS(). In practice, the exception was never raised. The OSError exception was not documented and ctypes.util.find_library() is expected to return None if the library is not found. --- Lib/ctypes/test/test_find.py | 7 ++- Lib/ctypes/util.py | 119 +++++++++++++++++++++++++++---------------- Misc/NEWS | 3 ++ 3 files changed, 85 insertions(+), 44 deletions(-) diff --git a/Lib/ctypes/test/test_find.py b/Lib/ctypes/test/test_find.py index e6bc19d..20c5337 100644 --- a/Lib/ctypes/test/test_find.py +++ b/Lib/ctypes/test/test_find.py @@ -1,5 +1,5 @@ import unittest -import os +import os, os.path import sys import test.support from ctypes import * @@ -64,6 +64,11 @@ class Test_OpenGL_libs(unittest.TestCase): self.skipTest('lib_gle not available') self.gle.gleGetJoinStyle + def test_shell_injection(self): + result = find_library('; echo Hello shell > ' + test.support.TESTFN) + self.assertFalse(os.path.lexists(test.support.TESTFN)) + self.assertIsNone(result) + # On platforms where the default shared library suffix is '.so', # at least some libraries can be loaded as attributes of the cdll # object, since ctypes now tries loading the lib again diff --git a/Lib/ctypes/util.py b/Lib/ctypes/util.py index 8ff4aff..0b96e59 100644 --- a/Lib/ctypes/util.py +++ b/Lib/ctypes/util.py @@ -1,6 +1,7 @@ -import sys, os -import contextlib +import os +import shutil import subprocess +import sys # find_library(name) returns the pathname of a library, or None. if os.name == "nt": @@ -94,28 +95,43 @@ elif os.name == "posix": import re, tempfile def _findLib_gcc(name): - expr = r'[^\(\)\s]*lib%s\.[^\(\)\s]*' % re.escape(name) - fdout, ccout = tempfile.mkstemp() - os.close(fdout) - cmd = 'if type gcc >/dev/null 2>&1; then CC=gcc; elif type cc >/dev/null 2>&1; then CC=cc;else exit 10; fi;' \ - 'LANG=C LC_ALL=C $CC -Wl,-t -o ' + ccout + ' 2>&1 -l' + name + # Run GCC's linker with the -t (aka --trace) option and examine the + # library name it prints out. The GCC command will fail because we + # haven't supplied a proper program with main(), but that does not + # matter. + expr = os.fsencode(r'[^\(\)\s]*lib%s\.[^\(\)\s]*' % re.escape(name)) + + c_compiler = shutil.which('gcc') + if not c_compiler: + c_compiler = shutil.which('cc') + if not c_compiler: + # No C compiler available, give up + return None + + temp = tempfile.NamedTemporaryFile() try: - f = os.popen(cmd) - try: - trace = f.read() - finally: - rv = f.close() + args = [c_compiler, '-Wl,-t', '-o', temp.name, '-l' + name] + + env = dict(os.environ) + env['LC_ALL'] = 'C' + env['LANG'] = 'C' + proc = subprocess.Popen(args, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + env=env) + with proc: + trace = proc.stdout.read() finally: try: - os.unlink(ccout) + temp.close() except FileNotFoundError: + # Raised if the file was already removed, which is the normal + # behaviour of GCC if linking fails pass - if rv == 10: - raise OSError('gcc or cc command not found') res = re.search(expr, trace) if not res: return None - return res.group(0) + return os.fsdecode(res.group(0)) if sys.platform == "sunos5": @@ -123,55 +139,65 @@ elif os.name == "posix": def _get_soname(f): if not f: return None - cmd = "/usr/ccs/bin/dump -Lpv 2>/dev/null " + f - with contextlib.closing(os.popen(cmd)) as f: - data = f.read() - res = re.search(r'\[.*\]\sSONAME\s+([^\s]+)', data) + + proc = subprocess.Popen(("/usr/ccs/bin/dump", "-Lpv", f), + stdout=subprocess.PIPE, + stderr=subprocess.DEVNULL) + with proc: + data = proc.stdout.read() + res = re.search(br'\[.*\]\sSONAME\s+([^\s]+)', data) if not res: return None - return res.group(1) + return os.fsdecode(res.group(1)) else: def _get_soname(f): # assuming GNU binutils / ELF if not f: return None - cmd = 'if ! type objdump >/dev/null 2>&1; then exit 10; fi;' \ - "objdump -p -j .dynamic 2>/dev/null " + f - f = os.popen(cmd) - try: - dump = f.read() - finally: - rv = f.close() - if rv == 10: - raise OSError('objdump command not found') - res = re.search(r'\sSONAME\s+([^\s]+)', dump) + objdump = shutil.which('objdump') + if not objdump: + # objdump is not available, give up + return None + + proc = subprocess.Popen((objdump, '-p', '-j', '.dynamic', f), + stdout=subprocess.PIPE, + stderr=subprocess.DEVNULL) + with proc: + dump = proc.stdout.read() + res = re.search(br'\sSONAME\s+([^\s]+)', dump) if not res: return None - return res.group(1) + return os.fsdecode(res.group(1)) if sys.platform.startswith(("freebsd", "openbsd", "dragonfly")): def _num_version(libname): # "libxyz.so.MAJOR.MINOR" => [ MAJOR, MINOR ] - parts = libname.split(".") + parts = libname.split(b".") nums = [] try: while parts: nums.insert(0, int(parts.pop())) except ValueError: pass - return nums or [ sys.maxsize ] + return nums or [sys.maxsize] def find_library(name): ename = re.escape(name) expr = r':-l%s\.\S+ => \S*/(lib%s\.\S+)' % (ename, ename) - with contextlib.closing(os.popen('/sbin/ldconfig -r 2>/dev/null')) as f: - data = f.read() + expr = os.fsencode(expr) + + proc = subprocess.Popen(('/sbin/ldconfig', '-r'), + stdout=subprocess.PIPE, + stderr=subprocess.DEVNULL) + with proc: + data = proc.stdout.read() + res = re.findall(expr, data) if not res: return _get_soname(_findLib_gcc(name)) res.sort(key=_num_version) - return res[-1] + return os.fsdecode(res[-1]) elif sys.platform == "sunos5": @@ -179,17 +205,24 @@ elif os.name == "posix": if not os.path.exists('/usr/bin/crle'): return None + env = dict(os.environ) + env['LC_ALL'] = 'C' + if is64: - cmd = 'env LC_ALL=C /usr/bin/crle -64 2>/dev/null' + args = ('/usr/bin/crle', '-64') else: - cmd = 'env LC_ALL=C /usr/bin/crle 2>/dev/null' + args = ('/usr/bin/crle',) paths = None - with contextlib.closing(os.popen(cmd)) as f: - for line in f.readlines(): + proc = subprocess.Popen(args, + stdout=subprocess.PIPE, + stderr=subprocess.DEVNULL, + env=env) + with proc: + for line in proc.stdout: line = line.strip() - if line.startswith('Default Library Path (ELF):'): - paths = line.split()[4] + if line.startswith(b'Default Library Path (ELF):'): + paths = os.fsdecode(line).split()[4] if not paths: return None diff --git a/Misc/NEWS b/Misc/NEWS index 3398a86..14fd247 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,9 @@ Core and Builtins Library ------- +- Issue #22636: Avoid shell injection problems with + ctypes.util.find_library(). + - Issue #16182: Fix various functions in the "readline" module to use the locale encoding, and fix get_begidx() and get_endidx() to return code point indexes. -- cgit v0.12 From e1b3431cef4873b2853199f4b5114de7e26de998 Mon Sep 17 00:00:00 2001 From: Martin Panter Date: Tue, 14 Jun 2016 04:08:30 +0000 Subject: Issue #22636: Handle OSError from subprocess, e.g. if command not found --- Lib/ctypes/util.py | 54 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 35 insertions(+), 19 deletions(-) diff --git a/Lib/ctypes/util.py b/Lib/ctypes/util.py index 0b96e59..7684eab 100644 --- a/Lib/ctypes/util.py +++ b/Lib/ctypes/util.py @@ -115,10 +115,13 @@ elif os.name == "posix": env = dict(os.environ) env['LC_ALL'] = 'C' env['LANG'] = 'C' - proc = subprocess.Popen(args, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - env=env) + try: + proc = subprocess.Popen(args, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + env=env) + except OSError: # E.g. bad executable + return None with proc: trace = proc.stdout.read() finally: @@ -140,9 +143,12 @@ elif os.name == "posix": if not f: return None - proc = subprocess.Popen(("/usr/ccs/bin/dump", "-Lpv", f), - stdout=subprocess.PIPE, - stderr=subprocess.DEVNULL) + try: + proc = subprocess.Popen(("/usr/ccs/bin/dump", "-Lpv", f), + stdout=subprocess.PIPE, + stderr=subprocess.DEVNULL) + except OSError: # E.g. command not found + return None with proc: data = proc.stdout.read() res = re.search(br'\[.*\]\sSONAME\s+([^\s]+)', data) @@ -159,9 +165,12 @@ elif os.name == "posix": # objdump is not available, give up return None - proc = subprocess.Popen((objdump, '-p', '-j', '.dynamic', f), - stdout=subprocess.PIPE, - stderr=subprocess.DEVNULL) + try: + proc = subprocess.Popen((objdump, '-p', '-j', '.dynamic', f), + stdout=subprocess.PIPE, + stderr=subprocess.DEVNULL) + except OSError: # E.g. bad executable + return None with proc: dump = proc.stdout.read() res = re.search(br'\sSONAME\s+([^\s]+)', dump) @@ -187,11 +196,15 @@ elif os.name == "posix": expr = r':-l%s\.\S+ => \S*/(lib%s\.\S+)' % (ename, ename) expr = os.fsencode(expr) - proc = subprocess.Popen(('/sbin/ldconfig', '-r'), - stdout=subprocess.PIPE, - stderr=subprocess.DEVNULL) - with proc: - data = proc.stdout.read() + try: + proc = subprocess.Popen(('/sbin/ldconfig', '-r'), + stdout=subprocess.PIPE, + stderr=subprocess.DEVNULL) + except OSError: # E.g. command not found + data = b'' + else: + with proc: + data = proc.stdout.read() res = re.findall(expr, data) if not res: @@ -214,10 +227,13 @@ elif os.name == "posix": args = ('/usr/bin/crle',) paths = None - proc = subprocess.Popen(args, - stdout=subprocess.PIPE, - stderr=subprocess.DEVNULL, - env=env) + try: + proc = subprocess.Popen(args, + stdout=subprocess.PIPE, + stderr=subprocess.DEVNULL, + env=env) + except OSError: # E.g. bad executable + return None with proc: for line in proc.stdout: line = line.strip() -- cgit v0.12 From ec84417ce88ebd467751c2ed3edd141b4e91cc03 Mon Sep 17 00:00:00 2001 From: Terry Jan Reedy Date: Tue, 14 Jun 2016 00:53:25 -0400 Subject: Issue #27245: IDLE: Cleanly delete custom themes and key bindings. Previously, when IDLE was started from a console or by import, a cascade of warnings was emitted. Patch by Serhiy Storchaka. --- Lib/idlelib/configDialog.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Lib/idlelib/configDialog.py b/Lib/idlelib/configDialog.py index b702253..5f5bd36 100644 --- a/Lib/idlelib/configDialog.py +++ b/Lib/idlelib/configDialog.py @@ -751,6 +751,7 @@ class ConfigDialog(Toplevel): if not tkMessageBox.askyesno( 'Delete Key Set', delmsg % keySetName, parent=self): return + self.DeactivateCurrentConfig() #remove key set from config idleConf.userCfg['keys'].remove_section(keySetName) if keySetName in self.changedItems['keys']: @@ -769,7 +770,8 @@ class ConfigDialog(Toplevel): self.keysAreBuiltin.set(idleConf.defaultCfg['main'].Get('Keys', 'default')) self.builtinKeys.set(idleConf.defaultCfg['main'].Get('Keys', 'name')) #user can't back out of these changes, they must be applied now - self.Apply() + self.SaveAllChangedConfigs() + self.ActivateConfigChanges() self.SetKeysType() def DeleteCustomTheme(self): @@ -778,6 +780,7 @@ class ConfigDialog(Toplevel): if not tkMessageBox.askyesno( 'Delete Theme', delmsg % themeName, parent=self): return + self.DeactivateCurrentConfig() #remove theme from config idleConf.userCfg['highlight'].remove_section(themeName) if themeName in self.changedItems['highlight']: @@ -796,7 +799,8 @@ class ConfigDialog(Toplevel): self.themeIsBuiltin.set(idleConf.defaultCfg['main'].Get('Theme', 'default')) self.builtinTheme.set(idleConf.defaultCfg['main'].Get('Theme', 'name')) #user can't back out of these changes, they must be applied now - self.Apply() + self.SaveAllChangedConfigs() + self.ActivateConfigChanges() self.SetThemeType() def GetColour(self): -- cgit v0.12 From 056f76d9782d54d069b7f6e967705f6fec4b4935 Mon Sep 17 00:00:00 2001 From: Martin Panter Date: Tue, 14 Jun 2016 05:45:31 +0000 Subject: Issue #16182: Attempted workarounds for Apple Editline --- Lib/test/test_readline.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/Lib/test/test_readline.py b/Lib/test/test_readline.py index 34a55b2..51e136c 100644 --- a/Lib/test/test_readline.py +++ b/Lib/test/test_readline.py @@ -15,6 +15,8 @@ from test.support.script_helper import assert_python_ok # Skip tests if there is no readline module readline = import_module('readline') +is_editline = readline.__doc__ and "libedit" in readline.__doc__ + @unittest.skipUnless(hasattr(readline, "clear_history"), "The history update test cannot be run because the " "clear_history method is not available.") @@ -99,14 +101,17 @@ class TestHistoryManipulation (unittest.TestCase): self.addCleanup(os.remove, TESTFN) readline.clear_history() readline.read_history_file(TESTFN) + if is_editline: + # An add_history() call seems to be required for get_history_ + # item() to register items from the file + readline.add_history("dummy") self.assertEqual(readline.get_history_item(1), "entrée 1") self.assertEqual(readline.get_history_item(2), "entrée 22") class TestReadline(unittest.TestCase): - @unittest.skipIf(readline._READLINE_VERSION < 0x0600 - and "libedit" not in readline.__doc__, + @unittest.skipIf(readline._READLINE_VERSION < 0x0600 and not is_editline, "not supported in this library version") def test_init(self): # Issue #19884: Ensure that the ANSI sequence "\033[1034h" is not @@ -127,7 +132,9 @@ class TestReadline(unittest.TestCase): if readline.__doc__ and "libedit" in readline.__doc__: readline.parse_and_bind(r'bind ^B ed-prev-char') readline.parse_and_bind(r'bind "\t" rl_complete') - readline.parse_and_bind('bind -s ^A "|t\xEB[after]"') + # The insert_line() call via pre_input_hook() does nothing with Editline, + # so include the extra text that would have been inserted here + readline.parse_and_bind('bind -s ^A "[\xEFnserted]|t\xEB[after]"') else: readline.parse_and_bind(r'Control-b: backward-char') readline.parse_and_bind(r'"\t": complete') @@ -173,8 +180,9 @@ print("history", ascii(readline.get_history_item(1))) self.assertIn(b"text 't\\xeb'\r\n", output) self.assertIn(b"line '[\\xefnserted]|t\\xeb[after]'\r\n", output) self.assertIn(b"indexes 11 13\r\n", output) - self.assertIn(b"substitution 't\\xeb'\r\n", output) - self.assertIn(b"matches ['t\\xebnt', 't\\xebxt']\r\n", output) + if not is_editline: # display() hook not called under Editline + self.assertIn(b"substitution 't\\xeb'\r\n", output) + self.assertIn(b"matches ['t\\xebnt', 't\\xebxt']\r\n", output) expected = br"'[\xefnserted]|t\xebxt[after]'" self.assertIn(b"result " + expected + b"\r\n", output) self.assertIn(b"history " + expected + b"\r\n", output) -- cgit v0.12 From 06d49bb89584921d17f3309530fc9544ef5b88c3 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Mon, 13 Jun 2016 23:41:19 -0700 Subject: sync ordering of stddef.h includes with expat 2.1.1 --- Modules/expat/xmlrole.c | 4 ++-- Modules/expat/xmltok.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Modules/expat/xmlrole.c b/Modules/expat/xmlrole.c index 9a8f85d..44772e2 100644 --- a/Modules/expat/xmlrole.c +++ b/Modules/expat/xmlrole.c @@ -2,6 +2,8 @@ See the file COPYING for copying permission. */ +#include + #ifdef COMPILED_FROM_DSP #include "winconfig.h" #elif defined(MACOS_CLASSIC) @@ -16,8 +18,6 @@ #endif #endif /* ndef COMPILED_FROM_DSP */ -#include - #include "expat_external.h" #include "internal.h" #include "xmlrole.h" diff --git a/Modules/expat/xmltok.c b/Modules/expat/xmltok.c index 205c07e..bf09dfc 100644 --- a/Modules/expat/xmltok.c +++ b/Modules/expat/xmltok.c @@ -2,6 +2,8 @@ See the file COPYING for copying permission. */ +#include + #ifdef COMPILED_FROM_DSP #include "winconfig.h" #elif defined(MACOS_CLASSIC) @@ -16,8 +18,6 @@ #endif #endif /* ndef COMPILED_FROM_DSP */ -#include - #include "expat_external.h" #include "internal.h" #include "xmltok.h" -- cgit v0.12 From 6afbc653a7bba73ecc56a6ba37632d25376dbe2f Mon Sep 17 00:00:00 2001 From: Martin Panter Date: Tue, 14 Jun 2016 08:45:43 +0000 Subject: Issue #16182: set_pre_input_hook() may not exist; document, and update test --- Doc/library/readline.rst | 7 +++++-- Lib/test/test_readline.py | 22 +++++++++++++++------- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/Doc/library/readline.rst b/Doc/library/readline.rst index e17e69c..4d3c099 100644 --- a/Doc/library/readline.rst +++ b/Doc/library/readline.rst @@ -104,7 +104,9 @@ The following functions operate on a history file: 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. + :c:func:`append_history` in the underlying library. This function + only exists if Python was compiled for a version of the library + that supports it. .. versionadded:: 3.5 @@ -185,7 +187,8 @@ Startup hooks 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. + readline starts reading input characters. This function only exists + if Python was compiled for a version of the library that supports it. Completion diff --git a/Lib/test/test_readline.py b/Lib/test/test_readline.py index 51e136c..b59b6b0 100644 --- a/Lib/test/test_readline.py +++ b/Lib/test/test_readline.py @@ -129,24 +129,32 @@ class TestReadline(unittest.TestCase): script = r"""import readline -if readline.__doc__ and "libedit" in readline.__doc__: - readline.parse_and_bind(r'bind ^B ed-prev-char') - readline.parse_and_bind(r'bind "\t" rl_complete') +is_editline = readline.__doc__ and "libedit" in readline.__doc__ +inserted = "[\xEFnserted]" +macro = "|t\xEB[after]" +set_pre_input_hook = getattr(readline, "set_pre_input_hook", None) +if is_editline or not set_pre_input_hook: # The insert_line() call via pre_input_hook() does nothing with Editline, # so include the extra text that would have been inserted here - readline.parse_and_bind('bind -s ^A "[\xEFnserted]|t\xEB[after]"') + macro = inserted + macro + +if is_editline: + readline.parse_and_bind(r'bind ^B ed-prev-char') + readline.parse_and_bind(r'bind "\t" rl_complete') + readline.parse_and_bind(r'bind -s ^A "{}"'.format(macro)) else: readline.parse_and_bind(r'Control-b: backward-char') readline.parse_and_bind(r'"\t": complete') readline.parse_and_bind(r'set disable-completion off') readline.parse_and_bind(r'set show-all-if-ambiguous off') readline.parse_and_bind(r'set show-all-if-unmodified off') - readline.parse_and_bind('Control-a: "|t\xEB[after]"') + readline.parse_and_bind(r'Control-a: "{}"'.format(macro)) def pre_input_hook(): - readline.insert_text("[\xEFnserted]") + readline.insert_text(inserted) readline.redisplay() -readline.set_pre_input_hook(pre_input_hook) +if set_pre_input_hook: + set_pre_input_hook(pre_input_hook) def completer(text, state): if text == "t\xEB": -- cgit v0.12 From 8e6d09c1ccb5fed0d1b074aae9325f41fed4705d Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Tue, 14 Jun 2016 12:33:31 +0300 Subject: Issue #26386: Fixed ttk.TreeView selection operations with item id's containing spaces. --- Lib/tkinter/test/test_ttk/test_widgets.py | 51 +++++++++++++++++++++++++++++++ Lib/tkinter/ttk.py | 4 ++- Misc/NEWS | 3 ++ 3 files changed, 57 insertions(+), 1 deletion(-) diff --git a/Lib/tkinter/test/test_ttk/test_widgets.py b/Lib/tkinter/test/test_ttk/test_widgets.py index c031351..8bd22d0 100644 --- a/Lib/tkinter/test/test_ttk/test_widgets.py +++ b/Lib/tkinter/test/test_ttk/test_widgets.py @@ -1486,6 +1486,57 @@ class TreeviewTest(AbstractWidgetTest, unittest.TestCase): value) + def test_selection(self): + # item 'none' doesn't exist + self.assertRaises(tkinter.TclError, self.tv.selection_set, 'none') + self.assertRaises(tkinter.TclError, self.tv.selection_add, 'none') + self.assertRaises(tkinter.TclError, self.tv.selection_remove, 'none') + self.assertRaises(tkinter.TclError, self.tv.selection_toggle, 'none') + + item1 = self.tv.insert('', 'end') + item2 = self.tv.insert('', 'end') + c1 = self.tv.insert(item1, 'end') + c2 = self.tv.insert(item1, 'end') + c3 = self.tv.insert(item1, 'end') + self.assertEqual(self.tv.selection(), ()) + + self.tv.selection_set((c1, item2)) + self.assertEqual(self.tv.selection(), (c1, item2)) + self.tv.selection_set(c2) + self.assertEqual(self.tv.selection(), (c2,)) + + self.tv.selection_add((c1, item2)) + self.assertEqual(self.tv.selection(), (c1, c2, item2)) + self.tv.selection_add(item1) + self.assertEqual(self.tv.selection(), (item1, c1, c2, item2)) + + self.tv.selection_remove((item1, c3)) + self.assertEqual(self.tv.selection(), (c1, c2, item2)) + self.tv.selection_remove(c2) + self.assertEqual(self.tv.selection(), (c1, item2)) + + self.tv.selection_toggle((c1, c3)) + self.assertEqual(self.tv.selection(), (c3, item2)) + self.tv.selection_toggle(item2) + self.assertEqual(self.tv.selection(), (c3,)) + + self.tv.insert('', 'end', id='with spaces') + self.tv.selection_set('with spaces') + self.assertEqual(self.tv.selection(), ('with spaces',)) + + self.tv.insert('', 'end', id='{brace') + self.tv.selection_set('{brace') + self.assertEqual(self.tv.selection(), ('{brace',)) + + self.tv.insert('', 'end', id='unicode\u20ac') + self.tv.selection_set('unicode\u20ac') + self.assertEqual(self.tv.selection(), ('unicode\u20ac',)) + + self.tv.insert('', 'end', id=b'bytes\xe2\x82\xac') + self.tv.selection_set(b'bytes\xe2\x82\xac') + self.assertEqual(self.tv.selection(), ('bytes\xe2\x82\xac',)) + + def test_set(self): self.tv['columns'] = ['A', 'B'] item = self.tv.insert('', 'end', values=['a', 'b']) diff --git a/Lib/tkinter/ttk.py b/Lib/tkinter/ttk.py index 8f9369b..0e5759d 100644 --- a/Lib/tkinter/ttk.py +++ b/Lib/tkinter/ttk.py @@ -1392,7 +1392,9 @@ class Treeview(Widget, tkinter.XView, tkinter.YView): def selection(self, selop=None, items=None): """If selop is not specified, returns selected items.""" - return self.tk.call(self._w, "selection", selop, items) + if isinstance(items, (str, bytes)): + items = (items,) + return self.tk.splitlist(self.tk.call(self._w, "selection", selop, items)) def selection_set(self, items): diff --git a/Misc/NEWS b/Misc/NEWS index 14fd247..eb810d0 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,9 @@ Core and Builtins Library ------- +- Issue #26386: Fixed ttk.TreeView selection operations with item id's + containing spaces. + - Issue #22636: Avoid shell injection problems with ctypes.util.find_library(). -- cgit v0.12 From 48b13f042746d4c8bf369877e3f40c3e0bbee1b7 Mon Sep 17 00:00:00 2001 From: Berker Peksag Date: Tue, 14 Jun 2016 12:51:07 +0300 Subject: Delete outdated paragraph about OptimizedUnicode again sqlite3.OptimizedUnicode is an alias for str in Python 3 and its behavior is already tested in CheckOptimizedUnicode in Lib/sqlite3/test/factory.py. sqlite3.OptimizedUnicode was undocumented in 0fc10a33eb4c and probably added back with the result of a bad merge. --- Doc/library/sqlite3.rst | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Doc/library/sqlite3.rst b/Doc/library/sqlite3.rst index ae4c7c4..605d8d3 100644 --- a/Doc/library/sqlite3.rst +++ b/Doc/library/sqlite3.rst @@ -489,10 +489,6 @@ Connection Objects :mod:`sqlite3` module will return Unicode objects for ``TEXT``. If you want to return bytestrings instead, you can set it to :class:`bytes`. - For efficiency reasons, there's also a way to return :class:`str` objects - only for non-ASCII data, and :class:`bytes` otherwise. To activate it, set - this attribute to :const:`sqlite3.OptimizedUnicode`. - You can also set it to any other callable that accepts a single bytestring parameter and returns the resulting object. -- cgit v0.12 From 2b50899a28c6fa860f4654224dbdf60c47c72821 Mon Sep 17 00:00:00 2001 From: Berker Peksag Date: Tue, 14 Jun 2016 13:25:11 +0300 Subject: Remove empty setUp and tearDown methods from sqlite3 tests They are not used as base classes by another tests so they can safely be removed. --- Lib/sqlite3/test/dbapi.py | 12 ------------ Lib/sqlite3/test/hooks.py | 6 ------ 2 files changed, 18 deletions(-) diff --git a/Lib/sqlite3/test/dbapi.py b/Lib/sqlite3/test/dbapi.py index 903e599..d9c3228 100644 --- a/Lib/sqlite3/test/dbapi.py +++ b/Lib/sqlite3/test/dbapi.py @@ -695,12 +695,6 @@ class ExtensionTests(unittest.TestCase): self.assertEqual(result, 5, "Basic test of Connection.executescript") class ClosedConTests(unittest.TestCase): - def setUp(self): - pass - - def tearDown(self): - pass - def CheckClosedConCursor(self): con = sqlite.connect(":memory:") con.close() @@ -768,12 +762,6 @@ class ClosedConTests(unittest.TestCase): con() class ClosedCurTests(unittest.TestCase): - def setUp(self): - pass - - def tearDown(self): - pass - def CheckClosed(self): con = sqlite.connect(":memory:") cur = con.cursor() diff --git a/Lib/sqlite3/test/hooks.py b/Lib/sqlite3/test/hooks.py index de69569..cafff93 100644 --- a/Lib/sqlite3/test/hooks.py +++ b/Lib/sqlite3/test/hooks.py @@ -25,12 +25,6 @@ import unittest import sqlite3 as sqlite class CollationTests(unittest.TestCase): - def setUp(self): - pass - - def tearDown(self): - pass - def CheckCreateCollationNotCallable(self): con = sqlite.connect(":memory:") with self.assertRaises(TypeError) as cm: -- cgit v0.12 From f85bce74db9198498f394cf3b12e3c9edab9fc09 Mon Sep 17 00:00:00 2001 From: Berker Peksag Date: Tue, 14 Jun 2016 14:19:02 +0300 Subject: Mark tests as skipped when a SQLite version is not supported --- Lib/sqlite3/test/dbapi.py | 4 ++-- Lib/sqlite3/test/regression.py | 3 +-- Lib/sqlite3/test/transactions.py | 12 ++++-------- Lib/sqlite3/test/types.py | 6 ++---- 4 files changed, 9 insertions(+), 16 deletions(-) diff --git a/Lib/sqlite3/test/dbapi.py b/Lib/sqlite3/test/dbapi.py index d9c3228..ec42eb7 100644 --- a/Lib/sqlite3/test/dbapi.py +++ b/Lib/sqlite3/test/dbapi.py @@ -177,9 +177,9 @@ class ConnectionTests(unittest.TestCase): with self.assertRaises(sqlite.OperationalError): cx.execute('insert into test(id) values(1)') + @unittest.skipIf(sqlite.sqlite_version_info >= (3, 3, 1), + 'needs sqlite versions older than 3.3.1') def CheckSameThreadErrorOnOldVersion(self): - if sqlite.sqlite_version_info >= (3, 3, 1): - self.skipTest('test needs sqlite3 versions older than 3.3.1') with self.assertRaises(sqlite.NotSupportedError) as cm: sqlite.connect(':memory:', check_same_thread=False) self.assertEqual(str(cm.exception), 'shared connections not available') diff --git a/Lib/sqlite3/test/regression.py b/Lib/sqlite3/test/regression.py index 0cf9002..44974b0 100644 --- a/Lib/sqlite3/test/regression.py +++ b/Lib/sqlite3/test/regression.py @@ -84,9 +84,8 @@ class RegressionTests(unittest.TestCase): cur.execute("select 1 x union select " + str(i)) con.close() + @unittest.skipIf(sqlite.sqlite_version_info < (3, 2, 2), 'needs sqlite 3.2.2 or newer') def CheckOnConflictRollback(self): - if sqlite.sqlite_version_info < (3, 2, 2): - return con = sqlite.connect(":memory:") con.execute("create table foo(x, unique(x) on conflict rollback)") con.execute("insert into foo(x) values (1)") diff --git a/Lib/sqlite3/test/transactions.py b/Lib/sqlite3/test/transactions.py index eae26c4..a25360a 100644 --- a/Lib/sqlite3/test/transactions.py +++ b/Lib/sqlite3/test/transactions.py @@ -111,25 +111,21 @@ class TransactionTests(unittest.TestCase): res = self.cur2.fetchall() self.assertEqual(len(res), 1) + @unittest.skipIf(sqlite.sqlite_version_info < (3, 2, 2), + 'test hangs on sqlite versions older than 3.2.2') def CheckRaiseTimeout(self): - if sqlite.sqlite_version_info < (3, 2, 2): - # This will fail (hang) on earlier versions of sqlite. - # Determine exact version it was fixed. 3.2.1 hangs. - return self.cur1.execute("create table test(i)") self.cur1.execute("insert into test(i) values (5)") with self.assertRaises(sqlite.OperationalError): self.cur2.execute("insert into test(i) values (5)") + @unittest.skipIf(sqlite.sqlite_version_info < (3, 2, 2), + 'test hangs on sqlite versions older than 3.2.2') def CheckLocking(self): """ This tests the improved concurrency with pysqlite 2.3.4. You needed to roll back con2 before you could commit con1. """ - if sqlite.sqlite_version_info < (3, 2, 2): - # This will fail (hang) on earlier versions of sqlite. - # Determine exact version it was fixed. 3.2.1 hangs. - return self.cur1.execute("create table test(i)") self.cur1.execute("insert into test(i) values (5)") with self.assertRaises(sqlite.OperationalError): diff --git a/Lib/sqlite3/test/types.py b/Lib/sqlite3/test/types.py index f7c8f9c..6667bc8 100644 --- a/Lib/sqlite3/test/types.py +++ b/Lib/sqlite3/test/types.py @@ -340,11 +340,9 @@ class DateTimeTests(unittest.TestCase): ts2 = self.cur.fetchone()[0] self.assertEqual(ts, ts2) + @unittest.skipIf(sqlite.sqlite_version_info < (3, 1), + 'the date functions are available on 3.1 or later') def CheckSqlTimestamp(self): - # The date functions are only available in SQLite version 3.1 or later - if sqlite.sqlite_version_info < (3, 1): - return - # SQLite's current_timestamp uses UTC time, while datetime.datetime.now() uses local time. now = datetime.datetime.now() self.cur.execute("insert into test(ts) values (current_timestamp)") -- cgit v0.12 From a8cadb2243759498dfc6b41c8cb29228d8b96f5d Mon Sep 17 00:00:00 2001 From: Martin Panter Date: Tue, 14 Jun 2016 11:29:31 +0000 Subject: Issue #16182: One more check for set_pre_input_hook() --- Lib/test/test_readline.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_readline.py b/Lib/test/test_readline.py index b59b6b0..8c2ad85 100644 --- a/Lib/test/test_readline.py +++ b/Lib/test/test_readline.py @@ -188,7 +188,7 @@ print("history", ascii(readline.get_history_item(1))) self.assertIn(b"text 't\\xeb'\r\n", output) self.assertIn(b"line '[\\xefnserted]|t\\xeb[after]'\r\n", output) self.assertIn(b"indexes 11 13\r\n", output) - if not is_editline: # display() hook not called under Editline + if not is_editline and hasattr(readline, "set_pre_input_hook"): self.assertIn(b"substitution 't\\xeb'\r\n", output) self.assertIn(b"matches ['t\\xebnt', 't\\xebxt']\r\n", output) expected = br"'[\xefnserted]|t\xebxt[after]'" -- cgit v0.12 From fd7f19ea67b0585929e723303c40de9153bba91d Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 14 Jun 2016 15:04:44 +0200 Subject: Issue #25843: Fix the NEWS entry --- Misc/NEWS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS b/Misc/NEWS index eb810d0..e132b96 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -124,7 +124,7 @@ Core and Builtins - 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`` + (``int``) and ``f2()`` returns ``1.0`` (``float``), even if ``1`` and ``1.0`` are equal. - Issue #22995: [UPDATE] Comment out the one of the pickleability tests in -- cgit v0.12 From b98a36e8f3006512f0fa4d94309fb9918eb8abdd Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 14 Jun 2016 16:31:35 +0200 Subject: Fix os.urandom() using getrandom() on Linux Issue #27278: Fix os.urandom() implementation using getrandom() on Linux. Truncate size to INT_MAX and loop until we collected enough random bytes, instead of casting a directly Py_ssize_t to int. --- Misc/NEWS | 4 ++++ Python/random.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Misc/NEWS b/Misc/NEWS index e132b96..7940cdc 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,10 @@ Core and Builtins Library ------- +- Issue #27278: Fix os.urandom() implementation using getrandom() on Linux. + Truncate size to INT_MAX and loop until we collected enough random bytes, + instead of casting a directly Py_ssize_t to int. + - Issue #26386: Fixed ttk.TreeView selection operations with item id's containing spaces. diff --git a/Python/random.c b/Python/random.c index 07dacfe..b961020 100644 --- a/Python/random.c +++ b/Python/random.c @@ -143,7 +143,7 @@ py_getrandom(void *buffer, Py_ssize_t size, int raise) to 1024 bytes */ n = Py_MIN(size, 1024); #else - n = size; + n = Py_MIN(size, INT_MAX); #endif errno = 0; -- cgit v0.12 From c72828ba3377a2139f36b8fdc9b0cbd5dd798712 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 14 Jun 2016 16:35:49 +0200 Subject: cleanup random.c Casting Py_ssize_t to Py_ssize_t is useless. --- Python/random.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Python/random.c b/Python/random.c index b961020..8ce0b3e 100644 --- a/Python/random.c +++ b/Python/random.c @@ -251,7 +251,7 @@ dev_urandom_noraise(unsigned char *buffer, Py_ssize_t size) break; } buffer += n; - size -= (Py_ssize_t)n; + size -= n; } close(fd); } -- cgit v0.12 From ba2ecd68414b9c53d00560579f5bc13459bc0449 Mon Sep 17 00:00:00 2001 From: "Gregory P. Smith" Date: Tue, 14 Jun 2016 09:19:20 -0700 Subject: Issue #27123: When an exception is raised within the context being managed by a contextlib.ExitStack() and one of the exit stack generators catches and raises it in a chain, do not re-raise the original exception when exiting, let the new chained one through. This avoids the PEP 479 bug described in issue25782. --- Lib/contextlib.py | 3 +++ Lib/test/test_contextlib.py | 28 ++++++++++++++++++++++++++++ Misc/NEWS | 6 ++++++ 3 files changed, 37 insertions(+) diff --git a/Lib/contextlib.py b/Lib/contextlib.py index 5377987..d44edd6 100644 --- a/Lib/contextlib.py +++ b/Lib/contextlib.py @@ -82,6 +82,9 @@ class _GeneratorContextManager(ContextDecorator): # raised inside the "with" statement from being suppressed. return exc is not value except RuntimeError as exc: + # Don't re-raise the passed in exception. (issue27112) + if exc is value: + return False # Likewise, avoid suppressing if a StopIteration exception # was passed to throw() and later wrapped into a RuntimeError # (see PEP 479). diff --git a/Lib/test/test_contextlib.py b/Lib/test/test_contextlib.py index 30a6377..a246c43 100644 --- a/Lib/test/test_contextlib.py +++ b/Lib/test/test_contextlib.py @@ -762,6 +762,34 @@ class TestExitStack(unittest.TestCase): stack.push(cm) self.assertIs(stack._exit_callbacks[-1], cm) + def test_dont_reraise_RuntimeError(self): + """https://bugs.python.org/issue27122""" + class UniqueException(Exception): pass + + @contextmanager + def second(): + try: + yield 1 + except Exception as exc: + raise UniqueException("new exception") from exc + + @contextmanager + def first(): + try: + yield 1 + except Exception as exc: + raise exc + + # The RuntimeError should be caught by second()'s exception + # handler which chain raised a new UniqueException. + with self.assertRaises(UniqueException) as err_ctx: + with ExitStack() as es_ctx: + es_ctx.enter_context(second()) + es_ctx.enter_context(first()) + raise RuntimeError("please no infinite loop.") + + self.assertEqual(err_ctx.exception.args[0], "new exception") + class TestRedirectStream: diff --git a/Misc/NEWS b/Misc/NEWS index 7940cdc..c85f6d0 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,12 @@ Core and Builtins Library ------- +- Issue #27123: When an exception is raised within the context being managed + by a contextlib.ExitStack() and one of the exit stack generators + catches and raises it in a chain, do not re-raise the original exception + when exiting, let the new chained one through. This avoids the PEP 479 + bug described in issue25782. + - Issue #27278: Fix os.urandom() implementation using getrandom() on Linux. Truncate size to INT_MAX and loop until we collected enough random bytes, instead of casting a directly Py_ssize_t to int. -- cgit v0.12 From fcbe337fefc00ace11e3c6b91ba790d7c3778ee8 Mon Sep 17 00:00:00 2001 From: "Gregory P. Smith" Date: Tue, 14 Jun 2016 09:27:44 -0700 Subject: issue27122: fix typo in the news file, wrong issue #. not issue27123. --- Misc/NEWS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS b/Misc/NEWS index c85f6d0..71dbb16 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,7 +13,7 @@ Core and Builtins Library ------- -- Issue #27123: When an exception is raised within the context being managed +- Issue #27122: When an exception is raised within the context being managed by a contextlib.ExitStack() and one of the exit stack generators catches and raises it in a chain, do not re-raise the original exception when exiting, let the new chained one through. This avoids the PEP 479 -- cgit v0.12 From cefa9172a237a56c67e8c9b302c84c1c3dffb871 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Tue, 14 Jun 2016 22:52:04 +0300 Subject: Issue #27238: Got rid of bare excepts in the turtle module. Original patch by Jelle Zijlstra. --- Lib/turtle.py | 18 +++++++++--------- Misc/ACKS | 1 + Misc/NEWS | 3 +++ 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/Lib/turtle.py b/Lib/turtle.py index cbd4f47..57cf3d9 100644 --- a/Lib/turtle.py +++ b/Lib/turtle.py @@ -179,7 +179,7 @@ def config_dict(filename): continue try: key, value = line.split("=") - except: + except ValueError: print("Bad line in config-file %s:\n%s" % (filename,line)) continue key = key.strip() @@ -192,7 +192,7 @@ def config_dict(filename): value = float(value) else: value = int(value) - except: + except ValueError: pass # value need not be converted cfgdict[key] = value return cfgdict @@ -220,7 +220,7 @@ def readconfig(cfgdict): try: head, tail = split(__file__) cfg_file2 = join(head, default_cfg) - except: + except Exception: cfg_file2 = "" if isfile(cfg_file2): cfgdict2 = config_dict(cfg_file2) @@ -229,7 +229,7 @@ def readconfig(cfgdict): try: readconfig(_CFG) -except: +except Exception: print ("No configfile read, reason unknown") @@ -653,7 +653,7 @@ class TurtleScreenBase(object): x, y = (self.cv.canvasx(event.x)/self.xscale, -self.cv.canvasy(event.y)/self.yscale) fun(x, y) - except: + except Exception: pass self.cv.tag_bind(item, "" % num, eventfun, add) @@ -1158,7 +1158,7 @@ class TurtleScreen(TurtleScreenBase): raise TurtleGraphicsError("bad color string: %s" % str(color)) try: r, g, b = color - except: + except (TypeError, ValueError): raise TurtleGraphicsError("bad color arguments: %s" % str(color)) if self._colormode == 1.0: r, g, b = [round(255.0*x) for x in (r, g, b)] @@ -2702,7 +2702,7 @@ class RawTurtle(TPen, TNavigator): return args try: r, g, b = args - except: + except (TypeError, ValueError): raise TurtleGraphicsError("bad color arguments: %s" % str(args)) if self.screen._colormode == 1.0: r, g, b = [round(255.0*x) for x in (r, g, b)] @@ -3865,7 +3865,7 @@ def read_docstrings(lang): try: # eval(key).im_func.__doc__ = docsdict[key] eval(key).__doc__ = docsdict[key] - except: + except Exception: print("Bad docstring-entry: %s" % key) _LANGUAGE = _CFG["language"] @@ -3875,7 +3875,7 @@ try: read_docstrings(_LANGUAGE) except ImportError: print("Cannot find docsdict for", _LANGUAGE) -except: +except Exception: print ("Unknown Error when trying to import %s-docstring-dictionary" % _LANGUAGE) diff --git a/Misc/ACKS b/Misc/ACKS index 632c85c..27bd691 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1655,6 +1655,7 @@ Uwe Zessin Cheng Zhang Kai Zhu Tarek Ziadé +Jelle Zijlstra Gennadiy Zlobin Doug Zongker Peter Åstrand diff --git a/Misc/NEWS b/Misc/NEWS index 71dbb16..d81a374 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,9 @@ Core and Builtins Library ------- +- Issue #27238: Got rid of bare excepts in the turtle module. Original patch + by Jelle Zijlstra. + - Issue #27122: When an exception is raised within the context being managed by a contextlib.ExitStack() and one of the exit stack generators catches and raises it in a chain, do not re-raise the original exception -- cgit v0.12 From 71e86367e090a0d0595a4221c8334d87979488e6 Mon Sep 17 00:00:00 2001 From: Martin Panter Date: Wed, 15 Jun 2016 00:24:34 +0000 Subject: Issue #27311: Fix ZipFile.writestr data argument name. Patch by John Hagen. --- Doc/library/zipfile.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/zipfile.rst b/Doc/library/zipfile.rst index b421ea5..a773769 100644 --- a/Doc/library/zipfile.rst +++ b/Doc/library/zipfile.rst @@ -343,9 +343,9 @@ ZipFile Objects If ``arcname`` (or ``filename``, if ``arcname`` is not given) contains a null byte, the name of the file in the archive will be truncated at the null byte. -.. method:: ZipFile.writestr(zinfo_or_arcname, bytes[, compress_type]) +.. method:: ZipFile.writestr(zinfo_or_arcname, data[, compress_type]) - Write the string *bytes* to the archive; *zinfo_or_arcname* is either the file + Write the string *data* to the archive; *zinfo_or_arcname* is either the file name it will be given in the archive, or a :class:`ZipInfo` instance. If it's an instance, at least the filename, date, and time must be given. If it's a name, the date and time is set to the current date and time. -- cgit v0.12 From 4b9e75ba7f5d2f0baf0603eed9b4029af8e82ff3 Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Wed, 15 Jun 2016 08:57:32 +0200 Subject: Docs: add html-stable autobuild variant --- Doc/Makefile | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Doc/Makefile b/Doc/Makefile index ea30231..2220d92 100644 --- a/Doc/Makefile +++ b/Doc/Makefile @@ -161,7 +161,7 @@ autobuild-dev: -make suspicious # for quick rebuilds (HTML only) -autobuild-html: +autobuild-dev-html: make html SPHINXOPTS='-A daily=1 -A versionswitcher=1' # for stable releases: only build if not in pre-release stage (alpha, beta) @@ -173,3 +173,9 @@ autobuild-stable: esac @make autobuild-dev +autobuild-stable-html: + @case $(DISTVERSION) in *[ab]*) \ + echo "Not building; $(DISTVERSION) is not a release version."; \ + exit 1;; \ + esac + @make autobuild-dev-html -- cgit v0.12 From 33e7ca78f919e1a85e28934616e71d65da9368e0 Mon Sep 17 00:00:00 2001 From: Berker Peksag Date: Wed, 15 Jun 2016 18:12:49 +0300 Subject: Make faq/general.rst gender-inclusive, patch by Sam Hathaway. --- Doc/faq/general.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/faq/general.rst b/Doc/faq/general.rst index 6b773dd..3f96700 100644 --- a/Doc/faq/general.rst +++ b/Doc/faq/general.rst @@ -438,7 +438,7 @@ remember the methods for a list, they can do something like this:: >>> L [1] -With the interpreter, documentation is never far from the student as he's +With the interpreter, documentation is never far from the student as they are programming. There are also good IDEs for Python. IDLE is a cross-platform IDE for Python -- cgit v0.12 From 694de3bff7f50eb8f5b3d2460c50825fa66c46c8 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Wed, 15 Jun 2016 20:06:07 +0300 Subject: Issue #27301: Fixed incorrect return codes for errors in compile.c. --- Python/compile.c | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/Python/compile.c b/Python/compile.c index 0c4a6c8..ce510aa 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -1494,6 +1494,9 @@ static int compiler_visit_kwonlydefaults(struct compiler *c, asdl_seq *kwonlyargs, asdl_seq *kw_defaults) { + /* Return the number of defaults + 1. + Returns 0 on error. + */ int i, default_count = 0; for (i = 0; i < asdl_seq_LEN(kwonlyargs); i++) { arg_ty arg = asdl_seq_GET(kwonlyargs, i); @@ -1501,16 +1504,16 @@ compiler_visit_kwonlydefaults(struct compiler *c, asdl_seq *kwonlyargs, if (default_) { PyObject *mangled = _Py_Mangle(c->u->u_private, arg->arg); if (!mangled) - return -1; + return 0; ADDOP_O(c, LOAD_CONST, mangled, consts); Py_DECREF(mangled); if (!compiler_visit_expr(c, default_)) { - return -1; + return 0; } default_count++; } } - return default_count; + return default_count + 1; } static int @@ -1554,17 +1557,17 @@ compiler_visit_annotations(struct compiler *c, arguments_ty args, expr_ty returns) { /* Push arg annotations and a list of the argument names. Return the # - of items pushed. The expressions are evaluated out-of-order wrt the + of items pushed + 1. The expressions are evaluated out-of-order wrt the source code. - More than 2^16-1 annotations is a SyntaxError. Returns -1 on error. + More than 2^16-1 annotations is a SyntaxError. Returns 0 on error. */ static identifier return_str; PyObject *names; Py_ssize_t len; names = PyList_New(0); if (!names) - return -1; + return 0; if (!compiler_visit_argannotations(c, args->args, names)) goto error; @@ -1614,11 +1617,11 @@ compiler_visit_annotations(struct compiler *c, arguments_ty args, Py_DECREF(names); /* We just checked that len <= 65535, see above */ - return Py_SAFE_DOWNCAST(len, Py_ssize_t, int); + return Py_SAFE_DOWNCAST(len + 1, Py_ssize_t, int); error: Py_DECREF(names); - return -1; + return 0; } static int @@ -1667,13 +1670,14 @@ compiler_function(struct compiler *c, stmt_ty s, int is_async) if (args->kwonlyargs) { int res = compiler_visit_kwonlydefaults(c, args->kwonlyargs, args->kw_defaults); - if (res < 0) + if (res == 0) return 0; - kw_default_count = res; + kw_default_count = res - 1; } num_annotations = compiler_visit_annotations(c, args, returns); - if (num_annotations < 0) + if (num_annotations == 0) return 0; + num_annotations--; assert((num_annotations & 0xFFFF) == num_annotations); if (!compiler_enter_scope(c, name, @@ -1889,8 +1893,8 @@ compiler_lambda(struct compiler *c, expr_ty e) if (args->kwonlyargs) { int res = compiler_visit_kwonlydefaults(c, args->kwonlyargs, args->kw_defaults); - if (res < 0) return 0; - kw_default_count = res; + if (res == 0) return 0; + kw_default_count = res - 1; } if (!compiler_enter_scope(c, name, COMPILER_SCOPE_LAMBDA, (void *)e, e->lineno)) @@ -2403,7 +2407,7 @@ compiler_import_as(struct compiler *c, identifier name, identifier asname) Py_ssize_t dot = PyUnicode_FindChar(name, '.', 0, PyUnicode_GET_LENGTH(name), 1); if (dot == -2) - return -1; + return 0; if (dot != -1) { /* Consume the base module name to get the first attribute */ Py_ssize_t pos = dot + 1; @@ -2412,12 +2416,12 @@ compiler_import_as(struct compiler *c, identifier name, identifier asname) dot = PyUnicode_FindChar(name, '.', pos, PyUnicode_GET_LENGTH(name), 1); if (dot == -2) - return -1; + return 0; attr = PyUnicode_Substring(name, pos, (dot != -1) ? dot : PyUnicode_GET_LENGTH(name)); if (!attr) - return -1; + return 0; ADDOP_O(c, LOAD_ATTR, attr, names); Py_DECREF(attr); pos = dot + 1; -- cgit v0.12 From dccc5edfa15890fb17afda19ab40b33810afab83 Mon Sep 17 00:00:00 2001 From: Ned Deily Date: Wed, 15 Jun 2016 18:06:32 -0400 Subject: Issue #27327: fix doc typo, noted by Jakub Wilk. --- Doc/library/re.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/re.rst b/Doc/library/re.rst index 18d5596..569b522 100644 --- a/Doc/library/re.rst +++ b/Doc/library/re.rst @@ -443,7 +443,7 @@ three digits in length. The ``'\u'`` and ``'\U'`` escape sequences have been added. .. deprecated-removed:: 3.5 3.6 - Unknown escapes consist of ``'\'`` and ASCII letter now raise a + Unknown escapes consisting of ``'\'`` and ASCII letter now raise a deprecation warning and will be forbidden in Python 3.6. -- cgit v0.12 From f88d83b922d3525ec65dbfe03e27f197ef1a9021 Mon Sep 17 00:00:00 2001 From: Zachary Ware Date: Wed, 15 Jun 2016 17:13:28 -0500 Subject: Issue #26930: Update Windows build to OpenSSL 1.0.2h --- Misc/NEWS | 1 + PCbuild/get_externals.bat | 2 +- PCbuild/python.props | 2 +- PCbuild/readme.txt | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS index d81a374..fe847b4 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -36,6 +36,7 @@ Library locale encoding, and fix get_begidx() and get_endidx() to return code point indexes. +- Issue #26930: Update Windows builds to use OpenSSL 1.0.2h. What's New in Python 3.5.2 final? ================================= diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat index 63ba282..9b2a084 100644 --- a/PCbuild/get_externals.bat +++ b/PCbuild/get_externals.bat @@ -54,7 +54,7 @@ echo.Fetching external libraries... set libraries= set libraries=%libraries% bzip2-1.0.6 if NOT "%IncludeSSL%"=="false" set libraries=%libraries% nasm-2.11.06 -if NOT "%IncludeSSL%"=="false" set libraries=%libraries% openssl-1.0.2g +if NOT "%IncludeSSL%"=="false" set libraries=%libraries% openssl-1.0.2h set libraries=%libraries% sqlite-3.8.11.0 if NOT "%IncludeTkinter%"=="false" set libraries=%libraries% tcl-core-8.6.4.2 if NOT "%IncludeTkinter%"=="false" set libraries=%libraries% tk-8.6.4.2 diff --git a/PCbuild/python.props b/PCbuild/python.props index 07acfab..843771d 100644 --- a/PCbuild/python.props +++ b/PCbuild/python.props @@ -41,7 +41,7 @@ $(ExternalsDir)sqlite-3.8.11.0\ $(ExternalsDir)bzip2-1.0.6\ $(ExternalsDir)xz-5.0.5\ - $(ExternalsDir)openssl-1.0.2g\ + $(ExternalsDir)openssl-1.0.2h\ $(opensslDir)include32 $(opensslDir)include64 $(ExternalsDir)\nasm-2.11.06\ diff --git a/PCbuild/readme.txt b/PCbuild/readme.txt index e68cc5c..d45eb27 100644 --- a/PCbuild/readme.txt +++ b/PCbuild/readme.txt @@ -169,7 +169,7 @@ _lzma Homepage: http://tukaani.org/xz/ _ssl - Python wrapper for version 1.0.2g of the OpenSSL secure sockets + Python wrapper for version 1.0.2h of the OpenSSL secure sockets library, which is built by ssl.vcxproj Homepage: http://www.openssl.org/ -- cgit v0.12 From adef6460d73ce1ab33af9c9ef014aa88f23c6d62 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Thu, 16 Jun 2016 22:08:46 +0300 Subject: Issue #27330: Fixed possible leaks in the ctypes module. --- Misc/NEWS | 2 ++ Modules/_ctypes/_ctypes.c | 25 +++++++++++++++++++------ Modules/_ctypes/callproc.c | 8 +++++++- Modules/_ctypes/cfield.c | 20 +++++--------------- 4 files changed, 33 insertions(+), 22 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS index fe847b4..66a95f7 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,8 @@ Core and Builtins Library ------- +- Issue #27330: Fixed possible leaks in the ctypes module. + - Issue #27238: Got rid of bare excepts in the turtle module. Original patch by Jelle Zijlstra. diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 2e01323..c49abf0 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -1252,8 +1252,10 @@ add_methods(PyTypeObject *type, PyMethodDef *meth) descr = PyDescr_NewMethod(type, meth); if (descr == NULL) return -1; - if (PyDict_SetItemString(dict,meth->ml_name, descr) < 0) + if (PyDict_SetItemString(dict, meth->ml_name, descr) < 0) { + Py_DECREF(descr); return -1; + } Py_DECREF(descr); } return 0; @@ -1268,8 +1270,10 @@ add_members(PyTypeObject *type, PyMemberDef *memb) descr = PyDescr_NewMember(type, memb); if (descr == NULL) return -1; - if (PyDict_SetItemString(dict, memb->name, descr) < 0) + if (PyDict_SetItemString(dict, memb->name, descr) < 0) { + Py_DECREF(descr); return -1; + } Py_DECREF(descr); } return 0; @@ -1285,8 +1289,10 @@ add_getset(PyTypeObject *type, PyGetSetDef *gsp) descr = PyDescr_NewGetSet(type, gsp); if (descr == NULL) return -1; - if (PyDict_SetItemString(dict, gsp->name, descr) < 0) + if (PyDict_SetItemString(dict, gsp->name, descr) < 0) { + Py_DECREF(descr); return -1; + } Py_DECREF(descr); } return 0; @@ -1778,6 +1784,7 @@ static PyObject *CreateSwappedType(PyTypeObject *type, PyObject *args, PyObject newname = PyUnicode_Concat(name, suffix); if (newname == NULL) { + Py_DECREF(swapped_args); return NULL; } @@ -1797,8 +1804,10 @@ static PyObject *CreateSwappedType(PyTypeObject *type, PyObject *args, PyObject stgdict = (StgDictObject *)PyObject_CallObject( (PyObject *)&PyCStgDict_Type, NULL); - if (!stgdict) /* XXX leaks result! */ + if (!stgdict) { + Py_DECREF(result); return NULL; + } stgdict->ffi_type_pointer = *fmt->pffi_type; stgdict->align = fmt->pffi_type->alignment; @@ -1978,8 +1987,10 @@ PyCSimpleType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) PyObject *meth; int x; meth = PyDescr_NewClassMethod(result, ml); - if (!meth) + if (!meth) { + Py_DECREF(result); return NULL; + } x = PyDict_SetItemString(result->tp_dict, ml->ml_name, meth); @@ -2159,8 +2170,10 @@ converters_from_argtypes(PyObject *ob) nArgs = PyTuple_GET_SIZE(ob); converters = PyTuple_New(nArgs); - if (!converters) + if (!converters) { + Py_DECREF(ob); return NULL; + } /* I have to check if this is correct. Using c_char, which has a size of 1, will be assumed to be pushed as only one byte! diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c index 03a911f..30e3a96 100644 --- a/Modules/_ctypes/callproc.c +++ b/Modules/_ctypes/callproc.c @@ -157,8 +157,10 @@ _ctypes_get_errobj(int **pspace) return NULL; memset(space, 0, sizeof(int) * 2); errobj = PyCapsule_New(space, CTYPES_CAPSULE_NAME_PYMEM, pymem_destructor); - if (errobj == NULL) + if (errobj == NULL) { + PyMem_Free(space); return NULL; + } if (-1 == PyDict_SetItem(dict, error_object_name, errobj)) { Py_DECREF(errobj); @@ -1681,6 +1683,10 @@ POINTER(PyObject *self, PyObject *cls) if (result == NULL) return result; key = PyLong_FromVoidPtr(result); + if (key == NULL) { + Py_DECREF(result); + return NULL; + } } else if (PyType_Check(cls)) { typ = (PyTypeObject *)cls; buf = PyMem_Malloc(strlen(typ->tp_name) + 3 + 1); diff --git a/Modules/_ctypes/cfield.c b/Modules/_ctypes/cfield.c index 8cb6d66..d666be5 100644 --- a/Modules/_ctypes/cfield.c +++ b/Modules/_ctypes/cfield.c @@ -1246,8 +1246,7 @@ U_set(void *ptr, PyObject *value, Py_ssize_t length) "unicode string expected instead of %s instance", value->ob_type->tp_name); return NULL; - } else - Py_INCREF(value); + } wstr = PyUnicode_AsUnicodeAndSize(value, &size); if (wstr == NULL) @@ -1256,7 +1255,6 @@ U_set(void *ptr, PyObject *value, Py_ssize_t length) PyErr_Format(PyExc_ValueError, "string too long (%zd, maximum length %zd)", size, length); - Py_DECREF(value); return NULL; } else if (size < length-1) /* copy terminating NUL character if there is space */ @@ -1266,6 +1264,7 @@ U_set(void *ptr, PyObject *value, Py_ssize_t length) return NULL; } + Py_INCREF(value); return value; } @@ -1292,9 +1291,7 @@ s_set(void *ptr, PyObject *value, Py_ssize_t length) char *data; Py_ssize_t size; - if(PyBytes_Check(value)) { - Py_INCREF(value); - } else { + if(!PyBytes_Check(value)) { PyErr_Format(PyExc_TypeError, "expected bytes, %s found", value->ob_type->tp_name); @@ -1302,11 +1299,9 @@ s_set(void *ptr, PyObject *value, Py_ssize_t length) } data = PyBytes_AS_STRING(value); - if (!data) - return NULL; size = strlen(data); /* XXX Why not Py_SIZE(value)? */ if (size < length) { - /* This will copy the leading NUL character + /* This will copy the terminating NUL character * if there is space for it. */ ++size; @@ -1314,13 +1309,11 @@ s_set(void *ptr, PyObject *value, Py_ssize_t length) PyErr_Format(PyExc_ValueError, "bytes too long (%zd, maximum length %zd)", size, length); - Py_DECREF(value); return NULL; } /* Also copy the terminating NUL character if there is space */ memcpy((char *)ptr, data, size); - Py_DECREF(value); _RET(value); } @@ -1428,9 +1421,7 @@ BSTR_set(void *ptr, PyObject *value, Py_ssize_t size) /* convert value into a PyUnicodeObject or NULL */ if (Py_None == value) { value = NULL; - } else if (PyUnicode_Check(value)) { - Py_INCREF(value); /* for the descref below */ - } else { + } else if (!PyUnicode_Check(value)) { PyErr_Format(PyExc_TypeError, "unicode string expected instead of %s instance", value->ob_type->tp_name); @@ -1449,7 +1440,6 @@ BSTR_set(void *ptr, PyObject *value, Py_ssize_t size) return NULL; } bstr = SysAllocStringLen(wvalue, (unsigned)wsize); - Py_DECREF(value); } else bstr = NULL; -- cgit v0.12 From ec721f3305c04b5d136e2d21cb73c5bdfdd81684 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 16 Jun 2016 23:53:47 +0200 Subject: py_getrandom(): use long type for the syscall() result Issue #27278. It should fix a conversion warning. In practice, the Linux kernel doesn't return more than 32 MB per call to the getrandom() syscall. --- Python/random.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Python/random.c b/Python/random.c index 8ce0b3e..3119872 100644 --- a/Python/random.c +++ b/Python/random.c @@ -132,7 +132,7 @@ py_getrandom(void *buffer, Py_ssize_t size, int raise) * see https://bugs.python.org/issue26839. To avoid this, use the * GRND_NONBLOCK flag. */ const int flags = GRND_NONBLOCK; - int n; + long n; if (!getrandom_works) return 0; @@ -143,7 +143,7 @@ py_getrandom(void *buffer, Py_ssize_t size, int raise) to 1024 bytes */ n = Py_MIN(size, 1024); #else - n = Py_MIN(size, INT_MAX); + n = Py_MIN(size, LONG_MAX); #endif errno = 0; -- cgit v0.12 From 85e6635edf4c56064fddd09f5350936dcd650389 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Fri, 17 Jun 2016 11:11:07 +0300 Subject: ctypes: the type of b_size is Py_ssize_t. --- Modules/_ctypes/_ctypes.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index c49abf0..311fb5d 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -1124,7 +1124,7 @@ CharArray_get_raw(CDataObject *self) static PyObject * CharArray_get_value(CDataObject *self) { - int i; + Py_ssize_t i; char *ptr = self->b_ptr; for (i = 0; i < self->b_size; ++i) if (*ptr++ == '\0') @@ -1180,9 +1180,9 @@ static PyGetSetDef CharArray_getsets[] = { static PyObject * WCharArray_get_value(CDataObject *self) { - unsigned int i; + Py_ssize_t i; wchar_t *ptr = (wchar_t *)self->b_ptr; - for (i = 0; i < self->b_size/sizeof(wchar_t); ++i) + for (i = 0; i < self->b_size/(Py_ssize_t)sizeof(wchar_t); ++i) if (*ptr++ == (wchar_t)0) break; return PyUnicode_FromWideChar((wchar_t *)self->b_ptr, i); @@ -1211,7 +1211,7 @@ WCharArray_set_value(CDataObject *self, PyObject *value) wstr = PyUnicode_AsUnicodeAndSize(value, &len); if (wstr == NULL) return -1; - if ((unsigned)len > self->b_size/sizeof(wchar_t)) { + if ((size_t)len > self->b_size/sizeof(wchar_t)) { PyErr_SetString(PyExc_ValueError, "string too long"); result = -1; -- cgit v0.12 From 08bb8a41cc976343795bd0e241cd7388e9f44ad5 Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Fri, 17 Jun 2016 09:32:38 -0700 Subject: Issue #27048: Prevents distutils failing on Windows when environment variables contain non-ASCII characters --- Lib/distutils/_msvccompiler.py | 6 ++---- Lib/distutils/tests/test_msvccompiler.py | 18 ++++++++++++++++++ Misc/NEWS | 3 +++ 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/Lib/distutils/_msvccompiler.py b/Lib/distutils/_msvccompiler.py index d0ba7d6..b120273 100644 --- a/Lib/distutils/_msvccompiler.py +++ b/Lib/distutils/_msvccompiler.py @@ -86,11 +86,9 @@ def _get_vc_env(plat_spec): try: out = subprocess.check_output( - '"{}" {} && set'.format(vcvarsall, plat_spec), - shell=True, + 'cmd /u /c "{}" {} && set'.format(vcvarsall, plat_spec), stderr=subprocess.STDOUT, - universal_newlines=True, - ) + ).decode('utf-16le', errors='replace') except subprocess.CalledProcessError as exc: log.error(exc.output) raise DistutilsPlatformError("Error executing {}" diff --git a/Lib/distutils/tests/test_msvccompiler.py b/Lib/distutils/tests/test_msvccompiler.py index c4d911f..4dc2488 100644 --- a/Lib/distutils/tests/test_msvccompiler.py +++ b/Lib/distutils/tests/test_msvccompiler.py @@ -83,6 +83,24 @@ class msvccompilerTestCase(support.TempdirManager, self.assertFalse(os.path.isfile(os.path.join( tempdir, os.path.basename(dll)))) + def test_get_vc_env_unicode(self): + import distutils._msvccompiler as _msvccompiler + + test_var = 'ṰḖṤṪ┅ṼẨṜ' + test_value = '₃⁴₅' + + # Ensure we don't early exit from _get_vc_env + old_distutils_use_sdk = os.environ.pop('DISTUTILS_USE_SDK', None) + os.environ[test_var] = test_value + try: + env = _msvccompiler._get_vc_env('x86') + self.assertIn(test_var.lower(), env) + self.assertEqual(test_value, env[test_var.lower()]) + finally: + os.environ.pop(test_var) + if old_distutils_use_sdk: + os.environ['DISTUTILS_USE_SDK'] = old_distutils_use_sdk + def test_suite(): return unittest.makeSuite(msvccompilerTestCase) diff --git a/Misc/NEWS b/Misc/NEWS index 66a95f7..5dff4db 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,9 @@ Core and Builtins Library ------- +- Issue #27048: Prevents distutils failing on Windows when environment + variables contain non-ASCII characters + - Issue #27330: Fixed possible leaks in the ctypes module. - Issue #27238: Got rid of bare excepts in the turtle module. Original patch -- cgit v0.12 From 886a5f352fd64bcdc814dad292bbb37739a1cdd9 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sat, 18 Jun 2016 09:58:24 +0300 Subject: Issue #27343: Fixed error message for conflicting initializers of ctypes.Structure. --- Lib/ctypes/test/test_structures.py | 6 +++--- Modules/_ctypes/_ctypes.c | 9 ++------- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/Lib/ctypes/test/test_structures.py b/Lib/ctypes/test/test_structures.py index 84d456c..d998c27 100644 --- a/Lib/ctypes/test/test_structures.py +++ b/Lib/ctypes/test/test_structures.py @@ -227,10 +227,10 @@ class StructureTestCase(unittest.TestCase): def test_conflicting_initializers(self): class POINT(Structure): - _fields_ = [("x", c_int), ("y", c_int)] + _fields_ = [("phi", c_float), ("rho", c_float)] # conflicting positional and keyword args - self.assertRaises(TypeError, POINT, 2, 3, x=4) - self.assertRaises(TypeError, POINT, 2, 3, y=4) + self.assertRaisesRegex(TypeError, "phi", POINT, 2, 3, phi=4) + self.assertRaisesRegex(TypeError, "rho", POINT, 2, 3, rho=4) # too many initializers self.assertRaises(TypeError, POINT, 2, 3, 4) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 311fb5d..a7a8105 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -4065,14 +4065,9 @@ _init_pos_args(PyObject *self, PyTypeObject *type, } val = PyTuple_GET_ITEM(args, i + index); if (kwds && PyDict_GetItem(kwds, name)) { - char *field = PyBytes_AsString(name); - if (field == NULL) { - PyErr_Clear(); - field = "???"; - } PyErr_Format(PyExc_TypeError, - "duplicate values for field '%s'", - field); + "duplicate values for field %R", + name); Py_DECREF(pair); Py_DECREF(name); return -1; -- cgit v0.12 From bae5d81f5d1f388aad48c2ce1aee8682b157e1bd Mon Sep 17 00:00:00 2001 From: Martin Panter Date: Sat, 18 Jun 2016 03:57:31 +0000 Subject: Issue #24314: Fix doc links for general attributes like __name__, __dict__ --- Doc/c-api/module.rst | 4 ++-- Doc/c-api/typeobj.rst | 4 ++-- Doc/library/builtins.rst | 2 +- Doc/library/enum.rst | 2 +- Doc/library/functions.rst | 10 ++++----- Doc/library/functools.rst | 2 +- Doc/library/inspect.rst | 9 ++++---- Doc/library/stdtypes.rst | 15 +++++++------ Doc/reference/datamodel.rst | 51 +++++++++++++++++++++++---------------------- Doc/tutorial/classes.rst | 4 ++-- Doc/whatsnew/2.1.rst | 4 ++-- Doc/whatsnew/2.2.rst | 14 ++++++------- Doc/whatsnew/2.3.rst | 8 +++---- Doc/whatsnew/3.0.rst | 4 ++-- 14 files changed, 69 insertions(+), 64 deletions(-) diff --git a/Doc/c-api/module.rst b/Doc/c-api/module.rst index 904b4b1..34f8443 100644 --- a/Doc/c-api/module.rst +++ b/Doc/c-api/module.rst @@ -59,10 +59,10 @@ Module Objects .. index:: single: __dict__ (module attribute) Return the dictionary object that implements *module*'s namespace; this object - is the same as the :attr:`__dict__` attribute of the module object. This + is the same as the :attr:`~object.__dict__` attribute of the module object. This function never fails. It is recommended extensions use other :c:func:`PyModule_\*` and :c:func:`PyObject_\*` functions rather than directly - manipulate a module's :attr:`__dict__`. + manipulate a module's :attr:`~object.__dict__`. .. c:function:: PyObject* PyModule_GetNameObject(PyObject *module) diff --git a/Doc/c-api/typeobj.rst b/Doc/c-api/typeobj.rst index ac589b8..2c448a0 100644 --- a/Doc/c-api/typeobj.rst +++ b/Doc/c-api/typeobj.rst @@ -111,10 +111,10 @@ type objects) *must* have the :attr:`ob_size` field. For statically allocated type objects, the tp_name field should contain a dot. Everything before the last dot is made accessible as the :attr:`__module__` attribute, and everything after the last dot is made accessible as the - :attr:`__name__` attribute. + :attr:`~definition.__name__` attribute. If no dot is present, the entire :c:member:`~PyTypeObject.tp_name` field is made accessible as the - :attr:`__name__` attribute, and the :attr:`__module__` attribute is undefined + :attr:`~definition.__name__` attribute, and the :attr:`__module__` attribute is undefined (unless explicitly set in the dictionary, as explained above). This means your type will be impossible to pickle. diff --git a/Doc/library/builtins.rst b/Doc/library/builtins.rst index 4b589a5..8fb1fef 100644 --- a/Doc/library/builtins.rst +++ b/Doc/library/builtins.rst @@ -37,6 +37,6 @@ that wants to implement an :func:`open` function that wraps the built-in As an implementation detail, most modules have the name ``__builtins__`` made available as part of their globals. The value of ``__builtins__`` is normally -either this module or the value of this module's :attr:`__dict__` attribute. +either this module or the value of this module's :attr:`~object.__dict__` attribute. Since this is an implementation detail, it may not be used by alternate implementations of Python. diff --git a/Doc/library/enum.rst b/Doc/library/enum.rst index 60467b4..a3d5afc 100644 --- a/Doc/library/enum.rst +++ b/Doc/library/enum.rst @@ -431,7 +431,7 @@ The solution is to specify the module name explicitly as follows:: the source, pickling will be disabled. The new pickle protocol 4 also, in some circumstances, relies on -:attr:`__qualname__` being set to the location where pickle will be able +:attr:`~definition.__qualname__` being set to the location where pickle will be able to find the class. For example, if the class was made available in class SomeData in the global scope:: diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index c3563f3..e609463 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -304,7 +304,7 @@ are always available. They are listed here in alphabetical order. :func:`dir` reports their attributes. If the object does not provide :meth:`__dir__`, the function tries its best to - gather information from the object's :attr:`__dict__` attribute, if defined, and + gather information from the object's :attr:`~object.__dict__` attribute, if defined, and from its type object. The resulting list is not necessarily complete, and may be inaccurate when the object has a custom :func:`__getattr__`. @@ -1446,7 +1446,7 @@ are always available. They are listed here in alphabetical order. With three arguments, return a new type object. This is essentially a dynamic form of the :keyword:`class` statement. The *name* string is the - class name and becomes the :attr:`~class.__name__` attribute; the *bases* + class name and becomes the :attr:`~definition.__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 is copied to a standard dictionary to become the @@ -1464,11 +1464,11 @@ are always available. They are listed here in alphabetical order. .. function:: vars([object]) Return the :attr:`~object.__dict__` attribute for a module, class, instance, - or any other object with a :attr:`__dict__` attribute. + or any other object with a :attr:`~object.__dict__` attribute. - Objects such as modules and instances have an updateable :attr:`__dict__` + Objects such as modules and instances have an updateable :attr:`~object.__dict__` attribute; however, other objects may have write restrictions on their - :attr:`__dict__` attributes (for example, classes use a + :attr:`~object.__dict__` attributes (for example, classes use a dictproxy to prevent direct dictionary updates). Without an argument, :func:`vars` acts like :func:`locals`. Note, the diff --git a/Doc/library/functools.rst b/Doc/library/functools.rst index abdd66f..127e3fa 100644 --- a/Doc/library/functools.rst +++ b/Doc/library/functools.rst @@ -474,7 +474,7 @@ have three read-only attributes: :class:`partial` objects are like :class:`function` objects in that they are callable, weak referencable, and can have attributes. There are some important -differences. For instance, the :attr:`__name__` and :attr:`__doc__` attributes +differences. For instance, the :attr:`~definition.__name__` and :attr:`__doc__` attributes are not created automatically. Also, :class:`partial` objects defined in classes behave like static methods and do not transform into bound methods during instance attribute look-up. diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst index b28d0f9..8e7ed19 100644 --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -374,8 +374,9 @@ attributes: are true. This, for example, is true of ``int.__add__``. An object passing this test - has a :attr:`__get__` attribute but not a :attr:`__set__` attribute, but - beyond that the set of attributes varies. :attr:`__name__` is usually + has a :meth:`~object.__get__` method but not a :meth:`~object.__set__` + method, but beyond that the set of attributes varies. A + :attr:`~definition.__name__` attribute is usually sensible, and :attr:`__doc__` often is. Methods implemented via descriptors that also pass one of the other tests @@ -388,11 +389,11 @@ attributes: Return true if the object is a data descriptor. - Data descriptors have both a :attr:`__get__` and a :attr:`__set__` attribute. + Data descriptors have both a :attr:`~object.__get__` and a :attr:`~object.__set__` method. Examples are properties (defined in Python), getsets, and members. The latter two are defined in C and there are more specific tests available for those types, which is robust across Python implementations. Typically, data - descriptors will also have :attr:`__name__` and :attr:`__doc__` attributes + descriptors will also have :attr:`~definition.__name__` and :attr:`__doc__` attributes (properties, getsets, and members have both of these attributes), but this is not guaranteed. diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index e8a488e..db1c2d0 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -4360,9 +4360,10 @@ an (external) *definition* for a module named *foo* somewhere.) A special attribute of every module is :attr:`~object.__dict__`. This is the dictionary containing the module's symbol table. Modifying this dictionary will actually change the module's symbol table, but direct assignment to the -:attr:`__dict__` attribute is not possible (you can write +:attr:`~object.__dict__` attribute is not possible (you can write ``m.__dict__['a'] = 1``, which defines ``m.a`` to be ``1``, but you can't write -``m.__dict__ = {}``). Modifying :attr:`__dict__` directly is not recommended. +``m.__dict__ = {}``). Modifying :attr:`~object.__dict__` directly is +not recommended. Modules built into the interpreter are written like this: ````. If loaded from a file, they are written as ``>> class C(object): @@ -383,7 +383,7 @@ attributes to a particular set of names. An example will make this clear:: AttributeError: 'C' object has no attribute 'newattr' Note how you get an :exc:`AttributeError` on the attempt to assign to an -attribute not listed in :attr:`__slots__`. +attribute not listed in :attr:`~object.__slots__`. .. _sect-rellinks: diff --git a/Doc/whatsnew/2.3.rst b/Doc/whatsnew/2.3.rst index b8cdcf1..fe8368e 100644 --- a/Doc/whatsnew/2.3.rst +++ b/Doc/whatsnew/2.3.rst @@ -1111,10 +1111,10 @@ Here are all of the changes that Python 2.3 makes to the core Python language. * One of the noted incompatibilities between old- and new-style classes has been - removed: you can now assign to the :attr:`__name__` and :attr:`__bases__` + removed: you can now assign to the :attr:`~definition.__name__` and :attr:`~class.__bases__` attributes of new-style classes. There are some restrictions on what can be - assigned to :attr:`__bases__` along the lines of those relating to assigning to - an instance's :attr:`__class__` attribute. + assigned to :attr:`~class.__bases__` along the lines of those relating to assigning to + an instance's :attr:`~instance.__class__` attribute. .. ====================================================================== @@ -1920,7 +1920,7 @@ Changes to Python's build process and to the C API include: * If you dynamically allocate type objects in your extension, you should be aware of a change in the rules relating to the :attr:`__module__` and - :attr:`__name__` attributes. In summary, you will want to ensure the type's + :attr:`~definition.__name__` attributes. In summary, you will want to ensure the type's dictionary contains a ``'__module__'`` key; making the module name the part of the type name leading up to the final period will no longer have the desired effect. For more detail, read the API reference documentation or the source. diff --git a/Doc/whatsnew/3.0.rst b/Doc/whatsnew/3.0.rst index 044d7be..f53e4f8 100644 --- a/Doc/whatsnew/3.0.rst +++ b/Doc/whatsnew/3.0.rst @@ -783,8 +783,8 @@ Operators And Special Methods :attr:`func_closure`, :attr:`func_code`, :attr:`func_defaults`, :attr:`func_dict`, :attr:`func_doc`, :attr:`func_globals`, :attr:`func_name` were renamed to :attr:`__closure__`, - :attr:`__code__`, :attr:`__defaults__`, :attr:`__dict__`, - :attr:`__doc__`, :attr:`__globals__`, :attr:`__name__`, + :attr:`__code__`, :attr:`__defaults__`, :attr:`~object.__dict__`, + :attr:`__doc__`, :attr:`__globals__`, :attr:`~definition.__name__`, respectively. * :meth:`__nonzero__` is now :meth:`__bool__`. -- cgit v0.12 From 9305d83425e2ec63b2769336907dd07b3151cd5f Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sat, 18 Jun 2016 13:53:36 +0300 Subject: Issue #26754: PyUnicode_FSDecoder() accepted a filename argument encoded as an iterable of integers. Now only strings and byte-like objects are accepted. --- Lib/test/test_compile.py | 7 +++++++ Lib/test/test_parser.py | 16 ++++++++++++++++ Lib/test/test_symtable.py | 6 ++++++ Lib/test/test_zipimport.py | 15 +++++++++++++++ Misc/NEWS | 11 +++++++++++ Objects/unicodeobject.c | 8 +++++++- 6 files changed, 62 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_compile.py b/Lib/test/test_compile.py index e0fdee3..824e843 100644 --- a/Lib/test/test_compile.py +++ b/Lib/test/test_compile.py @@ -472,6 +472,13 @@ if 1: d = {f(): f(), f(): f()} self.assertEqual(d, {1: 2, 3: 4}) + def test_compile_filename(self): + for filename in ('file.py', b'file.py', + bytearray(b'file.py'), memoryview(b'file.py')): + code = compile('pass', filename, 'exec') + self.assertEqual(code.co_filename, 'file.py') + self.assertRaises(TypeError, compile, 'pass', list(b'file.py'), 'exec') + @support.cpython_only def test_same_filename_used(self): s = """def f(): pass\ndef g(): pass""" diff --git a/Lib/test/test_parser.py b/Lib/test/test_parser.py index 3d301b4..ab6577f 100644 --- a/Lib/test/test_parser.py +++ b/Lib/test/test_parser.py @@ -627,6 +627,22 @@ class CompileTestCase(unittest.TestCase): code2 = parser.compilest(st) self.assertEqual(eval(code2), -3) + def test_compile_filename(self): + st = parser.expr('a + 5') + code = parser.compilest(st) + self.assertEqual(code.co_filename, '') + code = st.compile() + self.assertEqual(code.co_filename, '') + for filename in ('file.py', b'file.py', + bytearray(b'file.py'), memoryview(b'file.py')): + code = parser.compilest(st, filename) + self.assertEqual(code.co_filename, 'file.py') + code = st.compile(filename) + self.assertEqual(code.co_filename, 'file.py') + self.assertRaises(TypeError, parser.compilest, st, list(b'file.py')) + self.assertRaises(TypeError, st.compile, list(b'file.py')) + + class ParserStackLimitTestCase(unittest.TestCase): """try to push the parser to/over its limits. see http://bugs.python.org/issue1881 for a discussion diff --git a/Lib/test/test_symtable.py b/Lib/test/test_symtable.py index e5e7b83..c5d7fac 100644 --- a/Lib/test/test_symtable.py +++ b/Lib/test/test_symtable.py @@ -157,6 +157,12 @@ class SymtableTest(unittest.TestCase): self.fail("no SyntaxError for %r" % (brokencode,)) checkfilename("def f(x): foo)(") # parse-time checkfilename("def f(x): global x") # symtable-build-time + symtable.symtable("pass", b"spam", "exec") + with self.assertRaises(TypeError): + symtable.symtable("pass", bytearray(b"spam"), "exec") + symtable.symtable("pass", memoryview(b"spam"), "exec") + with self.assertRaises(TypeError): + symtable.symtable("pass", list(b"spam"), "exec") def test_eval(self): symbols = symtable.symtable("42", "?", "eval") diff --git a/Lib/test/test_zipimport.py b/Lib/test/test_zipimport.py index 0da5906..8e5e12d 100644 --- a/Lib/test/test_zipimport.py +++ b/Lib/test/test_zipimport.py @@ -600,6 +600,19 @@ class UncompressedZipImportTestCase(ImportHooksBaseTestCase): finally: os.remove(filename) + def testBytesPath(self): + filename = support.TESTFN + ".zip" + self.addCleanup(support.unlink, filename) + with ZipFile(filename, "w") as z: + zinfo = ZipInfo(TESTMOD + ".py", time.localtime(NOW)) + zinfo.compress_type = self.compression + z.writestr(zinfo, test_src) + + zipimport.zipimporter(filename) + zipimport.zipimporter(os.fsencode(filename)) + zipimport.zipimporter(bytearray(os.fsencode(filename))) + zipimport.zipimporter(memoryview(os.fsencode(filename))) + @support.requires_zlib class CompressedZipImportTestCase(UncompressedZipImportTestCase): @@ -620,6 +633,8 @@ class BadFileZipImportTestCase(unittest.TestCase): def testBadArgs(self): self.assertRaises(TypeError, zipimport.zipimporter, None) self.assertRaises(TypeError, zipimport.zipimporter, TESTMOD, kwd=None) + self.assertRaises(TypeError, zipimport.zipimporter, + list(os.fsencode(TESTMOD))) def testFilenameTooLong(self): self.assertZipFailure('A' * 33000) diff --git a/Misc/NEWS b/Misc/NEWS index 5dff4db..3c6d3ae 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,10 @@ Core and Builtins Library ------- +- Issue #26754: Some functions (compile() etc) accepted a filename argument + encoded as an iterable of integers. Now only strings and byte-like objects + are accepted. + - Issue #27048: Prevents distutils failing on Windows when environment variables contain non-ASCII characters @@ -43,6 +47,13 @@ Library - Issue #26930: Update Windows builds to use OpenSSL 1.0.2h. +C API +----- + +- Issue #26754: PyUnicode_FSDecoder() accepted a filename argument encoded as + an iterable of integers. Now only strings and byte-like objects are accepted. + + What's New in Python 3.5.2 final? ================================= diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index f11a082..1fcc83e 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -3666,7 +3666,7 @@ PyUnicode_FSDecoder(PyObject* arg, void* addr) output = arg; Py_INCREF(output); } - else { + else if (PyObject_CheckBuffer(arg)) { arg = PyBytes_FromObject(arg); if (!arg) return 0; @@ -3681,6 +3681,12 @@ PyUnicode_FSDecoder(PyObject* arg, void* addr) return 0; } } + else { + PyErr_Format(PyExc_TypeError, + "path should be string or bytes, not %.200s", + Py_TYPE(arg)->tp_name); + return 0; + } if (PyUnicode_READY(output) == -1) { Py_DECREF(output); return 0; -- cgit v0.12 From d37de3c41de46ebda801d60b171875352267977d Mon Sep 17 00:00:00 2001 From: Senthil Kumaran Date: Sat, 18 Jun 2016 11:21:50 -0700 Subject: issue27021 - Document SC_IOV_MAX limitation imposed by OS on os.writev. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Patch contributed Марк Коренберг. --- Doc/library/os.rst | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Doc/library/os.rst b/Doc/library/os.rst index 743efb6..7b26953 100644 --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -1195,7 +1195,11 @@ or `the MSDN `_ on Windo .. function:: writev(fd, buffers) Write the contents of *buffers* to file descriptor *fd*. *buffers* must be a - sequence of :term:`bytes-like objects `. + sequence of :term:`bytes-like objects `. Buffers are + processed in array order. Entire contents of first buffer is written before + proceeding to second, and so on. The operating system may set a limit + (sysconf() value SC_IOV_MAX) on the number of buffers that can be used. + :func:`~os.writev` writes the contents of each object to the file descriptor and returns the total number of bytes written. -- cgit v0.12 From 56fe4749fb79609de7a6ab83f7d444d271f64e38 Mon Sep 17 00:00:00 2001 From: Berker Peksag Date: Sat, 18 Jun 2016 21:42:37 +0300 Subject: Issue #27349: Fix typo in distutils upload command --- Lib/distutils/command/upload.py | 2 +- Lib/distutils/tests/test_upload.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Lib/distutils/command/upload.py b/Lib/distutils/command/upload.py index 0afcbf2..1fd574a 100644 --- a/Lib/distutils/command/upload.py +++ b/Lib/distutils/command/upload.py @@ -91,7 +91,7 @@ class upload(PyPIRCCommand): data = { # action ':action': 'file_upload', - 'protcol_version': '1', + 'protocol_version': '1', # identify release 'name': meta.get_name(), diff --git a/Lib/distutils/tests/test_upload.py b/Lib/distutils/tests/test_upload.py index 964aac7..3eecf8a 100644 --- a/Lib/distutils/tests/test_upload.py +++ b/Lib/distutils/tests/test_upload.py @@ -130,13 +130,14 @@ class uploadTestCase(PyPIRCCommandTestCase): # what did we send ? headers = dict(self.last_open.req.headers) - self.assertEqual(headers['Content-length'], '2161') + self.assertEqual(headers['Content-length'], '2162') content_type = headers['Content-type'] self.assertTrue(content_type.startswith('multipart/form-data')) self.assertEqual(self.last_open.req.get_method(), 'POST') expected_url = 'https://pypi.python.org/pypi' self.assertEqual(self.last_open.req.get_full_url(), expected_url) self.assertTrue(b'xxx' in self.last_open.req.data) + self.assertIn(b'protocol_version', self.last_open.req.data) # The PyPI response body was echoed results = self.get_logs(INFO) -- cgit v0.12 From 514f9736a712923756cdd1d3a5e845bf3fdb0994 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sat, 18 Jun 2016 22:08:11 +0300 Subject: Issue #27294: Numerical state in the repr for Tkinter event objects is now represented as a compination of known flags. --- Doc/library/curses.ascii.rst | 4 ++-- Lib/curses/ascii.py | 6 ++--- Lib/test/test_curses.py | 54 ++++++++++++++++++++++++++++++++++++++++++++ Misc/NEWS | 2 ++ 4 files changed, 61 insertions(+), 5 deletions(-) diff --git a/Doc/library/curses.ascii.rst b/Doc/library/curses.ascii.rst index f3661d9..db3c827 100644 --- a/Doc/library/curses.ascii.rst +++ b/Doc/library/curses.ascii.rst @@ -115,12 +115,12 @@ C library: .. function:: isblank(c) - Checks for an ASCII whitespace character. + Checks for an ASCII whitespace character; space or horizontal tab. .. function:: iscntrl(c) - Checks for an ASCII control character (in the range 0x00 to 0x1f). + Checks for an ASCII control character (in the range 0x00 to 0x1f or 0x7f). .. function:: isdigit(c) diff --git a/Lib/curses/ascii.py b/Lib/curses/ascii.py index 800fd8b..6a466e0 100644 --- a/Lib/curses/ascii.py +++ b/Lib/curses/ascii.py @@ -54,13 +54,13 @@ def _ctoi(c): def isalnum(c): return isalpha(c) or isdigit(c) def isalpha(c): return isupper(c) or islower(c) def isascii(c): return _ctoi(c) <= 127 # ? -def isblank(c): return _ctoi(c) in (8,32) -def iscntrl(c): return _ctoi(c) <= 31 +def isblank(c): return _ctoi(c) in (9, 32) +def iscntrl(c): return _ctoi(c) <= 31 or _ctoi(c) == 127 def isdigit(c): return _ctoi(c) >= 48 and _ctoi(c) <= 57 def isgraph(c): return _ctoi(c) >= 33 and _ctoi(c) <= 126 def islower(c): return _ctoi(c) >= 97 and _ctoi(c) <= 122 def isprint(c): return _ctoi(c) >= 32 and _ctoi(c) <= 126 -def ispunct(c): return _ctoi(c) != 32 and not isalnum(c) +def ispunct(c): return isgraph(c) and not isalnum(c) def isspace(c): return _ctoi(c) in (9, 10, 11, 12, 13, 32) def isupper(c): return _ctoi(c) >= 65 and _ctoi(c) <= 90 def isxdigit(c): return isdigit(c) or \ diff --git a/Lib/test/test_curses.py b/Lib/test/test_curses.py index 8411cdb..897d738 100644 --- a/Lib/test/test_curses.py +++ b/Lib/test/test_curses.py @@ -10,6 +10,7 @@ # import os +import string import sys import tempfile import unittest @@ -399,6 +400,55 @@ class MiscTests(unittest.TestCase): class TestAscii(unittest.TestCase): + def test_controlnames(self): + for name in curses.ascii.controlnames: + self.assertTrue(hasattr(curses.ascii, name), name) + + def test_ctypes(self): + def check(func, expected): + with self.subTest(ch=c, func=func): + self.assertEqual(func(i), expected) + self.assertEqual(func(c), expected) + + for i in range(256): + c = chr(i) + b = bytes([i]) + check(curses.ascii.isalnum, b.isalnum()) + check(curses.ascii.isalpha, b.isalpha()) + check(curses.ascii.isdigit, b.isdigit()) + check(curses.ascii.islower, b.islower()) + check(curses.ascii.isspace, b.isspace()) + check(curses.ascii.isupper, b.isupper()) + + check(curses.ascii.isascii, i < 128) + check(curses.ascii.ismeta, i >= 128) + check(curses.ascii.isctrl, i < 32) + check(curses.ascii.iscntrl, i < 32 or i == 127) + check(curses.ascii.isblank, c in ' \t') + check(curses.ascii.isgraph, 32 < i <= 126) + check(curses.ascii.isprint, 32 <= i <= 126) + check(curses.ascii.ispunct, c in string.punctuation) + check(curses.ascii.isxdigit, c in string.hexdigits) + + def test_ascii(self): + ascii = curses.ascii.ascii + self.assertEqual(ascii('\xc1'), 'A') + self.assertEqual(ascii('A'), 'A') + self.assertEqual(ascii(ord('\xc1')), ord('A')) + + def test_ctrl(self): + ctrl = curses.ascii.ctrl + self.assertEqual(ctrl('J'), '\n') + self.assertEqual(ctrl('\n'), '\n') + self.assertEqual(ctrl('@'), '\0') + self.assertEqual(ctrl(ord('J')), ord('\n')) + + def test_alt(self): + alt = curses.ascii.alt + self.assertEqual(alt('\n'), '\x8a') + self.assertEqual(alt('A'), '\xc1') + self.assertEqual(alt(ord('A')), 0xc1) + def test_unctrl(self): unctrl = curses.ascii.unctrl self.assertEqual(unctrl('a'), 'a') @@ -408,9 +458,13 @@ class TestAscii(unittest.TestCase): self.assertEqual(unctrl('\x7f'), '^?') self.assertEqual(unctrl('\n'), '^J') self.assertEqual(unctrl('\0'), '^@') + self.assertEqual(unctrl(ord('A')), 'A') + self.assertEqual(unctrl(ord('\n')), '^J') # Meta-bit characters self.assertEqual(unctrl('\x8a'), '!^J') self.assertEqual(unctrl('\xc1'), '!A') + self.assertEqual(unctrl(ord('\x8a')), '!^J') + self.assertEqual(unctrl(ord('\xc1')), '!A') if __name__ == '__main__': diff --git a/Misc/NEWS b/Misc/NEWS index 3c6d3ae..49304ba 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,8 @@ Core and Builtins Library ------- +- Issue #27079: Fixed curses.ascii functions isblank(), iscntrl() and ispunct(). + - Issue #26754: Some functions (compile() etc) accepted a filename argument encoded as an iterable of integers. Now only strings and byte-like objects are accepted. -- cgit v0.12 From 5943ea76d529f9ea18c73a61e10c6f53bdcc864f Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sun, 19 Jun 2016 18:30:43 +0300 Subject: Issue #23641: Added __getnewargs_ex__ to the list of special mock attributes. --- Lib/unittest/mock.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py index 86a5a3d..1adfcf9 100644 --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -1694,6 +1694,7 @@ _non_defaults = { '__reduce__', '__reduce_ex__', '__getinitargs__', '__getnewargs__', '__getstate__', '__setstate__', '__getformat__', '__setformat__', '__repr__', '__dir__', '__subclasses__', '__format__', + '__getnewargs_ex__', } -- cgit v0.12 From ce1a9f309fd5b88e2792a8e31c237412fc163d28 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Mon, 20 Jun 2016 05:29:54 +0300 Subject: Added more tests for issue #27122. --- Lib/test/test_contextlib.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/Lib/test/test_contextlib.py b/Lib/test/test_contextlib.py index a246c43..516403e 100644 --- a/Lib/test/test_contextlib.py +++ b/Lib/test/test_contextlib.py @@ -763,8 +763,9 @@ class TestExitStack(unittest.TestCase): self.assertIs(stack._exit_callbacks[-1], cm) def test_dont_reraise_RuntimeError(self): - """https://bugs.python.org/issue27122""" + # https://bugs.python.org/issue27122 class UniqueException(Exception): pass + class UniqueRuntimeError(RuntimeError): pass @contextmanager def second(): @@ -780,15 +781,20 @@ class TestExitStack(unittest.TestCase): except Exception as exc: raise exc - # The RuntimeError should be caught by second()'s exception + # The UniqueRuntimeError should be caught by second()'s exception # handler which chain raised a new UniqueException. with self.assertRaises(UniqueException) as err_ctx: with ExitStack() as es_ctx: es_ctx.enter_context(second()) es_ctx.enter_context(first()) - raise RuntimeError("please no infinite loop.") - - self.assertEqual(err_ctx.exception.args[0], "new exception") + raise UniqueRuntimeError("please no infinite loop.") + + exc = err_ctx.exception + self.assertIsInstance(exc, UniqueException) + self.assertIsInstance(exc.__context__, UniqueRuntimeError) + self.assertIsNone(exc.__context__.__context__) + self.assertIsNone(exc.__context__.__cause__) + self.assertIs(exc.__cause__, exc.__context__) class TestRedirectStream: -- cgit v0.12 From 2275e626b1694557f646fd8a06608074731d6c82 Mon Sep 17 00:00:00 2001 From: Martin Panter Date: Mon, 20 Jun 2016 07:52:50 +0000 Subject: Fix spelling errors in code comments --- Doc/tools/extensions/suspicious.py | 2 +- Objects/abstract.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/tools/extensions/suspicious.py b/Doc/tools/extensions/suspicious.py index d3ed849..0a70e57 100644 --- a/Doc/tools/extensions/suspicious.py +++ b/Doc/tools/extensions/suspicious.py @@ -270,5 +270,5 @@ class SuspiciousVisitor(nodes.GenericNodeVisitor): # ignore comments -- too much false positives. # (although doing this could miss some errors; # there were two sections "commented-out" by mistake - # in the Python docs that would not be catched) + # in the Python docs that would not be caught) raise nodes.SkipNode diff --git a/Objects/abstract.c b/Objects/abstract.c index a0362e7..585992d 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -2109,7 +2109,7 @@ _Py_CheckFunctionResult(PyObject *func, PyObject *result, const char *where) "%s returned NULL without setting an error", where); #ifdef Py_DEBUG - /* Ensure that the bug is catched in debug mode */ + /* Ensure that the bug is caught in debug mode */ Py_FatalError("a function returned NULL without setting an error"); #endif return NULL; @@ -2132,7 +2132,7 @@ _Py_CheckFunctionResult(PyObject *func, PyObject *result, const char *where) where); _PyErr_ChainExceptions(exc, val, tb); #ifdef Py_DEBUG - /* Ensure that the bug is catched in debug mode */ + /* Ensure that the bug is caught in debug mode */ Py_FatalError("a function returned a result with an error set"); #endif return NULL; -- cgit v0.12 From 6817c59cf08ac214737d86f37e63a431385a9613 Mon Sep 17 00:00:00 2001 From: Stefan Krah Date: Mon, 20 Jun 2016 12:10:13 +0200 Subject: Issue #27006: from_float(): call the subclass' __new__() and __init__(). --- Lib/test/test_decimal.py | 5 ++++- Modules/_decimal/_decimal.c | 10 ++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_decimal.py b/Lib/test/test_decimal.py index c0d21b1..cde5d78 100644 --- a/Lib/test/test_decimal.py +++ b/Lib/test/test_decimal.py @@ -2491,7 +2491,8 @@ class PythonAPItests(unittest.TestCase): Decimal = self.decimal.Decimal class MyDecimal(Decimal): - pass + def __init__(self, _): + self.x = 'y' self.assertTrue(issubclass(MyDecimal, Decimal)) @@ -2499,6 +2500,8 @@ class PythonAPItests(unittest.TestCase): self.assertEqual(type(r), MyDecimal) self.assertEqual(str(r), '0.1000000000000000055511151231257827021181583404541015625') + self.assertEqual(r.x, 'y') + bigint = 12345678901234567890123456789 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint)) self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan()) diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c index 112b44f..e69d715 100644 --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -2630,12 +2630,18 @@ PyDecType_FromSequenceExact(PyTypeObject *type, PyObject *v, /* class method */ static PyObject * -dec_from_float(PyObject *dec, PyObject *pyfloat) +dec_from_float(PyObject *type, PyObject *pyfloat) { PyObject *context; + PyObject *result; CURRENT_CONTEXT(context); - return PyDecType_FromFloatExact((PyTypeObject *)dec, pyfloat, context); + result = PyDecType_FromFloatExact(&PyDec_Type, pyfloat, context); + if (!PyDec_CheckExact(type) && result != NULL) { + Py_SETREF(result, PyObject_CallFunctionObjArgs(type, result, NULL)); + } + + return result; } /* create_decimal_from_float */ -- cgit v0.12 From 947f099d99f52badb14837066463c44b63476cfd Mon Sep 17 00:00:00 2001 From: Stefan Krah Date: Mon, 20 Jun 2016 14:12:52 +0200 Subject: Issue #27006: Do not use PyDec_CheckExact() on a type. --- Modules/_decimal/_decimal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c index e69d715..22053b4 100644 --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -2637,7 +2637,7 @@ dec_from_float(PyObject *type, PyObject *pyfloat) CURRENT_CONTEXT(context); result = PyDecType_FromFloatExact(&PyDec_Type, pyfloat, context); - if (!PyDec_CheckExact(type) && result != NULL) { + if (type != (PyObject *)&PyDec_Type && result != NULL) { Py_SETREF(result, PyObject_CallFunctionObjArgs(type, result, NULL)); } -- cgit v0.12 From c529af3fcb2c1a48780f66291970f4527659fa30 Mon Sep 17 00:00:00 2001 From: Berker Peksag Date: Mon, 20 Jun 2016 21:41:34 +0300 Subject: Issue #20120: Add a test case to verify the % char can be used in .pypirc I noticed that there is no test for this feature while doing triaging work on pypa/pypi-legacy. --- Lib/distutils/tests/test_config.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/Lib/distutils/tests/test_config.py b/Lib/distutils/tests/test_config.py index 4de825a..0b91d19 100644 --- a/Lib/distutils/tests/test_config.py +++ b/Lib/distutils/tests/test_config.py @@ -18,6 +18,7 @@ PYPIRC = """\ index-servers = server1 server2 + server3 [server1] username:me @@ -28,6 +29,10 @@ username:meagain password: secret realm:acme repository:http://another.pypi/ + +[server3] +username:cbiggles +password:yh^%#rest-of-my-password """ PYPIRC_OLD = """\ @@ -113,6 +118,20 @@ class PyPIRCCommandTestCase(support.TempdirManager, finally: f.close() + def test_config_interpolation(self): + # using the % character in .pypirc should not raise an error (#20120) + self.write_file(self.rc, PYPIRC) + cmd = self._cmd(self.dist) + cmd.repository = 'server3' + config = cmd._read_pypirc() + + config = list(sorted(config.items())) + waited = [('password', 'yh^%#rest-of-my-password'), ('realm', 'pypi'), + ('repository', 'https://pypi.python.org/pypi'), + ('server', 'server3'), ('username', 'cbiggles')] + self.assertEqual(config, waited) + + def test_suite(): return unittest.makeSuite(PyPIRCCommandTestCase) -- cgit v0.12 From 8550bd80ae1706f0683e4d0e6838bdf4930fefa4 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Tue, 21 Jun 2016 23:47:16 -0700 Subject: alter header; '%' really throws latex through a loop --- Doc/whatsnew/3.5.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst index dc55c65..8fc2f6c 100644 --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -356,8 +356,8 @@ unpackings (see :ref:`exprlists` and :ref:`dict`):: .. _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 ` to :class:`bytes` -- cgit v0.12 From 6ff7a14b914dc1a456c122da75b60cbb613ab31d Mon Sep 17 00:00:00 2001 From: Terry Jan Reedy Date: Wed, 22 Jun 2016 03:55:20 -0400 Subject: Issue #27365: Allow non-ascii in idlelib/NEWS.txt - minimal part for 3.5.2. --- Lib/idlelib/NEWS.txt | 4 ++-- Lib/idlelib/aboutDialog.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt index 6c41e28..00d5005 100644 --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -30,7 +30,7 @@ What's New in IDLE 3.5.2? Original patch by Saimadhav Heblikar. - Issue #18410: Add test for IDLE's search dialog. - Original patch by Westley Martnez. + Original patch by Westley Martínez. - Issue #21703: Add test for undo delegator. Original patch by Saimadhav Heblikar . @@ -48,7 +48,7 @@ What's New in IDLE 3.5.2? - 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 +- 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'. diff --git a/Lib/idlelib/aboutDialog.py b/Lib/idlelib/aboutDialog.py index 3112e6a..0457c43 100644 --- a/Lib/idlelib/aboutDialog.py +++ b/Lib/idlelib/aboutDialog.py @@ -130,7 +130,7 @@ class AboutDialog(Toplevel): self.display_file_text('About - Readme', 'README.txt', 'ascii') def ShowIDLENEWS(self): - self.display_file_text('About - NEWS', 'NEWS.txt', 'ascii') + self.display_file_text('About - NEWS', 'NEWS.txt', 'utf-8') def display_printer_text(self, title, printer): printer._Printer__setup() -- cgit v0.12 From 06a1fcbb0035c664fefc53ddb8df65cc03a537b7 Mon Sep 17 00:00:00 2001 From: Terry Jan Reedy Date: Wed, 22 Jun 2016 04:17:28 -0400 Subject: Issue #27365: Allow non-ascii in idlelib/NEWS.txt, for contributor names. Rest of patch that should not be cherry picked into 3.5.2 final. --- Lib/idlelib/aboutDialog.py | 2 ++ Lib/idlelib/idle_test/test_help_about.py | 52 ++++++++++++++++++++++++++++++++ Lib/idlelib/textView.py | 4 +++ 3 files changed, 58 insertions(+) create mode 100644 Lib/idlelib/idle_test/test_help_about.py diff --git a/Lib/idlelib/aboutDialog.py b/Lib/idlelib/aboutDialog.py index 0457c43..a8f75d2 100644 --- a/Lib/idlelib/aboutDialog.py +++ b/Lib/idlelib/aboutDialog.py @@ -145,5 +145,7 @@ class AboutDialog(Toplevel): self.destroy() if __name__ == '__main__': + import unittest + unittest.main('idlelib.idle_test.test_helpabout', verbosity=2, exit=False) from idlelib.idle_test.htest import run run(AboutDialog) diff --git a/Lib/idlelib/idle_test/test_help_about.py b/Lib/idlelib/idle_test/test_help_about.py new file mode 100644 index 0000000..d0a0127 --- /dev/null +++ b/Lib/idlelib/idle_test/test_help_about.py @@ -0,0 +1,52 @@ +'''Test idlelib.help_about. + +Coverage: +''' +from idlelib import aboutDialog as help_about +from idlelib import textView as textview +from idlelib.idle_test.mock_idle import Func +from idlelib.idle_test.mock_tk import Mbox +import unittest + +About = help_about.AboutDialog +class Dummy_about_dialog(): + # Dummy class for testing file display functions. + idle_credits = About.ShowIDLECredits + idle_readme = About.ShowIDLEAbout + idle_news = About.ShowIDLENEWS + # Called by the above + display_file_text = About.display_file_text + + +class DisplayFileTest(unittest.TestCase): + "Test that .txt files are found and properly decoded." + dialog = Dummy_about_dialog() + + @classmethod + def setUpClass(cls): + cls.orig_mbox = textview.tkMessageBox + cls.orig_view = textview.view_text + cls.mbox = Mbox() + cls.view = Func() + textview.tkMessageBox = cls.mbox + textview.view_text = cls.view + cls.About = Dummy_about_dialog() + + @classmethod + def tearDownClass(cls): + textview.tkMessageBox = cls.orig_mbox + textview.view_text = cls.orig_view + + def test_file_isplay(self): + for handler in (self.dialog.idle_credits, + self.dialog.idle_readme, + self.dialog.idle_news): + self.mbox.showerror.message = '' + self.view.called = False + handler() + self.assertEqual(self.mbox.showerror.message, '') + self.assertEqual(self.view.called, True) + + +if __name__ == '__main__': + unittest.main(verbosity=2) diff --git a/Lib/idlelib/textView.py b/Lib/idlelib/textView.py index 01b2d8f..12ac319 100644 --- a/Lib/idlelib/textView.py +++ b/Lib/idlelib/textView.py @@ -76,6 +76,10 @@ def view_file(parent, title, filename, encoding=None, modal=True): tkMessageBox.showerror(title='File Load Error', message='Unable to load file %r .' % filename, parent=parent) + except UnicodeDecodeError as err: + tkMessageBox.showerror(title='Unicode Decode Error', + message=str(err), + parent=parent) else: return view_text(parent, title, contents, modal) -- cgit v0.12 From dcb6c88a240fea82da8867d1de1022a4555f22b4 Mon Sep 17 00:00:00 2001 From: Terry Jan Reedy Date: Wed, 22 Jun 2016 22:46:34 -0400 Subject: Issue #27304: Source code links for sub-packages in the same file. Patch by Yoni Lavi --- Doc/library/dbm.rst | 10 ++++++++++ Doc/library/importlib.rst | 14 ++++++++++++++ Doc/library/json.rst | 8 +++++++- 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/Doc/library/dbm.rst b/Doc/library/dbm.rst index 6f64196..2a1db91 100644 --- a/Doc/library/dbm.rst +++ b/Doc/library/dbm.rst @@ -128,6 +128,9 @@ The individual submodules are described in the following sections. :platform: Unix :synopsis: GNU's reinterpretation of dbm. +**Source code:** :source:`Lib/dbm/gnu.py` + +-------------- This module is quite similar to the :mod:`dbm` module, but uses the GNU library ``gdbm`` instead to provide some additional functionality. Please note that the @@ -237,6 +240,9 @@ supported. :platform: Unix :synopsis: The standard "database" interface, based on ndbm. +**Source code:** :source:`Lib/dbm/ndbm.py` + +-------------- The :mod:`dbm.ndbm` module provides an interface to the Unix "(n)dbm" library. Dbm objects behave like mappings (dictionaries), except that keys and values are @@ -299,6 +305,8 @@ to locate the appropriate header file to simplify building this module. .. module:: dbm.dumb :synopsis: Portable implementation of the simple DBM interface. +**Source code:** :source:`Lib/dbm/dumb.py` + .. index:: single: databases .. note:: @@ -308,6 +316,8 @@ to locate the appropriate header file to simplify building this module. module is not written for speed and is not nearly as heavily used as the other database modules. +-------------- + The :mod:`dbm.dumb` module provides a persistent dictionary-like interface which is written entirely in Python. Unlike other modules such as :mod:`dbm.gnu` no external library is required. As with other persistent mappings, the keys and diff --git a/Doc/library/importlib.rst b/Doc/library/importlib.rst index 3302446..ff7cc91 100644 --- a/Doc/library/importlib.rst +++ b/Doc/library/importlib.rst @@ -211,6 +211,11 @@ Functions .. module:: importlib.abc :synopsis: Abstract base classes related to import +**Source code:** :source:`Lib/importlib/abc.py` + +-------------- + + The :mod:`importlib.abc` module contains all of the core abstract base classes used by :keyword:`import`. Some subclasses of the core abstract base classes are also provided to help in implementing the core ABCs. @@ -700,6 +705,10 @@ ABC hierarchy:: .. module:: importlib.machinery :synopsis: Importers and path hooks +**Source code:** :source:`Lib/importlib/machinery.py` + +-------------- + This module contains the various objects that help :keyword:`import` find and load modules. @@ -1082,6 +1091,11 @@ find and load modules. .. module:: importlib.util :synopsis: Utility code for importers + +**Source code:** :source:`Lib/importlib/util.py` + +-------------- + This module contains the various objects that help in the construction of an :term:`importer`. diff --git a/Doc/library/json.rst b/Doc/library/json.rst index 174e734..1e34cf3 100644 --- a/Doc/library/json.rst +++ b/Doc/library/json.rst @@ -629,13 +629,19 @@ when serializing instances of "exotic" numerical types such as :class:`decimal.Decimal`. .. highlight:: bash -.. module:: json.tool .. _json-commandline: Command Line Interface ---------------------- +.. module:: json.tool + :synopsis: A command line to validate and pretty-print JSON. + +**Source code:** :source:`Lib/json/tool.py` + +-------------- + The :mod:`json.tool` module provides a simple command line interface to validate and pretty-print JSON objects. -- cgit v0.12 From 9e941d6373ea5e233a26e5fb0af6731d88f14049 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Thu, 23 Jun 2016 23:55:34 +0300 Subject: Fixed integer overflow in array.buffer_info(). --- Modules/arraymodule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c index f73c599..2803177 100644 --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -1268,7 +1268,7 @@ array_array_buffer_info_impl(arrayobject *self) } PyTuple_SET_ITEM(retval, 0, v); - v = PyLong_FromLong((long)(Py_SIZE(self))); + v = PyLong_FromSsize_t(Py_SIZE(self)); if (v == NULL) { Py_DECREF(retval); return NULL; -- cgit v0.12 From 91d53e7b20baf5b9b58cb9737b8871793c23fd7b Mon Sep 17 00:00:00 2001 From: Berker Peksag Date: Fri, 24 Jun 2016 08:48:27 +0300 Subject: Make PyPIRCCommandTestCase derive from a base class Several test cases in distutils use PyPIRCCommandTestCase as their base class and as a result of that the following tests were ran more than once: * test_server_registration * test_server_empty_registration * test_config_interpolation This commit moves the infrastructure used by other tests into a new BasePyPIRCCommandTestCase class. --- Lib/distutils/tests/test_config.py | 9 ++++++--- Lib/distutils/tests/test_register.py | 4 ++-- Lib/distutils/tests/test_sdist.py | 4 ++-- Lib/distutils/tests/test_upload.py | 4 ++-- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/Lib/distutils/tests/test_config.py b/Lib/distutils/tests/test_config.py index 0b91d19..3dd92d6 100644 --- a/Lib/distutils/tests/test_config.py +++ b/Lib/distutils/tests/test_config.py @@ -52,14 +52,14 @@ password:xxx """ -class PyPIRCCommandTestCase(support.TempdirManager, +class BasePyPIRCCommandTestCase(support.TempdirManager, support.LoggingSilencer, support.EnvironGuard, unittest.TestCase): def setUp(self): """Patches the environment.""" - super(PyPIRCCommandTestCase, self).setUp() + super(BasePyPIRCCommandTestCase, self).setUp() self.tmp_dir = self.mkdtemp() os.environ['HOME'] = self.tmp_dir self.rc = os.path.join(self.tmp_dir, '.pypirc') @@ -78,7 +78,10 @@ class PyPIRCCommandTestCase(support.TempdirManager, def tearDown(self): """Removes the patch.""" set_threshold(self.old_threshold) - super(PyPIRCCommandTestCase, self).tearDown() + super(BasePyPIRCCommandTestCase, self).tearDown() + + +class PyPIRCCommandTestCase(BasePyPIRCCommandTestCase): def test_server_registration(self): # This test makes sure PyPIRCCommand knows how to: diff --git a/Lib/distutils/tests/test_register.py b/Lib/distutils/tests/test_register.py index 01acf23..e68b0af 100644 --- a/Lib/distutils/tests/test_register.py +++ b/Lib/distutils/tests/test_register.py @@ -12,7 +12,7 @@ from distutils.command.register import register from distutils.errors import DistutilsSetupError from distutils.log import INFO -from distutils.tests.test_config import PyPIRCCommandTestCase +from distutils.tests.test_config import BasePyPIRCCommandTestCase try: import docutils @@ -72,7 +72,7 @@ class FakeOpener(object): }.get(name.lower(), default) -class RegisterTestCase(PyPIRCCommandTestCase): +class RegisterTestCase(BasePyPIRCCommandTestCase): def setUp(self): super(RegisterTestCase, self).setUp() diff --git a/Lib/distutils/tests/test_sdist.py b/Lib/distutils/tests/test_sdist.py index 5a04e0d..5444b81 100644 --- a/Lib/distutils/tests/test_sdist.py +++ b/Lib/distutils/tests/test_sdist.py @@ -23,7 +23,7 @@ except ImportError: from distutils.command.sdist import sdist, show_formats from distutils.core import Distribution -from distutils.tests.test_config import PyPIRCCommandTestCase +from distutils.tests.test_config import BasePyPIRCCommandTestCase from distutils.errors import DistutilsOptionError from distutils.spawn import find_executable from distutils.log import WARN @@ -52,7 +52,7 @@ somecode%(sep)sdoc.dat somecode%(sep)sdoc.txt """ -class SDistTestCase(PyPIRCCommandTestCase): +class SDistTestCase(BasePyPIRCCommandTestCase): def setUp(self): # PyPIRCCommandTestCase creates a temp dir already diff --git a/Lib/distutils/tests/test_upload.py b/Lib/distutils/tests/test_upload.py index 3eecf8a..e836cc4 100644 --- a/Lib/distutils/tests/test_upload.py +++ b/Lib/distutils/tests/test_upload.py @@ -12,7 +12,7 @@ from distutils.core import Distribution from distutils.errors import DistutilsError from distutils.log import ERROR, INFO -from distutils.tests.test_config import PYPIRC, PyPIRCCommandTestCase +from distutils.tests.test_config import PYPIRC, BasePyPIRCCommandTestCase PYPIRC_LONG_PASSWORD = """\ [distutils] @@ -66,7 +66,7 @@ class FakeOpen(object): return self.code -class uploadTestCase(PyPIRCCommandTestCase): +class uploadTestCase(BasePyPIRCCommandTestCase): def setUp(self): super(uploadTestCase, self).setUp() -- cgit v0.12 From 79af27ef2e59025fdcfc02233cb9772363065bed Mon Sep 17 00:00:00 2001 From: Berker Peksag Date: Fri, 24 Jun 2016 08:54:43 +0300 Subject: Issue #27378: Remove an outdated reference from regex HOWTO Patch by Matt Morrison. --- Doc/howto/regex.rst | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Doc/howto/regex.rst b/Doc/howto/regex.rst index de3f461..371ef59 100644 --- a/Doc/howto/regex.rst +++ b/Doc/howto/regex.rst @@ -374,9 +374,7 @@ module. If you have :mod:`tkinter` available, you may also want to look at :source:`Tools/demo/redemo.py`, a demonstration program included with the Python distribution. It allows you to enter REs and strings, and displays whether the RE matches or fails. :file:`redemo.py` can be quite useful when -trying to debug a complicated RE. Phil Schwartz's `Kodos -`_ is also an interactive tool for developing and -testing RE patterns. +trying to debug a complicated RE. This HOWTO uses the standard Python interpreter for its examples. First, run the Python interpreter, import the :mod:`re` module, and compile a RE:: -- cgit v0.12 From 37e87e6ec116b0e0e41e9623eec2743c78d96b5c Mon Sep 17 00:00:00 2001 From: Berker Peksag Date: Fri, 24 Jun 2016 09:12:01 +0300 Subject: Issue #26547: Remove outdated term dictproxy from vars() documentation dictproxy was used in Python 2 and it was renamed to mappingproxy in Python 3.3. Patch by Julien. --- Doc/library/functions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index e609463..efa5bd3 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -1469,7 +1469,7 @@ are always available. They are listed here in alphabetical order. Objects such as modules and instances have an updateable :attr:`~object.__dict__` attribute; however, other objects may have write restrictions on their :attr:`~object.__dict__` attributes (for example, classes use a - dictproxy to prevent direct dictionary updates). + :class:`types.MappingProxyType` to prevent direct dictionary updates). Without an argument, :func:`vars` acts like :func:`locals`. Note, the locals dictionary is only useful for reads since updates to the locals -- cgit v0.12 From e495646a9702935ae47f01c4fd06b62328bf11cb Mon Sep 17 00:00:00 2001 From: Berker Peksag Date: Fri, 24 Jun 2016 09:28:50 +0300 Subject: Issue #18300: Set TERM='' by default in assert_python_* --- Lib/test/support/script_helper.py | 4 ++++ Lib/test/test_doctest.py | 24 +++++++++--------------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/Lib/test/support/script_helper.py b/Lib/test/support/script_helper.py index 9c2e9eb..c45d010 100644 --- a/Lib/test/support/script_helper.py +++ b/Lib/test/support/script_helper.py @@ -73,6 +73,10 @@ def run_python_until_end(*args, **env_vars): # Need to preserve the original environment, for in-place testing of # shared library builds. env = os.environ.copy() + # set TERM='' unless the TERM environment variable is passed explicitly + # see issues #11390 and #18300 + if 'TERM' not in env_vars: + env['TERM'] = '' # But a special flag that can be set to override -- in this case, the # caller is responsible to pass the full environment. if env_vars.pop('__cleanenv', None): diff --git a/Lib/test/test_doctest.py b/Lib/test/test_doctest.py index 29426a3..33163b9 100644 --- a/Lib/test/test_doctest.py +++ b/Lib/test/test_doctest.py @@ -2719,12 +2719,6 @@ output into something we can doctest against: >>> def normalize(s): ... return '\n'.join(s.decode().splitlines()) -Note: we also pass TERM='' to all the assert_python calls to avoid a bug -in the readline library that is triggered in these tests because we are -running them in a new python process. See: - - http://lists.gnu.org/archive/html/bug-readline/2013-06/msg00000.html - With those preliminaries out of the way, we'll start with a file with two simple tests and no errors. We'll run both the unadorned doctest command, and the verbose version, and then check the output: @@ -2741,9 +2735,9 @@ the verbose version, and then check the output: ... _ = f.write('\n') ... _ = f.write('And that is it.\n') ... rc1, out1, err1 = script_helper.assert_python_ok( - ... '-m', 'doctest', fn, TERM='') + ... '-m', 'doctest', fn) ... rc2, out2, err2 = script_helper.assert_python_ok( - ... '-m', 'doctest', '-v', fn, TERM='') + ... '-m', 'doctest', '-v', fn) With no arguments and passing tests, we should get no output: @@ -2806,17 +2800,17 @@ text files). ... _ = f.write(' \"\"\"\n') ... import shutil ... rc1, out1, err1 = script_helper.assert_python_failure( - ... '-m', 'doctest', fn, fn2, TERM='') + ... '-m', 'doctest', fn, fn2) ... rc2, out2, err2 = script_helper.assert_python_ok( - ... '-m', 'doctest', '-o', 'ELLIPSIS', fn, TERM='') + ... '-m', 'doctest', '-o', 'ELLIPSIS', fn) ... rc3, out3, err3 = script_helper.assert_python_ok( ... '-m', 'doctest', '-o', 'ELLIPSIS', - ... '-o', 'NORMALIZE_WHITESPACE', fn, fn2, TERM='') + ... '-o', 'NORMALIZE_WHITESPACE', fn, fn2) ... rc4, out4, err4 = script_helper.assert_python_failure( - ... '-m', 'doctest', '-f', fn, fn2, TERM='') + ... '-m', 'doctest', '-f', fn, fn2) ... rc5, out5, err5 = script_helper.assert_python_ok( ... '-m', 'doctest', '-v', '-o', 'ELLIPSIS', - ... '-o', 'NORMALIZE_WHITESPACE', fn, fn2, TERM='') + ... '-o', 'NORMALIZE_WHITESPACE', fn, fn2) Our first test run will show the errors from the first file (doctest stops if a file has errors). Note that doctest test-run error output appears on stdout, @@ -2922,7 +2916,7 @@ We should also check some typical error cases. Invalid file name: >>> rc, out, err = script_helper.assert_python_failure( - ... '-m', 'doctest', 'nosuchfile', TERM='') + ... '-m', 'doctest', 'nosuchfile') >>> rc, out (1, b'') >>> print(normalize(err)) # doctest: +ELLIPSIS @@ -2933,7 +2927,7 @@ Invalid file name: Invalid doctest option: >>> rc, out, err = script_helper.assert_python_failure( - ... '-m', 'doctest', '-o', 'nosuchoption', TERM='') + ... '-m', 'doctest', '-o', 'nosuchoption') >>> rc, out (2, b'') >>> print(normalize(err)) # doctest: +ELLIPSIS -- cgit v0.12 From a0643829252f523e0b607ec3674da748f5306d7b Mon Sep 17 00:00:00 2001 From: Berker Peksag Date: Fri, 24 Jun 2016 12:56:50 +0300 Subject: Issue #27381: Remove superfluous paren in zipfile documentation --- Doc/library/zipfile.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/zipfile.rst b/Doc/library/zipfile.rst index a773769..abe38c4 100644 --- a/Doc/library/zipfile.rst +++ b/Doc/library/zipfile.rst @@ -250,7 +250,7 @@ ZipFile Objects .. method:: ZipFile.extract(member, path=None, pwd=None) Extract a member from the archive to the current working directory; *member* - must be its full name or a :class:`ZipInfo` object). Its file information is + must be its full name or a :class:`ZipInfo` object. Its file information is extracted as accurately as possible. *path* specifies a different directory to extract to. *member* can be a filename or a :class:`ZipInfo` object. *pwd* is the password used for encrypted files. -- cgit v0.12 From 33f7310c5eeedf12690c3548e3315dbbfff6b770 Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Fri, 24 Jun 2016 10:32:15 -0700 Subject: Adds scripts for producing Nuget packages. --- Tools/msi/make_zip.py | 28 +++++++++++++----------- Tools/nuget/make_pkg.proj | 51 ++++++++++++++++++++++++++++++++++++++++++++ Tools/nuget/python.nuspec | 18 ++++++++++++++++ Tools/nuget/pythonx86.nuspec | 18 ++++++++++++++++ 4 files changed, 103 insertions(+), 12 deletions(-) create mode 100644 Tools/nuget/make_pkg.proj create mode 100644 Tools/nuget/python.nuspec create mode 100644 Tools/nuget/pythonx86.nuspec diff --git a/Tools/msi/make_zip.py b/Tools/msi/make_zip.py index 753ba0f..2fb40d1 100644 --- a/Tools/msi/make_zip.py +++ b/Tools/msi/make_zip.py @@ -75,10 +75,12 @@ def include_in_tools(p): return p.suffix.lower() in {'.py', '.pyw', '.txt'} FULL_LAYOUT = [ - ('/', 'PCBuild/$arch', 'python*.exe', is_not_debug), - ('/', 'PCBuild/$arch', 'python*.dll', is_not_debug), + ('/', 'PCBuild/$arch', 'python.exe', is_not_debug), + ('/', 'PCBuild/$arch', 'pythonw.exe', is_not_debug), + ('/', 'PCBuild/$arch', 'python{0.major}.dll'.format(sys.version_info), is_not_debug), + ('/', 'PCBuild/$arch', 'python{0.major}{0.minor}.dll'.format(sys.version_info), is_not_debug), ('DLLs/', 'PCBuild/$arch', '*.pyd', is_not_debug), - ('DLLs/', 'PCBuild/$arch', '*.dll', is_not_debug), + ('DLLs/', 'PCBuild/$arch', '*.dll', is_not_debug_or_python), ('include/', 'include', '*.h', None), ('include/', 'PC', 'pyconfig.h', None), ('Lib/', 'Lib', '**/*', include_in_lib), @@ -150,17 +152,17 @@ def rglob(root, pattern, condition): def main(): parser = argparse.ArgumentParser() parser.add_argument('-s', '--source', metavar='dir', help='The directory containing the repository root', type=Path) - parser.add_argument('-o', '--out', metavar='file', help='The name of the output self-extracting archive', type=Path, required=True) + parser.add_argument('-o', '--out', metavar='file', help='The name of the output self-extracting archive', type=Path, default=None) parser.add_argument('-t', '--temp', metavar='dir', help='A directory to temporarily extract files into', type=Path, default=None) parser.add_argument('-e', '--embed', help='Create an embedding layout', action='store_true', default=False) parser.add_argument('-a', '--arch', help='Specify the architecture to use (win32/amd64)', type=str, default="win32") ns = parser.parse_args() - source = ns.source or (Path(__file__).parent.parent.parent) + source = ns.source or (Path(__file__).resolve().parent.parent.parent) out = ns.out arch = ns.arch assert isinstance(source, Path) - assert isinstance(out, Path) + assert not out or isinstance(out, Path) assert isinstance(arch, str) if ns.temp: @@ -170,10 +172,11 @@ def main(): temp = Path(tempfile.mkdtemp()) delete_temp = True - try: - out.parent.mkdir(parents=True) - except FileExistsError: - pass + if out: + try: + out.parent.mkdir(parents=True) + except FileExistsError: + pass try: temp.mkdir(parents=True) except FileExistsError: @@ -190,8 +193,9 @@ def main(): with open(str(temp / 'pyvenv.cfg'), 'w') as f: print('applocal = true', file=f) - total = copy_to_layout(out, rglob(temp, '*', None)) - print('Wrote {} files to {}'.format(total, out)) + if out: + total = copy_to_layout(out, rglob(temp, '**/*', None)) + print('Wrote {} files to {}'.format(total, out)) finally: if delete_temp: shutil.rmtree(temp, True) diff --git a/Tools/nuget/make_pkg.proj b/Tools/nuget/make_pkg.proj new file mode 100644 index 0000000..812349a --- /dev/null +++ b/Tools/nuget/make_pkg.proj @@ -0,0 +1,51 @@ + + + + {10487945-15D1-4092-A214-338395C4116B} + python + $(OutputName)x86 + + false + + + + + + $(ExternalsDir)\windows-installer\nuget\nuget.exe + $(MajorVersionNumber).$(MinorVersionNumber).$(MicroVersionNumber) + false + $(OutputName).$(NuspecVersion) + .nupkg + $(OutputPath)\en-us\$(TargetName)$(TargetExt) + $(IntermediateOutputPath)\nuget_$(ArchName) + + rmdir /q/s "$(IntermediateOutputPath)" + + "$(PythonExe)" "$(MSBuildThisFileDirectory)\..\msi\make_zip.py" + $(PythonArguments) -t "$(IntermediateOutputPath)" -a $(ArchName) + + "$(Nuget)" pack "$(MSBuildThisFileDirectory)\$(OutputName).nuspec" + $(NugetArguments) -BasePath "$(IntermediateOutputPath)" + $(NugetArguments) -OutputDirectory "$(OutputPath)\en-us" + $(NugetArguments) -Version "$(NuspecVersion)" + $(NugetArguments) -NoPackageAnalysis -NonInteractive + + setlocal +set DOC_FILENAME=python$(PythonVersion).chm +set VCREDIST_PATH=$(VS140COMNTOOLS)\..\..\VC\redist\$(Platform)\Microsoft.VC140.CRT + + + + + + + + + + + + + + diff --git a/Tools/nuget/python.nuspec b/Tools/nuget/python.nuspec new file mode 100644 index 0000000..b3c5c34 --- /dev/null +++ b/Tools/nuget/python.nuspec @@ -0,0 +1,18 @@ + + + + python + Python + 0.0.0.0 + Python Software Foundation + https://docs.python.org/3/license.html + https://www.python.org/ + false + Installs 64-bit Python for use in build scenarios. + https://www.python.org/static/favicon.ico + python + + + + + diff --git a/Tools/nuget/pythonx86.nuspec b/Tools/nuget/pythonx86.nuspec new file mode 100644 index 0000000..b55c879 --- /dev/null +++ b/Tools/nuget/pythonx86.nuspec @@ -0,0 +1,18 @@ + + + + pythonx86 + Python (32-bit) + Python Software Foundation + 0.0.0.0 + https://docs.python.org/3/license.html + https://www.python.org/ + false + Installs 32-bit Python for use in build scenarios. + https://www.python.org/static/favicon.ico + python + + + + + -- cgit v0.12 From 3f9fbfcdd420a3277dcebbf61cd830b7626539a5 Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Fri, 24 Jun 2016 11:37:50 -0700 Subject: Preinstalls pip into the nuget package so that pip.exe is available after installation. --- Tools/nuget/make_pkg.proj | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Tools/nuget/make_pkg.proj b/Tools/nuget/make_pkg.proj index 812349a..15e6d8f 100644 --- a/Tools/nuget/make_pkg.proj +++ b/Tools/nuget/make_pkg.proj @@ -24,6 +24,8 @@ "$(PythonExe)" "$(MSBuildThisFileDirectory)\..\msi\make_zip.py" $(PythonArguments) -t "$(IntermediateOutputPath)" -a $(ArchName) + "$(IntermediateOutputPath)\python.exe" -B -c "import sys; sys.path.append('$(PySourcePath)\Lib'); import ensurepip; ensurepip._main()" + "$(Nuget)" pack "$(MSBuildThisFileDirectory)\$(OutputName).nuspec" $(NugetArguments) -BasePath "$(IntermediateOutputPath)" $(NugetArguments) -OutputDirectory "$(OutputPath)\en-us" @@ -40,9 +42,10 @@ set VCREDIST_PATH=$(VS140COMNTOOLS)\..\..\VC\redist\$(Platform)\Microsoft.VC140. + + -- cgit v0.12 From 559ad5d401229399e7bc887b62a87d9f69206fa6 Mon Sep 17 00:00:00 2001 From: Brett Cannon Date: Fri, 24 Jun 2016 12:22:14 -0700 Subject: Remove a stale reference to pathlib.PurePath.path --- Doc/library/os.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Doc/library/os.rst b/Doc/library/os.rst index 7b26953..e73d8ee 100644 --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -2053,9 +2053,8 @@ features: 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. + particular, the ``name`` attribute has the same meaning, as do the + ``is_dir()``, ``is_file()``, ``is_symlink()`` and ``stat()`` methods. .. versionadded:: 3.5 -- cgit v0.12 From e92dc9c23da8cb11f922f28353e6a58928aa5c71 Mon Sep 17 00:00:00 2001 From: Brett Cannon Date: Sat, 25 Jun 2016 10:47:53 -0700 Subject: Fix a scoping issue where an UnboundLocalError was triggered if a lazy-loaded module was already in sys.modules. --- Lib/importlib/util.py | 2 +- Lib/test/test_importlib/test_lazy.py | 16 +++++++++++++--- Misc/NEWS | 4 ++++ 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/Lib/importlib/util.py b/Lib/importlib/util.py index 4525b3f..e1fa07a 100644 --- a/Lib/importlib/util.py +++ b/Lib/importlib/util.py @@ -241,7 +241,7 @@ class _LazyModule(types.ModuleType): if id(self) != id(sys.modules[original_name]): msg = ('module object for {!r} substituted in sys.modules ' 'during a lazy load') - raise ValueError(msg.format(original_name)) + raise ValueError(msg.format(original_name)) # Update after loading since that's what would happen in an eager # loading situation. self.__dict__.update(attrs_updated) diff --git a/Lib/test/test_importlib/test_lazy.py b/Lib/test/test_importlib/test_lazy.py index 774b7a4..cc383c2 100644 --- a/Lib/test/test_importlib/test_lazy.py +++ b/Lib/test/test_importlib/test_lazy.py @@ -1,6 +1,8 @@ import importlib from importlib import abc from importlib import util +import sys +import types import unittest from . import util as test_util @@ -122,12 +124,20 @@ class LazyLoaderTests(unittest.TestCase): self.assertFalse(hasattr(module, '__name__')) def test_module_substitution_error(self): - source_code = 'import sys; sys.modules[__name__] = 42' - module = self.new_module(source_code) with test_util.uncache(TestingImporter.module_name): - with self.assertRaises(ValueError): + fresh_module = types.ModuleType(TestingImporter.module_name) + sys.modules[TestingImporter.module_name] = fresh_module + module = self.new_module() + with self.assertRaisesRegex(ValueError, "substituted"): module.__name__ + def test_module_already_in_sys(self): + with test_util.uncache(TestingImporter.module_name): + module = self.new_module() + sys.modules[TestingImporter.module_name] = module + # Force the load; just care that no exception is raised. + module.__name__ + if __name__ == '__main__': unittest.main() diff --git a/Misc/NEWS b/Misc/NEWS index 49304ba..f580afe 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,10 @@ Core and Builtins Library ------- +- Fix a scoping issue in importlib.util.LazyLoader which triggered an + UnboundLocalError when lazy-loading a module that was already put into + sys.modules. + - Issue #27079: Fixed curses.ascii functions isblank(), iscntrl() and ispunct(). - Issue #26754: Some functions (compile() etc) accepted a filename argument -- cgit v0.12 From e7614dd07d533ec4f22007d65649175b9dee8be4 Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Sat, 25 Jun 2016 16:13:30 -0700 Subject: Simplifies nuget build with better parameters. --- Tools/nuget/make_pkg.proj | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Tools/nuget/make_pkg.proj b/Tools/nuget/make_pkg.proj index 15e6d8f..bd3fad8 100644 --- a/Tools/nuget/make_pkg.proj +++ b/Tools/nuget/make_pkg.proj @@ -6,6 +6,7 @@ $(OutputName)x86 false + true @@ -24,7 +25,7 @@ "$(PythonExe)" "$(MSBuildThisFileDirectory)\..\msi\make_zip.py" $(PythonArguments) -t "$(IntermediateOutputPath)" -a $(ArchName) - "$(IntermediateOutputPath)\python.exe" -B -c "import sys; sys.path.append('$(PySourcePath)\Lib'); import ensurepip; ensurepip._main()" + "$(IntermediateOutputPath)\python.exe" -B -c "import sys; sys.path.append(r'$(PySourcePath)\Lib'); import ensurepip; ensurepip._main()" "$(Nuget)" pack "$(MSBuildThisFileDirectory)\$(OutputName).nuspec" $(NugetArguments) -BasePath "$(IntermediateOutputPath)" -- cgit v0.12 From 745a407df88f2c5baacb4e61d8e37e7ed5d4671f Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sun, 26 Jun 2016 17:42:23 +0300 Subject: Issue #22115: Fixed tracing Tkinter variables: * tracing in the "u" mode now works * trace_vdelete() with wrong mode no longer break tracing * trace_vinfo() now always returns a list of pairs of strings --- Lib/tkinter/__init__.py | 19 +++++---- Lib/tkinter/test/test_tkinter/test_variables.py | 51 ++++++++++++++++++++++++- Misc/NEWS | 4 ++ 3 files changed, 66 insertions(+), 8 deletions(-) diff --git a/Lib/tkinter/__init__.py b/Lib/tkinter/__init__.py index aa646dc..55bfb7f 100644 --- a/Lib/tkinter/__init__.py +++ b/Lib/tkinter/__init__.py @@ -271,7 +271,7 @@ class Variable: Return the name of the callback. """ - f = CallWrapper(callback, None, self).__call__ + f = CallWrapper(callback, None, self._root).__call__ cbname = repr(id(f)) try: callback = callback.__func__ @@ -295,14 +295,19 @@ class Variable: CBNAME is the name of the callback returned from trace_variable or trace. """ self._tk.call("trace", "vdelete", self._name, mode, cbname) - self._tk.deletecommand(cbname) - try: - self._tclCommands.remove(cbname) - except ValueError: - pass + cbname = self._tk.splitlist(cbname)[0] + for m, ca in self.trace_vinfo(): + if self._tk.splitlist(ca)[0] == cbname: + break + else: + self._tk.deletecommand(cbname) + try: + self._tclCommands.remove(cbname) + except ValueError: + pass def trace_vinfo(self): """Return all trace callback information.""" - return [self._tk.split(x) for x in self._tk.splitlist( + return [self._tk.splitlist(x) for x in self._tk.splitlist( self._tk.call("trace", "vinfo", self._name))] def __eq__(self, other): """Comparison for equality (==). diff --git a/Lib/tkinter/test/test_tkinter/test_variables.py b/Lib/tkinter/test/test_tkinter/test_variables.py index abdce96..1f74453 100644 --- a/Lib/tkinter/test/test_tkinter/test_variables.py +++ b/Lib/tkinter/test/test_tkinter/test_variables.py @@ -1,5 +1,5 @@ import unittest - +import gc from tkinter import (Variable, StringVar, IntVar, DoubleVar, BooleanVar, Tcl, TclError) @@ -87,6 +87,55 @@ class TestVariable(TestBase): v.set("value") self.assertTrue(v.side_effect) + def test_trace(self): + v = Variable(self.root) + vname = str(v) + trace = [] + def read_tracer(*args): + trace.append(('read',) + args) + def write_tracer(*args): + trace.append(('write',) + args) + cb1 = v.trace_variable('r', read_tracer) + cb2 = v.trace_variable('wu', write_tracer) + self.assertEqual(sorted(v.trace_vinfo()), [('r', cb1), ('wu', cb2)]) + self.assertEqual(trace, []) + + v.set('spam') + self.assertEqual(trace, [('write', vname, '', 'w')]) + + trace = [] + v.get() + self.assertEqual(trace, [('read', vname, '', 'r')]) + + trace = [] + info = sorted(v.trace_vinfo()) + v.trace_vdelete('w', cb1) # Wrong mode + self.assertEqual(sorted(v.trace_vinfo()), info) + with self.assertRaises(TclError): + v.trace_vdelete('r', 'spam') # Wrong command name + self.assertEqual(sorted(v.trace_vinfo()), info) + v.trace_vdelete('r', (cb1, 43)) # Wrong arguments + self.assertEqual(sorted(v.trace_vinfo()), info) + v.get() + self.assertEqual(trace, [('read', vname, '', 'r')]) + + trace = [] + v.trace_vdelete('r', cb1) + self.assertEqual(v.trace_vinfo(), [('wu', cb2)]) + v.get() + self.assertEqual(trace, []) + + trace = [] + del write_tracer + gc.collect() + v.set('eggs') + self.assertEqual(trace, [('write', vname, '', 'w')]) + + trace = [] + del v + gc.collect() + self.assertEqual(trace, [('write', vname, '', 'u')]) + class TestStringVar(TestBase): diff --git a/Misc/NEWS b/Misc/NEWS index f580afe..cc53bcd 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,10 @@ Core and Builtins Library ------- +- Issue #22115: Fixed tracing Tkinter variables: trace_vdelete() with wrong + mode no longer break tracing, trace_vinfo() now always returns a list of + pairs of strings, tracing in the "u" mode now works. + - Fix a scoping issue in importlib.util.LazyLoader which triggered an UnboundLocalError when lazy-loading a module that was already put into sys.modules. -- cgit v0.12 From 1e957d145fa1fc05ca1fbb9f135ab162c939ae14 Mon Sep 17 00:00:00 2001 From: Terry Jan Reedy Date: Sun, 26 Jun 2016 18:20:20 -0400 Subject: Update NEWS and idlelib NEWS.text. --- Lib/idlelib/NEWS.txt | 13 ++++++++++++- Misc/NEWS | 9 +++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt index 00d5005..6ef2aa5 100644 --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -1,6 +1,17 @@ +What's New in IDLE 3.5.3? +========================= +*Release date: 2017-01-01?* + +- Issue #27365: Allow non-ascii chars in IDLE NEWS.txt, for contributor names. + +- Issue #27245: IDLE: Cleanly delete custom themes and key bindings. + Previously, when IDLE was started from a console or by import, a cascade + of warnings was emitted. Patch by Serhiy Storchaka. + + What's New in IDLE 3.5.2? ========================= -*Release date: 2016-06-30?* +*Release date: 2016-06-26* - Issue #5124: Paste with text selected now replaces the selection on X11. This matches how paste works on Windows, Mac, most modern Linux apps, diff --git a/Misc/NEWS b/Misc/NEWS index cc53bcd..08aafb8 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -57,6 +57,15 @@ Library - Issue #26930: Update Windows builds to use OpenSSL 1.0.2h. +IDLE +---- + +- Issue #27365: Allow non-ascii chars in IDLE NEWS.txt, for contributor names. + +- Issue #27245: IDLE: Cleanly delete custom themes and key bindings. + Previously, when IDLE was started from a console or by import, a cascade + of warnings was emitted. Patch by Serhiy Storchaka. + C API ----- -- cgit v0.12