This function is safe to call before :c:func:`Py_Initialize`.
+ .. audit-event:: setopencodehook "" c.PyFile_SetOpenCodeHook
+
.. versionadded:: 3.8
If *bases* is a tuple, the created heap type contains all types contained
in it as base types.
- If *bases* is ``NULL``, the *Py_tp_base* slot is used instead.
+ If *bases* is ``NULL``, the *Py_tp_bases* slot is used instead.
+ If that also is ``NULL``, the *Py_tp_base* slot is used instead.
If that also is ``NULL``, the new type derives from :class:`object`.
The *module* argument can be used to record the module in which the new
* :c:member:`~PyBufferProcs.bf_getbuffer`
* :c:member:`~PyBufferProcs.bf_releasebuffer`
- Setting :c:data:`Py_tp_bases` may be problematic on some platforms.
+ Setting :c:data:`Py_tp_bases` or :c:data:`Py_tp_base` may be
+ problematic on some platforms.
To avoid issues, use the *bases* argument of
:py:func:`PyType_FromSpecWithBases` instead.
PyType_FromSpec:PyObject*::+1:
PyType_FromSpec:PyType_Spec*:spec::
+PyType_FromModuleAndSpec:PyObject*::+1:
+PyType_FromModuleAndSpec:PyObject*:module:+1:
+PyType_FromModuleAndSpec:PyType_Spec*:spec::
+PyType_FromModuleAndSpec:PyObject*:bases:0:
+
PyType_FromSpecWithBases:PyObject*::+1:
PyType_FromSpecWithBases:PyType_Spec*:spec::
PyType_FromSpecWithBases:PyObject*:bases:0:
f()
-* Use :func:`locals` or :func:`eval` to resolve the function name::
+* Use :func:`locals` to resolve the function name::
def myFunc():
print("hello")
f = locals()[fname]
f()
- f = eval(fname)
- f()
-
- Note: Using :func:`eval` is slow and dangerous. If you don't have absolute
- control over the contents of the string, someone could pass a string that
- resulted in an arbitrary function being executed.
Is there an equivalent to Perl's chomp() for removing trailing newlines from strings?
-------------------------------------------------------------------------------------
How do I iterate over a sequence in reverse order?
--------------------------------------------------
-Use the :func:`reversed` built-in function, which is new in Python 2.4::
+Use the :func:`reversed` built-in function::
for x in reversed(sequence):
... # do something with x ...
This won't touch your original sequence, but build a new copy with reversed
order to iterate over.
-With Python 2.3, you can use an extended slice syntax::
-
- for x in sequence[::-1]:
- ... # do something with x ...
-
How do you remove duplicates from a list?
-----------------------------------------
into a list.
+How do you remove multiple items from a list
+--------------------------------------------
+
+As with removing duplicates, explicitly iterating in reverse with a
+delete condition is one possibility. However, it is easier and faster
+to use slice replacement with an implicit or explicit forward iteration.
+Here are three variations.::
+
+ mylist[:] = filter(keep_function, mylist)
+ mylist[:] = (x for x in mylist if keep_condition)
+ mylist[:] = [x for x in mylist if keep_condition]
+
+The list comprehension may be fastest.
+
+
How do you make an array in Python?
-----------------------------------
['else', 'sort', 'to', 'something']
-An alternative for the last step is::
-
- >>> result = []
- >>> for p in pairs: result.append(p[1])
-
-If you find this more legible, you might prefer to use this instead of the final
-list comprehension. However, it is almost twice as slow for long lists. Why?
-First, the ``append()`` operation has to reallocate memory, and while it uses
-some tricks to avoid doing that each time, it still has to do it occasionally,
-and that costs quite a bit. Second, the expression "result.append" requires an
-extra attribute lookup, and third, there's a speed reduction from having to make
-all those function calls.
-
-
Objects
=======
How can I organize my code to make it easier to change the base class?
----------------------------------------------------------------------
-You could define an alias for the base class, assign the real base class to it
-before your class definition, and use the alias throughout your class. Then all
+You could assign the base class to an alias and derive from the alias. Then all
you have to change is the value assigned to the alias. Incidentally, this trick
is also handy if you want to decide dynamically (e.g. depending on availability
of resources) which base class to use. Example::
- BaseAlias = <real base class>
+ class Base:
+ ...
+
+ BaseAlias = Base
class Derived(BaseAlias):
- def meth(self):
- BaseAlias.meth(self)
- ...
+ ...
How do I create static class data and static class methods?
How do I make an executable from a Python script?
-------------------------------------------------
-See `cx_Freeze <https://anthony-tuininga.github.io/cx_Freeze/>`_ for a distutils extension
+See `cx_Freeze <https://cx-freeze.readthedocs.io/en/latest/>`_ for a distutils extension
that allows you to create console and GUI executables from Python code.
`py2exe <http://www.py2exe.org/>`_, the most popular extension for building
Python 2.x-based executables, does not yet support Python 3 but a version that
How do I check for a keypress without blocking?
-----------------------------------------------
-Use the msvcrt module. This is a standard Windows-specific extension module.
+Use the :mod:`msvcrt` module. This is a standard Windows-specific extension module.
It defines a function ``kbhit()`` which checks whether a keyboard hit is
present, and ``getch()`` which gets one character without echoing it.
including functions, methods, properties, class methods, static methods,
and reference to super classes.
- For more information about descriptors' methods, see :ref:`descriptors`.
+ For more information about descriptors' methods, see :ref:`descriptors`
+ or the :ref:`Descriptor How To Guide <descriptorhowto>`.
dictionary
An associative array, where arbitrary keys are mapped to values. The
keys can be any object with :meth:`__hash__` and :meth:`__eq__` methods.
Called a hash in Perl.
+ dictionary comprehension
+ A compact way to process all or part of the elements in an iterable and
+ return a dictionary with the results. ``results = {n: n ** 2 for n in
+ range(10)}`` generates a dictionary containing key ``n`` mapped to
+ value ``n ** 2``. See :ref:`comprehensions`.
+
dictionary view
The objects returned from :meth:`dict.keys`, :meth:`dict.values`, and
:meth:`dict.items` are called dictionary views. They provide a dynamic
See also the :term:`single dispatch` glossary entry, the
:func:`functools.singledispatch` decorator, and :pep:`443`.
+ generic type
+ A :term:`type` that can be parameterized; typically a container like
+ :class:`list`. Used for :term:`type hints <type hint>` and
+ :term:`annotations <annotation>`.
+
+ See :pep:`483` for more details, and :mod:`typing` or
+ :ref:`generic alias type <types-genericalias>` for its uses.
GIL
See :term:`global interpreter lock`.
:meth:`index`, :meth:`__contains__`, and
:meth:`__reversed__`. Types that implement this expanded
interface can be registered explicitly using
- :func:`~abc.register`.
+ :func:`~abc.ABCMeta.register`.
+
+ set comprehension
+ A compact way to process all or part of the elements in an iterable and
+ return a set with the results. ``results = {c for c in 'abracadabra' if
+ c not in 'abc'}`` generates the set of strings ``{'r', 'd'}``. See
+ :ref:`comprehensions`.
single dispatch
A form of :term:`generic function` dispatch where the implementation is
+.. _descriptorhowto:
+
======================
Descriptor HowTo Guide
======================
.. Contents::
+
+:term:`Descriptors <descriptor>` let objects customize attribute lookup,
+storage, and deletion.
+
+This guide has four major sections:
+
+1) The "primer" gives a basic overview, moving gently from simple examples,
+ adding one feature at a time. Start here if you're new to descriptors.
+
+2) The second section shows a complete, practical descriptor example. If you
+ already know the basics, start there.
+
+3) The third section provides a more technical tutorial that goes into the
+ detailed mechanics of how descriptors work. Most people don't need this
+ level of detail.
+
+4) The last section has pure Python equivalents for built-in descriptors that
+ are written in C. Read this if you're curious about how functions turn
+ into bound methods or about the implementation of common tools like
+ :func:`classmethod`, :func:`staticmethod`, :func:`property`, and
+ :term:`__slots__`.
+
+
+Primer
+^^^^^^
+
+In this primer, we start with the most basic possible example and then we'll
+add new capabilities one by one.
+
+
+Simple example: A descriptor that returns a constant
+----------------------------------------------------
+
+The :class:`Ten` class is a descriptor that always returns the constant ``10``
+from its :meth:`__get__` method:
+
+.. testcode::
+
+ class Ten:
+ def __get__(self, obj, objtype=None):
+ return 10
+
+To use the descriptor, it must be stored as a class variable in another class:
+
+.. testcode::
+
+ class A:
+ x = 5 # Regular class attribute
+ y = Ten() # Descriptor instance
+
+An interactive session shows the difference between normal attribute lookup
+and descriptor lookup:
+
+.. doctest::
+
+ >>> a = A() # Make an instance of class A
+ >>> a.x # Normal attribute lookup
+ 5
+ >>> a.y # Descriptor lookup
+ 10
+
+In the ``a.x`` attribute lookup, the dot operator finds the key ``x`` and the
+value ``5`` in the class dictionary. In the ``a.y`` lookup, the dot operator
+finds a descriptor instance, recognized by its ``__get__`` method, and calls
+that method which returns ``10``.
+
+Note that the value ``10`` is not stored in either the class dictionary or the
+instance dictionary. Instead, the value ``10`` is computed on demand.
+
+This example shows how a simple descriptor works, but it isn't very useful.
+For retrieving constants, normal attribute lookup would be better.
+
+In the next section, we'll create something more useful, a dynamic lookup.
+
+
+Dynamic lookups
+---------------
+
+Interesting descriptors typically run computations instead of returning
+constants:
+
+.. testcode::
+
+ import os
+
+ class DirectorySize:
+
+ def __get__(self, obj, objtype=None):
+ return len(os.listdir(obj.dirname))
+
+ class Directory:
+
+ size = DirectorySize() # Descriptor instance
+
+ def __init__(self, dirname):
+ self.dirname = dirname # Regular instance attribute
+
+An interactive session shows that the lookup is dynamic — it computes
+different, updated answers each time::
+
+ >>> s = Directory('songs')
+ >>> g = Directory('games')
+ >>> s.size # The songs directory has twenty files
+ 20
+ >>> g.size # The games directory has three files
+ 3
+ >>> open('games/newfile').close() # Add a fourth file to the directory
+ >>> g.size # File count is automatically updated
+ 4
+
+Besides showing how descriptors can run computations, this example also
+reveals the purpose of the parameters to :meth:`__get__`. The *self*
+parameter is *size*, an instance of *DirectorySize*. The *obj* parameter is
+either *g* or *s*, an instance of *Directory*. It is the *obj* parameter that
+lets the :meth:`__get__` method learn the target directory. The *objtype*
+parameter is the class *Directory*.
+
+
+Managed attributes
+------------------
+
+A popular use for descriptors is managing access to instance data. The
+descriptor is assigned to a public attribute in the class dictionary while the
+actual data is stored as a private attribute in the instance dictionary. The
+descriptor's :meth:`__get__` and :meth:`__set__` methods are triggered when
+the public attribute is accessed.
+
+In the following example, *age* is the public attribute and *_age* is the
+private attribute. When the public attribute is accessed, the descriptor logs
+the lookup or update:
+
+.. testcode::
+
+ import logging
+
+ logging.basicConfig(level=logging.INFO)
+
+ class LoggedAgeAccess:
+
+ def __get__(self, obj, objtype=None):
+ value = obj._age
+ logging.info('Accessing %r giving %r', 'age', value)
+ return value
+
+ def __set__(self, obj, value):
+ logging.info('Updating %r to %r', 'age', value)
+ obj._age = value
+
+ class Person:
+
+ age = LoggedAgeAccess() # Descriptor instance
+
+ def __init__(self, name, age):
+ self.name = name # Regular instance attribute
+ self.age = age # Calls __set__()
+
+ def birthday(self):
+ self.age += 1 # Calls both __get__() and __set__()
+
+
+An interactive session shows that all access to the managed attribute *age* is
+logged, but that the regular attribute *name* is not logged:
+
+.. testcode::
+ :hide:
+
+ import logging, sys
+ logging.basicConfig(level=logging.INFO, stream=sys.stdout, force=True)
+
+.. doctest::
+
+ >>> mary = Person('Mary M', 30) # The initial age update is logged
+ INFO:root:Updating 'age' to 30
+ >>> dave = Person('David D', 40)
+ INFO:root:Updating 'age' to 40
+
+ >>> vars(mary) # The actual data is in a private attribute
+ {'name': 'Mary M', '_age': 30}
+ >>> vars(dave)
+ {'name': 'David D', '_age': 40}
+
+ >>> mary.age # Access the data and log the lookup
+ INFO:root:Accessing 'age' giving 30
+ 30
+ >>> mary.birthday() # Updates are logged as well
+ INFO:root:Accessing 'age' giving 30
+ INFO:root:Updating 'age' to 31
+
+ >>> dave.name # Regular attribute lookup isn't logged
+ 'David D'
+ >>> dave.age # Only the managed attribute is logged
+ INFO:root:Accessing 'age' giving 40
+ 40
+
+One major issue with this example is that the private name *_age* is hardwired in
+the *LoggedAgeAccess* class. That means that each instance can only have one
+logged attribute and that its name is unchangeable. In the next example,
+we'll fix that problem.
+
+
+Customized names
+----------------
+
+When a class uses descriptors, it can inform each descriptor about which
+variable name was used.
+
+In this example, the :class:`Person` class has two descriptor instances,
+*name* and *age*. When the :class:`Person` class is defined, it makes a
+callback to :meth:`__set_name__` in *LoggedAccess* so that the field names can
+be recorded, giving each descriptor its own *public_name* and *private_name*:
+
+.. testcode::
+
+ import logging
+
+ logging.basicConfig(level=logging.INFO)
+
+ class LoggedAccess:
+
+ def __set_name__(self, owner, name):
+ self.public_name = name
+ self.private_name = '_' + name
+
+ def __get__(self, obj, objtype=None):
+ value = getattr(obj, self.private_name)
+ logging.info('Accessing %r giving %r', self.public_name, value)
+ return value
+
+ def __set__(self, obj, value):
+ logging.info('Updating %r to %r', self.public_name, value)
+ setattr(obj, self.private_name, value)
+
+ class Person:
+
+ name = LoggedAccess() # First descriptor instance
+ age = LoggedAccess() # Second descriptor instance
+
+ def __init__(self, name, age):
+ self.name = name # Calls the first descriptor
+ self.age = age # Calls the second descriptor
+
+ def birthday(self):
+ self.age += 1
+
+An interactive session shows that the :class:`Person` class has called
+:meth:`__set_name__` so that the field names would be recorded. Here
+we call :func:`vars` to look up the descriptor without triggering it:
+
+.. doctest::
+
+ >>> vars(vars(Person)['name'])
+ {'public_name': 'name', 'private_name': '_name'}
+ >>> vars(vars(Person)['age'])
+ {'public_name': 'age', 'private_name': '_age'}
+
+The new class now logs access to both *name* and *age*:
+
+.. testcode::
+ :hide:
+
+ import logging, sys
+ logging.basicConfig(level=logging.INFO, stream=sys.stdout, force=True)
+
+.. doctest::
+
+ >>> pete = Person('Peter P', 10)
+ INFO:root:Updating 'name' to 'Peter P'
+ INFO:root:Updating 'age' to 10
+ >>> kate = Person('Catherine C', 20)
+ INFO:root:Updating 'name' to 'Catherine C'
+ INFO:root:Updating 'age' to 20
+
+The two *Person* instances contain only the private names::
+
+ >>> vars(pete)
+ {'_name': 'Peter P', '_age': 10}
+ >>> vars(kate)
+ {'_name': 'Catherine C', '_age': 20}
+
+
+Closing thoughts
+----------------
+
+A :term:`descriptor` is what we call any object that defines :meth:`__get__`,
+:meth:`__set__`, or :meth:`__delete__`.
+
+Optionally, descriptors can have a :meth:`__set_name__` method. This is only
+used in cases where a descriptor needs to know either the class where it was
+created or the name of class variable it was assigned to. (This method, if
+present, is called even if the class is not a descriptor.)
+
+Descriptors get invoked by the dot "operator" during attribute lookup. If a
+descriptor is accessed indirectly with ``vars(some_class)[descriptor_name]``,
+the descriptor instance is returned without invoking it.
+
+Descriptors only work when used as class variables. When put in instances,
+they have no effect.
+
+The main motivation for descriptors is to provide a hook allowing objects
+stored in class variables to control what happens during attribute lookup.
+
+Traditionally, the calling class controls what happens during lookup.
+Descriptors invert that relationship and allow the data being looked-up to
+have a say in the matter.
+
+Descriptors are used throughout the language. It is how functions turn into
+bound methods. Common tools like :func:`classmethod`, :func:`staticmethod`,
+:func:`property`, and :func:`functools.cached_property` are all implemented as
+descriptors.
+
+
+Complete Practical Example
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+In this example, we create a practical and powerful tool for locating
+notoriously hard to find data corruption bugs.
+
+
+Validator class
+---------------
+
+A validator is a descriptor for managed attribute access. Prior to storing
+any data, it verifies that the new value meets various type and range
+restrictions. If those restrictions aren't met, it raises an exception to
+prevent data corruption at its source.
+
+This :class:`Validator` class is both an :term:`abstract base class` and a
+managed attribute descriptor:
+
+.. testcode::
+
+ from abc import ABC, abstractmethod
+
+ class Validator(ABC):
+
+ def __set_name__(self, owner, name):
+ self.private_name = '_' + name
+
+ def __get__(self, obj, objtype=None):
+ return getattr(obj, self.private_name)
+
+ def __set__(self, obj, value):
+ self.validate(value)
+ setattr(obj, self.private_name, value)
+
+ @abstractmethod
+ def validate(self, value):
+ pass
+
+Custom validators need to inherit from :class:`Validator` and must supply a
+:meth:`validate` method to test various restrictions as needed.
+
+
+Custom validators
+-----------------
+
+Here are three practical data validation utilities:
+
+1) :class:`OneOf` verifies that a value is one of a restricted set of options.
+
+2) :class:`Number` verifies that a value is either an :class:`int` or
+ :class:`float`. Optionally, it verifies that a value is between a given
+ minimum or maximum.
+
+3) :class:`String` verifies that a value is a :class:`str`. Optionally, it
+ validates a given minimum or maximum length. It can validate a
+ user-defined `predicate
+ <https://en.wikipedia.org/wiki/Predicate_(mathematical_logic)>`_ as well.
+
+.. testcode::
+
+ class OneOf(Validator):
+
+ def __init__(self, *options):
+ self.options = set(options)
+
+ def validate(self, value):
+ if value not in self.options:
+ raise ValueError(f'Expected {value!r} to be one of {self.options!r}')
+
+ class Number(Validator):
+
+ def __init__(self, minvalue=None, maxvalue=None):
+ self.minvalue = minvalue
+ self.maxvalue = maxvalue
+
+ def validate(self, value):
+ if not isinstance(value, (int, float)):
+ raise TypeError(f'Expected {value!r} to be an int or float')
+ if self.minvalue is not None and value < self.minvalue:
+ raise ValueError(
+ f'Expected {value!r} to be at least {self.minvalue!r}'
+ )
+ if self.maxvalue is not None and value > self.maxvalue:
+ raise ValueError(
+ f'Expected {value!r} to be no more than {self.maxvalue!r}'
+ )
+
+ class String(Validator):
+
+ def __init__(self, minsize=None, maxsize=None, predicate=None):
+ self.minsize = minsize
+ self.maxsize = maxsize
+ self.predicate = predicate
+
+ def validate(self, value):
+ if not isinstance(value, str):
+ raise TypeError(f'Expected {value!r} to be an str')
+ if self.minsize is not None and len(value) < self.minsize:
+ raise ValueError(
+ f'Expected {value!r} to be no smaller than {self.minsize!r}'
+ )
+ if self.maxsize is not None and len(value) > self.maxsize:
+ raise ValueError(
+ f'Expected {value!r} to be no bigger than {self.maxsize!r}'
+ )
+ if self.predicate is not None and not self.predicate(value):
+ raise ValueError(
+ f'Expected {self.predicate} to be true for {value!r}'
+ )
+
+
+Practical application
+---------------------
+
+Here's how the data validators can be used in a real class:
+
+.. testcode::
+
+ class Component:
+
+ name = String(minsize=3, maxsize=10, predicate=str.isupper)
+ kind = OneOf('wood', 'metal', 'plastic')
+ quantity = Number(minvalue=0)
+
+ def __init__(self, name, kind, quantity):
+ self.name = name
+ self.kind = kind
+ self.quantity = quantity
+
+The descriptors prevent invalid instances from being created:
+
+.. doctest::
+
+ >>> Component('Widget', 'metal', 5) # Blocked: 'Widget' is not all uppercase
+ Traceback (most recent call last):
+ ...
+ ValueError: Expected <method 'isupper' of 'str' objects> to be true for 'Widget'
+
+ >>> Component('WIDGET', 'metle', 5) # Blocked: 'metle' is misspelled
+ Traceback (most recent call last):
+ ...
+ ValueError: Expected 'metle' to be one of {'metal', 'plastic', 'wood'}
+
+ >>> Component('WIDGET', 'metal', -5) # Blocked: -5 is negative
+ Traceback (most recent call last):
+ ...
+ ValueError: Expected -5 to be at least 0
+ >>> Component('WIDGET', 'metal', 'V') # Blocked: 'V' isn't a number
+ Traceback (most recent call last):
+ ...
+ TypeError: Expected 'V' to be an int or float
+
+ >>> c = Component('WIDGET', 'metal', 5) # Allowed: The inputs are valid
+
+
+Technical Tutorial
+^^^^^^^^^^^^^^^^^^
+
+What follows is a more technical tutorial for the mechanics and details of how
+descriptors work.
+
+
Abstract
--------
Defines descriptors, summarizes the protocol, and shows how descriptors are
-called. Examines a custom descriptor and several built-in Python descriptors
-including functions, properties, static methods, and class methods. Shows how
-each works by giving a pure Python equivalent and a sample application.
+called. Provides an example showing how object relational mappings work.
Learning about descriptors not only provides access to a larger toolset, it
-creates a deeper understanding of how Python works and an appreciation for the
-elegance of its design.
+creates a deeper understanding of how Python works.
-Definition and Introduction
+Definition and introduction
---------------------------
-In general, a descriptor is an object attribute with "binding behavior", one
-whose attribute access has been overridden by methods in the descriptor
-protocol. Those methods are :meth:`__get__`, :meth:`__set__`, and
-:meth:`__delete__`. If any of those methods are defined for an object, it is
-said to be a descriptor.
+In general, a descriptor is an attribute value that has one of the methods in
+the descriptor protocol. Those methods are :meth:`__get__`, :meth:`__set__`,
+and :meth:`__delete__`. If any of those methods are defined for an the
+attribute, it is said to be a :term:`descriptor`.
The default behavior for attribute access is to get, set, or delete the
attribute from an object's dictionary. For instance, ``a.x`` has a lookup chain
starting with ``a.__dict__['x']``, then ``type(a).__dict__['x']``, and
-continuing through the base classes of ``type(a)`` excluding metaclasses. If the
+continuing through the method resolution order of ``type(a)``. If the
looked-up value is an object defining one of the descriptor methods, then Python
may override the default behavior and invoke the descriptor method instead.
Where this occurs in the precedence chain depends on which descriptor methods
were defined.
Descriptors are a powerful, general purpose protocol. They are the mechanism
-behind properties, methods, static methods, class methods, and :func:`super()`.
-They are used throughout Python itself to implement the new style classes
-introduced in version 2.2. Descriptors simplify the underlying C-code and offer
-a flexible set of new tools for everyday Python programs.
+behind properties, methods, static methods, class methods, and
+:func:`super()`. They are used throughout Python itself. Descriptors
+simplify the underlying C code and offer a flexible set of new tools for
+everyday Python programs.
-Descriptor Protocol
+Descriptor protocol
-------------------
``descr.__get__(self, obj, type=None) -> value``
If an object defines :meth:`__set__` or :meth:`__delete__`, it is considered
a data descriptor. Descriptors that only define :meth:`__get__` are called
-non-data descriptors (they are typically used for methods but other uses are
+non-data descriptors (they are often used for methods but other uses are
possible).
Data and non-data descriptors differ in how overrides are calculated with
placeholder is enough to make it a data descriptor.
-Invoking Descriptors
---------------------
+Overview of descriptor invocation
+---------------------------------
+
+A descriptor can be called directly with ``desc.__get__(obj)`` or
+``desc.__get__(None, cls)``.
+
+But it is more common for a descriptor to be invoked automatically from
+attribute access.
+
+The expression ``obj.x`` looks up the attribute ``x`` in the chain of
+namespaces for ``obj``. If the search finds a descriptor outside of the
+instance ``__dict__``, its :meth:`__get__` method is invoked according to the
+precedence rules listed below.
+
+The details of invocation depend on whether ``obj`` is an object, class, or
+instance of super.
+
+
+Invocation from an instance
+---------------------------
+
+Instance lookup scans through a chain of namespaces giving data descriptors
+the highest priority, followed by instance variables, then non-data
+descriptors, then class variables, and lastly :meth:`__getattr__` if it is
+provided.
-A descriptor can be called directly by its method name. For example,
-``d.__get__(obj)``.
+If a descriptor is found for ``a.x``, then it is invoked with:
+``desc.__get__(a, type(a))``.
-Alternatively, it is more common for a descriptor to be invoked automatically
-upon attribute access. For example, ``obj.d`` looks up ``d`` in the dictionary
-of ``obj``. If ``d`` defines the method :meth:`__get__`, then ``d.__get__(obj)``
-is invoked according to the precedence rules listed below.
+The logic for a dotted lookup is in :meth:`object.__getattribute__`. Here is
+a pure Python equivalent:
-The details of invocation depend on whether ``obj`` is an object or a class.
+.. testcode::
+
+ def object_getattribute(obj, name):
+ "Emulate PyObject_GenericGetAttr() in Objects/object.c"
+ null = object()
+ objtype = type(obj)
+ cls_var = getattr(objtype, name, null)
+ descr_get = getattr(type(cls_var), '__get__', null)
+ if descr_get is not null:
+ if (hasattr(type(cls_var), '__set__')
+ or hasattr(type(cls_var), '__delete__')):
+ return descr_get(cls_var, obj, objtype) # data descriptor
+ if hasattr(obj, '__dict__') and name in vars(obj):
+ return vars(obj)[name] # instance variable
+ if descr_get is not null:
+ return descr_get(cls_var, obj, objtype) # non-data descriptor
+ if cls_var is not null:
+ return cls_var # class variable
+ raise AttributeError(name)
-For objects, the machinery is in :meth:`object.__getattribute__` which
-transforms ``b.x`` into ``type(b).__dict__['x'].__get__(b, type(b))``. The
-implementation works through a precedence chain that gives data descriptors
-priority over instance variables, instance variables priority over non-data
-descriptors, and assigns lowest priority to :meth:`__getattr__` if provided.
-The full C implementation can be found in :c:func:`PyObject_GenericGetAttr()` in
-:source:`Objects/object.c`.
-For classes, the machinery is in :meth:`type.__getattribute__` which transforms
-``B.x`` into ``B.__dict__['x'].__get__(None, B)``. In pure Python, it looks
-like::
+.. testcode::
+ :hide:
- def __getattribute__(self, key):
- "Emulate type_getattro() in Objects/typeobject.c"
- v = object.__getattribute__(self, key)
- if hasattr(v, '__get__'):
- return v.__get__(None, self)
- return v
+ # Test the fidelity of object_getattribute() by comparing it with the
+ # normal object.__getattribute__(). The former will be accessed by
+ # square brackets and the latter by the dot operator.
+
+ class Object:
+
+ def __getitem__(obj, name):
+ try:
+ return object_getattribute(obj, name)
+ except AttributeError:
+ if not hasattr(type(obj), '__getattr__'):
+ raise
+ return type(obj).__getattr__(obj, name) # __getattr__
+
+ class DualOperator(Object):
+
+ x = 10
+
+ def __init__(self, z):
+ self.z = z
+
+ @property
+ def p2(self):
+ return 2 * self.x
+
+ @property
+ def p3(self):
+ return 3 * self.x
+
+ def m5(self, y):
+ return 5 * y
+
+ def m7(self, y):
+ return 7 * y
+
+ def __getattr__(self, name):
+ return ('getattr_hook', self, name)
+
+ class DualOperatorWithSlots:
+
+ __getitem__ = Object.__getitem__
+
+ __slots__ = ['z']
+
+ x = 15
+
+ def __init__(self, z):
+ self.z = z
+
+ @property
+ def p2(self):
+ return 2 * self.x
+
+ def m5(self, y):
+ return 5 * y
+
+ def __getattr__(self, name):
+ return ('getattr_hook', self, name)
+
+
+.. doctest::
+ :hide:
+
+ >>> a = DualOperator(11)
+ >>> vars(a).update(p3 = '_p3', m7 = '_m7')
+ >>> a.x == a['x'] == 10
+ True
+ >>> a.z == a['z'] == 11
+ True
+ >>> a.p2 == a['p2'] == 20
+ True
+ >>> a.p3 == a['p3'] == 30
+ True
+ >>> a.m5(100) == a.m5(100) == 500
+ True
+ >>> a.m7 == a['m7'] == '_m7'
+ True
+ >>> a.g == a['g'] == ('getattr_hook', a, 'g')
+ True
+
+ >>> b = DualOperatorWithSlots(22)
+ >>> b.x == b['x'] == 15
+ True
+ >>> b.z == b['z'] == 22
+ True
+ >>> b.p2 == b['p2'] == 30
+ True
+ >>> b.m5(200) == b['m5'](200) == 1000
+ True
+ >>> b.g == b['g'] == ('getattr_hook', b, 'g')
+ True
+
+
+Interestingly, attribute lookup doesn't call :meth:`object.__getattribute__`
+directly. Instead, both the dot operator and the :func:`getattr` function
+perform attribute lookup by way of a helper function:
+
+.. testcode::
+
+ def getattr_hook(obj, name):
+ "Emulate slot_tp_getattr_hook() in Objects/typeobject.c"
+ try:
+ return obj.__getattribute__(name)
+ except AttributeError:
+ if not hasattr(type(obj), '__getattr__'):
+ raise
+ return type(obj).__getattr__(obj, name) # __getattr__
+
+So if :meth:`__getattr__` exists, it is called whenever :meth:`__getattribute__`
+raises :exc:`AttributeError` (either directly or in one of the descriptor calls).
+
+Also, if a user calls :meth:`object.__getattribute__` directly, the
+:meth:`__getattr__` hook is bypassed entirely.
+
+
+Invocation from a class
+-----------------------
+
+The logic for a dotted lookup such as ``A.x`` is in
+:meth:`type.__getattribute__`. The steps are similar to those for
+:meth:`object.__getattribute__` but the instance dictionary lookup is replaced
+by a search through the class's :term:`method resolution order`.
+
+If a descriptor is found, it is invoked with ``desc.__get__(None, A)``.
+
+The full C implementation can be found in :c:func:`type_getattro()` and
+:c:func:`_PyType_Lookup()` in :source:`Objects/typeobject.c`.
+
+
+Invocation from super
+---------------------
+
+The logic for super's dotted lookup is in the :meth:`__getattribute__` method for
+object returned by :class:`super()`.
+
+A dotted lookup such as ``super(A, obj).m`` searches ``obj.__class__.__mro__``
+for the base class ``B`` immediately following ``A`` and then returns
+``B.__dict__['m'].__get__(obj, A)``. If not a descriptor, ``m`` is returned
+unchanged.
+
+The full C implementation can be found in :c:func:`super_getattro()` in
+:source:`Objects/typeobject.c`. A pure Python equivalent can be found in
+`Guido's Tutorial
+<https://www.python.org/download/releases/2.2.3/descrintro/#cooperation>`_.
+
+
+Summary of invocation logic
+---------------------------
+
+The mechanism for descriptors is embedded in the :meth:`__getattribute__()`
+methods for :class:`object`, :class:`type`, and :func:`super`.
The important points to remember are:
-* descriptors are invoked by the :meth:`__getattribute__` method
-* overriding :meth:`__getattribute__` prevents automatic descriptor calls
+* Descriptors are invoked by the :meth:`__getattribute__` method.
+
+* Classes inherit this machinery from :class:`object`, :class:`type`, or
+ :func:`super`.
+
+* Overriding :meth:`__getattribute__` prevents automatic descriptor calls
+ because all the descriptor logic is in that method.
+
* :meth:`object.__getattribute__` and :meth:`type.__getattribute__` make
- different calls to :meth:`__get__`.
-* data descriptors always override instance dictionaries.
-* non-data descriptors may be overridden by instance dictionaries.
+ different calls to :meth:`__get__`. The first includes the instance and may
+ include the class. The second puts in ``None`` for the instance and always
+ includes the class.
-The object returned by ``super()`` also has a custom :meth:`__getattribute__`
-method for invoking descriptors. The attribute lookup ``super(B, obj).m`` searches
-``obj.__class__.__mro__`` for the base class ``A`` immediately following ``B``
-and then returns ``A.__dict__['m'].__get__(obj, B)``. If not a descriptor,
-``m`` is returned unchanged. If not in the dictionary, ``m`` reverts to a
-search using :meth:`object.__getattribute__`.
+* Data descriptors always override instance dictionaries.
-The implementation details are in :c:func:`super_getattro()` in
-:source:`Objects/typeobject.c`. and a pure Python equivalent can be found in
-`Guido's Tutorial`_.
+* Non-data descriptors may be overridden by instance dictionaries.
-.. _`Guido's Tutorial`: https://www.python.org/download/releases/2.2.3/descrintro/#cooperation
-The details above show that the mechanism for descriptors is embedded in the
-:meth:`__getattribute__()` methods for :class:`object`, :class:`type`, and
-:func:`super`. Classes inherit this machinery when they derive from
-:class:`object` or if they have a meta-class providing similar functionality.
-Likewise, classes can turn-off descriptor invocation by overriding
-:meth:`__getattribute__()`.
+Automatic name notification
+---------------------------
+Sometimes it is desirable for a descriptor to know what class variable name it
+was assigned to. When a new class is created, the :class:`type` metaclass
+scans the dictionary of the new class. If any of the entries are descriptors
+and if they define :meth:`__set_name__`, that method is called with two
+arguments. The *owner* is the class where the descriptor is used, and the
+*name* is the class variable the descriptor was assigned to.
-Descriptor Example
-------------------
+The implementation details are in :c:func:`type_new()` and
+:c:func:`set_names()` in :source:`Objects/typeobject.c`.
-The following code creates a class whose objects are data descriptors which
-print a message for each get or set. Overriding :meth:`__getattribute__` is
-alternate approach that could do this for every attribute. However, this
-descriptor is useful for monitoring just a few chosen attributes::
+Since the update logic is in :meth:`type.__new__`, notifications only take
+place at the time of class creation. If descriptors are added to the class
+afterwards, :meth:`__set_name__` will need to be called manually.
- class RevealAccess:
- """A data descriptor that sets and returns values
- normally and prints a message logging their access.
- """
- def __init__(self, initval=None, name='var'):
- self.val = initval
- self.name = name
+ORM example
+-----------
- def __get__(self, obj, objtype):
- print('Retrieving', self.name)
- return self.val
+The following code is simplified skeleton showing how data descriptors could
+be used to implement an `object relational mapping
+<https://en.wikipedia.org/wiki/Object%E2%80%93relational_mapping>`_.
- def __set__(self, obj, val):
- print('Updating', self.name)
- self.val = val
+The essential idea is that the data is stored in an external database. The
+Python instances only hold keys to the database's tables. Descriptors take
+care of lookups or updates:
- >>> class MyClass:
- ... x = RevealAccess(10, 'var "x"')
- ... y = 5
- ...
- >>> m = MyClass()
- >>> m.x
- Retrieving var "x"
- 10
- >>> m.x = 20
- Updating var "x"
- >>> m.x
- Retrieving var "x"
- 20
- >>> m.y
- 5
+.. testcode::
+
+ class Field:
+
+ def __set_name__(self, owner, name):
+ self.fetch = f'SELECT {name} FROM {owner.table} WHERE {owner.key}=?;'
+ self.store = f'UPDATE {owner.table} SET {name}=? WHERE {owner.key}=?;'
+
+ def __get__(self, obj, objtype=None):
+ return conn.execute(self.fetch, [obj.key]).fetchone()[0]
+
+ def __set__(self, obj, value):
+ conn.execute(self.store, [value, obj.key])
+ conn.commit()
+
+We can use the :class:`Field` class to define `models
+<https://en.wikipedia.org/wiki/Database_model>`_ that describe the schema for
+each table in a database:
+
+.. testcode::
+
+ class Movie:
+ table = 'Movies' # Table name
+ key = 'title' # Primary key
+ director = Field()
+ year = Field()
+
+ def __init__(self, key):
+ self.key = key
+
+ class Song:
+ table = 'Music'
+ key = 'title'
+ artist = Field()
+ year = Field()
+ genre = Field()
+
+ def __init__(self, key):
+ self.key = key
-The protocol is simple and offers exciting possibilities. Several use cases are
-so common that they have been packaged into individual function calls.
-Properties, bound methods, static methods, and class methods are all
-based on the descriptor protocol.
+To use the models, first connect to the database::
+
+ >>> import sqlite3
+ >>> conn = sqlite3.connect('entertainment.db')
+
+An interactive session shows how data is retrieved from the database and how
+it can be updated:
+
+.. testsetup::
+
+ song_data = [
+ ('Country Roads', 'John Denver', 1972),
+ ('Me and Bobby McGee', 'Janice Joplin', 1971),
+ ('Coal Miners Daughter', 'Loretta Lynn', 1970),
+ ]
+
+ movie_data = [
+ ('Star Wars', 'George Lucas', 1977),
+ ('Jaws', 'Steven Spielberg', 1975),
+ ('Aliens', 'James Cameron', 1986),
+ ]
+
+ import sqlite3
+
+ conn = sqlite3.connect(':memory:')
+ conn.execute('CREATE TABLE Music (title text, artist text, year integer);')
+ conn.execute('CREATE INDEX MusicNdx ON Music (title);')
+ conn.executemany('INSERT INTO Music VALUES (?, ?, ?);', song_data)
+ conn.execute('CREATE TABLE Movies (title text, director text, year integer);')
+ conn.execute('CREATE INDEX MovieNdx ON Music (title);')
+ conn.executemany('INSERT INTO Movies VALUES (?, ?, ?);', movie_data)
+ conn.commit()
+
+.. doctest::
+
+ >>> Movie('Star Wars').director
+ 'George Lucas'
+ >>> jaws = Movie('Jaws')
+ >>> f'Released in {jaws.year} by {jaws.director}'
+ 'Released in 1975 by Steven Spielberg'
+
+ >>> Song('Country Roads').artist
+ 'John Denver'
+
+ >>> Movie('Star Wars').director = 'J.J. Abrams'
+ >>> Movie('Star Wars').director
+ 'J.J. Abrams'
+
+
+Pure Python Equivalents
+^^^^^^^^^^^^^^^^^^^^^^^
+
+The descriptor protocol is simple and offers exciting possibilities. Several
+use cases are so common that they have been prepackaged into built-in tools.
+Properties, bound methods, static methods, class methods, and \_\_slots\_\_ are
+all based on the descriptor protocol.
Properties
----------
Calling :func:`property` is a succinct way of building a data descriptor that
-triggers function calls upon access to an attribute. Its signature is::
+triggers a function call upon access to an attribute. Its signature is::
- property(fget=None, fset=None, fdel=None, doc=None) -> property attribute
+ property(fget=None, fset=None, fdel=None, doc=None) -> property
-The documentation shows a typical use to define a managed attribute ``x``::
+The documentation shows a typical use to define a managed attribute ``x``:
+
+.. testcode::
class C:
def getx(self): return self.__x
x = property(getx, setx, delx, "I'm the 'x' property.")
To see how :func:`property` is implemented in terms of the descriptor protocol,
-here is a pure Python equivalent::
+here is a pure Python equivalent:
+
+.. testcode::
class Property:
"Emulate PyProperty_Type() in Objects/descrobject.c"
def deleter(self, fdel):
return type(self)(self.fget, self.fset, fdel, self.__doc__)
+.. testcode::
+ :hide:
+
+ # Verify the Property() emulation
+
+ class CC:
+ def getx(self):
+ return self.__x
+ def setx(self, value):
+ self.__x = value
+ def delx(self):
+ del self.__x
+ x = Property(getx, setx, delx, "I'm the 'x' property.")
+
+ # Now do it again but use the decorator style
+
+ class CCC:
+ @Property
+ def x(self):
+ return self.__x
+ @x.setter
+ def x(self, value):
+ self.__x = value
+ @x.deleter
+ def x(self):
+ del self.__x
+
+
+.. doctest::
+ :hide:
+
+ >>> cc = CC()
+ >>> hasattr(cc, 'x')
+ False
+ >>> cc.x = 33
+ >>> cc.x
+ 33
+ >>> del cc.x
+ >>> hasattr(cc, 'x')
+ False
+
+ >>> ccc = CCC()
+ >>> hasattr(ccc, 'x')
+ False
+ >>> ccc.x = 333
+ >>> ccc.x == 333
+ True
+ >>> del ccc.x
+ >>> hasattr(ccc, 'x')
+ False
+
The :func:`property` builtin helps whenever a user interface has granted
attribute access and then subsequent changes require the intervention of a
method.
``Cell('b10').value``. Subsequent improvements to the program require the cell
to be recalculated on every access; however, the programmer does not want to
affect existing client code accessing the attribute directly. The solution is
-to wrap access to the value attribute in a property data descriptor::
+to wrap access to the value attribute in a property data descriptor:
+
+.. testcode::
class Cell:
- . . .
- def getvalue(self):
+ ...
+
+ @property
+ def value(self):
"Recalculate the cell before returning value"
self.recalc()
return self._value
- value = property(getvalue)
+Either the built-in :func:`property` or our :func:`Property` equivalent would
+work in this example.
-Functions and Methods
+
+Functions and methods
---------------------
Python's object oriented features are built upon a function based environment.
Using non-data descriptors, the two are merged seamlessly.
-Class dictionaries store methods as functions. In a class definition, methods
-are written using :keyword:`def` or :keyword:`lambda`, the usual tools for
-creating functions. Methods only differ from regular functions in that the
-first argument is reserved for the object instance. By Python convention, the
-instance reference is called *self* but may be called *this* or any other
-variable name.
+Functions stored in class dictionaries get turned into methods when invoked.
+Methods only differ from regular functions in that the object instance is
+prepended to the other arguments. By convention, the instance is called
+*self* but could be called *this* or any other variable name.
+
+Methods can be created manually with :class:`types.MethodType` which is
+roughly equivalent to:
-To support method calls, functions include the :meth:`__get__` method for
-binding methods during attribute access. This means that all functions are
-non-data descriptors which return bound methods when they are invoked from an
-object. In pure Python, it works like this::
+.. testcode::
+
+ class MethodType:
+ "Emulate Py_MethodType in Objects/classobject.c"
+
+ def __init__(self, func, obj):
+ self.__func__ = func
+ self.__self__ = obj
+
+ def __call__(self, *args, **kwargs):
+ func = self.__func__
+ obj = self.__self__
+ return func(obj, *args, **kwargs)
+
+To support automatic creation of methods, functions include the
+:meth:`__get__` method for binding methods during attribute access. This
+means that functions are non-data descriptors that return bound methods
+during dotted lookup from an instance. Here's how it works:
+
+.. testcode::
class Function:
- . . .
+ ...
+
def __get__(self, obj, objtype=None):
"Simulate func_descr_get() in Objects/funcobject.c"
if obj is None:
return self
- return types.MethodType(self, obj)
+ return MethodType(self, obj)
-Running the interpreter shows how the function descriptor works in practice::
+Running the following class in the interpreter shows how the function
+descriptor works in practice:
- >>> class D:
- ... def f(self, x):
- ... return x
- ...
- >>> d = D()
+.. testcode::
+
+ class D:
+ def f(self, x):
+ return x
+
+The function has a :term:`qualified name` attribute to support introspection:
+
+.. doctest::
+
+ >>> D.f.__qualname__
+ 'D.f'
+
+Accessing the function through the class dictionary does not invoke
+:meth:`__get__`. Instead, it just returns the underlying function object::
- # Access through the class dictionary does not invoke __get__.
- # It just returns the underlying function object.
>>> D.__dict__['f']
<function D.f at 0x00C45070>
- # Dotted access from a class calls __get__() which just returns
- # the underlying function unchanged.
+Dotted access from a class calls :meth:`__get__` which just returns the
+underlying function unchanged::
+
>>> D.f
<function D.f at 0x00C45070>
- # The function has a __qualname__ attribute to support introspection
- >>> D.f.__qualname__
- 'D.f'
+The interesting behavior occurs during dotted access from an instance. The
+dotted lookup calls :meth:`__get__` which returns a bound method object::
- # Dotted access from an instance calls __get__() which returns the
- # function wrapped in a bound method object
+ >>> d = D()
>>> d.f
<bound method D.f of <__main__.D object at 0x00B18C90>>
- # Internally, the bound method stores the underlying function and
- # the bound instance.
+Internally, the bound method stores the underlying function and the bound
+instance::
+
>>> d.f.__func__
- <function D.f at 0x1012e5ae8>
+ <function D.f at 0x00C45070>
+
>>> d.f.__self__
<__main__.D object at 0x1012e1f98>
+If you have ever wondered where *self* comes from in regular methods or where
+*cls* comes from in class methods, this is it!
+
-Static Methods and Class Methods
---------------------------------
+Static methods
+--------------
Non-data descriptors provide a simple mechanism for variations on the usual
patterns of binding functions into methods.
To recap, functions have a :meth:`__get__` method so that they can be converted
to a method when accessed as attributes. The non-data descriptor transforms an
-``obj.f(*args)`` call into ``f(obj, *args)``. Calling ``klass.f(*args)``
+``obj.f(*args)`` call into ``f(obj, *args)``. Calling ``cls.f(*args)``
becomes ``f(*args)``.
This chart summarizes the binding and its two most useful variants:
+-----------------+----------------------+------------------+
| Transformation | Called from an | Called from a |
- | | Object | Class |
+ | | object | class |
+=================+======================+==================+
| function | f(obj, \*args) | f(\*args) |
+-----------------+----------------------+------------------+
| staticmethod | f(\*args) | f(\*args) |
+-----------------+----------------------+------------------+
- | classmethod | f(type(obj), \*args) | f(klass, \*args) |
+ | classmethod | f(type(obj), \*args) | f(cls, \*args) |
+-----------------+----------------------+------------------+
Static methods return the underlying function without changes. Calling either
It can be called either from an object or the class: ``s.erf(1.5) --> .9332`` or
``Sample.erf(1.5) --> .9332``.
-Since staticmethods return the underlying function with no changes, the example
-calls are unexciting::
+Since static methods return the underlying function with no changes, the
+example calls are unexciting:
+
+.. testcode::
+
+ class E:
+ @staticmethod
+ def f(x):
+ print(x)
+
+.. doctest::
- >>> class E:
- ... def f(x):
- ... print(x)
- ... f = staticmethod(f)
- ...
>>> E.f(3)
3
>>> E().f(3)
3
Using the non-data descriptor protocol, a pure Python version of
-:func:`staticmethod` would look like this::
+:func:`staticmethod` would look like this:
+
+.. doctest::
class StaticMethod:
"Emulate PyStaticMethod_Type() in Objects/funcobject.c"
def __get__(self, obj, objtype=None):
return self.f
+
+Class methods
+-------------
+
Unlike static methods, class methods prepend the class reference to the
argument list before calling the function. This format is the same
-for whether the caller is an object or a class::
+for whether the caller is an object or a class:
- >>> class E:
- ... def f(klass, x):
- ... return klass.__name__, x
- ... f = classmethod(f)
- ...
- >>> print(E.f(3))
- ('E', 3)
- >>> print(E().f(3))
- ('E', 3)
+.. testcode::
+
+ class F:
+ @classmethod
+ def f(cls, x):
+ return cls.__name__, x
+.. doctest::
-This behavior is useful whenever the function only needs to have a class
-reference and does not care about any underlying data. One use for classmethods
-is to create alternate class constructors. In Python 2.3, the classmethod
-:func:`dict.fromkeys` creates a new dictionary from a list of keys. The pure
-Python equivalent is::
+ >>> F.f(3)
+ ('F', 3)
+ >>> F().f(3)
+ ('F', 3)
- class Dict:
- . . .
- def fromkeys(klass, iterable, value=None):
+This behavior is useful whenever the method only needs to have a class
+reference and does not rely on data stored in a specific instance. One use for
+class methods is to create alternate class constructors. For example, the
+classmethod :func:`dict.fromkeys` creates a new dictionary from a list of
+keys. The pure Python equivalent is:
+
+.. testcode::
+
+ class Dict(dict):
+ @classmethod
+ def fromkeys(cls, iterable, value=None):
"Emulate dict_fromkeys() in Objects/dictobject.c"
- d = klass()
+ d = cls()
for key in iterable:
d[key] = value
return d
- fromkeys = classmethod(fromkeys)
-Now a new dictionary of unique keys can be constructed like this::
+Now a new dictionary of unique keys can be constructed like this:
+
+.. doctest::
- >>> Dict.fromkeys('abracadabra')
- {'a': None, 'r': None, 'b': None, 'c': None, 'd': None}
+ >>> d = Dict.fromkeys('abracadabra')
+ >>> type(d) is Dict
+ True
+ >>> d
+ {'a': None, 'b': None, 'r': None, 'c': None, 'd': None}
Using the non-data descriptor protocol, a pure Python version of
-:func:`classmethod` would look like this::
+:func:`classmethod` would look like this:
+
+.. testcode::
class ClassMethod:
"Emulate PyClassMethod_Type() in Objects/funcobject.c"
def __init__(self, f):
self.f = f
- def __get__(self, obj, klass=None):
- if klass is None:
- klass = type(obj)
- def newfunc(*args):
- return self.f(klass, *args)
- return newfunc
+ def __get__(self, obj, cls=None):
+ if cls is None:
+ cls = type(obj)
+ if hasattr(obj, '__get__'):
+ return self.f.__get__(cls)
+ return MethodType(self.f, cls)
+
+.. testcode::
+ :hide:
+
+ # Verify the emulation works
+ class T:
+ @ClassMethod
+ def cm(cls, x, y):
+ return (cls, x, y)
+
+.. doctest::
+ :hide:
+
+ >>> T.cm(11, 22)
+ (<class 'T'>, 11, 22)
+
+ # Also call it from an instance
+ >>> t = T()
+ >>> t.cm(11, 22)
+ (<class 'T'>, 11, 22)
+
+The code path for ``hasattr(obj, '__get__')`` was added in Python 3.9 and
+makes it possible for :func:`classmethod` to support chained decorators.
+For example, a classmethod and property could be chained together:
+.. testcode::
+
+ class G:
+ @classmethod
+ @property
+ def __doc__(cls):
+ return f'A doc for {cls.__name__!r}'
+
+.. doctest::
+
+ >>> G.__doc__
+ "A doc for 'G'"
+
+
+Member objects and __slots__
+----------------------------
+
+When a class defines ``__slots__``, it replaces instance dictionaries with a
+fixed-length array of slot values. From a user point of view that has
+several effects:
+
+1. Provides immediate detection of bugs due to misspelled attribute
+assignments. Only attribute names specified in ``__slots__`` are allowed:
+
+.. testcode::
+
+ class Vehicle:
+ __slots__ = ('id_number', 'make', 'model')
+
+.. doctest::
+
+ >>> auto = Vehicle()
+ >>> auto.id_nubmer = 'VYE483814LQEX'
+ Traceback (most recent call last):
+ ...
+ AttributeError: 'Vehicle' object has no attribute 'id_nubmer'
+
+2. Helps create immutable objects where descriptors manage access to private
+attributes stored in ``__slots__``:
+
+.. testcode::
+
+ class Immutable:
+
+ __slots__ = ('_dept', '_name') # Replace the instance dictionary
+
+ def __init__(self, dept, name):
+ self._dept = dept # Store to private attribute
+ self._name = name # Store to private attribute
+
+ @property # Read-only descriptor
+ def dept(self):
+ return self._dept
+
+ @property
+ def name(self): # Read-only descriptor
+ return self._name
+
+.. doctest::
+
+ >>> mark = Immutable('Botany', 'Mark Watney')
+ >>> mark.dept
+ 'Botany'
+ >>> mark.dept = 'Space Pirate'
+ Traceback (most recent call last):
+ ...
+ AttributeError: can't set attribute
+ >>> mark.location = 'Mars'
+ Traceback (most recent call last):
+ ...
+ AttributeError: 'Immutable' object has no attribute 'location'
+
+3. Saves memory. On a 64-bit Linux build, an instance with two attributes
+takes 48 bytes with ``__slots__`` and 152 bytes without. This `flyweight
+design pattern <https://en.wikipedia.org/wiki/Flyweight_pattern>`_ likely only
+matters when a large number of instances are going to be created.
+
+4. Blocks tools like :func:`functools.cached_property` which require an
+instance dictionary to function correctly:
+
+.. testcode::
+
+ from functools import cached_property
+
+ class CP:
+ __slots__ = () # Eliminates the instance dict
+
+ @cached_property # Requires an instance dict
+ def pi(self):
+ return 4 * sum((-1.0)**n / (2.0*n + 1.0)
+ for n in reversed(range(100_000)))
+
+.. doctest::
+
+ >>> CP().pi
+ Traceback (most recent call last):
+ ...
+ TypeError: No '__dict__' attribute on 'CP' instance to cache 'pi' property.
+
+It is not possible to create an exact drop-in pure Python version of
+``__slots__`` because it requires direct access to C structures and control
+over object memory allocation. However, we can build a mostly faithful
+simulation where the actual C structure for slots is emulated by a private
+``_slotvalues`` list. Reads and writes to that private structure are managed
+by member descriptors:
+
+.. testcode::
+
+ null = object()
+
+ class Member:
+
+ def __init__(self, name, clsname, offset):
+ 'Emulate PyMemberDef in Include/structmember.h'
+ # Also see descr_new() in Objects/descrobject.c
+ self.name = name
+ self.clsname = clsname
+ self.offset = offset
+
+ def __get__(self, obj, objtype=None):
+ 'Emulate member_get() in Objects/descrobject.c'
+ # Also see PyMember_GetOne() in Python/structmember.c
+ value = obj._slotvalues[self.offset]
+ if value is null:
+ raise AttributeError(self.name)
+ return value
+
+ def __set__(self, obj, value):
+ 'Emulate member_set() in Objects/descrobject.c'
+ obj._slotvalues[self.offset] = value
+
+ def __delete__(self, obj):
+ 'Emulate member_delete() in Objects/descrobject.c'
+ value = obj._slotvalues[self.offset]
+ if value is null:
+ raise AttributeError(self.name)
+ obj._slotvalues[self.offset] = null
+
+ def __repr__(self):
+ 'Emulate member_repr() in Objects/descrobject.c'
+ return f'<Member {self.name!r} of {self.clsname!r}>'
+
+The :meth:`type.__new__` method takes care of adding member objects to class
+variables:
+
+.. testcode::
+
+ class Type(type):
+ 'Simulate how the type metaclass adds member objects for slots'
+
+ def __new__(mcls, clsname, bases, mapping):
+ 'Emuluate type_new() in Objects/typeobject.c'
+ # type_new() calls PyTypeReady() which calls add_methods()
+ slot_names = mapping.get('slot_names', [])
+ for offset, name in enumerate(slot_names):
+ mapping[name] = Member(name, clsname, offset)
+ return type.__new__(mcls, clsname, bases, mapping)
+
+The :meth:`object.__new__` method takes care of creating instances that have
+slots instead of an instance dictionary. Here is a rough simulation in pure
+Python:
+
+.. testcode::
+
+ class Object:
+ 'Simulate how object.__new__() allocates memory for __slots__'
+
+ def __new__(cls, *args):
+ 'Emulate object_new() in Objects/typeobject.c'
+ inst = super().__new__(cls)
+ if hasattr(cls, 'slot_names'):
+ empty_slots = [null] * len(cls.slot_names)
+ object.__setattr__(inst, '_slotvalues', empty_slots)
+ return inst
+
+ def __setattr__(self, name, value):
+ 'Emulate _PyObject_GenericSetAttrWithDict() Objects/object.c'
+ cls = type(self)
+ if hasattr(cls, 'slot_names') and name not in cls.slot_names:
+ raise AttributeError(
+ f'{type(self).__name__!r} object has no attribute {name!r}'
+ )
+ super().__setattr__(name, value)
+
+ def __delattr__(self, name):
+ 'Emulate _PyObject_GenericSetAttrWithDict() Objects/object.c'
+ cls = type(self)
+ if hasattr(cls, 'slot_names') and name not in cls.slot_names:
+ raise AttributeError(
+ f'{type(self).__name__!r} object has no attribute {name!r}'
+ )
+ super().__delattr__(name)
+
+To use the simulation in a real class, just inherit from :class:`Object` and
+set the :term:`metaclass` to :class:`Type`:
+
+.. testcode::
+
+ class H(Object, metaclass=Type):
+ 'Instance variables stored in slots'
+
+ slot_names = ['x', 'y']
+
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+At this point, the metaclass has loaded member objects for *x* and *y*::
+
+ >>> from pprint import pp
+ >>> pp(dict(vars(H)))
+ {'__module__': '__main__',
+ '__doc__': 'Instance variables stored in slots',
+ 'slot_names': ['x', 'y'],
+ '__init__': <function H.__init__ at 0x7fb5d302f9d0>,
+ 'x': <Member 'x' of 'H'>,
+ 'y': <Member 'y' of 'H'>}
+
+.. doctest::
+ :hide:
+
+ # We test this separately because the preceding section is not
+ # doctestable due to the hex memory address for the __init__ function
+ >>> isinstance(vars(H)['x'], Member)
+ True
+ >>> isinstance(vars(H)['y'], Member)
+ True
+
+When instances are created, they have a ``slot_values`` list where the
+attributes are stored:
+
+.. doctest::
+
+ >>> h = H(10, 20)
+ >>> vars(h)
+ {'_slotvalues': [10, 20]}
+ >>> h.x = 55
+ >>> vars(h)
+ {'_slotvalues': [55, 20]}
+
+Misspelled or unassigned attributes will raise an exception:
+
+.. doctest::
+
+ >>> h.xz
+ Traceback (most recent call last):
+ ...
+ AttributeError: 'H' object has no attribute 'xz'
+
+.. doctest::
+ :hide:
+
+ # Examples for deleted attributes are not shown because this section
+ # is already a bit lengthy. We still test that code here.
+ >>> del h.x
+ >>> hasattr(h, 'x')
+ False
+
+ # Also test the code for uninitialized slots
+ >>> class HU(Object, metaclass=Type):
+ ... slot_names = ['x', 'y']
+ ...
+ >>> hu = HU()
+ >>> hasattr(hu, 'x')
+ False
+ >>> hasattr(hu, 'y')
+ False
* const_ - A constant value required by some action_ and nargs_ selections.
* default_ - The value produced if the argument is absent from the
- command line.
+ command line and if it is absent from the namespace object.
* type_ - The type to which the command-line argument should be converted.
>>> parser.parse_args([])
Namespace(foo=42)
+If the target namespace already has an attribute set, the action *default*
+will not over write it::
+
+ >>> parser = argparse.ArgumentParser()
+ >>> parser.add_argument('--foo', default=42)
+ >>> parser.parse_args([], namespace=argparse.Namespace(foo=101))
+ Namespace(foo=101)
+
If the ``default`` value is a string, the parser parses the value as if it
were a command-line argument. In particular, the parser applies any type_
conversion argument, if provided, before setting the attribute on the
Any container can be passed as the *choices* value, so :class:`list` objects,
:class:`set` objects, and custom containers are all supported.
-This includes :class:`enum.Enum`, which could be used to restrain
-argument's choices; if we reuse previous rock/paper/scissors game example,
-this could be as follows::
-
- >>> from enum import Enum
- >>> class GameMove(Enum):
- ... ROCK = 'rock'
- ... PAPER = 'paper'
- ... SCISSORS = 'scissors'
- ...
- >>> parser = argparse.ArgumentParser(prog='game.py')
- >>> parser.add_argument('move', type=GameMove, choices=GameMove)
- >>> parser.parse_args(['rock'])
- Namespace(move=<GameMove.ROCK: 'rock'>)
+
+Use of :class:`enum.Enum` is not recommended because it is difficult to
+control its appearance in usage, help, and error messages.
required
fields as :class:`For` and :class:`With`, respectively. Only valid in the
body of an :class:`AsyncFunctionDef`.
+.. note::
+ When a string is parsed by :func:`ast.parse`, operator nodes (subclasses
+ of :class:`ast.operator`, :class:`ast.unaryop`, :class:`ast.cmpop`,
+ :class:`ast.boolop` and :class:`ast.expr_context`) on the returned tree
+ will be singletons. Changes to one will be reflected in all other
+ occurrences of the same value (e.g. :class:`ast.Add`).
+
:mod:`ast` Helpers
------------------
Added the *indent* option.
+.. _ast-compiler-flags:
+
+Compiler Flags
+--------------
+
+The following flags may be passed to :func:`compile` in order to change
+effects on the compilation of a program:
+
+.. data:: PyCF_ALLOW_TOP_LEVEL_AWAIT
+
+ Enables support for top-level ``await``, ``async for``, ``async with``
+ and async comprehensions.
+
+ .. versionadded:: 3.8
+
+.. data:: PyCF_ONLY_AST
+
+ Generates and returns an abstract syntax tree instead of returning a
+ compiled code object.
+
+.. data:: PyCF_TYPE_COMMENTS
+
+ Enables support for :pep:`484` and :pep:`526` style type comments
+ (``# type: <type>``, ``# type: ignore <stuff>``).
+
+ .. versionadded:: 3.8
+
+
.. _ast-cli:
Command-Line Usage
It works reliably even when the asyncio event loop is run in a non-main OS thread.
There is no noticeable overhead when handling a big number of children (*O(1)* each
- time a child terminates), but stating a thread per process requires extra memory.
+ time a child terminates), but starting a thread per process requires extra memory.
This watcher is used by default.
This implementation registers a :py:data:`SIGCHLD` signal handler on
instantiation. That can break third-party code that installs a custom handler for
- `SIGCHLD`. signal).
+ :py:data:`SIGCHLD` signal.
The watcher avoids disrupting other code spawning processes
by polling every process explicitly on a :py:data:`SIGCHLD` signal.
.. note::
- The default asyncio event loop implementation on **Windows** does not
- support subprocesses. Subprocesses are available for Windows if a
- :class:`ProactorEventLoop` is used.
- See :ref:`Subprocess Support on Windows <asyncio-windows-subprocess>`
+ Subprocesses are available for Windows if a :class:`ProactorEventLoop` is
+ used. See :ref:`Subprocess Support on Windows <asyncio-windows-subprocess>`
for details.
.. seealso::
return_when=ALL_COMPLETED)
Run :ref:`awaitable objects <asyncio-awaitables>` in the *aws*
- set concurrently and block until the condition specified
+ iterable concurrently and block until the condition specified
by *return_when*.
- The *aws* set must not be empty.
+ The *aws* iterable must not be empty.
Returns two sets of Tasks/Futures: ``(done, pending)``.
.. function:: as_completed(aws, \*, loop=None, timeout=None)
Run :ref:`awaitable objects <asyncio-awaitables>` in the *aws*
- set concurrently. Return an iterator of coroutines.
+ iterable concurrently. Return an iterator of coroutines.
Each coroutine returned can be awaited to get the earliest next
- result from the set of the remaining awaitables.
+ result from the iterable of the remaining awaitables.
Raises :exc:`asyncio.TimeoutError` if the timeout occurs before
all Futures are done.
Asynchronously run function *func* in a separate thread.
Any \*args and \*\*kwargs supplied for this function are directly passed
- to *func*. Also, the current :class:`contextvars.Context` is propogated,
+ to *func*. Also, the current :class:`contextvars.Context` is propagated,
allowing context variables from the event loop thread to be accessed in the
separate thread.
specific documentation for actual events raised.
.. audit-event-table::
+
+The following events are raised internally and do not correspond to any
+public API of CPython:
+
++--------------------------+-------------------------------------------+
+| Audit event | Arguments |
++==========================+===========================================+
+| _winapi.CreateFile | ``file_name``, ``desired_access``, |
+| | ``share_mode``, ``creation_disposition``, |
+| | ``flags_and_attributes`` |
++--------------------------+-------------------------------------------+
+| _winapi.CreateJunction | ``src_path``, ``dst_path`` |
++--------------------------+-------------------------------------------+
+| _winapi.CreateNamedPipe | ``name``, ``open_mode``, ``pipe_mode`` |
++--------------------------+-------------------------------------------+
+| _winapi.CreatePipe | |
++--------------------------+-------------------------------------------+
+| _winapi.CreateProcess | ``application_name``, ``command_line``, |
+| | ``current_directory`` |
++--------------------------+-------------------------------------------+
+| _winapi.OpenProcess | ``process_id``, ``desired_access`` |
++--------------------------+-------------------------------------------+
+| _winapi.TerminateProcess | ``handle``, ``exit_code`` |
++--------------------------+-------------------------------------------+
+| ctypes.PyObj_FromPtr | ``obj`` |
++--------------------------+-------------------------------------------+
Using :func:`compress` and :func:`decompress` to demonstrate round-trip compression:
>>> import bz2
-
>>> data = b"""\
... Donec rhoncus quis sapien sit amet molestie. Fusce scelerisque vel augue
... nec ullamcorper. Nam rutrum pretium placerat. Aliquam vel tristique lorem,
... Aliquam pharetra lacus non risus vehicula rutrum. Maecenas aliquam leo
... felis. Pellentesque semper nunc sit amet nibh ullamcorper, ac elementum
... dolor luctus. Curabitur lacinia mi ornare consectetur vestibulum."""
-
>>> c = bz2.compress(data)
>>> len(data) / len(c) # Data compression ratio
1.513595166163142
-
>>> d = bz2.decompress(c)
>>> data == d # Check equality to original object after round-trip
True
Using :class:`BZ2Compressor` for incremental compression:
>>> import bz2
-
>>> def gen_data(chunks=10, chunksize=1000):
... """Yield incremental blocks of chunksize bytes."""
... for _ in range(chunks):
Writing and reading a bzip2-compressed file in binary mode:
>>> import bz2
-
>>> data = b"""\
... Donec rhoncus quis sapien sit amet molestie. Fusce scelerisque vel augue
... nec ullamcorper. Nam rutrum pretium placerat. Aliquam vel tristique lorem,
... Aliquam pharetra lacus non risus vehicula rutrum. Maecenas aliquam leo
... felis. Pellentesque semper nunc sit amet nibh ullamcorper, ac elementum
... dolor luctus. Curabitur lacinia mi ornare consectetur vestibulum."""
-
>>> with bz2.open("myfile.bz2", "wb") as f:
... # Write compressed data to file
... unused = f.write(data)
-
>>> with bz2.open("myfile.bz2", "rb") as f:
... # Decompress data from file
... content = f.read()
-
>>> content == data # Check equality to original object after round-trip
True
:meth:`_from_iterable` which calls ``cls(iterable)`` to produce a new set.
If the :class:`Set` mixin is being used in a class with a different
constructor signature, you will need to override :meth:`_from_iterable`
- with a classmethod that can construct new instances from
+ with a classmethod or regular method that can construct new instances from
an iterable argument.
(2)
Named tuple instances do not have per-instance dictionaries, so they are
lightweight and require no more memory than regular tuples.
+ To support pickling, the named tuple class should be assigned to a variable
+ that matches *typename*.
+
.. versionchanged:: 3.1
Added support for *rename*.
An :class:`Executor` subclass that executes calls asynchronously using a pool
of at most *max_workers* processes. If *max_workers* is ``None`` or not
given, it will default to the number of processors on the machine.
- If *max_workers* is lower or equal to ``0``, then a :exc:`ValueError`
+ If *max_workers* is less than or equal to ``0``, then a :exc:`ValueError`
will be raised.
- On Windows, *max_workers* must be equal or lower than ``61``. If it is not
+ On Windows, *max_workers* must be less than or equal to ``61``. If it is not
then :exc:`ValueError` will be raised. If *max_workers* is ``None``, then
the default chosen will be at most ``61``, even if more processors are
available.
each worker process; *initargs* is a tuple of arguments passed to the
initializer. Should *initializer* raise an exception, all currently
pending jobs will raise a :exc:`~concurrent.futures.process.BrokenProcessPool`,
- as well any attempt to submit more jobs to the pool.
+ as well as any attempt to submit more jobs to the pool.
.. versionchanged:: 3.3
When one of the worker processes terminates abruptly, a
libraries use the standard C calling convention, and are assumed to return
:c:type:`int`.
+ On Windows creating a :class:`CDLL` instance may fail even if the DLL name
+ exists. When a dependent DLL of the loaded DLL is not found, a
+ :exc:`OSError` error is raised with the message *"[WinError 126] The
+ specified module could not be found".* This error message does not contain
+ the name of the missing DLL because the Windows API does not return this
+ information making this error hard to diagnose. To resolve this error and
+ determine which DLL is not found, you need to find the list of dependent
+ DLLs and determine which one is not found using Windows debugging and
+ tracing tools.
+
+.. seealso::
+
+ `Microsoft DUMPBIN tool <https://docs.microsoft.com/cpp/build/reference/dependents>`_
+ -- A tool to find DLL dependents.
+
.. class:: OleDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False, winmode=0)
``ctypes.seh_exception`` with argument ``code`` will be raised, allowing an
audit hook to replace the exception with its own.
-.. audit-event:: ctypes.call_function func_pointer,arguments ctype-foreign-functions
+.. audit-event:: ctypes.call_function func_pointer,arguments foreign-functions
Some ways to invoke foreign function calls may raise an auditing event
``ctypes.call_function`` with arguments ``function pointer`` and ``arguments``.
Returns the object to which to pointer points. Assigning to this
attribute changes the pointer to point to the assigned object.
-
.. opcode:: LIST_TO_TUPLE
- Pops a list from the stack and pushes a tuple containing the same values.
+ Pops a list from the stack and pushes a tuple containing the same values.
.. versionadded:: 3.9
.. opcode:: DICT_MERGE
- Like :opcode:`DICT_UPDATE` but raises an exception for duplicate keys.
+ Like :opcode:`DICT_UPDATE` but raises an exception for duplicate keys.
.. versionadded:: 3.9
.. opcode:: IS_OP (invert)
- Performs ``is`` comparison, or ``is not`` if ``invert`` is 1.
+ Performs ``is`` comparison, or ``is not`` if ``invert`` is 1.
.. versionadded:: 3.9
.. opcode:: CONTAINS_OP (invert)
- Performs ``in`` comparison, or ``not in`` if ``invert`` is 1.
+ Performs ``in`` comparison, or ``not in`` if ``invert`` is 1.
.. versionadded:: 3.9
.. opcode:: JUMP_IF_NOT_EXC_MATCH (target)
- Tests whether the second value on the stack is an exception matching TOS,
- and jumps if it is not. Pops two values from the stack.
+ Tests whether the second value on the stack is an exception matching TOS,
+ and jumps if it is not. Pops two values from the stack.
.. versionadded:: 3.9
* If it is an *integer*, the array will have that size and will be
initialized with null bytes.
- * If it is an object conforming to the *buffer* interface, a read-only buffer
- of the object will be used to initialize the bytes array.
+ * If it is an object conforming to the :ref:`buffer interface <bufferobjects>`,
+ a read-only buffer of the object will be used to initialize the bytes array.
* If it is an *iterable*, it must be an iterable of integers in the range
``0 <= x < 256``, which are used as the initial contents of the array.
interactive statement (in the latter case, expression statements that
evaluate to something other than ``None`` will be printed).
- The optional arguments *flags* and *dont_inherit* control which :ref:`future
- statements <future>` affect the compilation of *source*. If neither
- is present (or both are zero) the code is compiled with those future
- statements that are in effect in the code that is calling :func:`compile`. If the
- *flags* argument is given and *dont_inherit* is not (or is zero) then the
- future statements specified by the *flags* argument are used in addition to
- those that would be used anyway. If *dont_inherit* is a non-zero integer then
- the *flags* argument is it -- the future statements in effect around the call
- to compile are ignored.
-
- Future statements are specified by bits which can be bitwise ORed together to
- specify multiple statements. The bitfield required to specify a given feature
- can be found as the :attr:`~__future__._Feature.compiler_flag` attribute on
- the :class:`~__future__._Feature` instance in the :mod:`__future__` module.
-
- The optional argument *flags* also controls whether the compiled source is
- allowed to contain top-level ``await``, ``async for`` and ``async with``.
- When the bit ``ast.PyCF_ALLOW_TOP_LEVEL_AWAIT`` is set, the return code
- object has ``CO_COROUTINE`` set in ``co_code``, and can be interactively
- executed via ``await eval(code_object)``.
+ The optional arguments *flags* and *dont_inherit* control which
+ :ref:`compiler options <ast-compiler-flags>` should be activated
+ and which :ref:`future features <future>` should be allowed. If neither
+ is present (or both are zero) the code is compiled with the same flags that
+ affect the code that is calling :func:`compile`. If the *flags*
+ argument is given and *dont_inherit* is not (or is zero) then the compiler
+ options and the future statements specified by the *flags* argument are used
+ in addition to those that would be used anyway. If *dont_inherit* is a
+ non-zero integer then the *flags* argument is it -- the flags (future
+ features and compiler options) in the surrounding code are ignored.
+
+ Compiler options and future statements are specified by bits which can be
+ bitwise ORed together to specify multiple options. The bitfield required to
+ specify a given future feature can be found as the
+ :attr:`~__future__._Feature.compiler_flag` attribute on the
+ :class:`~__future__._Feature` instance in the :mod:`__future__` module.
+ :ref:`Compiler flags <ast-compiler-flags>` can be found in :mod:`ast`
+ module, with ``PyCF_`` prefix.
The argument *optimize* specifies the optimization level of the compiler; the
default value of ``-1`` selects the optimization level of the interpreter as
.. impl-detail:: This is the address of the object in memory.
+ .. audit-event:: builtins.id id id
+
.. function:: input([prompt])
def variance(self):
return statistics.variance(self._data)
- .. versionadded:: 3.8
+ Note, this decorator interferes with the operation of :pep:`412`
+ key-sharing dictionaries. This means that instance dictionaries
+ can take more space than usual.
- .. note::
+ Also, this decorator requires that the ``__dict__`` attribute on each instance
+ be a mutable mapping. This means it will not work with some types, such as
+ metaclasses (since the ``__dict__`` attributes on type instances are
+ read-only proxies for the class namespace), and those that specify
+ ``__slots__`` without including ``__dict__`` as one of the defined slots
+ (as such classes don't provide a ``__dict__`` attribute at all).
+
+ If a mutable mapping is not available or if space-efficient key sharing
+ is desired, an effect similar to :func:`cached_property` can be achieved
+ by a stacking :func:`property` on top of :func:`cache`::
- This decorator requires that the ``__dict__`` attribute on each instance
- be a mutable mapping. This means it will not work with some types, such as
- metaclasses (since the ``__dict__`` attributes on type instances are
- read-only proxies for the class namespace), and those that specify
- ``__slots__`` without including ``__dict__`` as one of the defined slots
- (as such classes don't provide a ``__dict__`` attribute at all).
+ class DataSet:
+ def __init__(self, sequence_of_numbers):
+ self._data = sequence_of_numbers
+
+ @property
+ @cache
+ def stdev(self):
+ return statistics.stdev(self._data)
+
+ .. versionadded:: 3.8
.. function:: cmp_to_key(func)
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.
\ No newline at end of file
+during instance attribute look-up.
Calltips
^^^^^^^^
-A calltip is shown when one types :kbd:`(` after the name of an *accessible*
-function. A name expression may include dots and subscripts. A calltip
-remains until it is clicked, the cursor is moved out of the argument area,
-or :kbd:`)` is typed. When the cursor is in the argument part of a definition,
-the menu or shortcut display a calltip.
-
-A calltip consists of the function signature and the first line of the
-docstring. For builtins without an accessible signature, the calltip
-consists of all lines up the fifth line or the first blank line. These
-details may change.
-
-The set of *accessible* functions depends on what modules have been imported
-into the user process, including those imported by Idle itself,
-and what definitions have been run, all since the last restart.
+A calltip is shown automatically when one types :kbd:`(` after the name
+of an *accessible* function. A function name expression may include
+dots and subscripts. A calltip remains until it is clicked, the cursor
+is moved out of the argument area, or :kbd:`)` is typed. Whenever the
+cursor is in the argument part of a definition, select Edit and "Show
+Call Tip" on the menu or enter its shortcut to display a calltip.
+
+The calltip consists of the function's signature and docstring up to
+the latter's first blank line or the fifth non-blank line. (Some builtin
+functions lack an accessible signature.) A '/' or '*' in the signature
+indicates that the preceding or following arguments are passed by
+position or name (keyword) only. Details are subject to change.
+
+In Shell, the accessible functions depends on what modules have been
+imported into the user process, including those imported by Idle itself,
+and which definitions have been run, all since the last restart.
For example, restart the Shell and enter ``itertools.count(``. A calltip
-appears because Idle imports itertools into the user process for its own use.
-(This could change.) Enter ``turtle.write(`` and nothing appears. Idle does
-not import turtle. The menu or shortcut do nothing either. Enter
-``import turtle`` and then ``turtle.write(`` will work.
-
-In an editor, import statements have no effect until one runs the file. One
-might want to run a file after writing the import statements at the top,
-or immediately run an existing file before editing.
+appears because Idle imports itertools into the user process for its own
+use. (This could change.) Enter ``turtle.write(`` and nothing appears.
+Idle does not itself import turtle. The menu entry and shortcut also do
+nothing. Enter ``import turtle``. Thereafter, ``turtle.write(``
+will display a calltip.
+
+In an editor, import statements have no effect until one runs the file.
+One might want to run a file after writing import statements, after
+adding function definitions, or after opening an existing file.
.. _code-context:
.. seealso::
- Documents describing the protocol, and sources and binaries for servers
- implementing it, can all be found at the University of Washington's *IMAP
- Information Center* (https://www.washington.edu/imap/).
+ Documents describing the protocol, sources for servers
+ implementing it, by the University of Washington's IMAP Information Center
+ can all be found at (**Source Code**) https://github.com/uw-imap/imap (**Not Maintained**).
.. _imap4-objects:
package. This attribute is not set on modules.
- :attr:`__package__`
- The parent package for the module/package. If the module is
- top-level then it has a value of the empty string. The
+ The fully-qualified name of the package under which the module was
+ loaded as a submodule (or the empty string for top-level modules).
+ For packages, it is the same as :attr:`__name__`. The
:func:`importlib.util.module_for_loader` decorator can handle the
details for :attr:`__package__`.
(``__loader__``)
- The loader to use for loading. For namespace packages this should be
- set to ``None``.
+ The :term:`Loader <loader>` that should be used when loading
+ the module. :term:`Finders <finder>` should always set this.
.. attribute:: origin
(``__package__``)
- (Read-only) Fully-qualified name of the package to which the module
- belongs as a submodule (or ``None``).
+ (Read-only) The fully-qualified name of the package under which the module
+ should be loaded as a submodule (or the empty string for top-level modules).
+ For packages, it is the same as :attr:`__name__`.
.. attribute:: has_location
.. _iana-ipv4-special-registry: https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
.. _iana-ipv6-special-registry: https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml
+.. method:: IPv4Address.__format__(fmt)
+
+ Returns a string representation of the IP address, controlled by
+ an explicit format string.
+ *fmt* can be one of the following: ``'s'``, the default option,
+ equivalent to :func:`str`, ``'b'`` for a zero-padded binary string,
+ ``'X'`` or ``'x'`` for an uppercase or lowercase hexadecimal
+ representation, or ``'n'``, which is equivalent to ``'b'`` for IPv4
+ addresses and ``'x'`` for IPv6. For binary and hexadecimal
+ representations, the form specifier ``'#'`` and the grouping option
+ ``'_'`` are available. ``__format__`` is used by ``format``, ``str.format``
+ and f-strings.
+
+ >>> format(ipaddress.IPv4Address('192.168.0.1'))
+ '192.168.0.1'
+ >>> '{:#b}'.format(ipaddress.IPv4Address('192.168.0.1'))
+ '0b11000000101010000000000000000001'
+ >>> f'{ipaddress.IPv6Address("2001:db8::1000"):s}'
+ '2001:db8::1000'
+ >>> format(ipaddress.IPv6Address('2001:db8::1000'), '_X')
+ '2001_0DB8_0000_0000_0000_0000_0000_1000'
+ >>> '{:#_n}'.format(ipaddress.IPv6Address('2001:db8::1000'))
+ '0x2001_0db8_0000_0000_0000_0000_0000_1000'
+
+ .. versionadded:: 3.9
+
.. class:: IPv6Address(address)
groups consisting entirely of zeroes included.
- For the following attributes, see the corresponding documentation of the
- :class:`IPv4Address` class:
+ For the following attributes and methods, see the corresponding
+ documentation of the :class:`IPv4Address` class:
.. attribute:: packed
.. attribute:: reverse_pointer
the embedded ``(server, client)`` IP address pair. For any other
address, this property will be ``None``.
+.. method:: IPv6Address.__format__(fmt)
+
+ Refer to the corresponding method documentation in
+ :class:`IPv4Address`.
+
+ .. versionadded:: 3.9
Conversion to Strings and Integers
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
"Count how many times the predicate is true"
return sum(map(pred, iterable))
- def padnone(iterable):
+ def pad_none(iterable):
"""Returns the sequence elements and then returns None indefinitely.
Useful for emulating the behavior of the built-in map() function.
nexts = cycle(islice(nexts, num_active))
def partition(pred, iterable):
- 'Use a predicate to partition entries into false entries and true entries'
+ "Use a predicate to partition entries into false entries and true entries"
# partition(is_odd, range(10)) --> 0 2 4 6 8 and 1 3 5 7 9
t1, t2 = tee(iterable)
return filterfalse(pred, t1), filter(pred, t2)
def random_product(*args, repeat=1):
"Random selection from itertools.product(*args, **kwds)"
pools = [tuple(pool) for pool in args] * repeat
- return tuple(random.choice(pool) for pool in pools)
+ return tuple(map(random.choice, pools))
def random_permutation(iterable, r=None):
"Random selection from itertools.permutations(iterable, r)"
"Random selection from itertools.combinations_with_replacement(iterable, r)"
pool = tuple(iterable)
n = len(pool)
- indices = sorted(random.randrange(n) for i in range(r))
+ indices = sorted(random.choices(range(n), k=r))
return tuple(pool[i] for i in indices)
def nth_combination(iterable, r, index):
- 'Equivalent to list(combinations(iterable, r))[index]'
+ "Equivalent to list(combinations(iterable, r))[index]"
pool = tuple(iterable)
n = len(pool)
if r < 0 or r > n:
.. seealso::
- `maildir man page from qmail <http://www.qmail.org/man/man5/maildir.html>`_
- The original specification of the format.
+ `maildir man page from Courier <http://www.courier-mta.org/maildir.html>`_
+ A specification of the format. Describes a common extension for
+ supporting folders.
`Using maildir format <https://cr.yp.to/proto/maildir.html>`_
Notes on Maildir by its inventor. Includes an updated name-creation scheme and
details on "info" semantics.
- `maildir man page from Courier <http://www.courier-mta.org/maildir.html>`_
- Another specification of the format. Describes a common extension for supporting
- folders.
-
.. _mailbox-mbox:
.. seealso::
- `mbox man page from qmail <http://www.qmail.org/man/man5/mbox.html>`_
- A specification of the format and its variations.
-
`mbox man page from tin <http://www.tin.org/bin/man.cgi?section=5&topic=mbox>`_
- Another specification of the format, with details on locking.
+ A specification of the format, with details on locking.
`Configuring Netscape Mail on Unix: Why The Content-Length Format is Bad <https://www.jwz.org/doc/content-length.html>`_
An argument for using the original mbox format rather than a variation.
Return the greatest common divisor of the specified integer arguments.
If any of the arguments is nonzero, then the returned value is the largest
- positive integer that is a divisor af all arguments. If all arguments
+ positive integer that is a divisor of all arguments. If all arguments
are zero, then the returned value is ``0``. ``gcd()`` without arguments
returns ``0``.
*spawn*
The parent process starts a fresh python interpreter process. The
child process will only inherit those resources necessary to run
- the process objects :meth:`~Process.run` method. In particular,
+ the process object's :meth:`~Process.run` method. In particular,
unnecessary file descriptors and handles from the parent process
will not be inherited. Starting a process using this method is
rather slow compared to using *fork* or *forkserver*.
filesystem.
* An ``'AF_PIPE'`` address is a string of the form
- :samp:`r'\\\\.\\pipe\\{PipeName}'`. To use :func:`Client` to connect to a named
- pipe on a remote computer called *ServerName* one should use an address of the
- form :samp:`r'\\\\{ServerName}\\pipe\\{PipeName}'` instead.
+ :samp:`r'\\\\.\\pipe\\{PipeName}'`. To use :func:`Client` to connect to a named
+ pipe on a remote computer called *ServerName* one should use an address of the
+ form :samp:`r'\\\\{ServerName}\\pipe\\{PipeName}'` instead.
Note that any string beginning with two backslashes is assumed by default to be
an ``'AF_PIPE'`` address rather than an ``'AF_UNIX'`` address.
The positional-only arguments *path*, *args*, and *env* are similar to
:func:`execve`.
- The *path* parameter is the path to the executable file.The *path* should
- contain a directory.Use :func:`posix_spawnp` to pass an executable file
+ The *path* parameter is the path to the executable file. The *path* should
+ contain a directory. Use :func:`posix_spawnp` to pass an executable file
without directory.
The *file_actions* argument may be a sequence of tuples describing actions
which means the OS version uses debugging code, i.e. code that checks arguments,
ranges, etc.
- .. note::
-
- This function works best with Mark Hammond's
- :mod:`win32all` package installed, but also on Python 2.3 and
- later (support for this was added in Python 2.6). It obviously
- only runs on Win32 compatible platforms.
-
.. function:: win32_edition()
Returns a string representing the current Windows edition. Possible
.. audit-event:: poplib.connect self,host,port poplib.POP3_SSL
- .. audit-event:: poplib.putline self,line popplib.POP3_SSL
+ .. audit-event:: poplib.putline self,line poplib.POP3_SSL
All commands will raise an :ref:`auditing event <auditing>`
``poplib.putline`` with arguments ``self`` and ``line``,
order so that the sample is reproducible.
+.. _real-valued-distributions:
+
Real-valued distributions
-------------------------
deviation. This is slightly faster than the :func:`normalvariate` function
defined below.
+ Multithreading note: When two threads call this function
+ simultaneously, it is possible that they will receive the
+ same return value. This can be avoided in three ways.
+ 1) Have each thread use a different instance of the random
+ number generator. 2) Put locks around all calls. 3) Use the
+ slower, but thread-safe :func:`normalvariate` function instead.
+
.. function:: lognormvariate(mu, sigma)
.. _random-examples:
-Examples and Recipes
---------------------
+Examples
+--------
Basic examples::
a tutorial by `Peter Norvig <http://norvig.com/bio.html>`_ covering
the basics of probability theory, how to write simulations, and
how to perform data analysis using Python.
+
+
+Recipes
+-------
+
+The default :func:`.random` returns multiples of 2⁻⁵³ in the range
+*0.0 ≤ x < 1.0*. All such numbers are evenly spaced and are exactly
+representable as Python floats. However, many other representable
+floats in that interval are not possible selections. For example,
+``0.05954861408025609`` isn't an integer multiple of 2⁻⁵³.
+
+The following recipe takes a different approach. All floats in the
+interval are possible selections. The mantissa comes from a uniform
+distribution of integers in the range *2⁵² ≤ mantissa < 2⁵³*. The
+exponent comes from a geometric distribution where exponents smaller
+than *-53* occur half as often as the next larger exponent.
+
+::
+
+ from random import Random
+ from math import ldexp
+
+ class FullRandom(Random):
+
+ def random(self):
+ mantissa = 0x10_0000_0000_0000 | self.getrandbits(52)
+ exponent = -53
+ x = 0
+ while not x:
+ x = self.getrandbits(32)
+ exponent += x.bit_length() - 32
+ return ldexp(mantissa, exponent)
+
+All :ref:`real valued distributions <real-valued-distributions>`
+in the class will use the new method::
+
+ >>> fr = FullRandom()
+ >>> fr.random()
+ 0.05954861408025609
+ >>> fr.expovariate(0.25)
+ 8.87925541791544
+
+The recipe is conceptually equivalent to an algorithm that chooses from
+all the multiples of 2⁻¹⁰⁷⁴ in the range *0.0 ≤ x < 1.0*. All such
+numbers are evenly spaced, but most have to be rounded down to the
+nearest representable Python float. (The value 2⁻¹⁰⁷⁴ is the smallest
+positive unnormalized float and is equal to ``math.ulp(0.0)``.)
+
+
+.. seealso::
+
+ `Generating Pseudo-random Floating-Point Values
+ <https://allendowney.com/research/rand/downey07randfloat.pdf>`_ a
+ paper by Allen B. Downey describing ways to generate more
+ fine-grained floats than normally generated by :func:`.random`.
.. function:: copy(src, dst, *, follow_symlinks=True)
Copies the file *src* to the file or directory *dst*. *src* and *dst*
- should be strings. If *dst* specifies a directory, the file will be
- copied into *dst* using the base filename from *src*. Returns the
- path to the newly created file.
+ should be :term:`path-like objects <path-like object>` or strings. If
+ *dst* specifies a directory, the file will be copied into *dst* using the
+ base filename from *src*. Returns the path to the newly created file.
If *follow_symlinks* is false, and *src* is a symbolic link,
*dst* will be created as a symbolic link. If *follow_symlinks*
will be created in or as *dst* and *src* will be removed.
If *copy_function* is given, it must be a callable that takes two arguments
- *src* and *dst*, and will be used to copy *src* to *dest* if
+ *src* and *dst*, and will be used to copy *src* to *dst* if
:func:`os.rename` cannot be used. If the source is a directory,
:func:`copytree` is called, passing it the :func:`copy_function`. The
default *copy_function* is :func:`copy2`. Using :func:`~shutil.copy` as the
Child process stopped or terminated.
- .. availability:: Windows.
+ .. availability:: Unix.
.. data:: SIGCLD
Return the path of the user-specific site-packages directory,
:data:`USER_SITE`. If it is not initialized yet, this function will also set
- it, respecting :envvar:`PYTHONNOUSERSITE` and :data:`USER_BASE`.
+ it, respecting :data:`USER_BASE`. To determine if the user-specific
+ site-packages was added to ``sys.path`` :data:`ENABLE_USER_SITE` should be
+ used.
.. versionadded:: 3.2
If the *timeout* parameter is set to be zero, it will raise a
:class:`ValueError` to prevent the creation of a non-blocking socket
-.. class:: LMTP(host='', port=LMTP_PORT, local_hostname=None,
+.. class:: LMTP(host='', port=LMTP_PORT, local_hostname=None, \
source_address=None[, timeout])
The LMTP protocol, which is very similar to ESMTP, is heavily based on the
.. versionchanged:: 3.8
Windows support was added.
+ .. note::
+
+ On Windows network interfaces have different names in different contexts
+ (all names are examples):
+
+ * UUID: ``{FB605B73-AAC2-49A6-9A2F-25416AEA0573}``
+ * name: ``ethernet_32770``
+ * friendly name: ``vEthernet (nat)``
+ * description: ``Hyper-V Virtual Ethernet Adapter``
+
+ This function returns names of the second form from the list, ``ethernet_32770``
+ in this example case.
+
.. function:: if_nametoindex(if_name)
.. versionchanged:: 3.8
Windows support was added.
+ .. seealso::
+ "Interface name" is a name as documented in :func:`if_nameindex`.
+
.. function:: if_indextoname(if_index)
.. versionchanged:: 3.8
Windows support was added.
+ .. seealso::
+ "Interface name" is a name as documented in :func:`if_nameindex`.
+
.. _socket-objects:
objects. If *iterable* is not specified, a new empty set is
returned.
+ Sets can be created by several means:
+
+ * Use a comma-separated list of elements within braces: ``{'jack', 'sjoerd'}``
+ * Use a set comprehension: ``{c for c in 'abracadabra' if c not in 'abc'}``
+ * Use the type constructor: ``set()``, ``set('foobar')``, ``set(['a', 'b', 'foo'])``
+
Instances of :class:`set` and :class:`frozenset` provide the following
operations:
Return a new dictionary initialized from an optional positional argument
and a possibly empty set of keyword arguments.
+ Dictionaries can be created by several means:
+
+ * Use a comma-separated list of ``key: value`` pairs within braces:
+ ``{'jack': 4098, 'sjoerd': 4127}`` or ``{4098: 'jack', 4127: 'sjoerd'}``
+ * Use a dict comprehension: ``{}``, ``{x: x ** 2 for x in range(10)}``
+ * Use the type constructor: ``dict()``,
+ ``dict([('foo', 100), ('bar', 200)])``, ``dict(foo=100, bar=200)``
+
If no positional argument is given, an empty dictionary is created.
If a positional argument is given and it is a mapping object, a dictionary
is created with the same key-value pairs as the mapping object. Otherwise,
single class dictionary lookup is negligible.
+.. _types-genericalias:
+
+Generic Alias Type
+==================
+
+.. index::
+ object: GenericAlias
+ pair: Generic; Alias
+
+``GenericAlias`` objects are created by subscripting a class (usually a
+container), such as ``list[int]``. They are intended primarily for
+:term:`type annotations <annotation>`.
+
+Usually, the :ref:`subscription <subscriptions>` of container objects calls the
+method :meth:`__getitem__` of the object. However, the subscription of some
+containers' classes may call the classmethod :meth:`__class_getitem__` of the
+class instead. The classmethod :meth:`__class_getitem__` should return a
+``GenericAlias`` object.
+
+.. note::
+ If the :meth:`__getitem__` of the class' metaclass is present, it will take
+ precedence over the :meth:`__class_getitem__` defined in the class (see
+ :pep:`560` for more details).
+
+The ``GenericAlias`` object acts as a proxy for :term:`generic types
+<generic type>`, implementing *parameterized generics* - a specific instance
+of a generic which provides the types for container elements.
+
+The user-exposed type for the ``GenericAlias`` object can be accessed from
+:class:`types.GenericAlias` and used for :func:`isinstance` checks. It can
+also be used to create ``GenericAlias`` objects directly.
+
+.. describe:: T[X, Y, ...]
+
+ Creates a ``GenericAlias`` representing a type ``T`` containing elements
+ of types *X*, *Y*, and more depending on the ``T`` used.
+ For example, a function expecting a :class:`list` containing
+ :class:`float` elements::
+
+ def average(values: list[float]) -> float:
+ return sum(values) / len(values)
+
+ Another example for :term:`mapping` objects, using a :class:`dict`, which
+ is a generic type expecting two type parameters representing the key type
+ and the value type. In this example, the function expects a ``dict`` with
+ keys of type :class:`str` and values of type :class:`int`::
+
+ def send_post_request(url: str, body: dict[str, int]) -> None:
+ ...
+
+The builtin functions :func:`isinstance` and :func:`issubclass` do not accept
+``GenericAlias`` types for their second argument::
+
+ >>> isinstance([1, 2], list[str])
+ Traceback (most recent call last):
+ File "<stdin>", line 1, in <module>
+ TypeError: isinstance() argument 2 cannot be a parameterized generic
+
+The Python runtime does not enforce :term:`type annotations <annotation>`.
+This extends to generic types and their type parameters. When creating
+an object from a ``GenericAlias``, container elements are not checked
+against their type. For example, the following code is discouraged, but will
+run without errors::
+
+ >>> t = list[str]
+ >>> t([1, 2, 3])
+ [1, 2, 3]
+
+Furthermore, parameterized generics erase type parameters during object
+creation::
+
+ >>> t = list[str]
+ >>> type(t)
+ <class 'types.GenericAlias'>
+
+ >>> l = t()
+ >>> type(l)
+ <class 'list'>
+
+Calling :func:`repr` or :func:`str` on a generic shows the parameterized type::
+
+ >>> repr(list[int])
+ 'list[int]'
+
+ >>> str(list[int])
+ 'list[int]'
+
+The :meth:`__getitem__` method of generics will raise an exception to disallow
+mistakes like ``dict[str][str]``::
+
+ >>> dict[str][str]
+ Traceback (most recent call last):
+ File "<stdin>", line 1, in <module>
+ TypeError: There are no type variables left in dict[str]
+
+However, such expressions are valid when :ref:`type variables <generics>` are
+used. The index must have as many elements as there are type variable items
+in the ``GenericAlias`` object's :attr:`__args__ <genericalias.__args__>`. ::
+
+ >>> from typing import TypeVar
+ >>> Y = TypeVar('Y')
+ >>> dict[str, Y][int]
+ dict[str, int]
+
+
+Standard Generic Collections
+----------------------------
+
+These standard library collections support parameterized generics.
+
+* :class:`tuple`
+* :class:`list`
+* :class:`dict`
+* :class:`set`
+* :class:`frozenset`
+* :class:`type`
+* :class:`collections.deque`
+* :class:`collections.defaultdict`
+* :class:`collections.OrderedDict`
+* :class:`collections.Counter`
+* :class:`collections.ChainMap`
+* :class:`collections.abc.Awaitable`
+* :class:`collections.abc.Coroutine`
+* :class:`collections.abc.AsyncIterable`
+* :class:`collections.abc.AsyncIterator`
+* :class:`collections.abc.AsyncGenerator`
+* :class:`collections.abc.Iterable`
+* :class:`collections.abc.Iterator`
+* :class:`collections.abc.Generator`
+* :class:`collections.abc.Reversible`
+* :class:`collections.abc.Container`
+* :class:`collections.abc.Collection`
+* :class:`collections.abc.Callable`
+* :class:`collections.abc.Set`
+* :class:`collections.abc.MutableSet`
+* :class:`collections.abc.Mapping`
+* :class:`collections.abc.MutableMapping`
+* :class:`collections.abc.Sequence`
+* :class:`collections.abc.MutableSequence`
+* :class:`collections.abc.ByteString`
+* :class:`collections.abc.MappingView`
+* :class:`collections.abc.KeysView`
+* :class:`collections.abc.ItemsView`
+* :class:`collections.abc.ValuesView`
+* :class:`contextlib.AbstractContextManager`
+* :class:`contextlib.AbstractAsyncContextManager`
+* :ref:`re.Pattern <re-objects>`
+* :ref:`re.Match <match-objects>`
+
+
+Special Attributes of Generic Alias
+-----------------------------------
+
+All parameterized generics implement special read-only attributes.
+
+.. attribute:: genericalias.__origin__
+
+ This attribute points at the non-parameterized generic class::
+
+ >>> list[int].__origin__
+ <class 'list'>
+
+
+.. attribute:: genericalias.__args__
+
+ This attribute is a :class:`tuple` (possibly of length 1) of generic
+ types passed to the original :meth:`__class_getitem__`
+ of the generic container::
+
+ >>> dict[str, list[int]].__args__
+ (<class 'str'>, list[int])
+
+
+.. attribute:: genericalias.__parameters__
+
+ This attribute is a lazily computed tuple (possibly empty) of unique type
+ variables found in ``__args__``::
+
+ >>> from typing import TypeVar
+
+ >>> T = TypeVar('T')
+ >>> list[T].__parameters__
+ (~T,)
+
+
+.. seealso::
+
+ * :pep:`585` -- "Type Hinting Generics In Standard Collections"
+ * :meth:`__class_getitem__` -- Used to implement parameterized generics.
+ * :ref:`generics` -- Generics in the :mod:`typing` module.
+
+.. versionadded:: 3.9
+
+
.. _typesother:
Other Built-in Types
The ``'#'`` option causes the "alternate form" to be used for the
conversion. The alternate form is defined differently for different
-types. This option is only valid for integer, float, complex and
-Decimal types. For integers, when binary, octal, or hexadecimal output
+types. This option is only valid for integer, float and complex
+types. For integers, when binary, octal, or hexadecimal output
is used, this option adds the prefix respective ``'0b'``, ``'0o'``, or
-``'0x'`` to the output value. For floats, complex and Decimal the
+``'0x'`` to the output value. For float and complex the
alternate form causes the result of the conversion to always contain a
decimal-point character, even if no digits follow it. Normally, a
decimal-point character appears in the result of these conversions
``'n'`` and ``None``). When doing so, :func:`float` is used to convert the
integer to a floating point number before formatting.
-The available presentation types for floating point and decimal values are:
+The available presentation types for :class:`float` and
+:class:`~decimal.Decimal` values are:
+---------+----------------------------------------------------------+
| Type | Meaning |
+=========+==========================================================+
- | ``'e'`` | Exponent notation. Prints the number in scientific |
- | | notation using the letter 'e' to indicate the exponent. |
- | | The default precision is ``6``. |
+ | ``'e'`` | Scientific notation. For a given precision ``p``, |
+ | | formats the number in scientific notation with the |
+ | | letter 'e' separating the coefficient from the exponent. |
+ | | The coefficient has one digit before and ``p`` digits |
+ | | after the decimal point, for a total of ``p + 1`` |
+ | | significant digits. With no precision given, uses a |
+ | | precision of ``6`` digits after the decimal point for |
+ | | :class:`float`, and shows all coefficient digits |
+ | | for :class:`~decimal.Decimal`. If no digits follow the |
+ | | decimal point, the decimal point is also removed unless |
+ | | the ``#`` option is used. |
+---------+----------------------------------------------------------+
- | ``'E'`` | Exponent notation. Same as ``'e'`` except it uses an |
- | | upper case 'E' as the separator character. |
+ | ``'E'`` | Scientific notation. Same as ``'e'`` except it uses |
+ | | an upper case 'E' as the separator character. |
+---------+----------------------------------------------------------+
- | ``'f'`` | Fixed-point notation. Displays the number as a |
- | | fixed-point number. The default precision is ``6``. |
+ | ``'f'`` | Fixed-point notation. For a given precision ``p``, |
+ | | formats the number as a decimal number with exactly |
+ | | ``p`` digits following the decimal point. With no |
+ | | precision given, uses a precision of ``6`` digits after |
+ | | the decimal point for :class:`float`, and uses a |
+ | | precision large enough to show all coefficient digits |
+ | | for :class:`~decimal.Decimal`. If no digits follow the |
+ | | decimal point, the decimal point is also removed unless |
+ | | the ``#`` option is used. |
+---------+----------------------------------------------------------+
| ``'F'`` | Fixed-point notation. Same as ``'f'``, but converts |
| | ``nan`` to ``NAN`` and ``inf`` to ``INF``. |
| | the precision. |
| | |
| | A precision of ``0`` is treated as equivalent to a |
- | | precision of ``1``. The default precision is ``6``. |
+ | | precision of ``1``. With no precision given, uses a |
+ | | precision of ``6`` significant digits for |
+ | | :class:`float`, and shows all coefficient digits |
+ | | for :class:`~decimal.Decimal`. |
+---------+----------------------------------------------------------+
| ``'G'`` | General format. Same as ``'g'`` except switches to |
| | ``'E'`` if the number gets too large. The |
When an auditing event is raised through the :func:`sys.audit` function, each
hook will be called in the order it was added with the event name and the
tuple of arguments. Native hooks added by :c:func:`PySys_AddAuditHook` are
- called first, followed by hooks added in the current interpreter.
+ called first, followed by hooks added in the current interpreter. Hooks
+ can then log the event, raise an exception to abort the operation,
+ or terminate the process entirely.
.. audit-event:: sys.addaudithook "" sys.addaudithook
- Raise an auditing event ``sys.addaudithook`` with no arguments. If any
+ Calling :func:`sys.addaudithook` will itself raise an auditing event
+ named ``sys.addaudithook`` with no arguments. If any
existing hooks raise an exception derived from :class:`RuntimeError`, the
new hook will not be added and the exception suppressed. As a result,
callers cannot assume that their hook has been added unless they control
all existing hooks.
+ See the :ref:`audit events table <audit-events>` for all events raised by
+ CPython, and :pep:`578` for the original design discussion.
+
.. versionadded:: 3.8
.. versionchanged:: 3.8.1
.. index:: single: auditing
- Raise an auditing event with any active hooks. The event name is a string
- identifying the event and its associated schema, which is the number and
- types of arguments. The schema for a given event is considered public and
- stable API and should not be modified between releases.
-
- This function will raise the first exception raised by any hook. In general,
- these errors should not be handled and should terminate the process as
- quickly as possible.
+ Raise an auditing event and trigger any active auditing hooks.
+ *event* is a string identifying the event, and *args* may contain
+ optional arguments with more information about the event. The
+ number and types of arguments for a given event are considered a
+ public and stable API and should not be modified between releases.
+
+ For example, one auditing event is named ``os.chdir``. This event has
+ one argument called *path* that will contain the requested new
+ working directory.
+
+ :func:`sys.audit` will call the existing auditing hooks, passing
+ the event name and arguments, and will re-raise the first exception
+ from any hook. In general, if an exception is raised, it should not
+ be handled and the process should be terminated as quickly as
+ possible. This allows hook implementations to decide how to respond
+ to particular events: they can merely log the event or abort the
+ operation by raising an exception.
Hooks are added using the :func:`sys.addaudithook` or
:c:func:`PySys_AddAuditHook` functions.
.. method:: TarFile.extractfile(member)
- Extract a member from the archive as a file object. *member* may be a filename
- or a :class:`TarInfo` object. If *member* is a regular file or a link, an
- :class:`io.BufferedReader` object is returned. Otherwise, :const:`None` is
- returned.
+ Extract a member from the archive as a file object. *member* may be
+ a filename or a :class:`TarInfo` object. If *member* is a regular file or
+ a link, an :class:`io.BufferedReader` object is returned. For all other
+ existing members, :const:`None` is returned. If *member* does not appear
+ in the archive, :exc:`KeyError` is raised.
.. versionchanged:: 3.3
Return an :class:`io.BufferedReader` object.
The :mod:`test.support.bytecode_helper` module provides support for testing
and inspecting bytecode generation.
+.. versionadded:: 3.9
+
The module defines the following class:
.. class:: BytecodeTestCase(unittest.TestCase)
The type of user-defined functions and functions created by
:keyword:`lambda` expressions.
+ .. audit-event:: function.__new__ code types.FunctionType
+
+ The audit event only occurs for direct instantiation of function objects,
+ and is not raised for normal compilation.
+
.. data:: GeneratorType
The type for code objects such as returned by :func:`compile`.
- .. audit-event:: code.__new__ code,filename,name,argcount,posonlyargcount,kwonlyargcount,nlocals,stacksize,flags CodeType
+ .. audit-event:: code.__new__ code,filename,name,argcount,posonlyargcount,kwonlyargcount,nlocals,stacksize,flags types.CodeType
Note that the audited arguments may not match the names or positions
- required by the initializer.
+ required by the initializer. The audit event only occurs for direct
+ instantiation of code objects, and is not raised for normal compilation.
.. method:: CodeType.replace(**kwargs)
Defaults to ``None``. Previously the attribute was optional.
+.. class:: GenericAlias(t_origin, t_args)
+
+ The type of :ref:`parameterized generics <types-genericalias>` such as
+ ``list[int]``.
+
+ ``t_origin`` should be a non-parameterized generic class, such as ``list``,
+ ``tuple`` or ``dict``. ``t_args`` should be a :class:`tuple` (possibly of
+ length 1) of types which parameterize ``t_origin``::
+
+ >>> from types import GenericAlias
+
+ >>> list[int] == GenericAlias(list, (int,))
+ True
+ >>> dict[str, int] == GenericAlias(dict, (str, int))
+ True
+
+ .. versionadded:: 3.9
+
+
.. class:: TracebackType(tb_next, tb_frame, tb_lasti, tb_lineno)
The type of traceback objects such as found in ``sys.exc_info()[2]``.
return "{}({})".format(type(self).__name__, ", ".join(items))
def __eq__(self, other):
- return self.__dict__ == other.__dict__
+ if isinstance(self, SimpleNamespace) and isinstance(other, SimpleNamespace):
+ return self.__dict__ == other.__dict__
+ return NotImplemented
``SimpleNamespace`` may be useful as a replacement for ``class NS: pass``.
However, for a structured record type use :func:`~collections.namedtuple`
is equivalent to ``Tuple[Any, ...]``, and in turn to :class:`tuple`.
.. deprecated:: 3.9
- :class:`builtins.tuple <tuple>` now supports ``[]``. See :pep:`585`.
+ :class:`builtins.tuple <tuple>` now supports ``[]``. See :pep:`585` and
+ :ref:`types-genericalias`.
.. data:: Union
:class:`collections.abc.Callable`.
.. deprecated:: 3.9
- :class:`collections.abc.Callable` now supports ``[]``. See :pep:`585`.
+ :class:`collections.abc.Callable` now supports ``[]``. See :pep:`585` and
+ :ref:`types-genericalias`.
.. class:: Type(Generic[CT_co])
:ref:`type variables <generics>`, and unions of any of these types.
For example::
- def new_non_team_user(user_class: Type[Union[BaseUser, ProUser]]): ...
+ def new_non_team_user(user_class: Type[Union[BasicUser, ProUser]]): ...
``Type[Any]`` is equivalent to ``Type`` which in turn is equivalent
to ``type``, which is the root of Python's metaclass hierarchy.
.. versionadded:: 3.5.2
.. deprecated:: 3.9
- :class:`builtins.type <type>` now supports ``[]``. See :pep:`585`.
+ :class:`builtins.type <type>` now supports ``[]``. See :pep:`585` and
+ :ref:`types-genericalias`.
.. data:: Literal
.. versionadded:: 3.8
+ .. versionchanged:: 3.9.1
+ ``Literal`` now de-duplicates parameters. Equality comparison of
+ ``Literal`` objects are no longer order dependent. ``Literal`` objects
+ will now raise a :exc:`TypeError` exception during equality comparisons
+ if one of their parameters are not :term:`immutable`.
+
.. data:: ClassVar
Special type construct to mark class variables.
Type variables exist primarily for the benefit of static type
checkers. They serve as the parameters for generic types as well
- as for generic function definitions. See class Generic for more
+ as for generic function definitions. See :class:`Generic` for more
information on generic types. Generic functions work as follows::
def repeat(x: T, n: int) -> Sequence[T]:
...
.. deprecated:: 3.9
- :class:`builtins.dict <dict>` now supports ``[]``. See :pep:`585`.
+ :class:`builtins.dict <dict>` now supports ``[]``. See :pep:`585` and
+ :ref:`types-genericalias`.
.. class:: List(list, MutableSequence[T])
return [item for item in vector if item > 0]
.. deprecated:: 3.9
- :class:`builtins.list <list>` now supports ``[]``. See :pep:`585`.
+ :class:`builtins.list <list>` now supports ``[]``. See :pep:`585` and
+ :ref:`types-genericalias`.
.. class:: Set(set, MutableSet[T])
to use an abstract collection type such as :class:`AbstractSet`.
.. deprecated:: 3.9
- :class:`builtins.set <set>` now supports ``[]``. See :pep:`585`.
+ :class:`builtins.set <set>` now supports ``[]``. See :pep:`585` and
+ :ref:`types-genericalias`.
.. class:: FrozenSet(frozenset, AbstractSet[T_co])
A generic version of :class:`builtins.frozenset <frozenset>`.
.. deprecated:: 3.9
- :class:`builtins.frozenset <frozenset>` now supports ``[]``. See :pep:`585`.
+ :class:`builtins.frozenset <frozenset>` now supports ``[]``. See
+ :pep:`585` and :ref:`types-genericalias`.
.. note:: :data:`Tuple` is a special form.
.. versionadded:: 3.5.2
.. deprecated:: 3.9
- :class:`collections.defaultdict` now supports ``[]``. See :pep:`585`.
+ :class:`collections.defaultdict` now supports ``[]``. See :pep:`585` and
+ :ref:`types-genericalias`.
.. class:: OrderedDict(collections.OrderedDict, MutableMapping[KT, VT])
.. versionadded:: 3.7.2
.. deprecated:: 3.9
- :class:`collections.OrderedDict` now supports ``[]``. See :pep:`585`.
+ :class:`collections.OrderedDict` now supports ``[]``. See :pep:`585` and
+ :ref:`types-genericalias`.
.. class:: ChainMap(collections.ChainMap, MutableMapping[KT, VT])
.. versionadded:: 3.6.1
.. deprecated:: 3.9
- :class:`collections.ChainMap` now supports ``[]``. See :pep:`585`.
+ :class:`collections.ChainMap` now supports ``[]``. See :pep:`585` and
+ :ref:`types-genericalias`.
.. class:: Counter(collections.Counter, Dict[T, int])
.. versionadded:: 3.6.1
.. deprecated:: 3.9
- :class:`collections.Counter` now supports ``[]``. See :pep:`585`.
+ :class:`collections.Counter` now supports ``[]``. See :pep:`585` and
+ :ref:`types-genericalias`.
.. class:: Deque(deque, MutableSequence[T])
.. versionadded:: 3.6.1
.. deprecated:: 3.9
- :class:`collections.deque` now supports ``[]``. See :pep:`585`.
+ :class:`collections.deque` now supports ``[]``. See :pep:`585` and
+ :ref:`types-genericalias`.
Other concrete types
""""""""""""""""""""
``Match[bytes]``. These types are also in the ``typing.re`` namespace.
.. deprecated:: 3.9
- Classes ``Pattern`` and ``Match`` from :mod:`re` now support ``[]``. See :pep:`585`.
+ Classes ``Pattern`` and ``Match`` from :mod:`re` now support ``[]``.
+ See :pep:`585` and :ref:`types-genericalias`.
.. class:: Text
A generic version of :class:`collections.abc.Set`.
.. deprecated:: 3.9
- :class:`collections.abc.Set` now supports ``[]``. See :pep:`585`.
+ :class:`collections.abc.Set` now supports ``[]``. See :pep:`585` and
+ :ref:`types-genericalias`.
.. class:: ByteString(Sequence[int])
annotate arguments of any of the types mentioned above.
.. deprecated:: 3.9
- :class:`collections.abc.ByteString` now supports ``[]``. See :pep:`585`.
+ :class:`collections.abc.ByteString` now supports ``[]``. See :pep:`585`
+ and :ref:`types-genericalias`.
.. class:: Collection(Sized, Iterable[T_co], Container[T_co])
.. versionadded:: 3.6.0
.. deprecated:: 3.9
- :class:`collections.abc.Collection` now supports ``[]``. See :pep:`585`.
+ :class:`collections.abc.Collection` now supports ``[]``. See :pep:`585`
+ and :ref:`types-genericalias`.
.. class:: Container(Generic[T_co])
A generic version of :class:`collections.abc.Container`.
.. deprecated:: 3.9
- :class:`collections.abc.Container` now supports ``[]``. See :pep:`585`.
+ :class:`collections.abc.Container` now supports ``[]``. See :pep:`585`
+ and :ref:`types-genericalias`.
.. class:: ItemsView(MappingView, Generic[KT_co, VT_co])
A generic version of :class:`collections.abc.ItemsView`.
.. deprecated:: 3.9
- :class:`collections.abc.ItemsView` now supports ``[]``. See :pep:`585`.
+ :class:`collections.abc.ItemsView` now supports ``[]``. See :pep:`585`
+ and :ref:`types-genericalias`.
.. class:: KeysView(MappingView[KT_co], AbstractSet[KT_co])
A generic version of :class:`collections.abc.KeysView`.
.. deprecated:: 3.9
- :class:`collections.abc.KeysView` now supports ``[]``. See :pep:`585`.
+ :class:`collections.abc.KeysView` now supports ``[]``. See :pep:`585`
+ and :ref:`types-genericalias`.
.. class:: Mapping(Sized, Collection[KT], Generic[VT_co])
return word_list[word]
.. deprecated:: 3.9
- :class:`collections.abc.Mapping` now supports ``[]``. See :pep:`585`.
+ :class:`collections.abc.Mapping` now supports ``[]``. See :pep:`585`
+ and :ref:`types-genericalias`.
.. class:: MappingView(Sized, Iterable[T_co])
A generic version of :class:`collections.abc.MappingView`.
.. deprecated:: 3.9
- :class:`collections.abc.MappingView` now supports ``[]``. See :pep:`585`.
+ :class:`collections.abc.MappingView` now supports ``[]``. See :pep:`585`
+ and :ref:`types-genericalias`.
.. class:: MutableMapping(Mapping[KT, VT])
A generic version of :class:`collections.abc.MutableMapping`.
.. deprecated:: 3.9
- :class:`collections.abc.MutableMapping` now supports ``[]``. See :pep:`585`.
+ :class:`collections.abc.MutableMapping` now supports ``[]``. See
+ :pep:`585` and :ref:`types-genericalias`.
.. class:: MutableSequence(Sequence[T])
A generic version of :class:`collections.abc.MutableSequence`.
.. deprecated:: 3.9
- :class:`collections.abc.MutableSequence` now supports ``[]``. See :pep:`585`.
+ :class:`collections.abc.MutableSequence` now supports ``[]``. See
+ :pep:`585` and :ref:`types-genericalias`.
.. class:: MutableSet(AbstractSet[T])
A generic version of :class:`collections.abc.MutableSet`.
.. deprecated:: 3.9
- :class:`collections.abc.MutableSet` now supports ``[]``. See :pep:`585`.
+ :class:`collections.abc.MutableSet` now supports ``[]``. See :pep:`585`
+ and :ref:`types-genericalias`.
.. class:: Sequence(Reversible[T_co], Collection[T_co])
A generic version of :class:`collections.abc.Sequence`.
.. deprecated:: 3.9
- :class:`collections.abc.Sequence` now supports ``[]``. See :pep:`585`.
+ :class:`collections.abc.Sequence` now supports ``[]``. See :pep:`585`
+ and :ref:`types-genericalias`.
.. class:: ValuesView(MappingView[VT_co])
A generic version of :class:`collections.abc.ValuesView`.
.. deprecated:: 3.9
- :class:`collections.abc.ValuesView` now supports ``[]``. See :pep:`585`.
+ :class:`collections.abc.ValuesView` now supports ``[]``. See :pep:`585`
+ and :ref:`types-genericalias`.
Corresponding to other types in :mod:`collections.abc`
""""""""""""""""""""""""""""""""""""""""""""""""""""""
A generic version of :class:`collections.abc.Iterable`.
.. deprecated:: 3.9
- :class:`collections.abc.Iterable` now supports ``[]``. See :pep:`585`.
+ :class:`collections.abc.Iterable` now supports ``[]``. See :pep:`585`
+ and :ref:`types-genericalias`.
.. class:: Iterator(Iterable[T_co])
A generic version of :class:`collections.abc.Iterator`.
.. deprecated:: 3.9
- :class:`collections.abc.Iterator` now supports ``[]``. See :pep:`585`.
+ :class:`collections.abc.Iterator` now supports ``[]``. See :pep:`585`
+ and :ref:`types-genericalias`.
.. class:: Generator(Iterator[T_co], Generic[T_co, T_contra, V_co])
start += 1
.. deprecated:: 3.9
- :class:`collections.abc.Generator` now supports ``[]``. See :pep:`585`.
+ :class:`collections.abc.Generator` now supports ``[]``. See :pep:`585`
+ and :ref:`types-genericalias`.
.. class:: Hashable
A generic version of :class:`collections.abc.Reversible`.
.. deprecated:: 3.9
- :class:`collections.abc.Reversible` now supports ``[]``. See :pep:`585`.
+ :class:`collections.abc.Reversible` now supports ``[]``. See :pep:`585`
+ and :ref:`types-genericalias`.
.. class:: Sized
.. versionadded:: 3.5.3
.. deprecated:: 3.9
- :class:`collections.abc.Coroutine` now supports ``[]``. See :pep:`585`.
+ :class:`collections.abc.Coroutine` now supports ``[]``. See :pep:`585`
+ and :ref:`types-genericalias`.
.. class:: AsyncGenerator(AsyncIterator[T_co], Generic[T_co, T_contra])
.. versionadded:: 3.6.1
.. deprecated:: 3.9
- :class:`collections.abc.AsyncGenerator` now supports ``[]``. See :pep:`585`.
+ :class:`collections.abc.AsyncGenerator` now supports ``[]``. See
+ :pep:`585` and :ref:`types-genericalias`.
.. class:: AsyncIterable(Generic[T_co])
.. versionadded:: 3.5.2
.. deprecated:: 3.9
- :class:`collections.abc.AsyncIterable` now supports ``[]``. See :pep:`585`.
+ :class:`collections.abc.AsyncIterable` now supports ``[]``. See :pep:`585`
+ and :ref:`types-genericalias`.
.. class:: AsyncIterator(AsyncIterable[T_co])
.. versionadded:: 3.5.2
.. deprecated:: 3.9
- :class:`collections.abc.AsyncIterator` now supports ``[]``. See :pep:`585`.
+ :class:`collections.abc.AsyncIterator` now supports ``[]``. See :pep:`585`
+ and :ref:`types-genericalias`.
.. class:: Awaitable(Generic[T_co])
.. versionadded:: 3.5.2
.. deprecated:: 3.9
- :class:`collections.abc.Awaitable` now supports ``[]``. See :pep:`585`.
+ :class:`collections.abc.Awaitable` now supports ``[]``. See :pep:`585`
+ and :ref:`types-genericalias`.
Context manager types
.. versionadded:: 3.6.0
.. deprecated:: 3.9
- :class:`collections.contextlib.AbstractContextManager` now supports ``[]``. See :pep:`585`.
+ :class:`contextlib.AbstractContextManager` now supports ``[]``. See
+ :pep:`585` and :ref:`types-genericalias`.
.. class:: AsyncContextManager(Generic[T_co])
.. versionadded:: 3.6.2
.. deprecated:: 3.9
- :class:`collections.contextlib.AbstractAsyncContextManager` now supports ``[]``. See :pep:`585`.
+ :class:`contextlib.AbstractAsyncContextManager` now supports ``[]``. See
+ :pep:`585` and :ref:`types-genericalias`.
Protocols
---------
For a typing object of the form ``X[Y, Z, ...]`` these functions return
``X`` and ``(Y, Z, ...)``. If ``X`` is a generic alias for a builtin or
:mod:`collections` class, it gets normalized to the original class.
+ If ``X`` is a :class:`Union` or :class:`Literal` contained in another
+ generic type, the order of ``(Y, Z, ...)`` may be different from the order
+ of the original arguments ``[Y, Z, ...]`` due to type caching.
For unsupported objects return ``None`` and ``()`` correspondingly.
Examples::
If ``from __future__ import annotations`` is used in Python 3.7 or later,
annotations are not evaluated at function definition time.
- Instead, the are stored as strings in ``__annotations__``,
+ Instead, they are stored as strings in ``__annotations__``,
This makes it unnecessary to use quotes around the annotation.
(see :pep:`563`).
.. decorator:: expectedFailure
- Mark the test as an expected failure. If the test fails it will be
- considered a success. If the test passes, it will be considered a failure.
+ Mark the test as an expected failure or error. If the test fails or errors
+ it will be considered a success. If the test passes, it will be considered
+ a failure.
.. exception:: SkipTest(reason)
.. method:: assertIs(first, second, msg=None)
assertIsNot(first, second, msg=None)
- Test that *first* and *second* evaluate (or don't evaluate) to the
- same object.
+ Test that *first* and *second* are (or are not) the same object.
.. versionadded:: 3.1
If given, *logger* should be a :class:`logging.Logger` object or a
:class:`str` giving the name of a logger. The default is the root
- logger, which will catch all messages.
+ logger, which will catch all messages that were not blocked by a
+ non-propagating descendent logger.
If given, *level* should be either a numeric logging level or
its string equivalent (for example either ``"ERROR"`` or
A list containing 2-tuples of :class:`TestCase` instances and strings
holding formatted tracebacks. Each tuple represents an expected failure
- of the test case.
+ or error of the test case.
.. attribute:: unexpectedSuccesses
.. method:: addExpectedFailure(test, err)
- Called when the test case *test* fails, but was marked with the
- :func:`expectedFailure` decorator.
+ Called when the test case *test* fails or errors, but was marked with
+ the :func:`expectedFailure` decorator.
The default implementation appends a tuple ``(test, formatted_err)`` to
the instance's :attr:`expectedFailures` attribute, where *formatted_err*
... # Work with dom.
-.. method:: Node.writexml(writer, indent="", addindent="", newl="",
+.. method:: Node.writexml(writer, indent="", addindent="", newl="", \
encoding=None, standalone=None)
Write XML to the writer object. The writer receives texts but not bytes as input,
The :meth:`toxml` method now preserves the attribute order specified
by the user.
-.. method:: Node.toprettyxml(indent="\\t", newl="\\n", encoding=None,
+.. method:: Node.toprettyxml(indent="\\t", newl="\\n", encoding=None, \
standalone=None)
Return a pretty-printed version of the document. *indent* specifies the
remove all countries with a rank higher than 50::
>>> for country in root.findall('country'):
+ ... # using root.findall() to avoid removal during traversal
... rank = int(country.find('rank').text)
... if rank > 50:
... root.remove(country)
...
>>> tree.write('output.xml')
+Note that concurrent modification while iterating can lead to problems,
+just like when iterating and modifying Python lists or dicts.
+Therefore, the example first collects all matching elements with
+``root.findall()``, and only then iterates over the list of matches.
+
Our XML now looks like this:
.. code-block:: xml
related to mathematical numbers, but subject to the limitations of numerical
representation in computers.
+ The string representations of the numeric classes, computed by
+ :meth:`__repr__` and :meth:`__str__`, have the following
+ properties:
+
+ * They are valid numeric literals which, when passed to their
+ class constructor, produce an object having the value of the
+ original numeric.
+
+ * The representation is in base 10, when possible.
+
+ * Leading zeros, possibly excepting a single zero before a
+ decimal point, are not shown.
+
+ * Trailing zeros, possibly excepting a single zero after a
+ decimal point, are not shown.
+
+ * A sign is shown only when the number is negative.
+
Python distinguishes between integers, floating point numbers, and complex
numbers:
context (e.g., in the condition of an ``if`` statement), Python will call
:func:`bool` on the value to determine if the result is true or false.
- By default, :meth:`__ne__` delegates to :meth:`__eq__` and
- inverts the result unless it is ``NotImplemented``. There are no other
- implied relationships among the comparison operators, for example,
- the truth of ``(x<y or x==y)`` does not imply ``x<=y``.
- To automatically generate ordering operations from a single root operation,
- see :func:`functools.total_ordering`.
+ By default, ``object`` implements :meth:`__eq__` by using ``is``, returning
+ ``NotImplemented`` in the case of a false comparison:
+ ``True if x is y else NotImplemented``. For :meth:`__ne__`, by default it
+ delegates to :meth:`__eq__` and inverts the result unless it is
+ ``NotImplemented``. There are no other implied relationships among the
+ comparison operators or default implementations; for example, the truth of
+ ``(x<y or x==y)`` does not imply ``x<=y``. To automatically generate ordering
+ operations from a single root operation, see :func:`functools.total_ordering`.
See the paragraph on :meth:`__hash__` for
some important notes on creating :term:`hashable` objects which support
result of implicit invocation via language syntax or built-in functions.
See :ref:`special-lookup`.
+ .. audit-event:: object.__getattr__ obj,name object.__getattribute__
+
+ For certain sensitive attribute accesses, raises an
+ :ref:`auditing event <auditing>` ``object.__getattr__`` with arguments
+ ``obj`` and ``name``.
+
.. method:: object.__setattr__(self, name, value)
call the base class method with the same name, for example,
``object.__setattr__(self, name, value)``.
+ .. audit-event:: object.__setattr__ obj,name,value object.__setattr__
+
+ For certain sensitive attribute assignments, raises an
+ :ref:`auditing event <auditing>` ``object.__setattr__`` with arguments
+ ``obj``, ``name``, ``value``.
+
.. method:: object.__delattr__(self, name)
Like :meth:`__setattr__` but for attribute deletion instead of assignment. This
should only be implemented if ``del obj.name`` is meaningful for the object.
+ .. audit-event:: object.__delattr__ obj,name object.__delattr__
+
+ For certain sensitive attribute deletions, raises an
+ :ref:`auditing event <auditing>` ``object.__delattr__`` with arguments
+ ``obj`` and ``name``.
+
.. method:: object.__dir__(self)
.. index:: pair: call; instance
Called when the instance is "called" as a function; if this method is defined,
- ``x(arg1, arg2, ...)`` is a shorthand for ``x.__call__(arg1, arg2, ...)``.
+ ``x(arg1, arg2, ...)`` roughly translates to ``type(x).__call__(x, arg1, ...)``.
.. _sequence-types:
.. note::
- If the right operand's type is a subclass of the left operand's type and that
- subclass provides the reflected method for the operation, this method will be
- called before the left operand's non-reflected method. This behavior allows
- subclasses to override their ancestors' operations.
+ If the right operand's type is a subclass of the left operand's type and
+ that subclass provides a different implementation of the reflected method
+ for the operation, this method will be called before the left operand's
+ non-reflected method. This behavior allows subclasses to override their
+ ancestors' operations.
.. method:: object.__iadd__(self, other)
method—that will instead have the opposite effect of explicitly
*blocking* such fallback.
-.. [#] For operands of the same type, it is assumed that if the non-reflected method
- (such as :meth:`__add__`) fails the operation is not supported, which is why the
- reflected method is not called.
+.. [#] For operands of the same type, it is assumed that if the non-reflected
+ method -- such as :meth:`__add__` -- fails then the overall operation is not
+ supported, which is why the reflected method is not called.
Displays for lists, sets and dictionaries
-----------------------------------------
+.. index:: single: comprehensions
+
For constructing a list, a set or a dictionary Python provides special syntax
called "displays", each of them in two flavors:
.. index::
pair: set; display
+ pair: set; comprehensions
object: set
single: {} (curly brackets); set expression
single: , (comma); expression list
.. index::
pair: dictionary; display
+ pair: dictionary; comprehensions
key, datum, key/datum pair
object: dictionary
single: {} (curly brackets); dictionary expression
object: dictionary
pair: sequence; item
-A subscription selects an item of a sequence (string, tuple or list) or mapping
-(dictionary) object:
+Subscription of a sequence (string, tuple or list) or mapping (dictionary)
+object usually selects an item from the collection:
.. productionlist:: python-grammar
subscription: `primary` "[" `expression_list` "]"
A string's items are characters. A character is not a separate data type but a
string of exactly one character.
+Subscription of certain :term:`classes <class>` or :term:`types <type>`
+creates a :ref:`generic alias <types-genericalias>`.
+In this case, user-defined classes can support subscription by providing a
+:meth:`__class_getitem__` classmethod.
+
.. _slicings:
Cached bytecode invalidation
----------------------------
-Before Python loads cached bytecode from ``.pyc`` file, it checks whether the
+Before Python loads cached bytecode from a ``.pyc`` file, it checks whether the
cache is up-to-date with the source ``.py`` file. By default, Python does this
by storing the source's last-modified timestamp and size in the cache file when
writing it. At runtime, the import system then validates the cache file by
This spec will always have "loader" set (with one exception).
To indicate to the import machinery that the spec represents a namespace
-:term:`portion`, the path entry finder sets "loader" on the spec to
-``None`` and "submodule_search_locations" to a list containing the
-portion.
+:term:`portion`, the path entry finder sets "submodule_search_locations" to
+a list containing the portion.
.. versionchanged:: 3.4
:meth:`~importlib.abc.PathEntryFinder.find_spec` replaced
:meth:`~importlib.abc.PathEntryFinder.find_loader` takes one argument, the
fully qualified name of the module being imported. ``find_loader()``
returns a 2-tuple where the first item is the loader and the second item
- is a namespace :term:`portion`. When the first item (i.e. the loader) is
- ``None``, this means that while the path entry finder does not have a
- loader for the named module, it knows that the path entry contributes to
- a namespace portion for the named module. This will almost always be the
- case where Python is asked to import a namespace package that has no
- physical presence on the file system. When a path entry finder returns
- ``None`` for the loader, the second item of the 2-tuple return value must
- be a sequence, although it can be empty.
-
- If ``find_loader()`` returns a non-``None`` loader value, the portion is
- ignored and the loader is returned from the path based finder, terminating
- the search through the path entries.
+ is a namespace :term:`portion`.
For backwards compatibility with other implementations of the import
protocol, many path entry finders also support the same,
* blank lines, and
* other future statements.
-The only feature in Python 3.7 that requires using the future statement is
-``annotations``.
+The only feature that requires using the future statement is
+``annotations`` (see :pep:`563`).
All historical features enabled by the future statement are still recognized
by Python 3. The list includes ``absolute_import``, ``division``,
classes=['stableabi']))
if par['objtype'] != 'function':
continue
- if not par[0].has_key('names') or not par[0]['names']:
+ if not par[0].has_key('ids') or not par[0]['ids']:
continue
- name = par[0]['names'][0]
+ name = par[0]['ids'][0]
if name.startswith("c."):
name = name[2:]
entry = self.get(name)
from sphinx.util.nodes import split_explicit_title
from sphinx.writers.text import TextWriter, TextTranslator
from sphinx.writers.latex import LaTeXTranslator
-from sphinx.domains.python import PyModulelevel, PyClassmember
+
+try:
+ from sphinx.domains.python import PyFunction, PyMethod
+except ImportError:
+ from sphinx.domains.python import PyClassmember as PyMethod
+ from sphinx.domains.python import PyModulelevel as PyFunction
# Support for checking for suspicious markup
return False
-class PyDecoratorFunction(PyDecoratorMixin, PyModulelevel):
+class PyDecoratorFunction(PyDecoratorMixin, PyFunction):
def run(self):
# a decorator function is a function after all
self.name = 'py:function'
- return PyModulelevel.run(self)
+ return PyFunction.run(self)
-class PyDecoratorMethod(PyDecoratorMixin, PyClassmember):
+# TODO: Use sphinx.domains.python.PyDecoratorMethod when possible
+class PyDecoratorMethod(PyDecoratorMixin, PyMethod):
def run(self):
self.name = 'py:method'
- return PyClassmember.run(self)
+ return PyMethod.run(self)
class PyCoroutineMixin(object):
return ret
-class PyCoroutineFunction(PyCoroutineMixin, PyModulelevel):
+class PyCoroutineFunction(PyCoroutineMixin, PyFunction):
def run(self):
self.name = 'py:function'
- return PyModulelevel.run(self)
+ return PyFunction.run(self)
-class PyCoroutineMethod(PyCoroutineMixin, PyClassmember):
+class PyCoroutineMethod(PyCoroutineMixin, PyMethod):
def run(self):
self.name = 'py:method'
- return PyClassmember.run(self)
+ return PyMethod.run(self)
-class PyAwaitableFunction(PyAwaitableMixin, PyClassmember):
+class PyAwaitableFunction(PyAwaitableMixin, PyFunction):
def run(self):
self.name = 'py:function'
- return PyClassmember.run(self)
+ return PyFunction.run(self)
-class PyAwaitableMethod(PyAwaitableMixin, PyClassmember):
+class PyAwaitableMethod(PyAwaitableMixin, PyMethod):
def run(self):
self.name = 'py:method'
- return PyClassmember.run(self)
+ return PyMethod.run(self)
-class PyAbstractMethod(PyClassmember):
+class PyAbstractMethod(PyMethod):
def handle_signature(self, sig, signode):
ret = super(PyAbstractMethod, self).handle_signature(sig, signode)
def run(self):
self.name = 'py:method'
- return PyClassmember.run(self)
+ return PyMethod.run(self)
# Support for documenting version of removal in deprecations
'3.8': '3.8',
'3.7': '3.7',
'3.6': '3.6',
- '3.5': '3.5',
'2.7': '2.7',
};
c-api/tuple,,:high,p[low:high]
c-api/unicode,,:end,str[start:end]
c-api/unicode,,:start,unicode[start:start+length]
-distutils/examples,267,`,This is the description of the ``foobar`` package.
+distutils/examples,,`,This is the description of the ``foobar`` package.
distutils/setupscript,,::,
extending/embedding,,:numargs,"if(!PyArg_ParseTuple(args, "":numargs""))"
extending/extending,,:myfunction,"PyArg_ParseTuple(args, ""D:myfunction"", &c);"
extending/extending,,:set,"if (PyArg_ParseTuple(args, ""O:set_callback"", &temp)) {"
extending/newtypes,,:call,"if (!PyArg_ParseTuple(args, ""sss:call"", &arg1, &arg2, &arg3)) {"
faq/programming,,:chr,">=4.0) or 1+f(xc,yc,x*x-y*y+xc,2.0*x*y+yc,k-1,f):f(xc,yc,x,y,k,f):chr("
-faq/programming,,::,for x in sequence[::-1]:
faq/programming,,:reduce,"print((lambda Ru,Ro,Iu,Io,IM,Sx,Sy:reduce(lambda x,y:x+y,map(lambda y,"
faq/programming,,:reduce,"Sx=Sx,Sy=Sy:reduce(lambda x,y:x+y,map(lambda x,xc=Ru,yc=yc,Ru=Ru,Ro=Ro,"
faq/windows,,:d48eceb,"Python 3.6.4 (v3.6.4:d48eceb, Dec 19 2017, 06:04:45) [MSC v.1900 32 bit (Intel)] on win32"
howto/curses,,:magenta,"2:green, 3:yellow, 4:blue, 5:magenta, 6:cyan, and 7:white. The"
howto/curses,,:cyan,"2:green, 3:yellow, 4:blue, 5:magenta, 6:cyan, and 7:white. The"
howto/curses,,:white,"2:green, 3:yellow, 4:blue, 5:magenta, 6:cyan, and 7:white. The"
+howto/descriptor,,:root,"INFO:root"
+howto/descriptor,,:Updating,"root:Updating"
+howto/descriptor,,:Accessing,"root:Accessing"
howto/instrumentation,,::,python$target:::function-entry
howto/instrumentation,,:function,python$target:::function-entry
howto/instrumentation,,::,python$target:::function-return
library/ipaddress,,::,IPv6Address('2001:db8::')
library/ipaddress,,:db8,>>> ipaddress.IPv6Address('2001:db8::1000')
library/ipaddress,,::,>>> ipaddress.IPv6Address('2001:db8::1000')
-library/ipaddress,,:db8,IPv6Address('2001:db8::1000')
-library/ipaddress,,::,IPv6Address('2001:db8::1000')
+library/ipaddress,,:db8,'2001:db8::1000'
+library/ipaddress,,::,'2001:db8::1000'
+library/ipaddress,231,:db8,">>> f'{ipaddress.IPv6Address(""2001:db8::1000""):s}'"
+library/ipaddress,231,::,">>> f'{ipaddress.IPv6Address(""2001:db8::1000""):s}'"
library/ipaddress,,::,IPv6Address('ff02::5678%1')
library/ipaddress,,::,fe80::1234
library/ipaddress,,:db8,">>> ipaddress.ip_address(""2001:db8::1"").reverse_pointer"
<li><a href="https://docs.python.org/3.8/">{% trans %}Python 3.8 (stable){% endtrans %}</a></li>
<li><a href="https://docs.python.org/3.7/">{% trans %}Python 3.7 (stable){% endtrans %}</a></li>
<li><a href="https://docs.python.org/3.6/">{% trans %}Python 3.6 (security-fixes){% endtrans %}</a></li>
- <li><a href="https://docs.python.org/3.5/">{% trans %}Python 3.5 (security-fixes){% endtrans %}</a></li>
<li><a href="https://docs.python.org/2.7/">{% trans %}Python 2.7 (EOL){% endtrans %}</a></li>
<li><a href="https://www.python.org/doc/versions/">{% trans %}All versions{% endtrans %}</a></li>
</ul>
Return the number of times *x* appears in the list.
-.. method:: list.sort(key=None, reverse=False)
+.. method:: list.sort(*, key=None, reverse=False)
:noindex:
Sort the items of the list in place (the arguments can be used for sort
==================
The :keyword:`raise` statement allows an optional :keyword:`from` which enables
-chaining exceptions by setting the ``__cause__`` attribute of the raised
-exception. For example::
+chaining exceptions. For example::
- raise RuntimeError from OSError
+ # exc must be exception instance or None.
+ raise RuntimeError from exc
This can be useful when you are transforming exceptions. For example::
>>> def func():
- ... raise IOError
+ ... raise IOError
...
>>> try:
... func()
<BLANKLINE>
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
- RuntimeError
+ RuntimeError: Failed to open database
-The expression following the :keyword:`from` must be either an exception or
-``None``. Exception chaining happens automatically when an exception is raised
-inside an exception handler or :keyword:`finally` section. Exception chaining
-can be disabled by using ``from None`` idiom:
+Exception chaining happens automatically when an exception is raised inside an
+:keyword:`except` or :keyword:`finally` section. Exception chaining can be
+disabled by using ``from None`` idiom:
>>> try:
... open('database.sqlite')
File "<stdin>", line 4, in <module>
RuntimeError
+For more information about chaining mechanics, see :ref:`bltin-exceptions`.
+
.. _tut-userexceptions:
If you're not using the :keyword:`with` keyword, then you should call
``f.close()`` to close the file and immediately free up any system
-resources used by it. If you don't explicitly close a file, Python's
-garbage collector will eventually destroy the object and close the
-open file for you, but the file may stay open for a while. Another
-risk is that different Python implementations will do this clean-up at
-different times.
+resources used by it.
+
+.. warning::
+ Calling ``f.write()`` without using the :keyword:`!with` keyword or calling
+ ``f.close()`` **might** result in the arguments
+ of ``f.write()`` not being completely written to the disk, even if the
+ program exits successfully.
+
+..
+ See also https://bugs.python.org/issue17852
After a file object is closed, either by a :keyword:`with` statement
or by calling ``f.close()``, attempts to use the file object will
the interactive session. You can also change the prompts :data:`sys.ps1` and
:data:`sys.ps2` and the hook :data:`sys.__interactivehook__` in this file.
- .. audit-event:: cpython.run_startup filename PYTHONSTARTUP
+ .. audit-event:: cpython.run_startup filename envvar-PYTHONSTARTUP
Raises an :ref:`auditing event <auditing>` ``cpython.run_startup`` with
the filename as the argument when called on startup.
Once an environment has been created, you may wish to activate it, e.g. by
sourcing an activate script in its bin directory.
-.. versionchanged:: 3.8
+.. versionchanged:: 3.9
Add ``--upgrade-deps`` option to upgrade pip + setuptools to the latest on PyPI
.. versionchanged:: 3.4
As specified in :pep:`11`, a Python release only supports a Windows platform
while Microsoft considers the platform under extended support. This means that
-Python |version| supports Windows Vista and newer. If you require Windows XP
-support then please install Python 3.4.
+Python |version| supports Windows 8.1 and newer. If you require Windows 7
+support, please install Python 3.8.
There are a number of different installers available for Windows, each with
certain benefits and downsides.
In the latest versions of Windows, this limitation can be expanded to
approximately 32,000 characters. Your administrator will need to activate the
-"Enable Win32 long paths" group policy, or set the registry value
-``HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem@LongPathsEnabled``
-to ``1``.
+"Enable Win32 long paths" group policy, or set ``LongPathsEnabled`` to ``1``
+in the registry key
+``HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem``.
This allows the :func:`open` function, the :mod:`os` module and most other
path functionality to accept and return paths longer than 260 characters.
(Many people worked on this for eight years but the problem was finally
solved by Serhiy Storchaka in :issue:`13153`.)
+New in 3.8.1:
+
+Add option to toggle cursor blink off. (Contributed by Zackery Spytz
+in :issue:`4603`.)
+
+Escape key now closes IDLE completion windows. (Contributed by Johnny
+Najera in :issue:`38944`.)
+
The changes above have been backported to 3.7 maintenance releases.
+Add keywords to module name completion list. (Contributed by Terry J.
+Reedy in :issue:`37765`.)
inspect
-------
(Contributed by Antoine Pitrou in :issue:`32388`.)
-* The :c:func:`PyCode_New` has a new parameter in the second position (*posonlyargcount*)
- to support :pep:`570`, indicating the number of positional-only arguments.
-
* The functions :c:func:`PyNode_AddChild` and :c:func:`PyParser_AddToken` now accept
two additional ``int`` arguments *end_lineno* and *end_col_offset*.
<devmode>` which helps to prepare your code to make it compatible with the
next Python version.
-Note: a number of pre-existing deprecatations were removed in this version
-of Python as well. Consult the :ref:`removed-in-python-39` section.
+Note: a number of pre-existing deprecations were removed in this version of
+Python as well. Consult the :ref:`removed-in-python-39` section.
New Features
-------------- --- --- --- --- --- ---
Variable and attribute read access:
- read_local 7.1 7.1 5.4 5.1 3.9 4.0
- read_nonlocal 7.1 8.1 5.8 5.4 4.4 4.8
- read_global 15.5 19.0 14.3 13.6 7.6 7.7
- read_builtin 21.1 21.6 18.5 19.0 7.5 7.7
- read_classvar_from_class 25.6 26.5 20.7 19.5 18.4 18.6
- read_classvar_from_instance 22.8 23.5 18.8 17.1 16.4 20.1
- read_instancevar 32.4 33.1 28.0 26.3 25.4 27.7
- read_instancevar_slots 27.8 31.3 20.8 20.8 20.2 24.5
- read_namedtuple 73.8 57.5 45.0 46.8 18.4 23.2
- read_boundmethod 37.6 37.9 29.6 26.9 27.7 45.9
+ read_local 7.1 7.1 5.4 5.1 3.9 3.9
+ read_nonlocal 7.1 8.1 5.8 5.4 4.4 4.5
+ read_global 15.5 19.0 14.3 13.6 7.6 7.8
+ read_builtin 21.1 21.6 18.5 19.0 7.5 7.8
+ read_classvar_from_class 25.6 26.5 20.7 19.5 18.4 17.9
+ read_classvar_from_instance 22.8 23.5 18.8 17.1 16.4 16.9
+ read_instancevar 32.4 33.1 28.0 26.3 25.4 25.3
+ read_instancevar_slots 27.8 31.3 20.8 20.8 20.2 20.5
+ read_namedtuple 73.8 57.5 45.0 46.8 18.4 18.7
+ read_boundmethod 37.6 37.9 29.6 26.9 27.7 41.1
Variable and attribute write access:
- write_local 8.7 9.3 5.5 5.3 4.3 4.2
- write_nonlocal 10.5 11.1 5.6 5.5 4.7 4.9
- write_global 19.7 21.2 18.0 18.0 15.8 17.2
- write_classvar 92.9 96.0 104.6 102.1 39.2 43.2
- write_instancevar 44.6 45.8 40.0 38.9 35.5 40.7
- write_instancevar_slots 35.6 36.1 27.3 26.6 25.7 27.7
+ write_local 8.7 9.3 5.5 5.3 4.3 4.3
+ write_nonlocal 10.5 11.1 5.6 5.5 4.7 4.8
+ write_global 19.7 21.2 18.0 18.0 15.8 16.7
+ write_classvar 92.9 96.0 104.6 102.1 39.2 39.8
+ write_instancevar 44.6 45.8 40.0 38.9 35.5 37.4
+ write_instancevar_slots 35.6 36.1 27.3 26.6 25.7 25.8
Data structure read access:
- read_list 24.2 24.5 20.8 20.8 19.0 21.1
- read_deque 24.7 25.5 20.2 20.6 19.8 21.6
- read_dict 24.3 25.7 22.3 23.0 21.0 22.5
- read_strdict 22.6 24.3 19.5 21.2 18.9 21.6
+ read_list 24.2 24.5 20.8 20.8 19.0 19.5
+ read_deque 24.7 25.5 20.2 20.6 19.8 20.2
+ read_dict 24.3 25.7 22.3 23.0 21.0 22.4
+ read_strdict 22.6 24.3 19.5 21.2 18.9 21.5
Data structure write access:
- write_list 27.1 28.5 22.5 21.6 20.0 21.6
- write_deque 28.7 30.1 22.7 21.8 23.5 23.2
- write_dict 31.4 33.3 29.3 29.2 24.7 27.8
- write_strdict 28.4 29.9 27.5 25.2 23.1 29.8
+ write_list 27.1 28.5 22.5 21.6 20.0 20.0
+ write_deque 28.7 30.1 22.7 21.8 23.5 21.7
+ write_dict 31.4 33.3 29.3 29.2 24.7 25.4
+ write_strdict 28.4 29.9 27.5 25.2 23.1 24.5
Stack (or queue) operations:
- list_append_pop 93.4 112.7 75.4 74.2 50.8 53.9
- deque_append_pop 43.5 57.0 49.4 49.2 42.5 45.5
- deque_append_popleft 43.7 57.3 49.7 49.7 42.8 45.5
+ list_append_pop 93.4 112.7 75.4 74.2 50.8 50.6
+ deque_append_pop 43.5 57.0 49.4 49.2 42.5 44.2
+ deque_append_popleft 43.7 57.3 49.7 49.7 42.8 46.4
Timing loop:
loop_overhead 0.5 0.6 0.4 0.3 0.3 0.3
and will be removed in future Python versions. ``value`` itself should be
used instead of ``Index(value)``. ``Tuple(slices, Load())`` should be
used instead of ``ExtSlice(slices)``.
- (Contributed by Serhiy Storchaka in :issue:`32892`.)
+ (Contributed by Serhiy Storchaka in :issue:`34822`.)
* :mod:`ast` classes ``Suite``, ``Param``, ``AugLoad`` and ``AugStore``
are considered deprecated and will be removed in future Python versions.
* ``COMPARE_OP`` for rich comparisons
* ``IS_OP`` for 'is' and 'is not' tests
- * ``CONTAINS_OP`` for 'in' and 'is not' tests
+ * ``CONTAINS_OP`` for 'in' and 'not in' tests
* ``JUMP_IF_NOT_EXC_MATCH`` for checking exceptions in 'try-except'
statements.
representation of a function-like object.
(Patch by Jeroen Demeyer in :issue:`37645`.)
+* Added :c:func:`PyObject_CallOneArg` for calling an object with one
+ positional argument
+ (Patch by Jeroen Demeyer in :issue:`37483`.)
+
Porting to Python 3.9
---------------------
``PyNullImporter_Type``, ``PyCmpWrapper_Type``, ``PySortWrapper_Type``,
``PyNoArgsFunction``.
(Contributed by Pablo Galindo Salgado in :issue:`39372`.)
+
+Notable changes in Python 3.9.1
+===============================
+
+typing
+------
+
+The behavior of :class:`typing.Literal` was changed to conform with :pep:`586`
+and to match the behavior of static type checkers specified in the PEP.
+
+1. ``Literal`` now de-duplicates parameters.
+2. Equality comparisons between ``Literal`` objects are now order independent.
+3. ``Literal`` comparisons now respect types. For example,
+ ``Literal[0] == Literal[False]`` previously evaluated to ``True``. It is
+ now ``False``. To support this change, the internally used type cache now
+ supports differentiating types.
+4. ``Literal`` objects will now raise a :exc:`TypeError` exception during
+ equality comparisons if one of their parameters are not :term:`immutable`.
+ Note that declaring ``Literal`` with mutable parameters will not throw
+ an error::
+
+ >>> from typing import Literal
+ >>> Literal[{0}]
+ >>> Literal[{0}] == Literal[{False}]
+ Traceback (most recent call last):
+ File "<stdin>", line 1, in <module>
+ TypeError: unhashable type: 'set'
+
+(Contributed by Yurii Karabas in :issue:`42345`.)
+
+macOS 11.0 (Big Sur) and Apple Silicon Mac support
+--------------------------------------------------
+
+As of 3.9.1, Python now fully supports building and running on macOS 11.0
+(Big Sur) and on Apple Silicon Macs (based on the ``ARM64`` architecture).
+A new universal build variant, ``universal2``, is now available to natively
+support both ``ARM64`` and ``Intel 64`` in one set of executables. Binaries
+can also now be built on current versions of macOS to be deployed on a range
+of older macOS versions (tested to 10.9) while making some newer OS
+functions and options conditionally available based on the operating system
+version in use at runtime ("weaklinking").
+
+(Contributed by Ronald Oussoren and Lawrence D'Anna in :issue:`41100`.)
| ASYNC 'with' a=','.with_item+ ':' tc=[TYPE_COMMENT] b=block {
CHECK_VERSION(5, "Async with statements are", _Py_AsyncWith(a, b, NEW_TYPE_COMMENT(p, tc), EXTRA)) }
with_item[withitem_ty]:
- | e=expression 'as' t=target &(',' | ')' | ':') { _Py_withitem(e, t, p->arena) }
+ | e=expression 'as' t=star_target &(',' | ')' | ':') { _Py_withitem(e, t, p->arena) }
| invalid_with_item
| e=expression { _Py_withitem(e, NULL, p->arena) }
| simple_stmt
| invalid_block
-expressions_list[asdl_seq*]: a=','.star_expression+ [','] { a }
star_expressions[expr_ty]:
| a=star_expression b=(',' c=star_expression { c })+ [','] {
_Py_Tuple(CHECK(_PyPegen_seq_insert_in_front(p, a, b)), Load, EXTRA) }
| is_bitwise_or
eq_bitwise_or[CmpopExprPair*]: '==' a=bitwise_or { _PyPegen_cmpop_expr_pair(p, Eq, a) }
noteq_bitwise_or[CmpopExprPair*]:
- | (tok='!=' {_PyPegen_check_barry_as_flufl(p) ? NULL : tok}) a=bitwise_or {_PyPegen_cmpop_expr_pair(p, NotEq, a) }
+ | (tok='!=' { _PyPegen_check_barry_as_flufl(p, tok) ? NULL : tok}) a=bitwise_or {_PyPegen_cmpop_expr_pair(p, NotEq, a) }
lte_bitwise_or[CmpopExprPair*]: '<=' a=bitwise_or { _PyPegen_cmpop_expr_pair(p, LtE, a) }
lt_bitwise_or[CmpopExprPair*]: '<' a=bitwise_or { _PyPegen_cmpop_expr_pair(p, Lt, a) }
gte_bitwise_or[CmpopExprPair*]: '>=' a=bitwise_or { _PyPegen_cmpop_expr_pair(p, GtE, a) }
| AWAIT a=primary { CHECK_VERSION(5, "Await expressions are", _Py_Await(a, EXTRA)) }
| primary
primary[expr_ty]:
+ | invalid_primary # must be before 'primay genexp' because of invalid_genexp
| a=primary '.' b=NAME { _Py_Attribute(a, b->v.Name.id, Load, EXTRA) }
| a=primary b=genexp { _Py_Call(a, CHECK(_PyPegen_singleton_seq(p, b)), NULL, EXTRA) }
| a=primary '(' b=[arguments] ')' {
| '(' a=(yield_expr | named_expression) ')' { a }
| invalid_group
genexp[expr_ty]:
- | '(' a=expression ~ b=for_if_clauses ')' { _Py_GeneratorExp(a, b, EXTRA) }
+ | '(' a=named_expression ~ b=for_if_clauses ')' { _Py_GeneratorExp(a, b, EXTRA) }
| invalid_comprehension
-set[expr_ty]: '{' a=expressions_list '}' { _Py_Set(a, EXTRA) }
+set[expr_ty]: '{' a=star_named_expressions '}' { _Py_Set(a, EXTRA) }
setcomp[expr_ty]:
- | '{' a=expression ~ b=for_if_clauses '}' { _Py_SetComp(a, b, EXTRA) }
+ | '{' a=named_expression ~ b=for_if_clauses '}' { _Py_SetComp(a, b, EXTRA) }
| invalid_comprehension
dict[expr_ty]:
| '{' a=[double_starred_kvpairs] '}' {
arguments[expr_ty] (memo):
| a=args [','] &')' { a }
- | incorrect_arguments
+ | invalid_arguments
args[expr_ty]:
| a=','.(starred_expression | named_expression !'=')+ b=[',' k=kwargs {k}] { _PyPegen_collect_call_seqs(p, a, b, EXTRA) }
| a=kwargs { _Py_Call(_PyPegen_dummy_name(p),
# From here on, there are rules for invalid syntax with specialised error messages
-incorrect_arguments:
+invalid_arguments:
| args ',' '*' { RAISE_SYNTAX_ERROR("iterable argument unpacking follows keyword argument unpacking") }
| a=expression for_if_clauses ',' [args | expression for_if_clauses] {
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "Generator expression must be parenthesized") }
RAISE_SYNTAX_ERROR_INVALID_TARGET(DEL_TARGETS, a) }
invalid_block:
| NEWLINE !INDENT { RAISE_INDENTATION_ERROR("expected an indented block") }
+invalid_primary:
+ | primary a='{' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "invalid syntax") }
invalid_comprehension:
| ('[' | '(' | '{') a=starred_expression for_if_clauses {
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "iterable unpacking cannot be used in comprehension") }
PyAPI_FUNC(char *) Py_UniversalNewlineFgets(char *, int, FILE*, PyObject *);
-#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03060000
-PyAPI_DATA(const char *) Py_FileSystemDefaultEncodeErrors;
-#endif
-
-#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03070000
-PyAPI_DATA(int) Py_UTF8Mode;
-#endif
-
/* The std printer acts as a preliminary sys.stderr until the new io
infrastructure is in place. */
PyAPI_FUNC(PyObject *) PyFile_NewStdPrinter(int);
If non-NULL, this is different than the default encoding for strings
*/
PyAPI_DATA(const char *) Py_FileSystemDefaultEncoding;
+#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03060000
+PyAPI_DATA(const char *) Py_FileSystemDefaultEncodeErrors;
+#endif
PyAPI_DATA(int) Py_HasFileSystemDefaultEncoding;
+#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03070000
+PyAPI_DATA(int) Py_UTF8Mode;
+#endif
+
/* A routine to check if a file descriptor can be select()-ed. */
#ifdef _MSC_VER
/* On Windows, any socket fd can be select()-ed, no matter how high */
# error "this header requires Py_BUILD_CORE define"
#endif
-#if ((defined(__GNUC__) \
- && ((__GNUC__ >= 5) || (__GNUC__ == 4) && (__GNUC_MINOR__ >= 8))) \
- || (defined(__clang__) \
- && (__clang_major__ >= 4 \
- || (__clang_major__ == 3 && __clang_minor__ >= 2))))
- /* __builtin_bswap16() is available since GCC 4.8 and clang 3.2,
+#if defined(__GNUC__) \
+ && ((__GNUC__ >= 5) || (__GNUC__ == 4) && (__GNUC_MINOR__ >= 8))
+ /* __builtin_bswap16() is available since GCC 4.8,
__builtin_bswap32() is available since GCC 4.3,
__builtin_bswap64() is available since GCC 4.3. */
# define _PY_HAVE_BUILTIN_BSWAP
static inline uint16_t
_Py_bswap16(uint16_t word)
{
-#ifdef _PY_HAVE_BUILTIN_BSWAP
+#if defined(_PY_HAVE_BUILTIN_BSWAP) || _Py__has_builtin(__builtin_bswap16)
return __builtin_bswap16(word);
#elif defined(_MSC_VER)
Py_BUILD_ASSERT(sizeof(word) == sizeof(unsigned short));
static inline uint32_t
_Py_bswap32(uint32_t word)
{
-#ifdef _PY_HAVE_BUILTIN_BSWAP
+#if defined(_PY_HAVE_BUILTIN_BSWAP) || _Py__has_builtin(__builtin_bswap32)
return __builtin_bswap32(word);
#elif defined(_MSC_VER)
Py_BUILD_ASSERT(sizeof(word) == sizeof(unsigned long));
static inline uint64_t
_Py_bswap64(uint64_t word)
{
-#ifdef _PY_HAVE_BUILTIN_BSWAP
+#if defined(_PY_HAVE_BUILTIN_BSWAP) || _Py__has_builtin(__builtin_bswap64)
return __builtin_bswap64(word);
#elif defined(_MSC_VER)
return _byteswap_uint64(word);
extern void _PySlice_Fini(void);
extern void _PyAsyncGen_Fini(void);
+extern int _PySignal_Init(int install_signal_handlers);
extern void PyOS_FiniInterrupts(void);
extern void _PyExc_Fini(void);
/*--start constants--*/
#define PY_MAJOR_VERSION 3
#define PY_MINOR_VERSION 9
-#define PY_MICRO_VERSION 0
+#define PY_MICRO_VERSION 1
#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_FINAL
#define PY_RELEASE_SERIAL 0
/* Version as a string */
-#define PY_VERSION "3.9.0"
+#define PY_VERSION "3.9.1"
/*--end constants--*/
/* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2.
# define _Py_NO_RETURN
#endif
+
+// Preprocessor check for a builtin preprocessor function. Always return 0
+// if __has_builtin() macro is not defined.
+//
+// __has_builtin() is available on clang and GCC 10.
+#ifdef __has_builtin
+# define _Py__has_builtin(x) __has_builtin(x)
+#else
+# define _Py__has_builtin(x) 0
+#endif
+
+
#endif /* Py_PYPORT_H */
return executable
-def _read_output(commandstring):
+def _read_output(commandstring, capture_stderr=False):
"""Output from successful command execution or None"""
# Similar to os.popen(commandstring, "r").read(),
# but without actually using os.popen because that
os.getpid(),), "w+b")
with contextlib.closing(fp) as fp:
- cmd = "%s 2>/dev/null >'%s'" % (commandstring, fp.name)
+ if capture_stderr:
+ cmd = "%s >'%s' 2>&1" % (commandstring, fp.name)
+ else:
+ cmd = "%s 2>/dev/null >'%s'" % (commandstring, fp.name)
return fp.read().decode('utf-8').strip() if not os.system(cmd) else None
return _SYSTEM_VERSION
+_SYSTEM_VERSION_TUPLE = None
+def _get_system_version_tuple():
+ """
+ Return the macOS system version as a tuple
+
+ The return value is safe to use to compare
+ two version numbers.
+ """
+ global _SYSTEM_VERSION_TUPLE
+ if _SYSTEM_VERSION_TUPLE is None:
+ osx_version = _get_system_version()
+ if osx_version:
+ try:
+ _SYSTEM_VERSION_TUPLE = tuple(int(i) for i in osx_version.split('.'))
+ except ValueError:
+ _SYSTEM_VERSION_TUPLE = ()
+
+ return _SYSTEM_VERSION_TUPLE
+
+
def _remove_original_values(_config_vars):
"""Remove original unmodified values for testing"""
# This is needed for higher-level cross-platform tests of get_platform.
_config_vars[_INITPRE + cv] = oldvalue
_config_vars[cv] = newvalue
+
+_cache_default_sysroot = None
+def _default_sysroot(cc):
+ """ Returns the root of the default SDK for this system, or '/' """
+ global _cache_default_sysroot
+
+ if _cache_default_sysroot is not None:
+ return _cache_default_sysroot
+
+ contents = _read_output('%s -c -E -v - </dev/null' % (cc,), True)
+ in_incdirs = False
+ for line in contents.splitlines():
+ if line.startswith("#include <...>"):
+ in_incdirs = True
+ elif line.startswith("End of search list"):
+ in_incdirs = False
+ elif in_incdirs:
+ line = line.strip()
+ if line == '/usr/include':
+ _cache_default_sysroot = '/'
+ elif line.endswith(".sdk/usr/include"):
+ _cache_default_sysroot = line[:-12]
+ if _cache_default_sysroot is None:
+ _cache_default_sysroot = '/'
+
+ return _cache_default_sysroot
+
def _supports_universal_builds():
"""Returns True if universal builds are supported on this system"""
# As an approximation, we assume that if we are running on 10.4 or above,
# builds, in particular -isysroot and -arch arguments to the compiler. This
# is in support of allowing 10.4 universal builds to run on 10.3.x systems.
- osx_version = _get_system_version()
- if osx_version:
- try:
- osx_version = tuple(int(i) for i in osx_version.split('.'))
- except ValueError:
- osx_version = ''
+ osx_version = _get_system_version_tuple()
return bool(osx_version >= (10, 4)) if osx_version else False
+def _supports_arm64_builds():
+ """Returns True if arm64 builds are supported on this system"""
+ # There are two sets of systems supporting macOS/arm64 builds:
+ # 1. macOS 11 and later, unconditionally
+ # 2. macOS 10.15 with Xcode 12.2 or later
+ # For now the second category is ignored.
+ osx_version = _get_system_version_tuple()
+ return osx_version >= (11, 0) if osx_version else False
+
def _find_appropriate_compiler(_config_vars):
"""Find appropriate C compiler for extension module builds"""
except ValueError:
break
+ elif not _supports_arm64_builds():
+ # Look for "-arch arm64" and drop that
+ for idx in reversed(range(len(compiler_so))):
+ if compiler_so[idx] == '-arch' and compiler_so[idx+1] == "arm64":
+ del compiler_so[idx:idx+2]
+
if 'ARCHFLAGS' in os.environ and not stripArch:
# User specified different -arch flags in the environ,
# see also distutils.sysconfig
if len(archs) == 1:
machine = archs[0]
+ elif archs == ('arm64', 'x86_64'):
+ machine = 'universal2'
elif archs == ('i386', 'ppc'):
machine = 'fat'
elif archs == ('i386', 'x86_64'):
except ValueError:
return self
+
+_SINGLE_QUOTES = ("'", '"')
+_MULTI_QUOTES = ('"""', "'''")
+_ALL_QUOTES = (*_SINGLE_QUOTES, *_MULTI_QUOTES)
+
class _Unparser(NodeVisitor):
"""Methods in this class recursively traverse an AST and
output source code for the abstract syntax; original formatting
is disregarded."""
- def __init__(self):
+ def __init__(self, *, _avoid_backslashes=False):
self._source = []
self._buffer = []
self._precedences = {}
self._type_ignores = {}
self._indent = 0
+ self._avoid_backslashes = _avoid_backslashes
def interleave(self, inter, f, seq):
"""Call f on each item in seq, calling inter() in between."""
with self.block(extra=self.get_type_comment(node)):
self.traverse(node.body)
+ def _str_literal_helper(
+ self, string, *, quote_types=_ALL_QUOTES, escape_special_whitespace=False
+ ):
+ """Helper for writing string literals, minimizing escapes.
+ Returns the tuple (string literal to write, possible quote types).
+ """
+ def escape_char(c):
+ # \n and \t are non-printable, but we only escape them if
+ # escape_special_whitespace is True
+ if not escape_special_whitespace and c in "\n\t":
+ return c
+ # Always escape backslashes and other non-printable characters
+ if c == "\\" or not c.isprintable():
+ return c.encode("unicode_escape").decode("ascii")
+ return c
+
+ escaped_string = "".join(map(escape_char, string))
+ possible_quotes = quote_types
+ if "\n" in escaped_string:
+ possible_quotes = [q for q in possible_quotes if q in _MULTI_QUOTES]
+ possible_quotes = [q for q in possible_quotes if q not in escaped_string]
+ if not possible_quotes:
+ # If there aren't any possible_quotes, fallback to using repr
+ # on the original string. Try to use a quote from quote_types,
+ # e.g., so that we use triple quotes for docstrings.
+ string = repr(string)
+ quote = next((q for q in quote_types if string[0] in q), string[0])
+ return string[1:-1], [quote]
+ if escaped_string:
+ # Sort so that we prefer '''"''' over """\""""
+ possible_quotes.sort(key=lambda q: q[0] == escaped_string[-1])
+ # If we're using triple quotes and we'd need to escape a final
+ # quote, escape it
+ if possible_quotes[0][0] == escaped_string[-1]:
+ assert len(possible_quotes[0]) == 3
+ escaped_string = escaped_string[:-1] + "\\" + escaped_string[-1]
+ return escaped_string, possible_quotes
+
+ def _write_str_avoiding_backslashes(self, string, *, quote_types=_ALL_QUOTES):
+ """Write string literal value with a best effort attempt to avoid backslashes."""
+ string, quote_types = self._str_literal_helper(string, quote_types=quote_types)
+ quote_type = quote_types[0]
+ self.write(f"{quote_type}{string}{quote_type}")
+
def visit_JoinedStr(self, node):
self.write("f")
- self._fstring_JoinedStr(node, self.buffer_writer)
- self.write(repr(self.buffer))
+ if self._avoid_backslashes:
+ self._fstring_JoinedStr(node, self.buffer_writer)
+ self._write_str_avoiding_backslashes(self.buffer)
+ return
+
+ # If we don't need to avoid backslashes globally (i.e., we only need
+ # to avoid them inside FormattedValues), it's cosmetically preferred
+ # to use escaped whitespace. That is, it's preferred to use backslashes
+ # for cases like: f"{x}\n". To accomplish this, we keep track of what
+ # in our buffer corresponds to FormattedValues and what corresponds to
+ # Constant parts of the f-string, and allow escapes accordingly.
+ buffer = []
+ for value in node.values:
+ meth = getattr(self, "_fstring_" + type(value).__name__)
+ meth(value, self.buffer_writer)
+ buffer.append((self.buffer, isinstance(value, Constant)))
+ new_buffer = []
+ quote_types = _ALL_QUOTES
+ for value, is_constant in buffer:
+ # Repeatedly narrow down the list of possible quote_types
+ value, quote_types = self._str_literal_helper(
+ value, quote_types=quote_types,
+ escape_special_whitespace=is_constant
+ )
+ new_buffer.append(value)
+ value = "".join(new_buffer)
+ quote_type = quote_types[0]
+ self.write(f"{quote_type}{value}{quote_type}")
def visit_FormattedValue(self, node):
self.write("f")
self._fstring_FormattedValue(node, self.buffer_writer)
- self.write(repr(self.buffer))
+ self._write_str_avoiding_backslashes(self.buffer)
def _fstring_JoinedStr(self, node, write):
for value in node.values:
def _fstring_FormattedValue(self, node, write):
write("{")
- unparser = type(self)()
+ unparser = type(self)(_avoid_backslashes=True)
unparser.set_precedence(_Precedence.TEST.next(), node.value)
expr = unparser.visit(node.value)
if expr.startswith("{"):
write(" ") # Separate pair of opening brackets as "{ {"
+ if "\\" in expr:
+ raise ValueError("Unable to avoid backslash in f-string expression part")
write(expr)
if node.conversion != -1:
conversion = chr(node.conversion)
self.write(node.id)
def _write_docstring(self, node):
- def esc_char(c):
- if c in ("\n", "\t"):
- # In the AST form, we don't know the author's intentation
- # about how this should be displayed. We'll only escape
- # \n and \t, because they are more likely to be unescaped
- # in the source
- return c
- return c.encode('unicode_escape').decode('ascii')
-
self.fill()
if node.kind == "u":
self.write("u")
-
- value = node.value
- if value:
- # Preserve quotes in the docstring by escaping them
- value = "".join(map(esc_char, value))
- if value[-1] == '"':
- value = value.replace('"', '\\"', -1)
- value = value.replace('"""', '""\\"')
-
- self.write(f'"""{value}"""')
+ self._write_str_avoiding_backslashes(node.value, quote_types=_MULTI_QUOTES)
def _write_constant(self, value):
if isinstance(value, (float, complex)):
# Substitute overflowing decimal literal for AST infinities.
self.write(repr(value).replace("inf", _INFSTR))
+ elif self._avoid_backslashes and isinstance(value, str):
+ self._write_str_avoiding_backslashes(value)
else:
self.write(repr(value))
__all__ = ()
import reprlib
+from _thread import get_ident
from . import format_helpers
return f'cb=[{cb}]'
+# bpo-42183: _repr_running is needed for repr protection
+# when a Future or Task result contains itself directly or indirectly.
+# The logic is borrowed from @reprlib.recursive_repr decorator.
+# Unfortunately, the direct decorator usage is impossible because of
+# AttributeError: '_asyncio.Task' object has no attribute '__module__' error.
+#
+# After fixing this thing we can return to the decorator based approach.
+_repr_running = set()
+
+
def _future_repr_info(future):
# (Future) -> str
"""helper function for Future.__repr__"""
if future._exception is not None:
info.append(f'exception={future._exception!r}')
else:
- # use reprlib to limit the length of the output, especially
- # for very long strings
- result = reprlib.repr(future._result)
+ key = id(future), get_ident()
+ if key in _repr_running:
+ result = '...'
+ else:
+ _repr_running.add(key)
+ try:
+ # use reprlib to limit the length of the output, especially
+ # for very long strings
+ result = reprlib.repr(future._result)
+ finally:
+ _repr_running.discard(key)
info.append(f'result={result}')
if future._callbacks:
info.append(_format_callbacks(future._callbacks))
- expected: total number of expected bytes (or None if unknown)
"""
def __init__(self, partial, expected):
+ r_expected = 'undefined' if expected is None else repr(expected)
super().__init__(f'{len(partial)} bytes read on a total of '
- f'{expected!r} expected bytes')
+ f'{r_expected} expected bytes')
self.partial = partial
self.expected = expected
async def wait(fs, *, loop=None, timeout=None, return_when=ALL_COMPLETED):
"""Wait for the Futures and coroutines given by fs to complete.
- The sequence futures must not be empty.
+ The fs iterable must not be empty.
Coroutines will be wrapped in Tasks.
"and scheduled for removal in Python 3.10.",
DeprecationWarning, stacklevel=2)
- if any(coroutines.iscoroutine(f) for f in set(fs)):
+ fs = set(fs)
+
+ if any(coroutines.iscoroutine(f) for f in fs):
warnings.warn("The explicit passing of coroutine objects to "
"asyncio.wait() is deprecated since Python 3.8, and "
"scheduled for removal in Python 3.11.",
DeprecationWarning, stacklevel=2)
- fs = {ensure_future(f, loop=loop) for f in set(fs)}
+ fs = {ensure_future(f, loop=loop) for f in fs}
return await _wait(fs, timeout, return_when, loop)
Note: The futures 'f' are not necessarily members of fs.
"""
if futures.isfuture(fs) or coroutines.iscoroutine(fs):
- raise TypeError(f"expect a list of futures, not {type(fs).__name__}")
+ raise TypeError(f"expect an iterable of futures, not {type(fs).__name__}")
from .queues import Queue # Import here to avoid circular import problem.
done = Queue(loop=loop)
first = 0
while first <= len(self.hqxdata) - self.linelen:
last = first + self.linelen
- self.ofp.write(self.hqxdata[first:last] + b'\n')
+ self.ofp.write(self.hqxdata[first:last] + b'\r')
self.linelen = LINELEN
first = last
self.hqxdata = self.hqxdata[first:]
if force:
- self.ofp.write(self.hqxdata + b':\n')
+ self.ofp.write(self.hqxdata + b':\r')
def close(self):
if self.data:
(options, args) = parser.parse_args()
sys.argv[:] = args
+ # The script that we're profiling may chdir, so capture the absolute path
+ # to the output file at startup.
+ if options.outfile is not None:
+ options.outfile = os.path.abspath(options.outfile)
+
if len(args) > 0:
if options.module:
code = "run_module(modname, run_name='__main__')"
def __iter__(self):
d = {}
for mapping in reversed(self.maps):
- d.update(mapping) # reuses stored hash values if possible
+ d.update(dict.fromkeys(mapping)) # reuses stored hash values if possible
return iter(d)
def __contains__(self, key):
return obj
_HEAPTYPE = 1<<9
+_new_type = type(int.__new__)
# Python code for object.__reduce_ex__ for protocols 0 and 1
for base in cls.__mro__:
if hasattr(base, '__flags__') and not base.__flags__ & _HEAPTYPE:
break
+ new = base.__new__
+ if isinstance(new, _new_type) and new.__self__ is base:
+ break
else:
base = object # not really reachable
if base is object:
from ctypes.macholib.framework import framework_info
from ctypes.macholib.dylib import dylib_info
from itertools import *
+try:
+ from _ctypes import _dyld_shared_cache_contains_path
+except ImportError:
+ def _dyld_shared_cache_contains_path(*args):
+ raise NotImplementedError
__all__ = [
'dyld_find', 'framework_find',
dyld_executable_path_search(name, executable_path),
dyld_default_search(name, env),
), env):
+
if os.path.isfile(path):
return path
+ try:
+ if _dyld_shared_cache_contains_path(path):
+ return path
+ except NotImplementedError:
+ pass
+
raise ValueError("dylib %s could not be found" % (name,))
def framework_find(fn, executable_path=None, env=None):
import unittest
+import unittest.mock
import os.path
import sys
import test.support
@unittest.skipUnless(sys.platform.startswith('linux'),
'Test only valid for Linux')
-class LibPathFindTest(unittest.TestCase):
+class FindLibraryLinux(unittest.TestCase):
def test_find_on_libpath(self):
import subprocess
import tempfile
# LD_LIBRARY_PATH)
self.assertEqual(find_library(libname), 'lib%s.so' % libname)
+ def test_find_library_with_gcc(self):
+ with unittest.mock.patch("ctypes.util._findSoname_ldconfig", lambda *args: None):
+ self.assertNotEqual(find_library('c'), None)
+
+ def test_find_library_with_ld(self):
+ with unittest.mock.patch("ctypes.util._findSoname_ldconfig", lambda *args: None), \
+ unittest.mock.patch("ctypes.util._findLib_gcc", lambda *args: None):
+ self.assertNotEqual(find_library('c'), None)
+
if __name__ == "__main__":
unittest.main()
class MachOTest(unittest.TestCase):
@unittest.skipUnless(sys.platform == "darwin", 'OSX-specific test')
def test_find(self):
-
- self.assertEqual(find_lib('pthread'),
- '/usr/lib/libSystem.B.dylib')
+ # On Mac OS 11, system dylibs are only present in the shared cache,
+ # so symlinks like libpthread.dylib -> libSystem.B.dylib will not
+ # be resolved by dyld_find
+ self.assertIn(find_lib('pthread'),
+ ('/usr/lib/libSystem.B.dylib', '/usr/lib/libpthread.dylib'))
result = find_lib('z')
# Issue #21093: dyld default search path includes $HOME/lib and
# /usr/local/lib before /usr/lib, which caused test failures if
# a local copy of libz exists in one of them. Now ignore the head
# of the path.
- self.assertRegex(result, r".*/lib/libz\..*.*\.dylib")
+ self.assertRegex(result, r".*/lib/libz.*\.dylib")
- self.assertEqual(find_lib('IOKit'),
- '/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit')
+ self.assertIn(find_lib('IOKit'),
+ ('/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit',
+ '/System/Library/Frameworks/IOKit.framework/IOKit'))
if __name__ == "__main__":
unittest.main()
-import sys
import unittest
+# also work on POSIX
+
from ctypes import *
+from ctypes import wintypes
+
-@unittest.skipUnless(sys.platform.startswith('win'), 'Windows-only test')
class WinTypesTest(unittest.TestCase):
def test_variant_bool(self):
- from ctypes import wintypes
# reads 16-bits from memory, anything non-zero is True
for true_value in (1, 32767, 32768, 65535, 65537):
true = POINTER(c_int16)(c_int16(true_value))
vb.value = []
self.assertIs(vb.value, False)
+
if __name__ == "__main__":
unittest.main()
# Andreas Degert's find functions, using gcc, /sbin/ldconfig, objdump
import re, tempfile
+ def _is_elf(filename):
+ "Return True if the given file is an ELF file"
+ elf_header = b'\x7fELF'
+ with open(filename, 'br') as thefile:
+ return thefile.read(4) == elf_header
+
def _findLib_gcc(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
# Raised if the file was already removed, which is the normal
# behaviour of GCC if linking fails
pass
- res = re.search(expr, trace)
+ res = re.findall(expr, trace)
if not res:
return None
- return os.fsdecode(res.group(0))
+
+ for file in res:
+ # Check if the given file is an elf file: gcc can report
+ # some files that are linker scripts and not actual
+ # shared objects. See bpo-41976 for more details
+ if not _is_elf(file):
+ continue
+ return os.fsdecode(file)
if sys.platform == "sunos5":
stderr=subprocess.PIPE,
universal_newlines=True)
out, _ = p.communicate()
- res = re.search(expr, os.fsdecode(out))
- if res:
- result = res.group(0)
+ res = re.findall(expr, os.fsdecode(out))
+ for file in res:
+ # Check if the given file is an elf file: gcc can report
+ # some files that are linker scripts and not actual
+ # shared objects. See bpo-41976 for more details
+ if not _is_elf(file):
+ continue
+ return os.fsdecode(file)
except Exception:
pass # result will be None
return result
def find_library(name):
# See issue #9998
return _findSoname_ldconfig(name) or \
- _get_soname(_findLib_gcc(name) or _findLib_ld(name))
+ _get_soname(_findLib_gcc(name)) or _get_soname(_findLib_ld(name))
################################################################
# test code
self._tzinfo = tzinfo
def __reduce_ex__(self, protocol):
- return (time, self._getstate(protocol))
+ return (self.__class__, self._getstate(protocol))
def __reduce__(self):
return self.__reduce_ex__(2)
global _cfg_target, _cfg_target_split
if _cfg_target is None:
from distutils import sysconfig
- _cfg_target = sysconfig.get_config_var(
- 'MACOSX_DEPLOYMENT_TARGET') or ''
+ _cfg_target = str(sysconfig.get_config_var(
+ 'MACOSX_DEPLOYMENT_TARGET') or '')
if _cfg_target:
_cfg_target_split = [int(x) for x in _cfg_target.split('.')]
if _cfg_target:
deptarget = sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET')
if deptarget:
# increment the minor version number (i.e. 10.6 -> 10.7)
- deptarget = [int(x) for x in deptarget.split('.')]
+ deptarget = [int(x) for x in str(deptarget).split('.')]
deptarget[-1] += 1
deptarget = '.'.join(str(i) for i in deptarget)
self._try_compile_deployment_target('<', deptarget)
# get the deployment target that the interpreter was built with
target = sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET')
- target = tuple(map(int, target.split('.')[0:2]))
+ target = tuple(map(int, str(target).split('.')[0:2]))
# format the target value as defined in the Apple
# Availability Macros. We can't use the macro names since
# at least one value we test with will not exist yet.
- if target[1] < 10:
+ if target[:2] < (10, 10):
# for 10.1 through 10.9.x -> "10n0"
target = '%02d%01d0' % target
else:
# for 10.10 and beyond -> "10nn00"
- target = '%02d%02d00' % target
+ if len(target) >= 2:
+ target = '%02d%02d00' % target
+ else:
+ # 11 and later can have no minor version (11 instead of 11.0)
+ target = '%02d0000' % target
deptarget_ext = Extension(
'deptarget',
[deptarget_c],
cflags = sysconfig.get_config_var('CFLAGS')
m = re.search(r'-isysroot\s*(\S+)', cflags)
if m is None:
- sysroot = '/'
+ sysroot = _osx_support._default_sysroot(sysconfig.get_config_var('CC'))
else:
sysroot = m.group(1)
# If we munged the cte, copy the message again and re-fix the CTE.
if munge_cte:
msg = deepcopy(msg)
- msg.replace_header('content-transfer-encoding', munge_cte[0])
+ # Preserve the header order if the CTE header already exists.
+ if msg.get('content-transfer-encoding') is None:
+ msg['Content-Transfer-Encoding'] = munge_cte[0]
+ else:
+ msg.replace_header('content-transfer-encoding', munge_cte[0])
msg.replace_header('content-type', munge_cte[1])
# Write the headers. First we see if the message object wants to
# handle that itself. If not, we'll do it generically.
class CycleError(ValueError):
- """Subclass of ValueError raised by TopologicalSorterif cycles exist in the graph
+ """Subclass of ValueError raised by TopologicalSorter.prepare if cycles
+ exist in the working graph.
If multiple cycles exist, only one undefined choice among them will be reported
and included in the exception. The detected cycle can be accessed via the second
return result
def is_active(self):
- """Return True if more progress can be made and ``False`` otherwise.
+ """Return ``True`` if more progress can be made and ``False`` otherwise.
Progress can be made if cycles do not block the resolution and either there
are still nodes ready that haven't yet been returned by "get_ready" or the
"""Marks a set of nodes returned by "get_ready" as processed.
This method unblocks any successor of each node in *nodes* for being returned
- in the future by a a call to "get_ready"
+ in the future by a call to "get_ready".
Raises :exec:`ValueError` if any node in *nodes* has already been marked as
processed by a previous call to this method, if a node was not added to the
referer = self.headers.get('referer')
if referer:
env['HTTP_REFERER'] = referer
- accept = []
- for line in self.headers.getallmatchingheaders('accept'):
- if line[:1] in "\t\n\r ":
- accept.append(line.strip())
- else:
- accept = accept + line[7:].split(',')
+ accept = self.headers.get_all('accept', ())
env['HTTP_ACCEPT'] = ','.join(accept)
ua = self.headers.get('user-agent')
if ua:
Various different formats and sizes are available at this GitHub Pull Request:
https://github.com/python/cpython/pull/17473
+
+The idle.ico file was created with ImageMagick:
+
+ $ convert idle_16.png idle_32.png idle_48.png idle_256.png idle.ico
+What's New in IDLE 3.9.1
+Released on 2020-12-07?
+======================================
+
+
+bpo-42508: Keep IDLE running on macOS. Remove obsolete workaround
+that prevented running files with shortcuts when using new universal2
+installers built on macOS 11.
+
+bpo-42426: Fix reporting offset of the RE error in searchengine.
+
+bpo-42416: Get docstrings for IDLE calltips more often
+by using inspect.getdoc.
+
+bpo-33987: Mostly finish using ttk widgets, mainly for editor,
+settings, and searches. Some patches by Mark Roseman.
+
+bpo-41775: Make 'IDLE Shell' the shell title.
+
+bpo-35764: Rewrite the Calltips doc section.
+
+bpo-40181: In calltips, stop reminding that '/' marks the end of
+positional-only arguments.
+
+
What's New in IDLE 3.9.0 (since 3.8.0)
Released on 2020-10-05?
======================================
-
bpo-41468: Improve IDLE run crash error message (which users should
never see).
self.open_calltip(False)
def open_calltip(self, evalfuncs):
- self.remove_calltip_window()
+ """Maybe close an existing calltip and maybe open a new calltip.
+ Called from (force_open|try_open|refresh)_calltip_event functions.
+ """
hp = HyperParser(self.editwin, "insert")
sur_paren = hp.get_surrounding_brackets('(')
+
+ # If not inside parentheses, no calltip.
if not sur_paren:
+ self.remove_calltip_window()
return
+
+ # If a calltip is shown for the current parentheses, do
+ # nothing.
+ if self.active_calltip:
+ opener_line, opener_col = map(int, sur_paren[0].split('.'))
+ if (
+ (opener_line, opener_col) ==
+ (self.active_calltip.parenline, self.active_calltip.parencol)
+ ):
+ return
+
hp.set_index(sur_paren[0])
- expression = hp.get_expression()
+ try:
+ expression = hp.get_expression()
+ except ValueError:
+ expression = None
if not expression:
+ # No expression before the opening parenthesis, e.g.
+ # because it's in a string or the opener for a tuple:
+ # Do nothing.
return
+
+ # At this point, the current index is after an opening
+ # parenthesis, in a section of code, preceded by a valid
+ # expression. If there is a calltip shown, it's not for the
+ # same index and should be closed.
+ self.remove_calltip_window()
+
+ # Simple, fast heuristic: If the preceding expression includes
+ # an opening parenthesis, it likely includes a function call.
if not evalfuncs and (expression.find('(') != -1):
return
+
argspec = self.fetch_tip(expression)
if not argspec:
return
_first_param = re.compile(r'(?<=\()\w*\,?\s*')
_default_callable_argspec = "See source or doc"
_invalid_method = "invalid method signature"
-_argument_positional = " # '/' marks preceding args as positional-only."
def get_argspec(ob):
'''Return a string describing the signature of a callable object, or ''.
ob_call = ob.__call__
except BaseException: # Buggy user object could raise anything.
return '' # No popup for non-callables.
+ # For Get_argspecTest.test_buggy_getattr_class, CallA() & CallB().
fob = ob_call if isinstance(ob_call, types.MethodType) else ob
# Initialize argspec and wrap it to get lines.
else:
argspec = ''
- if '/' in argspec and len(argspec) < _MAX_COLS - len(_argument_positional):
- # Add explanation TODO remove after 3.7, before 3.9.
- argspec += _argument_positional
if isinstance(fob, type) and argspec == '()':
# If fob has no argument, use default callable argspec.
argspec = _default_callable_argspec
if len(argspec) > _MAX_COLS else [argspec] if argspec else [])
# Augment lines from docstring, if any, and join to get argspec.
- if isinstance(ob_call, types.MethodType):
- doc = ob_call.__doc__
- else:
- doc = getattr(ob, "__doc__", "")
+ doc = inspect.getdoc(ob)
if doc:
for line in doc.split('\n', _MAX_LINES)[:_MAX_LINES]:
line = line.strip()
if not _utest:
self.withdraw()
- self.configure(borderwidth=5)
self.title(title or 'IDLE Preferences')
x = parent.winfo_rootx() + 20
y = parent.winfo_rooty() + (30 if not _htest else 150)
"""Create and place widgets for tabbed dialog.
Widgets Bound to self:
+ frame: encloses all other widgets
note: Notebook
highpage: HighPage
fontpage: FontPage
load_configs: Load pages except for extensions.
activate_config_changes: Tell editors to reload.
"""
- self.note = note = Notebook(self)
+ self.frame = frame = Frame(self, padding="5px")
+ self.frame.grid(sticky="nwes")
+ self.note = note = Notebook(frame)
self.highpage = HighPage(note)
self.fontpage = FontPage(note, self.highpage)
self.keyspage = KeysPage(note)
padding_args = {}
else:
padding_args = {'padding': (6, 3)}
- outer = Frame(self, padding=2)
+ outer = Frame(self.frame, padding=2)
buttons_frame = Frame(outer, padding=2)
self.buttons = {}
for txt, cmd in (
def __init__(self, master):
super().__init__(master)
- self.cd = master.master
+ self.cd = master.winfo_toplevel()
self.style = Style(master)
self.create_page_highlight()
self.load_theme_cfg()
def __init__(self, master):
super().__init__(master)
- self.cd = master.master
+ self.cd = master.winfo_toplevel()
self.create_page_keys()
self.load_key_cfg()
<!DOCTYPE html>
-<html xmlns="http://www.w3.org/1999/xhtml">
+<html>
<head>
<meta charset="utf-8" />
- <title>IDLE — Python 3.10.0a0 documentation</title>
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <title>IDLE — Python 3.10.0a1 documentation</title>
<link rel="stylesheet" href="../_static/pydoctheme.css" type="text/css" />
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
- <script type="text/javascript" id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script>
- <script type="text/javascript" src="../_static/jquery.js"></script>
- <script type="text/javascript" src="../_static/underscore.js"></script>
- <script type="text/javascript" src="../_static/doctools.js"></script>
- <script type="text/javascript" src="../_static/language_data.js"></script>
+ <script id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script>
+ <script src="../_static/jquery.js"></script>
+ <script src="../_static/underscore.js"></script>
+ <script src="../_static/doctools.js"></script>
+ <script src="../_static/language_data.js"></script>
- <script type="text/javascript" src="../_static/sidebar.js"></script>
+ <script src="../_static/sidebar.js"></script>
<link rel="search" type="application/opensearchdescription+xml"
- title="Search within Python 3.10.0a0 documentation"
+ title="Search within Python 3.10.0a1 documentation"
href="../_static/opensearch.xml"/>
<link rel="author" title="About these documents" href="../about.html" />
<link rel="index" title="Index" href="../genindex.html" />
<li>
- <a href="../index.html">3.10.0a0 Documentation</a> »
+ <a href="../index.html">3.10.0a1 Documentation</a> »
</li>
<li class="nav-item nav-item-1"><a href="index.html" >The Python Standard Library</a> »</li>
<li class="nav-item nav-item-2"><a href="tk.html" accesskey="U">Graphical User Interfaces with Tk</a> »</li>
+ <li class="nav-item nav-item-this"><a href="">IDLE</a></li>
<li class="right">
the <kbd class="kbd docutils literal notranslate">Command</kbd> key on macOS.</p>
<ul>
<li><p><kbd class="kbd docutils literal notranslate">Backspace</kbd> deletes to the left; <kbd class="kbd docutils literal notranslate">Del</kbd> deletes to the right</p></li>
-<li><p><kbd class="kbd docutils literal notranslate">C-Backspace</kbd> delete word left; <kbd class="kbd docutils literal notranslate">C-Del</kbd> delete word to the right</p></li>
-<li><p>Arrow keys and <kbd class="kbd docutils literal notranslate">Page Up</kbd>/<kbd class="kbd docutils literal notranslate">Page Down</kbd> to move around</p></li>
-<li><p><kbd class="kbd docutils literal notranslate">C-LeftArrow</kbd> and <kbd class="kbd docutils literal notranslate">C-RightArrow</kbd> moves by words</p></li>
+<li><p><kbd class="kbd docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">Backspace</kbd></kbd> delete word left; <kbd class="kbd docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">Del</kbd></kbd> delete word to the right</p></li>
+<li><p>Arrow keys and <kbd class="kbd docutils literal notranslate"><kbd class="kbd docutils literal notranslate">Page</kbd> <kbd class="kbd docutils literal notranslate">Up</kbd></kbd>/<kbd class="kbd docutils literal notranslate"><kbd class="kbd docutils literal notranslate">Page</kbd> <kbd class="kbd docutils literal notranslate">Down</kbd></kbd> to move around</p></li>
+<li><p><kbd class="kbd docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">LeftArrow</kbd></kbd> and <kbd class="kbd docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">RightArrow</kbd></kbd> moves by words</p></li>
<li><p><kbd class="kbd docutils literal notranslate">Home</kbd>/<kbd class="kbd docutils literal notranslate">End</kbd> go to begin/end of line</p></li>
-<li><p><kbd class="kbd docutils literal notranslate">C-Home</kbd>/<kbd class="kbd docutils literal notranslate">C-End</kbd> go to begin/end of file</p></li>
+<li><p><kbd class="kbd docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">Home</kbd></kbd>/<kbd class="kbd docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">End</kbd></kbd> go to begin/end of file</p></li>
<li><p>Some useful Emacs bindings are inherited from Tcl/Tk:</p>
<blockquote>
<div><ul class="simple">
-<li><p><kbd class="kbd docutils literal notranslate">C-a</kbd> beginning of line</p></li>
-<li><p><kbd class="kbd docutils literal notranslate">C-e</kbd> end of line</p></li>
-<li><p><kbd class="kbd docutils literal notranslate">C-k</kbd> kill line (but doesn’t put it in clipboard)</p></li>
-<li><p><kbd class="kbd docutils literal notranslate">C-l</kbd> center window around the insertion point</p></li>
-<li><p><kbd class="kbd docutils literal notranslate">C-b</kbd> go backward one character without deleting (usually you can
+<li><p><kbd class="kbd docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">a</kbd></kbd> beginning of line</p></li>
+<li><p><kbd class="kbd docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">e</kbd></kbd> end of line</p></li>
+<li><p><kbd class="kbd docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">k</kbd></kbd> kill line (but doesn’t put it in clipboard)</p></li>
+<li><p><kbd class="kbd docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">l</kbd></kbd> center window around the insertion point</p></li>
+<li><p><kbd class="kbd docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">b</kbd></kbd> go backward one character without deleting (usually you can
also use the cursor key for this)</p></li>
-<li><p><kbd class="kbd docutils literal notranslate">C-f</kbd> go forward one character without deleting (usually you can
+<li><p><kbd class="kbd docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">f</kbd></kbd> go forward one character without deleting (usually you can
also use the cursor key for this)</p></li>
-<li><p><kbd class="kbd docutils literal notranslate">C-p</kbd> go up one line (usually you can also use the cursor key for
+<li><p><kbd class="kbd docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">p</kbd></kbd> go up one line (usually you can also use the cursor key for
this)</p></li>
-<li><p><kbd class="kbd docutils literal notranslate">C-d</kbd> delete next character</p></li>
+<li><p><kbd class="kbd docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">d</kbd></kbd> delete next character</p></li>
</ul>
</div></blockquote>
</li>
</ul>
-<p>Standard keybindings (like <kbd class="kbd docutils literal notranslate">C-c</kbd> to copy and <kbd class="kbd docutils literal notranslate">C-v</kbd> to paste)
+<p>Standard keybindings (like <kbd class="kbd docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">c</kbd></kbd> to copy and <kbd class="kbd docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">v</kbd></kbd> to paste)
may work. Keybindings are selected in the Configure IDLE dialog.</p>
</div>
<div class="section" id="automatic-indentation">
directory name and a separator.</p>
<p>Instead of waiting, or after a box is closed, open a completion box
immediately with Show Completions on the Edit menu. The default hot
-key is <kbd class="kbd docutils literal notranslate">C-space</kbd>. If one types a prefix for the desired name
+key is <kbd class="kbd docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">space</kbd></kbd>. If one types a prefix for the desired name
before opening the box, the first match or near miss is made visible.
The result is the same as if one enters a prefix
after the box is displayed. Show Completions after a quote completes
</div>
<div class="section" id="calltips">
<span id="id4"></span><h3>Calltips<a class="headerlink" href="#calltips" title="Permalink to this headline">¶</a></h3>
-<p>A calltip is shown when one types <kbd class="kbd docutils literal notranslate">(</kbd> after the name of an <em>accessible</em>
-function. A name expression may include dots and subscripts. A calltip
-remains until it is clicked, the cursor is moved out of the argument area,
-or <kbd class="kbd docutils literal notranslate">)</kbd> is typed. When the cursor is in the argument part of a definition,
-the menu or shortcut display a calltip.</p>
-<p>A calltip consists of the function signature and the first line of the
-docstring. For builtins without an accessible signature, the calltip
-consists of all lines up the fifth line or the first blank line. These
-details may change.</p>
-<p>The set of <em>accessible</em> functions depends on what modules have been imported
-into the user process, including those imported by Idle itself,
-and what definitions have been run, all since the last restart.</p>
+<p>A calltip is shown automatically when one types <kbd class="kbd docutils literal notranslate">(</kbd> after the name
+of an <em>accessible</em> function. A function name expression may include
+dots and subscripts. A calltip remains until it is clicked, the cursor
+is moved out of the argument area, or <kbd class="kbd docutils literal notranslate">)</kbd> is typed. Whenever the
+cursor is in the argument part of a definition, select Edit and “Show
+Call Tip” on the menu or enter its shortcut to display a calltip.</p>
+<p>The calltip consists of the function’s signature and docstring up to
+the latter’s first blank line or the fifth non-blank line. (Some builtin
+functions lack an accessible signature.) A ‘/’ or ‘*’ in the signature
+indicates that the preceding or following arguments are passed by
+position or name (keyword) only. Details are subject to change.</p>
+<p>In Shell, the accessible functions depends on what modules have been
+imported into the user process, including those imported by Idle itself,
+and which definitions have been run, all since the last restart.</p>
<p>For example, restart the Shell and enter <code class="docutils literal notranslate"><span class="pre">itertools.count(</span></code>. A calltip
-appears because Idle imports itertools into the user process for its own use.
-(This could change.) Enter <code class="docutils literal notranslate"><span class="pre">turtle.write(</span></code> and nothing appears. Idle does
-not import turtle. The menu or shortcut do nothing either. Enter
-<code class="docutils literal notranslate"><span class="pre">import</span> <span class="pre">turtle</span></code> and then <code class="docutils literal notranslate"><span class="pre">turtle.write(</span></code> will work.</p>
-<p>In an editor, import statements have no effect until one runs the file. One
-might want to run a file after writing the import statements at the top,
-or immediately run an existing file before editing.</p>
+appears because Idle imports itertools into the user process for its own
+use. (This could change.) Enter <code class="docutils literal notranslate"><span class="pre">turtle.write(</span></code> and nothing appears.
+Idle does not itself import turtle. The menu entry and shortcut also do
+nothing. Enter <code class="docutils literal notranslate"><span class="pre">import</span> <span class="pre">turtle</span></code>. Thereafter, <code class="docutils literal notranslate"><span class="pre">turtle.write(</span></code>
+will display a calltip.</p>
+<p>In an editor, import statements have no effect until one runs the file.
+One might want to run a file after writing import statements, after
+adding function definitions, or after opening an existing file.</p>
</div>
<div class="section" id="code-context">
<span id="id5"></span><h3>Code Context<a class="headerlink" href="#code-context" title="Permalink to this headline">¶</a></h3>
<p>The editing features described in previous subsections work when entering
code interactively. IDLE’s Shell window also responds to the following keys.</p>
<ul>
-<li><p><kbd class="kbd docutils literal notranslate">C-c</kbd> interrupts executing command</p></li>
-<li><p><kbd class="kbd docutils literal notranslate">C-d</kbd> sends end-of-file; closes window if typed at a <code class="docutils literal notranslate"><span class="pre">>>></span></code> prompt</p></li>
-<li><p><kbd class="kbd docutils literal notranslate">Alt-/</kbd> (Expand word) is also useful to reduce typing</p>
+<li><p><kbd class="kbd docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">c</kbd></kbd> interrupts executing command</p></li>
+<li><p><kbd class="kbd docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">d</kbd></kbd> sends end-of-file; closes window if typed at a <code class="docutils literal notranslate"><span class="pre">>>></span></code> prompt</p></li>
+<li><p><kbd class="kbd docutils literal notranslate"><kbd class="kbd docutils literal notranslate">Alt</kbd>-<kbd class="kbd docutils literal notranslate">/</kbd></kbd> (Expand word) is also useful to reduce typing</p>
<p>Command history</p>
<ul class="simple">
-<li><p><kbd class="kbd docutils literal notranslate">Alt-p</kbd> retrieves previous command matching what you have typed. On
-macOS use <kbd class="kbd docutils literal notranslate">C-p</kbd>.</p></li>
-<li><p><kbd class="kbd docutils literal notranslate">Alt-n</kbd> retrieves next. On macOS use <kbd class="kbd docutils literal notranslate">C-n</kbd>.</p></li>
+<li><p><kbd class="kbd docutils literal notranslate"><kbd class="kbd docutils literal notranslate">Alt</kbd>-<kbd class="kbd docutils literal notranslate">p</kbd></kbd> retrieves previous command matching what you have typed. On
+macOS use <kbd class="kbd docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">p</kbd></kbd>.</p></li>
+<li><p><kbd class="kbd docutils literal notranslate"><kbd class="kbd docutils literal notranslate">Alt</kbd>-<kbd class="kbd docutils literal notranslate">n</kbd></kbd> retrieves next. On macOS use <kbd class="kbd docutils literal notranslate"><kbd class="kbd docutils literal notranslate">C</kbd>-<kbd class="kbd docutils literal notranslate">n</kbd></kbd>.</p></li>
<li><p><kbd class="kbd docutils literal notranslate">Return</kbd> while on any previous command retrieves that command</p></li>
</ul>
</li>
</div>
+ <div class="clearer"></div>
</div>
</div>
</div>
<li>
- <a href="../index.html">3.10.0a0 Documentation</a> »
+ <a href="../index.html">3.10.0a1 Documentation</a> »
</li>
<li class="nav-item nav-item-1"><a href="index.html" >The Python Standard Library</a> »</li>
<li class="nav-item nav-item-2"><a href="tk.html" >Graphical User Interfaces with Tk</a> »</li>
+ <li class="nav-item nav-item-this"><a href="">IDLE</a></li>
<li class="right">
<br />
<br />
- Last updated on Sep 09, 2020.
+ Last updated on Oct 20, 2020.
<a href="https://docs.python.org/3/bugs.html">Found a bug</a>?
<br />
- Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 2.1.1.
+ Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.2.1.
</div>
</body>
from os.path import abspath, dirname, isfile, join
from platform import python_version
-from tkinter import Toplevel, Frame, Text, Menu
-from tkinter.ttk import Menubutton, Scrollbar
+from tkinter import Toplevel, Text, Menu
+from tkinter.ttk import Frame, Menubutton, Scrollbar, Style
from tkinter import font as tkfont
from idlelib.config import idleConf
def __init__(self, parent, filename):
Frame.__init__(self, parent)
self.text = text = HelpText(self, filename)
- self['background'] = text['background']
+ self.style = Style(parent)
+ self['style'] = 'helpframe.TFrame'
+ self.style.configure('helpframe.TFrame', background=text['background'])
self.toc = toc = self.toc_menu(text)
self.scroll = scroll = Scrollbar(self, command=text.yview)
text['yscrollcommand'] = scroll.set
A gui object is anything with a master or parent parameter, which is
typically required in spite of what the doc strings say.
"""
+import re
+from _tkinter import TclError
+
class Event:
'''Minimal mock with attributes for testing event handlers.
"Create event with attributes needed for test"
self.__dict__.update(kwds)
+
class Var:
"Use for String/Int/BooleanVar: incomplete"
def __init__(self, master=None, value=None, name=None):
def get(self):
return self.value
+
class Mbox_func:
"""Generic mock for messagebox functions, which all have the same signature.
self.kwds = kwds
return self.result # Set by tester for ask functions
+
class Mbox:
"""Mock for tkinter.messagebox with an Mbox_func for each function.
showinfo = Mbox_func() # None
showwarning = Mbox_func() # None
-from _tkinter import TclError
class Text:
"""A semi-functional non-gui replacement for tkinter.Text text editors.
if char.endswith(' lineend') or char == 'end':
return line, linelength
# Tk requires that ignored chars before ' lineend' be valid int
+ if m := re.fullmatch(r'end-(\d*)c', char, re.A): # Used by hyperparser.
+ return line, linelength - int(m.group(1))
# Out of bounds char becomes first or last index of line
char = int(char)
n -= 1
return n, len(self.data[n]) + endflag
-
def insert(self, index, chars):
"Insert chars before the character at index."
self.data[line+1:line+1] = chars[1:]
self.data[line+len(chars)-1] += after
-
def get(self, index1, index2=None):
"Return slice from index1 to index2 (default is 'index1+1')."
lines.append(self.data[endline][:endchar])
return ''.join(lines)
-
def delete(self, index1, index2=None):
'''Delete slice from index1 to index2 (default is 'index1+1').
"Bind to this widget at event sequence a call to function func."
pass
+
class Entry:
"Mock for tkinter.Entry."
def focus_set(self):
-"Test calltip, coverage 60%"
+"Test calltip, coverage 76%"
from idlelib import calltip
import unittest
+from unittest.mock import Mock
import textwrap
import types
import re
+from idlelib.idle_test.mock_tk import Text
# Test Class TC is used in multiple get_argspec test methods
if List.__doc__ is not None:
tiptest(List,
- f'(iterable=(), /){calltip._argument_positional}'
+ f'(iterable=(), /)'
f'\n{List.__doc__}')
tiptest(list.__new__,
'(*args, **kwargs)\n'
'Create and return a new object. '
'See help(type) for accurate signature.')
tiptest(list.__init__,
- '(self, /, *args, **kwargs)'
- + calltip._argument_positional + '\n' +
+ '(self, /, *args, **kwargs)\n'
'Initialize self. See help(type(self)) for accurate signature.')
- append_doc = (calltip._argument_positional
- + "\nAppend object to the end of the list.")
+ append_doc = "\nAppend object to the end of the list."
tiptest(list.append, '(self, object, /)' + append_doc)
tiptest(List.append, '(self, object, /)' + append_doc)
tiptest([].append, '(object, /)' + append_doc)
(width=70, initial_indent='', subsequent_indent='', expand_tabs=True,
replace_whitespace=True, fix_sentence_endings=False, break_long_words=True,
drop_whitespace=True, break_on_hyphens=True, tabsize=8, *, max_lines=None,
- placeholder=' [...]')''')
+ placeholder=' [...]')
+Object for wrapping/filling text. The public interface consists of
+the wrap() and fill() methods; the other methods are just there for
+subclasses to override in order to tweak the default behaviour.
+If you want to completely replace the main wrapping algorithm,
+you\'ll probably have to override _wrap_chunks().''')
def test_properly_formated(self):
__class__ = property({}.__getitem__, {}.__setitem__)
class Object(metaclass=Type):
__slots__ = '__class__'
- for meth, mtip in ((Type, default_tip), (Object, default_tip),
+ for meth, mtip in ((Type, get_spec(type)), (Object, default_tip),
(Object(), '')):
with self.subTest(meth=meth, mtip=mtip):
self.assertEqual(get_spec(meth), mtip)
self.assertIs(calltip.get_entity('int'), int)
+# Test the 9 Calltip methods.
+# open_calltip is about half the code; the others are fairly trivial.
+# The default mocks are what are needed for open_calltip.
+
+class mock_Shell():
+ "Return mock sufficient to pass to hyperparser."
+ def __init__(self, text):
+ text.tag_prevrange = Mock(return_value=None)
+ self.text = text
+ self.prompt_last_line = ">>> "
+ self.indentwidth = 4
+ self.tabwidth = 8
+
+
+class mock_TipWindow:
+ def __init__(self):
+ pass
+
+ def showtip(self, text, parenleft, parenright):
+ self.args = parenleft, parenright
+ self.parenline, self.parencol = map(int, parenleft.split('.'))
+
+
+class WrappedCalltip(calltip.Calltip):
+ def _make_tk_calltip_window(self):
+ return mock_TipWindow()
+
+ def remove_calltip_window(self, event=None):
+ if self.active_calltip: # Setup to None.
+ self.active_calltip = None
+ self.tips_removed += 1 # Setup to 0.
+
+ def fetch_tip(self, expression):
+ return 'tip'
+
+
+class CalltipTest(unittest.TestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ cls.text = Text()
+ cls.ct = WrappedCalltip(mock_Shell(cls.text))
+
+ def setUp(self):
+ self.text.delete('1.0', 'end') # Insert and call
+ self.ct.active_calltip = None
+ # Test .active_calltip, +args
+ self.ct.tips_removed = 0
+
+ def open_close(self, testfunc):
+ # Open-close template with testfunc called in between.
+ opentip = self.ct.open_calltip
+ self.text.insert(1.0, 'f(')
+ opentip(False)
+ self.tip = self.ct.active_calltip
+ testfunc(self) ###
+ self.text.insert('insert', ')')
+ opentip(False)
+ self.assertIsNone(self.ct.active_calltip, None)
+
+ def test_open_close(self):
+ def args(self):
+ self.assertEqual(self.tip.args, ('1.1', '1.end'))
+ self.open_close(args)
+
+ def test_repeated_force(self):
+ def force(self):
+ for char in 'abc':
+ self.text.insert('insert', 'a')
+ self.ct.open_calltip(True)
+ self.ct.open_calltip(True)
+ self.assertIs(self.ct.active_calltip, self.tip)
+ self.open_close(force)
+
+ def test_repeated_parens(self):
+ def parens(self):
+ for context in "a", "'":
+ with self.subTest(context=context):
+ self.text.insert('insert', context)
+ for char in '(()())':
+ self.text.insert('insert', char)
+ self.assertIs(self.ct.active_calltip, self.tip)
+ self.text.insert('insert', "'")
+ self.open_close(parens)
+
+ def test_comment_parens(self):
+ def comment(self):
+ self.text.insert('insert', "# ")
+ for char in '(()())':
+ self.text.insert('insert', char)
+ self.assertIs(self.ct.active_calltip, self.tip)
+ self.text.insert('insert', "\n")
+ self.open_close(comment)
+
+
if __name__ == '__main__':
unittest.main(verbosity=2)
def test_make_entry(self):
equal = self.assertEqual
self.dialog.row = 0
- self.dialog.top = self.root
+ self.dialog.frame = Frame(self.root)
entry, label = self.dialog.make_entry("Test:", 'hello')
equal(label['text'], 'Test:')
equal(self.dialog.row, 1)
def test_create_entries(self):
- self.dialog.top = self.root
+ self.dialog.frame = Frame(self.root)
self.dialog.row = 0
self.engine.setpat('hello')
self.dialog.create_entries()
def test_make_frame(self):
self.dialog.row = 0
- self.dialog.top = self.root
+ self.dialog.frame = Frame(self.root)
frame, label = self.dialog.make_frame()
self.assertEqual(label, '')
self.assertEqual(str(type(frame)), "<class 'tkinter.ttk.Frame'>")
self.assertEqual(label['text'], 'testlabel')
def btn_test_setup(self, meth):
- self.dialog.top = self.root
+ self.dialog.frame = Frame(self.root)
self.dialog.row = 0
return meth()
self.assertEqual(var.get(), state)
def test_make_button(self):
- self.dialog.top = self.root
- self.dialog.buttonframe = Frame(self.dialog.top)
+ self.dialog.frame = Frame(self.root)
+ self.dialog.buttonframe = Frame(self.dialog.frame)
btn = self.dialog.make_button('Test', self.dialog.close)
self.assertEqual(btn['text'], 'Test')
def test_create_command_buttons(self):
- self.dialog.top = self.root
+ self.dialog.frame = Frame(self.root)
self.dialog.create_command_buttons()
# Look for close button command in buttonframe
closebuttoncommand = ''
engine.setpat('')
Equal(engine.getprog(), None)
+ Equal(Mbox.showerror.message,
+ 'Error: Empty regular expression')
engine.setpat('+')
engine.revar.set(1)
Equal(engine.getprog(), None)
- self.assertEqual(Mbox.showerror.message,
- 'Error: nothing to repeat at position 0\nPattern: +')
+ Equal(Mbox.showerror.message,
+ 'Error: nothing to repeat\nPattern: +\nOffset: 0')
def test_report_error(self):
showerror = Mbox.showerror
def runcode(self, code):
"Override base class method"
if self.tkconsole.executing:
- self.interp.restart_subprocess()
+ self.restart_subprocess()
self.checklinecache()
debugger = self.debugger
try:
class PyShell(OutputWindow):
- shell_title = "Python " + python_version() + " Shell"
+ shell_title = "IDLE Shell " + python_version()
# Override classes
ColorDelegator = ModifiedColorDelegator
"""
import os
import tabnanny
+import time
import tokenize
import tkinter.messagebox as tkMessageBox
self.root = self.editwin.root
# cli_args is list of strings that extends sys.argv
self.cli_args = []
-
- if macosx.isCocoaTk():
- self.editwin.text_frame.bind('<<run-module-event-2>>', self._run_module_event)
+ self.perf = 0.0 # Workaround for macOS 11 Uni2; see bpo-42508.
def check_module_event(self, event):
if isinstance(self.editwin, outwin.OutputWindow):
finally:
shell.set_warning_stream(saved_stream)
- def run_module_event(self, event):
- if macosx.isCocoaTk():
- # Tk-Cocoa in MacOSX is broken until at least
- # Tk 8.5.9, and without this rather
- # crude workaround IDLE would hang when a user
- # tries to run a module using the keyboard shortcut
- # (the menu item works fine).
- self.editwin.text_frame.after(200,
- lambda: self.editwin.text_frame.event_generate(
- '<<run-module-event-2>>'))
- return 'break'
- else:
- return self._run_module_event(event)
-
def run_custom_event(self, event):
- return self._run_module_event(event, customize=True)
+ return self.run_module_event(event, customize=True)
- def _run_module_event(self, event, *, customize=False):
+ def run_module_event(self, event, *, customize=False):
"""Run the module after setting up the environment.
First check the syntax. Next get customization. If OK, make
module being executed and also add that directory to its
sys.path if not already included.
"""
+ if macosx.isCocoaTk() and (time.perf_counter() - self.perf < .05):
+ return 'break'
if isinstance(self.editwin, outwin.OutputWindow):
self.editwin.text.bell()
return 'break'
# XXX This should really be a function of EditorWindow...
tkMessageBox.showerror(title, message, parent=self.editwin.text)
self.editwin.text.focus_set()
+ self.perf = time.perf_counter()
if __name__ == "__main__":
'''Initialize root, engine, and top attributes.
top (level widget): set in create_widgets() called from open().
+ frame: container for all widgets in dialog.
text (Text searched): set in open(), only used in subclasses().
ent (ry): created in make_entry() called from create_entry().
row (of grid): 0 in create_widgets(), +1 in make_entry/frame().
top.wm_title(self.title)
top.wm_iconname(self.icon)
self.top = top
+ self.frame = Frame(top, padding="5px")
+ self.frame.grid(sticky="nwes")
+ top.grid_columnconfigure(0, weight=100)
+ top.grid_rowconfigure(0, weight=100)
self.row = 0
- self.top.grid_columnconfigure(0, pad=2, weight=0)
- self.top.grid_columnconfigure(1, pad=2, minsize=100, weight=100)
+ self.frame.grid_columnconfigure(0, pad=2, weight=0)
+ self.frame.grid_columnconfigure(1, pad=2, minsize=100, weight=100)
self.create_entries() # row 0 (and maybe 1), cols 0, 1
self.create_option_buttons() # next row, cols 0, 1
entry - gridded labeled Entry for text entry.
label - Label widget, returned for testing.
'''
- label = Label(self.top, text=label_text)
+ label = Label(self.frame, text=label_text)
label.grid(row=self.row, column=0, sticky="nw")
- entry = Entry(self.top, textvariable=var, exportselection=0)
+ entry = Entry(self.frame, textvariable=var, exportselection=0)
entry.grid(row=self.row, column=1, sticky="nwe")
self.row = self.row + 1
return entry, label
label - Label widget, returned for testing.
'''
if labeltext:
- label = Label(self.top, text=labeltext)
+ label = Label(self.frame, text=labeltext)
label.grid(row=self.row, column=0, sticky="nw")
else:
label = ''
- frame = Frame(self.top)
+ frame = Frame(self.frame)
frame.grid(row=self.row, column=1, columnspan=1, sticky="nwe")
self.row = self.row + 1
return frame, label
def create_command_buttons(self):
"Place buttons in vertical command frame gridded on right."
- f = self.buttonframe = Frame(self.top)
+ f = self.buttonframe = Frame(self.frame)
f.grid(row=0,column=2,padx=2,pady=2,ipadx=2,ipady=2)
b = self.make_button("Close", self.close)
flags = flags | re.IGNORECASE
try:
prog = re.compile(pat, flags)
- except re.error as what:
- args = what.args
- msg = args[0]
- col = args[1] if len(args) >= 2 else -1
- self.report_error(pat, msg, col)
+ except re.error as e:
+ self.report_error(pat, e.msg, e.pos)
return None
return prog
- def report_error(self, pat, msg, col=-1):
+ def report_error(self, pat, msg, col=None):
# Derived class could override this with something fancier
msg = "Error: " + str(msg)
if pat:
msg = msg + "\nPattern: " + str(pat)
- if col >= 0:
+ if col is not None:
msg = msg + "\nOffset: " + str(col)
tkMessageBox.showerror("Regular expression error",
msg, master=self.root)
-from tkinter import Frame, Label
+from tkinter.ttk import Label, Frame
class MultiStatusBar(Frame):
def _multistatus_bar(parent): # htest #
- from tkinter import Toplevel, Frame, Text, Button
+ from tkinter import Toplevel, Text
+ from tkinter.ttk import Frame, Button
top = Toplevel(parent)
x, y = map(int, parent.geometry().split('+')[1:])
top.geometry("+%d+%d" %(x, y + 175))
lnum = object.co_firstlineno - 1
pat = re.compile(r'^(\s*def\s)|(\s*async\s+def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)')
while lnum > 0:
- if pat.match(lines[lnum]): break
+ try:
+ line = lines[lnum]
+ except IndexError:
+ raise OSError('lineno is out of bounds')
+ if pat.match(line):
+ break
lnum = lnum - 1
return lines, lnum
raise OSError('could not find code object')
self.indecorator = False
self.decoratorhasargs = False
self.last = 1
+ self.body_col0 = None
def tokeneater(self, type, token, srowcol, erowcol, line):
if not self.started and not self.indecorator:
elif self.passline:
pass
elif type == tokenize.INDENT:
+ if self.body_col0 is None and self.started:
+ self.body_col0 = erowcol[1]
self.indent = self.indent + 1
self.passline = True
elif type == tokenize.DEDENT:
# not e.g. for "if: else:" or "try: finally:" blocks)
if self.indent <= 0:
raise EndOfBlock
+ elif type == tokenize.COMMENT:
+ if self.body_col0 is not None and srowcol[1] >= self.body_col0:
+ # Include comments if indented at least as much as the block
+ self.last = srowcol[0]
elif self.indent == 0 and type not in (tokenize.COMMENT, tokenize.NL):
# any other token on the same indentation level end the previous
# block as well, except the pseudo-tokens COMMENT and NL.
responsible for converting a LogRecord to (usually) a string which can
be interpreted by either a human or an external system. The base Formatter
allows a formatting string to be specified. If none is supplied, the
- the style-dependent default value, "%(message)s", "{message}", or
+ style-dependent default value, "%(message)s", "{message}", or
"${message}", is used.
The Formatter can be initialized with a format string which makes use of
"""
Determine if the specified record is to be logged.
- Is the specified record to be logged? Returns 0 for no, nonzero for
- yes. If deemed appropriate, the record may be modified in-place.
+ Returns True if the record should be logged, or False otherwise.
+ If deemed appropriate, the record may be modified in-place.
"""
if self.nlen == 0:
return True
# Protect the iteration by using a list copy of sys.modules against dynamic
# modules that trigger imports of other modules upon calls to getattr.
for module_name, module in sys.modules.copy().items():
- if module_name == '__main__' or module is None:
+ if (module_name == '__main__'
+ or module_name == '__mp_main__' # bpo-42406
+ or module is None):
continue
try:
if _getattribute(module, name)[0] is obj:
self.parser.StartElementHandler = self.handle_begin_element
self.parser.EndElementHandler = self.handle_end_element
self.parser.CharacterDataHandler = self.handle_data
+ self.parser.EntityDeclHandler = self.handle_entity_decl
self.parser.ParseFile(fileobj)
return self.root
+ def handle_entity_decl(self, entity_name, is_parameter_entity, value, base, system_id, public_id, notation_name):
+ # Reject plist files with entity declarations to avoid XML vulnerabilies in expat.
+ # Regular plist files don't contain those declerations, and Apple's plutil tool does not
+ # accept them either.
+ raise InvalidFileException("XML entity declarations are not supported in plist files")
+
def handle_begin_element(self, element, attrs):
self.data = []
handler = getattr(self, "begin_" + element, None)
self.add_object(False)
def end_integer(self):
- self.add_object(int(self.get_data()))
+ raw = self.get_data()
+ if raw.startswith('0x') or raw.startswith('0X'):
+ self.add_object(int(raw, 16))
+ else:
+ self.add_object(int(raw))
def end_real(self):
self.add_object(float(self.get_data()))
return self._read_object(top_object)
except (OSError, IndexError, struct.error, OverflowError,
- UnicodeDecodeError):
+ ValueError):
raise InvalidFileException()
def _get_size(self, tokenL):
def _read_ints(self, n, size):
data = self._fp.read(size * n)
if size in _BINARY_FORMAT:
- return struct.unpack('>' + _BINARY_FORMAT[size] * n, data)
+ return struct.unpack(f'>{n}{_BINARY_FORMAT[size]}', data)
else:
if not size or len(data) != size * n:
raise InvalidFileException()
elif tokenH == 0x40: # data
s = self._get_size(tokenL)
result = self._fp.read(s)
+ if len(result) != s:
+ raise InvalidFileException()
elif tokenH == 0x50: # ascii string
s = self._get_size(tokenL)
- result = self._fp.read(s).decode('ascii')
+ data = self._fp.read(s)
+ if len(data) != s:
+ raise InvalidFileException()
+ result = data.decode('ascii')
elif tokenH == 0x60: # unicode string
- s = self._get_size(tokenL)
- result = self._fp.read(s * 2).decode('utf-16be')
+ s = self._get_size(tokenL) * 2
+ data = self._fp.read(s)
+ if len(data) != s:
+ raise InvalidFileException()
+ result = data.decode('utf-16be')
elif tokenH == 0x80: # UID
# used by Key-Archiver plist files
obj_refs = self._read_refs(s)
result = self._dict_type()
self._objects[ref] = result
- for k, o in zip(key_refs, obj_refs):
- result[self._read_object(k)] = self._read_object(o)
-
+ try:
+ for k, o in zip(key_refs, obj_refs):
+ result[self._read_object(k)] = self._read_object(o)
+ except TypeError:
+ raise InvalidFileException()
else:
raise InvalidFileException()
elif count < 1 << 16:
return 2
- elif count << 1 << 32:
+ elif count < 1 << 32:
return 4
else:
(options, args) = parser.parse_args()
sys.argv[:] = args
+ # The script that we're profiling may chdir, so capture the absolute path
+ # to the output file at startup.
+ if options.outfile is not None:
+ options.outfile = os.path.abspath(options.outfile)
+
if len(args) > 0:
if options.module:
import runpy
TIME = 'time', 'tottime'
def __new__(cls, *values):
- obj = str.__new__(cls)
-
- obj._value_ = values[0]
+ value = values[0]
+ obj = str.__new__(cls, value)
+ obj._value_ = value
for other_value in values[1:]:
cls._value2member_map_[other_value] = obj
obj._all_values = values
# -*- coding: utf-8 -*-
-# Autogenerated by Sphinx on Sun Oct 4 19:26:28 2020
+# Autogenerated by Sphinx on Mon Dec 7 15:00:07 2020
topics = {'assert': 'The "assert" statement\n'
'**********************\n'
'\n'
'syntax or\n'
' built-in functions. See Special method lookup.\n'
'\n'
+ ' For certain sensitive attribute accesses, raises an '
+ 'auditing event\n'
+ ' "object.__getattr__" with arguments "obj" and '
+ '"name".\n'
+ '\n'
'object.__setattr__(self, name, value)\n'
'\n'
' Called when an attribute assignment is attempted. '
'for example,\n'
' "object.__setattr__(self, name, value)".\n'
'\n'
+ ' For certain sensitive attribute assignments, raises '
+ 'an auditing\n'
+ ' event "object.__setattr__" with arguments "obj", '
+ '"name", "value".\n'
+ '\n'
'object.__delattr__(self, name)\n'
'\n'
' Like "__setattr__()" but for attribute deletion '
'obj.name" is\n'
' meaningful for the object.\n'
'\n'
+ ' For certain sensitive attribute deletions, raises an '
+ 'auditing event\n'
+ ' "object.__delattr__" with arguments "obj" and '
+ '"name".\n'
+ '\n'
'object.__dir__(self)\n'
'\n'
' Called when "dir()" is called on the object. A '
'\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',
+ ' is defined, "x(arg1, arg2, ...)" roughly translates to\n'
+ ' "type(x).__call__(x, arg1, ...)".\n',
'calls': 'Calls\n'
'*****\n'
'\n'
' on the value to determine if the result is true or '
'false.\n'
'\n'
- ' By default, "__ne__()" delegates to "__eq__()" and '
- 'inverts the\n'
- ' result unless it is "NotImplemented". There are no '
- 'other implied\n'
- ' relationships among the comparison operators, for '
- 'example, the\n'
- ' truth of "(x<y or x==y)" does not imply "x<=y". To '
- 'automatically\n'
- ' generate ordering operations from a single root '
- 'operation, see\n'
+ ' By default, "object" implements "__eq__()" by using '
+ '"is", returning\n'
+ ' "NotImplemented" in the case of a false comparison: '
+ '"True if x is y\n'
+ ' else NotImplemented". For "__ne__()", by default it '
+ 'delegates to\n'
+ ' "__eq__()" and inverts the result unless it is '
+ '"NotImplemented".\n'
+ ' There are no other implied relationships among the '
+ 'comparison\n'
+ ' operators or default implementations; for example, the '
+ 'truth of\n'
+ ' "(x<y or x==y)" does not imply "x<=y". To automatically '
+ 'generate\n'
+ ' ordering operations from a single root operation, see\n'
' "functools.total_ordering()".\n'
'\n'
' See the paragraph on "__hash__()" for some important '
'for the\n'
'conversion. The alternate form is defined differently for '
'different\n'
- 'types. This option is only valid for integer, float, '
- 'complex and\n'
- 'Decimal types. For integers, when binary, octal, or '
- 'hexadecimal output\n'
- 'is used, this option adds the prefix respective "\'0b\'", '
- '"\'0o\'", or\n'
- '"\'0x\'" to the output value. For floats, complex and '
- 'Decimal the\n'
- 'alternate form causes the result of the conversion to '
- 'always contain a\n'
- 'decimal-point character, even if no digits follow it. '
- 'Normally, a\n'
- 'decimal-point character appears in the result of these '
- 'conversions\n'
- 'only if a digit follows it. In addition, for "\'g\'" and '
- '"\'G\'"\n'
- 'conversions, trailing zeros are not removed from the '
- 'result.\n'
+ 'types. This option is only valid for integer, float and '
+ 'complex\n'
+ 'types. For integers, when binary, octal, or hexadecimal '
+ 'output is\n'
+ 'used, this option adds the prefix respective "\'0b\'", '
+ '"\'0o\'", or "\'0x\'"\n'
+ 'to the output value. For float and complex the alternate '
+ 'form causes\n'
+ 'the result of the conversion to always contain a '
+ 'decimal-point\n'
+ 'character, even if no digits follow it. Normally, a '
+ 'decimal-point\n'
+ 'character appears in the result of these conversions only '
+ 'if a digit\n'
+ 'follows it. In addition, for "\'g\'" and "\'G\'" '
+ 'conversions, trailing\n'
+ 'zeros are not removed from the result.\n'
'\n'
'The "\',\'" option signals the use of a comma for a '
'thousands separator.\n'
'the integer\n'
'to a floating point number before formatting.\n'
'\n'
- 'The available presentation types for floating point and '
- 'decimal values\n'
- 'are:\n'
+ 'The available presentation types for "float" and "Decimal" '
+ 'values are:\n'
'\n'
' '
'+-----------+------------------------------------------------------------+\n'
'|\n'
' '
'|===========|============================================================|\n'
- ' | "\'e\'" | Exponent notation. Prints the number in '
- 'scientific |\n'
- ' | | notation using the letter ‘e’ to indicate '
- 'the exponent. |\n'
- ' | | The default precision is '
- '"6". |\n'
+ ' | "\'e\'" | Scientific notation. For a given '
+ 'precision "p", formats |\n'
+ ' | | the number in scientific notation with the '
+ 'letter ‘e’ |\n'
+ ' | | separating the coefficient from the '
+ 'exponent. The |\n'
+ ' | | coefficient has one digit before and "p" '
+ 'digits after the |\n'
+ ' | | decimal point, for a total of "p + 1" '
+ 'significant digits. |\n'
+ ' | | With no precision given, uses a precision '
+ 'of "6" digits |\n'
+ ' | | after the decimal point for "float", and '
+ 'shows all |\n'
+ ' | | coefficient digits for "Decimal". If no '
+ 'digits follow the |\n'
+ ' | | decimal point, the decimal point is also '
+ 'removed unless |\n'
+ ' | | the "#" option is '
+ 'used. |\n'
' '
'+-----------+------------------------------------------------------------+\n'
- ' | "\'E\'" | Exponent notation. Same as "\'e\'" '
- 'except it uses an upper |\n'
+ ' | "\'E\'" | Scientific notation. Same as "\'e\'" '
+ 'except it uses an upper |\n'
' | | case ‘E’ as the separator '
'character. |\n'
' '
'+-----------+------------------------------------------------------------+\n'
- ' | "\'f\'" | Fixed-point notation. Displays the '
- 'number as a fixed-point |\n'
- ' | | number. The default precision is '
- '"6". |\n'
+ ' | "\'f\'" | Fixed-point notation. For a given '
+ 'precision "p", formats |\n'
+ ' | | the number as a decimal number with '
+ 'exactly "p" digits |\n'
+ ' | | following the decimal point. With no '
+ 'precision given, uses |\n'
+ ' | | a precision of "6" digits after the '
+ 'decimal point for |\n'
+ ' | | "float", and uses a precision large enough '
+ 'to show all |\n'
+ ' | | coefficient digits for "Decimal". If no '
+ 'digits follow the |\n'
+ ' | | decimal point, the decimal point is also '
+ 'removed unless |\n'
+ ' | | the "#" option is '
+ 'used. |\n'
' '
'+-----------+------------------------------------------------------------+\n'
' | "\'F\'" | Fixed-point notation. Same as "\'f\'", '
' | | regardless of the precision. A precision '
'of "0" is |\n'
' | | treated as equivalent to a precision of '
- '"1". The default |\n'
- ' | | precision is '
- '"6". |\n'
+ '"1". With no |\n'
+ ' | | precision given, uses a precision of "6" '
+ 'significant |\n'
+ ' | | digits for "float", and shows all '
+ 'coefficient digits for |\n'
+ ' | | '
+ '"Decimal". '
+ '|\n'
' '
'+-----------+------------------------------------------------------------+\n'
' | "\'G\'" | General format. Same as "\'g\'" except '
'\n'
'* other future statements.\n'
'\n'
- 'The only feature in Python 3.7 that requires using the future\n'
- 'statement is "annotations".\n'
+ 'The only feature that requires using the future statement is\n'
+ '"annotations" (see **PEP 563**).\n'
'\n'
'All historical features enabled by the future statement are still\n'
'recognized by Python 3. The list includes "absolute_import",\n'
'\n'
' If the right operand’s type is a subclass of the left '
'operand’s\n'
- ' type and that subclass provides the reflected method '
- 'for the\n'
- ' operation, this method will be called before the left '
- 'operand’s\n'
- ' non-reflected method. This behavior allows subclasses '
- 'to\n'
- ' override their ancestors’ operations.\n'
+ ' type and that subclass provides a different '
+ 'implementation of the\n'
+ ' reflected method for the operation, this method will '
+ 'be called\n'
+ ' before the left operand’s non-reflected method. This '
+ 'behavior\n'
+ ' allows subclasses to override their ancestors’ '
+ 'operations.\n'
'\n'
'object.__iadd__(self, other)\n'
'object.__isub__(self, other)\n'
' on the value to determine if the result is true or '
'false.\n'
'\n'
- ' By default, "__ne__()" delegates to "__eq__()" and '
- 'inverts the\n'
- ' result unless it is "NotImplemented". There are no other '
- 'implied\n'
- ' relationships among the comparison operators, for '
- 'example, the\n'
- ' truth of "(x<y or x==y)" does not imply "x<=y". To '
- 'automatically\n'
- ' generate ordering operations from a single root '
- 'operation, see\n'
+ ' By default, "object" implements "__eq__()" by using "is", '
+ 'returning\n'
+ ' "NotImplemented" in the case of a false comparison: "True '
+ 'if x is y\n'
+ ' else NotImplemented". For "__ne__()", by default it '
+ 'delegates to\n'
+ ' "__eq__()" and inverts the result unless it is '
+ '"NotImplemented".\n'
+ ' There are no other implied relationships among the '
+ 'comparison\n'
+ ' operators or default implementations; for example, the '
+ 'truth of\n'
+ ' "(x<y or x==y)" does not imply "x<=y". To automatically '
+ 'generate\n'
+ ' ordering operations from a single root operation, see\n'
' "functools.total_ordering()".\n'
'\n'
' See the paragraph on "__hash__()" for some important '
'syntax or\n'
' built-in functions. See Special method lookup.\n'
'\n'
+ ' For certain sensitive attribute accesses, raises an '
+ 'auditing event\n'
+ ' "object.__getattr__" with arguments "obj" and "name".\n'
+ '\n'
'object.__setattr__(self, name, value)\n'
'\n'
' Called when an attribute assignment is attempted. This '
'example,\n'
' "object.__setattr__(self, name, value)".\n'
'\n'
+ ' For certain sensitive attribute assignments, raises an '
+ 'auditing\n'
+ ' event "object.__setattr__" with arguments "obj", "name", '
+ '"value".\n'
+ '\n'
'object.__delattr__(self, name)\n'
'\n'
' Like "__setattr__()" but for attribute deletion instead '
'obj.name" is\n'
' meaningful for the object.\n'
'\n'
+ ' For certain sensitive attribute deletions, raises an '
+ 'auditing event\n'
+ ' "object.__delattr__" with arguments "obj" and "name".\n'
+ '\n'
'object.__dir__(self)\n'
'\n'
' Called when "dir()" is called on the object. A sequence '
'\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'
+ ' is defined, "x(arg1, arg2, ...)" roughly translates to\n'
+ ' "type(x).__call__(x, arg1, ...)".\n'
'\n'
'\n'
'Emulating container types\n'
'\n'
' If the right operand’s type is a subclass of the left '
'operand’s\n'
- ' type and that subclass provides the reflected method '
- 'for the\n'
- ' operation, this method will be called before the left '
- 'operand’s\n'
- ' non-reflected method. This behavior allows subclasses '
- 'to\n'
- ' override their ancestors’ operations.\n'
+ ' type and that subclass provides a different '
+ 'implementation of the\n'
+ ' reflected method for the operation, this method will be '
+ 'called\n'
+ ' before the left operand’s non-reflected method. This '
+ 'behavior\n'
+ ' allows subclasses to override their ancestors’ '
+ 'operations.\n'
'\n'
'object.__iadd__(self, other)\n'
'object.__isub__(self, other)\n'
'subscriptions': 'Subscriptions\n'
'*************\n'
'\n'
- 'A subscription selects an item of a sequence (string, tuple '
- 'or list)\n'
- 'or mapping (dictionary) object:\n'
+ 'Subscription of a sequence (string, tuple or list) or '
+ 'mapping\n'
+ '(dictionary) object usually selects an item from the '
+ 'collection:\n'
'\n'
' subscription ::= primary "[" expression_list "]"\n'
'\n'
'\n'
'A string’s items are characters. A character is not a '
'separate data\n'
- 'type but a string of exactly one character.\n',
+ 'type but a string of exactly one character.\n'
+ '\n'
+ 'Subscription of certain *classes* or *types* creates a '
+ 'generic alias.\n'
+ 'In this case, user-defined classes can support subscription '
+ 'by\n'
+ 'providing a "__class_getitem__()" classmethod.\n',
'truth': 'Truth Value Testing\n'
'*******************\n'
'\n'
'representation\n'
' in computers.\n'
'\n'
+ ' The string representations of the numeric classes, computed by\n'
+ ' "__repr__()" and "__str__()", have the following properties:\n'
+ '\n'
+ ' * They are valid numeric literals which, when passed to their '
+ 'class\n'
+ ' constructor, produce an object having the value of the '
+ 'original\n'
+ ' numeric.\n'
+ '\n'
+ ' * The representation is in base 10, when possible.\n'
+ '\n'
+ ' * Leading zeros, possibly excepting a single zero before a '
+ 'decimal\n'
+ ' point, are not shown.\n'
+ '\n'
+ ' * Trailing zeros, possibly excepting a single zero after a '
+ 'decimal\n'
+ ' point, are not shown.\n'
+ '\n'
+ ' * A sign is shown only when the number is negative.\n'
+ '\n'
' Python distinguishes between integers, floating point numbers, '
'and\n'
' complex numbers:\n'
'positional\n'
' argument and a possibly empty set of keyword arguments.\n'
'\n'
+ ' Dictionaries can be created by several means:\n'
+ '\n'
+ ' * Use a comma-separated list of "key: value" pairs within '
+ 'braces:\n'
+ ' "{\'jack\': 4098, \'sjoerd\': 4127}" or "{4098: '
+ "'jack', 4127:\n"
+ ' \'sjoerd\'}"\n'
+ '\n'
+ ' * Use a dict comprehension: "{}", "{x: x ** 2 for x in '
+ 'range(10)}"\n'
+ '\n'
+ ' * Use the type constructor: "dict()", "dict([(\'foo\', '
+ "100), ('bar',\n"
+ ' 200)])", "dict(foo=100, bar=200)"\n'
+ '\n'
' If no positional argument is given, an empty dictionary '
'is created.\n'
' If a positional argument is given and it is a mapping '
_USE_CP_SENDFILE = hasattr(os, "sendfile") and sys.platform.startswith("linux")
_HAS_FCOPYFILE = posix and hasattr(posix, "_fcopyfile") # macOS
+# CMD defaults in Windows 10
+_WIN_DEFAULT_PATHEXT = ".COM;.EXE;.BAT;.CMD;.VBS;.JS;.WS;.MSC"
+
__all__ = ["copyfileobj", "copyfile", "copymode", "copystat", "copy", "copy2",
"copytree", "move", "rmtree", "Error", "SpecialFileError",
"ExecError", "make_archive", "get_archive_formats",
try:
fd = os.open(path, os.O_RDONLY)
except Exception:
- onerror(os.lstat, path, sys.exc_info())
+ onerror(os.open, path, sys.exc_info())
return
try:
if os.path.samestat(orig_st, os.fstat(fd)):
path.insert(0, curdir)
# PATHEXT is necessary to check on Windows.
- pathext = os.environ.get("PATHEXT", "").split(os.pathsep)
+ pathext_source = os.getenv("PATHEXT") or _WIN_DEFAULT_PATHEXT
+ pathext = [ext for ext in pathext_source.split(os.pathsep) if ext]
+
if use_bytes:
pathext = [os.fsencode(ext) for ext in pathext]
# See if the given file matches any of the expected path extensions.
# The race condition can still happen if the race condition
# described above happens between the returncode test
# and the kill() call.
- os.kill(self.pid, sig)
+ try:
+ os.kill(self.pid, sig)
+ except ProcessLookupError:
+ # Supress the race condition error; bpo-40550.
+ pass
def terminate(self):
"""Terminate the process with SIGTERM
_newSymbolTable = SymbolTableFactory()
-class SymbolTable(object):
+class SymbolTable:
def __init__(self, raw_table, filename):
self._table = raw_table
else:
kind = "%s " % self.__class__.__name__
- if self._table.name == "global":
+ if self._table.name == "top":
return "<{0}SymbolTable for module {1}>".format(kind, self._filename)
else:
return "<{0}SymbolTable for {1} in {2}>".format(kind,
if sym is None:
flags = self._table.symbols[name]
namespaces = self.__check_children(name)
- sym = self._symbols[name] = Symbol(name, flags, namespaces)
+ module_scope = (self._table.name == "top")
+ sym = self._symbols[name] = Symbol(name, flags, namespaces,
+ module_scope=module_scope)
return sym
def get_symbols(self):
return self.__methods
-class Symbol(object):
+class Symbol:
- def __init__(self, name, flags, namespaces=None):
+ def __init__(self, name, flags, namespaces=None, *, module_scope=False):
self.__name = name
self.__flags = flags
self.__scope = (flags >> SCOPE_OFF) & SCOPE_MASK # like PyST_GetScope()
self.__namespaces = namespaces or ()
+ self.__module_scope = module_scope
def __repr__(self):
return "<symbol {0!r}>".format(self.__name)
return bool(self.__flags & DEF_PARAM)
def is_global(self):
- return bool(self.__scope in (GLOBAL_IMPLICIT, GLOBAL_EXPLICIT))
+ """Return *True* if the sysmbol is global.
+ """
+ return bool(self.__scope in (GLOBAL_IMPLICIT, GLOBAL_EXPLICIT)
+ or (self.__module_scope and self.__flags & DEF_BOUND))
def is_nonlocal(self):
return bool(self.__flags & DEF_NONLOCAL)
return bool(self.__scope == GLOBAL_EXPLICIT)
def is_local(self):
- return bool(self.__scope in (LOCAL, CELL))
+ """Return *True* if the symbol is local.
+ """
+ return bool(self.__scope in (LOCAL, CELL)
+ or (self.__module_scope and self.__flags & DEF_BOUND))
def is_annotated(self):
return bool(self.__flags & DEF_ANNOT)
self.__write(b"\037\213\010\010" + timestamp + b"\002\377")
if self.name.endswith(".gz"):
self.name = self.name[:-3]
+ # Honor "directory components removed" from RFC1952
+ self.name = os.path.basename(self.name)
# RFC1952 says we must use ISO-8859-1 for the FNAME field.
self.__write(self.name.encode("iso-8859-1", "replace") + NUL)
def extractfile(self, member):
"""Extract a member from the archive as a file object. `member' may be
- a filename or a TarInfo object. If `member' is a regular file or a
- link, an io.BufferedReader object is returned. Otherwise, None is
- returned.
+ a filename or a TarInfo object. If `member' is a regular file or
+ a link, an io.BufferedReader object is returned. For all other
+ existing members, None is returned. If `member' does not appear
+ in the archive, KeyError is raised.
"""
self._check("r")
try:
# For systems that support symbolic and hard links.
if tarinfo.issym():
+ if os.path.lexists(targetpath):
+ # Avoid FileExistsError on following os.symlink.
+ os.unlink(targetpath)
os.symlink(tarinfo.linkname, targetpath)
else:
# See extract().
green = pickler.dumps(orig, proto)
derived = unpickler.loads(green)
self.assertEqual(orig, derived)
+ self.assertTrue(isinstance(derived, SubclassDate))
def test_backdoor_resistance(self):
# For fast unpickling, the constructor accepts a pickle byte string.
green = pickler.dumps(orig, proto)
derived = unpickler.loads(green)
self.assertEqual(orig, derived)
+ self.assertTrue(isinstance(derived, SubclassDatetime))
def test_compat_unpickle(self):
tests = [
green = pickler.dumps(orig, proto)
derived = unpickler.loads(green)
self.assertEqual(orig, derived)
+ self.assertTrue(isinstance(derived, SubclassTime))
def test_compat_unpickle(self):
tests = [
custom_method = Callable().as_method_of(42)
del Callable
+
+# line 95
+class WhichComments:
+ # line 97
+ # before f
+ def f(self):
+ # line 100
+ # start f
+ return 1
+ # line 103
+ # end f
+ # line 105
+ # after f
+
+ # before asyncf - line 108
+ async def asyncf(self):
+ # start asyncf
+ return 2
+ # end asyncf
+ # after asyncf - line 113
+ # end of WhichComments - line 114
+ # after WhichComments - line 115
self._test_mapping_file_plain()
def _test_mapping_file_plain(self):
- unichrs = lambda s: ''.join(map(chr, map(eval, s.split('+'))))
+ def unichrs(s):
+ return ''.join(chr(int(x, 16)) for x in s.split('+'))
+
urt_wa = {}
with self.open_mapping_file() as f:
for line in f:
if not line:
break
- data = line.split('#')[0].strip().split()
+ data = line.split('#')[0].split()
if len(data) != 2:
continue
- csetval = eval(data[0])
- if csetval <= 0x7F:
- csetch = bytes([csetval & 0xff])
- elif csetval >= 0x1000000:
- csetch = bytes([(csetval >> 24), ((csetval >> 16) & 0xff),
- ((csetval >> 8) & 0xff), (csetval & 0xff)])
- elif csetval >= 0x10000:
- csetch = bytes([(csetval >> 16), ((csetval >> 8) & 0xff),
- (csetval & 0xff)])
- elif csetval >= 0x100:
- csetch = bytes([(csetval >> 8), (csetval & 0xff)])
- else:
+ if data[0][:2] != '0x':
+ self.fail(f"Invalid line: {line!r}")
+ csetch = bytes.fromhex(data[0][2:])
+ if len(csetch) == 1 and 0x80 <= csetch[0]:
continue
unich = unichrs(data[1])
self.assertEqual(B(x), B(y), detail)
self.assertEqual(x.__dict__, y.__dict__, detail)
+ def test_newobj_overridden_new(self):
+ # Test that Python class with C implemented __new__ is pickleable
+ for proto in protocols:
+ x = MyIntWithNew2(1)
+ x.foo = 42
+ s = self.dumps(x, proto)
+ y = self.loads(s)
+ self.assertIs(type(y), MyIntWithNew2)
+ self.assertEqual(int(y), 1)
+ self.assertEqual(y.foo, 42)
+
def test_newobj_not_class(self):
# Issue 24552
global SimpleNewObj
MyStr, MyUnicode,
MyTuple, MyList, MyDict, MySet, MyFrozenSet]
+class MyIntWithNew(int):
+ def __new__(cls, value):
+ raise AssertionError
+
+class MyIntWithNew2(MyIntWithNew):
+ __new__ = int.__new__
+
class SlotList(MyList):
__slots__ = ["foo"]
'ps_AF': ('\u066b', '\u066c'),
}
+if sys.platform == 'win32':
+ # ps_AF doesn't work on Windows: see bpo-38324 (msg361830)
+ del known_numerics['ps_AF']
+
class _LocaleTests(unittest.TestCase):
def setUp(self):
self.loop.stop()
self.loop.call_later(0.1, callback, 'hello world')
- t0 = time.monotonic()
self.loop.run_forever()
- t1 = time.monotonic()
self.assertEqual(results, ['hello world'])
- self.assertTrue(0.08 <= t1-t0 <= 0.8, t1-t0)
def test_call_soon(self):
results = []
ssl=sslcontext_client,
server_hostname='localhost')
client, pr = self.loop.run_until_complete(f_c)
+ self.loop.run_until_complete(proto.connected)
# close connection
proto.transport.close()
ssl=sslcontext_client,
server_hostname='localhost')
client, pr = self.loop.run_until_complete(f_c)
+ self.loop.run_until_complete(proto.connected)
# extra info is available
self.check_ssl_extra_info(client, peername=(host, port),
--- /dev/null
+# IsolatedAsyncioTestCase based tests
+import asyncio
+import unittest
+
+
+class FutureTests(unittest.IsolatedAsyncioTestCase):
+ async def test_recursive_repr_for_pending_tasks(self):
+ # The call crashes if the guard for recursive call
+ # in base_futures:_future_repr_info is absent
+ # See Also: https://bugs.python.org/issue42183
+
+ async def func():
+ return asyncio.all_tasks()
+
+ # The repr() call should not raise RecursiveError at first.
+ # The check for returned string is not very reliable but
+ # exact comparison for the whole string is even weaker.
+ self.assertIn('...', repr(await asyncio.wait_for(func(), timeout=10)))
def test_readuntil_eof(self):
stream = asyncio.StreamReader(loop=self.loop)
- stream.feed_data(b'some dataAA')
+ data = b'some dataAA'
+ stream.feed_data(data)
stream.feed_eof()
- with self.assertRaises(asyncio.IncompleteReadError) as cm:
+ with self.assertRaisesRegex(asyncio.IncompleteReadError,
+ 'undefined expected bytes') as cm:
self.loop.run_until_complete(stream.readuntil(b'AAA'))
- self.assertEqual(cm.exception.partial, b'some dataAA')
+ self.assertEqual(cm.exception.partial, data)
self.assertIsNone(cm.exception.expected)
self.assertEqual(b'', stream._buffer)
loop.advance_time(10)
loop.run_until_complete(asyncio.wait([a, b]))
+ def test_wait_with_iterator_of_tasks(self):
+
+ def gen():
+ when = yield
+ self.assertAlmostEqual(0.1, when)
+ when = yield 0
+ self.assertAlmostEqual(0.15, when)
+ yield 0.15
+
+ loop = self.new_test_loop(gen)
+
+ a = self.new_task(loop, asyncio.sleep(0.1))
+ b = self.new_task(loop, asyncio.sleep(0.15))
+
+ async def foo():
+ done, pending = await asyncio.wait(iter([b, a]))
+ self.assertEqual(done, set([a, b]))
+ self.assertEqual(pending, set())
+ return 42
+
+ res = loop.run_until_complete(self.new_task(loop, foo()))
+ self.assertEqual(res, 42)
+ self.assertAlmostEqual(0.15, loop.time())
+
def test_as_completed(self):
def gen():
self.assertRaises(binhex.Error, binhex.binhex, self.fname3, self.fname2)
+ def test_binhex_line_endings(self):
+ # bpo-29566: Ensure the line endings are those for macOS 9
+ with open(self.fname1, 'wb') as f:
+ f.write(self.DATA)
+
+ binhex.binhex(self.fname1, self.fname2)
+
+ with open(self.fname2, 'rb') as fp:
+ contents = fp.read()
+
+ self.assertNotIn(b'\n', contents)
+
def test_main():
support.run_unittest(BinHexTestCase)
c_char_p)
PyBytes_FromFormat = pythonapi.PyBytes_FromFormat
+ PyBytes_FromFormat.argtypes = (c_char_p,)
PyBytes_FromFormat.restype = py_object
# basic tests
maxDiff = None
def test_external(self):
+ # bpo-42398: Test that the destination file is left unchanged if the
+ # content does not change. Moreover, check also that the file
+ # modification time does not change in this case.
source = support.findfile('clinic.test')
with open(source, 'r', encoding='utf-8') as f:
- original = f.read()
- with support.temp_dir() as testdir:
- testfile = os.path.join(testdir, 'clinic.test.c')
+ orig_contents = f.read()
+
+ with support.temp_dir() as tmp_dir:
+ testfile = os.path.join(tmp_dir, 'clinic.test.c')
with open(testfile, 'w', encoding='utf-8') as f:
- f.write(original)
- clinic.parse_file(testfile, force=True)
+ f.write(orig_contents)
+ old_mtime_ns = os.stat(testfile).st_mtime_ns
+
+ clinic.parse_file(testfile)
+
with open(testfile, 'r', encoding='utf-8') as f:
- result = f.read()
- self.assertEqual(result, original)
+ new_contents = f.read()
+ new_mtime_ns = os.stat(testfile).st_mtime_ns
+
+ self.assertEqual(new_contents, orig_contents)
+ # Don't change the file modification time
+ # if the content does not change
+ self.assertEqual(new_mtime_ns, old_mtime_ns)
if __name__ == "__main__":
("", len(allbytes))
)
+ self.assertRaisesRegex(TypeError,
+ "character mapping must be in range\\(0x110000\\)",
+ codecs.charmap_decode,
+ b"\x00\x01\x02", "strict", {0: "A", 1: 'Bb', 2: -2}
+ )
+
+ self.assertRaisesRegex(TypeError,
+ "character mapping must be in range\\(0x110000\\)",
+ codecs.charmap_decode,
+ b"\x00\x01\x02", "strict", {0: "A", 1: 'Bb', 2: 999999999}
+ )
+
def test_decode_with_int2int_map(self):
a = ord('a')
b = ord('b')
('e', 55), ('f', 666), ('g', 777), ('h', 88888),
('i', 9999), ('j', 0)])
+ def test_iter_not_calling_getitem_on_maps(self):
+ class DictWithGetItem(UserDict):
+ def __init__(self, *args, **kwds):
+ self.called = False
+ UserDict.__init__(self, *args, **kwds)
+ def __getitem__(self, item):
+ self.called = True
+ UserDict.__getitem__(self, item)
+
+ d = DictWithGetItem(a=1)
+ c = ChainMap(d)
+ d.called = False
+
+ set(c) # iterate over chain map
+ self.assertFalse(d.called, '__getitem__ was called')
+
def test_dict_coercion(self):
d = ChainMap(dict(a=1, b=2), dict(b=20, c=30))
self.assertEqual(dict(d), dict(a=1, b=2, c=30))
# coerce both to a real set then check equality
self.assertSetEqual(set(s1), set(s2))
+ def test_Set_from_iterable(self):
+ """Verify _from_iterable overriden to an instance method works."""
+ class SetUsingInstanceFromIterable(MutableSet):
+ def __init__(self, values, created_by):
+ if not created_by:
+ raise ValueError(f'created_by must be specified')
+ self.created_by = created_by
+ self._values = set(values)
+
+ def _from_iterable(self, values):
+ return type(self)(values, 'from_iterable')
+
+ def __contains__(self, value):
+ return value in self._values
+
+ def __iter__(self):
+ yield from self._values
+
+ def __len__(self):
+ return len(self._values)
+
+ def add(self, value):
+ self._values.add(value)
+
+ def discard(self, value):
+ self._values.discard(value)
+
+ impl = SetUsingInstanceFromIterable([1, 2, 3], 'test')
+
+ actual = impl - {1}
+ self.assertIsInstance(actual, SetUsingInstanceFromIterable)
+ self.assertEqual('from_iterable', actual.created_by)
+ self.assertEqual({2, 3}, actual)
+
+ actual = impl | {4}
+ self.assertIsInstance(actual, SetUsingInstanceFromIterable)
+ self.assertEqual('from_iterable', actual.created_by)
+ self.assertEqual({1, 2, 3, 4}, actual)
+
+ actual = impl & {2}
+ self.assertIsInstance(actual, SetUsingInstanceFromIterable)
+ self.assertEqual('from_iterable', actual.created_by)
+ self.assertEqual({2}, actual)
+
+ actual = impl ^ {3, 4}
+ self.assertIsInstance(actual, SetUsingInstanceFromIterable)
+ self.assertEqual('from_iterable', actual.created_by)
+ self.assertEqual({1, 2, 4}, actual)
+
+ # NOTE: ixor'ing with a list is important here: internally, __ixor__
+ # only calls _from_iterable if the other value isn't already a Set.
+ impl ^= [3, 4]
+ self.assertIsInstance(impl, SetUsingInstanceFromIterable)
+ self.assertEqual('test', impl.created_by)
+ self.assertEqual({1, 2, 4}, impl)
+
def test_Set_interoperability_with_real_sets(self):
# Issue: 8743
class ListSet(Set):
g.flatten(msg)
self.assertEqual(fullrepr, s.getvalue())
+ def test_nonascii_as_string_without_cte(self):
+ m = textwrap.dedent("""\
+ MIME-Version: 1.0
+ Content-type: text/plain; charset="iso-8859-1"
+
+ Test if non-ascii messages with no Content-Transfer-Encoding set
+ can be as_string'd:
+ Föö bär
+ """)
+ source = m.encode('iso-8859-1')
+ expected = textwrap.dedent("""\
+ MIME-Version: 1.0
+ Content-type: text/plain; charset="iso-8859-1"
+ Content-Transfer-Encoding: quoted-printable
+
+ Test if non-ascii messages with no Content-Transfer-Encoding set
+ can be as_string'd:
+ F=F6=F6 b=E4r
+ """)
+ msg = email.message_from_bytes(source)
+ self.assertEqual(msg.as_string(), expected)
+
+ def test_nonascii_as_string_without_content_type_and_cte(self):
+ m = textwrap.dedent("""\
+ MIME-Version: 1.0
+
+ Test if non-ascii messages with no Content-Type nor
+ Content-Transfer-Encoding set can be as_string'd:
+ Föö bär
+ """)
+ source = m.encode('iso-8859-1')
+ expected = source.decode('ascii', 'replace')
+ msg = email.message_from_bytes(source)
+ self.assertEqual(msg.as_string(), expected)
+
def test_as_bytes(self):
msg = self._msgobj('msg_01.txt')
with openfile('msg_01.txt') as fp:
check(b'Python = "\xcf\xb3\xf2\xee\xed" +', 1, 18)
check('x = "a', 1, 7)
check('lambda x: x = 2', 1, 1)
+ check('f{a + b + c}', 1, 2)
# Errors thrown by compile.c
check('class foo:return 1', 1, 11)
raise TypeError('requires _testcapi.with_tp_del')
return C
+try:
+ from _testcapi import without_gc
+except ImportError:
+ def without_gc(cls):
+ class C:
+ def __new__(cls, *args, **kwargs):
+ raise TypeError('requires _testcapi.without_gc')
+ return C
+
from test import support
assert self.id_ == id(self)
+@without_gc
class NonGC(NonGCSimpleBase):
__slots__ = ()
+@without_gc
class NonGCResurrector(NonGCSimpleBase):
__slots__ = ()
class Simple(SimpleBase):
pass
-class SimpleResurrector(NonGCResurrector, SimpleBase):
- pass
+# Can't inherit from NonGCResurrector, in case importing without_gc fails.
+class SimpleResurrector(SimpleBase):
+
+ def side_effect(self):
+ """
+ Resurrect self by storing self in a class-wide list.
+ """
+ self.survivors.append(self)
class TestBase:
self.assert_survivors([])
self.assertIs(wr(), None)
+ @support.cpython_only
def test_non_gc(self):
with SimpleBase.test():
s = NonGC()
self.assert_del_calls(ids)
self.assert_survivors([])
+ @support.cpython_only
def test_non_gc_resurrect(self):
with SimpleBase.test():
s = NonGCResurrector()
localeconv = locale.localeconv()
sep = localeconv['thousands_sep']
point = localeconv['decimal_point']
+ grouping = localeconv['grouping']
text = format(123456789, "n")
- self.assertIn(sep, text)
+ if grouping:
+ self.assertIn(sep, text)
self.assertEqual(text.replace(sep, ''), '123456789')
text = format(1234.5, "n")
- self.assertIn(sep, text)
+ if grouping:
+ self.assertIn(sep, text)
self.assertIn(point, text)
self.assertEqual(text.replace(sep, ''), '1234' + point + '5')
finally:
self.assertTrue(gc.is_tracked(UserInt()))
self.assertTrue(gc.is_tracked([]))
self.assertTrue(gc.is_tracked(set()))
- self.assertFalse(gc.is_tracked(UserClassSlots()))
- self.assertFalse(gc.is_tracked(UserFloatSlots()))
- self.assertFalse(gc.is_tracked(UserIntSlots()))
+ self.assertTrue(gc.is_tracked(UserClassSlots()))
+ self.assertTrue(gc.is_tracked(UserFloatSlots()))
+ self.assertTrue(gc.is_tracked(UserIntSlots()))
def test_is_finalized(self):
# Objects not tracked by the always gc return false
"embedding. Saw %s.%s:\n%s"
% (gdb_major_version, gdb_minor_version,
gdb_version))
-if (gdb_major_version, gdb_minor_version) >= (9, 2):
- # gdb 9.2 on Fedora Rawhide is not reliable, see:
- # * https://bugs.python.org/issue41473
- # * https://bugzilla.redhat.com/show_bug.cgi?id=1866884
- raise unittest.SkipTest("https://bugzilla.redhat.com/show_bug.cgi?id=1866884")
if not sysconfig.is_python_build():
raise unittest.SkipTest("test_gdb only works on source builds at the moment.")
from dataclasses import Field
from functools import partial, partialmethod, cached_property
from mailbox import Mailbox, _PartialFile
-from ctypes import Array, LibraryLoader
+try:
+ import ctypes
+except ImportError:
+ ctypes = None
from difflib import SequenceMatcher
from filecmp import dircmp
from fileinput import FileInput
except ImportError:
# multiprocessing.shared_memory is not available on e.g. Android
ShareableList = None
-from multiprocessing.queues import SimpleQueue
+from multiprocessing.queues import SimpleQueue as MPSimpleQueue
from os import DirEntry
from re import Pattern, Match
from types import GenericAlias, MappingProxyType, AsyncGeneratorType
class BaseTest(unittest.TestCase):
"""Test basics."""
+ generic_types = [type, tuple, list, dict, set, frozenset, enumerate,
+ defaultdict, deque,
+ SequenceMatcher,
+ dircmp,
+ FileInput,
+ OrderedDict, Counter, UserDict, UserList,
+ Pattern, Match,
+ partial, partialmethod, cached_property,
+ AbstractContextManager, AbstractAsyncContextManager,
+ Awaitable, Coroutine,
+ AsyncIterable, AsyncIterator,
+ AsyncGenerator, Generator,
+ Iterable, Iterator,
+ Reversible,
+ Container, Collection,
+ Callable,
+ Mailbox, _PartialFile,
+ ContextVar, Token,
+ Field,
+ Set, MutableSet,
+ Mapping, MutableMapping, MappingView,
+ KeysView, ItemsView, ValuesView,
+ Sequence, MutableSequence,
+ MappingProxyType, AsyncGeneratorType,
+ DirEntry,
+ chain,
+ TemporaryDirectory, SpooledTemporaryFile,
+ Queue, SimpleQueue,
+ _AssertRaisesContext,
+ SplitResult, ParseResult,
+ ValueProxy, ApplyResult,
+ WeakSet, ReferenceType, ref,
+ ShareableList, MPSimpleQueue,
+ Future, _WorkItem,
+ Morsel]
+ if ctypes is not None:
+ generic_types.extend((ctypes.Array, ctypes.LibraryLoader))
def test_subscriptable(self):
- for t in (type, tuple, list, dict, set, frozenset, enumerate,
- defaultdict, deque,
- SequenceMatcher,
- dircmp,
- FileInput,
- OrderedDict, Counter, UserDict, UserList,
- Pattern, Match,
- partial, partialmethod, cached_property,
- AbstractContextManager, AbstractAsyncContextManager,
- Awaitable, Coroutine,
- AsyncIterable, AsyncIterator,
- AsyncGenerator, Generator,
- Iterable, Iterator,
- Reversible,
- Container, Collection,
- Callable,
- Mailbox, _PartialFile,
- ContextVar, Token,
- Field,
- Set, MutableSet,
- Mapping, MutableMapping, MappingView,
- KeysView, ItemsView, ValuesView,
- Sequence, MutableSequence,
- MappingProxyType, AsyncGeneratorType,
- DirEntry,
- chain,
- TemporaryDirectory, SpooledTemporaryFile,
- Queue, SimpleQueue,
- _AssertRaisesContext,
- Array, LibraryLoader,
- SplitResult, ParseResult,
- ValueProxy, ApplyResult,
- WeakSet, ReferenceType, ref,
- ShareableList, SimpleQueue,
- Future, _WorkItem,
- Morsel,
- ):
+ for t in self.generic_types:
if t is None:
continue
tname = t.__name__
for generic_alias_property in ("__origin__", "__args__", "__parameters__"):
self.assertIn(generic_alias_property, dir_of_gen_alias)
+ def test_weakref(self):
+ for t in self.generic_types:
+ if t is None:
+ continue
+ tname = t.__name__
+ with self.subTest(f"Testing {tname}"):
+ alias = t[int]
+ self.assertEqual(ref(alias)(), alias)
+
+ def test_no_kwargs(self):
+ # bpo-42576
+ with self.assertRaises(TypeError):
+ GenericAlias(bad=float)
+
+
if __name__ == "__main__":
unittest.main()
# Were we compiled --with-pydebug or with #define Py_DEBUG?
COMPILED_WITH_PYDEBUG = hasattr(sys, 'gettotalrefcount')
-c_hashlib = import_fresh_module('hashlib', fresh=['_hashlib'])
-py_hashlib = import_fresh_module('hashlib', blocked=['_hashlib'])
-
+# default builtin hash module
+default_builtin_hashes = {'md5', 'sha1', 'sha256', 'sha512', 'sha3', 'blake2'}
+# --with-builtin-hashlib-hashes override
builtin_hashes = sysconfig.get_config_var("PY_BUILTIN_HASHLIB_HASHES")
if builtin_hashes is None:
- builtin_hashes = {'md5', 'sha1', 'sha256', 'sha512', 'sha3', 'blake2'}
+ builtin_hashes = default_builtin_hashes
else:
builtin_hashes = {
m.strip() for m in builtin_hashes.strip('"').lower().split(",")
}
+# hashlib with and without OpenSSL backend for PBKDF2
+# only import builtin_hashlib when all builtin hashes are available.
+# Otherwise import prints noise on stderr
+openssl_hashlib = import_fresh_module('hashlib', fresh=['_hashlib'])
+if builtin_hashes == default_builtin_hashes:
+ builtin_hashlib = import_fresh_module('hashlib', blocked=['_hashlib'])
+else:
+ builtin_hashlib = None
+
try:
from _hashlib import HASH, HASHXOF, openssl_md_meth_names
except ImportError:
iterations=1, dklen=None)
self.assertEqual(out, self.pbkdf2_results['sha1'][0][0])
+ @unittest.skipIf(builtin_hashlib is None, "test requires builtin_hashlib")
def test_pbkdf2_hmac_py(self):
- self._test_pbkdf2_hmac(py_hashlib.pbkdf2_hmac, builtin_hashes)
+ self._test_pbkdf2_hmac(builtin_hashlib.pbkdf2_hmac, builtin_hashes)
- @unittest.skipUnless(hasattr(c_hashlib, 'pbkdf2_hmac'),
+ @unittest.skipUnless(hasattr(openssl_hashlib, 'pbkdf2_hmac'),
' test requires OpenSSL > 1.0')
def test_pbkdf2_hmac_c(self):
- self._test_pbkdf2_hmac(c_hashlib.pbkdf2_hmac, openssl_md_meth_names)
-
+ self._test_pbkdf2_hmac(openssl_hashlib.pbkdf2_hmac, openssl_md_meth_names)
- @unittest.skipUnless(hasattr(c_hashlib, 'scrypt'),
+ @unittest.skipUnless(hasattr(hashlib, 'scrypt'),
' test requires OpenSSL > 1.1')
def test_scrypt(self):
for password, salt, n, r, p, expected in self.scrypt_test_vectors:
Written by Cody A.W. Somerville <cody-somerville@ubuntu.com>,
Josip Dzolonga, and Michael Otteneder for the 2007/08 GHOP contest.
"""
-
+from collections import OrderedDict
from http.server import BaseHTTPRequestHandler, HTTPServer, \
SimpleHTTPRequestHandler, CGIHTTPRequestHandler
from http import server, HTTPStatus
import email.message
import email.utils
import html
-import http.client
+import http, http.client
import urllib.parse
import tempfile
import time
print(os.environ["%s"])
"""
+cgi_file6 = """\
+#!%s
+import os
+
+print("Content-type: text/plain")
+print()
+print(repr(os.environ))
+"""
+
@unittest.skipIf(hasattr(os, 'geteuid') and os.geteuid() == 0,
"This test can't be run reliably as root (issue #13308).")
file5.write(cgi_file1 % self.pythonexe)
os.chmod(self.file5_path, 0o777)
+ self.file6_path = os.path.join(self.cgi_dir, 'file6.py')
+ with open(self.file6_path, 'w', encoding='utf-8') as file6:
+ file6.write(cgi_file6 % self.pythonexe)
+ os.chmod(self.file6_path, 0o777)
+
os.chdir(self.parent_dir)
def tearDown(self):
os.remove(self.file4_path)
if self.file5_path:
os.remove(self.file5_path)
+ if self.file6_path:
+ os.remove(self.file6_path)
os.rmdir(self.cgi_child_dir)
os.rmdir(self.cgi_dir)
os.rmdir(self.cgi_dir_in_sub_dir)
finally:
CGIHTTPRequestHandler.cgi_directories.remove('/sub/dir/cgi-bin')
+ def test_accept(self):
+ browser_accept = \
+ 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'
+ tests = (
+ ((('Accept', browser_accept),), browser_accept),
+ ((), ''),
+ # Hack case to get two values for the one header
+ ((('Accept', 'text/html'), ('ACCEPT', 'text/plain')),
+ 'text/html,text/plain'),
+ )
+ for headers, expected in tests:
+ headers = OrderedDict(headers)
+ with self.subTest(headers):
+ res = self.request('/cgi-bin/file6.py', 'GET', headers=headers)
+ self.assertEqual(http.HTTPStatus.OK, res.status)
+ expected = f"'HTTP_ACCEPT': {expected!r}"
+ self.assertIn(expected.encode('ascii'), res.read())
class SocketlessRequestHandler(SimpleHTTPRequestHandler):
('ParrotDroppings', mod.ParrotDroppings),
('StupidGit', mod.StupidGit),
('Tit', mod.MalodorousPervert),
+ ('WhichComments', mod.WhichComments),
])
tree = inspect.getclasstree([cls[1] for cls in classes])
self.assertEqual(tree,
[(mod.FesteringGob, (mod.MalodorousPervert,
mod.ParrotDroppings))
]
- ]
+ ],
+ (mod.WhichComments, (object,),)
]
])
tree = inspect.getclasstree([cls[1] for cls in classes], True)
[(mod.FesteringGob, (mod.MalodorousPervert,
mod.ParrotDroppings))
]
- ]
+ ],
+ (mod.WhichComments, (object,),)
]
])
# as argument to another function.
self.assertSourceEqual(mod2.anonymous, 55, 55)
+class TestBlockComments(GetSourceBase):
+ fodderModule = mod
+
+ def test_toplevel_class(self):
+ self.assertSourceEqual(mod.WhichComments, 96, 114)
+
+ def test_class_method(self):
+ self.assertSourceEqual(mod.WhichComments.f, 99, 104)
+
+ def test_class_async_method(self):
+ self.assertSourceEqual(mod.WhichComments.asyncf, 109, 112)
+
class TestBuggyCases(GetSourceBase):
fodderModule = mod2
self.assertRaises(IOError, inspect.findsource, co)
self.assertRaises(IOError, inspect.getsource, co)
+ def test_findsource_with_out_of_bounds_lineno(self):
+ mod_len = len(inspect.getsource(mod))
+ src = '\n' * 2* mod_len + "def f(): pass"
+ co = compile(src, mod.__file__, "exec")
+ g, l = {}, {}
+ eval(co, g, l)
+ func = l['f']
+ self.assertEqual(func.__code__.co_firstlineno, 1+2*mod_len)
+ with self.assertRaisesRegex(IOError, "lineno is out of bounds"):
+ inspect.findsource(func)
+
def test_getsource_on_method(self):
self.assertSourceEqual(mod2.ClassWithMethod.method, 118, 119)
def test_main():
run_unittest(
- TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBuggyCases,
- TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
+ TestDecorators, TestRetrievingSourceCode, TestOneliners, TestBlockComments,
+ TestBuggyCases, TestInterpreterStack, TestClassesAndFunctions, TestPredicates,
TestGetcallargsFunctions, TestGetcallargsMethods,
TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState,
TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject,
self.assertEqual(True, issubclass(B(), int))
+ def test_infinite_recursion_in_bases(self):
+ class X:
+ @property
+ def __bases__(self):
+ return self.__bases__
+
+ self.assertRaises(RecursionError, issubclass, X(), int)
+ self.assertRaises(RecursionError, issubclass, int, X())
+ self.assertRaises(RecursionError, isinstance, 1, X())
+
def blowstack(fxn, arg, compare_to):
# Make sure that calling isinstance with a deeply nested tuple for its
... "Count how many times the predicate is true"
... return sum(map(pred, iterable))
->>> def padnone(iterable):
+>>> def pad_none(iterable):
... "Returns the sequence elements and then returns None indefinitely"
... return chain(iterable, repeat(None))
>>> list(pairwise('a'))
[]
->>> list(islice(padnone('abc'), 0, 6))
+>>> list(islice(pad_none('abc'), 0, 6))
['a', 'b', 'c', None, None, None]
>>> list(ncycles('abc', 3))
import unittest
-from test.support import check_warnings
+from test.support import check_warnings, import_fresh_module
with check_warnings(("", PendingDeprecationWarning)):
- from lib2to3.tests import load_tests
+ load_tests = import_fresh_module('lib2to3.tests', fresh=['lib2to3']).load_tests
if __name__ == '__main__':
unittest.main()
class MockRaceConditionHandler:
def __init__(self, mem_hdlr):
self.mem_hdlr = mem_hdlr
+ self.threads = []
def removeTarget(self):
self.mem_hdlr.setTarget(None)
def handle(self, msg):
- t = threading.Thread(target=self.removeTarget)
- t.daemon = True
- t.start()
+ thread = threading.Thread(target=self.removeTarget)
+ self.threads.append(thread)
+ thread.start()
target = MockRaceConditionHandler(self.mem_hdlr)
- self.mem_hdlr.setTarget(target)
+ try:
+ self.mem_hdlr.setTarget(target)
- for _ in range(10):
- time.sleep(0.005)
- self.mem_logger.info("not flushed")
- self.mem_logger.warning("flushed")
+ for _ in range(10):
+ time.sleep(0.005)
+ self.mem_logger.info("not flushed")
+ self.mem_logger.warning("flushed")
+ finally:
+ for thread in target.threads:
+ support.join_thread(thread)
class ExceptionFormatter(logging.Formatter):
"assignment expression within a comprehension cannot be used in a class body"):
exec(code, {}, {})
- def test_named_expression_invalid_rebinding_comprehension_iteration_variable(self):
+ def test_named_expression_invalid_rebinding_list_comprehension_iteration_variable(self):
cases = [
("Local reuse", 'i', "[i := 0 for i in range(5)]"),
("Nested reuse", 'j', "[[(j := 0) for i in range(5)] for j in range(5)]"),
with self.assertRaisesRegex(SyntaxError, msg):
exec(code, {}, {})
- def test_named_expression_invalid_rebinding_comprehension_inner_loop(self):
+ def test_named_expression_invalid_rebinding_list_comprehension_inner_loop(self):
cases = [
("Inner reuse", 'j', "[i for i in range(5) if (j := 0) for j in range(5)]"),
("Inner unpacking reuse", 'j', "[i for i in range(5) if (j := 0) for j, k in [(0, 1)]]"),
with self.assertRaisesRegex(SyntaxError, msg):
exec(f"lambda: {code}", {}) # Function scope
- def test_named_expression_invalid_comprehension_iterable_expression(self):
+ def test_named_expression_invalid_list_comprehension_iterable_expression(self):
cases = [
("Top level", "[i for i in (i := range(5))]"),
("Inside tuple", "[i for i in (2, 3, i := range(5))]"),
with self.assertRaisesRegex(SyntaxError, msg):
exec(f"lambda: {code}", {}) # Function scope
+ def test_named_expression_invalid_rebinding_set_comprehension_iteration_variable(self):
+ cases = [
+ ("Local reuse", 'i', "{i := 0 for i in range(5)}"),
+ ("Nested reuse", 'j', "{{(j := 0) for i in range(5)} for j in range(5)}"),
+ ("Reuse inner loop target", 'j', "{(j := 0) for i in range(5) for j in range(5)}"),
+ ("Unpacking reuse", 'i', "{i := 0 for i, j in {(0, 1)}}"),
+ ("Reuse in loop condition", 'i', "{i+1 for i in range(5) if (i := 0)}"),
+ ("Unreachable reuse", 'i', "{False or (i:=0) for i in range(5)}"),
+ ("Unreachable nested reuse", 'i',
+ "{(i, j) for i in range(5) for j in range(5) if True or (i:=10)}"),
+ ]
+ for case, target, code in cases:
+ msg = f"assignment expression cannot rebind comprehension iteration variable '{target}'"
+ with self.subTest(case=case):
+ with self.assertRaisesRegex(SyntaxError, msg):
+ exec(code, {}, {})
+
+ def test_named_expression_invalid_rebinding_set_comprehension_inner_loop(self):
+ cases = [
+ ("Inner reuse", 'j', "{i for i in range(5) if (j := 0) for j in range(5)}"),
+ ("Inner unpacking reuse", 'j', "{i for i in range(5) if (j := 0) for j, k in {(0, 1)}}"),
+ ]
+ for case, target, code in cases:
+ msg = f"comprehension inner loop cannot rebind assignment expression target '{target}'"
+ with self.subTest(case=case):
+ with self.assertRaisesRegex(SyntaxError, msg):
+ exec(code, {}) # Module scope
+ with self.assertRaisesRegex(SyntaxError, msg):
+ exec(code, {}, {}) # Class scope
+ with self.assertRaisesRegex(SyntaxError, msg):
+ exec(f"lambda: {code}", {}) # Function scope
+
+ def test_named_expression_invalid_set_comprehension_iterable_expression(self):
+ cases = [
+ ("Top level", "{i for i in (i := range(5))}"),
+ ("Inside tuple", "{i for i in (2, 3, i := range(5))}"),
+ ("Inside list", "{i for i in {2, 3, i := range(5)}}"),
+ ("Different name", "{i for i in (j := range(5))}"),
+ ("Lambda expression", "{i for i in (lambda:(j := range(5)))()}"),
+ ("Inner loop", "{i for i in range(5) for j in (i := range(5))}"),
+ ("Nested comprehension", "{i for i in {j for j in (k := range(5))}}"),
+ ("Nested comprehension condition", "{i for i in {j for j in range(5) if (j := True)}}"),
+ ("Nested comprehension body", "{i for i in {(j := True) for j in range(5)}}"),
+ ]
+ msg = "assignment expression cannot be used in a comprehension iterable expression"
+ for case, code in cases:
+ with self.subTest(case=case):
+ with self.assertRaisesRegex(SyntaxError, msg):
+ exec(code, {}) # Module scope
+ with self.assertRaisesRegex(SyntaxError, msg):
+ exec(code, {}, {}) # Class scope
+ with self.assertRaisesRegex(SyntaxError, msg):
+ exec(f"lambda: {code}", {}) # Function scope
+
class NamedExpressionAssignmentTest(unittest.TestCase):
self.assertEqual(nonlocal_var, None)
f()
+ def test_named_expression_scope_in_genexp(self):
+ a = 1
+ b = [1, 2, 3, 4]
+ genexp = (c := i + a for i in b)
+
+ self.assertNotIn("c", locals())
+ for idx, elem in enumerate(genexp):
+ self.assertEqual(elem, b[idx] + a)
+
if __name__ == "__main__":
unittest.main()
with self.assertRaises(ValueError):
f()
+ def test_bpo_42057(self):
+ for i in range(10):
+ try:
+ raise Exception
+ except Exception or Exception:
+ pass
+
if __name__ == "__main__":
unittest.main()
+import sysconfig
import textwrap
import unittest
from distutils.tests.support import TempdirManager
from test import support
from test.support.script_helper import assert_python_ok
+_py_cflags_nodist = sysconfig.get_config_var('PY_CFLAGS_NODIST')
+_pgo_flag = sysconfig.get_config_var('PGO_PROF_USE_FLAG')
+if _pgo_flag and _py_cflags_nodist and _pgo_flag in _py_cflags_nodist:
+ raise unittest.SkipTest("peg_generator test disabled under PGO build")
+
test_tools.skip_if_missing("peg_generator")
with test_tools.imports_under_tool("peg_generator"):
from pegen.grammar_parser import GeneratedParser as GrammarParser
# On Snow Leopard, sw_vers reports 10.6.0 as 10.6
if len_diff > 0:
expect_list.extend(['0'] * len_diff)
- self.assertEqual(result_list, expect_list)
+ # For compatibility with older binaries, macOS 11.x may report
+ # itself as '10.16' rather than '11.x.y'.
+ if result_list != ['10', '16']:
+ self.assertEqual(result_list, expect_list)
# res[1] claims to contain
# (version, dev_stage, non_release_version)
self.assertEqual(res[1], ('', '', ''))
if sys.byteorder == 'little':
- self.assertIn(res[2], ('i386', 'x86_64'))
+ self.assertIn(res[2], ('i386', 'x86_64', 'arm64'))
else:
self.assertEqual(res[2], 'PowerPC')
import copy
import operator
import pickle
+import struct
import unittest
import plistlib
import os
AAABOQ=='''),
}
+XML_PLIST_WITH_ENTITY=b'''\
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd" [
+ <!ENTITY entity "replacement text">
+ ]>
+<plist version="1.0">
+ <dict>
+ <key>A</key>
+ <string>&entity;</string>
+ </dict>
+</plist>
+'''
+
+INVALID_BINARY_PLISTS = [
+ ('too short data',
+ b''
+ ),
+ ('too large offset_table_offset and offset_size = 1',
+ b'\x00\x08'
+ b'\x00\x00\x00\x00\x00\x00\x01\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x00'
+ b'\x00\x00\x00\x00\x00\x00\x00\x2a'
+ ),
+ ('too large offset_table_offset and nonstandard offset_size',
+ b'\x00\x00\x00\x08'
+ b'\x00\x00\x00\x00\x00\x00\x03\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x00'
+ b'\x00\x00\x00\x00\x00\x00\x00\x2c'
+ ),
+ ('integer overflow in offset_table_offset',
+ b'\x00\x08'
+ b'\x00\x00\x00\x00\x00\x00\x01\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x00'
+ b'\xff\xff\xff\xff\xff\xff\xff\xff'
+ ),
+ ('too large top_object',
+ b'\x00\x08'
+ b'\x00\x00\x00\x00\x00\x00\x01\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x09'
+ ),
+ ('integer overflow in top_object',
+ b'\x00\x08'
+ b'\x00\x00\x00\x00\x00\x00\x01\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x01'
+ b'\xff\xff\xff\xff\xff\xff\xff\xff'
+ b'\x00\x00\x00\x00\x00\x00\x00\x09'
+ ),
+ ('too large num_objects and offset_size = 1',
+ b'\x00\x08'
+ b'\x00\x00\x00\x00\x00\x00\x01\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\xff'
+ b'\x00\x00\x00\x00\x00\x00\x00\x00'
+ b'\x00\x00\x00\x00\x00\x00\x00\x09'
+ ),
+ ('too large num_objects and nonstandard offset_size',
+ b'\x00\x00\x00\x08'
+ b'\x00\x00\x00\x00\x00\x00\x03\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\xff'
+ b'\x00\x00\x00\x00\x00\x00\x00\x00'
+ b'\x00\x00\x00\x00\x00\x00\x00\x09'
+ ),
+ ('extremally large num_objects (32 bit)',
+ b'\x00\x08'
+ b'\x00\x00\x00\x00\x00\x00\x01\x01'
+ b'\x00\x00\x00\x00\x7f\xff\xff\xff'
+ b'\x00\x00\x00\x00\x00\x00\x00\x00'
+ b'\x00\x00\x00\x00\x00\x00\x00\x09'
+ ),
+ ('extremally large num_objects (64 bit)',
+ b'\x00\x08'
+ b'\x00\x00\x00\x00\x00\x00\x01\x01'
+ b'\x00\x00\x00\xff\xff\xff\xff\xff'
+ b'\x00\x00\x00\x00\x00\x00\x00\x00'
+ b'\x00\x00\x00\x00\x00\x00\x00\x09'
+ ),
+ ('integer overflow in num_objects',
+ b'\x00\x08'
+ b'\x00\x00\x00\x00\x00\x00\x01\x01'
+ b'\xff\xff\xff\xff\xff\xff\xff\xff'
+ b'\x00\x00\x00\x00\x00\x00\x00\x00'
+ b'\x00\x00\x00\x00\x00\x00\x00\x09'
+ ),
+ ('offset_size = 0',
+ b'\x00\x08'
+ b'\x00\x00\x00\x00\x00\x00\x00\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x00'
+ b'\x00\x00\x00\x00\x00\x00\x00\x09'
+ ),
+ ('ref_size = 0',
+ b'\xa1\x01\x00\x08\x0a'
+ b'\x00\x00\x00\x00\x00\x00\x01\x00'
+ b'\x00\x00\x00\x00\x00\x00\x00\x02'
+ b'\x00\x00\x00\x00\x00\x00\x00\x00'
+ b'\x00\x00\x00\x00\x00\x00\x00\x0b'
+ ),
+ ('too large offset',
+ b'\x00\x2a'
+ b'\x00\x00\x00\x00\x00\x00\x01\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x00'
+ b'\x00\x00\x00\x00\x00\x00\x00\x09'
+ ),
+ ('integer overflow in offset',
+ b'\x00\xff\xff\xff\xff\xff\xff\xff\xff'
+ b'\x00\x00\x00\x00\x00\x00\x08\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x00'
+ b'\x00\x00\x00\x00\x00\x00\x00\x09'
+ ),
+ ('too large array size',
+ b'\xaf\x00\x01\xff\x00\x08\x0c'
+ b'\x00\x00\x00\x00\x00\x00\x01\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x02'
+ b'\x00\x00\x00\x00\x00\x00\x00\x00'
+ b'\x00\x00\x00\x00\x00\x00\x00\x0d'
+ ),
+ ('extremally large array size (32-bit)',
+ b'\xaf\x02\x7f\xff\xff\xff\x01\x00\x08\x0f'
+ b'\x00\x00\x00\x00\x00\x00\x01\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x02'
+ b'\x00\x00\x00\x00\x00\x00\x00\x00'
+ b'\x00\x00\x00\x00\x00\x00\x00\x10'
+ ),
+ ('extremally large array size (64-bit)',
+ b'\xaf\x03\x00\x00\x00\xff\xff\xff\xff\xff\x01\x00\x08\x13'
+ b'\x00\x00\x00\x00\x00\x00\x01\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x02'
+ b'\x00\x00\x00\x00\x00\x00\x00\x00'
+ b'\x00\x00\x00\x00\x00\x00\x00\x14'
+ ),
+ ('integer overflow in array size',
+ b'\xaf\x03\xff\xff\xff\xff\xff\xff\xff\xff\x01\x00\x08\x13'
+ b'\x00\x00\x00\x00\x00\x00\x01\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x02'
+ b'\x00\x00\x00\x00\x00\x00\x00\x00'
+ b'\x00\x00\x00\x00\x00\x00\x00\x14'
+ ),
+ ('too large reference index',
+ b'\xa1\x02\x00\x08\x0a'
+ b'\x00\x00\x00\x00\x00\x00\x01\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x02'
+ b'\x00\x00\x00\x00\x00\x00\x00\x00'
+ b'\x00\x00\x00\x00\x00\x00\x00\x0b'
+ ),
+ ('integer overflow in reference index',
+ b'\xa1\xff\xff\xff\xff\xff\xff\xff\xff\x00\x08\x11'
+ b'\x00\x00\x00\x00\x00\x00\x01\x08'
+ b'\x00\x00\x00\x00\x00\x00\x00\x02'
+ b'\x00\x00\x00\x00\x00\x00\x00\x00'
+ b'\x00\x00\x00\x00\x00\x00\x00\x12'
+ ),
+ ('too large bytes size',
+ b'\x4f\x00\x23\x41\x08'
+ b'\x00\x00\x00\x00\x00\x00\x01\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x00'
+ b'\x00\x00\x00\x00\x00\x00\x00\x0c'
+ ),
+ ('extremally large bytes size (32-bit)',
+ b'\x4f\x02\x7f\xff\xff\xff\x41\x08'
+ b'\x00\x00\x00\x00\x00\x00\x01\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x00'
+ b'\x00\x00\x00\x00\x00\x00\x00\x0f'
+ ),
+ ('extremally large bytes size (64-bit)',
+ b'\x4f\x03\x00\x00\x00\xff\xff\xff\xff\xff\x41\x08'
+ b'\x00\x00\x00\x00\x00\x00\x01\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x00'
+ b'\x00\x00\x00\x00\x00\x00\x00\x13'
+ ),
+ ('integer overflow in bytes size',
+ b'\x4f\x03\xff\xff\xff\xff\xff\xff\xff\xff\x41\x08'
+ b'\x00\x00\x00\x00\x00\x00\x01\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x00'
+ b'\x00\x00\x00\x00\x00\x00\x00\x13'
+ ),
+ ('too large ASCII size',
+ b'\x5f\x00\x23\x41\x08'
+ b'\x00\x00\x00\x00\x00\x00\x01\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x00'
+ b'\x00\x00\x00\x00\x00\x00\x00\x0c'
+ ),
+ ('extremally large ASCII size (32-bit)',
+ b'\x5f\x02\x7f\xff\xff\xff\x41\x08'
+ b'\x00\x00\x00\x00\x00\x00\x01\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x00'
+ b'\x00\x00\x00\x00\x00\x00\x00\x0f'
+ ),
+ ('extremally large ASCII size (64-bit)',
+ b'\x5f\x03\x00\x00\x00\xff\xff\xff\xff\xff\x41\x08'
+ b'\x00\x00\x00\x00\x00\x00\x01\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x00'
+ b'\x00\x00\x00\x00\x00\x00\x00\x13'
+ ),
+ ('integer overflow in ASCII size',
+ b'\x5f\x03\xff\xff\xff\xff\xff\xff\xff\xff\x41\x08'
+ b'\x00\x00\x00\x00\x00\x00\x01\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x00'
+ b'\x00\x00\x00\x00\x00\x00\x00\x13'
+ ),
+ ('invalid ASCII',
+ b'\x51\xff\x08'
+ b'\x00\x00\x00\x00\x00\x00\x01\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x00'
+ b'\x00\x00\x00\x00\x00\x00\x00\x0a'
+ ),
+ ('too large UTF-16 size',
+ b'\x6f\x00\x13\x20\xac\x00\x08'
+ b'\x00\x00\x00\x00\x00\x00\x01\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x00'
+ b'\x00\x00\x00\x00\x00\x00\x00\x0e'
+ ),
+ ('extremally large UTF-16 size (32-bit)',
+ b'\x6f\x02\x4f\xff\xff\xff\x20\xac\x00\x08'
+ b'\x00\x00\x00\x00\x00\x00\x01\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x00'
+ b'\x00\x00\x00\x00\x00\x00\x00\x11'
+ ),
+ ('extremally large UTF-16 size (64-bit)',
+ b'\x6f\x03\x00\x00\x00\xff\xff\xff\xff\xff\x20\xac\x00\x08'
+ b'\x00\x00\x00\x00\x00\x00\x01\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x00'
+ b'\x00\x00\x00\x00\x00\x00\x00\x15'
+ ),
+ ('integer overflow in UTF-16 size',
+ b'\x6f\x03\xff\xff\xff\xff\xff\xff\xff\xff\x20\xac\x00\x08'
+ b'\x00\x00\x00\x00\x00\x00\x01\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x00'
+ b'\x00\x00\x00\x00\x00\x00\x00\x15'
+ ),
+ ('invalid UTF-16',
+ b'\x61\xd8\x00\x08'
+ b'\x00\x00\x00\x00\x00\x00\x01\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x00'
+ b'\x00\x00\x00\x00\x00\x00\x00\x0b'
+ ),
+ ('non-hashable key',
+ b'\xd1\x01\x01\xa0\x08\x0b'
+ b'\x00\x00\x00\x00\x00\x00\x01\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x02'
+ b'\x00\x00\x00\x00\x00\x00\x00\x00'
+ b'\x00\x00\x00\x00\x00\x00\x00\x0c'
+ ),
+ ('too large datetime (datetime overflow)',
+ b'\x33\x42\x50\x00\x00\x00\x00\x00\x00\x08'
+ b'\x00\x00\x00\x00\x00\x00\x01\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x00'
+ b'\x00\x00\x00\x00\x00\x00\x00\x11'
+ ),
+ ('too large datetime (timedelta overflow)',
+ b'\x33\x42\xe0\x00\x00\x00\x00\x00\x00\x08'
+ b'\x00\x00\x00\x00\x00\x00\x01\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x00'
+ b'\x00\x00\x00\x00\x00\x00\x00\x11'
+ ),
+ ('invalid datetime (Infinity)',
+ b'\x33\x7f\xf0\x00\x00\x00\x00\x00\x00\x08'
+ b'\x00\x00\x00\x00\x00\x00\x01\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x00'
+ b'\x00\x00\x00\x00\x00\x00\x00\x11'
+ ),
+ ('invalid datetime (NaN)',
+ b'\x33\x7f\xf8\x00\x00\x00\x00\x00\x00\x08'
+ b'\x00\x00\x00\x00\x00\x00\x01\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x01'
+ b'\x00\x00\x00\x00\x00\x00\x00\x00'
+ b'\x00\x00\x00\x00\x00\x00\x00\x11'
+ ),
+]
+
class TestPlistlib(unittest.TestCase):
self.assertRaises(ValueError, plistlib.loads,
b"<plist><integer>not real</integer></plist>")
+ def test_integer_notations(self):
+ pl = b"<plist><integer>456</integer></plist>"
+ value = plistlib.loads(pl)
+ self.assertEqual(value, 456)
+
+ pl = b"<plist><integer>0xa</integer></plist>"
+ value = plistlib.loads(pl)
+ self.assertEqual(value, 10)
+
+ pl = b"<plist><integer>0123</integer></plist>"
+ value = plistlib.loads(pl)
+ self.assertEqual(value, 123)
+
def test_xml_encodings(self):
base = TESTDATA[plistlib.FMT_XML]
with self.assertRaises(OverflowError):
plistlib.dumps(huge_uid, fmt=plistlib.FMT_BINARY)
+ def test_xml_plist_with_entity_decl(self):
+ with self.assertRaisesRegex(plistlib.InvalidFileException,
+ "XML entity declarations are not supported"):
+ plistlib.loads(XML_PLIST_WITH_ENTITY, fmt=plistlib.FMT_XML)
+
class TestBinaryPlistlib(unittest.TestCase):
+ @staticmethod
+ def decode(*objects, offset_size=1, ref_size=1):
+ data = [b'bplist00']
+ offset = 8
+ offsets = []
+ for x in objects:
+ offsets.append(offset.to_bytes(offset_size, 'big'))
+ data.append(x)
+ offset += len(x)
+ tail = struct.pack('>6xBBQQQ', offset_size, ref_size,
+ len(objects), 0, offset)
+ data.extend(offsets)
+ data.append(tail)
+ return plistlib.loads(b''.join(data), fmt=plistlib.FMT_BINARY)
+
def test_nonstandard_refs_size(self):
# Issue #21538: Refs and offsets are 24-bit integers
data = (b'bplist00'
def test_dump_duplicates(self):
# Test effectiveness of saving duplicated objects
- for x in (None, False, True, 12345, 123.45, 'abcde', b'abcde',
+ for x in (None, False, True, 12345, 123.45, 'abcde', 'абвгд', b'abcde',
datetime.datetime(2004, 10, 26, 10, 33, 33),
bytearray(b'abcde'), [12, 345], (12, 345), {'12': 345}):
with self.subTest(x=x):
b = plistlib.loads(plistlib.dumps(a, fmt=plistlib.FMT_BINARY))
self.assertIs(b['x'], b)
+ def test_deep_nesting(self):
+ for N in [300, 100000]:
+ chunks = [b'\xa1' + (i + 1).to_bytes(4, 'big') for i in range(N)]
+ try:
+ result = self.decode(*chunks, b'\x54seed', offset_size=4, ref_size=4)
+ except RecursionError:
+ pass
+ else:
+ for i in range(N):
+ self.assertIsInstance(result, list)
+ self.assertEqual(len(result), 1)
+ result = result[0]
+ self.assertEqual(result, 'seed')
+
def test_large_timestamp(self):
# Issue #26709: 32-bit timestamp out of range
for ts in -2**31-1, 2**31:
data = plistlib.dumps(d, fmt=plistlib.FMT_BINARY)
self.assertEqual(plistlib.loads(data), d)
+ def test_load_singletons(self):
+ self.assertIs(self.decode(b'\x00'), None)
+ self.assertIs(self.decode(b'\x08'), False)
+ self.assertIs(self.decode(b'\x09'), True)
+ self.assertEqual(self.decode(b'\x0f'), b'')
+
+ def test_load_int(self):
+ self.assertEqual(self.decode(b'\x10\x00'), 0)
+ self.assertEqual(self.decode(b'\x10\xfe'), 0xfe)
+ self.assertEqual(self.decode(b'\x11\xfe\xdc'), 0xfedc)
+ self.assertEqual(self.decode(b'\x12\xfe\xdc\xba\x98'), 0xfedcba98)
+ self.assertEqual(self.decode(b'\x13\x01\x23\x45\x67\x89\xab\xcd\xef'),
+ 0x0123456789abcdef)
+ self.assertEqual(self.decode(b'\x13\xfe\xdc\xba\x98\x76\x54\x32\x10'),
+ -0x123456789abcdf0)
+
+ def test_unsupported(self):
+ unsupported = [*range(1, 8), *range(10, 15),
+ 0x20, 0x21, *range(0x24, 0x33), *range(0x34, 0x40)]
+ for i in [0x70, 0x90, 0xb0, 0xc0, 0xe0, 0xf0]:
+ unsupported.extend(i + j for j in range(16))
+ for token in unsupported:
+ with self.subTest(f'token {token:02x}'):
+ with self.assertRaises(plistlib.InvalidFileException):
+ self.decode(bytes([token]) + b'\x00'*16)
+
def test_invalid_binary(self):
- for data in [
- # too short data
- b'',
- # too large offset_table_offset and nonstandard offset_size
- b'\x00\x08'
- b'\x00\x00\x00\x00\x00\x00\x03\x01'
- b'\x00\x00\x00\x00\x00\x00\x00\x01'
- b'\x00\x00\x00\x00\x00\x00\x00\x00'
- b'\x00\x00\x00\x00\x00\x00\x00\x2a',
- # integer overflow in offset_table_offset
- b'\x00\x08'
- b'\x00\x00\x00\x00\x00\x00\x01\x01'
- b'\x00\x00\x00\x00\x00\x00\x00\x01'
- b'\x00\x00\x00\x00\x00\x00\x00\x00'
- b'\xff\xff\xff\xff\xff\xff\xff\xff',
- # offset_size = 0
- b'\x00\x08'
- b'\x00\x00\x00\x00\x00\x00\x00\x01'
- b'\x00\x00\x00\x00\x00\x00\x00\x01'
- b'\x00\x00\x00\x00\x00\x00\x00\x00'
- b'\x00\x00\x00\x00\x00\x00\x00\x09',
- # ref_size = 0
- b'\xa1\x01\x00\x08\x0a'
- b'\x00\x00\x00\x00\x00\x00\x01\x00'
- b'\x00\x00\x00\x00\x00\x00\x00\x02'
- b'\x00\x00\x00\x00\x00\x00\x00\x00'
- b'\x00\x00\x00\x00\x00\x00\x00\x0b',
- # integer overflow in offset
- b'\x00\xff\xff\xff\xff\xff\xff\xff\xff'
- b'\x00\x00\x00\x00\x00\x00\x08\x01'
- b'\x00\x00\x00\x00\x00\x00\x00\x01'
- b'\x00\x00\x00\x00\x00\x00\x00\x00'
- b'\x00\x00\x00\x00\x00\x00\x00\x09',
- # invalid ASCII
- b'\x51\xff\x08'
- b'\x00\x00\x00\x00\x00\x00\x01\x01'
- b'\x00\x00\x00\x00\x00\x00\x00\x01'
- b'\x00\x00\x00\x00\x00\x00\x00\x00'
- b'\x00\x00\x00\x00\x00\x00\x00\x0a',
- # invalid UTF-16
- b'\x61\xd8\x00\x08'
- b'\x00\x00\x00\x00\x00\x00\x01\x01'
- b'\x00\x00\x00\x00\x00\x00\x00\x01'
- b'\x00\x00\x00\x00\x00\x00\x00\x00'
- b'\x00\x00\x00\x00\x00\x00\x00\x0b',
- ]:
- with self.assertRaises(plistlib.InvalidFileException):
- plistlib.loads(b'bplist00' + data, fmt=plistlib.FMT_BINARY)
+ for name, data in INVALID_BINARY_PLISTS:
+ with self.subTest(name):
+ with self.assertRaises(plistlib.InvalidFileException):
+ plistlib.loads(b'bplist00' + data, fmt=plistlib.FMT_BINARY)
class TestKeyedArchive(unittest.TestCase):
if sys.platform == 'darwin':
import sysconfig
dt = sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET') or '10.0'
- if tuple(int(n) for n in dt.split('.')[0:2]) < (10, 6):
+ if tuple(int(n) for n in str(dt).split('.')[0:2]) < (10, 6):
raise unittest.SkipTest("getgroups(2) is broken prior to 10.6")
# 'id -G' and 'os.getgroups()' should return the same
assert_python_ok(*args, PATH=path)
+@unittest.skipUnless(sys.platform == "darwin", "test weak linking on macOS")
+class TestPosixWeaklinking(unittest.TestCase):
+ # These test cases verify that weak linking support on macOS works
+ # as expected. These cases only test new behaviour introduced by weak linking,
+ # regular behaviour is tested by the normal test cases.
+ #
+ # See the section on Weak Linking in Mac/README.txt for more information.
+ def setUp(self):
+ import sysconfig
+ import platform
+
+ config_vars = sysconfig.get_config_vars()
+ self.available = { nm for nm in config_vars if nm.startswith("HAVE_") and config_vars[nm] }
+ self.mac_ver = tuple(int(part) for part in platform.mac_ver()[0].split("."))
+
+ def _verify_available(self, name):
+ if name not in self.available:
+ raise unittest.SkipTest(f"{name} not weak-linked")
+
+ def test_pwritev(self):
+ self._verify_available("HAVE_PWRITEV")
+ if self.mac_ver >= (10, 16):
+ self.assertTrue(hasattr(os, "pwritev"), "os.pwritev is not available")
+ self.assertTrue(hasattr(os, "preadv"), "os.readv is not available")
+
+ else:
+ self.assertFalse(hasattr(os, "pwritev"), "os.pwritev is available")
+ self.assertFalse(hasattr(os, "preadv"), "os.readv is available")
+
+ def test_stat(self):
+ self._verify_available("HAVE_FSTATAT")
+ if self.mac_ver >= (10, 10):
+ self.assertIn("HAVE_FSTATAT", posix._have_functions)
+
+ else:
+ self.assertNotIn("HAVE_FSTATAT", posix._have_functions)
+
+ with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"):
+ os.stat("file", dir_fd=0)
+
+ def test_access(self):
+ self._verify_available("HAVE_FACCESSAT")
+ if self.mac_ver >= (10, 10):
+ self.assertIn("HAVE_FACCESSAT", posix._have_functions)
+
+ else:
+ self.assertNotIn("HAVE_FACCESSAT", posix._have_functions)
+
+ with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"):
+ os.access("file", os.R_OK, dir_fd=0)
+
+ with self.assertRaisesRegex(NotImplementedError, "follow_symlinks unavailable"):
+ os.access("file", os.R_OK, follow_symlinks=False)
+
+ with self.assertRaisesRegex(NotImplementedError, "effective_ids unavailable"):
+ os.access("file", os.R_OK, effective_ids=True)
+
+ def test_chmod(self):
+ self._verify_available("HAVE_FCHMODAT")
+ if self.mac_ver >= (10, 10):
+ self.assertIn("HAVE_FCHMODAT", posix._have_functions)
+
+ else:
+ self.assertNotIn("HAVE_FCHMODAT", posix._have_functions)
+ self.assertIn("HAVE_LCHMOD", posix._have_functions)
+
+ with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"):
+ os.chmod("file", 0o644, dir_fd=0)
+
+ def test_chown(self):
+ self._verify_available("HAVE_FCHOWNAT")
+ if self.mac_ver >= (10, 10):
+ self.assertIn("HAVE_FCHOWNAT", posix._have_functions)
+
+ else:
+ self.assertNotIn("HAVE_FCHOWNAT", posix._have_functions)
+ self.assertIn("HAVE_LCHOWN", posix._have_functions)
+
+ with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"):
+ os.chown("file", 0, 0, dir_fd=0)
+
+ def test_link(self):
+ self._verify_available("HAVE_LINKAT")
+ if self.mac_ver >= (10, 10):
+ self.assertIn("HAVE_LINKAT", posix._have_functions)
+
+ else:
+ self.assertNotIn("HAVE_LINKAT", posix._have_functions)
+
+ with self.assertRaisesRegex(NotImplementedError, "src_dir_fd unavailable"):
+ os.link("source", "target", src_dir_fd=0)
+
+ with self.assertRaisesRegex(NotImplementedError, "dst_dir_fd unavailable"):
+ os.link("source", "target", dst_dir_fd=0)
+
+ with self.assertRaisesRegex(NotImplementedError, "src_dir_fd unavailable"):
+ os.link("source", "target", src_dir_fd=0, dst_dir_fd=0)
+
+ # issue 41355: !HAVE_LINKAT code path ignores the follow_symlinks flag
+ with support.temp_dir() as base_path:
+ link_path = os.path.join(base_path, "link")
+ target_path = os.path.join(base_path, "target")
+ source_path = os.path.join(base_path, "source")
+
+ with open(source_path, "w") as fp:
+ fp.write("data")
+
+ os.symlink("target", link_path)
+
+ # Calling os.link should fail in the link(2) call, and
+ # should not reject *follow_symlinks* (to match the
+ # behaviour you'd get when building on a platform without
+ # linkat)
+ with self.assertRaises(FileExistsError):
+ os.link(source_path, link_path, follow_symlinks=True)
+
+ with self.assertRaises(FileExistsError):
+ os.link(source_path, link_path, follow_symlinks=False)
+
+
+ def test_listdir_scandir(self):
+ self._verify_available("HAVE_FDOPENDIR")
+ if self.mac_ver >= (10, 10):
+ self.assertIn("HAVE_FDOPENDIR", posix._have_functions)
+
+ else:
+ self.assertNotIn("HAVE_FDOPENDIR", posix._have_functions)
+
+ with self.assertRaisesRegex(TypeError, "listdir: path should be string, bytes, os.PathLike or None, not int"):
+ os.listdir(0)
+
+ with self.assertRaisesRegex(TypeError, "scandir: path should be string, bytes, os.PathLike or None, not int"):
+ os.scandir(0)
+
+ def test_mkdir(self):
+ self._verify_available("HAVE_MKDIRAT")
+ if self.mac_ver >= (10, 10):
+ self.assertIn("HAVE_MKDIRAT", posix._have_functions)
+
+ else:
+ self.assertNotIn("HAVE_MKDIRAT", posix._have_functions)
+
+ with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"):
+ os.mkdir("dir", dir_fd=0)
+
+ def test_rename_replace(self):
+ self._verify_available("HAVE_RENAMEAT")
+ if self.mac_ver >= (10, 10):
+ self.assertIn("HAVE_RENAMEAT", posix._have_functions)
+
+ else:
+ self.assertNotIn("HAVE_RENAMEAT", posix._have_functions)
+
+ with self.assertRaisesRegex(NotImplementedError, "src_dir_fd and dst_dir_fd unavailable"):
+ os.rename("a", "b", src_dir_fd=0)
+
+ with self.assertRaisesRegex(NotImplementedError, "src_dir_fd and dst_dir_fd unavailable"):
+ os.rename("a", "b", dst_dir_fd=0)
+
+ with self.assertRaisesRegex(NotImplementedError, "src_dir_fd and dst_dir_fd unavailable"):
+ os.replace("a", "b", src_dir_fd=0)
+
+ with self.assertRaisesRegex(NotImplementedError, "src_dir_fd and dst_dir_fd unavailable"):
+ os.replace("a", "b", dst_dir_fd=0)
+
+ def test_unlink_rmdir(self):
+ self._verify_available("HAVE_UNLINKAT")
+ if self.mac_ver >= (10, 10):
+ self.assertIn("HAVE_UNLINKAT", posix._have_functions)
+
+ else:
+ self.assertNotIn("HAVE_UNLINKAT", posix._have_functions)
+
+ with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"):
+ os.unlink("path", dir_fd=0)
+
+ with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"):
+ os.rmdir("path", dir_fd=0)
+
+ def test_open(self):
+ self._verify_available("HAVE_OPENAT")
+ if self.mac_ver >= (10, 10):
+ self.assertIn("HAVE_OPENAT", posix._have_functions)
+
+ else:
+ self.assertNotIn("HAVE_OPENAT", posix._have_functions)
+
+ with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"):
+ os.open("path", os.O_RDONLY, dir_fd=0)
+
+ def test_readlink(self):
+ self._verify_available("HAVE_READLINKAT")
+ if self.mac_ver >= (10, 10):
+ self.assertIn("HAVE_READLINKAT", posix._have_functions)
+
+ else:
+ self.assertNotIn("HAVE_READLINKAT", posix._have_functions)
+
+ with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"):
+ os.readlink("path", dir_fd=0)
+
+ def test_symlink(self):
+ self._verify_available("HAVE_SYMLINKAT")
+ if self.mac_ver >= (10, 10):
+ self.assertIn("HAVE_SYMLINKAT", posix._have_functions)
+
+ else:
+ self.assertNotIn("HAVE_SYMLINKAT", posix._have_functions)
+
+ with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"):
+ os.symlink("a", "b", dir_fd=0)
+
+ def test_utime(self):
+ self._verify_available("HAVE_FUTIMENS")
+ self._verify_available("HAVE_UTIMENSAT")
+ if self.mac_ver >= (10, 13):
+ self.assertIn("HAVE_FUTIMENS", posix._have_functions)
+ self.assertIn("HAVE_UTIMENSAT", posix._have_functions)
+
+ else:
+ self.assertNotIn("HAVE_FUTIMENS", posix._have_functions)
+ self.assertNotIn("HAVE_UTIMENSAT", posix._have_functions)
+
+ with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"):
+ os.utime("path", dir_fd=0)
+
+
def test_main():
try:
support.run_unittest(
PosixGroupsTester,
TestPosixSpawn,
TestPosixSpawnP,
+ TestPosixWeaklinking
)
finally:
support.reap_children()
import os
from difflib import unified_diff
from io import StringIO
-from test.support import TESTFN, run_unittest, unlink
+from test.support import TESTFN, run_unittest, unlink, temp_dir, change_cwd
from contextlib import contextmanager
import profile
assert_python_ok('-m', self.profilermodule.__name__,
'-m', 'timeit', '-n', '1')
+ def test_output_file_when_changing_directory(self):
+ with temp_dir() as tmpdir, change_cwd(tmpdir):
+ os.mkdir('dest')
+ with open('demo.py', 'w') as f:
+ f.write('import os; os.chdir("dest")')
+
+ assert_python_ok(
+ '-m', self.profilermodule.__name__,
+ '-o', 'out.pstats',
+ 'demo.py',
+ )
+
+ self.assertTrue(os.path.exists('out.pstats'))
+
def regenerate_expected_output(filename, cls):
filename = filename.rstrip('co')
self.assertIn('pass2', funcs_called)
self.assertIn('pass3', funcs_called)
+ def test_SortKey_enum(self):
+ self.assertEqual(SortKey.FILENAME, 'filename')
+ self.assertNotEqual(SortKey.FILENAME, SortKey.CALLS)
+
if __name__ == "__main__":
unittest.main()
rv = shutil.which(program, path=self.temp_dir)
self.assertEqual(rv, temp_filexyz.name)
+ # Issue 40592: See https://bugs.python.org/issue40592
+ @unittest.skipUnless(sys.platform == "win32", 'test specific to Windows')
+ def test_pathext_with_empty_str(self):
+ ext = ".xyz"
+ temp_filexyz = tempfile.NamedTemporaryFile(dir=self.temp_dir,
+ prefix="Tmp2", suffix=ext)
+ self.addCleanup(temp_filexyz.close)
+
+ # strip path and extension
+ program = os.path.basename(temp_filexyz.name)
+ program = os.path.splitext(program)[0]
+
+ with support.EnvironmentVarGuard() as env:
+ env['PATHEXT'] = f"{ext};" # note the ;
+ rv = shutil.which(program, path=self.temp_dir)
+ self.assertEqual(rv, temp_filexyz.name)
+
class TestWhichBytes(TestWhich):
def setUp(self):
@test.support.requires_resource('network')
@test.support.system_must_validate_cert
- @unittest.skipUnless(sys.version_info[3] == 'final',
- 'only for released versions')
@unittest.skipUnless(hasattr(urllib.request, "HTTPSHandler"),
'need SSL support to download license')
def test_license_exists_at_url(self):
# string displayed by license in the absence of a LICENSE file.
url = license._Printer__data.split()[1]
req = urllib.request.Request(url, method='HEAD')
+ # Reset global urllib.request._opener
+ self.addCleanup(urllib.request.urlcleanup)
try:
with socket_helper.transient_internet(url):
with urllib.request.urlopen(req) as data:
@requires_minimum_version
@requires_tls_version('TLSv1_2')
+ @requires_tls_version('TLSv1')
def test_min_max_version_mismatch(self):
client_context, server_context, hostname = testing_context()
# client 1.0, server 1.2 (mismatch)
with self.assertRaises(ValueError):
subprocess.check_call(ZERO_RETURN_CMD, user=-1)
+ with self.assertRaises(OverflowError):
+ subprocess.check_call(ZERO_RETURN_CMD,
+ cwd=os.curdir, env=os.environ, user=2**64)
+
if pwd is None and name_uid is not None:
with self.assertRaises(ValueError):
subprocess.check_call(ZERO_RETURN_CMD, user=name_uid)
with self.assertRaises(ValueError):
subprocess.check_call(ZERO_RETURN_CMD, group=-1)
+ with self.assertRaises(OverflowError):
+ subprocess.check_call(ZERO_RETURN_CMD,
+ cwd=os.curdir, env=os.environ, group=2**64)
+
if grp is None:
with self.assertRaises(ValueError):
subprocess.check_call(ZERO_RETURN_CMD, group=name_group)
with self.assertRaises(ValueError):
subprocess.check_call(ZERO_RETURN_CMD, extra_groups=[-1])
+ with self.assertRaises(ValueError):
+ subprocess.check_call(ZERO_RETURN_CMD,
+ cwd=os.curdir, env=os.environ,
+ extra_groups=[2**64])
+
if grp is None:
with self.assertRaises(ValueError):
subprocess.check_call(ZERO_RETURN_CMD,
# so Popen failed to read it and uses a default returncode instead.
self.assertIsNotNone(proc.returncode)
+ def test_send_signal_race2(self):
+ # bpo-40550: the process might exist between the returncode check and
+ # the kill operation
+ p = subprocess.Popen([sys.executable, '-c', 'exit(1)'])
+
+ # wait for process to exit
+ while not p.returncode:
+ p.poll()
+
+ with mock.patch.object(p, 'poll', new=lambda: None):
+ p.returncode = None
+ p.send_signal(signal.SIGTERM)
+
def test_communicate_repeated_call_after_stdout_close(self):
proc = subprocess.Popen([sys.executable, '-c',
'import os, time; os.close(1), time.sleep(2)'],
glob = 42
some_var = 12
+some_non_assigned_global_var = 11
+some_assigned_global_var = 11
class Mine:
instance_var = 24
def spam(a, b, *var, **kw):
global bar
+ global some_assigned_global_var
+ some_assigned_global_var = 12
bar = 47
some_var = 10
x = 23
def test_lineno(self):
self.assertEqual(self.top.get_lineno(), 0)
- self.assertEqual(self.spam.get_lineno(), 12)
+ self.assertEqual(self.spam.get_lineno(), 14)
def test_function_info(self):
func = self.spam
self.assertEqual(sorted(func.get_parameters()), ["a", "b", "kw", "var"])
expected = ['a', 'b', 'internal', 'kw', 'other_internal', 'some_var', 'var', 'x']
self.assertEqual(sorted(func.get_locals()), expected)
- self.assertEqual(sorted(func.get_globals()), ["bar", "glob"])
+ self.assertEqual(sorted(func.get_globals()), ["bar", "glob", "some_assigned_global_var"])
self.assertEqual(self.internal.get_frees(), ("x",))
def test_globals(self):
self.assertFalse(self.internal.lookup("x").is_global())
self.assertFalse(self.Mine.lookup("instance_var").is_global())
self.assertTrue(self.spam.lookup("bar").is_global())
+ # Module-scope globals are both global and local
+ self.assertTrue(self.top.lookup("some_non_assigned_global_var").is_global())
+ self.assertTrue(self.top.lookup("some_assigned_global_var").is_global())
def test_nonlocal(self):
self.assertFalse(self.spam.lookup("some_var").is_nonlocal())
def test_local(self):
self.assertTrue(self.spam.lookup("x").is_local())
self.assertFalse(self.spam.lookup("bar").is_local())
+ # Module-scope globals are both global and local
+ self.assertTrue(self.top.lookup("some_non_assigned_global_var").is_local())
+ self.assertTrue(self.top.lookup("some_assigned_global_var").is_local())
def test_free(self):
self.assertTrue(self.internal.lookup("x").is_free())
top = symtable.symtable(code, "?", "exec")
self.assertIsNotNone(find_block(top, "\u017d"))
+ def test_symtable_repr(self):
+ self.assertEqual(str(self.top), "<SymbolTable for module ?>")
+ self.assertEqual(str(self.spam), "<Function SymbolTable for spam in ?>")
+
if __name__ == '__main__':
unittest.main()
else:
self.fail("compile() did not raise SyntaxError")
+ def test_curly_brace_after_primary_raises_immediately(self):
+ self._check_error("f{", "invalid syntax", mode="single")
+
def test_assign_call(self):
self._check_error("f() = 1", "assign")
except SyntaxError:
self.fail("Empty line after a line continuation character is valid.")
+ @support.cpython_only
+ def test_nested_named_except_blocks(self):
+ code = ""
+ for i in range(12):
+ code += f"{' '*i}try:\n"
+ code += f"{' '*(i+1)}raise Exception\n"
+ code += f"{' '*i}except Exception as e:\n"
+ code += f"{' '*4*12}pass"
+ self._check_error(code, "too many statically nested blocks")
+
+ def test_barry_as_flufl_with_syntax_errors(self):
+ # The "barry_as_flufl" rule can produce some "bugs-at-a-distance" if
+ # is reading the wrong token in the presence of syntax errors later
+ # in the file. See bpo-42214 for more information.
+ code = """
+def func1():
+ if a != b:
+ raise ValueError
+
+def func2():
+ try
+ return 1
+ finally:
+ pass
+"""
+ self._check_error(code, "invalid syntax")
+
+ def test_invalid_line_continuation_left_recursive(self):
+ # Check bpo-42218: SyntaxErrors following left-recursive rules
+ # (t_primary_raw in this case) need to be tested explicitly
+ self._check_error("A.\u018a\\ ",
+ "unexpected character after line continuation character")
+ self._check_error("A.\u03bc\\\n",
+ "unexpected EOF while parsing")
def test_main():
support.run_unittest(SyntaxTestCase)
f.write('something\n')
os.symlink(source_file, target_file)
with tarfile.open(temparchive, 'w') as tar:
- tar.add(source_file)
- tar.add(target_file)
+ tar.add(source_file, arcname="source")
+ tar.add(target_file, arcname="symlink")
# Let's extract it to the location which contains the symlink
- with tarfile.open(temparchive) as tar:
+ with tarfile.open(temparchive, errorlevel=2) as tar:
# this should not raise OSError: [Errno 17] File exists
try:
tar.extractall(path=tempdir)
pax_headers={'non': 'empty'})
self.assertFalse(f.closed)
+
class GzipWriteTest(GzipTest, WriteTest):
pass
+
class Bz2WriteTest(Bz2Test, WriteTest):
pass
+
class LzmaWriteTest(LzmaTest, WriteTest):
pass
finally:
os.umask(original_umask)
+
class GzipStreamWriteTest(GzipTest, StreamWriteTest):
- pass
+ def test_source_directory_not_leaked(self):
+ """
+ Ensure the source directory is not included in the tar header
+ per bpo-41316.
+ """
+ tarfile.open(tmpname, self.mode).close()
+ payload = pathlib.Path(tmpname).read_text(encoding='latin-1')
+ assert os.path.dirname(tmpname) not in payload
+
class Bz2StreamWriteTest(Bz2Test, StreamWriteTest):
decompressor = bz2.BZ2Decompressor if bz2 else None
t = threading.Thread(daemon=True)
self.assertTrue(t.daemon)
+ @unittest.skipUnless(hasattr(os, 'fork'), 'needs os.fork()')
+ def test_fork_at_exit(self):
+ # bpo-42350: Calling os.fork() after threading._shutdown() must
+ # not log an error.
+ code = textwrap.dedent("""
+ import atexit
+ import os
+ import sys
+ from test.support import wait_process
+
+ # Import the threading module to register its "at fork" callback
+ import threading
+
+ def exit_handler():
+ pid = os.fork()
+ if not pid:
+ print("child process ok", file=sys.stderr, flush=True)
+ # child process
+ sys.exit()
+ else:
+ wait_process(pid, exitcode=0)
+
+ # exit_handler() will be called after threading._shutdown()
+ atexit.register(exit_handler)
+ """)
+ _, out, err = assert_python_ok("-c", code)
+ self.assertEqual(out, b'')
+ self.assertEqual(err.rstrip(), b'child process ok')
+
@unittest.skipUnless(hasattr(os, 'fork'), 'test needs fork()')
def test_dummy_thread_after_fork(self):
# Issue #14308: a dummy thread in the active list doesn't mess up
with self.assertRaises(ValueError):
pytime_object_to_timespec(float('nan'), time_rnd)
+@unittest.skipUnless(sys.platform == "darwin", "test weak linking on macOS")
+class TestTimeWeaklinking(unittest.TestCase):
+ # These test cases verify that weak linking support on macOS works
+ # as expected. These cases only test new behaviour introduced by weak linking,
+ # regular behaviour is tested by the normal test cases.
+ #
+ # See the section on Weak Linking in Mac/README.txt for more information.
+ def test_clock_functions(self):
+ import sysconfig
+ import platform
+
+ config_vars = sysconfig.get_config_vars()
+ var_name = "HAVE_CLOCK_GETTIME"
+ if var_name not in config_vars or not config_vars[var_name]:
+ raise unittest.SkipTest(f"{var_name} is not available")
+
+ mac_ver = tuple(int(x) for x in platform.mac_ver()[0].split("."))
+
+ clock_names = [
+ "CLOCK_MONOTONIC", "clock_gettime", "clock_gettime_ns", "clock_settime",
+ "clock_settime_ns", "clock_getres"]
+
+ if mac_ver >= (10, 12):
+ for name in clock_names:
+ self.assertTrue(hasattr(time, name), f"time.{name} is not available")
+
+ else:
+ for name in clock_names:
+ self.assertFalse(hasattr(time, name), f"time.{name} is available")
+
if __name__ == "__main__":
unittest.main()
self.assertEqual(exc_info[0], exc.exc_type)
self.assertEqual(str(exc_info[1]), str(exc))
- def test_comparison(self):
+ def test_no_refs_to_exception_and_traceback_objects(self):
+ try:
+ 1/0
+ except Exception:
+ exc_info = sys.exc_info()
+
+ refcnt1 = sys.getrefcount(exc_info[1])
+ refcnt2 = sys.getrefcount(exc_info[2])
+ exc = traceback.TracebackException(*exc_info)
+ self.assertEqual(sys.getrefcount(exc_info[1]), refcnt1)
+ self.assertEqual(sys.getrefcount(exc_info[2]), refcnt2)
+
+ def test_comparison_basic(self):
try:
1/0
except Exception:
self.assertNotEqual(exc, object())
self.assertEqual(exc, ALWAYS_EQ)
+ def test_comparison_params_variations(self):
+ def raise_exc():
+ try:
+ raise ValueError('bad value')
+ except:
+ raise
+
+ def raise_with_locals():
+ x, y = 1, 2
+ raise_exc()
+
+ try:
+ raise_with_locals()
+ except Exception:
+ exc_info = sys.exc_info()
+
+ exc = traceback.TracebackException(*exc_info)
+ exc1 = traceback.TracebackException(*exc_info, limit=10)
+ exc2 = traceback.TracebackException(*exc_info, limit=2)
+
+ self.assertEqual(exc, exc1) # limit=10 gets all frames
+ self.assertNotEqual(exc, exc2) # limit=2 truncates the output
+
+ # locals change the output
+ exc3 = traceback.TracebackException(*exc_info, capture_locals=True)
+ self.assertNotEqual(exc, exc3)
+
+ # there are no locals in the innermost frame
+ exc4 = traceback.TracebackException(*exc_info, limit=-1)
+ exc5 = traceback.TracebackException(*exc_info, limit=-1, capture_locals=True)
+ self.assertEqual(exc4, exc5)
+
+ # there are locals in the next-to-innermost frame
+ exc6 = traceback.TracebackException(*exc_info, limit=-2)
+ exc7 = traceback.TracebackException(*exc_info, limit=-2, capture_locals=True)
+ self.assertNotEqual(exc6, exc7)
+
+ def test_comparison_equivalent_exceptions_are_equal(self):
+ excs = []
+ for _ in range(2):
+ try:
+ 1/0
+ except:
+ excs.append(traceback.TracebackException(*sys.exc_info()))
+ self.assertEqual(excs[0], excs[1])
+ self.assertEqual(list(excs[0].format()), list(excs[1].format()))
+
def test_unhashable(self):
class UnhashableException(Exception):
def __eq__(self, other):
f = test_frame(c, None, None)
tb = test_tb(f, 6, None)
exc = traceback.TracebackException(Exception, e, tb, lookup_lines=False)
- self.assertEqual({}, linecache.cache)
+ self.assertEqual(linecache.cache, {})
linecache.updatecache('/foo.py', globals())
self.assertEqual(exc.stack[0].line, "import sys")
self.assertEqual(repr(u), repr(int))
u = Union[List[int], int]
self.assertEqual(repr(u), 'typing.Union[typing.List[int], int]')
+ u = Union[list[int], dict[str, float]]
+ self.assertEqual(repr(u), 'typing.Union[list[int], dict[str, float]]')
def test_cannot_subclass(self):
with self.assertRaises(TypeError):
self.assertEqual(repr(Tuple[()]), 'typing.Tuple[()]')
self.assertEqual(repr(Tuple[int, float]), 'typing.Tuple[int, float]')
self.assertEqual(repr(Tuple[int, ...]), 'typing.Tuple[int, ...]')
+ self.assertEqual(repr(Tuple[list[int]]), 'typing.Tuple[list[int]]')
def test_errors(self):
with self.assertRaises(TypeError):
self.assertEqual(repr(ct2), 'typing.Callable[[str, float], int]')
ctv = Callable[..., str]
self.assertEqual(repr(ctv), 'typing.Callable[..., str]')
+ ct3 = Callable[[str, float], list[int]]
+ self.assertEqual(repr(ct3), 'typing.Callable[[str, float], list[int]]')
def test_callable_with_ellipsis(self):
self.assertEqual(repr(Literal[int]), "typing.Literal[int]")
self.assertEqual(repr(Literal), "typing.Literal")
self.assertEqual(repr(Literal[None]), "typing.Literal[None]")
+ self.assertEqual(repr(Literal[1, 2, 3, 3]), "typing.Literal[1, 2, 3]")
def test_cannot_init(self):
with self.assertRaises(TypeError):
with self.assertRaises(TypeError):
Literal[1][1]
+ def test_equal(self):
+ self.assertNotEqual(Literal[0], Literal[False])
+ self.assertNotEqual(Literal[True], Literal[1])
+ self.assertNotEqual(Literal[1], Literal[2])
+ self.assertNotEqual(Literal[1, True], Literal[1])
+ self.assertEqual(Literal[1], Literal[1])
+ self.assertEqual(Literal[1, 2], Literal[2, 1])
+ self.assertEqual(Literal[1, 2, 3], Literal[1, 2, 3, 3])
+
+ def test_hash(self):
+ self.assertEqual(hash(Literal[1]), hash(Literal[1]))
+ self.assertEqual(hash(Literal[1, 2]), hash(Literal[2, 1]))
+ self.assertEqual(hash(Literal[1, 2, 3]), hash(Literal[1, 2, 3, 3]))
+
+ def test_args(self):
+ self.assertEqual(Literal[1, 2, 3].__args__, (1, 2, 3))
+ self.assertEqual(Literal[1, 2, 3, 3].__args__, (1, 2, 3))
+ self.assertEqual(Literal[1, Literal[2], Literal[3, 4]].__args__, (1, 2, 3, 4))
+ # Mutable arguments will not be deduplicated
+ self.assertEqual(Literal[[], []].__args__, ([], []))
+
+ def test_flatten(self):
+ l1 = Literal[Literal[1], Literal[2], Literal[3]]
+ l2 = Literal[Literal[1, 2], 3]
+ l3 = Literal[Literal[1, 2, 3]]
+ for l in l1, l2, l3:
+ self.assertEqual(l, Literal[1, 2, 3])
+ self.assertEqual(l.__args__, (1, 2, 3))
+
XK = TypeVar('XK', str, bytes)
XV = TypeVar('XV')
self.assertEqual(repr(cv), 'typing.Final[int]')
cv = Final[Employee]
self.assertEqual(repr(cv), 'typing.Final[%s.Employee]' % __name__)
+ cv = Final[tuple[int]]
+ self.assertEqual(repr(cv), 'typing.Final[tuple[int]]')
def test_cannot_subclass(self):
with self.assertRaises(TypeError):
def test_from_format(self):
support.import_module('ctypes')
from ctypes import (
+ c_char_p,
pythonapi, py_object, sizeof,
c_int, c_long, c_longlong, c_ssize_t,
c_uint, c_ulong, c_ulonglong, c_size_t, c_void_p)
name = "PyUnicode_FromFormat"
_PyUnicode_FromFormat = getattr(pythonapi, name)
+ _PyUnicode_FromFormat.argtypes = (c_char_p,)
_PyUnicode_FromFormat.restype = py_object
def PyUnicode_FromFormat(format, *args):
# See issue 25180
self.check_ast_roundtrip(r"""f'{f"{0}"*3}'""")
self.check_ast_roundtrip(r"""f'{f"{y}"*3}'""")
+ self.check_ast_roundtrip("""f''""")
+ self.check_ast_roundtrip('''f"""'end' "quote\\""""''')
+
+ def test_fstrings_complicated(self):
+ # See issue 28002
+ self.check_ast_roundtrip("""f'''{"'"}'''""")
+ self.check_ast_roundtrip('''f\'\'\'-{f"""*{f"+{f'.{x}.'}+"}*"""}-\'\'\'''')
+ self.check_ast_roundtrip('''f\'\'\'-{f"""*{f"+{f'.{x}.'}+"}*"""}-'single quote\\'\'\'\'''')
+ self.check_ast_roundtrip('f"""{\'\'\'\n\'\'\'}"""')
+ self.check_ast_roundtrip('f"""{g(\'\'\'\n\'\'\')}"""')
+ self.check_ast_roundtrip('''f"a\\r\\nb"''')
+ self.check_ast_roundtrip('''f"\\u2028{'x'}"''')
def test_strings(self):
self.check_ast_roundtrip("u'foo'")
)
)
+ def test_invalid_fstring_backslash(self):
+ self.check_invalid(ast.FormattedValue(value=ast.Constant(value="\\\\")))
+
def test_invalid_set(self):
self.check_invalid(ast.Set(elts=[]))
'\r\\r\t\\t\n\\n',
'""">>> content = \"\"\"blabla\"\"\" <<<"""',
r'foo\n\x00',
- '🐍⛎𩸽üéş^\N{LONG RIGHTWARDS SQUIGGLE ARROW}'
-
+ "' \\'\\'\\'\"\"\" \"\"\\'\\' \\'",
+ '🐍⛎𩸽üéş^\\\\X\\\\BB\N{LONG RIGHTWARDS SQUIGGLE ARROW}'
)
for docstring in docstrings:
# check as Module docstrings for easy testing
self.check_src_roundtrip("call((yield x))")
self.check_src_roundtrip("return x + (yield x)")
-
def test_class_bases_and_keywords(self):
self.check_src_roundtrip("class X:\n pass")
self.check_src_roundtrip("class X(A):\n pass")
self.check_src_roundtrip("class X(*args):\n pass")
self.check_src_roundtrip("class X(*args, **kwargs):\n pass")
+ def test_fstrings(self):
+ self.check_src_roundtrip('''f\'\'\'-{f"""*{f"+{f'.{x}.'}+"}*"""}-\'\'\'''')
+ self.check_src_roundtrip('''f"\\u2028{'x'}"''')
+ self.check_src_roundtrip(r"f'{x}\n'")
+ self.check_src_roundtrip('''f''\'{"""\n"""}\\n''\'''')
+ self.check_src_roundtrip('''f''\'{f"""{x}\n"""}\\n''\'''')
+
def test_docstrings(self):
docstrings = (
'"""simple doc string"""',
'""""""',
'"""\'\'\'"""',
'"""\'\'\'\'\'\'"""',
+ '"""🐍⛎𩸽üéş^\\\\X\\\\BB⟿"""',
+ '"""end in single \'quote\'"""',
+ "'''end in double \"quote\"'''",
+ '"""almost end in double "quote"."""',
)
for prefix in docstring_prefixes:
lib_dir = pathlib.Path(__file__).parent / ".."
test_directories = (lib_dir, lib_dir / "test")
- skip_files = {"test_fstring.py"}
run_always_files = {"test_grammar.py", "test_syntax.py", "test_compile.py",
- "test_ast.py", "test_asdl_parser.py"}
+ "test_ast.py", "test_asdl_parser.py", "test_fstring.py"}
_files_to_test = None
if test.support.verbose:
print(f"Testing {item.absolute()}")
- # Some f-strings are not correctly round-tripped by
- # Tools/parser/unparse.py. See issue 28002 for details.
- # We need to skip files that contain such f-strings.
- if item.name in self.skip_files:
- if test.support.verbose:
- print(f"Skipping {item.absolute()}: see issue 28002")
- continue
-
with self.subTest(filename=item):
source = read_pyfile(item)
self.check_ast_roundtrip(source)
bypass = {'exclude_simple': True, 'exceptions': []}
self.assertTrue(_proxy_bypass_macosx_sysconf('test', bypass))
+ # Check that invalid prefix lengths are ignored
+ bypass = {
+ 'exclude_simple': False,
+ 'exceptions': [ '10.0.0.0/40', '172.19.10.0/24' ]
+ }
+ host = '172.19.10.5'
+ self.assertTrue(_proxy_bypass_macosx_sysconf(host, bypass),
+ 'expected bypass of %s to be True' % host)
+ host = '10.0.1.5'
+ self.assertFalse(_proxy_bypass_macosx_sysconf(host, bypass),
+ 'expected bypass of %s to be False' % host)
+
def check_basic_auth(self, headers, realm):
with self.subTest(realm=realm, headers=headers):
opener = OpenerDirector()
import sys
import unittest
from collections import deque
-from contextlib import _GeneratorContextManager, contextmanager
+from contextlib import _GeneratorContextManager, contextmanager, nullcontext
class MockContextManager(_GeneratorContextManager):
self.assertEqual(blah.two, 2)
self.assertEqual(blah.three, 3)
+ def testWithExtendedTargets(self):
+ with nullcontext(range(1, 5)) as (a, *b, c):
+ self.assertEqual(a, 1)
+ self.assertEqual(b, [2, 3])
+ self.assertEqual(c, 4)
+
class ExitSwallowsExceptionTestCase(unittest.TestCase):
#self.assertEqual(c14n_roundtrip("<doc xmlns:x='http://example.com/x' xmlns='http://example.com/default'><b y:a1='1' xmlns='http://example.com/default' a3='3' xmlns:y='http://example.com/y' y:a2='2'/></doc>"),
#'<doc xmlns:x="http://example.com/x"><b xmlns:y="http://example.com/y" a3="3" y:a1="1" y:a2="2"></b></doc>')
+ # Namespace issues
+ xml = '<X xmlns="http://nps/a"><Y targets="abc,xyz"></Y></X>'
+ self.assertEqual(c14n_roundtrip(xml), xml)
+ xml = '<X xmlns="http://nps/a"><Y xmlns="http://nsp/b" targets="abc,xyz"></Y></X>'
+ self.assertEqual(c14n_roundtrip(xml), xml)
+ xml = '<X xmlns="http://nps/a"><Y xmlns:b="http://nsp/b" b:targets="abc,xyz"></Y></X>'
+ self.assertEqual(c14n_roundtrip(xml), xml)
+
def test_c14n_exclusion(self):
xml = textwrap.dedent("""\
<root xmlns:x="http://example.com/x">
self.assertEqual(zipf.comment, b"an updated comment")
# check that comments are correctly shortened in append mode
+ # and the file is indeed truncated
with zipfile.ZipFile(TESTFN,mode="w") as zipf:
zipf.comment = b"original comment that's longer"
zipf.writestr("foo.txt", "O, for a Muse of Fire!")
+ original_zip_size = os.path.getsize(TESTFN)
with zipfile.ZipFile(TESTFN,mode="a") as zipf:
zipf.comment = b"shorter comment"
+ self.assertTrue(original_zip_size > os.path.getsize(TESTFN))
with zipfile.ZipFile(TESTFN,mode="r") as zipf:
self.assertEqual(zipf.comment, b"shorter comment")
import importlib.metadata
import io
import json
-import lzma
import os
import pathlib
import pickle
from . import _support as test_support
from ._support import OS_ENV_LOCK, TZPATH_TEST_LOCK, ZoneInfoTestBase
+from test.support import import_module
+lzma = import_module('lzma')
py_zoneinfo, c_zoneinfo = test_support.get_modules()
try:
# they may be in an invalid state leading to a deadlock or crash.
self._started._at_fork_reinit()
if is_alive:
- self._tstate_lock._at_fork_reinit()
- self._tstate_lock.acquire()
+ # bpo-42350: If the fork happens when the thread is already stopped
+ # (ex: after threading._shutdown() has been called), _tstate_lock
+ # is None. Do nothing in this case.
+ if self._tstate_lock is not None:
+ self._tstate_lock._at_fork_reinit()
+ self._tstate_lock.acquire()
else:
# The thread isn't alive after fork: it doesn't have a tstate
# anymore.
class EventType(str, enum.Enum):
KeyPress = '2'
- Key = KeyPress,
+ Key = KeyPress
KeyRelease = '3'
ButtonPress = '4'
- Button = ButtonPress,
+ Button = ButtonPress
ButtonRelease = '5'
Motion = '6'
Enter = '7'
Colormap = '32'
ClientMessage = '33' # undocumented
Mapping = '34' # undocumented
- VirtualEvent = '35', # undocumented
- Activate = '36',
- Deactivate = '37',
- MouseWheel = '38',
+ VirtualEvent = '35' # undocumented
+ Activate = '36'
+ Deactivate = '37'
+ MouseWheel = '38'
- def __str__(self):
- return self.name
+ __str__ = str.__str__
class Event:
'num', 'delta', 'focus',
'x', 'y', 'width', 'height')
return '<%s event%s>' % (
- self.type,
+ getattr(self.type, 'name', self.type),
''.join(' %s=%s' % (k, attrs[k]) for k in keys if k in attrs)
)
with self.assertRaises(tkinter.TclError):
root.clipboard_get()
+ def test_event_repr_defaults(self):
+ e = tkinter.Event()
+ e.serial = 12345
+ e.num = '??'
+ e.height = '??'
+ e.keycode = '??'
+ e.state = 0
+ e.time = 123456789
+ e.width = '??'
+ e.x = '??'
+ e.y = '??'
+ e.char = ''
+ e.keysym = '??'
+ e.keysym_num = '??'
+ e.type = '100'
+ e.widget = '??'
+ e.x_root = '??'
+ e.y_root = '??'
+ e.delta = 0
+ self.assertEqual(repr(e), '<100 event>')
+
+ def test_event_repr(self):
+ e = tkinter.Event()
+ e.serial = 12345
+ e.num = 3
+ e.focus = True
+ e.height = 200
+ e.keycode = 65
+ e.state = 0x30405
+ e.time = 123456789
+ e.width = 300
+ e.x = 10
+ e.y = 20
+ e.char = 'A'
+ e.send_event = True
+ e.keysym = 'Key-A'
+ e.keysym_num = ord('A')
+ e.type = tkinter.EventType.Configure
+ e.widget = '.text'
+ e.x_root = 1010
+ e.y_root = 1020
+ e.delta = -1
+ self.assertEqual(repr(e),
+ "<Configure event send_event=True"
+ " state=Shift|Control|Button3|0x30000"
+ " keysym=Key-A keycode=65 char='A'"
+ " num=3 delta=-1 focus=True"
+ " x=10 y=20 width=300 height=200>")
tests_gui = (MiscTest, )
def test_from(self):
widget = self.create()
- self.checkFloatParam(widget, 'from', 100, 14.9, 15.1, conv=float_round)
+ conv = False if get_tk_patchlevel() >= (8, 6, 10) else float_round
+ self.checkFloatParam(widget, 'from', 100, 14.9, 15.1, conv=conv)
def test_label(self):
widget = self.create()
def test_horizontal_range(self):
lscale = ttk.LabeledScale(self.root, from_=0, to=10)
lscale.pack()
- lscale.wait_visibility()
lscale.update()
linfo_1 = lscale.label.place_info()
def test_variable_change(self):
x = ttk.LabeledScale(self.root)
x.pack()
- x.wait_visibility()
x.update()
curr_xcoord = x.scale.coords()[0]
def test_resize(self):
x = ttk.LabeledScale(self.root)
x.pack(expand=True, fill='both')
- x.wait_visibility()
x.update()
width, height = x.master.winfo_width(), x.master.winfo_height()
# check that variable is updated correctly
optmenu.pack()
- optmenu.wait_visibility()
optmenu['menu'].invoke(0)
self.assertEqual(optmenu._variable.get(), items[0])
textvar2 = tkinter.StringVar(self.root)
optmenu2 = ttk.OptionMenu(self.root, textvar2, default, *items)
optmenu.pack()
- optmenu.wait_visibility()
optmenu2.pack()
- optmenu2.wait_visibility()
optmenu['menu'].invoke(1)
optmenu2['menu'].invoke(2)
optmenu_stringvar_name = optmenu['menu'].entrycget(0, 'variable')
result = ttk._format_mapdict(opts)
self.assertEqual(result, ('-üñíćódè', 'á vãl'))
+ self.assertEqual(ttk._format_mapdict({'opt': [('value',)]}),
+ ('-opt', '{} value'))
+
# empty states
valid = {'opt': [('', '', 'hi')]}
self.assertEqual(ttk._format_mapdict(valid), ('-opt', '{ } hi'))
opts = {'a': None}
self.assertRaises(TypeError, ttk._format_mapdict, opts)
- # items in the value must have size >= 2
- self.assertRaises(IndexError, ttk._format_mapdict,
- {'a': [('invalid', )]})
-
def test_format_elemcreate(self):
self.assertTrue(ttk._format_elemcreate(None), (None, ()))
import unittest
+import sys
import tkinter
from tkinter import ttk
+from test import support
from test.support import requires, run_unittest
from tkinter.test.support import AbstractTkTest
requires('gui')
+CLASS_NAMES = [
+ '.', 'ComboboxPopdownFrame', 'Heading',
+ 'Horizontal.TProgressbar', 'Horizontal.TScale', 'Item', 'Sash',
+ 'TButton', 'TCheckbutton', 'TCombobox', 'TEntry',
+ 'TLabelframe', 'TLabelframe.Label', 'TMenubutton',
+ 'TNotebook', 'TNotebook.Tab', 'Toolbutton', 'TProgressbar',
+ 'TRadiobutton', 'Treeview', 'TScale', 'TScrollbar', 'TSpinbox',
+ 'Vertical.TProgressbar', 'Vertical.TScale'
+]
+
class StyleTest(AbstractTkTest, unittest.TestCase):
def setUp(self):
def test_map(self):
style = self.style
- style.map('TButton', background=[('active', 'background', 'blue')])
- self.assertEqual(style.map('TButton', 'background'),
- [('active', 'background', 'blue')] if self.wantobjects else
- [('active background', 'blue')])
- self.assertIsInstance(style.map('TButton'), dict)
+
+ # Single state
+ for states in ['active'], [('active',)]:
+ with self.subTest(states=states):
+ style.map('TButton', background=[(*states, 'white')])
+ expected = [('active', 'white')]
+ self.assertEqual(style.map('TButton', 'background'), expected)
+ m = style.map('TButton')
+ self.assertIsInstance(m, dict)
+ self.assertEqual(m['background'], expected)
+
+ # Multiple states
+ for states in ['pressed', '!disabled'], ['pressed !disabled'], [('pressed', '!disabled')]:
+ with self.subTest(states=states):
+ style.map('TButton', background=[(*states, 'black')])
+ expected = [('pressed', '!disabled', 'black')]
+ self.assertEqual(style.map('TButton', 'background'), expected)
+ m = style.map('TButton')
+ self.assertIsInstance(m, dict)
+ self.assertEqual(m['background'], expected)
+
+ # Default state
+ for states in [], [''], [()]:
+ with self.subTest(states=states):
+ style.map('TButton', background=[(*states, 'grey')])
+ expected = [('grey',)]
+ self.assertEqual(style.map('TButton', 'background'), expected)
+ m = style.map('TButton')
+ self.assertIsInstance(m, dict)
+ self.assertEqual(m['background'], expected)
def test_lookup(self):
self.style.theme_use(curr_theme)
+ def test_configure_custom_copy(self):
+ style = self.style
+
+ curr_theme = self.style.theme_use()
+ self.addCleanup(self.style.theme_use, curr_theme)
+ for theme in self.style.theme_names():
+ self.style.theme_use(theme)
+ for name in CLASS_NAMES:
+ default = style.configure(name)
+ if not default:
+ continue
+ with self.subTest(theme=theme, name=name):
+ if support.verbose >= 2:
+ print('configure', theme, name, default)
+ if (theme in ('vista', 'xpnative')
+ and sys.getwindowsversion()[:2] == (6, 1)):
+ # Fails on the Windows 7 buildbot
+ continue
+ newname = f'C.{name}'
+ self.assertEqual(style.configure(newname), None)
+ style.configure(newname, **default)
+ self.assertEqual(style.configure(newname), default)
+ for key, value in default.items():
+ self.assertEqual(style.configure(newname, key), value)
+
+
+ def test_map_custom_copy(self):
+ style = self.style
+
+ curr_theme = self.style.theme_use()
+ self.addCleanup(self.style.theme_use, curr_theme)
+ for theme in self.style.theme_names():
+ self.style.theme_use(theme)
+ for name in CLASS_NAMES:
+ default = style.map(name)
+ if not default:
+ continue
+ with self.subTest(theme=theme, name=name):
+ if support.verbose >= 2:
+ print('map', theme, name, default)
+ if (theme in ('vista', 'xpnative')
+ and sys.getwindowsversion()[:2] == (6, 1)):
+ # Fails on the Windows 7 buildbot
+ continue
+ newname = f'C.{name}'
+ self.assertEqual(style.map(newname), {})
+ style.map(newname, **default)
+ self.assertEqual(style.map(newname), default)
+ for key, value in default.items():
+ self.assertEqual(style.map(newname, key), value)
+
+
tests_gui = (StyleTest, )
if __name__ == "__main__":
super().setUp()
self.widget = ttk.Button(self.root, width=0, text="Text")
self.widget.pack()
- self.widget.wait_visibility()
def test_identify(self):
- self.widget.update_idletasks()
+ self.widget.update()
self.assertEqual(self.widget.identify(
int(self.widget.winfo_width() / 2),
int(self.widget.winfo_height() / 2)
def test_identify(self):
self.entry.pack()
- self.entry.wait_visibility()
- self.entry.update_idletasks()
+ self.entry.update()
# bpo-27313: macOS Cocoa widget differs from X, allow either
if sys.platform == 'darwin':
def _show_drop_down_listbox(self):
width = self.combo.winfo_width()
- self.combo.event_generate('<ButtonPress-1>', x=width - 5, y=5)
- self.combo.event_generate('<ButtonRelease-1>', x=width - 5, y=5)
+ x, y = width - 5, 5
+ self.assertRegex(self.combo.identify(x, y), r'.*downarrow\Z')
+ self.combo.event_generate('<ButtonPress-1>', x=x, y=y)
+ self.combo.event_generate('<ButtonRelease-1>', x=x, y=y)
self.combo.update_idletasks()
-
def test_virtual_event(self):
success = []
self.combo.bind('<<ComboboxSelected>>',
lambda evt: success.append(True))
self.combo.pack()
- self.combo.wait_visibility()
+ self.combo.update()
height = self.combo.winfo_height()
self._show_drop_down_listbox()
self.combo['postcommand'] = lambda: success.append(True)
self.combo.pack()
- self.combo.wait_visibility()
+ self.combo.update()
self._show_drop_down_listbox()
self.assertTrue(success)
self.assertRaises(tkinter.TclError, self.paned.sashpos, 1)
self.paned.pack(expand=True, fill='both')
- self.paned.wait_visibility()
curr_pos = self.paned.sashpos(0)
self.paned.sashpos(0, 1000)
self.nb.add(self.child1, text='a')
self.nb.pack()
- self.nb.wait_visibility()
+ self.nb.update()
if sys.platform == 'darwin':
tb_idx = "@20,5"
else:
def test_select(self):
self.nb.pack()
- self.nb.wait_visibility()
+ self.nb.update()
success = []
tab_changed = []
def test_traversal(self):
self.nb.pack()
- self.nb.wait_visibility()
+ self.nb.update()
self.nb.select(0)
+ self.assertEqual(self.nb.identify(5, 5), 'focus')
simulate_mouse_click(self.nb, 5, 5)
self.nb.focus_force()
self.nb.event_generate('<Control-Tab>')
self.nb.tab(self.child1, text='a', underline=0)
self.nb.enable_traversal()
self.nb.focus_force()
+ self.assertEqual(self.nb.identify(5, 5), 'focus')
simulate_mouse_click(self.nb, 5, 5)
if sys.platform == 'darwin':
self.nb.event_generate('<Option-a>')
height = self.spin.winfo_height()
x = width - 5
y = height//2 - 5
+ self.assertRegex(self.spin.identify(x, y), r'.*uparrow\Z')
self.spin.event_generate('<ButtonPress-1>', x=x, y=y)
self.spin.event_generate('<ButtonRelease-1>', x=x, y=y)
self.spin.update_idletasks()
height = self.spin.winfo_height()
x = width - 5
y = height//2 + 4
+ self.assertRegex(self.spin.identify(x, y), r'.*downarrow\Z')
self.spin.event_generate('<ButtonPress-1>', x=x, y=y)
self.spin.event_generate('<ButtonRelease-1>', x=x, y=y)
self.spin.update_idletasks()
def test_bbox(self):
self.tv.pack()
self.assertEqual(self.tv.bbox(''), '')
- self.tv.wait_visibility()
self.tv.update()
item_id = self.tv.insert('', 'end')
def test_heading_callback(self):
def simulate_heading_click(x, y):
+ if tcl_version >= (8, 6):
+ self.assertEqual(self.tv.identify_column(x), '#0')
+ self.assertEqual(self.tv.identify_region(x, y), 'heading')
simulate_mouse_click(self.tv, x, y)
self.tv.update()
success = [] # no success for now
self.tv.pack()
- self.tv.wait_visibility()
self.tv.heading('#0', command=lambda: success.append(True))
self.tv.column('#0', width=100)
self.tv.update()
lambda evt: events.append(2))
self.tv.pack()
- self.tv.wait_visibility()
self.tv.update()
pos_y = set()
# ['active selected', 'grey', 'focus', [1, 2, 3, 4]]
opt_val = []
for *state, val in items:
- # hacks for backward compatibility
- state[0] # raise IndexError if empty
if len(state) == 1:
# if it is empty (something that evaluates to False), then
# format it to Tcl code to denote the "normal" state
def _list_from_statespec(stuple):
"""Construct a list from the given statespec tuple according to the
accepted statespec accepted by _format_mapdict."""
- nval = []
- for val in stuple:
- typename = getattr(val, 'typename', None)
- if typename is None:
- nval.append(val)
- else: # this is a Tcl object
+ if isinstance(stuple, str):
+ return stuple
+ result = []
+ it = iter(stuple)
+ for state, val in zip(it, it):
+ if hasattr(state, 'typename'): # this is a Tcl object
+ state = str(state).split()
+ elif isinstance(state, str):
+ state = state.split()
+ elif not isinstance(state, (tuple, list)):
+ state = (state,)
+ if hasattr(val, 'typename'):
val = str(val)
- if typename == 'StateSpec':
- val = val.split()
- nval.append(val)
+ result.append((*state, val))
- it = iter(nval)
- return [_flatten(spec) for spec in zip(it, it)]
+ return result
def _list_from_layouttuple(tk, ltuple):
"""Construct a list from the tuple returned by ttk::layout, this is
or something else of your preference. A statespec is compound of
one or more states and then a value."""
if query_opt is not None:
- return _list_from_statespec(self.tk.splitlist(
- self.tk.call(self._name, "map", style, '-%s' % query_opt)))
+ result = self.tk.call(self._name, "map", style, '-%s' % query_opt)
+ return _list_from_statespec(self.tk.splitlist(result))
- return _splitdict(
- self.tk,
- self.tk.call(self._name, "map", style, *_format_mapdict(kw)),
- conv=_tclobj_to_py)
+ result = self.tk.call(self._name, "map", style, *_format_mapdict(kw))
+ return {k: _list_from_statespec(self.tk.splitlist(v))
+ for k, v in _splitdict(self.tk, result).items()}
def lookup(self, style, option, state=None, default=None):
_seen=_seen)
else:
context = None
- self.exc_traceback = exc_traceback
self.__cause__ = cause
self.__context__ = context
self.__suppress_context__ = \
not self.__suppress_context__):
yield from self.__context__.format(chain=chain)
yield _context_message
- if self.exc_traceback is not None:
+ if self.stack:
yield 'Traceback (most recent call last):\n'
- yield from self.stack.format()
+ yield from self.stack.format()
yield from self.format_exception_only()
typically enough to uniquely identify a type. For everything
else, we fall back on repr(obj).
"""
+ if isinstance(obj, types.GenericAlias):
+ return repr(obj)
if isinstance(obj, type):
if obj.__module__ == 'builtins':
return obj.__qualname__
f" actual {alen}, expected {elen}")
+def _deduplicate(params):
+ # Weed out strict duplicates, preserving the first of each occurrence.
+ all_params = set(params)
+ if len(all_params) < len(params):
+ new_params = []
+ for t in params:
+ if t in all_params:
+ new_params.append(t)
+ all_params.remove(t)
+ params = new_params
+ assert not all_params, all_params
+ return params
+
+
def _remove_dups_flatten(parameters):
"""An internal helper for Union creation and substitution: flatten Unions
among parameters, then remove duplicates.
params.extend(p[1:])
else:
params.append(p)
- # Weed out strict duplicates, preserving the first of each occurrence.
- all_params = set(params)
- if len(all_params) < len(params):
- new_params = []
- for t in params:
- if t in all_params:
- new_params.append(t)
- all_params.remove(t)
- params = new_params
- assert not all_params, all_params
+
+ return tuple(_deduplicate(params))
+
+
+def _flatten_literal_params(parameters):
+ """An internal helper for Literal creation: flatten Literals among parameters"""
+ params = []
+ for p in parameters:
+ if isinstance(p, _LiteralGenericAlias):
+ params.extend(p.__args__)
+ else:
+ params.append(p)
return tuple(params)
_cleanups = []
-def _tp_cache(func):
+def _tp_cache(func=None, /, *, typed=False):
"""Internal wrapper caching __getitem__ of generic types with a fallback to
original function for non-hashable arguments.
"""
- cached = functools.lru_cache()(func)
- _cleanups.append(cached.cache_clear)
+ def decorator(func):
+ cached = functools.lru_cache(typed=typed)(func)
+ _cleanups.append(cached.cache_clear)
- @functools.wraps(func)
- def inner(*args, **kwds):
- try:
- return cached(*args, **kwds)
- except TypeError:
- pass # All real errors (not unhashable args) are raised below.
- return func(*args, **kwds)
- return inner
+ @functools.wraps(func)
+ def inner(*args, **kwds):
+ try:
+ return cached(*args, **kwds)
+ except TypeError:
+ pass # All real errors (not unhashable args) are raised below.
+ return func(*args, **kwds)
+ return inner
+
+ if func is not None:
+ return decorator(func)
+ return decorator
def _eval_type(t, globalns, localns, recursive_guard=frozenset()):
"""Evaluate all forward references in the given type t.
def __getitem__(self, parameters):
return self._getitem(self, parameters)
+
+class _LiteralSpecialForm(_SpecialForm, _root=True):
+ @_tp_cache(typed=True)
+ def __getitem__(self, parameters):
+ return self._getitem(self, parameters)
+
+
@_SpecialForm
def Any(self, parameters):
"""Special type indicating an unconstrained type.
arg = _type_check(parameters, f"{self} requires a single type.")
return Union[arg, type(None)]
-@_SpecialForm
+@_LiteralSpecialForm
def Literal(self, parameters):
"""Special typing form to define literal types (a.k.a. value types).
"""
# There is no '_type_check' call because arguments to Literal[...] are
# values, not types.
- return _GenericAlias(self, parameters)
+ if not isinstance(parameters, tuple):
+ parameters = (parameters,)
+
+ parameters = _flatten_literal_params(parameters)
+
+ try:
+ parameters = tuple(p for p, _ in _deduplicate(list(_value_and_type_iter(parameters))))
+ except TypeError: # unhashable parameters
+ pass
+
+ return _LiteralGenericAlias(self, parameters)
class ForwardRef(_Final, _root=True):
return super().__repr__()
+def _value_and_type_iter(parameters):
+ return ((p, type(p)) for p in parameters)
+
+
+class _LiteralGenericAlias(_GenericAlias, _root=True):
+
+ def __eq__(self, other):
+ if not isinstance(other, _LiteralGenericAlias):
+ return NotImplemented
+
+ return set(_value_and_type_iter(self.__args__)) == set(_value_and_type_iter(other.__args__))
+
+ def __hash__(self):
+ return hash(frozenset(_value_and_type_iter(self.__args__)))
+
+
class Generic:
"""Abstract base class for generic types.
mask = 8 * (m.group(1).count('.') + 1)
else:
mask = int(mask[1:])
+
+ if mask < 0 or mask > 32:
+ # System libraries ignore invalid prefix lengths
+ continue
+
mask = 32 - mask
if (hostIP >> mask) == (base >> mask):
cmd = "xdg-settings get default-web-browser".split()
raw_result = subprocess.check_output(cmd, stderr=subprocess.DEVNULL)
result = raw_result.decode().strip()
- except (FileNotFoundError, subprocess.CalledProcessError, PermissionError) :
+ except (FileNotFoundError, subprocess.CalledProcessError, PermissionError, NotADirectoryError) :
pass
else:
global _os_preferred_browser
self._declared_ns_stack[-1].append((uri, prefix))
return f'{prefix}:{tag}' if prefix else tag, tag, uri
+ if not uri:
+ # As soon as a default namespace is defined,
+ # anything that has no namespace (and thus, no prefix) goes there.
+ return tag, tag, uri
+
raise ValueError(f'Namespace "{uri}" is not declared in scope')
def data(self, data):
centDirSize, centDirOffset, len(self._comment))
self.fp.write(endrec)
self.fp.write(self._comment)
+ if self.mode == "a":
+ self.fp.truncate()
self.fp.flush()
def _fpclose(self, fp):
DEPSRC = os.path.join(WORKDIR, 'third-party')
DEPSRC = os.path.expanduser('~/Universal/other-sources')
-universal_opts_map = { '32-bit': ('i386', 'ppc',),
+universal_opts_map = { 'universal2': ('arm64', 'x86_64'),
+ '32-bit': ('i386', 'ppc',),
'64-bit': ('x86_64', 'ppc64',),
'intel': ('i386', 'x86_64'),
'intel-32': ('i386',),
'3-way': ('ppc', 'i386', 'x86_64'),
'all': ('i386', 'ppc', 'x86_64', 'ppc64',) }
default_target_map = {
+ 'universal2': '10.9',
'64-bit': '10.5',
'3-way': '10.5',
'intel': '10.5',
def getDeptargetTuple():
return tuple([int(n) for n in DEPTARGET.split('.')[0:2]])
+def getBuildTuple():
+ return tuple([int(n) for n in platform.mac_ver()[0].split('.')[0:2]])
+
def getTargetCompilers():
target_cc_map = {
'10.4': ('gcc-4.0', 'g++-4.0'),
def internalTk():
return getDeptargetTuple() >= (10, 6)
+# Do we use 8.6.8 when building our own copy
+# of Tcl/Tk or a modern version.
+# We use the old version when buildin on
+# old versions of macOS due to build issues.
+def useOldTk():
+ return getBuildTuple() < (10, 15)
+
+
+def tweak_tcl_build(basedir, archList):
+ with open("Makefile", "r") as fp:
+ contents = fp.readlines()
+
+ # For reasons I don't understand the tcl configure script
+ # decides that some stdlib symbols aren't present, before
+ # deciding that strtod is broken.
+ new_contents = []
+ for line in contents:
+ if line.startswith("COMPAT_OBJS"):
+ # note: the space before strtod.o is intentional,
+ # the detection of a broken strtod results in
+ # "fixstrod.o" on this line.
+ for nm in ("strstr.o", "strtoul.o", " strtod.o"):
+ line = line.replace(nm, "")
+ new_contents.append(line)
+
+ with open("Makefile", "w") as fp:
+ fp.writelines(new_contents)
+
# List of names of third party software built with this installer.
# The names will be inserted into the rtf version of the License.
THIRD_PARTY_LIBS = []
buildrecipe=build_universal_openssl,
configure=None,
install=None,
+ patches=[
+ "openssl-mac-arm64.patch",
+ ],
),
])
if internalTk():
+ if useOldTk():
+ tcl_tk_ver='8.6.8'
+ tcl_checksum='81656d3367af032e0ae6157eff134f89'
+
+ tk_checksum='5e0faecba458ee1386078fb228d008ba'
+ tk_patches = ['tk868_on_10_8_10_9.patch']
+
+ else:
+ tcl_tk_ver='8.6.10'
+ tcl_checksum='97c55573f8520bcab74e21bfd8d0aadc'
+
+ tk_checksum='602a47ad9ecac7bf655ada729d140a94'
+ tk_patches = [ ]
+
+
result.extend([
dict(
- name="Tcl 8.6.8",
- url="ftp://ftp.tcl.tk/pub/tcl//tcl8_6/tcl8.6.8-src.tar.gz",
- checksum='81656d3367af032e0ae6157eff134f89',
+ name="Tcl %s"%(tcl_tk_ver,),
+ url="ftp://ftp.tcl.tk/pub/tcl//tcl8_6/tcl%s-src.tar.gz"%(tcl_tk_ver,),
+ checksum=tcl_checksum,
buildDir="unix",
configure_pre=[
'--enable-shared',
'--libdir=/Library/Frameworks/Python.framework/Versions/%s/lib'%(getVersion(),),
],
useLDFlags=False,
+ buildrecipe=tweak_tcl_build,
install='make TCL_LIBRARY=%(TCL_LIBRARY)s && make install TCL_LIBRARY=%(TCL_LIBRARY)s DESTDIR=%(DESTDIR)s'%{
"DESTDIR": shellQuote(os.path.join(WORKDIR, 'libraries')),
"TCL_LIBRARY": shellQuote('/Library/Frameworks/Python.framework/Versions/%s/lib/tcl8.6'%(getVersion())),
},
),
dict(
- name="Tk 8.6.8",
- url="ftp://ftp.tcl.tk/pub/tcl//tcl8_6/tk8.6.8-src.tar.gz",
- checksum='5e0faecba458ee1386078fb228d008ba',
- patches=[
- "tk868_on_10_8_10_9.patch",
- ],
+ name="Tk %s"%(tcl_tk_ver,),
+ url="ftp://ftp.tcl.tk/pub/tcl//tcl8_6/tk%s-src.tar.gz"%(tcl_tk_ver,),
+ checksum=tk_checksum,
+ patches=tk_patches,
buildDir="unix",
configure_pre=[
'--enable-aqua',
),
),
dict(
- name="SQLite 3.32.3",
- url="https://sqlite.org/2020/sqlite-autoconf-3320300.tar.gz",
- checksum='2e3911a3c15e85c2f2d040154bbe5ce3',
+ name="SQLite 3.33.0",
+ url="https://sqlite.org/2020/sqlite-autoconf-3330000.tar.gz",
+ checksum='842a8a100d7b01b09e543deb2b7951dd',
extra_cflags=('-Os '
'-DSQLITE_ENABLE_FTS5 '
'-DSQLITE_ENABLE_FTS4 '
Check that we're running on a supported system.
"""
- if sys.version_info[0:2] < (2, 5):
- fatal("This script must be run with Python 2.5 (or later)")
+ if sys.version_info[0:2] < (2, 7):
+ fatal("This script must be run with Python 2.7 (or later)")
if platform.system() != 'Darwin':
fatal("This script should be run on a macOS 10.5 (or later) system")
base_path = base_path + ':' + OLD_DEVELOPER_TOOLS
os.environ['PATH'] = base_path
print("Setting default PATH: %s"%(os.environ['PATH']))
- # Ensure we have access to sphinx-build.
- # You may have to create a link in /usr/bin for it.
- runCommand('sphinx-build --version')
def parseOptions(args=None):
"""
arch_opts = {
"i386": ["darwin-i386-cc"],
"x86_64": ["darwin64-x86_64-cc", "enable-ec_nistp_64_gcc_128"],
+ "arm64": ["darwin64-arm64-cc"],
"ppc": ["darwin-ppc-cc"],
"ppc64": ["darwin64-ppc-cc"],
}
if os.path.exists(outdir):
shutil.rmtree(outdir)
+ # We used to use the deployment target as the last characters of the
+ # installer file name. With the introduction of weaklinked installer
+ # variants, we may have two variants with the same file name, i.e.
+ # both ending in '10.9'. To avoid this, we now use the major/minor
+ # version numbers of the macOS version we are building on, i.e.
+ # '10.9' as before for 10.9+ variant, '11.0' for universal2 11.0-.
+ # it's not ideal but should cause the least disruption to packaging
+ # workflows.
+ build_system_version = '.'.join(platform.mac_ver()[0].split('.')[0:2])
imagepath = os.path.join(outdir,
- 'python-%s-macosx%s'%(getFullVersion(),DEPTARGET))
+ 'python-%s-macosx%s'%(getFullVersion(),build_system_version))
if INCLUDE_TIMESTAMP:
imagepath = imagepath + '-%04d-%02d-%02d'%(time.localtime()[:3])
imagepath = imagepath + '.dmg'
--- /dev/null
+diff -ur openssl-1.1.1g-orig/Configurations/10-main.conf openssl-1.1.1g/Configurations/10-main.conf
+--- openssl-1.1.1g-orig/Configurations/10-main.conf 2020-04-21 14:22:39.000000000 +0200
++++ openssl-1.1.1g/Configurations/10-main.conf 2020-07-26 12:21:32.000000000 +0200
+@@ -1557,6 +1557,14 @@
+ bn_ops => "SIXTY_FOUR_BIT_LONG",
+ perlasm_scheme => "macosx",
+ },
++ "darwin64-arm64-cc" => {
++ inherit_from => [ "darwin-common", asm("aarch64_asm") ],
++ CFLAGS => add("-Wall"),
++ cflags => add("-arch arm64"),
++ lib_cppflags => add("-DL_ENDIAN"),
++ bn_ops => "SIXTY_FOUR_BIT_LONG",
++ perlasm_scheme => "ios64",
++ },
+
+ ##### GNU Hurd
+ "hurd-x86" => {
+diff -ur openssl-1.1.1g-orig/config openssl-1.1.1g/config
+--- openssl-1.1.1g-orig/config 2020-04-21 14:22:39.000000000 +0200
++++ openssl-1.1.1g/config 2020-07-26 12:21:59.000000000 +0200
+@@ -255,6 +255,9 @@
+ ;;
+ x86_64)
+ echo "x86_64-apple-darwin${VERSION}"
++ ;;
++ arm64)
++ echo "arm64-apple-darwin${VERSION}"
+ ;;
+ *)
+ echo "i686-apple-darwin${VERSION}"
+@@ -497,6 +500,9 @@
+ else
+ OUT="darwin64-x86_64-cc"
+ fi ;;
++ x86_64-apple-darwin*)
++ OUT="darwin64-arm64-cc"
++ ;;
+ armv6+7-*-iphoneos)
+ __CNF_CFLAGS="$__CNF_CFLAGS -arch armv6 -arch armv7"
+ __CNF_CXXFLAGS="$__CNF_CXXFLAGS -arch armv6 -arch armv7"
\f3\fmodern\fcharset0 CourierNewPSMT;}
{\colortbl;\red255\green255\blue255;}
{\*\expandedcolortbl;;}
-\margl1440\margr1440\vieww13380\viewh14600\viewkind0
+\margl1440\margr1440\vieww13380\viewh14580\viewkind0
\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0
\f0\fs24 \cf0 This package will install Python $FULL_VERSION for macOS $MACOSX_DEPLOYMENT_TARGET for the following architecture(s): $ARCHITECTURES.\
\f0\b0 button to proceed.\
\
-\f1\b \ul Other changes\
+\f1\b \ul macOS 11.0 (Big Sur) and Apple Silicon Mac support [new in 3.9.1]\
+
+\f0\b0 \ulnone \
+As of 2020-11, macOS 11.0 (Big Sur) is the latest release of macOS and one of its major features is the support of new Apple Silicon Macs that are based on the ARM64 CPU architecture specification rather than the Intel 64 (x86_64) architecture used previously. There are other changes in Big Sur that affect Python operation regardless of CPU architecture. As of 3.9.1, Python binaries from python.org fully support Big Sur. \
+\
+python.org binaries for macOS have been provided via a downloadable installer that supports the Intel 64 architecture on macOS 10.9 and newer. This installer variant remains the default download for 3.9.1; it will install and run on all Macs that run macOS 10.9 or later, including 11.0 (Big Sur). This variant should run transparently on new Apple Silicon Macs using Apple's Rosetta 2 emulation. \
+\
+Beginning with 3.9.1, we also provide a new "universal2" installer variant that provides universal binaries for both ARM64 and Intel 64 architectures and is also supported on all Macs that support macOS 10.9 or later. Some of the advantages of the new installer variant: native ARM64 code on Apple Silicon Macs should run significantly faster than Rosetta2-emulated code; some operating system functions and options introduced in macOS releases since 10.9 are now exposed when available (primarily in the os module); binary wheels built for use with the current 10.9 variant *should* also work with the new variant; the new installer variant includes Tcl/Tk 8.6.10 rather than 8.6.8.\
+\
+Because of the scope of changes needed to fully support 11.0 and Apple Silicon Macs, the new "universal2" variant should be considered
+\f2\i experimental
+\f0\i0 in the 3.9.1 release. You may need to upgrade third-party components, like pip, to later versions once they are released. You may experience differences in behavior in IDLE and other Tk-based applications due to using the newer version of Tk. As always, if you encounter problems when using this installer variant, please check {\field{\*\fldinst{HYPERLINK "https://bugs.python.org"}}{\fldrslt https://bugs.python.org}} for existing reports and for opening new issues.\
+
+\f1\b \ul \
+Other changes\
\f0\b0 \ulnone \
For other changes in this release, see the
using the configure option ``--with-universal-archs=VALUE``. The following
values are available:
+ * ``universal2``: ``arm64``, ``x86_64``
+
* ``intel``: ``i386``, ``x86_64``
* ``intel-32``: ``i386``
* 10.15 and later SDKs support ``intel-64`` only
+ * 11.0 and later SDKs support ``universal2``
+
The makefile for a framework build will also install ``python3.x-32``
binaries when the universal architecture includes at least one 32-bit
architecture (that is, for all flavors but ``64-bit`` and ``intel-64``).
And lastly a framework installation installs files in ``/usr/local/bin``, all of
them symbolic links to files in ``/Library/Frameworks/Python.framework/Versions/X.Y/bin``.
+Weak linking support
+====================
+
+The CPython sources support building with the latest SDK while targetting deployment
+to macOS 10.9. This is done through weak linking of symbols introduced in macOS
+10.10 or later and checking for their availability at runtime.
+
+This requires the use of Apple's compiler toolchain on macOS 10.13 or later.
+
+The basic implementation pattern is:
+
+* ``HAVE_<FUNCTION>`` is a macro defined (or not) by the configure script
+
+* ``HAVE_<FUNCTION>_RUNTIME`` is a macro defined in the relevant source
+ files. This expands to a call to ``__builtin_available`` when using
+ a new enough Apple compiler, and to a true value otherwise.
+
+* Use ``HAVE_<FUNCTION>_RUNTIME`` before calling ``<function>``. This macro
+ *must* be used a the sole expression in an if statement::
+
+ if (HAVE_<FUNCTION>_RUNTIME) {
+ /* <function> is available */
+ }
+
+ Or:
+
+ if (HAVE_<FUNCTION>_RUNTIME) {} else {
+ /* <function> is not available */
+ }
+
+ Using other patterns (such as ``!HAVE_<FUNCTION>_RUNTIME``) is not supported
+ by Apple's compilers.
+
Resources
=========
size_t count;
cpu_type_t cpu_types[1];
short flags = 0;
-#ifdef __LP64__
- int ch;
-#endif
if ((errno = posix_spawnattr_init(spawnattr)) != 0) {
err(2, "posix_spawnattr_int");
#elif defined(__ppc__)
cpu_types[0] = CPU_TYPE_POWERPC;
+
#elif defined(__i386__)
cpu_types[0] = CPU_TYPE_X86;
+
+#elif defined(__arm64__)
+ cpu_types[0] = CPU_TYPE_ARM64;
+
#else
# error "Unknown CPU"
+
#endif
if (posix_spawnattr_setbinpref_np(spawnattr, count,
/* We're weak-linking to posix-spawnv to ensure that
* an executable build on 10.5 can work on 10.4.
*/
- if (posix_spawn != NULL) {
+
+ if (&posix_spawn != NULL) {
posix_spawnattr_t spawnattr = NULL;
setup_spawnattr(&spawnattr);
$(srcdir)/Include/cpython/dictobject.h \
$(srcdir)/Include/cpython/fileobject.h \
$(srcdir)/Include/cpython/fileutils.h \
+ $(srcdir)/Include/cpython/frameobject.h \
$(srcdir)/Include/cpython/import.h \
$(srcdir)/Include/cpython/initconfig.h \
$(srcdir)/Include/cpython/interpreteridobject.h \
Emmanuel Arias
Alicia Arlen
Jeffrey Armstrong
+Justin Turner Arthur
Jason Asbahr
David Ascher
Ammar Askar
Erik de Bueger
Jan-Hein Bührman
Lars Buitinck
+Artem Bulgakov
Dick Bulterman
Bill Bumgarner
Jimmy Burgett
Jason Curtis
Hakan Celik
Paul Dagnelie
+Florian Dahlitz
Lisandro Dalcin
Darren Dale
Andrew Dalke
Peter Ingebretson
Tony Ingraldi
John Interrante
+Dean Inwood
Bob Ippolito
Roger Irwin
Atsuo Ishimoto
Rafe Kaplan
Jacob Kaplan-Moss
Allison Kaptur
+Yurii Karabas
Janne Karila
Per Øyvind Karlsen
Anton Kasyanov
Doug Zongker
Peter Åstrand
Vlad Emelianov
+Andrey Doroschenko
(Entries should be added in rough alphabetical order by last names)
Python News
+++++++++++
+What's New in Python 3.9.1 final?
+=================================
+
+*Release date: 2020-12-07*
+
+Core and Builtins
+-----------------
+
+- bpo-42576: ``types.GenericAlias`` will now raise a ``TypeError`` when
+ attempting to initialize with a keyword argument. Previously, this would
+ cause the interpreter to crash if the interpreter was compiled with debug
+ symbols. This does not affect interpreters compiled for release. Patch by
+ Ken Jin.
+
+Library
+-------
+
+- bpo-5054: CGIHTTPRequestHandler.run_cgi() HTTP_ACCEPT improperly parsed.
+ Replace the special purpose getallmatchingheaders with generic get_all
+ method and add relevant tests.
+
+ Original Patch by Martin Panter. Modified by Senthil Kumaran.
+
+- bpo-17735: :func:`inspect.findsource` now raises :exc:`OSError` instead of
+ :exc:`IndexError` when :attr:`co_lineno` of a code object is greater than
+ the file length. This can happen, for example, when a file is edited after
+ it was imported. PR by Irit Katriel.
+
+- bpo-42116: Fix handling of trailing comments by :func:`inspect.getsource`.
+
+- bpo-42487: ChainMap.__iter__ no longer calls __getitem__ on underlying
+ maps
+
+- bpo-42482: :class:`~traceback.TracebackException` no longer holds a
+ reference to the exception's traceback object. Consequently, instances of
+ TracebackException for equivalent but non-equal exceptions now compare as
+ equal.
+
+- bpo-42406: We fixed an issue in `pickle.whichmodule` in which importing
+ `multiprocessing` could change the how pickle identifies which module an
+ object belongs to, potentially breaking the unpickling of those objects.
+
+- bpo-34215: Clarify the error message for
+ :exc:`asyncio.IncompleteReadError` when ``expected`` is ``None``.
+
+- bpo-12800: Extracting a symlink from a tarball should succeed and
+ overwrite the symlink if it already exists. The fix is to remove the
+ existing file or symlink before extraction. Based on patch by Chris AtLee,
+ Jeffrey Kintscher, and Senthil Kumaran.
+
+Tests
+-----
+
+- bpo-41473: Reenable test_gdb on gdb 9.2 and newer:
+ https://bugzilla.redhat.com/show_bug.cgi?id=1866884 bug is fixed in gdb
+ 10.1.
+
+- bpo-42553: Fix ``test_asyncio.test_call_later()`` race condition: don't
+ measure asyncio performance in the ``call_later()`` unit test. The test
+ failed randomly on the CI.
+
+macOS
+-----
+
+- bpo-41116: If no explicit macOS SDK was specified, setup.py should check
+ for Tcl and TK frameworks in /Library/Frameworks; the previous commit
+ inadvertently broke that test.
+
+- bpo-42504: Fix build on macOS Big Sur when MACOSX_DEPLOYMENT_TARGET=11
+
+IDLE
+----
+
+- bpo-42508: Keep IDLE running on macOS. Remove obsolete workaround that
+ prevented running files with shortcuts when using new universal2
+ installers built on macOS 11.
+
+
+What's New in Python 3.9.1 release candidate 1?
+===============================================
+
+*Release date: 2020-11-24*
+
+Security
+--------
+
+- bpo-42103: Prevented potential DoS attack via CPU and RAM exhaustion when
+ processing malformed Apple Property List files in binary format.
+
+- bpo-42051: The :mod:`plistlib` module no longer accepts entity
+ declarations in XML plist files to avoid XML vulnerabilities. This should
+ not affect users as entity declarations are not used in regular plist
+ files.
+
+- bpo-40791: Add ``volatile`` to the accumulator variable in
+ ``hmac.compare_digest``, making constant-time-defeating optimizations less
+ likely.
+
+Core and Builtins
+-----------------
+
+- bpo-41686: On Windows, the ``SIGINT`` event, ``_PyOS_SigintEvent()``, is
+ now created even if Python is configured to not install signal handlers
+ (if :c:member:`PyConfig.install_signal_handlers` equals to 0, or
+ ``Py_InitializeEx(0)``).
+
+- bpo-42381: Allow assignment expressions in set literals and set
+ comprehensions as per PEP 572. Patch by Pablo Galindo.
+
+- bpo-42374: Fix a regression introduced by the new parser, where an
+ unparenthesized walrus operator was not allowed within generator
+ expressions.
+
+- bpo-42296: On Windows, fix a regression in signal handling which prevented
+ to interrupt a program using CTRL+C. The signal handler can be run in a
+ thread different than the Python thread, in which case the test deciding
+ if the thread can handle signals is wrong.
+
+- bpo-42332: :class:`types.GenericAlias` objects can now be the targets of
+ weakrefs.
+
+- bpo-42218: Fixed a bug in the PEG parser that was causing crashes in debug
+ mode. Now errors are checked in left-recursive rules to avoid cases where
+ such errors do not get handled in time and appear as long-distance crashes
+ in other places.
+
+- bpo-42214: Fixed a possible crash in the PEG parser when checking for the
+ '!=' token in the ``barry_as_flufl`` rule. Patch by Pablo Galindo.
+
+- bpo-42143: Fix handling of errors during creation of ``PyFunctionObject``,
+ which resulted in operations on uninitialized memory. Patch by Yonatan
+ Goldschmidt.
+
+- bpo-41659: Fix a bug in the parser, where a curly brace following a
+ `primary` didn't fail immediately. This led to invalid expressions like `a
+ {b}` to throw a :exc:`SyntaxError` with a wrong offset, or invalid
+ expressions ending with a curly brace like `a {` to not fail immediately
+ in the REPL.
+
+- bpo-42150: Fix possible buffer overflow in the new parser when checking
+ for continuation lines. Patch by Pablo Galindo.
+
+- bpo-42123: Run the parser two times. On the first run, disable all the
+ rules that only generate better error messages to gain performance. If
+ there's a parse failure, run the parser a second time with those enabled.
+
+- bpo-41910: Document the default implementation of `object.__eq__`.
+
+- bpo-42057: Fix peephole optimizer misoptimize conditional jump +
+ JUMP_IF_NOT_EXC_MATCH pair.
+
+- bpo-41984: The garbage collector now tracks all user-defined classes.
+ Patch by Brandt Bucher.
+
+- bpo-41993: Fixed potential issues with removing not completely initialized
+ module from ``sys.modules`` when import fails.
+
+- bpo-41979: Star-unpacking is now allowed for with item's targets in the
+ PEG parser.
+
+- bpo-41909: Fixed stack overflow in :func:`issubclass` and
+ :func:`isinstance` when getting the ``__bases__`` attribute leads to
+ infinite recursion.
+
+- bpo-41894: When loading a native module and a load failure occurs, prevent
+ a possible UnicodeDecodeError when not running in a UTF-8 locale by
+ decoding the load error message using the current locale's encoding.
+
+- bpo-39934: Correctly count control blocks in 'except' in compiler. Ensures
+ that a syntax error, rather a fatal error, occurs for deeply nested, named
+ exception handlers.
+
+Library
+-------
+
+- bpo-42328: Fixed :meth:`tkinter.ttk.Style.map`. The function accepts now
+ the representation of the default state as empty sequence (as returned by
+ ``Style.map()``). The structure of the result is now the same on all
+ platform and does not depend on the value of ``wantobjects``.
+
+- bpo-42345: Fix various issues with ``typing.Literal`` parameter handling
+ (flatten, deduplicate, use type to cache key). Patch provided by Yurii
+ Karabas.
+
+- bpo-42350: Fix the :class:`threading.Thread` class at fork: do nothing if
+ the thread is already stopped (ex: fork called at Python exit).
+ Previously, an error was logged in the child process.
+
+- bpo-42014: The ``onerror`` callback from ``shutil.rmtree`` now receives
+ correct function when ``os.open`` fails.
+
+- bpo-42237: Fix `os.sendfile()` on illumos.
+
+- bpo-42249: Fixed writing binary Plist files larger than 4 GiB.
+
+- bpo-35455: On Solaris, :func:`~time.thread_time` is now implemented with
+ ``gethrvtime()`` because ``clock_gettime(CLOCK_THREAD_CPUTIME_ID)`` is not
+ always available. Patch by Jakub Kulik.
+
+- bpo-42233: The :func:`repr` of :mod:`typing` types containing
+ :ref:`Generic Alias Types <types-genericalias>` previously did not show
+ the parameterized types in the ``GenericAlias``. They have now been
+ changed to do so.
+
+- bpo-41754: webbrowser: Ignore *NotADirectoryError* when calling
+ ``xdg-settings``.
+
+- bpo-29566: ``binhex.binhex()`` consisently writes macOS 9 line endings.
+
+- bpo-42183: Fix a stack overflow error for asyncio Task or Future repr().
+
+ The overflow occurs under some circumstances when a Task or Future
+ recursively returns itself.
+
+- bpo-42146: Fix memory leak in :func:`subprocess.Popen` in case an uid
+ (gid) specified in `user` (`group`, `extra_groups`) overflows `uid_t`
+ (`gid_t`).
+
+- bpo-42140: Improve asyncio.wait function to create the futures set just
+ one time.
+
+- bpo-42103: :exc:`~plistlib.InvalidFileException` and :exc:`RecursionError`
+ are now the only errors caused by loading malformed binary Plist file
+ (previously ValueError and TypeError could be raised in some specific
+ cases).
+
+- bpo-41052: Pickling heap types implemented in C with protocols 0 and 1
+ raises now an error instead of producing incorrect data.
+
+- bpo-41491: plistlib: fix parsing XML plists with hexadecimal integer
+ values
+
+- bpo-42065: Fix an incorrectly formatted error from
+ :meth:`_codecs.charmap_decode` when called with a mapped value outside the
+ range of valid Unicode code points. PR by Max Bernstein.
+
+- bpo-41966: Fix pickling pure Python :class:`datetime.time` subclasses.
+ Patch by Dean Inwood.
+
+- bpo-41976: Fixed a bug that was causing :func:`ctypes.util.find_library`
+ to return ``None`` when triying to locate a library in an environment when
+ gcc>=9 is available and ``ldconfig`` is not. Patch by Pablo Galindo
+
+- bpo-41900: C14N 2.0 serialisation in xml.etree.ElementTree failed for
+ unprefixed attributes when a default namespace was defined.
+
+- bpo-41840: Fix a bug in the :mod:`symtable` module that was causing
+ module-scope global variables to not be reported as both local and global.
+ Patch by Pablo Galindo.
+
+- bpo-41831: ``str()`` for the ``type`` attribute of the ``tkinter.Event``
+ object always returns now the numeric code returned by Tk instead of the
+ name of the event type.
+
+- bpo-41817: fix `tkinter.EventType` Enum so all members are strings, and
+ none are tuples
+
+- bpo-41815: Fix SQLite3 segfault when backing up closed database. Patch
+ contributed by Peter David McCormick.
+
+- bpo-41316: Fix the :mod:`tarfile` module to write only basename of TAR
+ file to GZIP compression header.
+
+- bpo-16936: Allow ``ctypes.wintypes`` to be imported on non-Windows
+ systems.
+
+- bpo-40592: :func:`shutil.which` now ignores empty entries in
+ :envvar:`PATHEXT` instead of treating them as a match.
+
+- bpo-40550: Fix time-of-check/time-of-action issue in
+ subprocess.Popen.send_signal.
+
+- bpo-40492: Fix ``--outfile`` for :mod:`cProfile` / :mod:`profile` not
+ writing the output file in the original directory when the program being
+ profiled changes the working directory. PR by Anthony Sottile.
+
+- bpo-40105: ZipFile truncates files to avoid corruption when a shorter
+ comment is provided in append ("a") mode. Patch by Jan Mazur.
+
+- bpo-27321: Fixed KeyError exception when flattening an email to a string
+ attempts to replace a non-existent Content-Transfer-Encoding header.
+
+Documentation
+-------------
+
+- bpo-42153: Fix the URL for the IMAP protocol documents.
+
+- bpo-42061: Document __format__ functionality for IP addresses.
+
+- bpo-42010: Clarify that subscription expressions are also valid for
+ certain :term:`classes <class>` and :term:`types <type>` in the standard
+ library, and for user-defined classes and types if the classmethod
+ :meth:`__class_getitem__` is provided.
+
+- bpo-41805: Documented :ref:`generic alias type <types-genericalias>` and
+ :data:`types.GenericAlias`. Also added an entry in glossary for
+ :term:`generic types <generic type>`.
+
+- bpo-41774: In Programming FAQ "Sequences (Tuples/Lists)" section, add "How
+ do you remove multiple items from a list".
+
+- bpo-35293: Fix RemovedInSphinx40Warning when building the documentation.
+ Patch by Dong-hee Na.
+
+- bpo-41726: Update the refcounts info of ``PyType_FromModuleAndSpec``.
+
+- bpo-39693: Fix tarfile's extractfile documentation
+
+- bpo-39416: Document some restrictions on the default string
+ representations of numeric classes.
+
+Tests
+-----
+
+- bpo-40754: Include ``_testinternalcapi`` module in Windows installer for
+ test suite
+
+- bpo-41739: Fix test_logging.test_race_between_set_target_and_flush(): the
+ test now waits until all threads complete to avoid leaking running
+ threads.
+
+- bpo-41970: Avoid a test failure in ``test_lib2to3`` if the module has
+ already imported at the time the test executes. Patch by Pablo Galindo.
+
+- bpo-41944: Tests for CJK codecs no longer call ``eval()`` on content
+ received via HTTP.
+
+- bpo-41939: Fix test_site.test_license_exists_at_url(): call
+ ``urllib.request.urlcleanup()`` to reset the global
+ ``urllib.request._opener``. Patch by Victor Stinner.
+
+- bpo-41561: test_ssl: skip test_min_max_version_mismatch when TLS 1.0 is
+ not available
+
+- bpo-41602: Add tests for SIGINT handling in the runpy module.
+
+- bpo-41306: Fixed a failure in ``test_tk.test_widgets.ScaleTest`` happening
+ when executing the test with Tk 8.6.10.
+
+Build
+-----
+
+- bpo-42398: Fix a race condition in "make regen-all" when make -jN option
+ is used to run jobs in parallel. The clinic.py script now only use atomic
+ write to write files. Moveover, generated files are now left unchanged if
+ the content does not change, to not change the file modification time.
+
+- bpo-41617: Fix building ``pycore_bitutils.h`` internal header on old clang
+ version without ``__builtin_bswap16()`` (ex: Xcode 4.6.3 on Mac OS X
+ 10.7). Patch by Joshua Root and Victor Stinner.
+
+- bpo-38249: Update :c:macro:`Py_UNREACHABLE` to use __builtin_unreachable()
+ if only the compiler is able to use it. Patch by Dong-hee Na.
+
+- bpo-40998: Addressed three compiler warnings found by undefined behavior
+ sanitizer (ubsan).
+
+Windows
+-------
+
+- bpo-42120: Remove macro definition of ``copysign`` (to ``_copysign``) in
+ headers.
+
+- bpo-38439: Updates the icons for IDLE in the Windows Store package.
+
+- bpo-41744: Fixes automatic import of props file when using the Nuget
+ package.
+
+- bpo-41557: Update Windows installer to use SQLite 3.33.0.
+
+- bpo-38324: Avoid Unicode errors when accessing certain locale data on
+ Windows.
+
+macOS
+-----
+
+- bpo-41116: Ensure distutils.unixxcompiler.find_library_file can find
+ system provided libraries on macOS 11.
+
+- bpo-41100: Add support for macOS 11 and Apple Silicon systems.
+
+ It is now possible to build "Universal 2" binaries using
+ "--enable-universalsdk --with-universal-archs=universal2".
+
+ Binaries build on later macOS versions can be deployed back to older
+ versions (tested up to macOS 10.9), when using the correct deployment
+ target. This is tested using Xcode 11 and later.
+
+- bpo-38443: The ``--enable-universalsdk`` and ``--with-universal-archs``
+ options for the configure script now check that the specified
+ architectures can be used.
+
+- bpo-41471: Ignore invalid prefix lengths in system proxy excludes.
+
+- bpo-41557: Update macOS installer to use SQLite 3.33.0.
+
+IDLE
+----
+
+- bpo-42426: Fix reporting offset of the RE error in searchengine.
+
+- bpo-42415: Get docstrings for IDLE calltips more often by using
+ inspect.getdoc.
+
+- bpo-33987: Mostly finish using ttk widgets, mainly for editor, settings,
+ and searches. Some patches by Mark Roseman.
+
+- bpo-41775: Use 'IDLE Shell' as shell title
+
+- bpo-35764: Rewrite the Calltips doc section.
+
+- bpo-40181: In calltips, stop reminding that '/' marks the end of
+ positional-only arguments.
+
+- bpo-40511: Typing opening and closing parentheses inside the parentheses
+ of a function call will no longer cause unnecessary "flashing" off and on
+ of an existing open call-tip, e.g. when typed in a string literal.
+
+- bpo-38439: Add a 256×256 pixel IDLE icon to the Windows .ico file. Created
+ by Andrew Clover. Remove the low-color gif variations from the .ico file.
+
+C API
+-----
+
+- bpo-42015: Fix potential crash in deallocating method objects when
+ dynamically allocated `PyMethodDef`'s lifetime is managed through the
+ ``self`` argument of a `PyCFunction`.
+
+- bpo-41986: :c:data:`Py_FileSystemDefaultEncodeErrors` and
+ :c:data:`Py_UTF8Mode` are available again in limited API.
+
+
What's New in Python 3.9.0 final?
=================================
- bpo-33387: Removed WITH_CLEANUP_START, WITH_CLEANUP_FINISH, BEGIN_FINALLY,
END_FINALLY, CALL_FINALLY and POP_FINALLY bytecodes. Replaced with RERAISE
- and WITH_EXCEPT_FINISH bytecodes. The compiler now generates different
- code for exceptional and non-exceptional branches for 'with' and
- 'try-except' statements. For 'try-finally' statements the 'finally' block
- is replicated for each exit from the 'try' body.
+ and WITH_EXCEPT_START bytecodes. The compiler now generates different code
+ for exceptional and non-exceptional branches for 'with' and 'try-except'
+ statements. For 'try-finally' statements the 'finally' block is replicated
+ for each exit from the 'try' body.
Library
-------
#include "Python.h"
#include "frameobject.h"
+#include <stdbool.h>
+
#include <ffi.h>
#ifdef MS_WIN32
#include <windows.h>
Py_XDECREF(self->callable);
Py_XDECREF(self->restype);
if (self->pcl_write)
- ffi_closure_free(self->pcl_write);
+ Py_ffi_closure_free(self->pcl_write);
PyObject_GC_Del(self);
}
assert(CThunk_CheckExact((PyObject *)p));
- p->pcl_write = ffi_closure_alloc(sizeof(ffi_closure),
- &p->pcl_exec);
+ p->pcl_write = Py_ffi_closure_alloc(sizeof(ffi_closure), &p->pcl_exec);
if (p->pcl_write == NULL) {
PyErr_NoMemory();
goto error;
"ffi_prep_cif failed with %d", result);
goto error;
}
-#if defined(X86_DARWIN) || defined(POWERPC_DARWIN)
- result = ffi_prep_closure(p->pcl_write, &p->cif, closure_fcn, p);
+#if HAVE_FFI_PREP_CLOSURE_LOC
+# if USING_APPLE_OS_LIBFFI
+# define HAVE_FFI_PREP_CLOSURE_LOC_RUNTIME __builtin_available(macos 10.15, ios 13, watchos 6, tvos 13, *)
+# else
+# define HAVE_FFI_PREP_CLOSURE_LOC_RUNTIME 1
+# endif
+ if (HAVE_FFI_PREP_CLOSURE_LOC_RUNTIME) {
+ result = ffi_prep_closure_loc(p->pcl_write, &p->cif, closure_fcn,
+ p,
+ p->pcl_exec);
+ } else
+#endif
+ {
+#if USING_APPLE_OS_LIBFFI && defined(__arm64__)
+ PyErr_Format(PyExc_NotImplementedError, "ffi_prep_closure_loc() is missing");
+ goto error;
#else
- result = ffi_prep_closure_loc(p->pcl_write, &p->cif, closure_fcn,
- p,
- p->pcl_exec);
+#if defined(__clang__) || defined(MACOSX)
+ #pragma clang diagnostic push
+ #pragma clang diagnostic ignored "-Wdeprecated-declarations"
+#endif
+#if defined(__GNUC__)
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
+ result = ffi_prep_closure(p->pcl_write, &p->cif, closure_fcn, p);
+
+#if defined(__clang__) || defined(MACOSX)
+ #pragma clang diagnostic pop
+#endif
+#if defined(__GNUC__)
+ #pragma GCC diagnostic pop
+#endif
+
+#endif
+ }
if (result != FFI_OK) {
PyErr_Format(PyExc_RuntimeError,
"ffi_prep_closure failed with %d", result);
#include "Python.h"
#include "structmember.h" // PyMemberDef
+#include <stdbool.h>
+
#ifdef MS_WIN32
#include <windows.h>
#include <tchar.h>
#include "ctypes_dlfcn.h"
#endif
+#ifdef __APPLE__
+#include <mach-o/dyld.h>
+#endif
+
#ifdef MS_WIN32
#include <malloc.h>
#endif
ffi_type **atypes,
ffi_type *restype,
void *resmem,
- int argcount)
+ int argcount,
+ int argtypecount)
{
PyThreadState *_save = NULL; /* For Py_BLOCK_THREADS and Py_UNBLOCK_THREADS */
PyObject *error_object = NULL;
if ((flags & FUNCFLAG_CDECL) == 0)
cc = FFI_STDCALL;
#endif
- if (FFI_OK != ffi_prep_cif(&cif,
- cc,
- argcount,
- restype,
- atypes)) {
- PyErr_SetString(PyExc_RuntimeError,
- "ffi_prep_cif failed");
- return -1;
+
+# if USING_APPLE_OS_LIBFFI
+# define HAVE_FFI_PREP_CIF_VAR_RUNTIME __builtin_available(macos 10.15, ios 13, watchos 6, tvos 13, *)
+# elif HAVE_FFI_PREP_CIF_VAR
+# define HAVE_FFI_PREP_CIF_VAR_RUNTIME true
+# else
+# define HAVE_FFI_PREP_CIF_VAR_RUNTIME false
+# endif
+
+ /* Even on Apple-arm64 the calling convention for variadic functions conincides
+ * with the standard calling convention in the case that the function called
+ * only with its fixed arguments. Thus, we do not need a special flag to be
+ * set on variadic functions. We treat a function as variadic if it is called
+ * with a nonzero number of variadic arguments */
+ bool is_variadic = (argtypecount != 0 && argcount > argtypecount);
+ (void) is_variadic;
+
+#if defined(__APPLE__) && defined(__arm64__)
+ if (is_variadic) {
+ if (HAVE_FFI_PREP_CIF_VAR_RUNTIME) {
+ } else {
+ PyErr_SetString(PyExc_NotImplementedError, "ffi_prep_cif_var() is missing");
+ return -1;
+ }
+ }
+#endif
+
+#if HAVE_FFI_PREP_CIF_VAR
+ if (is_variadic) {
+ if (HAVE_FFI_PREP_CIF_VAR_RUNTIME) {
+ if (FFI_OK != ffi_prep_cif_var(&cif,
+ cc,
+ argtypecount,
+ argcount,
+ restype,
+ atypes)) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "ffi_prep_cif_var failed");
+ return -1;
+ }
+ } else {
+ if (FFI_OK != ffi_prep_cif(&cif,
+ cc,
+ argcount,
+ restype,
+ atypes)) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "ffi_prep_cif failed");
+ return -1;
+ }
+ }
+ } else
+#endif
+
+ {
+ if (FFI_OK != ffi_prep_cif(&cif,
+ cc,
+ argcount,
+ restype,
+ atypes)) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "ffi_prep_cif failed");
+ return -1;
+ }
}
if (flags & (FUNCFLAG_USE_ERRNO | FUNCFLAG_USE_LASTERROR)) {
if (-1 == _call_function_pointer(flags, pProc, avalues, atypes,
rtype, resbuf,
- Py_SAFE_DOWNCAST(argcount,
- Py_ssize_t,
- int)))
+ Py_SAFE_DOWNCAST(argcount, Py_ssize_t, int),
+ Py_SAFE_DOWNCAST(argtype_count, Py_ssize_t, int)))
goto cleanup;
#ifdef WORDS_BIGENDIAN
}
#else
+#ifdef HAVE_DYLD_SHARED_CACHE_CONTAINS_PATH
+static PyObject *py_dyld_shared_cache_contains_path(PyObject *self, PyObject *args)
+{
+ PyObject *name, *name2;
+ char *name_str;
+
+ if (__builtin_available(macOS 11.0, iOS 14.0, tvOS 14.0, watchOS 7.0, *)) {
+ int r;
+
+ if (!PyArg_ParseTuple(args, "O", &name))
+ return NULL;
+
+ if (name == Py_None)
+ Py_RETURN_FALSE;
+
+ if (PyUnicode_FSConverter(name, &name2) == 0)
+ return NULL;
+ name_str = PyBytes_AS_STRING(name2);
+
+ r = _dyld_shared_cache_contains_path(name_str);
+ Py_DECREF(name2);
+
+ if (r) {
+ Py_RETURN_TRUE;
+ } else {
+ Py_RETURN_FALSE;
+ }
+
+ } else {
+ PyErr_SetString(PyExc_NotImplementedError, "_dyld_shared_cache_contains_path symbol is missing");
+ return NULL;
+ }
+
+ }
+#endif
+
static PyObject *py_dl_open(PyObject *self, PyObject *args)
{
PyObject *name, *name2;
return Py_BuildValue("siN", dict->format, dict->ndim, shape);
}
+
+
PyMethodDef _ctypes_module_methods[] = {
{"get_errno", get_errno, METH_NOARGS},
{"set_errno", set_errno, METH_VARARGS},
{"dlclose", py_dl_close, METH_VARARGS, "dlclose a library"},
{"dlsym", py_dl_sym, METH_VARARGS, "find symbol in shared library"},
#endif
+#ifdef HAVE_DYLD_SHARED_CACHE_CONTAINS_PATH
+ {"_dyld_shared_cache_contains_path", py_dyld_shared_cache_contains_path, METH_VARARGS, "check if path is in the shared cache"},
+#endif
{"alignment", align_func, METH_O, alignment_doc},
{"sizeof", sizeof_func, METH_O, sizeof_doc},
{"byref", byref, METH_VARARGS, byref_doc},
return PyLong_FromLong(val);
}
-#ifdef MS_WIN32
+#ifndef MS_WIN32
+/* http://msdn.microsoft.com/en-us/library/cc237864.aspx */
+#define VARIANT_FALSE 0x0000
+#define VARIANT_TRUE 0xFFFF
+#endif
/* short BOOL - VARIANT_BOOL */
static PyObject *
vBOOL_set(void *ptr, PyObject *value, Py_ssize_t size)
{
return PyBool_FromLong((long)*(short int *)ptr);
}
-#endif
static PyObject *
bool_set(void *ptr, PyObject *value, Py_ssize_t size)
#endif
#ifdef MS_WIN32
{ 'X', BSTR_set, BSTR_get, &ffi_type_pointer},
- { 'v', vBOOL_set, vBOOL_get, &ffi_type_sshort},
#endif
+ { 'v', vBOOL_set, vBOOL_get, &ffi_type_sshort},
#if SIZEOF__BOOL == 1
{ '?', bool_set, bool_get, &ffi_type_uchar}, /* Also fallback for no native _Bool support */
#elif SIZEOF__BOOL == SIZEOF_SHORT
extern PyObject *ComError;
#endif
+#if USING_MALLOC_CLOSURE_DOT_C
+void Py_ffi_closure_free(void *p);
+void *Py_ffi_closure_alloc(size_t size, void** codeloc);
+#else
+#define Py_ffi_closure_free ffi_closure_free
+#define Py_ffi_closure_alloc ffi_closure_alloc
+#endif
+
/*
Local Variables:
compile-command: "python setup.py -q build install --home ~"
/******************************************************************/
/* put the item back into the free list */
-void ffi_closure_free(void *p)
+void Py_ffi_closure_free(void *p)
{
+#if USING_APPLE_OS_LIBFFI && HAVE_FFI_CLOSURE_ALLOC
+ if (__builtin_available(macos 10.15, ios 13, watchos 6, tvos 13, *)) {
+ ffi_closure_free(p);
+ return;
+ }
+#endif
ITEM *item = (ITEM *)p;
item->next = free_list;
free_list = item;
}
/* return one item from the free list, allocating more if needed */
-void *ffi_closure_alloc(size_t ignored, void** codeloc)
+void *Py_ffi_closure_alloc(size_t size, void** codeloc)
{
+#if USING_APPLE_OS_LIBFFI && HAVE_FFI_CLOSURE_ALLOC
+ if (__builtin_available(macos 10.15, ios 13, watchos 6, tvos 13, *)) {
+ return ffi_closure_alloc(size, codeloc);
+ }
+#endif
ITEM *item;
if (!free_list)
more_core();
#elif defined(__x86_64__)
#define CONFIG_64
#define ASM
+ #elif defined(__arm64__)
+ #define CONFIG_64
+ #define ANSI
#else
#error "unknown architecture for universal build."
#endif
static int
locale_decode_monetary(PyObject *dict, struct lconv *lc)
{
+#ifndef MS_WINDOWS
int change_locale;
change_locale = (!locale_is_ascii(lc->int_curr_symbol)
|| !locale_is_ascii(lc->currency_symbol)
}
}
+#define GET_LOCALE_STRING(ATTR) PyUnicode_DecodeLocale(lc->ATTR, NULL)
+#else /* MS_WINDOWS */
+/* Use _W_* fields of Windows struct lconv */
+#define GET_LOCALE_STRING(ATTR) PyUnicode_FromWideChar(lc->_W_ ## ATTR, -1)
+#endif /* MS_WINDOWS */
+
int res = -1;
#define RESULT_STRING(ATTR) \
do { \
PyObject *obj; \
- obj = PyUnicode_DecodeLocale(lc->ATTR, NULL); \
+ obj = GET_LOCALE_STRING(ATTR); \
if (obj == NULL) { \
goto done; \
} \
RESULT_STRING(mon_decimal_point);
RESULT_STRING(mon_thousands_sep);
#undef RESULT_STRING
+#undef GET_LOCALE_STRING
res = 0;
done:
+#ifndef MS_WINDOWS
if (loc != NULL) {
setlocale(LC_CTYPE, oldloc);
}
PyMem_Free(oldloc);
+#endif
return res;
}
Py_DECREF(obj); \
} while (0)
+#ifdef MS_WINDOWS
+/* Use _W_* fields of Windows struct lconv */
+#define GET_LOCALE_STRING(ATTR) PyUnicode_FromWideChar(lc->_W_ ## ATTR, -1)
+#else
+#define GET_LOCALE_STRING(ATTR) PyUnicode_DecodeLocale(lc->ATTR, NULL)
+#endif
#define RESULT_STRING(s)\
do { \
- x = PyUnicode_DecodeLocale(lc->s, NULL); \
+ x = GET_LOCALE_STRING(s); \
RESULT(#s, x); \
} while (0)
RESULT_INT(n_sign_posn);
/* Numeric information: LC_NUMERIC encoding */
- PyObject *decimal_point, *thousands_sep;
+ PyObject *decimal_point = NULL, *thousands_sep = NULL;
if (_Py_GetLocaleconvNumeric(lc, &decimal_point, &thousands_sep) < 0) {
+ Py_XDECREF(decimal_point);
+ Py_XDECREF(thousands_sep);
goto failed;
}
#undef RESULT
#undef RESULT_STRING
#undef RESULT_INT
+#undef GET_LOCALE_STRING
}
#if defined(HAVE_WCSCOLL)
volatile const unsigned char *left;
volatile const unsigned char *right;
Py_ssize_t i;
- unsigned char result;
+ volatile unsigned char result;
/* loop count depends on length of b */
length = len_b;
uid_t uid;
gid_t gid, *groups = NULL;
int child_umask;
- PyObject *cwd_obj, *cwd_obj2;
+ PyObject *cwd_obj, *cwd_obj2 = NULL;
const char *cwd;
pid_t pid;
int need_to_reenable_gc = 0;
cwd = PyBytes_AsString(cwd_obj2);
} else {
cwd = NULL;
- cwd_obj2 = NULL;
}
if (groups_list != Py_None) {
return PyLong_FromPid(pid);
cleanup:
+ Py_XDECREF(cwd_obj2);
if (envp)
_Py_FreeCharPArray(envp);
if (argv)
}
-/*[clinic input]
-
-_random.Random.__reduce__
-
-[clinic start generated code]*/
-
-static PyObject *
-_random_Random___reduce___impl(RandomObject *self)
-/*[clinic end generated code: output=ddea0dcdb60ffd6d input=bd38ec35fd157e0f]*/
-{
- PyErr_Format(PyExc_TypeError,
- "cannot pickle %s object",
- Py_TYPE(self)->tp_name);
- return NULL;
-}
-
static PyMethodDef random_methods[] = {
_RANDOM_RANDOM_RANDOM_METHODDEF
_RANDOM_RANDOM_SEED_METHODDEF
_RANDOM_RANDOM_GETSTATE_METHODDEF
_RANDOM_RANDOM_SETSTATE_METHODDEF
_RANDOM_RANDOM_GETRANDBITS_METHODDEF
- _RANDOM_RANDOM___REDUCE___METHODDEF
{NULL, NULL} /* sentinel */
};
if (ip == NULL) {
if (!SSL_set_tlsext_host_name(self->ssl, server_hostname)) {
_setSSLError(NULL, 0, __FILE__, __LINE__);
+ goto error;
}
}
if (self->ctx->check_hostname) {
return obj;
}
+static PyObject *
+without_gc(PyObject *Py_UNUSED(self), PyObject *obj)
+{
+ PyTypeObject *tp = (PyTypeObject*)obj;
+ if (!PyType_Check(obj) || !PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE)) {
+ return PyErr_Format(PyExc_TypeError, "heap type expected, got %R", obj);
+ }
+ if (PyType_IS_GC(tp)) {
+ // Don't try this at home, kids:
+ tp->tp_flags -= Py_TPFLAGS_HAVE_GC;
+ tp->tp_free = PyObject_Del;
+ tp->tp_traverse = NULL;
+ tp->tp_clear = NULL;
+ }
+ assert(!PyType_IS_GC(tp));
+ Py_INCREF(obj);
+ return obj;
+}
+
static PyMethodDef ml;
static PyObject *
{"meth_fastcall", (PyCFunction)(void(*)(void))meth_fastcall, METH_FASTCALL},
{"meth_fastcall_keywords", (PyCFunction)(void(*)(void))meth_fastcall_keywords, METH_FASTCALL|METH_KEYWORDS},
{"pynumber_tobase", pynumber_tobase, METH_VARARGS},
+ {"without_gc", without_gc, METH_O},
{NULL, NULL} /* sentinel */
};
trace_t *trace = (trace_t *)value;
trace_t *trace2 = raw_malloc(sizeof(trace_t));
- if (traces2 == NULL) {
+ if (trace2 == NULL) {
return -1;
}
*trace2 = *trace;
exit:
return return_value;
}
-
-PyDoc_STRVAR(_random_Random___reduce____doc__,
-"__reduce__($self, /)\n"
-"--\n"
-"\n");
-
-#define _RANDOM_RANDOM___REDUCE___METHODDEF \
- {"__reduce__", (PyCFunction)_random_Random___reduce__, METH_NOARGS, _random_Random___reduce____doc__},
-
-static PyObject *
-_random_Random___reduce___impl(RandomObject *self);
-
-static PyObject *
-_random_Random___reduce__(RandomObject *self, PyObject *Py_UNUSED(ignored))
-{
- return _random_Random___reduce___impl(self);
-}
-/*[clinic end generated code: output=d8a99be3f1192219 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=a7feb0c9c8d1b627 input=a9049054013a1b77]*/
calculate_program_macos(wchar_t **abs_path_p)
{
char execpath[MAXPATHLEN + 1];
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
uint32_t nsexeclength = Py_ARRAY_LENGTH(execpath) - 1;
-#else
- unsigned long nsexeclength = Py_ARRAY_LENGTH(execpath) - 1;
-#endif
/* On Mac OS X, if a script uses an interpreter of the form
"#!/opt/python2.3/bin/python", the kernel only passes "python"
of the compiler used. Different compilers define their own feature
test macro, e.g. '_MSC_VER'. */
-#ifdef __APPLE__
- /*
- * Step 1 of support for weak-linking a number of symbols existing on
- * OSX 10.4 and later, see the comment in the #ifdef __APPLE__ block
- * at the end of this file for more information.
- */
-# pragma weak lchown
-# pragma weak statvfs
-# pragma weak fstatvfs
-
-#endif /* __APPLE__ */
-
#define PY_SSIZE_T_CLEAN
#include "Python.h"
#include <stdio.h> /* needed for ctermid() */
+/*
+ * A number of APIs are available on macOS from a certain macOS version.
+ * To support building with a new SDK while deploying to older versions
+ * the availability test is split into two:
+ * - HAVE_<FUNCTION>: The configure check for compile time availability
+ * - HAVE_<FUNCTION>_RUNTIME: Runtime check for availability
+ *
+ * The latter is always true when not on macOS, or when using a compiler
+ * that does not support __has_builtin (older versions of Xcode).
+ *
+ * Due to compiler restrictions there is one valid use of HAVE_<FUNCTION>_RUNTIME:
+ * if (HAVE_<FUNCTION>_RUNTIME) { ... }
+ *
+ * In mixing the test with other tests or using negations will result in compile
+ * errors.
+ */
+#if defined(__APPLE__)
+
+#if defined(__has_builtin) && __has_builtin(__builtin_available)
+# define HAVE_FSTATAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
+# define HAVE_FACCESSAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
+# define HAVE_FCHMODAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
+# define HAVE_FCHOWNAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
+# define HAVE_LINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
+# define HAVE_FDOPENDIR_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
+# define HAVE_MKDIRAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
+# define HAVE_RENAMEAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
+# define HAVE_UNLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
+# define HAVE_OPENAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
+# define HAVE_READLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
+# define HAVE_SYMLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
+# define HAVE_FUTIMENS_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
+# define HAVE_UTIMENSAT_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
+# define HAVE_PWRITEV_RUNTIME __builtin_available(macOS 11.0, iOS 14.0, tvOS 14.0, watchOS 7.0, *)
+
+# define HAVE_POSIX_SPAWN_SETSID_RUNTIME __builtin_available(macOS 10.15, *)
+
+#else /* Xcode 8 or earlier */
+
+ /* __builtin_available is not present in these compilers, but
+ * some of the symbols might be weak linked (10.10 SDK or later
+ * deploying on 10.9.
+ *
+ * Fall back to the older style of availability checking for
+ * symbols introduced in macOS 10.10.
+ */
+
+# ifdef HAVE_FSTATAT
+# define HAVE_FSTATAT_RUNTIME (fstatat != NULL)
+# endif
+
+# ifdef HAVE_FACCESSAT
+# define HAVE_FACCESSAT_RUNTIME (faccessat != NULL)
+# endif
+
+# ifdef HAVE_FCHMODAT
+# define HAVE_FCHMODAT_RUNTIME (fchmodat != NULL)
+# endif
+
+# ifdef HAVE_FCHOWNAT
+# define HAVE_FCHOWNAT_RUNTIME (fchownat != NULL)
+# endif
+
+# ifdef HAVE_LINKAT
+# define HAVE_LINKAT_RUNTIME (linkat != NULL)
+# endif
+
+# ifdef HAVE_FDOPENDIR
+# define HAVE_FDOPENDIR_RUNTIME (fdopendir != NULL)
+# endif
+
+# ifdef HAVE_MKDIRAT
+# define HAVE_MKDIRAT_RUNTIME (mkdirat != NULL)
+# endif
+
+# ifdef HAVE_RENAMEAT
+# define HAVE_RENAMEAT_RUNTIME (renameat != NULL)
+# endif
+
+# ifdef HAVE_UNLINKAT
+# define HAVE_UNLINKAT_RUNTIME (unlinkat != NULL)
+# endif
+
+# ifdef HAVE_OPENAT
+# define HAVE_OPENAT_RUNTIME (openat != NULL)
+# endif
+
+# ifdef HAVE_READLINKAT
+# define HAVE_READLINKAT_RUNTIME (readlinkat != NULL)
+# endif
+
+# ifdef HAVE_SYMLINKAT
+# define HAVE_SYMLINKAT_RUNTIME (symlinkat != NULL)
+# endif
+
+#endif
+
+#ifdef HAVE_FUTIMESAT
+/* Some of the logic for weak linking depends on this assertion */
+# error "HAVE_FUTIMESAT unexpectedly defined"
+#endif
+
+#else
+# define HAVE_FSTATAT_RUNTIME 1
+# define HAVE_FACCESSAT_RUNTIME 1
+# define HAVE_FCHMODAT_RUNTIME 1
+# define HAVE_FCHOWNAT_RUNTIME 1
+# define HAVE_LINKAT_RUNTIME 1
+# define HAVE_FDOPENDIR_RUNTIME 1
+# define HAVE_MKDIRAT_RUNTIME 1
+# define HAVE_RENAMEAT_RUNTIME 1
+# define HAVE_UNLINKAT_RUNTIME 1
+# define HAVE_OPENAT_RUNTIME 1
+# define HAVE_READLINKAT_RUNTIME 1
+# define HAVE_SYMLINKAT_RUNTIME 1
+# define HAVE_FUTIMENS_RUNTIME 1
+# define HAVE_UTIMENSAT_RUNTIME 1
+# define HAVE_PWRITEV_RUNTIME 1
+#endif
+
+
#ifdef __cplusplus
extern "C" {
#endif
STRUCT_STAT st;
int result;
+#ifdef HAVE_FSTATAT
+ int fstatat_unavailable = 0;
+#endif
+
#if !defined(MS_WINDOWS) && !defined(HAVE_FSTATAT) && !defined(HAVE_LSTAT)
if (follow_symlinks_specified(function_name, follow_symlinks))
return NULL;
else
#endif /* HAVE_LSTAT */
#ifdef HAVE_FSTATAT
- if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks)
- result = fstatat(dir_fd, path->narrow, &st,
+ if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
+ if (HAVE_FSTATAT_RUNTIME) {
+ result = fstatat(dir_fd, path->narrow, &st,
follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
- else
+
+ } else {
+ fstatat_unavailable = 1;
+ }
+ } else
#endif /* HAVE_FSTATAT */
result = STAT(path->narrow, &st);
#endif /* MS_WINDOWS */
Py_END_ALLOW_THREADS
+#ifdef HAVE_FSTATAT
+ if (fstatat_unavailable) {
+ argument_unavailable_error("stat", "dir_fd");
+ return NULL;
+ }
+#endif
+
if (result != 0) {
return path_error(path);
}
int result;
#endif
+#ifdef HAVE_FACCESSAT
+ int faccessat_unavailable = 0;
+#endif
+
#ifndef HAVE_FACCESSAT
if (follow_symlinks_specified("access", follow_symlinks))
return -1;
if ((dir_fd != DEFAULT_DIR_FD) ||
effective_ids ||
!follow_symlinks) {
- int flags = 0;
- if (!follow_symlinks)
- flags |= AT_SYMLINK_NOFOLLOW;
- if (effective_ids)
- flags |= AT_EACCESS;
- result = faccessat(dir_fd, path->narrow, mode, flags);
+
+ if (HAVE_FACCESSAT_RUNTIME) {
+ int flags = 0;
+ if (!follow_symlinks)
+ flags |= AT_SYMLINK_NOFOLLOW;
+ if (effective_ids)
+ flags |= AT_EACCESS;
+ result = faccessat(dir_fd, path->narrow, mode, flags);
+ } else {
+ faccessat_unavailable = 1;
+ }
}
else
#endif
result = access(path->narrow, mode);
Py_END_ALLOW_THREADS
+
+#ifdef HAVE_FACCESSAT
+ if (faccessat_unavailable) {
+ if (dir_fd != DEFAULT_DIR_FD) {
+ argument_unavailable_error("access", "dir_fd");
+ return -1;
+ }
+ if (follow_symlinks_specified("access", follow_symlinks))
+ return -1;
+
+ if (effective_ids) {
+ argument_unavailable_error("access", "effective_ids");
+ return -1;
+ }
+ /* should be unreachable */
+ return -1;
+ }
+#endif
return_value = !result;
#endif
#ifdef HAVE_FCHMODAT
int fchmodat_nofollow_unsupported = 0;
+ int fchmodat_unsupported = 0;
#endif
#if !(defined(HAVE_FCHMODAT) || defined(HAVE_LCHMOD))
if (path->fd != -1)
result = fchmod(path->fd, mode);
else
-#endif
+#endif /* HAVE_CHMOD */
#ifdef HAVE_LCHMOD
if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
result = lchmod(path->narrow, mode);
else
-#endif
+#endif /* HAVE_LCHMOD */
#ifdef HAVE_FCHMODAT
if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
- /*
- * fchmodat() doesn't currently support AT_SYMLINK_NOFOLLOW!
- * The documentation specifically shows how to use it,
- * and then says it isn't implemented yet.
- * (true on linux with glibc 2.15, and openindiana 3.x)
- *
- * Once it is supported, os.chmod will automatically
- * support dir_fd and follow_symlinks=False. (Hopefully.)
- * Until then, we need to be careful what exception we raise.
- */
- result = fchmodat(dir_fd, path->narrow, mode,
- follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
- /*
- * But wait! We can't throw the exception without allowing threads,
- * and we can't do that in this nested scope. (Macro trickery, sigh.)
- */
- fchmodat_nofollow_unsupported =
- result &&
- ((errno == ENOTSUP) || (errno == EOPNOTSUPP)) &&
- !follow_symlinks;
+ if (HAVE_FCHMODAT_RUNTIME) {
+ /*
+ * fchmodat() doesn't currently support AT_SYMLINK_NOFOLLOW!
+ * The documentation specifically shows how to use it,
+ * and then says it isn't implemented yet.
+ * (true on linux with glibc 2.15, and openindiana 3.x)
+ *
+ * Once it is supported, os.chmod will automatically
+ * support dir_fd and follow_symlinks=False. (Hopefully.)
+ * Until then, we need to be careful what exception we raise.
+ */
+ result = fchmodat(dir_fd, path->narrow, mode,
+ follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
+ /*
+ * But wait! We can't throw the exception without allowing threads,
+ * and we can't do that in this nested scope. (Macro trickery, sigh.)
+ */
+ fchmodat_nofollow_unsupported =
+ result &&
+ ((errno == ENOTSUP) || (errno == EOPNOTSUPP)) &&
+ !follow_symlinks;
+ } else {
+ fchmodat_unsupported = 1;
+ fchmodat_nofollow_unsupported = 1;
+
+ result = -1;
+ }
}
else
-#endif
+#endif /* HAVE_FHCMODAT */
result = chmod(path->narrow, mode);
Py_END_ALLOW_THREADS
if (result) {
#ifdef HAVE_FCHMODAT
+ if (fchmodat_unsupported) {
+ if (dir_fd != DEFAULT_DIR_FD) {
+ argument_unavailable_error("chmod", "dir_fd");
+ return NULL;
+ }
+ }
+
if (fchmodat_nofollow_unsupported) {
if (dir_fd != DEFAULT_DIR_FD)
dir_fd_and_follow_symlinks_invalid("chmod",
return NULL;
}
else
-#endif
+#endif /* HAVE_FCHMODAT */
return path_error(path);
}
-#endif
+#endif /* MS_WINDOWS */
Py_RETURN_NONE;
}
{
int result;
+#if defined(HAVE_FCHOWNAT)
+ int fchownat_unsupported = 0;
+#endif
+
#if !(defined(HAVE_LCHOWN) || defined(HAVE_FCHOWNAT))
if (follow_symlinks_specified("chown", follow_symlinks))
return NULL;
fd_and_follow_symlinks_invalid("chown", path->fd, follow_symlinks))
return NULL;
-#ifdef __APPLE__
- /*
- * This is for Mac OS X 10.3, which doesn't have lchown.
- * (But we still have an lchown symbol because of weak-linking.)
- * It doesn't have fchownat either. So there's no possibility
- * of a graceful failover.
- */
- if ((!follow_symlinks) && (lchown == NULL)) {
- follow_symlinks_specified("chown", follow_symlinks);
- return NULL;
- }
-#endif
-
if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid,
dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
return NULL;
else
#endif
#ifdef HAVE_FCHOWNAT
- if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks))
+ if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
+ if (HAVE_FCHOWNAT_RUNTIME) {
result = fchownat(dir_fd, path->narrow, uid, gid,
follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
- else
+ } else {
+ fchownat_unsupported = 1;
+ }
+ } else
#endif
result = chown(path->narrow, uid, gid);
Py_END_ALLOW_THREADS
+#ifdef HAVE_FCHOWNAT
+ if (fchownat_unsupported) {
+ /* This would be incorrect if the current platform
+ * doesn't support lchown.
+ */
+ argument_unavailable_error(NULL, "dir_fd");
+ return NULL;
+ }
+#endif
+
if (result)
return path_error(path);
#else
int result;
#endif
+#if defined(HAVE_LINKAT)
+ int linkat_unavailable = 0;
+#endif
#ifndef HAVE_LINKAT
if ((src_dir_fd != DEFAULT_DIR_FD) || (dst_dir_fd != DEFAULT_DIR_FD)) {
#ifdef HAVE_LINKAT
if ((src_dir_fd != DEFAULT_DIR_FD) ||
(dst_dir_fd != DEFAULT_DIR_FD) ||
- (!follow_symlinks))
- result = linkat(src_dir_fd, src->narrow,
- dst_dir_fd, dst->narrow,
- follow_symlinks ? AT_SYMLINK_FOLLOW : 0);
+ (!follow_symlinks)) {
+
+ if (HAVE_LINKAT_RUNTIME) {
+
+ result = linkat(src_dir_fd, src->narrow,
+ dst_dir_fd, dst->narrow,
+ follow_symlinks ? AT_SYMLINK_FOLLOW : 0);
+
+ }
+#ifdef __APPLE__
+ else {
+ if (src_dir_fd == DEFAULT_DIR_FD && dst_dir_fd == DEFAULT_DIR_FD) {
+ /* See issue 41355: This matches the behaviour of !HAVE_LINKAT */
+ result = link(src->narrow, dst->narrow);
+ } else {
+ linkat_unavailable = 1;
+ }
+ }
+#endif
+ }
else
#endif /* HAVE_LINKAT */
result = link(src->narrow, dst->narrow);
Py_END_ALLOW_THREADS
+#ifdef HAVE_LINKAT
+ if (linkat_unavailable) {
+ /* Either or both dir_fd arguments were specified */
+ if (src_dir_fd != DEFAULT_DIR_FD) {
+ argument_unavailable_error("link", "src_dir_fd");
+ } else {
+ argument_unavailable_error("link", "dst_dir_fd");
+ }
+ return NULL;
+ }
+#endif
+
if (result)
return path_error2(src, dst);
#endif /* MS_WINDOWS */
errno = 0;
#ifdef HAVE_FDOPENDIR
if (path->fd != -1) {
+ if (HAVE_FDOPENDIR_RUNTIME) {
/* closedir() closes the FD, so we duplicate it */
fd = _Py_dup(path->fd);
if (fd == -1)
Py_BEGIN_ALLOW_THREADS
dirp = fdopendir(fd);
Py_END_ALLOW_THREADS
+ } else {
+ PyErr_SetString(PyExc_TypeError,
+ "listdir: path should be string, bytes, os.PathLike or None, not int");
+ return NULL;
+ }
}
else
#endif
/*[clinic end generated code: output=a70446903abe821f input=e965f68377e9b1ce]*/
{
int result;
+#ifdef HAVE_MKDIRAT
+ int mkdirat_unavailable = 0;
+#endif
if (PySys_Audit("os.mkdir", "Oii", path->object, mode,
dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
#else
Py_BEGIN_ALLOW_THREADS
#if HAVE_MKDIRAT
- if (dir_fd != DEFAULT_DIR_FD)
+ if (dir_fd != DEFAULT_DIR_FD) {
+ if (HAVE_MKDIRAT_RUNTIME) {
result = mkdirat(dir_fd, path->narrow, mode);
- else
+
+ } else {
+ mkdirat_unavailable = 1;
+ }
+ } else
#endif
#if defined(__WATCOMC__) && !defined(__QNX__)
result = mkdir(path->narrow);
result = mkdir(path->narrow, mode);
#endif
Py_END_ALLOW_THREADS
+
+#if HAVE_MKDIRAT
+ if (mkdirat_unavailable) {
+ argument_unavailable_error(NULL, "dir_fd");
+ return NULL;
+ }
+#endif
+
if (result < 0)
return path_error(path);
#endif /* MS_WINDOWS */
const char *function_name = is_replace ? "replace" : "rename";
int dir_fd_specified;
+#ifdef HAVE_RENAMEAT
+ int renameat_unavailable = 0;
+#endif
+
#ifdef MS_WINDOWS
BOOL result;
int flags = is_replace ? MOVEFILE_REPLACE_EXISTING : 0;
Py_BEGIN_ALLOW_THREADS
#ifdef HAVE_RENAMEAT
- if (dir_fd_specified)
- result = renameat(src_dir_fd, src->narrow, dst_dir_fd, dst->narrow);
- else
+ if (dir_fd_specified) {
+ if (HAVE_RENAMEAT_RUNTIME) {
+ result = renameat(src_dir_fd, src->narrow, dst_dir_fd, dst->narrow);
+ } else {
+ renameat_unavailable = 1;
+ }
+ } else
#endif
result = rename(src->narrow, dst->narrow);
Py_END_ALLOW_THREADS
+
+#ifdef HAVE_RENAMEAT
+ if (renameat_unavailable) {
+ argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
+ return NULL;
+ }
+#endif
+
if (result)
return path_error2(src, dst);
#endif
/*[clinic end generated code: output=080eb54f506e8301 input=38c8b375ca34a7e2]*/
{
int result;
+#ifdef HAVE_UNLINKAT
+ int unlinkat_unavailable = 0;
+#endif
if (PySys_Audit("os.rmdir", "Oi", path->object,
dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
result = !RemoveDirectoryW(path->wide);
#else
#ifdef HAVE_UNLINKAT
- if (dir_fd != DEFAULT_DIR_FD)
+ if (dir_fd != DEFAULT_DIR_FD) {
+ if (HAVE_UNLINKAT_RUNTIME) {
result = unlinkat(dir_fd, path->narrow, AT_REMOVEDIR);
- else
+ } else {
+ unlinkat_unavailable = 1;
+ result = -1;
+ }
+ } else
#endif
result = rmdir(path->narrow);
#endif
Py_END_ALLOW_THREADS
+#ifdef HAVE_UNLINKAT
+ if (unlinkat_unavailable) {
+ argument_unavailable_error("rmdir", "dir_fd");
+ return NULL;
+ }
+#endif
+
if (result)
return path_error(path);
/*[clinic end generated code: output=621797807b9963b1 input=d7bcde2b1b2a2552]*/
{
int result;
+#ifdef HAVE_UNLINKAT
+ int unlinkat_unavailable = 0;
+#endif
if (PySys_Audit("os.remove", "Oi", path->object,
dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
result = !Py_DeleteFileW(path->wide);
#else
#ifdef HAVE_UNLINKAT
- if (dir_fd != DEFAULT_DIR_FD)
+ if (dir_fd != DEFAULT_DIR_FD) {
+ if (HAVE_UNLINKAT_RUNTIME) {
+
result = unlinkat(dir_fd, path->narrow, 0);
- else
+ } else {
+ unlinkat_unavailable = 1;
+ }
+ } else
#endif /* HAVE_UNLINKAT */
result = unlink(path->narrow);
#endif
_Py_END_SUPPRESS_IPH
Py_END_ALLOW_THREADS
+#ifdef HAVE_UNLINKAT
+ if (unlinkat_unavailable) {
+ argument_unavailable_error(NULL, "dir_fd");
+ return NULL;
+ }
+#endif
+
if (result)
return path_error(path);
static int
utime_dir_fd(utime_t *ut, int dir_fd, const char *path, int follow_symlinks)
{
-#ifdef HAVE_UTIMENSAT
+#if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
+ if (HAVE_UTIMENSAT_RUNTIME) {
+ int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
+ UTIME_TO_TIMESPEC;
+ return utimensat(dir_fd, path, time, flags);
+ } else {
+ errno = ENOSYS;
+ return -1;
+ }
+#elif defined(HAVE_UTIMENSAT)
int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
UTIME_TO_TIMESPEC;
return utimensat(dir_fd, path, time, flags);
utime_fd(utime_t *ut, int fd)
{
#ifdef HAVE_FUTIMENS
+
+ if (HAVE_FUTIMENS_RUNTIME) {
+
UTIME_TO_TIMESPEC;
return futimens(fd, time);
-#else
+
+ } else
+#ifndef HAVE_FUTIMES
+ {
+ /* Not sure if this can happen */
+ PyErr_SetString(
+ PyExc_RuntimeError,
+ "neither futimens nor futimes are supported"
+ " on this system");
+ return -1;
+ }
+#endif
+
+#endif
+#ifdef HAVE_FUTIMES
+ {
UTIME_TO_TIMEVAL;
return futimes(fd, time);
+ }
#endif
}
utime_nofollow_symlinks(utime_t *ut, const char *path)
{
#ifdef HAVE_UTIMENSAT
- UTIME_TO_TIMESPEC;
- return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW);
-#else
+ if (HAVE_UTIMENSAT_RUNTIME) {
+ UTIME_TO_TIMESPEC;
+ return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW);
+ } else
+#ifndef HAVE_LUTIMES
+ {
+ /* Not sure if this can happen */
+ PyErr_SetString(
+ PyExc_RuntimeError,
+ "neither utimensat nor lutimes are supported"
+ " on this system");
+ return -1;
+ }
+#endif
+#endif
+
+#ifdef HAVE_LUTIMES
+ {
UTIME_TO_TIMEVAL;
return lutimes(path, time);
+ }
#endif
}
static int
utime_default(utime_t *ut, const char *path)
{
-#ifdef HAVE_UTIMENSAT
+#if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
+ if (HAVE_UTIMENSAT_RUNTIME) {
+ UTIME_TO_TIMESPEC;
+ return utimensat(DEFAULT_DIR_FD, path, time, 0);
+ } else {
+ UTIME_TO_TIMEVAL;
+ return utimes(path, time);
+ }
+#elif defined(HAVE_UTIMENSAT)
UTIME_TO_TIMESPEC;
return utimensat(DEFAULT_DIR_FD, path, time, 0);
#elif defined(HAVE_UTIMES)
#endif
#if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
- if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks))
+ if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
result = utime_dir_fd(&utime, dir_fd, path->narrow, follow_symlinks);
- else
+
+ } else
#endif
#if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
Py_END_ALLOW_THREADS
+#if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
+ /* See utime_dir_fd implementation */
+ if (result == -1 && errno == ENOSYS) {
+ argument_unavailable_error(NULL, "dir_fd");
+ return NULL;
+ }
+#endif
+
if (result < 0) {
/* see previous comment about not putting filename in error here */
posix_error();
}
if (setsid) {
+#ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
+ if (HAVE_POSIX_SPAWN_SETSID_RUNTIME) {
+#endif
#ifdef POSIX_SPAWN_SETSID
all_flags |= POSIX_SPAWN_SETSID;
#elif defined(POSIX_SPAWN_SETSID_NP)
argument_unavailable_error(func_name, "setsid");
return -1;
#endif
+
+#ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
+ } else {
+ argument_unavailable_error(func_name, "setsid");
+ return -1;
+ }
+#endif /* HAVE_POSIX_SPAWN_SETSID_RUNTIME */
+
}
if (setsigmask) {
#if defined(HAVE_READLINK)
char buffer[MAXPATHLEN+1];
ssize_t length;
+#ifdef HAVE_READLINKAT
+ int readlinkat_unavailable = 0;
+#endif
Py_BEGIN_ALLOW_THREADS
#ifdef HAVE_READLINKAT
- if (dir_fd != DEFAULT_DIR_FD)
- length = readlinkat(dir_fd, path->narrow, buffer, MAXPATHLEN);
- else
+ if (dir_fd != DEFAULT_DIR_FD) {
+ if (HAVE_READLINKAT_RUNTIME) {
+ length = readlinkat(dir_fd, path->narrow, buffer, MAXPATHLEN);
+ } else {
+ readlinkat_unavailable = 1;
+ }
+ } else
#endif
length = readlink(path->narrow, buffer, MAXPATHLEN);
Py_END_ALLOW_THREADS
+#ifdef HAVE_READLINKAT
+ if (readlinkat_unavailable) {
+ argument_unavailable_error(NULL, "dir_fd");
+ return NULL;
+ }
+#endif
+
if (length < 0) {
return path_error(path);
}
static int windows_has_symlink_unprivileged_flag = TRUE;
#else
int result;
+#ifdef HAVE_SYMLINKAT
+ int symlinkat_unavailable = 0;
+#endif
#endif
if (PySys_Audit("os.symlink", "OOi", src->object, dst->object,
}
Py_BEGIN_ALLOW_THREADS
-#if HAVE_SYMLINKAT
- if (dir_fd != DEFAULT_DIR_FD)
- result = symlinkat(src->narrow, dir_fd, dst->narrow);
- else
+#ifdef HAVE_SYMLINKAT
+ if (dir_fd != DEFAULT_DIR_FD) {
+ if (HAVE_SYMLINKAT_RUNTIME) {
+ result = symlinkat(src->narrow, dir_fd, dst->narrow);
+ } else {
+ symlinkat_unavailable = 1;
+ }
+ } else
#endif
result = symlink(src->narrow, dst->narrow);
Py_END_ALLOW_THREADS
+#ifdef HAVE_SYMLINKAT
+ if (symlinkat_unavailable) {
+ argument_unavailable_error(NULL, "dir_fd");
+ return NULL;
+ }
+#endif
+
if (result)
return path_error2(src, dst);
#endif
{
int fd;
int async_err = 0;
+#ifdef HAVE_OPENAT
+ int openat_unavailable = 0;
+#endif
#ifdef O_CLOEXEC
int *atomic_flag_works = &_Py_open_cloexec_works;
fd = _wopen(path->wide, flags, mode);
#else
#ifdef HAVE_OPENAT
- if (dir_fd != DEFAULT_DIR_FD)
- fd = openat(dir_fd, path->narrow, flags, mode);
- else
+ if (dir_fd != DEFAULT_DIR_FD) {
+ if (HAVE_OPENAT_RUNTIME) {
+ fd = openat(dir_fd, path->narrow, flags, mode);
+
+ } else {
+ openat_unavailable = 1;
+ fd = -1;
+ }
+ } else
#endif /* HAVE_OPENAT */
fd = open(path->narrow, flags, mode);
#endif /* !MS_WINDOWS */
} while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
_Py_END_SUPPRESS_IPH
+#ifdef HAVE_OPENAT
+ if (openat_unavailable) {
+ argument_unavailable_error(NULL, "dir_fd");
+ return -1;
+ }
+#endif
+
if (fd < 0) {
if (!async_err)
PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
} while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
#else
do {
+#ifdef __APPLE__
+/* This entire function will be removed from the module dict when the API
+ * is not available.
+ */
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunguarded-availability"
+#pragma clang diagnostic ignored "-Wunguarded-availability-new"
+#endif
Py_BEGIN_ALLOW_THREADS
_Py_BEGIN_SUPPRESS_IPH
n = preadv(fd, iov, cnt, offset);
_Py_END_SUPPRESS_IPH
Py_END_ALLOW_THREADS
} while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
+
+#ifdef __APPLE__
+#pragma clang diagnostic pop
+#endif
+
#endif
iov_cleanup(iov, buf, cnt);
if (offset >= st.st_size) {
return Py_BuildValue("i", 0);
}
+
+ // On illumos specifically sendfile() may perform a partial write but
+ // return -1/an error (in one confirmed case the destination socket
+ // had a 5 second timeout set and errno was EAGAIN) and it's on the client
+ // code to check if the offset parameter was modified by sendfile().
+ //
+ // We need this variable to track said change.
+ off_t original_offset = offset;
#endif
do {
Py_BEGIN_ALLOW_THREADS
ret = sendfile(out_fd, in_fd, &offset, count);
+#if defined(__sun) && defined(__SVR4)
+ // This handles illumos-specific sendfile() partial write behavior,
+ // see a comment above for more details.
+ if (ret < 0 && offset != original_offset) {
+ ret = offset - original_offset;
+ }
+#endif
Py_END_ALLOW_THREADS
} while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
if (ret < 0)
Py_END_ALLOW_THREADS
} while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
#else
+
+#ifdef __APPLE__
+/* This entire function will be removed from the module dict when the API
+ * is not available.
+ */
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunguarded-availability"
+#pragma clang diagnostic ignored "-Wunguarded-availability-new"
+#endif
do {
Py_BEGIN_ALLOW_THREADS
_Py_BEGIN_SUPPRESS_IPH
_Py_END_SUPPRESS_IPH
Py_END_ALLOW_THREADS
} while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
+
+#ifdef __APPLE__
+#pragma clang diagnostic pop
+#endif
+
#endif
iov_cleanup(iov, buf, cnt);
Py_BEGIN_ALLOW_THREADS
#ifdef HAVE_FSTATVFS
if (path->fd != -1) {
-#ifdef __APPLE__
- /* handle weak-linking on Mac OS X 10.3 */
- if (fstatvfs == NULL) {
- fd_specified("statvfs", path->fd);
- return NULL;
- }
-#endif
result = fstatvfs(path->fd, &st);
}
else
const char *path = PyBytes_AS_STRING(ub);
if (self->dir_fd != DEFAULT_DIR_FD) {
#ifdef HAVE_FSTATAT
+ if (HAVE_FSTATAT_RUNTIME) {
result = fstatat(self->dir_fd, path, &st,
follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
-#else
+ } else
+
+#endif /* HAVE_FSTATAT */
+ {
+ Py_DECREF(ub);
PyErr_SetString(PyExc_NotImplementedError, "can't fetch stat");
return NULL;
-#endif /* HAVE_FSTATAT */
+ }
}
else
#endif
#else /* POSIX */
errno = 0;
#ifdef HAVE_FDOPENDIR
- if (path->fd != -1) {
+ if (iterator->path.fd != -1) {
+ if (HAVE_FDOPENDIR_RUNTIME) {
/* closedir() closes the FD, so we duplicate it */
fd = _Py_dup(path->fd);
if (fd == -1)
Py_BEGIN_ALLOW_THREADS
iterator->dirp = fdopendir(fd);
Py_END_ALLOW_THREADS
+ } else {
+ PyErr_SetString(PyExc_TypeError,
+ "scandir: path should be string, bytes, os.PathLike or None, not int");
+ return NULL;
+ }
}
else
#endif
}
-static const char * const have_functions[] = {
+
+#define PROBE(name, test) \
+ static int name(void) \
+ { \
+ if (test) { \
+ return 1; \
+ } else { \
+ return 0; \
+ } \
+ }
+
+#ifdef HAVE_FSTATAT
+PROBE(probe_fstatat, HAVE_FSTATAT_RUNTIME)
+#endif
#ifdef HAVE_FACCESSAT
- "HAVE_FACCESSAT",
+PROBE(probe_faccessat, HAVE_FACCESSAT_RUNTIME)
+#endif
+
+#ifdef HAVE_FCHMODAT
+PROBE(probe_fchmodat, HAVE_FCHMODAT_RUNTIME)
+#endif
+
+#ifdef HAVE_FCHOWNAT
+PROBE(probe_fchownat, HAVE_FCHOWNAT_RUNTIME)
+#endif
+
+#ifdef HAVE_LINKAT
+PROBE(probe_linkat, HAVE_LINKAT_RUNTIME)
+#endif
+
+#ifdef HAVE_FDOPENDIR
+PROBE(probe_fdopendir, HAVE_FDOPENDIR_RUNTIME)
+#endif
+
+#ifdef HAVE_MKDIRAT
+PROBE(probe_mkdirat, HAVE_MKDIRAT_RUNTIME)
+#endif
+
+#ifdef HAVE_RENAMEAT
+PROBE(probe_renameat, HAVE_RENAMEAT_RUNTIME)
+#endif
+
+#ifdef HAVE_UNLINKAT
+PROBE(probe_unlinkat, HAVE_UNLINKAT_RUNTIME)
+#endif
+
+#ifdef HAVE_OPENAT
+PROBE(probe_openat, HAVE_OPENAT_RUNTIME)
+#endif
+
+#ifdef HAVE_READLINKAT
+PROBE(probe_readlinkat, HAVE_READLINKAT_RUNTIME)
+#endif
+
+#ifdef HAVE_SYMLINKAT
+PROBE(probe_symlinkat, HAVE_SYMLINKAT_RUNTIME)
+#endif
+
+#ifdef HAVE_FUTIMENS
+PROBE(probe_futimens, HAVE_FUTIMENS_RUNTIME)
+#endif
+
+#ifdef HAVE_UTIMENSAT
+PROBE(probe_utimensat, HAVE_UTIMENSAT_RUNTIME)
+#endif
+
+
+
+
+static const struct have_function {
+ const char * const label;
+ int (*probe)(void);
+} have_functions[] = {
+
+#ifdef HAVE_FACCESSAT
+ { "HAVE_FACCESSAT", probe_faccessat },
#endif
#ifdef HAVE_FCHDIR
- "HAVE_FCHDIR",
+ { "HAVE_FCHDIR", NULL },
#endif
#ifdef HAVE_FCHMOD
- "HAVE_FCHMOD",
+ { "HAVE_FCHMOD", NULL },
#endif
#ifdef HAVE_FCHMODAT
- "HAVE_FCHMODAT",
+ { "HAVE_FCHMODAT", probe_fchmodat },
#endif
#ifdef HAVE_FCHOWN
- "HAVE_FCHOWN",
+ { "HAVE_FCHOWN", NULL },
#endif
#ifdef HAVE_FCHOWNAT
- "HAVE_FCHOWNAT",
+ { "HAVE_FCHOWNAT", probe_fchownat },
#endif
#ifdef HAVE_FEXECVE
- "HAVE_FEXECVE",
+ { "HAVE_FEXECVE", NULL },
#endif
#ifdef HAVE_FDOPENDIR
- "HAVE_FDOPENDIR",
+ { "HAVE_FDOPENDIR", probe_fdopendir },
#endif
#ifdef HAVE_FPATHCONF
- "HAVE_FPATHCONF",
+ { "HAVE_FPATHCONF", NULL },
#endif
#ifdef HAVE_FSTATAT
- "HAVE_FSTATAT",
+ { "HAVE_FSTATAT", probe_fstatat },
#endif
#ifdef HAVE_FSTATVFS
- "HAVE_FSTATVFS",
+ { "HAVE_FSTATVFS", NULL },
#endif
#if defined HAVE_FTRUNCATE || defined MS_WINDOWS
- "HAVE_FTRUNCATE",
+ { "HAVE_FTRUNCATE", NULL },
#endif
#ifdef HAVE_FUTIMENS
- "HAVE_FUTIMENS",
+ { "HAVE_FUTIMENS", probe_futimens },
#endif
#ifdef HAVE_FUTIMES
- "HAVE_FUTIMES",
+ { "HAVE_FUTIMES", NULL },
#endif
#ifdef HAVE_FUTIMESAT
- "HAVE_FUTIMESAT",
+ { "HAVE_FUTIMESAT", NULL },
#endif
#ifdef HAVE_LINKAT
- "HAVE_LINKAT",
+ { "HAVE_LINKAT", probe_linkat },
#endif
#ifdef HAVE_LCHFLAGS
- "HAVE_LCHFLAGS",
+ { "HAVE_LCHFLAGS", NULL },
#endif
#ifdef HAVE_LCHMOD
- "HAVE_LCHMOD",
+ { "HAVE_LCHMOD", NULL },
#endif
#ifdef HAVE_LCHOWN
- "HAVE_LCHOWN",
+ { "HAVE_LCHOWN", NULL },
#endif
#ifdef HAVE_LSTAT
- "HAVE_LSTAT",
+ { "HAVE_LSTAT", NULL },
#endif
#ifdef HAVE_LUTIMES
- "HAVE_LUTIMES",
+ { "HAVE_LUTIMES", NULL },
#endif
#ifdef HAVE_MEMFD_CREATE
- "HAVE_MEMFD_CREATE",
+ { "HAVE_MEMFD_CREATE", NULL },
#endif
#ifdef HAVE_MKDIRAT
- "HAVE_MKDIRAT",
+ { "HAVE_MKDIRAT", probe_mkdirat },
#endif
#ifdef HAVE_MKFIFOAT
- "HAVE_MKFIFOAT",
+ { "HAVE_MKFIFOAT", NULL },
#endif
#ifdef HAVE_MKNODAT
- "HAVE_MKNODAT",
+ { "HAVE_MKNODAT", NULL },
#endif
#ifdef HAVE_OPENAT
- "HAVE_OPENAT",
+ { "HAVE_OPENAT", probe_openat },
#endif
#ifdef HAVE_READLINKAT
- "HAVE_READLINKAT",
+ { "HAVE_READLINKAT", probe_readlinkat },
#endif
#ifdef HAVE_RENAMEAT
- "HAVE_RENAMEAT",
+ { "HAVE_RENAMEAT", probe_renameat },
#endif
#ifdef HAVE_SYMLINKAT
- "HAVE_SYMLINKAT",
+ { "HAVE_SYMLINKAT", probe_symlinkat },
#endif
#ifdef HAVE_UNLINKAT
- "HAVE_UNLINKAT",
+ { "HAVE_UNLINKAT", probe_unlinkat },
#endif
#ifdef HAVE_UTIMENSAT
- "HAVE_UTIMENSAT",
+ { "HAVE_UTIMENSAT", probe_utimensat },
#endif
#ifdef MS_WINDOWS
- "MS_WINDOWS",
+ { "MS_WINDOWS", NULL },
#endif
- NULL
+ { NULL, NULL }
};
{
_posixstate *state = get_posix_state(m);
+#if defined(HAVE_PWRITEV)
+ if (HAVE_PWRITEV_RUNTIME) {} else {
+ PyObject* dct = PyModule_GetDict(m);
+
+ if (dct == NULL) {
+ return -1;
+ }
+
+ if (PyDict_DelItemString(dct, "pwritev") == -1) {
+ PyErr_Clear();
+ }
+ if (PyDict_DelItemString(dct, "preadv") == -1) {
+ PyErr_Clear();
+ }
+ }
+#endif
+
/* Initialize environ dictionary */
PyObject *v = convertenviron();
Py_XINCREF(v);
PyModule_AddObject(m, "uname_result", (PyObject *)UnameResultType);
state->UnameResultType = (PyObject *)UnameResultType;
-#ifdef __APPLE__
- /*
- * Step 2 of weak-linking support on Mac OS X.
- *
- * The code below removes functions that are not available on the
- * currently active platform.
- *
- * This block allow one to use a python binary that was build on
- * OSX 10.4 on OSX 10.3, without losing access to new APIs on
- * OSX 10.4.
- */
-#ifdef HAVE_FSTATVFS
- if (fstatvfs == NULL) {
- if (PyObject_DelAttrString(m, "fstatvfs") == -1) {
- return -1;
- }
- }
-#endif /* HAVE_FSTATVFS */
-
-#ifdef HAVE_STATVFS
- if (statvfs == NULL) {
- if (PyObject_DelAttrString(m, "statvfs") == -1) {
- return -1;
- }
- }
-#endif /* HAVE_STATVFS */
-
-# ifdef HAVE_LCHOWN
- if (lchown == NULL) {
- if (PyObject_DelAttrString(m, "lchown") == -1) {
- return -1;
- }
- }
-#endif /* HAVE_LCHOWN */
-
-
-#endif /* __APPLE__ */
-
if ((state->billion = PyLong_FromLong(1000000000)) == NULL)
return -1;
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
if (!list) {
return -1;
}
- for (const char * const *trace = have_functions; *trace; trace++) {
- PyObject *unicode = PyUnicode_DecodeASCII(*trace, strlen(*trace), NULL);
+ for (const struct have_function *trace = have_functions; trace->label; trace++) {
+ PyObject *unicode;
+ if (trace->probe && !trace->probe()) continue;
+ unicode = PyUnicode_DecodeASCII(trace->label, strlen(trace->label), NULL);
if (!unicode)
return -1;
if (PyList_Append(list, unicode))
return -1;
Py_DECREF(unicode);
}
+
PyModule_AddObject(m, "_have_functions", list);
return 0;
goto finally;
#endif
-#ifdef MS_WINDOWS
- /* Create manual-reset event, initially unset */
- sigint_event = CreateEvent(NULL, TRUE, FALSE, FALSE);
-#endif
-
if (PyErr_Occurred()) {
Py_DECREF(m);
m = NULL;
}
}
+
+static int
+signal_install_handlers(void)
+{
+#ifdef SIGPIPE
+ PyOS_setsig(SIGPIPE, SIG_IGN);
+#endif
+#ifdef SIGXFZ
+ PyOS_setsig(SIGXFZ, SIG_IGN);
+#endif
+#ifdef SIGXFSZ
+ PyOS_setsig(SIGXFSZ, SIG_IGN);
+#endif
+
+ // Import _signal to install the Python SIGINT handler
+ PyObject *module = PyImport_ImportModule("_signal");
+ if (!module) {
+ return -1;
+ }
+ Py_DECREF(module);
+
+ return 0;
+}
+
+
+int
+_PySignal_Init(int install_signal_handlers)
+{
+#ifdef MS_WINDOWS
+ /* Create manual-reset event, initially unset */
+ sigint_event = CreateEvent(NULL, TRUE, FALSE, FALSE);
+ if (sigint_event == NULL) {
+ PyErr_SetFromWindowsErr(0);
+ return -1;
+ }
+#endif
+
+ if (install_signal_handlers) {
+ if (signal_install_handlers() < 0) {
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+
void
PyOS_FiniInterrupts(void)
{
#define _Py_tzname tzname
#endif
+#if defined(__APPLE__ ) && defined(__has_builtin)
+# if __has_builtin(__builtin_available)
+# define HAVE_CLOCK_GETTIME_RUNTIME __builtin_available(macOS 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *)
+# endif
+#endif
+#ifndef HAVE_CLOCK_GETTIME_RUNTIME
+# define HAVE_CLOCK_GETTIME_RUNTIME 1
+#endif
+
#define SEC_TO_NS (1000 * 1000 * 1000)
/* Forward declarations */
}
#ifdef HAVE_CLOCK_GETTIME
+
+#ifdef __APPLE__
+/*
+ * The clock_* functions will be removed from the module
+ * dict entirely when the C API is not available.
+ */
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunguarded-availability"
+#endif
+
static PyObject *
time_clock_gettime(PyObject *self, PyObject *args)
{
"clock_getres(clk_id) -> floating point number\n\
\n\
Return the resolution (precision) of the specified clock clk_id.");
+
+#ifdef __APPLE__
+#pragma clang diagnostic pop
+#endif
+
#endif /* HAVE_CLOCK_GETRES */
#ifdef HAVE_PTHREAD_GETCPUCLOCKID
#if defined(HAVE_CLOCK_GETTIME) \
&& (defined(CLOCK_PROCESS_CPUTIME_ID) || defined(CLOCK_PROF))
struct timespec ts;
+
+ if (HAVE_CLOCK_GETTIME_RUNTIME) {
+
#ifdef CLOCK_PROF
- const clockid_t clk_id = CLOCK_PROF;
- const char *function = "clock_gettime(CLOCK_PROF)";
+ const clockid_t clk_id = CLOCK_PROF;
+ const char *function = "clock_gettime(CLOCK_PROF)";
#else
- const clockid_t clk_id = CLOCK_PROCESS_CPUTIME_ID;
- const char *function = "clock_gettime(CLOCK_PROCESS_CPUTIME_ID)";
+ const clockid_t clk_id = CLOCK_PROCESS_CPUTIME_ID;
+ const char *function = "clock_gettime(CLOCK_PROCESS_CPUTIME_ID)";
#endif
- if (clock_gettime(clk_id, &ts) == 0) {
- if (info) {
- struct timespec res;
- info->implementation = function;
- info->monotonic = 1;
- info->adjustable = 0;
- if (clock_getres(clk_id, &res)) {
- PyErr_SetFromErrno(PyExc_OSError);
- return -1;
+ if (clock_gettime(clk_id, &ts) == 0) {
+ if (info) {
+ struct timespec res;
+ info->implementation = function;
+ info->monotonic = 1;
+ info->adjustable = 0;
+ if (clock_getres(clk_id, &res)) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ return -1;
+ }
+ info->resolution = res.tv_sec + res.tv_nsec * 1e-9;
}
- info->resolution = res.tv_sec + res.tv_nsec * 1e-9;
- }
- if (_PyTime_FromTimespec(tp, &ts) < 0) {
- return -1;
+ if (_PyTime_FromTimespec(tp, &ts) < 0) {
+ return -1;
+ }
+ return 0;
}
- return 0;
}
#endif
return 0;
}
+#elif defined(__sun) && defined(__SVR4)
+#define HAVE_THREAD_TIME
+static int
+_PyTime_GetThreadTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info)
+{
+ /* bpo-35455: On Solaris, CLOCK_THREAD_CPUTIME_ID clock is not always
+ available; use gethrvtime() to substitute this functionality. */
+ if (info) {
+ info->implementation = "gethrvtime()";
+ info->resolution = 1e-9;
+ info->monotonic = 1;
+ info->adjustable = 0;
+ }
+ *tp = _PyTime_FromNanoseconds(gethrvtime());
+ return 0;
+}
+
#elif defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_PROCESS_CPUTIME_ID)
#define HAVE_THREAD_TIME
+
+#if defined(__APPLE__) && defined(__has_attribute) && __has_attribute(availability)
+static int
+_PyTime_GetThreadTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info)
+ __attribute__((availability(macos, introduced=10.12)))
+ __attribute__((availability(ios, introduced=10.0)))
+ __attribute__((availability(tvos, introduced=10.0)))
+ __attribute__((availability(watchos, introduced=3.0)));
+#endif
+
static int
_PyTime_GetThreadTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info)
{
#endif
#ifdef HAVE_THREAD_TIME
+#ifdef __APPLE__
+/*
+ * The clock_* functions will be removed from the module
+ * dict entirely when the C API is not available.
+ */
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunguarded-availability"
+#endif
+
static PyObject *
time_thread_time(PyObject *self, PyObject *unused)
{
\n\
Thread time for profiling as nanoseconds:\n\
sum of the kernel and user-space CPU time.");
+
+#ifdef __APPLE__
+#pragma clang diagnostic pop
+#endif
+
#endif
}
#ifdef HAVE_THREAD_TIME
else if (strcmp(name, "thread_time") == 0) {
- if (_PyTime_GetThreadTimeWithInfo(&t, &info) < 0) {
+
+#ifdef __APPLE__
+ if (HAVE_CLOCK_GETTIME_RUNTIME) {
+#endif
+ if (_PyTime_GetThreadTimeWithInfo(&t, &info) < 0) {
+ return NULL;
+ }
+#ifdef __APPLE__
+ } else {
+ PyErr_SetString(PyExc_ValueError, "unknown clock");
return NULL;
}
+#endif
}
#endif
else {
static int
time_exec(PyObject *module)
{
+#if defined(__APPLE__) && defined(HAVE_CLOCK_GETTIME)
+ if (HAVE_CLOCK_GETTIME_RUNTIME) {
+ /* pass: ^^^ cannot use '!' here */
+ } else {
+ PyObject* dct = PyModule_GetDict(module);
+ if (dct == NULL) {
+ return -1;
+ }
+
+ if (PyDict_DelItemString(dct, "clock_gettime") == -1) {
+ PyErr_Clear();
+ }
+ if (PyDict_DelItemString(dct, "clock_gettime_ns") == -1) {
+ PyErr_Clear();
+ }
+ if (PyDict_DelItemString(dct, "clock_settime") == -1) {
+ PyErr_Clear();
+ }
+ if (PyDict_DelItemString(dct, "clock_settime_ns") == -1) {
+ PyErr_Clear();
+ }
+ if (PyDict_DelItemString(dct, "clock_getres") == -1) {
+ PyErr_Clear();
+ }
+ }
+#endif
+#if defined(__APPLE__) && defined(HAVE_THREAD_TIME)
+ if (HAVE_CLOCK_GETTIME_RUNTIME) {
+ /* pass: ^^^ cannot use '!' here */
+ } else {
+ PyObject* dct = PyModule_GetDict(module);
+
+ if (PyDict_DelItemString(dct, "thread_time") == -1) {
+ PyErr_Clear();
+ }
+ if (PyDict_DelItemString(dct, "thread_time_ns") == -1) {
+ PyErr_Clear();
+ }
+ }
+#endif
/* Set, or reset, module variables like time.timezone */
if (init_timezone(module) < 0) {
return -1;
}
#if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_CLOCK_SETTIME) || defined(HAVE_CLOCK_GETRES)
+ if (HAVE_CLOCK_GETTIME_RUNTIME) {
#ifdef CLOCK_REALTIME
- if (PyModule_AddIntMacro(module, CLOCK_REALTIME) < 0) {
- return -1;
- }
+ if (PyModule_AddIntMacro(module, CLOCK_REALTIME) < 0) {
+ return -1;
+ }
#endif
+
#ifdef CLOCK_MONOTONIC
- if (PyModule_AddIntMacro(module, CLOCK_MONOTONIC) < 0) {
- return -1;
- }
+
+ if (PyModule_AddIntMacro(module, CLOCK_MONOTONIC) < 0) {
+ return -1;
+ }
+
#endif
#ifdef CLOCK_MONOTONIC_RAW
- if (PyModule_AddIntMacro(module, CLOCK_MONOTONIC_RAW) < 0) {
- return -1;
- }
+ if (PyModule_AddIntMacro(module, CLOCK_MONOTONIC_RAW) < 0) {
+ return -1;
+ }
#endif
+
#ifdef CLOCK_HIGHRES
- if (PyModule_AddIntMacro(module, CLOCK_HIGHRES) < 0) {
- return -1;
- }
+ if (PyModule_AddIntMacro(module, CLOCK_HIGHRES) < 0) {
+ return -1;
+ }
#endif
#ifdef CLOCK_PROCESS_CPUTIME_ID
- if (PyModule_AddIntMacro(module, CLOCK_PROCESS_CPUTIME_ID) < 0) {
- return -1;
- }
+ if (PyModule_AddIntMacro(module, CLOCK_PROCESS_CPUTIME_ID) < 0) {
+ return -1;
+ }
#endif
+
#ifdef CLOCK_THREAD_CPUTIME_ID
- if (PyModule_AddIntMacro(module, CLOCK_THREAD_CPUTIME_ID) < 0) {
- return -1;
- }
+ if (PyModule_AddIntMacro(module, CLOCK_THREAD_CPUTIME_ID) < 0) {
+ return -1;
+ }
#endif
#ifdef CLOCK_PROF
- if (PyModule_AddIntMacro(module, CLOCK_PROF) < 0) {
- return -1;
- }
+ if (PyModule_AddIntMacro(module, CLOCK_PROF) < 0) {
+ return -1;
+ }
#endif
#ifdef CLOCK_BOOTTIME
- if (PyModule_AddIntMacro(module, CLOCK_BOOTTIME) < 0) {
- return -1;
- }
+ if (PyModule_AddIntMacro(module, CLOCK_BOOTTIME) < 0) {
+ return -1;
+ }
#endif
#ifdef CLOCK_TAI
- if (PyModule_AddIntMacro(module, CLOCK_TAI) < 0) {
- return -1;
- }
+ if (PyModule_AddIntMacro(module, CLOCK_TAI) < 0) {
+ return -1;
+ }
#endif
#ifdef CLOCK_UPTIME
- if (PyModule_AddIntMacro(module, CLOCK_UPTIME) < 0) {
- return -1;
- }
+ if (PyModule_AddIntMacro(module, CLOCK_UPTIME) < 0) {
+ return -1;
+ }
#endif
#ifdef CLOCK_UPTIME_RAW
- if (PyModule_AddIntMacro(module, CLOCK_UPTIME_RAW) < 0) {
- return -1;
- }
+
+ if (PyModule_AddIntMacro(module, CLOCK_UPTIME_RAW) < 0) {
+ return -1;
+ }
#endif
+ }
#endif /* defined(HAVE_CLOCK_GETTIME) || defined(HAVE_CLOCK_SETTIME) || defined(HAVE_CLOCK_GETRES) */
_Py_IDENTIFIER(__bases__);
PyObject *bases;
- Py_ALLOW_RECURSION
(void)_PyObject_LookupAttrId(cls, &PyId___bases__, &bases);
- Py_END_ALLOW_RECURSION
if (bases != NULL && !PyTuple_Check(bases)) {
Py_DECREF(bases);
return NULL;
return NULL;
}
+ /* __module__: If module name is in globals, use it.
+ Otherwise, use None. */
+ module = PyDict_GetItemWithError(globals, __name__);
+ if (module) {
+ Py_INCREF(module);
+ }
+ else if (PyErr_Occurred()) {
+ return NULL;
+ }
+
op = PyObject_GC_New(PyFunctionObject, &PyFunction_Type);
- if (op == NULL)
+ if (op == NULL) {
+ Py_XDECREF(module);
return NULL;
+ }
+ /* Note: No failures from this point on, since func_dealloc() does not
+ expect a partially-created object. */
op->func_weakreflist = NULL;
Py_INCREF(code);
op->func_kwdefaults = NULL; /* No keyword only defaults */
op->func_closure = NULL;
op->vectorcall = _PyFunction_Vectorcall;
+ op->func_module = module;
consts = ((PyCodeObject *)code)->co_consts;
if (PyTuple_Size(consts) >= 1) {
op->func_doc = doc;
op->func_dict = NULL;
- op->func_module = NULL;
op->func_annotations = NULL;
- /* __module__: If module name is in globals, use it.
- Otherwise, use None. */
- module = PyDict_GetItemWithError(globals, __name__);
- if (module) {
- Py_INCREF(module);
- op->func_module = module;
- }
- else if (PyErr_Occurred()) {
- Py_DECREF(op);
- return NULL;
- }
if (qualname)
op->func_qualname = qualname;
else
PyObject *origin;
PyObject *args;
PyObject *parameters;
+ PyObject* weakreflist;
} gaobject;
static void
gaobject *alias = (gaobject *)self;
_PyObject_GC_UNTRACK(self);
+ if (alias->weakreflist != NULL) {
+ PyObject_ClearWeakRefs((PyObject *)alias);
+ }
Py_XDECREF(alias->origin);
Py_XDECREF(alias->args);
Py_XDECREF(alias->parameters);
static PyObject *
ga_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
- if (!_PyArg_NoKwnames("GenericAlias", kwds)) {
+ if (!_PyArg_NoKeywords("GenericAlias", kwds)) {
return NULL;
}
if (!_PyArg_CheckPositional("GenericAlias", PyTuple_GET_SIZE(args), 2, 2)) {
.tp_name = "types.GenericAlias",
.tp_doc = "Represent a PEP 585 generic type\n"
"\n"
- "E.g. for t = list[int], t.origin is list and t.args is (int,).",
+ "E.g. for t = list[int], t.__origin__ is list and t.__args__ is (int,).",
.tp_basicsize = sizeof(gaobject),
.tp_dealloc = ga_dealloc,
.tp_repr = ga_repr,
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
.tp_traverse = ga_traverse,
.tp_richcompare = ga_richcompare,
+ .tp_weaklistoffset = offsetof(gaobject, weakreflist),
.tp_methods = ga_methods,
.tp_members = ga_members,
.tp_alloc = PyType_GenericAlloc,
alias->origin = origin;
alias->args = args;
alias->parameters = NULL;
+ alias->weakreflist = NULL;
_PyObject_GC_TRACK(alias);
return (PyObject *)alias;
}
if (m->m_weakreflist != NULL) {
PyObject_ClearWeakRefs((PyObject*) m);
}
+ // Dereference class before m_self: PyCFunction_GET_CLASS accesses
+ // PyMethodDef m_ml, which could be kept alive by m_self
+ Py_XDECREF(PyCFunction_GET_CLASS(m));
Py_XDECREF(m->m_self);
Py_XDECREF(m->m_module);
- Py_XDECREF(PyCFunction_GET_CLASS(m));
PyObject_GC_Del(m);
}
static int
meth_traverse(PyCFunctionObject *m, visitproc visit, void *arg)
{
+ Py_VISIT(PyCFunction_GET_CLASS(m));
Py_VISIT(m->m_self);
Py_VISIT(m->m_module);
- Py_VISIT(PyCFunction_GET_CLASS(m));
return 0;
}
slots = NULL;
/* Initialize tp_flags */
+ // All heap types need GC, since we can create a reference cycle by storing
+ // an instance on one of its parents:
type->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HEAPTYPE |
- Py_TPFLAGS_BASETYPE;
- if (base->tp_flags & Py_TPFLAGS_HAVE_GC)
- type->tp_flags |= Py_TPFLAGS_HAVE_GC;
+ Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC;
/* Initialize essential fields */
type->tp_as_async = &et->as_async;
}
type->tp_dealloc = subtype_dealloc;
- /* Enable GC unless this class is not adding new instance variables and
- the base class did not use GC. */
- if ((base->tp_flags & Py_TPFLAGS_HAVE_GC) ||
- type->tp_basicsize > base->tp_basicsize)
- type->tp_flags |= Py_TPFLAGS_HAVE_GC;
-
/* Always override allocation strategy to use regular heap */
type->tp_alloc = PyType_GenericAlloc;
- if (type->tp_flags & Py_TPFLAGS_HAVE_GC) {
- type->tp_free = PyObject_GC_Del;
- type->tp_traverse = subtype_traverse;
- type->tp_clear = subtype_clear;
- }
- else
- type->tp_free = PyObject_Del;
+ type->tp_free = PyObject_GC_Del;
+ type->tp_traverse = subtype_traverse;
+ type->tp_clear = subtype_clear;
/* store type in class' cell if one is supplied */
cell = _PyDict_GetItemIdWithError(dict, &PyId___classcell__);
base = slot->pfunc;
else if (slot->slot == Py_tp_bases) {
bases = slot->pfunc;
- Py_INCREF(bases);
}
}
- if (!bases)
+ if (!bases) {
bases = PyTuple_Pack(1, base);
- if (!bases)
+ if (!bases)
+ goto fail;
+ }
+ else if (!PyTuple_Check(bases)) {
+ PyErr_SetString(PyExc_SystemError, "Py_tp_bases is not a tuple");
goto fail;
+ }
+ else {
+ Py_INCREF(bases);
+ }
}
- else
+ else if (!PyTuple_Check(bases)) {
+ PyErr_SetString(PyExc_SystemError, "bases is not a tuple");
+ goto fail;
+ }
+ else {
Py_INCREF(bases);
+ }
/* Calculate best base, and check that all bases are type objects */
base = best_base(bases);
if (base == NULL) {
+ Py_DECREF(bases);
goto fail;
}
if (!_PyType_HasFeature(base, Py_TPFLAGS_BASETYPE)) {
PyErr_Format(PyExc_TypeError,
"type '%.100s' is not an acceptable base type",
base->tp_name);
+ Py_DECREF(bases);
goto fail;
}
type->tp_as_buffer = &res->as_buffer;
/* Set tp_base and tp_bases */
type->tp_bases = bases;
- bases = NULL;
Py_INCREF(base);
type->tp_base = base;
/* generate replacement */
for (i = collstart; i < collend; ++i) {
- str += sprintf(str, "&#%d;", PyUnicode_READ(kind, data, i));
+ size = sprintf(str, "&#%d;", PyUnicode_READ(kind, data, i));
+ if (size < 0) {
+ return NULL;
+ }
+ str += size;
}
return str;
}
_PyUnicode_WSTR_LENGTH(unicode) = 0;
#endif
}
- /* maxchar exeeds 16 bit, wee need 4 bytes for unicode characters */
+ /* maxchar exceeds 16 bit, wee need 4 bytes for unicode characters */
else {
#if SIZEOF_WCHAR_T == 2
/* in case the native representation is 2-bytes, we need to allocate a
goto Undefined;
if (value < 0 || value > MAX_UNICODE) {
PyErr_Format(PyExc_TypeError,
- "character mapping must be in range(0x%lx)",
+ "character mapping must be in range(0x%x)",
(unsigned long)MAX_UNICODE + 1);
goto onError;
}
}
PyObject *t;
- Py_ALLOW_RECURSION
t = PyDict_SetDefault(interned, s, s);
- Py_END_ALLOW_RECURSION
if (t == NULL) {
PyErr_Clear();
IDLE_VE_DATA = dict(
DisplayName="IDLE (Python {})".format(VER_DOT),
Description="IDLE editor for Python {}".format(VER_DOT),
- Square150x150Logo="_resources/pythonwx150.png",
- Square44x44Logo="_resources/pythonwx44.png",
+ Square150x150Logo="_resources/idlex150.png",
+ Square44x44Logo="_resources/idlex44.png",
BackgroundColor="transparent",
)
src = icons / "pythonwx{}.png".format(px)
yield f"_resources/pythonwx{px}.png", src
yield f"_resources/pythonwx{px}$targetsize-{px}_altform-unplated.png", src
+ if ns.include_idle and ns.include_launchers:
+ for px in [44, 150]:
+ src = icons / "idlex{}.png".format(px)
+ yield f"_resources/idlex{px}.png", src
+ yield f"_resources/idlex{px}$targetsize-{px}_altform-unplated.png", src
yield f"_resources/py.png", icons / "py.png"
sccd = ns.source / SCCD_FILENAME
if sccd.is_file():
#define Py_IS_NAN _isnan
#define Py_IS_INFINITY(X) (!_finite(X) && !_isnan(X))
#define Py_IS_FINITE(X) _finite(X)
-#define copysign _copysign
/* define some ANSI types that are not defined in earlier Win headers */
#if _MSC_VER >= 1200
echo. -c Release ^| Debug ^| PGInstrument ^| PGUpdate\r
echo. Set the configuration (default: Release)\r
echo. -p x64 ^| Win32 ^| ARM ^| ARM64\r
-echo. Set the platform (default: Win32)\r
+echo. Set the platform (default: x64)\r
echo. -t Build ^| Rebuild ^| Clean ^| CleanAll\r
echo. Set the target manually\r
echo. --pgo-job The job to use for PGO training; implies --pgo\r
\r
:Run\r
setlocal\r
-set platf=Win32\r
+set platf=x64\r
set conf=Release\r
set target=Build\r
set dir=%~dp0\r
\r
echo Build environments: x86, amd64, x86_amd64\r
echo.\r
-set VSTOOLS=%VS140COMNTOOLS%\r
-if "%VSTOOLS%"=="" set VSTOOLS=%VS120COMNTOOLS%\r
-if "%VSTOOLS%"=="" set VSTOOLS=%VS110COMNTOOLS%\r
-if "%VSTOOLS%"=="" set VSTOOLS=%VS100COMNTOOLS%\r
-call "%VSTOOLS%..\..\VC\vcvarsall.bat" %*\r
+set _ARGS=%*\r
+if NOT DEFINED _ARGS set _ARGS=amd64\r
+\r
+if not exist "%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" goto :skip_vswhere\r
+set VSTOOLS=\r
+for /F "tokens=*" %%i in ('"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -property installationPath -latest -prerelease -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64') DO @(set VSTOOLS=%%i\VC\Auxiliary\Build\vcvarsall.bat)\r
+if not defined VSTOOLS goto :skip_vswhere\r
+call "%VSTOOLS%" %_ARGS%\r
+exit /B 0\r
+\r
+:skip_vswhere\r
+if not defined VSTOOLS set VSTOOLS=%VS140COMNTOOLS%\r
+if not defined VSTOOLS set VSTOOLS=%VS120COMNTOOLS%\r
+if not defined VSTOOLS set VSTOOLS=%VS110COMNTOOLS%\r
+if not defined VSTOOLS set VSTOOLS=%VS100COMNTOOLS%\r
+call "%VSTOOLS%..\..\VC\vcvarsall.bat" %_ARGS%\r
--- /dev/null
+$pcbuild = $script:MyInvocation.MyCommand.Path | Split-Path -parent;\r
+& cmd /K "$pcbuild\env.bat" $args\r
set libraries=%libraries% bzip2-1.0.6\r
if NOT "%IncludeLibffiSrc%"=="false" set libraries=%libraries% libffi\r
if NOT "%IncludeSSLSrc%"=="false" set libraries=%libraries% openssl-1.1.1g\r
-set libraries=%libraries% sqlite-3.32.3.0\r
+set libraries=%libraries% sqlite-3.33.0.0\r
if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tcl-core-8.6.9.0\r
if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tk-8.6.9.0\r
if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tix-8.4.3.6\r
rem -d Run Debug build (python_d.exe). Else release build.\r
\r
setlocal\r
-set exe=win32\python\r
+set PCBUILD=%~dp0\r
+set exedir=%PCBUILD%\amd64\r
+set exe=python\r
PATH %PATH%;..\externals\tcltk\bin\r
\r
-if "%1"=="-d" (set exe=%exe%_d) & shift\r
+:CheckOpts\r
+if "%1"=="-d" (set exe=%exe%_d) & shift & goto :CheckOpts\r
+if "%1"=="-p" (call :SetExeDir %2) & shift & shift & goto :CheckOpts\r
\r
-set cmd=%exe% ../Lib/idlelib/idle.py %1 %2 %3 %4 %5 %6 %7 %8 %9\r
+set cmd=%exedir%\%exe% %PCBUILD%\..\Lib\idlelib\idle.py %1 %2 %3 %4 %5 %6 %7 %8 %9\r
\r
echo on\r
%cmd%\r
+exit /B %LASTERRORCODE%\r
+\r
+:SetExeDir\r
+if /I %1 EQU Win32 (set exedir=%PCBUILD%\win32)\r
+if /I %1 EQU x64 (set exedir=%PCBUILD%\amd64)\r
+if /I %1 EQU ARM (set exedir=%PCBUILD%\arm32)\r
+if /I %1 EQU ARM64 (set exedir=%PCBUILD%\arm64)\r
+exit /B 0\r
echo.\r
echo.\r
echo.Available flags:\r
-echo. -x64 build for x64\r
-echo. -x86 build for x86\r
-echo. -arm32 build for arm32\r
-echo. -arm64 build for arm64\r
+echo. -x64 enable x64 build\r
+echo. -x86 enable x86 build\r
+echo. -arm32 enable arm32 build\r
+echo. -arm64 enable arm64 build\r
echo. -? this help\r
echo. --install-cygwin install cygwin to c:\cygwin\r
exit /b 127\r
if "%1"=="" goto :CheckOptsDone\r
if /I "%1"=="-x64" (set BUILD_X64=1) & shift & goto :CheckOpts\r
if /I "%1"=="-x86" (set BUILD_X86=1) & shift & goto :CheckOpts\r
+if /I "%1"=="-win32" (set BUILD_X86=1) & shift & goto :CheckOpts\r
if /I "%1"=="-arm32" (set BUILD_ARM32=1) & shift & goto :CheckOpts\r
if /I "%1"=="-arm64" (set BUILD_ARM64=1) & shift & goto :CheckOpts\r
if /I "%1"=="-pdb" (set BUILD_PDB=-g) & shift & goto :CheckOpts\r
if NOT DEFINED SH if exist c:\cygwin\bin\sh.exe set SH=c:\cygwin\bin\sh.exe\r
\r
if NOT DEFINED VCVARSALL (\r
- if exist "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" (\r
- set VCVARSALL="C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Auxiliary\Build\vcvarsall.bat"\r
- )\r
+ for /F "tokens=*" %%i in ('"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -property installationPath -latest -prerelease -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64') DO @(set VCVARSALL="%%i\VC\Auxiliary\Build\vcvarsall.bat")\r
)\r
if ^%VCVARSALL:~0,1% NEQ ^" SET VCVARSALL="%VCVARSALL%"\r
\r
<SdkBinPath Condition="!Exists($(SdkBinPath))">$(registry:HKEY_LOCAL_MACHINE\Software\Microsoft\Windows Kits\Installed Roots@KitsRoot81)\bin\x86</SdkBinPath>\r
<SdkBinPath Condition="!Exists($(SdkBinPath))">$(registry:HKEY_LOCAL_MACHINE\Software\Microsoft\Windows Kits\Installed Roots@KitsRoot)\bin\x86</SdkBinPath>\r
<SdkBinPath Condition="!Exists($(SdkBinPath))">$(registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.1A@InstallationFolder)\Bin\</SdkBinPath>\r
- <_SignCommand Condition="Exists($(SdkBinPath)) and '$(SigningCertificate)' != '' and $(SupportSigning)">"$(SdkBinPath)\signtool.exe" sign /a /n "$(SigningCertificate)" /fd sha256 /t http://timestamp.verisign.com/scripts/timestamp.dll /d "Python $(PythonVersion)"</_SignCommand>\r
- <_SignCommand Condition="Exists($(SdkBinPath)) and '$(SigningCertificateSha1)' != '' and $(SupportSigning)">"$(SdkBinPath)\signtool.exe" sign /a /sha1 "$(SigningCertificateSha1)" /fd sha256 /t http://timestamp.verisign.com/scripts/timestamp.dll /d "Python $(PythonVersion)"</_SignCommand>\r
+ <_SignCommand Condition="Exists($(SdkBinPath)) and '$(SigningCertificate)' != '' and $(SupportSigning)">"$(SdkBinPath)\signtool.exe" sign /a /n "$(SigningCertificate)" /fd sha256 /tr http://timestamp.digicert.com/ /td sha256 /d "Python $(PythonVersion)"</_SignCommand>\r
+ <_SignCommand Condition="Exists($(SdkBinPath)) and '$(SigningCertificateSha1)' != '' and $(SupportSigning)">"$(SdkBinPath)\signtool.exe" sign /a /sha1 "$(SigningCertificateSha1)" /fd sha256 /tr http://timestamp.digicert.com/ /td sha256 /d "Python $(PythonVersion)"</_SignCommand>\r
<_MakeCatCommand Condition="Exists($(SdkBinPath))">"$(SdkBinPath)\makecat.exe"</_MakeCatCommand>\r
</PropertyGroup>\r
\r
<ExternalsDir>$(EXTERNALS_DIR)</ExternalsDir>\r
<ExternalsDir Condition="$(ExternalsDir) == ''">$([System.IO.Path]::GetFullPath(`$(PySourcePath)externals`))</ExternalsDir>\r
<ExternalsDir Condition="!HasTrailingSlash($(ExternalsDir))">$(ExternalsDir)\</ExternalsDir>\r
- <sqlite3Dir>$(ExternalsDir)sqlite-3.32.3.0\</sqlite3Dir>\r
+ <sqlite3Dir>$(ExternalsDir)sqlite-3.33.0.0\</sqlite3Dir>\r
<bz2Dir>$(ExternalsDir)bzip2-1.0.6\</bz2Dir>\r
<lzmaDir>$(ExternalsDir)xz-5.2.2\</lzmaDir>\r
<libffiDir>$(ExternalsDir)libffi\</libffiDir>\r
again when building.\r
\r
_sqlite3\r
- Wraps SQLite 3.32.3.0, which is itself built by sqlite3.vcxproj\r
+ Wraps SQLite 3.33.0, which is itself built by sqlite3.vcxproj\r
Homepage:\r
http://www.sqlite.org/\r
_tkinter\r
rem -q "quick" -- normally the tests are run twice, the first time\r
rem after deleting all the .pyc files reachable from Lib/.\r
rem -q runs the tests just once, and without deleting .pyc files.\r
-rem -x64 Run the 64-bit build of python (or python_d if -d was specified)\r
-rem When omitted, uses %PREFIX% if set or the 32-bit build\r
+rem -p <Win32|x64|ARM|ARM64> or -win32, -x64, -arm32, -arm64\r
+rem Run the specified architecture of python (or python_d if -d\r
+rem was specified). If omitted, uses %PREFIX% if set or 64-bit.\r
rem All leading instances of these switches are shifted off, and\r
rem whatever remains (up to 9 arguments) is passed to regrtest.py.\r
rem For example,\r
if "%1"=="-O" (set dashO=-O) & shift & goto CheckOpts\r
if "%1"=="-q" (set qmode=yes) & shift & goto CheckOpts\r
if "%1"=="-d" (set suffix=_d) & shift & goto CheckOpts\r
+if "%1"=="-win32" (set prefix=%pcbuild%win32) & shift & goto CheckOpts\r
if "%1"=="-x64" (set prefix=%pcbuild%amd64) & shift & goto CheckOpts\r
if "%1"=="-arm64" (set prefix=%pcbuild%arm64) & shift & goto CheckOpts\r
if "%1"=="-arm32" (set prefix=%pcbuild%arm32) & shift & goto CheckOpts\r
+if "%1"=="-p" (call :SetPlatform %~2) & shift & shift & goto CheckOpts\r
if NOT "%1"=="" (set regrtestargs=%regrtestargs% %1) & shift & goto CheckOpts\r
\r
-if not defined prefix set prefix=%pcbuild%win32\r
+if not defined prefix set prefix=%pcbuild%amd64\r
set exe=%prefix%\python%suffix%.exe\r
set cmd="%exe%" %dashO% -u -Wd -E -bb -m test %regrtestargs%\r
if defined qmode goto Qmode\r
\r
echo About to run again without deleting .pyc first:\r
pause\r
+goto Qmode\r
+\r
+:SetPlatform\r
+if /I %1 EQU Win32 (set prefix=%pcbuild%win32) & exit /B 0\r
+if /I %1 EQU x64 (set prefix=%pcbuild%amd64) & exit /B 0\r
+if /I %1 EQU ARM64 (set prefix=%pcbuild%arm64) & exit /B 0\r
+if /I %1 EQU ARM (set prefix=%pcbuild%arm32) & exit /B 0\r
+echo Invalid platform "%1"\r
+exit /B 1\r
\r
:Qmode\r
echo on\r
#define class_def_type 1056
#define class_def_raw_type 1057
#define block_type 1058
-#define expressions_list_type 1059
-#define star_expressions_type 1060
-#define star_expression_type 1061
-#define star_named_expressions_type 1062
-#define star_named_expression_type 1063
-#define named_expression_type 1064
-#define annotated_rhs_type 1065
-#define expressions_type 1066
-#define expression_type 1067
-#define lambdef_type 1068
-#define lambda_params_type 1069
-#define lambda_parameters_type 1070
-#define lambda_slash_no_default_type 1071
-#define lambda_slash_with_default_type 1072
-#define lambda_star_etc_type 1073
-#define lambda_kwds_type 1074
-#define lambda_param_no_default_type 1075
-#define lambda_param_with_default_type 1076
-#define lambda_param_maybe_default_type 1077
-#define lambda_param_type 1078
-#define disjunction_type 1079
-#define conjunction_type 1080
-#define inversion_type 1081
-#define comparison_type 1082
-#define compare_op_bitwise_or_pair_type 1083
-#define eq_bitwise_or_type 1084
-#define noteq_bitwise_or_type 1085
-#define lte_bitwise_or_type 1086
-#define lt_bitwise_or_type 1087
-#define gte_bitwise_or_type 1088
-#define gt_bitwise_or_type 1089
-#define notin_bitwise_or_type 1090
-#define in_bitwise_or_type 1091
-#define isnot_bitwise_or_type 1092
-#define is_bitwise_or_type 1093
-#define bitwise_or_type 1094 // Left-recursive
-#define bitwise_xor_type 1095 // Left-recursive
-#define bitwise_and_type 1096 // Left-recursive
-#define shift_expr_type 1097 // Left-recursive
-#define sum_type 1098 // Left-recursive
-#define term_type 1099 // Left-recursive
-#define factor_type 1100
-#define power_type 1101
-#define await_primary_type 1102
-#define primary_type 1103 // Left-recursive
-#define slices_type 1104
-#define slice_type 1105
-#define atom_type 1106
-#define strings_type 1107
-#define list_type 1108
-#define listcomp_type 1109
-#define tuple_type 1110
-#define group_type 1111
-#define genexp_type 1112
-#define set_type 1113
-#define setcomp_type 1114
-#define dict_type 1115
-#define dictcomp_type 1116
-#define double_starred_kvpairs_type 1117
-#define double_starred_kvpair_type 1118
-#define kvpair_type 1119
-#define for_if_clauses_type 1120
-#define for_if_clause_type 1121
-#define yield_expr_type 1122
-#define arguments_type 1123
-#define args_type 1124
-#define kwargs_type 1125
-#define starred_expression_type 1126
-#define kwarg_or_starred_type 1127
-#define kwarg_or_double_starred_type 1128
-#define star_targets_type 1129
-#define star_targets_seq_type 1130
-#define star_target_type 1131
-#define star_atom_type 1132
-#define single_target_type 1133
-#define single_subscript_attribute_target_type 1134
-#define del_targets_type 1135
-#define del_target_type 1136
-#define del_t_atom_type 1137
-#define targets_type 1138
-#define target_type 1139
-#define t_primary_type 1140 // Left-recursive
-#define t_lookahead_type 1141
-#define t_atom_type 1142
-#define incorrect_arguments_type 1143
-#define invalid_kwarg_type 1144
-#define invalid_named_expression_type 1145
-#define invalid_assignment_type 1146
-#define invalid_ann_assign_target_type 1147
-#define invalid_del_stmt_type 1148
-#define invalid_block_type 1149
+#define star_expressions_type 1059
+#define star_expression_type 1060
+#define star_named_expressions_type 1061
+#define star_named_expression_type 1062
+#define named_expression_type 1063
+#define annotated_rhs_type 1064
+#define expressions_type 1065
+#define expression_type 1066
+#define lambdef_type 1067
+#define lambda_params_type 1068
+#define lambda_parameters_type 1069
+#define lambda_slash_no_default_type 1070
+#define lambda_slash_with_default_type 1071
+#define lambda_star_etc_type 1072
+#define lambda_kwds_type 1073
+#define lambda_param_no_default_type 1074
+#define lambda_param_with_default_type 1075
+#define lambda_param_maybe_default_type 1076
+#define lambda_param_type 1077
+#define disjunction_type 1078
+#define conjunction_type 1079
+#define inversion_type 1080
+#define comparison_type 1081
+#define compare_op_bitwise_or_pair_type 1082
+#define eq_bitwise_or_type 1083
+#define noteq_bitwise_or_type 1084
+#define lte_bitwise_or_type 1085
+#define lt_bitwise_or_type 1086
+#define gte_bitwise_or_type 1087
+#define gt_bitwise_or_type 1088
+#define notin_bitwise_or_type 1089
+#define in_bitwise_or_type 1090
+#define isnot_bitwise_or_type 1091
+#define is_bitwise_or_type 1092
+#define bitwise_or_type 1093 // Left-recursive
+#define bitwise_xor_type 1094 // Left-recursive
+#define bitwise_and_type 1095 // Left-recursive
+#define shift_expr_type 1096 // Left-recursive
+#define sum_type 1097 // Left-recursive
+#define term_type 1098 // Left-recursive
+#define factor_type 1099
+#define power_type 1100
+#define await_primary_type 1101
+#define primary_type 1102 // Left-recursive
+#define slices_type 1103
+#define slice_type 1104
+#define atom_type 1105
+#define strings_type 1106
+#define list_type 1107
+#define listcomp_type 1108
+#define tuple_type 1109
+#define group_type 1110
+#define genexp_type 1111
+#define set_type 1112
+#define setcomp_type 1113
+#define dict_type 1114
+#define dictcomp_type 1115
+#define double_starred_kvpairs_type 1116
+#define double_starred_kvpair_type 1117
+#define kvpair_type 1118
+#define for_if_clauses_type 1119
+#define for_if_clause_type 1120
+#define yield_expr_type 1121
+#define arguments_type 1122
+#define args_type 1123
+#define kwargs_type 1124
+#define starred_expression_type 1125
+#define kwarg_or_starred_type 1126
+#define kwarg_or_double_starred_type 1127
+#define star_targets_type 1128
+#define star_targets_seq_type 1129
+#define star_target_type 1130
+#define star_atom_type 1131
+#define single_target_type 1132
+#define single_subscript_attribute_target_type 1133
+#define del_targets_type 1134
+#define del_target_type 1135
+#define del_t_atom_type 1136
+#define targets_type 1137
+#define target_type 1138
+#define t_primary_type 1139 // Left-recursive
+#define t_lookahead_type 1140
+#define t_atom_type 1141
+#define invalid_arguments_type 1142
+#define invalid_kwarg_type 1143
+#define invalid_named_expression_type 1144
+#define invalid_assignment_type 1145
+#define invalid_ann_assign_target_type 1146
+#define invalid_del_stmt_type 1147
+#define invalid_block_type 1148
+#define invalid_primary_type 1149 // Left-recursive
#define invalid_comprehension_type 1150
#define invalid_dict_comprehension_type 1151
#define invalid_parameters_type 1152
#define _loop1_67_type 1227
#define _loop1_68_type 1228
#define _tmp_69_type 1229
-#define _loop0_71_type 1230
-#define _gather_70_type 1231
-#define _loop1_72_type 1232
-#define _loop0_74_type 1233
-#define _gather_73_type 1234
-#define _loop1_75_type 1235
+#define _loop1_70_type 1230
+#define _loop0_72_type 1231
+#define _gather_71_type 1232
+#define _loop1_73_type 1233
+#define _loop0_74_type 1234
+#define _loop0_75_type 1235
#define _loop0_76_type 1236
-#define _loop0_77_type 1237
+#define _loop1_77_type 1237
#define _loop0_78_type 1238
#define _loop1_79_type 1239
-#define _loop0_80_type 1240
+#define _loop1_80_type 1240
#define _loop1_81_type 1241
-#define _loop1_82_type 1242
+#define _loop0_82_type 1242
#define _loop1_83_type 1243
#define _loop0_84_type 1244
#define _loop1_85_type 1245
#define _loop0_86_type 1246
#define _loop1_87_type 1247
-#define _loop0_88_type 1248
+#define _loop1_88_type 1248
#define _loop1_89_type 1249
#define _loop1_90_type 1250
-#define _loop1_91_type 1251
-#define _loop1_92_type 1252
-#define _tmp_93_type 1253
-#define _loop0_95_type 1254
-#define _gather_94_type 1255
+#define _tmp_91_type 1251
+#define _loop0_93_type 1252
+#define _gather_92_type 1253
+#define _tmp_94_type 1254
+#define _tmp_95_type 1255
#define _tmp_96_type 1256
#define _tmp_97_type 1257
-#define _tmp_98_type 1258
+#define _loop1_98_type 1258
#define _tmp_99_type 1259
-#define _loop1_100_type 1260
-#define _tmp_101_type 1261
-#define _tmp_102_type 1262
-#define _loop0_104_type 1263
-#define _gather_103_type 1264
-#define _loop1_105_type 1265
-#define _loop0_106_type 1266
-#define _loop0_107_type 1267
-#define _loop0_109_type 1268
-#define _gather_108_type 1269
-#define _tmp_110_type 1270
+#define _tmp_100_type 1260
+#define _loop0_102_type 1261
+#define _gather_101_type 1262
+#define _loop1_103_type 1263
+#define _loop0_104_type 1264
+#define _loop0_105_type 1265
+#define _loop0_107_type 1266
+#define _gather_106_type 1267
+#define _tmp_108_type 1268
+#define _loop0_110_type 1269
+#define _gather_109_type 1270
#define _loop0_112_type 1271
#define _gather_111_type 1272
#define _loop0_114_type 1273
#define _gather_113_type 1274
#define _loop0_116_type 1275
#define _gather_115_type 1276
-#define _loop0_118_type 1277
-#define _gather_117_type 1278
-#define _loop0_119_type 1279
-#define _loop0_121_type 1280
-#define _gather_120_type 1281
-#define _tmp_122_type 1282
+#define _loop0_117_type 1277
+#define _loop0_119_type 1278
+#define _gather_118_type 1279
+#define _tmp_120_type 1280
+#define _loop0_122_type 1281
+#define _gather_121_type 1282
#define _loop0_124_type 1283
#define _gather_123_type 1284
-#define _loop0_126_type 1285
-#define _gather_125_type 1286
-#define _tmp_127_type 1287
+#define _tmp_125_type 1285
+#define _loop0_126_type 1286
+#define _loop0_127_type 1287
#define _loop0_128_type 1288
-#define _loop0_129_type 1289
-#define _loop0_130_type 1290
-#define _tmp_131_type 1291
+#define _tmp_129_type 1289
+#define _tmp_130_type 1290
+#define _loop0_131_type 1291
#define _tmp_132_type 1292
#define _loop0_133_type 1293
#define _tmp_134_type 1294
-#define _loop0_135_type 1295
+#define _tmp_135_type 1295
#define _tmp_136_type 1296
#define _tmp_137_type 1297
#define _tmp_138_type 1298
#define _tmp_148_type 1308
#define _tmp_149_type 1309
#define _tmp_150_type 1310
-#define _tmp_151_type 1311
-#define _tmp_152_type 1312
-#define _loop1_153_type 1313
-#define _loop1_154_type 1314
-#define _tmp_155_type 1315
-#define _tmp_156_type 1316
+#define _loop1_151_type 1311
+#define _loop1_152_type 1312
+#define _tmp_153_type 1313
+#define _tmp_154_type 1314
static mod_ty file_rule(Parser *p);
static mod_ty interactive_rule(Parser *p);
static stmt_ty class_def_rule(Parser *p);
static stmt_ty class_def_raw_rule(Parser *p);
static asdl_seq* block_rule(Parser *p);
-static asdl_seq* expressions_list_rule(Parser *p);
static expr_ty star_expressions_rule(Parser *p);
static expr_ty star_expression_rule(Parser *p);
static asdl_seq* star_named_expressions_rule(Parser *p);
static expr_ty t_primary_rule(Parser *p);
static void *t_lookahead_rule(Parser *p);
static expr_ty t_atom_rule(Parser *p);
-static void *incorrect_arguments_rule(Parser *p);
+static void *invalid_arguments_rule(Parser *p);
static void *invalid_kwarg_rule(Parser *p);
static void *invalid_named_expression_rule(Parser *p);
static void *invalid_assignment_rule(Parser *p);
static expr_ty invalid_ann_assign_target_rule(Parser *p);
static void *invalid_del_stmt_rule(Parser *p);
static void *invalid_block_rule(Parser *p);
+static void *invalid_primary_rule(Parser *p);
static void *invalid_comprehension_rule(Parser *p);
static void *invalid_dict_comprehension_rule(Parser *p);
static void *invalid_parameters_rule(Parser *p);
static asdl_seq *_loop1_67_rule(Parser *p);
static asdl_seq *_loop1_68_rule(Parser *p);
static void *_tmp_69_rule(Parser *p);
-static asdl_seq *_loop0_71_rule(Parser *p);
-static asdl_seq *_gather_70_rule(Parser *p);
-static asdl_seq *_loop1_72_rule(Parser *p);
+static asdl_seq *_loop1_70_rule(Parser *p);
+static asdl_seq *_loop0_72_rule(Parser *p);
+static asdl_seq *_gather_71_rule(Parser *p);
+static asdl_seq *_loop1_73_rule(Parser *p);
static asdl_seq *_loop0_74_rule(Parser *p);
-static asdl_seq *_gather_73_rule(Parser *p);
-static asdl_seq *_loop1_75_rule(Parser *p);
+static asdl_seq *_loop0_75_rule(Parser *p);
static asdl_seq *_loop0_76_rule(Parser *p);
-static asdl_seq *_loop0_77_rule(Parser *p);
+static asdl_seq *_loop1_77_rule(Parser *p);
static asdl_seq *_loop0_78_rule(Parser *p);
static asdl_seq *_loop1_79_rule(Parser *p);
-static asdl_seq *_loop0_80_rule(Parser *p);
+static asdl_seq *_loop1_80_rule(Parser *p);
static asdl_seq *_loop1_81_rule(Parser *p);
-static asdl_seq *_loop1_82_rule(Parser *p);
+static asdl_seq *_loop0_82_rule(Parser *p);
static asdl_seq *_loop1_83_rule(Parser *p);
static asdl_seq *_loop0_84_rule(Parser *p);
static asdl_seq *_loop1_85_rule(Parser *p);
static asdl_seq *_loop0_86_rule(Parser *p);
static asdl_seq *_loop1_87_rule(Parser *p);
-static asdl_seq *_loop0_88_rule(Parser *p);
+static asdl_seq *_loop1_88_rule(Parser *p);
static asdl_seq *_loop1_89_rule(Parser *p);
static asdl_seq *_loop1_90_rule(Parser *p);
-static asdl_seq *_loop1_91_rule(Parser *p);
-static asdl_seq *_loop1_92_rule(Parser *p);
-static void *_tmp_93_rule(Parser *p);
-static asdl_seq *_loop0_95_rule(Parser *p);
-static asdl_seq *_gather_94_rule(Parser *p);
+static void *_tmp_91_rule(Parser *p);
+static asdl_seq *_loop0_93_rule(Parser *p);
+static asdl_seq *_gather_92_rule(Parser *p);
+static void *_tmp_94_rule(Parser *p);
+static void *_tmp_95_rule(Parser *p);
static void *_tmp_96_rule(Parser *p);
static void *_tmp_97_rule(Parser *p);
-static void *_tmp_98_rule(Parser *p);
+static asdl_seq *_loop1_98_rule(Parser *p);
static void *_tmp_99_rule(Parser *p);
-static asdl_seq *_loop1_100_rule(Parser *p);
-static void *_tmp_101_rule(Parser *p);
-static void *_tmp_102_rule(Parser *p);
+static void *_tmp_100_rule(Parser *p);
+static asdl_seq *_loop0_102_rule(Parser *p);
+static asdl_seq *_gather_101_rule(Parser *p);
+static asdl_seq *_loop1_103_rule(Parser *p);
static asdl_seq *_loop0_104_rule(Parser *p);
-static asdl_seq *_gather_103_rule(Parser *p);
-static asdl_seq *_loop1_105_rule(Parser *p);
-static asdl_seq *_loop0_106_rule(Parser *p);
+static asdl_seq *_loop0_105_rule(Parser *p);
static asdl_seq *_loop0_107_rule(Parser *p);
-static asdl_seq *_loop0_109_rule(Parser *p);
-static asdl_seq *_gather_108_rule(Parser *p);
-static void *_tmp_110_rule(Parser *p);
+static asdl_seq *_gather_106_rule(Parser *p);
+static void *_tmp_108_rule(Parser *p);
+static asdl_seq *_loop0_110_rule(Parser *p);
+static asdl_seq *_gather_109_rule(Parser *p);
static asdl_seq *_loop0_112_rule(Parser *p);
static asdl_seq *_gather_111_rule(Parser *p);
static asdl_seq *_loop0_114_rule(Parser *p);
static asdl_seq *_gather_113_rule(Parser *p);
static asdl_seq *_loop0_116_rule(Parser *p);
static asdl_seq *_gather_115_rule(Parser *p);
-static asdl_seq *_loop0_118_rule(Parser *p);
-static asdl_seq *_gather_117_rule(Parser *p);
+static asdl_seq *_loop0_117_rule(Parser *p);
static asdl_seq *_loop0_119_rule(Parser *p);
-static asdl_seq *_loop0_121_rule(Parser *p);
-static asdl_seq *_gather_120_rule(Parser *p);
-static void *_tmp_122_rule(Parser *p);
+static asdl_seq *_gather_118_rule(Parser *p);
+static void *_tmp_120_rule(Parser *p);
+static asdl_seq *_loop0_122_rule(Parser *p);
+static asdl_seq *_gather_121_rule(Parser *p);
static asdl_seq *_loop0_124_rule(Parser *p);
static asdl_seq *_gather_123_rule(Parser *p);
+static void *_tmp_125_rule(Parser *p);
static asdl_seq *_loop0_126_rule(Parser *p);
-static asdl_seq *_gather_125_rule(Parser *p);
-static void *_tmp_127_rule(Parser *p);
+static asdl_seq *_loop0_127_rule(Parser *p);
static asdl_seq *_loop0_128_rule(Parser *p);
-static asdl_seq *_loop0_129_rule(Parser *p);
-static asdl_seq *_loop0_130_rule(Parser *p);
-static void *_tmp_131_rule(Parser *p);
+static void *_tmp_129_rule(Parser *p);
+static void *_tmp_130_rule(Parser *p);
+static asdl_seq *_loop0_131_rule(Parser *p);
static void *_tmp_132_rule(Parser *p);
static asdl_seq *_loop0_133_rule(Parser *p);
static void *_tmp_134_rule(Parser *p);
-static asdl_seq *_loop0_135_rule(Parser *p);
+static void *_tmp_135_rule(Parser *p);
static void *_tmp_136_rule(Parser *p);
static void *_tmp_137_rule(Parser *p);
static void *_tmp_138_rule(Parser *p);
static void *_tmp_148_rule(Parser *p);
static void *_tmp_149_rule(Parser *p);
static void *_tmp_150_rule(Parser *p);
-static void *_tmp_151_rule(Parser *p);
-static void *_tmp_152_rule(Parser *p);
-static asdl_seq *_loop1_153_rule(Parser *p);
-static asdl_seq *_loop1_154_rule(Parser *p);
-static void *_tmp_155_rule(Parser *p);
-static void *_tmp_156_rule(Parser *p);
+static asdl_seq *_loop1_151_rule(Parser *p);
+static asdl_seq *_loop1_152_rule(Parser *p);
+static void *_tmp_153_rule(Parser *p);
+static void *_tmp_154_rule(Parser *p);
// file: statements? $
return NULL;
}
}
- { // invalid_assignment
+ if (p->call_invalid_rules) { // invalid_assignment
if (p->error_indicator) {
D(p->level--);
return NULL;
D(fprintf(stderr, "%*c%s del_stmt[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'del' del_targets &(';' | NEWLINE)"));
}
- { // invalid_del_stmt
+ if (p->call_invalid_rules) { // invalid_del_stmt
if (p->error_indicator) {
D(p->level--);
return NULL;
D(fprintf(stderr, "%*c%s import_from_targets[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'*'"));
}
- { // invalid_import_from_targets
+ if (p->call_invalid_rules) { // invalid_import_from_targets
if (p->error_indicator) {
D(p->level--);
return NULL;
}
p->mark = _mark;
void *_raw = dotted_name_raw(p);
+ if (p->error_indicator)
+ return NULL;
if (_raw == NULL || p->mark <= _resmark)
break;
_resmark = p->mark;
return NULL;
}
}
- { // invalid_for_target
+ if (p->call_invalid_rules) { // invalid_for_target
if (p->error_indicator) {
D(p->level--);
return NULL;
return _res;
}
-// with_item: expression 'as' target &(',' | ')' | ':') | invalid_with_item | expression
+// with_item:
+// | expression 'as' star_target &(',' | ')' | ':')
+// | invalid_with_item
+// | expression
static withitem_ty
with_item_rule(Parser *p)
{
}
withitem_ty _res = NULL;
int _mark = p->mark;
- { // expression 'as' target &(',' | ')' | ':')
+ { // expression 'as' star_target &(',' | ')' | ':')
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> with_item[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression 'as' target &(',' | ')' | ':')"));
+ D(fprintf(stderr, "%*c> with_item[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression 'as' star_target &(',' | ')' | ':')"));
Token * _keyword;
expr_ty e;
expr_ty t;
&&
(_keyword = _PyPegen_expect_token(p, 520)) // token='as'
&&
- (t = target_rule(p)) // target
+ (t = star_target_rule(p)) // star_target
&&
_PyPegen_lookahead(1, _tmp_47_rule, p)
)
{
- D(fprintf(stderr, "%*c+ with_item[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression 'as' target &(',' | ')' | ':')"));
+ D(fprintf(stderr, "%*c+ with_item[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression 'as' star_target &(',' | ')' | ':')"));
_res = _Py_withitem ( e , t , p -> arena );
if (_res == NULL && PyErr_Occurred()) {
p->error_indicator = 1;
}
p->mark = _mark;
D(fprintf(stderr, "%*c%s with_item[%d-%d]: %s failed!\n", p->level, ' ',
- p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression 'as' target &(',' | ')' | ':')"));
+ p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression 'as' star_target &(',' | ')' | ':')"));
}
- { // invalid_with_item
+ if (p->call_invalid_rules) { // invalid_with_item
if (p->error_indicator) {
D(p->level--);
return NULL;
D(fprintf(stderr, "%*c%s func_type_comment[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NEWLINE TYPE_COMMENT &(NEWLINE INDENT)"));
}
- { // invalid_double_type_comments
+ if (p->call_invalid_rules) { // invalid_double_type_comments
if (p->error_indicator) {
D(p->level--);
return NULL;
}
arguments_ty _res = NULL;
int _mark = p->mark;
- { // invalid_parameters
+ if (p->call_invalid_rules) { // invalid_parameters
if (p->error_indicator) {
D(p->level--);
return NULL;
D(fprintf(stderr, "%*c%s star_etc[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwds"));
}
- { // invalid_star_etc
+ if (p->call_invalid_rules) { // invalid_star_etc
if (p->error_indicator) {
D(p->level--);
return NULL;
D(fprintf(stderr, "%*c%s block[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "simple_stmt"));
}
- { // invalid_block
+ if (p->call_invalid_rules) { // invalid_block
if (p->error_indicator) {
D(p->level--);
return NULL;
return _res;
}
-// expressions_list: ','.star_expression+ ','?
-static asdl_seq*
-expressions_list_rule(Parser *p)
-{
- D(p->level++);
- if (p->error_indicator) {
- D(p->level--);
- return NULL;
- }
- asdl_seq* _res = NULL;
- int _mark = p->mark;
- { // ','.star_expression+ ','?
- if (p->error_indicator) {
- D(p->level--);
- return NULL;
- }
- D(fprintf(stderr, "%*c> expressions_list[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.star_expression+ ','?"));
- void *_opt_var;
- UNUSED(_opt_var); // Silence compiler warnings
- asdl_seq * a;
- if (
- (a = _gather_70_rule(p)) // ','.star_expression+
- &&
- (_opt_var = _PyPegen_expect_token(p, 12), 1) // ','?
- )
- {
- D(fprintf(stderr, "%*c+ expressions_list[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.star_expression+ ','?"));
- _res = a;
- if (_res == NULL && PyErr_Occurred()) {
- p->error_indicator = 1;
- D(p->level--);
- return NULL;
- }
- goto done;
- }
- p->mark = _mark;
- D(fprintf(stderr, "%*c%s expressions_list[%d-%d]: %s failed!\n", p->level, ' ',
- p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','.star_expression+ ','?"));
- }
- _res = NULL;
- done:
- D(p->level--);
- return _res;
-}
-
// star_expressions:
// | star_expression ((',' star_expression))+ ','?
// | star_expression ','
if (
(a = star_expression_rule(p)) // star_expression
&&
- (b = _loop1_72_rule(p)) // ((',' star_expression))+
+ (b = _loop1_70_rule(p)) // ((',' star_expression))+
&&
(_opt_var = _PyPegen_expect_token(p, 12), 1) // ','?
)
UNUSED(_opt_var); // Silence compiler warnings
asdl_seq * a;
if (
- (a = _gather_73_rule(p)) // ','.star_named_expression+
+ (a = _gather_71_rule(p)) // ','.star_named_expression+
&&
(_opt_var = _PyPegen_expect_token(p, 12), 1) // ','?
)
D(fprintf(stderr, "%*c%s named_expression[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression !':='"));
}
- { // invalid_named_expression
+ if (p->call_invalid_rules) { // invalid_named_expression
if (p->error_indicator) {
D(p->level--);
return NULL;
if (
(a = expression_rule(p)) // expression
&&
- (b = _loop1_75_rule(p)) // ((',' expression))+
+ (b = _loop1_73_rule(p)) // ((',' expression))+
&&
(_opt_var = _PyPegen_expect_token(p, 12), 1) // ','?
)
}
arguments_ty _res = NULL;
int _mark = p->mark;
- { // invalid_lambda_parameters
+ if (p->call_invalid_rules) { // invalid_lambda_parameters
if (p->error_indicator) {
D(p->level--);
return NULL;
if (
(a = lambda_slash_no_default_rule(p)) // lambda_slash_no_default
&&
- (b = _loop0_76_rule(p)) // lambda_param_no_default*
+ (b = _loop0_74_rule(p)) // lambda_param_no_default*
&&
- (c = _loop0_77_rule(p)) // lambda_param_with_default*
+ (c = _loop0_75_rule(p)) // lambda_param_with_default*
&&
(d = lambda_star_etc_rule(p), 1) // lambda_star_etc?
)
if (
(a = lambda_slash_with_default_rule(p)) // lambda_slash_with_default
&&
- (b = _loop0_78_rule(p)) // lambda_param_with_default*
+ (b = _loop0_76_rule(p)) // lambda_param_with_default*
&&
(c = lambda_star_etc_rule(p), 1) // lambda_star_etc?
)
asdl_seq * b;
void *c;
if (
- (a = _loop1_79_rule(p)) // lambda_param_no_default+
+ (a = _loop1_77_rule(p)) // lambda_param_no_default+
&&
- (b = _loop0_80_rule(p)) // lambda_param_with_default*
+ (b = _loop0_78_rule(p)) // lambda_param_with_default*
&&
(c = lambda_star_etc_rule(p), 1) // lambda_star_etc?
)
asdl_seq * a;
void *b;
if (
- (a = _loop1_81_rule(p)) // lambda_param_with_default+
+ (a = _loop1_79_rule(p)) // lambda_param_with_default+
&&
(b = lambda_star_etc_rule(p), 1) // lambda_star_etc?
)
Token * _literal_1;
asdl_seq * a;
if (
- (a = _loop1_82_rule(p)) // lambda_param_no_default+
+ (a = _loop1_80_rule(p)) // lambda_param_no_default+
&&
(_literal = _PyPegen_expect_token(p, 17)) // token='/'
&&
Token * _literal;
asdl_seq * a;
if (
- (a = _loop1_83_rule(p)) // lambda_param_no_default+
+ (a = _loop1_81_rule(p)) // lambda_param_no_default+
&&
(_literal = _PyPegen_expect_token(p, 17)) // token='/'
&&
asdl_seq * a;
asdl_seq * b;
if (
- (a = _loop0_84_rule(p)) // lambda_param_no_default*
+ (a = _loop0_82_rule(p)) // lambda_param_no_default*
&&
- (b = _loop1_85_rule(p)) // lambda_param_with_default+
+ (b = _loop1_83_rule(p)) // lambda_param_with_default+
&&
(_literal = _PyPegen_expect_token(p, 17)) // token='/'
&&
asdl_seq * a;
asdl_seq * b;
if (
- (a = _loop0_86_rule(p)) // lambda_param_no_default*
+ (a = _loop0_84_rule(p)) // lambda_param_no_default*
&&
- (b = _loop1_87_rule(p)) // lambda_param_with_default+
+ (b = _loop1_85_rule(p)) // lambda_param_with_default+
&&
(_literal = _PyPegen_expect_token(p, 17)) // token='/'
&&
&&
(a = lambda_param_no_default_rule(p)) // lambda_param_no_default
&&
- (b = _loop0_88_rule(p)) // lambda_param_maybe_default*
+ (b = _loop0_86_rule(p)) // lambda_param_maybe_default*
&&
(c = lambda_kwds_rule(p), 1) // lambda_kwds?
)
&&
(_literal_1 = _PyPegen_expect_token(p, 12)) // token=','
&&
- (b = _loop1_89_rule(p)) // lambda_param_maybe_default+
+ (b = _loop1_87_rule(p)) // lambda_param_maybe_default+
&&
(c = lambda_kwds_rule(p), 1) // lambda_kwds?
)
D(fprintf(stderr, "%*c%s lambda_star_etc[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_kwds"));
}
- { // invalid_lambda_star_etc
+ if (p->call_invalid_rules) { // invalid_lambda_star_etc
if (p->error_indicator) {
D(p->level--);
return NULL;
if (
(a = conjunction_rule(p)) // conjunction
&&
- (b = _loop1_90_rule(p)) // (('or' conjunction))+
+ (b = _loop1_88_rule(p)) // (('or' conjunction))+
)
{
D(fprintf(stderr, "%*c+ disjunction[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "conjunction (('or' conjunction))+"));
if (
(a = inversion_rule(p)) // inversion
&&
- (b = _loop1_91_rule(p)) // (('and' inversion))+
+ (b = _loop1_89_rule(p)) // (('and' inversion))+
)
{
D(fprintf(stderr, "%*c+ conjunction[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "inversion (('and' inversion))+"));
if (
(a = bitwise_or_rule(p)) // bitwise_or
&&
- (b = _loop1_92_rule(p)) // compare_op_bitwise_or_pair+
+ (b = _loop1_90_rule(p)) // compare_op_bitwise_or_pair+
)
{
D(fprintf(stderr, "%*c+ comparison[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "bitwise_or compare_op_bitwise_or_pair+"));
return NULL;
}
D(fprintf(stderr, "%*c> noteq_bitwise_or[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('!=') bitwise_or"));
- void *_tmp_93_var;
+ void *_tmp_91_var;
expr_ty a;
if (
- (_tmp_93_var = _tmp_93_rule(p)) // '!='
+ (_tmp_91_var = _tmp_91_rule(p)) // '!='
&&
(a = bitwise_or_rule(p)) // bitwise_or
)
}
p->mark = _mark;
void *_raw = bitwise_or_raw(p);
+ if (p->error_indicator)
+ return NULL;
if (_raw == NULL || p->mark <= _resmark)
break;
_resmark = p->mark;
}
p->mark = _mark;
void *_raw = bitwise_xor_raw(p);
+ if (p->error_indicator)
+ return NULL;
if (_raw == NULL || p->mark <= _resmark)
break;
_resmark = p->mark;
}
p->mark = _mark;
void *_raw = bitwise_and_raw(p);
+ if (p->error_indicator)
+ return NULL;
if (_raw == NULL || p->mark <= _resmark)
break;
_resmark = p->mark;
}
p->mark = _mark;
void *_raw = shift_expr_raw(p);
+ if (p->error_indicator)
+ return NULL;
if (_raw == NULL || p->mark <= _resmark)
break;
_resmark = p->mark;
}
p->mark = _mark;
void *_raw = sum_raw(p);
+ if (p->error_indicator)
+ return NULL;
if (_raw == NULL || p->mark <= _resmark)
break;
_resmark = p->mark;
}
p->mark = _mark;
void *_raw = term_raw(p);
+ if (p->error_indicator)
+ return NULL;
if (_raw == NULL || p->mark <= _resmark)
break;
_resmark = p->mark;
// Left-recursive
// primary:
+// | invalid_primary
// | primary '.' NAME
// | primary genexp
// | primary '(' arguments? ')'
}
p->mark = _mark;
void *_raw = primary_raw(p);
+ if (p->error_indicator)
+ return NULL;
if (_raw == NULL || p->mark <= _resmark)
break;
_resmark = p->mark;
UNUSED(_start_lineno); // Only used by EXTRA macro
int _start_col_offset = p->tokens[_mark]->col_offset;
UNUSED(_start_col_offset); // Only used by EXTRA macro
+ if (p->call_invalid_rules) { // invalid_primary
+ if (p->error_indicator) {
+ D(p->level--);
+ return NULL;
+ }
+ D(fprintf(stderr, "%*c> primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_primary"));
+ void *invalid_primary_var;
+ if (
+ (invalid_primary_var = invalid_primary_rule(p)) // invalid_primary
+ )
+ {
+ D(fprintf(stderr, "%*c+ primary[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "invalid_primary"));
+ _res = invalid_primary_var;
+ goto done;
+ }
+ p->mark = _mark;
+ D(fprintf(stderr, "%*c%s primary[%d-%d]: %s failed!\n", p->level, ' ',
+ p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "invalid_primary"));
+ }
{ // primary '.' NAME
if (p->error_indicator) {
D(p->level--);
UNUSED(_opt_var); // Silence compiler warnings
asdl_seq * a;
if (
- (a = _gather_94_rule(p)) // ','.slice+
+ (a = _gather_92_rule(p)) // ','.slice+
&&
(_opt_var = _PyPegen_expect_token(p, 12), 1) // ','?
)
&&
(b = expression_rule(p), 1) // expression?
&&
- (c = _tmp_96_rule(p), 1) // [':' expression?]
+ (c = _tmp_94_rule(p), 1) // [':' expression?]
)
{
D(fprintf(stderr, "%*c+ slice[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression? ':' expression? [':' expression?]"));
return NULL;
}
D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'(' (tuple | group | genexp)"));
- void *_tmp_97_var;
+ void *_tmp_95_var;
if (
_PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 7) // token='('
&&
- (_tmp_97_var = _tmp_97_rule(p)) // tuple | group | genexp
+ (_tmp_95_var = _tmp_95_rule(p)) // tuple | group | genexp
)
{
D(fprintf(stderr, "%*c+ atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "&'(' (tuple | group | genexp)"));
- _res = _tmp_97_var;
+ _res = _tmp_95_var;
goto done;
}
p->mark = _mark;
return NULL;
}
D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'[' (list | listcomp)"));
- void *_tmp_98_var;
+ void *_tmp_96_var;
if (
_PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 9) // token='['
&&
- (_tmp_98_var = _tmp_98_rule(p)) // list | listcomp
+ (_tmp_96_var = _tmp_96_rule(p)) // list | listcomp
)
{
D(fprintf(stderr, "%*c+ atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "&'[' (list | listcomp)"));
- _res = _tmp_98_var;
+ _res = _tmp_96_var;
goto done;
}
p->mark = _mark;
return NULL;
}
D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'{' (dict | set | dictcomp | setcomp)"));
- void *_tmp_99_var;
+ void *_tmp_97_var;
if (
_PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 25) // token='{'
&&
- (_tmp_99_var = _tmp_99_rule(p)) // dict | set | dictcomp | setcomp
+ (_tmp_97_var = _tmp_97_rule(p)) // dict | set | dictcomp | setcomp
)
{
D(fprintf(stderr, "%*c+ atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "&'{' (dict | set | dictcomp | setcomp)"));
- _res = _tmp_99_var;
+ _res = _tmp_97_var;
goto done;
}
p->mark = _mark;
D(fprintf(stderr, "%*c> strings[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "STRING+"));
asdl_seq * a;
if (
- (a = _loop1_100_rule(p)) // STRING+
+ (a = _loop1_98_rule(p)) // STRING+
)
{
D(fprintf(stderr, "%*c+ strings[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "STRING+"));
return NULL;
}
}
- { // invalid_comprehension
+ if (p->call_invalid_rules) { // invalid_comprehension
if (p->error_indicator) {
D(p->level--);
return NULL;
if (
(_literal = _PyPegen_expect_token(p, 7)) // token='('
&&
- (a = _tmp_101_rule(p), 1) // [star_named_expression ',' star_named_expressions?]
+ (a = _tmp_99_rule(p), 1) // [star_named_expression ',' star_named_expressions?]
&&
(_literal_1 = _PyPegen_expect_token(p, 8)) // token=')'
)
if (
(_literal = _PyPegen_expect_token(p, 7)) // token='('
&&
- (a = _tmp_102_rule(p)) // yield_expr | named_expression
+ (a = _tmp_100_rule(p)) // yield_expr | named_expression
&&
(_literal_1 = _PyPegen_expect_token(p, 8)) // token=')'
)
D(fprintf(stderr, "%*c%s group[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'(' (yield_expr | named_expression) ')'"));
}
- { // invalid_group
+ if (p->call_invalid_rules) { // invalid_group
if (p->error_indicator) {
D(p->level--);
return NULL;
return _res;
}
-// genexp: '(' expression ~ for_if_clauses ')' | invalid_comprehension
+// genexp: '(' named_expression ~ for_if_clauses ')' | invalid_comprehension
static expr_ty
genexp_rule(Parser *p)
{
UNUSED(_start_lineno); // Only used by EXTRA macro
int _start_col_offset = p->tokens[_mark]->col_offset;
UNUSED(_start_col_offset); // Only used by EXTRA macro
- { // '(' expression ~ for_if_clauses ')'
+ { // '(' named_expression ~ for_if_clauses ')'
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> genexp[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' expression ~ for_if_clauses ')'"));
+ D(fprintf(stderr, "%*c> genexp[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' named_expression ~ for_if_clauses ')'"));
int _cut_var = 0;
Token * _literal;
Token * _literal_1;
if (
(_literal = _PyPegen_expect_token(p, 7)) // token='('
&&
- (a = expression_rule(p)) // expression
+ (a = named_expression_rule(p)) // named_expression
&&
(_cut_var = 1)
&&
(_literal_1 = _PyPegen_expect_token(p, 8)) // token=')'
)
{
- D(fprintf(stderr, "%*c+ genexp[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' expression ~ for_if_clauses ')'"));
+ D(fprintf(stderr, "%*c+ genexp[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' named_expression ~ for_if_clauses ')'"));
Token *_token = _PyPegen_get_last_nonnwhitespace_token(p);
if (_token == NULL) {
D(p->level--);
}
p->mark = _mark;
D(fprintf(stderr, "%*c%s genexp[%d-%d]: %s failed!\n", p->level, ' ',
- p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'(' expression ~ for_if_clauses ')'"));
+ p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'(' named_expression ~ for_if_clauses ')'"));
if (_cut_var) {
D(p->level--);
return NULL;
}
}
- { // invalid_comprehension
+ if (p->call_invalid_rules) { // invalid_comprehension
if (p->error_indicator) {
D(p->level--);
return NULL;
return _res;
}
-// set: '{' expressions_list '}'
+// set: '{' star_named_expressions '}'
static expr_ty
set_rule(Parser *p)
{
UNUSED(_start_lineno); // Only used by EXTRA macro
int _start_col_offset = p->tokens[_mark]->col_offset;
UNUSED(_start_col_offset); // Only used by EXTRA macro
- { // '{' expressions_list '}'
+ { // '{' star_named_expressions '}'
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> set[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' expressions_list '}'"));
+ D(fprintf(stderr, "%*c> set[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' star_named_expressions '}'"));
Token * _literal;
Token * _literal_1;
asdl_seq* a;
if (
(_literal = _PyPegen_expect_token(p, 25)) // token='{'
&&
- (a = expressions_list_rule(p)) // expressions_list
+ (a = star_named_expressions_rule(p)) // star_named_expressions
&&
(_literal_1 = _PyPegen_expect_token(p, 26)) // token='}'
)
{
- D(fprintf(stderr, "%*c+ set[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' expressions_list '}'"));
+ D(fprintf(stderr, "%*c+ set[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' star_named_expressions '}'"));
Token *_token = _PyPegen_get_last_nonnwhitespace_token(p);
if (_token == NULL) {
D(p->level--);
}
p->mark = _mark;
D(fprintf(stderr, "%*c%s set[%d-%d]: %s failed!\n", p->level, ' ',
- p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{' expressions_list '}'"));
+ p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{' star_named_expressions '}'"));
}
_res = NULL;
done:
return _res;
}
-// setcomp: '{' expression ~ for_if_clauses '}' | invalid_comprehension
+// setcomp: '{' named_expression ~ for_if_clauses '}' | invalid_comprehension
static expr_ty
setcomp_rule(Parser *p)
{
UNUSED(_start_lineno); // Only used by EXTRA macro
int _start_col_offset = p->tokens[_mark]->col_offset;
UNUSED(_start_col_offset); // Only used by EXTRA macro
- { // '{' expression ~ for_if_clauses '}'
+ { // '{' named_expression ~ for_if_clauses '}'
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> setcomp[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' expression ~ for_if_clauses '}'"));
+ D(fprintf(stderr, "%*c> setcomp[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' named_expression ~ for_if_clauses '}'"));
int _cut_var = 0;
Token * _literal;
Token * _literal_1;
if (
(_literal = _PyPegen_expect_token(p, 25)) // token='{'
&&
- (a = expression_rule(p)) // expression
+ (a = named_expression_rule(p)) // named_expression
&&
(_cut_var = 1)
&&
(_literal_1 = _PyPegen_expect_token(p, 26)) // token='}'
)
{
- D(fprintf(stderr, "%*c+ setcomp[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' expression ~ for_if_clauses '}'"));
+ D(fprintf(stderr, "%*c+ setcomp[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' named_expression ~ for_if_clauses '}'"));
Token *_token = _PyPegen_get_last_nonnwhitespace_token(p);
if (_token == NULL) {
D(p->level--);
}
p->mark = _mark;
D(fprintf(stderr, "%*c%s setcomp[%d-%d]: %s failed!\n", p->level, ' ',
- p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{' expression ~ for_if_clauses '}'"));
+ p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{' named_expression ~ for_if_clauses '}'"));
if (_cut_var) {
D(p->level--);
return NULL;
}
}
- { // invalid_comprehension
+ if (p->call_invalid_rules) { // invalid_comprehension
if (p->error_indicator) {
D(p->level--);
return NULL;
D(fprintf(stderr, "%*c%s dictcomp[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{' kvpair for_if_clauses '}'"));
}
- { // invalid_dict_comprehension
+ if (p->call_invalid_rules) { // invalid_dict_comprehension
if (p->error_indicator) {
D(p->level--);
return NULL;
UNUSED(_opt_var); // Silence compiler warnings
asdl_seq * a;
if (
- (a = _gather_103_rule(p)) // ','.double_starred_kvpair+
+ (a = _gather_101_rule(p)) // ','.double_starred_kvpair+
&&
(_opt_var = _PyPegen_expect_token(p, 12), 1) // ','?
)
return NULL;
}
D(fprintf(stderr, "%*c> for_if_clauses[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "for_if_clause+"));
- asdl_seq * _loop1_105_var;
+ asdl_seq * _loop1_103_var;
if (
- (_loop1_105_var = _loop1_105_rule(p)) // for_if_clause+
+ (_loop1_103_var = _loop1_103_rule(p)) // for_if_clause+
)
{
D(fprintf(stderr, "%*c+ for_if_clauses[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "for_if_clause+"));
- _res = _loop1_105_var;
+ _res = _loop1_103_var;
goto done;
}
p->mark = _mark;
&&
(b = disjunction_rule(p)) // disjunction
&&
- (c = _loop0_106_rule(p)) // (('if' disjunction))*
+ (c = _loop0_104_rule(p)) // (('if' disjunction))*
)
{
D(fprintf(stderr, "%*c+ for_if_clause[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "ASYNC 'for' star_targets 'in' ~ disjunction (('if' disjunction))*"));
&&
(b = disjunction_rule(p)) // disjunction
&&
- (c = _loop0_107_rule(p)) // (('if' disjunction))*
+ (c = _loop0_105_rule(p)) // (('if' disjunction))*
)
{
D(fprintf(stderr, "%*c+ for_if_clause[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'for' star_targets 'in' ~ disjunction (('if' disjunction))*"));
return NULL;
}
}
- { // invalid_for_target
+ if (p->call_invalid_rules) { // invalid_for_target
if (p->error_indicator) {
D(p->level--);
return NULL;
return _res;
}
-// arguments: args ','? &')' | incorrect_arguments
+// arguments: args ','? &')' | invalid_arguments
static expr_ty
arguments_rule(Parser *p)
{
D(fprintf(stderr, "%*c%s arguments[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "args ','? &')'"));
}
- { // incorrect_arguments
+ if (p->call_invalid_rules) { // invalid_arguments
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> arguments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "incorrect_arguments"));
- void *incorrect_arguments_var;
+ D(fprintf(stderr, "%*c> arguments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "invalid_arguments"));
+ void *invalid_arguments_var;
if (
- (incorrect_arguments_var = incorrect_arguments_rule(p)) // incorrect_arguments
+ (invalid_arguments_var = invalid_arguments_rule(p)) // invalid_arguments
)
{
- D(fprintf(stderr, "%*c+ arguments[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "incorrect_arguments"));
- _res = incorrect_arguments_var;
+ D(fprintf(stderr, "%*c+ arguments[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "invalid_arguments"));
+ _res = invalid_arguments_var;
goto done;
}
p->mark = _mark;
D(fprintf(stderr, "%*c%s arguments[%d-%d]: %s failed!\n", p->level, ' ',
- p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "incorrect_arguments"));
+ p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "invalid_arguments"));
}
_res = NULL;
done:
asdl_seq * a;
void *b;
if (
- (a = _gather_108_rule(p)) // ','.(starred_expression | named_expression !'=')+
+ (a = _gather_106_rule(p)) // ','.(starred_expression | named_expression !'=')+
&&
- (b = _tmp_110_rule(p), 1) // [',' kwargs]
+ (b = _tmp_108_rule(p), 1) // [',' kwargs]
)
{
D(fprintf(stderr, "%*c+ args[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.(starred_expression | named_expression !'=')+ [',' kwargs]"));
asdl_seq * a;
asdl_seq * b;
if (
- (a = _gather_111_rule(p)) // ','.kwarg_or_starred+
+ (a = _gather_109_rule(p)) // ','.kwarg_or_starred+
&&
(_literal = _PyPegen_expect_token(p, 12)) // token=','
&&
- (b = _gather_113_rule(p)) // ','.kwarg_or_double_starred+
+ (b = _gather_111_rule(p)) // ','.kwarg_or_double_starred+
)
{
D(fprintf(stderr, "%*c+ kwargs[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.kwarg_or_starred+ ',' ','.kwarg_or_double_starred+"));
return NULL;
}
D(fprintf(stderr, "%*c> kwargs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.kwarg_or_starred+"));
- asdl_seq * _gather_115_var;
+ asdl_seq * _gather_113_var;
if (
- (_gather_115_var = _gather_115_rule(p)) // ','.kwarg_or_starred+
+ (_gather_113_var = _gather_113_rule(p)) // ','.kwarg_or_starred+
)
{
D(fprintf(stderr, "%*c+ kwargs[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.kwarg_or_starred+"));
- _res = _gather_115_var;
+ _res = _gather_113_var;
goto done;
}
p->mark = _mark;
return NULL;
}
D(fprintf(stderr, "%*c> kwargs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.kwarg_or_double_starred+"));
- asdl_seq * _gather_117_var;
+ asdl_seq * _gather_115_var;
if (
- (_gather_117_var = _gather_117_rule(p)) // ','.kwarg_or_double_starred+
+ (_gather_115_var = _gather_115_rule(p)) // ','.kwarg_or_double_starred+
)
{
D(fprintf(stderr, "%*c+ kwargs[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.kwarg_or_double_starred+"));
- _res = _gather_117_var;
+ _res = _gather_115_var;
goto done;
}
p->mark = _mark;
D(fprintf(stderr, "%*c%s kwarg_or_starred[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "starred_expression"));
}
- { // invalid_kwarg
+ if (p->call_invalid_rules) { // invalid_kwarg
if (p->error_indicator) {
D(p->level--);
return NULL;
D(fprintf(stderr, "%*c%s kwarg_or_double_starred[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'**' expression"));
}
- { // invalid_kwarg
+ if (p->call_invalid_rules) { // invalid_kwarg
if (p->error_indicator) {
D(p->level--);
return NULL;
if (
(a = star_target_rule(p)) // star_target
&&
- (b = _loop0_119_rule(p)) // ((',' star_target))*
+ (b = _loop0_117_rule(p)) // ((',' star_target))*
&&
(_opt_var = _PyPegen_expect_token(p, 12), 1) // ','?
)
UNUSED(_opt_var); // Silence compiler warnings
asdl_seq * a;
if (
- (a = _gather_120_rule(p)) // ','.star_target+
+ (a = _gather_118_rule(p)) // ','.star_target+
&&
(_opt_var = _PyPegen_expect_token(p, 12), 1) // ','?
)
if (
(_literal = _PyPegen_expect_token(p, 16)) // token='*'
&&
- (a = _tmp_122_rule(p)) // !'*' star_target
+ (a = _tmp_120_rule(p)) // !'*' star_target
)
{
D(fprintf(stderr, "%*c+ star_target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' (!'*' star_target)"));
UNUSED(_opt_var); // Silence compiler warnings
asdl_seq * a;
if (
- (a = _gather_123_rule(p)) // ','.del_target+
+ (a = _gather_121_rule(p)) // ','.del_target+
&&
(_opt_var = _PyPegen_expect_token(p, 12), 1) // ','?
)
UNUSED(_opt_var); // Silence compiler warnings
asdl_seq * a;
if (
- (a = _gather_125_rule(p)) // ','.target+
+ (a = _gather_123_rule(p)) // ','.target+
&&
(_opt_var = _PyPegen_expect_token(p, 12), 1) // ','?
)
}
p->mark = _mark;
void *_raw = t_primary_raw(p);
+ if (p->error_indicator)
+ return NULL;
if (_raw == NULL || p->mark <= _resmark)
break;
_resmark = p->mark;
return _res;
}
-// incorrect_arguments:
+// invalid_arguments:
// | args ',' '*'
// | expression for_if_clauses ',' [args | expression for_if_clauses]
// | args for_if_clauses
// | args ',' expression for_if_clauses
// | args ',' args
static void *
-incorrect_arguments_rule(Parser *p)
+invalid_arguments_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> incorrect_arguments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args ',' '*'"));
+ D(fprintf(stderr, "%*c> invalid_arguments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args ',' '*'"));
Token * _literal;
Token * _literal_1;
expr_ty args_var;
(_literal_1 = _PyPegen_expect_token(p, 16)) // token='*'
)
{
- D(fprintf(stderr, "%*c+ incorrect_arguments[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "args ',' '*'"));
+ D(fprintf(stderr, "%*c+ invalid_arguments[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "args ',' '*'"));
_res = RAISE_SYNTAX_ERROR ( "iterable argument unpacking follows keyword argument unpacking" );
if (_res == NULL && PyErr_Occurred()) {
p->error_indicator = 1;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s incorrect_arguments[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s invalid_arguments[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "args ',' '*'"));
}
{ // expression for_if_clauses ',' [args | expression for_if_clauses]
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> incorrect_arguments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses ',' [args | expression for_if_clauses]"));
+ D(fprintf(stderr, "%*c> invalid_arguments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses ',' [args | expression for_if_clauses]"));
Token * _literal;
void *_opt_var;
UNUSED(_opt_var); // Silence compiler warnings
&&
(_literal = _PyPegen_expect_token(p, 12)) // token=','
&&
- (_opt_var = _tmp_127_rule(p), 1) // [args | expression for_if_clauses]
+ (_opt_var = _tmp_125_rule(p), 1) // [args | expression for_if_clauses]
)
{
- D(fprintf(stderr, "%*c+ incorrect_arguments[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses ',' [args | expression for_if_clauses]"));
+ D(fprintf(stderr, "%*c+ invalid_arguments[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses ',' [args | expression for_if_clauses]"));
_res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "Generator expression must be parenthesized" );
if (_res == NULL && PyErr_Occurred()) {
p->error_indicator = 1;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s incorrect_arguments[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s invalid_arguments[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression for_if_clauses ',' [args | expression for_if_clauses]"));
}
{ // args for_if_clauses
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> incorrect_arguments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args for_if_clauses"));
+ D(fprintf(stderr, "%*c> invalid_arguments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args for_if_clauses"));
expr_ty a;
asdl_seq* for_if_clauses_var;
if (
(for_if_clauses_var = for_if_clauses_rule(p)) // for_if_clauses
)
{
- D(fprintf(stderr, "%*c+ incorrect_arguments[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "args for_if_clauses"));
+ D(fprintf(stderr, "%*c+ invalid_arguments[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "args for_if_clauses"));
_res = _PyPegen_nonparen_genexp_in_call ( p , a );
if (_res == NULL && PyErr_Occurred()) {
p->error_indicator = 1;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s incorrect_arguments[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s invalid_arguments[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "args for_if_clauses"));
}
{ // args ',' expression for_if_clauses
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> incorrect_arguments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args ',' expression for_if_clauses"));
+ D(fprintf(stderr, "%*c> invalid_arguments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args ',' expression for_if_clauses"));
Token * _literal;
expr_ty a;
expr_ty args_var;
(for_if_clauses_var = for_if_clauses_rule(p)) // for_if_clauses
)
{
- D(fprintf(stderr, "%*c+ incorrect_arguments[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "args ',' expression for_if_clauses"));
+ D(fprintf(stderr, "%*c+ invalid_arguments[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "args ',' expression for_if_clauses"));
_res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "Generator expression must be parenthesized" );
if (_res == NULL && PyErr_Occurred()) {
p->error_indicator = 1;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s incorrect_arguments[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s invalid_arguments[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "args ',' expression for_if_clauses"));
}
{ // args ',' args
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> incorrect_arguments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args ',' args"));
+ D(fprintf(stderr, "%*c> invalid_arguments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args ',' args"));
Token * _literal;
expr_ty a;
expr_ty args_var;
(args_var = args_rule(p)) // args
)
{
- D(fprintf(stderr, "%*c+ incorrect_arguments[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "args ',' args"));
+ D(fprintf(stderr, "%*c+ invalid_arguments[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "args ',' args"));
_res = _PyPegen_arguments_parsing_error ( p , a );
if (_res == NULL && PyErr_Occurred()) {
p->error_indicator = 1;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s incorrect_arguments[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s invalid_arguments[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "args ',' args"));
}
_res = NULL;
D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expression ',' star_named_expressions* ':' expression"));
Token * _literal;
Token * _literal_1;
- asdl_seq * _loop0_128_var;
+ asdl_seq * _loop0_126_var;
expr_ty a;
expr_ty expression_var;
if (
&&
(_literal = _PyPegen_expect_token(p, 12)) // token=','
&&
- (_loop0_128_var = _loop0_128_rule(p)) // star_named_expressions*
+ (_loop0_126_var = _loop0_126_rule(p)) // star_named_expressions*
&&
(_literal_1 = _PyPegen_expect_token(p, 11)) // token=':'
&&
}
D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "((star_targets '='))* star_expressions '='"));
Token * _literal;
- asdl_seq * _loop0_129_var;
+ asdl_seq * _loop0_127_var;
expr_ty a;
if (
- (_loop0_129_var = _loop0_129_rule(p)) // ((star_targets '='))*
+ (_loop0_127_var = _loop0_127_rule(p)) // ((star_targets '='))*
&&
(a = star_expressions_rule(p)) // star_expressions
&&
}
D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "((star_targets '='))* yield_expr '='"));
Token * _literal;
- asdl_seq * _loop0_130_var;
+ asdl_seq * _loop0_128_var;
expr_ty a;
if (
- (_loop0_130_var = _loop0_130_rule(p)) // ((star_targets '='))*
+ (_loop0_128_var = _loop0_128_rule(p)) // ((star_targets '='))*
&&
(a = yield_expr_rule(p)) // yield_expr
&&
return NULL;
}
D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions augassign (yield_expr | star_expressions)"));
- void *_tmp_131_var;
+ void *_tmp_129_var;
expr_ty a;
AugOperator* augassign_var;
if (
&&
(augassign_var = augassign_rule(p)) // augassign
&&
- (_tmp_131_var = _tmp_131_rule(p)) // yield_expr | star_expressions
+ (_tmp_129_var = _tmp_129_rule(p)) // yield_expr | star_expressions
)
{
D(fprintf(stderr, "%*c+ invalid_assignment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions augassign (yield_expr | star_expressions)"));
return _res;
}
+// Left-recursive
+// invalid_primary: primary '{'
+static void *
+invalid_primary_rule(Parser *p)
+{
+ D(p->level++);
+ if (p->error_indicator) {
+ D(p->level--);
+ return NULL;
+ }
+ void * _res = NULL;
+ int _mark = p->mark;
+ { // primary '{'
+ if (p->error_indicator) {
+ D(p->level--);
+ return NULL;
+ }
+ D(fprintf(stderr, "%*c> invalid_primary[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "primary '{'"));
+ Token * a;
+ expr_ty primary_var;
+ if (
+ (primary_var = primary_rule(p)) // primary
+ &&
+ (a = _PyPegen_expect_token(p, 25)) // token='{'
+ )
+ {
+ D(fprintf(stderr, "%*c+ invalid_primary[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "primary '{'"));
+ _res = RAISE_SYNTAX_ERROR_KNOWN_LOCATION ( a , "invalid syntax" );
+ if (_res == NULL && PyErr_Occurred()) {
+ p->error_indicator = 1;
+ D(p->level--);
+ return NULL;
+ }
+ goto done;
+ }
+ p->mark = _mark;
+ D(fprintf(stderr, "%*c%s invalid_primary[%d-%d]: %s failed!\n", p->level, ' ',
+ p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "primary '{'"));
+ }
+ _res = NULL;
+ done:
+ D(p->level--);
+ return _res;
+}
+
// invalid_comprehension: ('[' | '(' | '{') starred_expression for_if_clauses
static void *
invalid_comprehension_rule(Parser *p)
return NULL;
}
D(fprintf(stderr, "%*c> invalid_comprehension[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('[' | '(' | '{') starred_expression for_if_clauses"));
- void *_tmp_132_var;
+ void *_tmp_130_var;
expr_ty a;
asdl_seq* for_if_clauses_var;
if (
- (_tmp_132_var = _tmp_132_rule(p)) // '[' | '(' | '{'
+ (_tmp_130_var = _tmp_130_rule(p)) // '[' | '(' | '{'
&&
(a = starred_expression_rule(p)) // starred_expression
&&
return NULL;
}
D(fprintf(stderr, "%*c> invalid_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default* (slash_with_default | param_with_default+) param_no_default"));
- asdl_seq * _loop0_133_var;
- void *_tmp_134_var;
+ asdl_seq * _loop0_131_var;
+ void *_tmp_132_var;
arg_ty param_no_default_var;
if (
- (_loop0_133_var = _loop0_133_rule(p)) // param_no_default*
+ (_loop0_131_var = _loop0_131_rule(p)) // param_no_default*
&&
- (_tmp_134_var = _tmp_134_rule(p)) // slash_with_default | param_with_default+
+ (_tmp_132_var = _tmp_132_rule(p)) // slash_with_default | param_with_default+
&&
(param_no_default_var = param_no_default_rule(p)) // param_no_default
)
return NULL;
}
D(fprintf(stderr, "%*c> invalid_lambda_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default* (lambda_slash_with_default | lambda_param_with_default+) lambda_param_no_default"));
- asdl_seq * _loop0_135_var;
- void *_tmp_136_var;
+ asdl_seq * _loop0_133_var;
+ void *_tmp_134_var;
arg_ty lambda_param_no_default_var;
if (
- (_loop0_135_var = _loop0_135_rule(p)) // lambda_param_no_default*
+ (_loop0_133_var = _loop0_133_rule(p)) // lambda_param_no_default*
&&
- (_tmp_136_var = _tmp_136_rule(p)) // lambda_slash_with_default | lambda_param_with_default+
+ (_tmp_134_var = _tmp_134_rule(p)) // lambda_slash_with_default | lambda_param_with_default+
&&
(lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default
)
}
D(fprintf(stderr, "%*c> invalid_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' (')' | ',' (')' | '**'))"));
Token * _literal;
- void *_tmp_137_var;
+ void *_tmp_135_var;
if (
(_literal = _PyPegen_expect_token(p, 16)) // token='*'
&&
- (_tmp_137_var = _tmp_137_rule(p)) // ')' | ',' (')' | '**')
+ (_tmp_135_var = _tmp_135_rule(p)) // ')' | ',' (')' | '**')
)
{
D(fprintf(stderr, "%*c+ invalid_star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' (')' | ',' (')' | '**'))"));
}
D(fprintf(stderr, "%*c> invalid_lambda_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' (':' | ',' (':' | '**'))"));
Token * _literal;
- void *_tmp_138_var;
+ void *_tmp_136_var;
if (
(_literal = _PyPegen_expect_token(p, 16)) // token='*'
&&
- (_tmp_138_var = _tmp_138_rule(p)) // ':' | ',' (':' | '**')
+ (_tmp_136_var = _tmp_136_rule(p)) // ':' | ',' (':' | '**')
)
{
D(fprintf(stderr, "%*c+ invalid_lambda_star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' (':' | ',' (':' | '**'))"));
return NULL;
}
D(fprintf(stderr, "%*c> _loop1_22[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')"));
- void *_tmp_139_var;
+ void *_tmp_137_var;
while (
- (_tmp_139_var = _tmp_139_rule(p)) // star_targets '='
+ (_tmp_137_var = _tmp_137_rule(p)) // star_targets '='
)
{
- _res = _tmp_139_var;
+ _res = _tmp_137_var;
if (_n == _children_capacity) {
_children_capacity *= 2;
void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
return NULL;
}
D(fprintf(stderr, "%*c> _loop0_31[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('.' | '...')"));
- void *_tmp_140_var;
+ void *_tmp_138_var;
while (
- (_tmp_140_var = _tmp_140_rule(p)) // '.' | '...'
+ (_tmp_138_var = _tmp_138_rule(p)) // '.' | '...'
)
{
- _res = _tmp_140_var;
+ _res = _tmp_138_var;
if (_n == _children_capacity) {
_children_capacity *= 2;
void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
return NULL;
}
D(fprintf(stderr, "%*c> _loop1_32[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('.' | '...')"));
- void *_tmp_141_var;
+ void *_tmp_139_var;
while (
- (_tmp_141_var = _tmp_141_rule(p)) // '.' | '...'
+ (_tmp_139_var = _tmp_139_rule(p)) // '.' | '...'
)
{
- _res = _tmp_141_var;
+ _res = _tmp_139_var;
if (_n == _children_capacity) {
_children_capacity *= 2;
void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
return NULL;
}
D(fprintf(stderr, "%*c> _loop1_68[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('@' named_expression NEWLINE)"));
- void *_tmp_142_var;
+ void *_tmp_140_var;
while (
- (_tmp_142_var = _tmp_142_rule(p)) // '@' named_expression NEWLINE
+ (_tmp_140_var = _tmp_140_rule(p)) // '@' named_expression NEWLINE
)
{
- _res = _tmp_142_var;
+ _res = _tmp_140_var;
if (_n == _children_capacity) {
_children_capacity *= 2;
void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
return _res;
}
-// _loop0_71: ',' star_expression
-static asdl_seq *
-_loop0_71_rule(Parser *p)
-{
- D(p->level++);
- if (p->error_indicator) {
- D(p->level--);
- return NULL;
- }
- void *_res = NULL;
- int _mark = p->mark;
- int _start_mark = p->mark;
- void **_children = PyMem_Malloc(sizeof(void *));
- if (!_children) {
- p->error_indicator = 1;
- PyErr_NoMemory();
- D(p->level--);
- return NULL;
- }
- ssize_t _children_capacity = 1;
- ssize_t _n = 0;
- { // ',' star_expression
- if (p->error_indicator) {
- D(p->level--);
- return NULL;
- }
- D(fprintf(stderr, "%*c> _loop0_71[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_expression"));
- Token * _literal;
- expr_ty elem;
- while (
- (_literal = _PyPegen_expect_token(p, 12)) // token=','
- &&
- (elem = star_expression_rule(p)) // star_expression
- )
- {
- _res = elem;
- if (_res == NULL && PyErr_Occurred()) {
- p->error_indicator = 1;
- PyMem_Free(_children);
- D(p->level--);
- return NULL;
- }
- if (_n == _children_capacity) {
- _children_capacity *= 2;
- void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
- if (!_new_children) {
- p->error_indicator = 1;
- PyErr_NoMemory();
- D(p->level--);
- return NULL;
- }
- _children = _new_children;
- }
- _children[_n++] = _res;
- _mark = p->mark;
- }
- p->mark = _mark;
- D(fprintf(stderr, "%*c%s _loop0_71[%d-%d]: %s failed!\n", p->level, ' ',
- p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_expression"));
- }
- asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena);
- if (!_seq) {
- PyMem_Free(_children);
- p->error_indicator = 1;
- PyErr_NoMemory();
- D(p->level--);
- return NULL;
- }
- for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]);
- PyMem_Free(_children);
- _PyPegen_insert_memo(p, _start_mark, _loop0_71_type, _seq);
- D(p->level--);
- return _seq;
-}
-
-// _gather_70: star_expression _loop0_71
-static asdl_seq *
-_gather_70_rule(Parser *p)
-{
- D(p->level++);
- if (p->error_indicator) {
- D(p->level--);
- return NULL;
- }
- asdl_seq * _res = NULL;
- int _mark = p->mark;
- { // star_expression _loop0_71
- if (p->error_indicator) {
- D(p->level--);
- return NULL;
- }
- D(fprintf(stderr, "%*c> _gather_70[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expression _loop0_71"));
- expr_ty elem;
- asdl_seq * seq;
- if (
- (elem = star_expression_rule(p)) // star_expression
- &&
- (seq = _loop0_71_rule(p)) // _loop0_71
- )
- {
- D(fprintf(stderr, "%*c+ _gather_70[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expression _loop0_71"));
- _res = _PyPegen_seq_insert_in_front(p, elem, seq);
- goto done;
- }
- p->mark = _mark;
- D(fprintf(stderr, "%*c%s _gather_70[%d-%d]: %s failed!\n", p->level, ' ',
- p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_expression _loop0_71"));
- }
- _res = NULL;
- done:
- D(p->level--);
- return _res;
-}
-
-// _loop1_72: (',' star_expression)
+// _loop1_70: (',' star_expression)
static asdl_seq *
-_loop1_72_rule(Parser *p)
+_loop1_70_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _loop1_72[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_expression)"));
- void *_tmp_143_var;
+ D(fprintf(stderr, "%*c> _loop1_70[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_expression)"));
+ void *_tmp_141_var;
while (
- (_tmp_143_var = _tmp_143_rule(p)) // ',' star_expression
+ (_tmp_141_var = _tmp_141_rule(p)) // ',' star_expression
)
{
- _res = _tmp_143_var;
+ _res = _tmp_141_var;
if (_n == _children_capacity) {
_children_capacity *= 2;
void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
_mark = p->mark;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _loop1_72[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _loop1_70[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(',' star_expression)"));
}
if (_n == 0 || p->error_indicator) {
}
for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]);
PyMem_Free(_children);
- _PyPegen_insert_memo(p, _start_mark, _loop1_72_type, _seq);
+ _PyPegen_insert_memo(p, _start_mark, _loop1_70_type, _seq);
D(p->level--);
return _seq;
}
-// _loop0_74: ',' star_named_expression
+// _loop0_72: ',' star_named_expression
static asdl_seq *
-_loop0_74_rule(Parser *p)
+_loop0_72_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _loop0_74[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_named_expression"));
+ D(fprintf(stderr, "%*c> _loop0_72[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_named_expression"));
Token * _literal;
expr_ty elem;
while (
_mark = p->mark;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _loop0_74[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _loop0_72[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_named_expression"));
}
asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena);
}
for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]);
PyMem_Free(_children);
- _PyPegen_insert_memo(p, _start_mark, _loop0_74_type, _seq);
+ _PyPegen_insert_memo(p, _start_mark, _loop0_72_type, _seq);
D(p->level--);
return _seq;
}
-// _gather_73: star_named_expression _loop0_74
+// _gather_71: star_named_expression _loop0_72
static asdl_seq *
-_gather_73_rule(Parser *p)
+_gather_71_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
}
asdl_seq * _res = NULL;
int _mark = p->mark;
- { // star_named_expression _loop0_74
+ { // star_named_expression _loop0_72
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _gather_73[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expression _loop0_74"));
+ D(fprintf(stderr, "%*c> _gather_71[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expression _loop0_72"));
expr_ty elem;
asdl_seq * seq;
if (
(elem = star_named_expression_rule(p)) // star_named_expression
&&
- (seq = _loop0_74_rule(p)) // _loop0_74
+ (seq = _loop0_72_rule(p)) // _loop0_72
)
{
- D(fprintf(stderr, "%*c+ _gather_73[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_named_expression _loop0_74"));
+ D(fprintf(stderr, "%*c+ _gather_71[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_named_expression _loop0_72"));
_res = _PyPegen_seq_insert_in_front(p, elem, seq);
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _gather_73[%d-%d]: %s failed!\n", p->level, ' ',
- p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_named_expression _loop0_74"));
+ D(fprintf(stderr, "%*c%s _gather_71[%d-%d]: %s failed!\n", p->level, ' ',
+ p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_named_expression _loop0_72"));
}
_res = NULL;
done:
return _res;
}
-// _loop1_75: (',' expression)
+// _loop1_73: (',' expression)
static asdl_seq *
-_loop1_75_rule(Parser *p)
+_loop1_73_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _loop1_75[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' expression)"));
- void *_tmp_144_var;
+ D(fprintf(stderr, "%*c> _loop1_73[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' expression)"));
+ void *_tmp_142_var;
while (
- (_tmp_144_var = _tmp_144_rule(p)) // ',' expression
+ (_tmp_142_var = _tmp_142_rule(p)) // ',' expression
)
{
- _res = _tmp_144_var;
+ _res = _tmp_142_var;
if (_n == _children_capacity) {
_children_capacity *= 2;
void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
_mark = p->mark;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _loop1_75[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _loop1_73[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(',' expression)"));
}
if (_n == 0 || p->error_indicator) {
}
for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]);
PyMem_Free(_children);
- _PyPegen_insert_memo(p, _start_mark, _loop1_75_type, _seq);
+ _PyPegen_insert_memo(p, _start_mark, _loop1_73_type, _seq);
D(p->level--);
return _seq;
}
-// _loop0_76: lambda_param_no_default
+// _loop0_74: lambda_param_no_default
static asdl_seq *
-_loop0_76_rule(Parser *p)
+_loop0_74_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _loop0_76[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default"));
+ D(fprintf(stderr, "%*c> _loop0_74[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default"));
arg_ty lambda_param_no_default_var;
while (
(lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default
_mark = p->mark;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _loop0_76[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _loop0_74[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default"));
}
asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena);
}
for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]);
PyMem_Free(_children);
- _PyPegen_insert_memo(p, _start_mark, _loop0_76_type, _seq);
+ _PyPegen_insert_memo(p, _start_mark, _loop0_74_type, _seq);
D(p->level--);
return _seq;
}
-// _loop0_77: lambda_param_with_default
+// _loop0_75: lambda_param_with_default
static asdl_seq *
-_loop0_77_rule(Parser *p)
+_loop0_75_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _loop0_77[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default"));
+ D(fprintf(stderr, "%*c> _loop0_75[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default"));
NameDefaultPair* lambda_param_with_default_var;
while (
(lambda_param_with_default_var = lambda_param_with_default_rule(p)) // lambda_param_with_default
_mark = p->mark;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _loop0_77[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _loop0_75[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_with_default"));
}
asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena);
}
for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]);
PyMem_Free(_children);
- _PyPegen_insert_memo(p, _start_mark, _loop0_77_type, _seq);
+ _PyPegen_insert_memo(p, _start_mark, _loop0_75_type, _seq);
D(p->level--);
return _seq;
}
-// _loop0_78: lambda_param_with_default
+// _loop0_76: lambda_param_with_default
static asdl_seq *
-_loop0_78_rule(Parser *p)
+_loop0_76_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _loop0_78[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default"));
+ D(fprintf(stderr, "%*c> _loop0_76[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default"));
NameDefaultPair* lambda_param_with_default_var;
while (
(lambda_param_with_default_var = lambda_param_with_default_rule(p)) // lambda_param_with_default
_mark = p->mark;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _loop0_78[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _loop0_76[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_with_default"));
}
asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena);
}
for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]);
PyMem_Free(_children);
- _PyPegen_insert_memo(p, _start_mark, _loop0_78_type, _seq);
+ _PyPegen_insert_memo(p, _start_mark, _loop0_76_type, _seq);
D(p->level--);
return _seq;
}
-// _loop1_79: lambda_param_no_default
+// _loop1_77: lambda_param_no_default
static asdl_seq *
-_loop1_79_rule(Parser *p)
+_loop1_77_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _loop1_79[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default"));
+ D(fprintf(stderr, "%*c> _loop1_77[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default"));
arg_ty lambda_param_no_default_var;
while (
(lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default
_mark = p->mark;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _loop1_79[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _loop1_77[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default"));
}
if (_n == 0 || p->error_indicator) {
}
for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]);
PyMem_Free(_children);
- _PyPegen_insert_memo(p, _start_mark, _loop1_79_type, _seq);
+ _PyPegen_insert_memo(p, _start_mark, _loop1_77_type, _seq);
D(p->level--);
return _seq;
}
-// _loop0_80: lambda_param_with_default
+// _loop0_78: lambda_param_with_default
static asdl_seq *
-_loop0_80_rule(Parser *p)
+_loop0_78_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _loop0_80[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default"));
+ D(fprintf(stderr, "%*c> _loop0_78[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default"));
NameDefaultPair* lambda_param_with_default_var;
while (
(lambda_param_with_default_var = lambda_param_with_default_rule(p)) // lambda_param_with_default
_mark = p->mark;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _loop0_80[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _loop0_78[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_with_default"));
}
asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena);
}
for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]);
PyMem_Free(_children);
- _PyPegen_insert_memo(p, _start_mark, _loop0_80_type, _seq);
+ _PyPegen_insert_memo(p, _start_mark, _loop0_78_type, _seq);
D(p->level--);
return _seq;
}
-// _loop1_81: lambda_param_with_default
+// _loop1_79: lambda_param_with_default
static asdl_seq *
-_loop1_81_rule(Parser *p)
+_loop1_79_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _loop1_81[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default"));
+ D(fprintf(stderr, "%*c> _loop1_79[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default"));
NameDefaultPair* lambda_param_with_default_var;
while (
(lambda_param_with_default_var = lambda_param_with_default_rule(p)) // lambda_param_with_default
_mark = p->mark;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _loop1_81[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _loop1_79[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_with_default"));
}
if (_n == 0 || p->error_indicator) {
}
for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]);
PyMem_Free(_children);
- _PyPegen_insert_memo(p, _start_mark, _loop1_81_type, _seq);
+ _PyPegen_insert_memo(p, _start_mark, _loop1_79_type, _seq);
D(p->level--);
return _seq;
}
-// _loop1_82: lambda_param_no_default
+// _loop1_80: lambda_param_no_default
static asdl_seq *
-_loop1_82_rule(Parser *p)
+_loop1_80_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _loop1_82[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default"));
+ D(fprintf(stderr, "%*c> _loop1_80[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default"));
arg_ty lambda_param_no_default_var;
while (
(lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default
_mark = p->mark;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _loop1_82[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _loop1_80[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default"));
}
if (_n == 0 || p->error_indicator) {
}
for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]);
PyMem_Free(_children);
- _PyPegen_insert_memo(p, _start_mark, _loop1_82_type, _seq);
+ _PyPegen_insert_memo(p, _start_mark, _loop1_80_type, _seq);
D(p->level--);
return _seq;
}
-// _loop1_83: lambda_param_no_default
+// _loop1_81: lambda_param_no_default
static asdl_seq *
-_loop1_83_rule(Parser *p)
+_loop1_81_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _loop1_83[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default"));
+ D(fprintf(stderr, "%*c> _loop1_81[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default"));
arg_ty lambda_param_no_default_var;
while (
(lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default
_mark = p->mark;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _loop1_83[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _loop1_81[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default"));
}
if (_n == 0 || p->error_indicator) {
}
for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]);
PyMem_Free(_children);
- _PyPegen_insert_memo(p, _start_mark, _loop1_83_type, _seq);
+ _PyPegen_insert_memo(p, _start_mark, _loop1_81_type, _seq);
D(p->level--);
return _seq;
}
-// _loop0_84: lambda_param_no_default
+// _loop0_82: lambda_param_no_default
static asdl_seq *
-_loop0_84_rule(Parser *p)
+_loop0_82_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _loop0_84[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default"));
+ D(fprintf(stderr, "%*c> _loop0_82[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default"));
arg_ty lambda_param_no_default_var;
while (
(lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default
_mark = p->mark;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _loop0_84[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _loop0_82[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default"));
}
asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena);
}
for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]);
PyMem_Free(_children);
- _PyPegen_insert_memo(p, _start_mark, _loop0_84_type, _seq);
+ _PyPegen_insert_memo(p, _start_mark, _loop0_82_type, _seq);
D(p->level--);
return _seq;
}
-// _loop1_85: lambda_param_with_default
+// _loop1_83: lambda_param_with_default
static asdl_seq *
-_loop1_85_rule(Parser *p)
+_loop1_83_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _loop1_85[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default"));
+ D(fprintf(stderr, "%*c> _loop1_83[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default"));
NameDefaultPair* lambda_param_with_default_var;
while (
(lambda_param_with_default_var = lambda_param_with_default_rule(p)) // lambda_param_with_default
_mark = p->mark;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _loop1_85[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _loop1_83[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_with_default"));
}
if (_n == 0 || p->error_indicator) {
}
for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]);
PyMem_Free(_children);
- _PyPegen_insert_memo(p, _start_mark, _loop1_85_type, _seq);
+ _PyPegen_insert_memo(p, _start_mark, _loop1_83_type, _seq);
D(p->level--);
return _seq;
}
-// _loop0_86: lambda_param_no_default
+// _loop0_84: lambda_param_no_default
static asdl_seq *
-_loop0_86_rule(Parser *p)
+_loop0_84_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _loop0_86[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default"));
+ D(fprintf(stderr, "%*c> _loop0_84[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default"));
arg_ty lambda_param_no_default_var;
while (
(lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default
_mark = p->mark;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _loop0_86[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _loop0_84[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default"));
}
asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena);
}
for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]);
PyMem_Free(_children);
- _PyPegen_insert_memo(p, _start_mark, _loop0_86_type, _seq);
+ _PyPegen_insert_memo(p, _start_mark, _loop0_84_type, _seq);
D(p->level--);
return _seq;
}
-// _loop1_87: lambda_param_with_default
+// _loop1_85: lambda_param_with_default
static asdl_seq *
-_loop1_87_rule(Parser *p)
+_loop1_85_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _loop1_87[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default"));
+ D(fprintf(stderr, "%*c> _loop1_85[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default"));
NameDefaultPair* lambda_param_with_default_var;
while (
(lambda_param_with_default_var = lambda_param_with_default_rule(p)) // lambda_param_with_default
_mark = p->mark;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _loop1_87[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _loop1_85[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_with_default"));
}
if (_n == 0 || p->error_indicator) {
}
for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]);
PyMem_Free(_children);
- _PyPegen_insert_memo(p, _start_mark, _loop1_87_type, _seq);
+ _PyPegen_insert_memo(p, _start_mark, _loop1_85_type, _seq);
D(p->level--);
return _seq;
}
-// _loop0_88: lambda_param_maybe_default
+// _loop0_86: lambda_param_maybe_default
static asdl_seq *
-_loop0_88_rule(Parser *p)
+_loop0_86_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _loop0_88[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default"));
+ D(fprintf(stderr, "%*c> _loop0_86[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default"));
NameDefaultPair* lambda_param_maybe_default_var;
while (
(lambda_param_maybe_default_var = lambda_param_maybe_default_rule(p)) // lambda_param_maybe_default
_mark = p->mark;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _loop0_88[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _loop0_86[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_maybe_default"));
}
asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena);
}
for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]);
PyMem_Free(_children);
- _PyPegen_insert_memo(p, _start_mark, _loop0_88_type, _seq);
+ _PyPegen_insert_memo(p, _start_mark, _loop0_86_type, _seq);
D(p->level--);
return _seq;
}
-// _loop1_89: lambda_param_maybe_default
+// _loop1_87: lambda_param_maybe_default
static asdl_seq *
-_loop1_89_rule(Parser *p)
+_loop1_87_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _loop1_89[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default"));
+ D(fprintf(stderr, "%*c> _loop1_87[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default"));
NameDefaultPair* lambda_param_maybe_default_var;
while (
(lambda_param_maybe_default_var = lambda_param_maybe_default_rule(p)) // lambda_param_maybe_default
_mark = p->mark;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _loop1_89[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _loop1_87[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_maybe_default"));
}
if (_n == 0 || p->error_indicator) {
}
for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]);
PyMem_Free(_children);
- _PyPegen_insert_memo(p, _start_mark, _loop1_89_type, _seq);
+ _PyPegen_insert_memo(p, _start_mark, _loop1_87_type, _seq);
D(p->level--);
return _seq;
}
-// _loop1_90: ('or' conjunction)
+// _loop1_88: ('or' conjunction)
static asdl_seq *
-_loop1_90_rule(Parser *p)
+_loop1_88_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _loop1_90[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('or' conjunction)"));
- void *_tmp_145_var;
+ D(fprintf(stderr, "%*c> _loop1_88[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('or' conjunction)"));
+ void *_tmp_143_var;
while (
- (_tmp_145_var = _tmp_145_rule(p)) // 'or' conjunction
+ (_tmp_143_var = _tmp_143_rule(p)) // 'or' conjunction
)
{
- _res = _tmp_145_var;
+ _res = _tmp_143_var;
if (_n == _children_capacity) {
_children_capacity *= 2;
void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
_mark = p->mark;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _loop1_90[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _loop1_88[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "('or' conjunction)"));
}
if (_n == 0 || p->error_indicator) {
}
for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]);
PyMem_Free(_children);
- _PyPegen_insert_memo(p, _start_mark, _loop1_90_type, _seq);
+ _PyPegen_insert_memo(p, _start_mark, _loop1_88_type, _seq);
D(p->level--);
return _seq;
}
-// _loop1_91: ('and' inversion)
+// _loop1_89: ('and' inversion)
static asdl_seq *
-_loop1_91_rule(Parser *p)
+_loop1_89_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _loop1_91[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('and' inversion)"));
- void *_tmp_146_var;
+ D(fprintf(stderr, "%*c> _loop1_89[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('and' inversion)"));
+ void *_tmp_144_var;
while (
- (_tmp_146_var = _tmp_146_rule(p)) // 'and' inversion
+ (_tmp_144_var = _tmp_144_rule(p)) // 'and' inversion
)
{
- _res = _tmp_146_var;
+ _res = _tmp_144_var;
if (_n == _children_capacity) {
_children_capacity *= 2;
void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
_mark = p->mark;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _loop1_91[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _loop1_89[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "('and' inversion)"));
}
if (_n == 0 || p->error_indicator) {
}
for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]);
PyMem_Free(_children);
- _PyPegen_insert_memo(p, _start_mark, _loop1_91_type, _seq);
+ _PyPegen_insert_memo(p, _start_mark, _loop1_89_type, _seq);
D(p->level--);
return _seq;
}
-// _loop1_92: compare_op_bitwise_or_pair
+// _loop1_90: compare_op_bitwise_or_pair
static asdl_seq *
-_loop1_92_rule(Parser *p)
+_loop1_90_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _loop1_92[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "compare_op_bitwise_or_pair"));
+ D(fprintf(stderr, "%*c> _loop1_90[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "compare_op_bitwise_or_pair"));
CmpopExprPair* compare_op_bitwise_or_pair_var;
while (
(compare_op_bitwise_or_pair_var = compare_op_bitwise_or_pair_rule(p)) // compare_op_bitwise_or_pair
_mark = p->mark;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _loop1_92[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _loop1_90[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "compare_op_bitwise_or_pair"));
}
if (_n == 0 || p->error_indicator) {
}
for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]);
PyMem_Free(_children);
- _PyPegen_insert_memo(p, _start_mark, _loop1_92_type, _seq);
+ _PyPegen_insert_memo(p, _start_mark, _loop1_90_type, _seq);
D(p->level--);
return _seq;
}
-// _tmp_93: '!='
+// _tmp_91: '!='
static void *
-_tmp_93_rule(Parser *p)
+_tmp_91_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_93[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!='"));
+ D(fprintf(stderr, "%*c> _tmp_91[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!='"));
Token * tok;
if (
(tok = _PyPegen_expect_token(p, 28)) // token='!='
)
{
- D(fprintf(stderr, "%*c+ _tmp_93[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!='"));
- _res = _PyPegen_check_barry_as_flufl ( p ) ? NULL : tok;
+ D(fprintf(stderr, "%*c+ _tmp_91[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!='"));
+ _res = _PyPegen_check_barry_as_flufl ( p , tok ) ? NULL : tok;
if (_res == NULL && PyErr_Occurred()) {
p->error_indicator = 1;
D(p->level--);
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_93[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_91[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'!='"));
}
_res = NULL;
return _res;
}
-// _loop0_95: ',' slice
+// _loop0_93: ',' slice
static asdl_seq *
-_loop0_95_rule(Parser *p)
+_loop0_93_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _loop0_95[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' slice"));
+ D(fprintf(stderr, "%*c> _loop0_93[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' slice"));
Token * _literal;
expr_ty elem;
while (
_mark = p->mark;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _loop0_95[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _loop0_93[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' slice"));
}
asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena);
}
for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]);
PyMem_Free(_children);
- _PyPegen_insert_memo(p, _start_mark, _loop0_95_type, _seq);
+ _PyPegen_insert_memo(p, _start_mark, _loop0_93_type, _seq);
D(p->level--);
return _seq;
}
-// _gather_94: slice _loop0_95
+// _gather_92: slice _loop0_93
static asdl_seq *
-_gather_94_rule(Parser *p)
+_gather_92_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
}
asdl_seq * _res = NULL;
int _mark = p->mark;
- { // slice _loop0_95
+ { // slice _loop0_93
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _gather_94[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slice _loop0_95"));
+ D(fprintf(stderr, "%*c> _gather_92[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slice _loop0_93"));
expr_ty elem;
asdl_seq * seq;
if (
(elem = slice_rule(p)) // slice
&&
- (seq = _loop0_95_rule(p)) // _loop0_95
+ (seq = _loop0_93_rule(p)) // _loop0_93
)
{
- D(fprintf(stderr, "%*c+ _gather_94[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slice _loop0_95"));
+ D(fprintf(stderr, "%*c+ _gather_92[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slice _loop0_93"));
_res = _PyPegen_seq_insert_in_front(p, elem, seq);
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _gather_94[%d-%d]: %s failed!\n", p->level, ' ',
- p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "slice _loop0_95"));
+ D(fprintf(stderr, "%*c%s _gather_92[%d-%d]: %s failed!\n", p->level, ' ',
+ p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "slice _loop0_93"));
}
_res = NULL;
done:
return _res;
}
-// _tmp_96: ':' expression?
+// _tmp_94: ':' expression?
static void *
-_tmp_96_rule(Parser *p)
+_tmp_94_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_96[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':' expression?"));
+ D(fprintf(stderr, "%*c> _tmp_94[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':' expression?"));
Token * _literal;
void *d;
if (
(d = expression_rule(p), 1) // expression?
)
{
- D(fprintf(stderr, "%*c+ _tmp_96[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':' expression?"));
+ D(fprintf(stderr, "%*c+ _tmp_94[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':' expression?"));
_res = d;
if (_res == NULL && PyErr_Occurred()) {
p->error_indicator = 1;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_96[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_94[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':' expression?"));
}
_res = NULL;
return _res;
}
-// _tmp_97: tuple | group | genexp
+// _tmp_95: tuple | group | genexp
static void *
-_tmp_97_rule(Parser *p)
+_tmp_95_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_97[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "tuple"));
+ D(fprintf(stderr, "%*c> _tmp_95[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "tuple"));
expr_ty tuple_var;
if (
(tuple_var = tuple_rule(p)) // tuple
)
{
- D(fprintf(stderr, "%*c+ _tmp_97[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "tuple"));
+ D(fprintf(stderr, "%*c+ _tmp_95[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "tuple"));
_res = tuple_var;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_97[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_95[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "tuple"));
}
{ // group
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_97[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "group"));
+ D(fprintf(stderr, "%*c> _tmp_95[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "group"));
expr_ty group_var;
if (
(group_var = group_rule(p)) // group
)
{
- D(fprintf(stderr, "%*c+ _tmp_97[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "group"));
+ D(fprintf(stderr, "%*c+ _tmp_95[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "group"));
_res = group_var;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_97[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_95[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "group"));
}
{ // genexp
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_97[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "genexp"));
+ D(fprintf(stderr, "%*c> _tmp_95[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "genexp"));
expr_ty genexp_var;
if (
(genexp_var = genexp_rule(p)) // genexp
)
{
- D(fprintf(stderr, "%*c+ _tmp_97[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "genexp"));
+ D(fprintf(stderr, "%*c+ _tmp_95[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "genexp"));
_res = genexp_var;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_97[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_95[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "genexp"));
}
_res = NULL;
return _res;
}
-// _tmp_98: list | listcomp
+// _tmp_96: list | listcomp
static void *
-_tmp_98_rule(Parser *p)
+_tmp_96_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_98[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "list"));
+ D(fprintf(stderr, "%*c> _tmp_96[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "list"));
expr_ty list_var;
if (
(list_var = list_rule(p)) // list
)
{
- D(fprintf(stderr, "%*c+ _tmp_98[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "list"));
+ D(fprintf(stderr, "%*c+ _tmp_96[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "list"));
_res = list_var;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_98[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_96[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "list"));
}
{ // listcomp
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_98[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "listcomp"));
+ D(fprintf(stderr, "%*c> _tmp_96[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "listcomp"));
expr_ty listcomp_var;
if (
(listcomp_var = listcomp_rule(p)) // listcomp
)
{
- D(fprintf(stderr, "%*c+ _tmp_98[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "listcomp"));
+ D(fprintf(stderr, "%*c+ _tmp_96[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "listcomp"));
_res = listcomp_var;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_98[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_96[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "listcomp"));
}
_res = NULL;
return _res;
}
-// _tmp_99: dict | set | dictcomp | setcomp
+// _tmp_97: dict | set | dictcomp | setcomp
static void *
-_tmp_99_rule(Parser *p)
+_tmp_97_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_99[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "dict"));
+ D(fprintf(stderr, "%*c> _tmp_97[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "dict"));
expr_ty dict_var;
if (
(dict_var = dict_rule(p)) // dict
)
{
- D(fprintf(stderr, "%*c+ _tmp_99[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "dict"));
+ D(fprintf(stderr, "%*c+ _tmp_97[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "dict"));
_res = dict_var;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_99[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_97[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "dict"));
}
{ // set
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_99[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "set"));
+ D(fprintf(stderr, "%*c> _tmp_97[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "set"));
expr_ty set_var;
if (
(set_var = set_rule(p)) // set
)
{
- D(fprintf(stderr, "%*c+ _tmp_99[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "set"));
+ D(fprintf(stderr, "%*c+ _tmp_97[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "set"));
_res = set_var;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_99[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_97[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "set"));
}
{ // dictcomp
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_99[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "dictcomp"));
+ D(fprintf(stderr, "%*c> _tmp_97[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "dictcomp"));
expr_ty dictcomp_var;
if (
(dictcomp_var = dictcomp_rule(p)) // dictcomp
)
{
- D(fprintf(stderr, "%*c+ _tmp_99[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "dictcomp"));
+ D(fprintf(stderr, "%*c+ _tmp_97[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "dictcomp"));
_res = dictcomp_var;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_99[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_97[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "dictcomp"));
}
{ // setcomp
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_99[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "setcomp"));
+ D(fprintf(stderr, "%*c> _tmp_97[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "setcomp"));
expr_ty setcomp_var;
if (
(setcomp_var = setcomp_rule(p)) // setcomp
)
{
- D(fprintf(stderr, "%*c+ _tmp_99[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "setcomp"));
+ D(fprintf(stderr, "%*c+ _tmp_97[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "setcomp"));
_res = setcomp_var;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_99[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_97[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "setcomp"));
}
_res = NULL;
return _res;
}
-// _loop1_100: STRING
+// _loop1_98: STRING
static asdl_seq *
-_loop1_100_rule(Parser *p)
+_loop1_98_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _loop1_100[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "STRING"));
+ D(fprintf(stderr, "%*c> _loop1_98[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "STRING"));
expr_ty string_var;
while (
(string_var = _PyPegen_string_token(p)) // STRING
_mark = p->mark;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _loop1_100[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _loop1_98[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "STRING"));
}
if (_n == 0 || p->error_indicator) {
}
for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]);
PyMem_Free(_children);
- _PyPegen_insert_memo(p, _start_mark, _loop1_100_type, _seq);
+ _PyPegen_insert_memo(p, _start_mark, _loop1_98_type, _seq);
D(p->level--);
return _seq;
}
-// _tmp_101: star_named_expression ',' star_named_expressions?
+// _tmp_99: star_named_expression ',' star_named_expressions?
static void *
-_tmp_101_rule(Parser *p)
+_tmp_99_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_101[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expression ',' star_named_expressions?"));
+ D(fprintf(stderr, "%*c> _tmp_99[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expression ',' star_named_expressions?"));
Token * _literal;
expr_ty y;
void *z;
(z = star_named_expressions_rule(p), 1) // star_named_expressions?
)
{
- D(fprintf(stderr, "%*c+ _tmp_101[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_named_expression ',' star_named_expressions?"));
+ D(fprintf(stderr, "%*c+ _tmp_99[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_named_expression ',' star_named_expressions?"));
_res = _PyPegen_seq_insert_in_front ( p , y , z );
if (_res == NULL && PyErr_Occurred()) {
p->error_indicator = 1;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_101[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_99[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_named_expression ',' star_named_expressions?"));
}
_res = NULL;
return _res;
}
-// _tmp_102: yield_expr | named_expression
+// _tmp_100: yield_expr | named_expression
static void *
-_tmp_102_rule(Parser *p)
+_tmp_100_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_102[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr"));
+ D(fprintf(stderr, "%*c> _tmp_100[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr"));
expr_ty yield_expr_var;
if (
(yield_expr_var = yield_expr_rule(p)) // yield_expr
)
{
- D(fprintf(stderr, "%*c+ _tmp_102[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr"));
+ D(fprintf(stderr, "%*c+ _tmp_100[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr"));
_res = yield_expr_var;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_102[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_100[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "yield_expr"));
}
{ // named_expression
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_102[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "named_expression"));
+ D(fprintf(stderr, "%*c> _tmp_100[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "named_expression"));
expr_ty named_expression_var;
if (
(named_expression_var = named_expression_rule(p)) // named_expression
)
{
- D(fprintf(stderr, "%*c+ _tmp_102[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "named_expression"));
+ D(fprintf(stderr, "%*c+ _tmp_100[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "named_expression"));
_res = named_expression_var;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_102[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_100[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "named_expression"));
}
_res = NULL;
return _res;
}
-// _loop0_104: ',' double_starred_kvpair
+// _loop0_102: ',' double_starred_kvpair
static asdl_seq *
-_loop0_104_rule(Parser *p)
+_loop0_102_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _loop0_104[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' double_starred_kvpair"));
+ D(fprintf(stderr, "%*c> _loop0_102[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' double_starred_kvpair"));
Token * _literal;
KeyValuePair* elem;
while (
_mark = p->mark;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _loop0_104[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _loop0_102[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' double_starred_kvpair"));
}
asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena);
}
for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]);
PyMem_Free(_children);
- _PyPegen_insert_memo(p, _start_mark, _loop0_104_type, _seq);
+ _PyPegen_insert_memo(p, _start_mark, _loop0_102_type, _seq);
D(p->level--);
return _seq;
}
-// _gather_103: double_starred_kvpair _loop0_104
+// _gather_101: double_starred_kvpair _loop0_102
static asdl_seq *
-_gather_103_rule(Parser *p)
+_gather_101_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
}
asdl_seq * _res = NULL;
int _mark = p->mark;
- { // double_starred_kvpair _loop0_104
+ { // double_starred_kvpair _loop0_102
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _gather_103[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_104"));
+ D(fprintf(stderr, "%*c> _gather_101[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_102"));
KeyValuePair* elem;
asdl_seq * seq;
if (
(elem = double_starred_kvpair_rule(p)) // double_starred_kvpair
&&
- (seq = _loop0_104_rule(p)) // _loop0_104
+ (seq = _loop0_102_rule(p)) // _loop0_102
)
{
- D(fprintf(stderr, "%*c+ _gather_103[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_104"));
+ D(fprintf(stderr, "%*c+ _gather_101[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_102"));
_res = _PyPegen_seq_insert_in_front(p, elem, seq);
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _gather_103[%d-%d]: %s failed!\n", p->level, ' ',
- p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "double_starred_kvpair _loop0_104"));
+ D(fprintf(stderr, "%*c%s _gather_101[%d-%d]: %s failed!\n", p->level, ' ',
+ p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "double_starred_kvpair _loop0_102"));
}
_res = NULL;
done:
return _res;
}
-// _loop1_105: for_if_clause
+// _loop1_103: for_if_clause
static asdl_seq *
-_loop1_105_rule(Parser *p)
+_loop1_103_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _loop1_105[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "for_if_clause"));
+ D(fprintf(stderr, "%*c> _loop1_103[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "for_if_clause"));
comprehension_ty for_if_clause_var;
while (
(for_if_clause_var = for_if_clause_rule(p)) // for_if_clause
_mark = p->mark;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _loop1_105[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _loop1_103[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "for_if_clause"));
}
if (_n == 0 || p->error_indicator) {
}
for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]);
PyMem_Free(_children);
- _PyPegen_insert_memo(p, _start_mark, _loop1_105_type, _seq);
+ _PyPegen_insert_memo(p, _start_mark, _loop1_103_type, _seq);
D(p->level--);
return _seq;
}
-// _loop0_106: ('if' disjunction)
+// _loop0_104: ('if' disjunction)
static asdl_seq *
-_loop0_106_rule(Parser *p)
+_loop0_104_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _loop0_106[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('if' disjunction)"));
- void *_tmp_147_var;
+ D(fprintf(stderr, "%*c> _loop0_104[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('if' disjunction)"));
+ void *_tmp_145_var;
while (
- (_tmp_147_var = _tmp_147_rule(p)) // 'if' disjunction
+ (_tmp_145_var = _tmp_145_rule(p)) // 'if' disjunction
)
{
- _res = _tmp_147_var;
+ _res = _tmp_145_var;
if (_n == _children_capacity) {
_children_capacity *= 2;
void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
_mark = p->mark;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _loop0_106[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _loop0_104[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "('if' disjunction)"));
}
asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena);
}
for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]);
PyMem_Free(_children);
- _PyPegen_insert_memo(p, _start_mark, _loop0_106_type, _seq);
+ _PyPegen_insert_memo(p, _start_mark, _loop0_104_type, _seq);
D(p->level--);
return _seq;
}
-// _loop0_107: ('if' disjunction)
+// _loop0_105: ('if' disjunction)
static asdl_seq *
-_loop0_107_rule(Parser *p)
+_loop0_105_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _loop0_107[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('if' disjunction)"));
- void *_tmp_148_var;
+ D(fprintf(stderr, "%*c> _loop0_105[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('if' disjunction)"));
+ void *_tmp_146_var;
while (
- (_tmp_148_var = _tmp_148_rule(p)) // 'if' disjunction
+ (_tmp_146_var = _tmp_146_rule(p)) // 'if' disjunction
)
{
- _res = _tmp_148_var;
+ _res = _tmp_146_var;
if (_n == _children_capacity) {
_children_capacity *= 2;
void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
_mark = p->mark;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _loop0_107[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _loop0_105[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "('if' disjunction)"));
}
asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena);
}
for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]);
PyMem_Free(_children);
- _PyPegen_insert_memo(p, _start_mark, _loop0_107_type, _seq);
+ _PyPegen_insert_memo(p, _start_mark, _loop0_105_type, _seq);
D(p->level--);
return _seq;
}
-// _loop0_109: ',' (starred_expression | named_expression !'=')
+// _loop0_107: ',' (starred_expression | named_expression !'=')
static asdl_seq *
-_loop0_109_rule(Parser *p)
+_loop0_107_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _loop0_109[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (starred_expression | named_expression !'=')"));
+ D(fprintf(stderr, "%*c> _loop0_107[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (starred_expression | named_expression !'=')"));
Token * _literal;
void *elem;
while (
(_literal = _PyPegen_expect_token(p, 12)) // token=','
&&
- (elem = _tmp_149_rule(p)) // starred_expression | named_expression !'='
+ (elem = _tmp_147_rule(p)) // starred_expression | named_expression !'='
)
{
_res = elem;
_mark = p->mark;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _loop0_109[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _loop0_107[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (starred_expression | named_expression !'=')"));
}
asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena);
}
for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]);
PyMem_Free(_children);
- _PyPegen_insert_memo(p, _start_mark, _loop0_109_type, _seq);
+ _PyPegen_insert_memo(p, _start_mark, _loop0_107_type, _seq);
D(p->level--);
return _seq;
}
-// _gather_108: (starred_expression | named_expression !'=') _loop0_109
+// _gather_106: (starred_expression | named_expression !'=') _loop0_107
static asdl_seq *
-_gather_108_rule(Parser *p)
+_gather_106_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
}
asdl_seq * _res = NULL;
int _mark = p->mark;
- { // (starred_expression | named_expression !'=') _loop0_109
+ { // (starred_expression | named_expression !'=') _loop0_107
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _gather_108[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(starred_expression | named_expression !'=') _loop0_109"));
+ D(fprintf(stderr, "%*c> _gather_106[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(starred_expression | named_expression !'=') _loop0_107"));
void *elem;
asdl_seq * seq;
if (
- (elem = _tmp_149_rule(p)) // starred_expression | named_expression !'='
+ (elem = _tmp_147_rule(p)) // starred_expression | named_expression !'='
&&
- (seq = _loop0_109_rule(p)) // _loop0_109
+ (seq = _loop0_107_rule(p)) // _loop0_107
)
{
- D(fprintf(stderr, "%*c+ _gather_108[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(starred_expression | named_expression !'=') _loop0_109"));
+ D(fprintf(stderr, "%*c+ _gather_106[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(starred_expression | named_expression !'=') _loop0_107"));
_res = _PyPegen_seq_insert_in_front(p, elem, seq);
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _gather_108[%d-%d]: %s failed!\n", p->level, ' ',
- p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(starred_expression | named_expression !'=') _loop0_109"));
+ D(fprintf(stderr, "%*c%s _gather_106[%d-%d]: %s failed!\n", p->level, ' ',
+ p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(starred_expression | named_expression !'=') _loop0_107"));
}
_res = NULL;
done:
return _res;
}
-// _tmp_110: ',' kwargs
+// _tmp_108: ',' kwargs
static void *
-_tmp_110_rule(Parser *p)
+_tmp_108_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_110[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwargs"));
+ D(fprintf(stderr, "%*c> _tmp_108[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwargs"));
Token * _literal;
asdl_seq* k;
if (
(k = kwargs_rule(p)) // kwargs
)
{
- D(fprintf(stderr, "%*c+ _tmp_110[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' kwargs"));
+ D(fprintf(stderr, "%*c+ _tmp_108[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' kwargs"));
_res = k;
if (_res == NULL && PyErr_Occurred()) {
p->error_indicator = 1;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_110[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_108[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' kwargs"));
}
_res = NULL;
return _res;
}
-// _loop0_112: ',' kwarg_or_starred
+// _loop0_110: ',' kwarg_or_starred
static asdl_seq *
-_loop0_112_rule(Parser *p)
+_loop0_110_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _loop0_112[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_starred"));
+ D(fprintf(stderr, "%*c> _loop0_110[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_starred"));
Token * _literal;
KeywordOrStarred* elem;
while (
_mark = p->mark;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _loop0_112[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _loop0_110[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' kwarg_or_starred"));
}
asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena);
}
for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]);
PyMem_Free(_children);
- _PyPegen_insert_memo(p, _start_mark, _loop0_112_type, _seq);
+ _PyPegen_insert_memo(p, _start_mark, _loop0_110_type, _seq);
D(p->level--);
return _seq;
}
-// _gather_111: kwarg_or_starred _loop0_112
+// _gather_109: kwarg_or_starred _loop0_110
static asdl_seq *
-_gather_111_rule(Parser *p)
+_gather_109_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
}
asdl_seq * _res = NULL;
int _mark = p->mark;
- { // kwarg_or_starred _loop0_112
+ { // kwarg_or_starred _loop0_110
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _gather_111[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_112"));
+ D(fprintf(stderr, "%*c> _gather_109[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_110"));
KeywordOrStarred* elem;
asdl_seq * seq;
if (
(elem = kwarg_or_starred_rule(p)) // kwarg_or_starred
&&
- (seq = _loop0_112_rule(p)) // _loop0_112
+ (seq = _loop0_110_rule(p)) // _loop0_110
)
{
- D(fprintf(stderr, "%*c+ _gather_111[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_112"));
+ D(fprintf(stderr, "%*c+ _gather_109[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_110"));
_res = _PyPegen_seq_insert_in_front(p, elem, seq);
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _gather_111[%d-%d]: %s failed!\n", p->level, ' ',
- p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_starred _loop0_112"));
+ D(fprintf(stderr, "%*c%s _gather_109[%d-%d]: %s failed!\n", p->level, ' ',
+ p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_starred _loop0_110"));
}
_res = NULL;
done:
return _res;
}
-// _loop0_114: ',' kwarg_or_double_starred
+// _loop0_112: ',' kwarg_or_double_starred
static asdl_seq *
-_loop0_114_rule(Parser *p)
+_loop0_112_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _loop0_114[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_double_starred"));
+ D(fprintf(stderr, "%*c> _loop0_112[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_double_starred"));
Token * _literal;
KeywordOrStarred* elem;
while (
_mark = p->mark;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _loop0_114[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _loop0_112[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' kwarg_or_double_starred"));
}
asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena);
}
for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]);
PyMem_Free(_children);
- _PyPegen_insert_memo(p, _start_mark, _loop0_114_type, _seq);
+ _PyPegen_insert_memo(p, _start_mark, _loop0_112_type, _seq);
D(p->level--);
return _seq;
}
-// _gather_113: kwarg_or_double_starred _loop0_114
+// _gather_111: kwarg_or_double_starred _loop0_112
static asdl_seq *
-_gather_113_rule(Parser *p)
+_gather_111_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
}
asdl_seq * _res = NULL;
int _mark = p->mark;
- { // kwarg_or_double_starred _loop0_114
+ { // kwarg_or_double_starred _loop0_112
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _gather_113[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_114"));
+ D(fprintf(stderr, "%*c> _gather_111[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_112"));
KeywordOrStarred* elem;
asdl_seq * seq;
if (
(elem = kwarg_or_double_starred_rule(p)) // kwarg_or_double_starred
&&
- (seq = _loop0_114_rule(p)) // _loop0_114
+ (seq = _loop0_112_rule(p)) // _loop0_112
)
{
- D(fprintf(stderr, "%*c+ _gather_113[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_114"));
+ D(fprintf(stderr, "%*c+ _gather_111[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_112"));
_res = _PyPegen_seq_insert_in_front(p, elem, seq);
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _gather_113[%d-%d]: %s failed!\n", p->level, ' ',
- p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_double_starred _loop0_114"));
+ D(fprintf(stderr, "%*c%s _gather_111[%d-%d]: %s failed!\n", p->level, ' ',
+ p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_double_starred _loop0_112"));
}
_res = NULL;
done:
return _res;
}
-// _loop0_116: ',' kwarg_or_starred
+// _loop0_114: ',' kwarg_or_starred
static asdl_seq *
-_loop0_116_rule(Parser *p)
+_loop0_114_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _loop0_116[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_starred"));
+ D(fprintf(stderr, "%*c> _loop0_114[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_starred"));
Token * _literal;
KeywordOrStarred* elem;
while (
_mark = p->mark;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _loop0_116[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _loop0_114[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' kwarg_or_starred"));
}
asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena);
}
for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]);
PyMem_Free(_children);
- _PyPegen_insert_memo(p, _start_mark, _loop0_116_type, _seq);
+ _PyPegen_insert_memo(p, _start_mark, _loop0_114_type, _seq);
D(p->level--);
return _seq;
}
-// _gather_115: kwarg_or_starred _loop0_116
+// _gather_113: kwarg_or_starred _loop0_114
static asdl_seq *
-_gather_115_rule(Parser *p)
+_gather_113_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
}
asdl_seq * _res = NULL;
int _mark = p->mark;
- { // kwarg_or_starred _loop0_116
+ { // kwarg_or_starred _loop0_114
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _gather_115[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_116"));
+ D(fprintf(stderr, "%*c> _gather_113[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_114"));
KeywordOrStarred* elem;
asdl_seq * seq;
if (
(elem = kwarg_or_starred_rule(p)) // kwarg_or_starred
&&
- (seq = _loop0_116_rule(p)) // _loop0_116
+ (seq = _loop0_114_rule(p)) // _loop0_114
)
{
- D(fprintf(stderr, "%*c+ _gather_115[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_116"));
+ D(fprintf(stderr, "%*c+ _gather_113[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_114"));
_res = _PyPegen_seq_insert_in_front(p, elem, seq);
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _gather_115[%d-%d]: %s failed!\n", p->level, ' ',
- p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_starred _loop0_116"));
+ D(fprintf(stderr, "%*c%s _gather_113[%d-%d]: %s failed!\n", p->level, ' ',
+ p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_starred _loop0_114"));
}
_res = NULL;
done:
return _res;
}
-// _loop0_118: ',' kwarg_or_double_starred
+// _loop0_116: ',' kwarg_or_double_starred
static asdl_seq *
-_loop0_118_rule(Parser *p)
+_loop0_116_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _loop0_118[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_double_starred"));
+ D(fprintf(stderr, "%*c> _loop0_116[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_double_starred"));
Token * _literal;
KeywordOrStarred* elem;
while (
_mark = p->mark;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _loop0_118[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _loop0_116[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' kwarg_or_double_starred"));
}
asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena);
}
for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]);
PyMem_Free(_children);
- _PyPegen_insert_memo(p, _start_mark, _loop0_118_type, _seq);
+ _PyPegen_insert_memo(p, _start_mark, _loop0_116_type, _seq);
D(p->level--);
return _seq;
}
-// _gather_117: kwarg_or_double_starred _loop0_118
+// _gather_115: kwarg_or_double_starred _loop0_116
static asdl_seq *
-_gather_117_rule(Parser *p)
+_gather_115_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
}
asdl_seq * _res = NULL;
int _mark = p->mark;
- { // kwarg_or_double_starred _loop0_118
+ { // kwarg_or_double_starred _loop0_116
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _gather_117[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_118"));
+ D(fprintf(stderr, "%*c> _gather_115[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_116"));
KeywordOrStarred* elem;
asdl_seq * seq;
if (
(elem = kwarg_or_double_starred_rule(p)) // kwarg_or_double_starred
&&
- (seq = _loop0_118_rule(p)) // _loop0_118
+ (seq = _loop0_116_rule(p)) // _loop0_116
)
{
- D(fprintf(stderr, "%*c+ _gather_117[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_118"));
+ D(fprintf(stderr, "%*c+ _gather_115[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_116"));
_res = _PyPegen_seq_insert_in_front(p, elem, seq);
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _gather_117[%d-%d]: %s failed!\n", p->level, ' ',
- p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_double_starred _loop0_118"));
+ D(fprintf(stderr, "%*c%s _gather_115[%d-%d]: %s failed!\n", p->level, ' ',
+ p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_double_starred _loop0_116"));
}
_res = NULL;
done:
return _res;
}
-// _loop0_119: (',' star_target)
+// _loop0_117: (',' star_target)
static asdl_seq *
-_loop0_119_rule(Parser *p)
+_loop0_117_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _loop0_119[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_target)"));
- void *_tmp_150_var;
+ D(fprintf(stderr, "%*c> _loop0_117[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_target)"));
+ void *_tmp_148_var;
while (
- (_tmp_150_var = _tmp_150_rule(p)) // ',' star_target
+ (_tmp_148_var = _tmp_148_rule(p)) // ',' star_target
)
{
- _res = _tmp_150_var;
+ _res = _tmp_148_var;
if (_n == _children_capacity) {
_children_capacity *= 2;
void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
_mark = p->mark;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _loop0_119[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _loop0_117[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(',' star_target)"));
}
asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena);
}
for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]);
PyMem_Free(_children);
- _PyPegen_insert_memo(p, _start_mark, _loop0_119_type, _seq);
+ _PyPegen_insert_memo(p, _start_mark, _loop0_117_type, _seq);
D(p->level--);
return _seq;
}
-// _loop0_121: ',' star_target
+// _loop0_119: ',' star_target
static asdl_seq *
-_loop0_121_rule(Parser *p)
+_loop0_119_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _loop0_121[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target"));
+ D(fprintf(stderr, "%*c> _loop0_119[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target"));
Token * _literal;
expr_ty elem;
while (
_mark = p->mark;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _loop0_121[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _loop0_119[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_target"));
}
asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena);
}
for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]);
PyMem_Free(_children);
- _PyPegen_insert_memo(p, _start_mark, _loop0_121_type, _seq);
+ _PyPegen_insert_memo(p, _start_mark, _loop0_119_type, _seq);
D(p->level--);
return _seq;
}
-// _gather_120: star_target _loop0_121
+// _gather_118: star_target _loop0_119
static asdl_seq *
-_gather_120_rule(Parser *p)
+_gather_118_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
}
asdl_seq * _res = NULL;
int _mark = p->mark;
- { // star_target _loop0_121
+ { // star_target _loop0_119
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _gather_120[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_target _loop0_121"));
+ D(fprintf(stderr, "%*c> _gather_118[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_target _loop0_119"));
expr_ty elem;
asdl_seq * seq;
if (
(elem = star_target_rule(p)) // star_target
&&
- (seq = _loop0_121_rule(p)) // _loop0_121
+ (seq = _loop0_119_rule(p)) // _loop0_119
)
{
- D(fprintf(stderr, "%*c+ _gather_120[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_target _loop0_121"));
+ D(fprintf(stderr, "%*c+ _gather_118[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_target _loop0_119"));
_res = _PyPegen_seq_insert_in_front(p, elem, seq);
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _gather_120[%d-%d]: %s failed!\n", p->level, ' ',
- p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_target _loop0_121"));
+ D(fprintf(stderr, "%*c%s _gather_118[%d-%d]: %s failed!\n", p->level, ' ',
+ p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_target _loop0_119"));
}
_res = NULL;
done:
return _res;
}
-// _tmp_122: !'*' star_target
+// _tmp_120: !'*' star_target
static void *
-_tmp_122_rule(Parser *p)
+_tmp_120_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_122[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "!'*' star_target"));
+ D(fprintf(stderr, "%*c> _tmp_120[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "!'*' star_target"));
expr_ty star_target_var;
if (
_PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 16) // token='*'
(star_target_var = star_target_rule(p)) // star_target
)
{
- D(fprintf(stderr, "%*c+ _tmp_122[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "!'*' star_target"));
+ D(fprintf(stderr, "%*c+ _tmp_120[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "!'*' star_target"));
_res = star_target_var;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_122[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_120[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "!'*' star_target"));
}
_res = NULL;
return _res;
}
-// _loop0_124: ',' del_target
+// _loop0_122: ',' del_target
static asdl_seq *
-_loop0_124_rule(Parser *p)
+_loop0_122_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _loop0_124[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' del_target"));
+ D(fprintf(stderr, "%*c> _loop0_122[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' del_target"));
Token * _literal;
expr_ty elem;
while (
_mark = p->mark;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _loop0_124[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _loop0_122[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' del_target"));
}
asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena);
}
for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]);
PyMem_Free(_children);
- _PyPegen_insert_memo(p, _start_mark, _loop0_124_type, _seq);
+ _PyPegen_insert_memo(p, _start_mark, _loop0_122_type, _seq);
D(p->level--);
return _seq;
}
-// _gather_123: del_target _loop0_124
+// _gather_121: del_target _loop0_122
static asdl_seq *
-_gather_123_rule(Parser *p)
+_gather_121_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
}
asdl_seq * _res = NULL;
int _mark = p->mark;
- { // del_target _loop0_124
+ { // del_target _loop0_122
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _gather_123[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "del_target _loop0_124"));
+ D(fprintf(stderr, "%*c> _gather_121[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "del_target _loop0_122"));
expr_ty elem;
asdl_seq * seq;
if (
(elem = del_target_rule(p)) // del_target
&&
- (seq = _loop0_124_rule(p)) // _loop0_124
+ (seq = _loop0_122_rule(p)) // _loop0_122
)
{
- D(fprintf(stderr, "%*c+ _gather_123[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "del_target _loop0_124"));
+ D(fprintf(stderr, "%*c+ _gather_121[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "del_target _loop0_122"));
_res = _PyPegen_seq_insert_in_front(p, elem, seq);
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _gather_123[%d-%d]: %s failed!\n", p->level, ' ',
- p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "del_target _loop0_124"));
+ D(fprintf(stderr, "%*c%s _gather_121[%d-%d]: %s failed!\n", p->level, ' ',
+ p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "del_target _loop0_122"));
}
_res = NULL;
done:
return _res;
}
-// _loop0_126: ',' target
+// _loop0_124: ',' target
static asdl_seq *
-_loop0_126_rule(Parser *p)
+_loop0_124_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _loop0_126[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' target"));
+ D(fprintf(stderr, "%*c> _loop0_124[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' target"));
Token * _literal;
expr_ty elem;
while (
_mark = p->mark;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _loop0_126[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _loop0_124[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' target"));
}
asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena);
}
for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]);
PyMem_Free(_children);
- _PyPegen_insert_memo(p, _start_mark, _loop0_126_type, _seq);
+ _PyPegen_insert_memo(p, _start_mark, _loop0_124_type, _seq);
D(p->level--);
return _seq;
}
-// _gather_125: target _loop0_126
+// _gather_123: target _loop0_124
static asdl_seq *
-_gather_125_rule(Parser *p)
+_gather_123_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
}
asdl_seq * _res = NULL;
int _mark = p->mark;
- { // target _loop0_126
+ { // target _loop0_124
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _gather_125[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "target _loop0_126"));
+ D(fprintf(stderr, "%*c> _gather_123[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "target _loop0_124"));
expr_ty elem;
asdl_seq * seq;
if (
(elem = target_rule(p)) // target
&&
- (seq = _loop0_126_rule(p)) // _loop0_126
+ (seq = _loop0_124_rule(p)) // _loop0_124
)
{
- D(fprintf(stderr, "%*c+ _gather_125[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "target _loop0_126"));
+ D(fprintf(stderr, "%*c+ _gather_123[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "target _loop0_124"));
_res = _PyPegen_seq_insert_in_front(p, elem, seq);
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _gather_125[%d-%d]: %s failed!\n", p->level, ' ',
- p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "target _loop0_126"));
+ D(fprintf(stderr, "%*c%s _gather_123[%d-%d]: %s failed!\n", p->level, ' ',
+ p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "target _loop0_124"));
}
_res = NULL;
done:
return _res;
}
-// _tmp_127: args | expression for_if_clauses
+// _tmp_125: args | expression for_if_clauses
static void *
-_tmp_127_rule(Parser *p)
+_tmp_125_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_127[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args"));
+ D(fprintf(stderr, "%*c> _tmp_125[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args"));
expr_ty args_var;
if (
(args_var = args_rule(p)) // args
)
{
- D(fprintf(stderr, "%*c+ _tmp_127[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "args"));
+ D(fprintf(stderr, "%*c+ _tmp_125[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "args"));
_res = args_var;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_127[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_125[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "args"));
}
{ // expression for_if_clauses
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_127[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses"));
+ D(fprintf(stderr, "%*c> _tmp_125[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses"));
expr_ty expression_var;
asdl_seq* for_if_clauses_var;
if (
(for_if_clauses_var = for_if_clauses_rule(p)) // for_if_clauses
)
{
- D(fprintf(stderr, "%*c+ _tmp_127[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses"));
+ D(fprintf(stderr, "%*c+ _tmp_125[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses"));
_res = _PyPegen_dummy_name(p, expression_var, for_if_clauses_var);
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_127[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_125[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression for_if_clauses"));
}
_res = NULL;
return _res;
}
-// _loop0_128: star_named_expressions
+// _loop0_126: star_named_expressions
static asdl_seq *
-_loop0_128_rule(Parser *p)
+_loop0_126_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _loop0_128[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expressions"));
+ D(fprintf(stderr, "%*c> _loop0_126[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expressions"));
asdl_seq* star_named_expressions_var;
while (
(star_named_expressions_var = star_named_expressions_rule(p)) // star_named_expressions
_mark = p->mark;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _loop0_128[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _loop0_126[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_named_expressions"));
}
asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena);
}
for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]);
PyMem_Free(_children);
- _PyPegen_insert_memo(p, _start_mark, _loop0_128_type, _seq);
+ _PyPegen_insert_memo(p, _start_mark, _loop0_126_type, _seq);
D(p->level--);
return _seq;
}
-// _loop0_129: (star_targets '=')
+// _loop0_127: (star_targets '=')
static asdl_seq *
-_loop0_129_rule(Parser *p)
+_loop0_127_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _loop0_129[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')"));
- void *_tmp_151_var;
+ D(fprintf(stderr, "%*c> _loop0_127[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')"));
+ void *_tmp_149_var;
while (
- (_tmp_151_var = _tmp_151_rule(p)) // star_targets '='
+ (_tmp_149_var = _tmp_149_rule(p)) // star_targets '='
)
{
- _res = _tmp_151_var;
+ _res = _tmp_149_var;
if (_n == _children_capacity) {
_children_capacity *= 2;
void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
_mark = p->mark;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _loop0_129[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _loop0_127[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(star_targets '=')"));
}
asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena);
}
for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]);
PyMem_Free(_children);
- _PyPegen_insert_memo(p, _start_mark, _loop0_129_type, _seq);
+ _PyPegen_insert_memo(p, _start_mark, _loop0_127_type, _seq);
D(p->level--);
return _seq;
}
-// _loop0_130: (star_targets '=')
+// _loop0_128: (star_targets '=')
static asdl_seq *
-_loop0_130_rule(Parser *p)
+_loop0_128_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _loop0_130[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')"));
- void *_tmp_152_var;
+ D(fprintf(stderr, "%*c> _loop0_128[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')"));
+ void *_tmp_150_var;
while (
- (_tmp_152_var = _tmp_152_rule(p)) // star_targets '='
+ (_tmp_150_var = _tmp_150_rule(p)) // star_targets '='
)
{
- _res = _tmp_152_var;
+ _res = _tmp_150_var;
if (_n == _children_capacity) {
_children_capacity *= 2;
void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
_mark = p->mark;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _loop0_130[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _loop0_128[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(star_targets '=')"));
}
asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena);
}
for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]);
PyMem_Free(_children);
- _PyPegen_insert_memo(p, _start_mark, _loop0_130_type, _seq);
+ _PyPegen_insert_memo(p, _start_mark, _loop0_128_type, _seq);
D(p->level--);
return _seq;
}
-// _tmp_131: yield_expr | star_expressions
+// _tmp_129: yield_expr | star_expressions
static void *
-_tmp_131_rule(Parser *p)
+_tmp_129_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_131[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr"));
+ D(fprintf(stderr, "%*c> _tmp_129[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr"));
expr_ty yield_expr_var;
if (
(yield_expr_var = yield_expr_rule(p)) // yield_expr
)
{
- D(fprintf(stderr, "%*c+ _tmp_131[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr"));
+ D(fprintf(stderr, "%*c+ _tmp_129[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr"));
_res = yield_expr_var;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_131[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_129[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "yield_expr"));
}
{ // star_expressions
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_131[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions"));
+ D(fprintf(stderr, "%*c> _tmp_129[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions"));
expr_ty star_expressions_var;
if (
(star_expressions_var = star_expressions_rule(p)) // star_expressions
)
{
- D(fprintf(stderr, "%*c+ _tmp_131[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions"));
+ D(fprintf(stderr, "%*c+ _tmp_129[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions"));
_res = star_expressions_var;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_131[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_129[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_expressions"));
}
_res = NULL;
return _res;
}
-// _tmp_132: '[' | '(' | '{'
+// _tmp_130: '[' | '(' | '{'
static void *
-_tmp_132_rule(Parser *p)
+_tmp_130_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_132[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['"));
+ D(fprintf(stderr, "%*c> _tmp_130[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['"));
Token * _literal;
if (
(_literal = _PyPegen_expect_token(p, 9)) // token='['
)
{
- D(fprintf(stderr, "%*c+ _tmp_132[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'['"));
+ D(fprintf(stderr, "%*c+ _tmp_130[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'['"));
_res = _literal;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_132[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_130[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'['"));
}
{ // '('
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_132[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'('"));
+ D(fprintf(stderr, "%*c> _tmp_130[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'('"));
Token * _literal;
if (
(_literal = _PyPegen_expect_token(p, 7)) // token='('
)
{
- D(fprintf(stderr, "%*c+ _tmp_132[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'('"));
+ D(fprintf(stderr, "%*c+ _tmp_130[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'('"));
_res = _literal;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_132[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_130[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'('"));
}
{ // '{'
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_132[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'"));
+ D(fprintf(stderr, "%*c> _tmp_130[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'"));
Token * _literal;
if (
(_literal = _PyPegen_expect_token(p, 25)) // token='{'
)
{
- D(fprintf(stderr, "%*c+ _tmp_132[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{'"));
+ D(fprintf(stderr, "%*c+ _tmp_130[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{'"));
_res = _literal;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_132[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_130[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{'"));
}
_res = NULL;
return _res;
}
-// _loop0_133: param_no_default
+// _loop0_131: param_no_default
static asdl_seq *
-_loop0_133_rule(Parser *p)
+_loop0_131_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _loop0_133[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default"));
+ D(fprintf(stderr, "%*c> _loop0_131[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default"));
arg_ty param_no_default_var;
while (
(param_no_default_var = param_no_default_rule(p)) // param_no_default
_mark = p->mark;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _loop0_133[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _loop0_131[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_no_default"));
}
asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena);
}
for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]);
PyMem_Free(_children);
- _PyPegen_insert_memo(p, _start_mark, _loop0_133_type, _seq);
+ _PyPegen_insert_memo(p, _start_mark, _loop0_131_type, _seq);
D(p->level--);
return _seq;
}
-// _tmp_134: slash_with_default | param_with_default+
+// _tmp_132: slash_with_default | param_with_default+
static void *
-_tmp_134_rule(Parser *p)
+_tmp_132_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_134[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slash_with_default"));
+ D(fprintf(stderr, "%*c> _tmp_132[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slash_with_default"));
SlashWithDefault* slash_with_default_var;
if (
(slash_with_default_var = slash_with_default_rule(p)) // slash_with_default
)
{
- D(fprintf(stderr, "%*c+ _tmp_134[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slash_with_default"));
+ D(fprintf(stderr, "%*c+ _tmp_132[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slash_with_default"));
_res = slash_with_default_var;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_134[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_132[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "slash_with_default"));
}
{ // param_with_default+
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_134[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default+"));
- asdl_seq * _loop1_153_var;
+ D(fprintf(stderr, "%*c> _tmp_132[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default+"));
+ asdl_seq * _loop1_151_var;
if (
- (_loop1_153_var = _loop1_153_rule(p)) // param_with_default+
+ (_loop1_151_var = _loop1_151_rule(p)) // param_with_default+
)
{
- D(fprintf(stderr, "%*c+ _tmp_134[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_with_default+"));
- _res = _loop1_153_var;
+ D(fprintf(stderr, "%*c+ _tmp_132[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_with_default+"));
+ _res = _loop1_151_var;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_134[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_132[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_with_default+"));
}
_res = NULL;
return _res;
}
-// _loop0_135: lambda_param_no_default
+// _loop0_133: lambda_param_no_default
static asdl_seq *
-_loop0_135_rule(Parser *p)
+_loop0_133_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _loop0_135[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default"));
+ D(fprintf(stderr, "%*c> _loop0_133[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default"));
arg_ty lambda_param_no_default_var;
while (
(lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default
_mark = p->mark;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _loop0_135[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _loop0_133[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default"));
}
asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena);
}
for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]);
PyMem_Free(_children);
- _PyPegen_insert_memo(p, _start_mark, _loop0_135_type, _seq);
+ _PyPegen_insert_memo(p, _start_mark, _loop0_133_type, _seq);
D(p->level--);
return _seq;
}
-// _tmp_136: lambda_slash_with_default | lambda_param_with_default+
+// _tmp_134: lambda_slash_with_default | lambda_param_with_default+
static void *
-_tmp_136_rule(Parser *p)
+_tmp_134_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_136[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_slash_with_default"));
+ D(fprintf(stderr, "%*c> _tmp_134[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_slash_with_default"));
SlashWithDefault* lambda_slash_with_default_var;
if (
(lambda_slash_with_default_var = lambda_slash_with_default_rule(p)) // lambda_slash_with_default
)
{
- D(fprintf(stderr, "%*c+ _tmp_136[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_slash_with_default"));
+ D(fprintf(stderr, "%*c+ _tmp_134[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_slash_with_default"));
_res = lambda_slash_with_default_var;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_136[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_134[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_slash_with_default"));
}
{ // lambda_param_with_default+
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_136[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default+"));
- asdl_seq * _loop1_154_var;
+ D(fprintf(stderr, "%*c> _tmp_134[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default+"));
+ asdl_seq * _loop1_152_var;
if (
- (_loop1_154_var = _loop1_154_rule(p)) // lambda_param_with_default+
+ (_loop1_152_var = _loop1_152_rule(p)) // lambda_param_with_default+
)
{
- D(fprintf(stderr, "%*c+ _tmp_136[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default+"));
- _res = _loop1_154_var;
+ D(fprintf(stderr, "%*c+ _tmp_134[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default+"));
+ _res = _loop1_152_var;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_136[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_134[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_with_default+"));
}
_res = NULL;
return _res;
}
-// _tmp_137: ')' | ',' (')' | '**')
+// _tmp_135: ')' | ',' (')' | '**')
static void *
-_tmp_137_rule(Parser *p)
+_tmp_135_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_137[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'"));
+ D(fprintf(stderr, "%*c> _tmp_135[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'"));
Token * _literal;
if (
(_literal = _PyPegen_expect_token(p, 8)) // token=')'
)
{
- D(fprintf(stderr, "%*c+ _tmp_137[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'"));
+ D(fprintf(stderr, "%*c+ _tmp_135[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'"));
_res = _literal;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_137[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_135[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "')'"));
}
{ // ',' (')' | '**')
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_137[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')"));
+ D(fprintf(stderr, "%*c> _tmp_135[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')"));
Token * _literal;
- void *_tmp_155_var;
+ void *_tmp_153_var;
if (
(_literal = _PyPegen_expect_token(p, 12)) // token=','
&&
- (_tmp_155_var = _tmp_155_rule(p)) // ')' | '**'
+ (_tmp_153_var = _tmp_153_rule(p)) // ')' | '**'
)
{
- D(fprintf(stderr, "%*c+ _tmp_137[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')"));
- _res = _PyPegen_dummy_name(p, _literal, _tmp_155_var);
+ D(fprintf(stderr, "%*c+ _tmp_135[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')"));
+ _res = _PyPegen_dummy_name(p, _literal, _tmp_153_var);
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_137[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_135[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (')' | '**')"));
}
_res = NULL;
return _res;
}
-// _tmp_138: ':' | ',' (':' | '**')
+// _tmp_136: ':' | ',' (':' | '**')
static void *
-_tmp_138_rule(Parser *p)
+_tmp_136_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_138[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'"));
+ D(fprintf(stderr, "%*c> _tmp_136[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'"));
Token * _literal;
if (
(_literal = _PyPegen_expect_token(p, 11)) // token=':'
)
{
- D(fprintf(stderr, "%*c+ _tmp_138[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'"));
+ D(fprintf(stderr, "%*c+ _tmp_136[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'"));
_res = _literal;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_138[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_136[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'"));
}
{ // ',' (':' | '**')
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_138[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')"));
+ D(fprintf(stderr, "%*c> _tmp_136[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')"));
Token * _literal;
- void *_tmp_156_var;
+ void *_tmp_154_var;
if (
(_literal = _PyPegen_expect_token(p, 12)) // token=','
&&
- (_tmp_156_var = _tmp_156_rule(p)) // ':' | '**'
+ (_tmp_154_var = _tmp_154_rule(p)) // ':' | '**'
)
{
- D(fprintf(stderr, "%*c+ _tmp_138[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')"));
- _res = _PyPegen_dummy_name(p, _literal, _tmp_156_var);
+ D(fprintf(stderr, "%*c+ _tmp_136[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')"));
+ _res = _PyPegen_dummy_name(p, _literal, _tmp_154_var);
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_138[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_136[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (':' | '**')"));
}
_res = NULL;
return _res;
}
-// _tmp_139: star_targets '='
+// _tmp_137: star_targets '='
static void *
-_tmp_139_rule(Parser *p)
+_tmp_137_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_139[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='"));
+ D(fprintf(stderr, "%*c> _tmp_137[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='"));
Token * _literal;
expr_ty z;
if (
(_literal = _PyPegen_expect_token(p, 22)) // token='='
)
{
- D(fprintf(stderr, "%*c+ _tmp_139[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='"));
+ D(fprintf(stderr, "%*c+ _tmp_137[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='"));
_res = z;
if (_res == NULL && PyErr_Occurred()) {
p->error_indicator = 1;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_139[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_137[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_targets '='"));
}
_res = NULL;
return _res;
}
-// _tmp_140: '.' | '...'
+// _tmp_138: '.' | '...'
static void *
-_tmp_140_rule(Parser *p)
+_tmp_138_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_140[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'"));
+ D(fprintf(stderr, "%*c> _tmp_138[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'"));
Token * _literal;
if (
(_literal = _PyPegen_expect_token(p, 23)) // token='.'
)
{
- D(fprintf(stderr, "%*c+ _tmp_140[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'"));
+ D(fprintf(stderr, "%*c+ _tmp_138[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'"));
_res = _literal;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_140[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_138[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'.'"));
}
{ // '...'
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_140[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'"));
+ D(fprintf(stderr, "%*c> _tmp_138[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'"));
Token * _literal;
if (
(_literal = _PyPegen_expect_token(p, 52)) // token='...'
)
{
- D(fprintf(stderr, "%*c+ _tmp_140[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'"));
+ D(fprintf(stderr, "%*c+ _tmp_138[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'"));
_res = _literal;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_140[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_138[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'...'"));
}
_res = NULL;
return _res;
}
-// _tmp_141: '.' | '...'
+// _tmp_139: '.' | '...'
static void *
-_tmp_141_rule(Parser *p)
+_tmp_139_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_141[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'"));
+ D(fprintf(stderr, "%*c> _tmp_139[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'"));
Token * _literal;
if (
(_literal = _PyPegen_expect_token(p, 23)) // token='.'
)
{
- D(fprintf(stderr, "%*c+ _tmp_141[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'"));
+ D(fprintf(stderr, "%*c+ _tmp_139[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'"));
_res = _literal;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_141[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_139[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'.'"));
}
{ // '...'
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_141[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'"));
+ D(fprintf(stderr, "%*c> _tmp_139[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'"));
Token * _literal;
if (
(_literal = _PyPegen_expect_token(p, 52)) // token='...'
)
{
- D(fprintf(stderr, "%*c+ _tmp_141[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'"));
+ D(fprintf(stderr, "%*c+ _tmp_139[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'"));
_res = _literal;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_141[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_139[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'...'"));
}
_res = NULL;
return _res;
}
-// _tmp_142: '@' named_expression NEWLINE
+// _tmp_140: '@' named_expression NEWLINE
static void *
-_tmp_142_rule(Parser *p)
+_tmp_140_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_142[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE"));
+ D(fprintf(stderr, "%*c> _tmp_140[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE"));
Token * _literal;
expr_ty f;
Token * newline_var;
(newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE'
)
{
- D(fprintf(stderr, "%*c+ _tmp_142[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE"));
+ D(fprintf(stderr, "%*c+ _tmp_140[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE"));
_res = f;
if (_res == NULL && PyErr_Occurred()) {
p->error_indicator = 1;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_142[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_140[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'@' named_expression NEWLINE"));
}
_res = NULL;
return _res;
}
-// _tmp_143: ',' star_expression
+// _tmp_141: ',' star_expression
static void *
-_tmp_143_rule(Parser *p)
+_tmp_141_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_143[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_expression"));
+ D(fprintf(stderr, "%*c> _tmp_141[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_expression"));
Token * _literal;
expr_ty c;
if (
(c = star_expression_rule(p)) // star_expression
)
{
- D(fprintf(stderr, "%*c+ _tmp_143[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_expression"));
+ D(fprintf(stderr, "%*c+ _tmp_141[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_expression"));
_res = c;
if (_res == NULL && PyErr_Occurred()) {
p->error_indicator = 1;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_143[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_141[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_expression"));
}
_res = NULL;
return _res;
}
-// _tmp_144: ',' expression
+// _tmp_142: ',' expression
static void *
-_tmp_144_rule(Parser *p)
+_tmp_142_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_144[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression"));
+ D(fprintf(stderr, "%*c> _tmp_142[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression"));
Token * _literal;
expr_ty c;
if (
(c = expression_rule(p)) // expression
)
{
- D(fprintf(stderr, "%*c+ _tmp_144[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' expression"));
+ D(fprintf(stderr, "%*c+ _tmp_142[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' expression"));
_res = c;
if (_res == NULL && PyErr_Occurred()) {
p->error_indicator = 1;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_144[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_142[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' expression"));
}
_res = NULL;
return _res;
}
-// _tmp_145: 'or' conjunction
+// _tmp_143: 'or' conjunction
static void *
-_tmp_145_rule(Parser *p)
+_tmp_143_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_145[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'or' conjunction"));
+ D(fprintf(stderr, "%*c> _tmp_143[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'or' conjunction"));
Token * _keyword;
expr_ty c;
if (
(c = conjunction_rule(p)) // conjunction
)
{
- D(fprintf(stderr, "%*c+ _tmp_145[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'or' conjunction"));
+ D(fprintf(stderr, "%*c+ _tmp_143[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'or' conjunction"));
_res = c;
if (_res == NULL && PyErr_Occurred()) {
p->error_indicator = 1;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_145[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_143[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'or' conjunction"));
}
_res = NULL;
return _res;
}
-// _tmp_146: 'and' inversion
+// _tmp_144: 'and' inversion
static void *
-_tmp_146_rule(Parser *p)
+_tmp_144_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_146[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'and' inversion"));
+ D(fprintf(stderr, "%*c> _tmp_144[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'and' inversion"));
Token * _keyword;
expr_ty c;
if (
(c = inversion_rule(p)) // inversion
)
{
- D(fprintf(stderr, "%*c+ _tmp_146[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'and' inversion"));
+ D(fprintf(stderr, "%*c+ _tmp_144[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'and' inversion"));
_res = c;
if (_res == NULL && PyErr_Occurred()) {
p->error_indicator = 1;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_146[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_144[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'and' inversion"));
}
_res = NULL;
return _res;
}
-// _tmp_147: 'if' disjunction
+// _tmp_145: 'if' disjunction
static void *
-_tmp_147_rule(Parser *p)
+_tmp_145_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction"));
+ D(fprintf(stderr, "%*c> _tmp_145[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction"));
Token * _keyword;
expr_ty z;
if (
(z = disjunction_rule(p)) // disjunction
)
{
- D(fprintf(stderr, "%*c+ _tmp_147[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction"));
+ D(fprintf(stderr, "%*c+ _tmp_145[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction"));
_res = z;
if (_res == NULL && PyErr_Occurred()) {
p->error_indicator = 1;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_147[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_145[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'if' disjunction"));
}
_res = NULL;
return _res;
}
-// _tmp_148: 'if' disjunction
+// _tmp_146: 'if' disjunction
static void *
-_tmp_148_rule(Parser *p)
+_tmp_146_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_148[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction"));
+ D(fprintf(stderr, "%*c> _tmp_146[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction"));
Token * _keyword;
expr_ty z;
if (
(z = disjunction_rule(p)) // disjunction
)
{
- D(fprintf(stderr, "%*c+ _tmp_148[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction"));
+ D(fprintf(stderr, "%*c+ _tmp_146[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction"));
_res = z;
if (_res == NULL && PyErr_Occurred()) {
p->error_indicator = 1;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_148[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_146[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'if' disjunction"));
}
_res = NULL;
return _res;
}
-// _tmp_149: starred_expression | named_expression !'='
+// _tmp_147: starred_expression | named_expression !'='
static void *
-_tmp_149_rule(Parser *p)
+_tmp_147_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_149[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "starred_expression"));
+ D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "starred_expression"));
expr_ty starred_expression_var;
if (
(starred_expression_var = starred_expression_rule(p)) // starred_expression
)
{
- D(fprintf(stderr, "%*c+ _tmp_149[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "starred_expression"));
+ D(fprintf(stderr, "%*c+ _tmp_147[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "starred_expression"));
_res = starred_expression_var;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_149[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_147[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "starred_expression"));
}
{ // named_expression !'='
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_149[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "named_expression !'='"));
+ D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "named_expression !'='"));
expr_ty named_expression_var;
if (
(named_expression_var = named_expression_rule(p)) // named_expression
_PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 22) // token='='
)
{
- D(fprintf(stderr, "%*c+ _tmp_149[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "named_expression !'='"));
+ D(fprintf(stderr, "%*c+ _tmp_147[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "named_expression !'='"));
_res = named_expression_var;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_149[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_147[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "named_expression !'='"));
}
_res = NULL;
return _res;
}
-// _tmp_150: ',' star_target
+// _tmp_148: ',' star_target
static void *
-_tmp_150_rule(Parser *p)
+_tmp_148_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_150[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target"));
+ D(fprintf(stderr, "%*c> _tmp_148[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target"));
Token * _literal;
expr_ty c;
if (
(c = star_target_rule(p)) // star_target
)
{
- D(fprintf(stderr, "%*c+ _tmp_150[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_target"));
+ D(fprintf(stderr, "%*c+ _tmp_148[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_target"));
_res = c;
if (_res == NULL && PyErr_Occurred()) {
p->error_indicator = 1;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_150[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_148[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_target"));
}
_res = NULL;
return _res;
}
-// _tmp_151: star_targets '='
+// _tmp_149: star_targets '='
static void *
-_tmp_151_rule(Parser *p)
+_tmp_149_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_151[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='"));
+ D(fprintf(stderr, "%*c> _tmp_149[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='"));
Token * _literal;
expr_ty star_targets_var;
if (
(_literal = _PyPegen_expect_token(p, 22)) // token='='
)
{
- D(fprintf(stderr, "%*c+ _tmp_151[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='"));
+ D(fprintf(stderr, "%*c+ _tmp_149[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='"));
_res = _PyPegen_dummy_name(p, star_targets_var, _literal);
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_151[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_149[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_targets '='"));
}
_res = NULL;
return _res;
}
-// _tmp_152: star_targets '='
+// _tmp_150: star_targets '='
static void *
-_tmp_152_rule(Parser *p)
+_tmp_150_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_152[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='"));
+ D(fprintf(stderr, "%*c> _tmp_150[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='"));
Token * _literal;
expr_ty star_targets_var;
if (
(_literal = _PyPegen_expect_token(p, 22)) // token='='
)
{
- D(fprintf(stderr, "%*c+ _tmp_152[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='"));
+ D(fprintf(stderr, "%*c+ _tmp_150[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='"));
_res = _PyPegen_dummy_name(p, star_targets_var, _literal);
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_152[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_150[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_targets '='"));
}
_res = NULL;
return _res;
}
-// _loop1_153: param_with_default
+// _loop1_151: param_with_default
static asdl_seq *
-_loop1_153_rule(Parser *p)
+_loop1_151_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _loop1_153[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default"));
+ D(fprintf(stderr, "%*c> _loop1_151[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default"));
NameDefaultPair* param_with_default_var;
while (
(param_with_default_var = param_with_default_rule(p)) // param_with_default
_mark = p->mark;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _loop1_153[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _loop1_151[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_with_default"));
}
if (_n == 0 || p->error_indicator) {
}
for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]);
PyMem_Free(_children);
- _PyPegen_insert_memo(p, _start_mark, _loop1_153_type, _seq);
+ _PyPegen_insert_memo(p, _start_mark, _loop1_151_type, _seq);
D(p->level--);
return _seq;
}
-// _loop1_154: lambda_param_with_default
+// _loop1_152: lambda_param_with_default
static asdl_seq *
-_loop1_154_rule(Parser *p)
+_loop1_152_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _loop1_154[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default"));
+ D(fprintf(stderr, "%*c> _loop1_152[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default"));
NameDefaultPair* lambda_param_with_default_var;
while (
(lambda_param_with_default_var = lambda_param_with_default_rule(p)) // lambda_param_with_default
_mark = p->mark;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _loop1_154[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _loop1_152[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_with_default"));
}
if (_n == 0 || p->error_indicator) {
}
for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]);
PyMem_Free(_children);
- _PyPegen_insert_memo(p, _start_mark, _loop1_154_type, _seq);
+ _PyPegen_insert_memo(p, _start_mark, _loop1_152_type, _seq);
D(p->level--);
return _seq;
}
-// _tmp_155: ')' | '**'
+// _tmp_153: ')' | '**'
static void *
-_tmp_155_rule(Parser *p)
+_tmp_153_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_155[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'"));
+ D(fprintf(stderr, "%*c> _tmp_153[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'"));
Token * _literal;
if (
(_literal = _PyPegen_expect_token(p, 8)) // token=')'
)
{
- D(fprintf(stderr, "%*c+ _tmp_155[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'"));
+ D(fprintf(stderr, "%*c+ _tmp_153[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'"));
_res = _literal;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_155[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_153[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "')'"));
}
{ // '**'
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_155[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'"));
+ D(fprintf(stderr, "%*c> _tmp_153[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'"));
Token * _literal;
if (
(_literal = _PyPegen_expect_token(p, 35)) // token='**'
)
{
- D(fprintf(stderr, "%*c+ _tmp_155[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'"));
+ D(fprintf(stderr, "%*c+ _tmp_153[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'"));
_res = _literal;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_155[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_153[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'**'"));
}
_res = NULL;
return _res;
}
-// _tmp_156: ':' | '**'
+// _tmp_154: ':' | '**'
static void *
-_tmp_156_rule(Parser *p)
+_tmp_154_rule(Parser *p)
{
D(p->level++);
if (p->error_indicator) {
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_156[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'"));
+ D(fprintf(stderr, "%*c> _tmp_154[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'"));
Token * _literal;
if (
(_literal = _PyPegen_expect_token(p, 11)) // token=':'
)
{
- D(fprintf(stderr, "%*c+ _tmp_156[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'"));
+ D(fprintf(stderr, "%*c+ _tmp_154[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'"));
_res = _literal;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_156[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_154[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'"));
}
{ // '**'
D(p->level--);
return NULL;
}
- D(fprintf(stderr, "%*c> _tmp_156[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'"));
+ D(fprintf(stderr, "%*c> _tmp_154[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'"));
Token * _literal;
if (
(_literal = _PyPegen_expect_token(p, 35)) // token='**'
)
{
- D(fprintf(stderr, "%*c+ _tmp_156[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'"));
+ D(fprintf(stderr, "%*c+ _tmp_154[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'"));
_res = _literal;
goto done;
}
p->mark = _mark;
- D(fprintf(stderr, "%*c%s _tmp_156[%d-%d]: %s failed!\n", p->level, ' ',
+ D(fprintf(stderr, "%*c%s _tmp_154[%d-%d]: %s failed!\n", p->level, ' ',
p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'**'"));
}
_res = NULL;
return NULL;
}
p = buf = PyBytes_AsString(u);
+ if (p == NULL) {
+ return NULL;
+ }
end = s + len;
while (s < end) {
if (*s == '\\') {
/* Checks if the NOTEQUAL token is valid given the current parser flags
0 indicates success and nonzero indicates failure (an exception may be set) */
int
-_PyPegen_check_barry_as_flufl(Parser *p) {
- Token *t = p->tokens[p->fill - 1];
+_PyPegen_check_barry_as_flufl(Parser *p, Token* t) {
assert(t->bytes != NULL);
assert(t->type == NOTEQUAL);
/* Newlines are allowed if preceded by a line continuation character
or if they appear inside a string. */
- if (!cur || *(cur - 1) == '\\' || newline_in_string(p, cur)) {
+ if (!cur || (cur != p->tok->buf && *(cur - 1) == '\\')
+ || newline_in_string(p, cur)) {
return 0;
}
char c = *cur;
p->feature_version = feature_version;
p->known_err_token = NULL;
p->level = 0;
+ p->call_invalid_rules = 0;
return p;
}
+static void
+reset_parser_state(Parser *p)
+{
+ for (int i = 0; i < p->fill; i++) {
+ p->tokens[i]->memo = NULL;
+ }
+ p->mark = 0;
+ p->call_invalid_rules = 1;
+}
+
void *
_PyPegen_run_parser(Parser *p)
{
void *res = _PyPegen_parse(p);
if (res == NULL) {
+ reset_parser_state(p);
+ _PyPegen_parse(p);
if (PyErr_Occurred()) {
return NULL;
}
growable_comment_array type_ignore_comments;
Token *known_err_token;
int level;
+ int call_invalid_rules;
} Parser;
typedef struct {
int end_col_offset, PyArena *arena);
expr_ty _PyPegen_concatenate_strings(Parser *p, asdl_seq *);
asdl_seq *_PyPegen_join_sequences(Parser *, asdl_seq *, asdl_seq *);
-int _PyPegen_check_barry_as_flufl(Parser *);
+int _PyPegen_check_barry_as_flufl(Parser *, Token *);
mod_ty _PyPegen_make_module(Parser *, asdl_seq *);
// Error reporting helpers
}
} else {
modname_obj = Py_None;
+ Py_INCREF(modname_obj);
}
/* This assumes the line number is zero for now. */
- return PyTuple_Pack(5, action_str, Py_None,
- category, modname_obj, _PyLong_Zero);
+ PyObject *filter = PyTuple_Pack(5, action_str, Py_None,
+ category, modname_obj, _PyLong_Zero);
+ Py_DECREF(modname_obj);
+ return filter;
}
#endif
# include <sanitizer/msan_interface.h>
#endif
+#if defined(__APPLE__) && defined(__has_builtin)
+# if __has_builtin(__builtin_available)
+# define HAVE_GETENTRYPY_GETRANDOM_RUNTIME __builtin_available(macOS 10.12, iOS 10.10, tvOS 10.0, watchOS 3.0, *)
+# endif
+#endif
+#ifndef HAVE_GETENTRYPY_GETRANDOM_RUNTIME
+# define HAVE_GETENTRYPY_GETRANDOM_RUNTIME 1
+#endif
+
+
#ifdef Py_DEBUG
int _Py_HashSecret_Initialized = 0;
#else
error.
getentropy() is retried if it failed with EINTR: interrupted by a signal. */
+
+#if defined(__APPLE__) && defined(__has_attribute) && __has_attribute(availability)
+static int
+py_getentropy(char *buffer, Py_ssize_t size, int raise)
+ __attribute__((availability(macos,introduced=10.12)))
+ __attribute__((availability(ios,introduced=10.0)))
+ __attribute__((availability(tvos,introduced=10.0)))
+ __attribute__((availability(watchos,introduced=3.0)));
+#endif
+
static int
py_getentropy(char *buffer, Py_ssize_t size, int raise)
{
#else
#if defined(PY_GETRANDOM) || defined(PY_GETENTROPY)
+ if (HAVE_GETENTRYPY_GETRANDOM_RUNTIME) {
#ifdef PY_GETRANDOM
- res = py_getrandom(buffer, size, blocking, raise);
+ res = py_getrandom(buffer, size, blocking, raise);
#else
- res = py_getentropy(buffer, size, raise);
+ res = py_getentropy(buffer, size, raise);
#endif
- if (res < 0) {
- return -1;
- }
- if (res == 1) {
- return 0;
- }
- /* getrandom() or getentropy() function is not available: failed with
- ENOSYS or EPERM. Fall back on reading from /dev/urandom. */
+ if (res < 0) {
+ return -1;
+ }
+ if (res == 1) {
+ return 0;
+ }
+ /* getrandom() or getentropy() function is not available: failed with
+ ENOSYS or EPERM. Fall back on reading from /dev/urandom. */
+ } /* end of availability block */
#endif
return dev_urandom(buffer, size, raise);
static inline void
-SIGNAL_PENDING_SIGNALS(PyInterpreterState *interp)
+SIGNAL_PENDING_SIGNALS(PyInterpreterState *interp, int force)
{
struct _ceval_runtime_state *ceval = &interp->runtime->ceval;
struct _ceval_state *ceval2 = &interp->ceval;
_Py_atomic_store_relaxed(&ceval->signals_pending, 1);
- /* eval_breaker is not set to 1 if thread_can_handle_signals() is false */
- COMPUTE_EVAL_BREAKER(interp, ceval, ceval2);
+ if (force) {
+ _Py_atomic_store_relaxed(&ceval2->eval_breaker, 1);
+ }
+ else {
+ /* eval_breaker is not set to 1 if thread_can_handle_signals() is false */
+ COMPUTE_EVAL_BREAKER(interp, ceval, ceval2);
+ }
}
void
_PyEval_SignalReceived(PyInterpreterState *interp)
{
+#ifdef MS_WINDOWS
+ // bpo-42296: On Windows, _PyEval_SignalReceived() is called from a signal
+ // handler which can run in a thread different than the Python thread, in
+ // which case _Py_ThreadCanHandleSignals() is wrong. Ignore
+ // _Py_ThreadCanHandleSignals() and always set eval_breaker to 1.
+ //
+ // The next eval_frame_handle_pending() call will call
+ // _Py_ThreadCanHandleSignals() to recompute eval_breaker.
+ int force = 1;
+#else
+ int force = 0;
+#endif
/* bpo-30703: Function called when the C signal handler of Python gets a
signal. We cannot queue a callback using _PyEval_AddPendingCall() since
that function is not async-signal-safe. */
- SIGNAL_PENDING_SIGNALS(interp);
+ SIGNAL_PENDING_SIGNALS(interp, force);
}
/* Push one item onto the queue while holding the lock. */
UNSIGNAL_PENDING_SIGNALS(tstate->interp);
if (_PyErr_CheckSignalsTstate(tstate) < 0) {
/* On failure, re-schedule a call to handle_signals(). */
- SIGNAL_PENDING_SIGNALS(tstate->interp);
+ SIGNAL_PENDING_SIGNALS(tstate->interp, 0);
return -1;
}
return 0;
return -1;
}
+#ifdef MS_WINDOWS
+ // bpo-42296: On Windows, _PyEval_SignalReceived() can be called in a
+ // different thread than the Python thread, in which case
+ // _Py_ThreadCanHandleSignals() is wrong. Recompute eval_breaker in the
+ // current Python thread with the correct _Py_ThreadCanHandleSignals()
+ // value. It prevents to interrupt the eval loop at every instruction if
+ // the current Python thread cannot handle signals (if
+ // _Py_ThreadCanHandleSignals() is false).
+ COMPUTE_EVAL_BREAKER(tstate->interp, ceval, ceval2);
+#endif
+
return 0;
}
compiler IR.
*/
-enum fblocktype { WHILE_LOOP, FOR_LOOP, EXCEPT, FINALLY_TRY, FINALLY_END,
- WITH, ASYNC_WITH, HANDLER_CLEANUP, POP_VALUE };
+enum fblocktype { WHILE_LOOP, FOR_LOOP, TRY_EXCEPT, FINALLY_TRY, FINALLY_END,
+ WITH, ASYNC_WITH, HANDLER_CLEANUP, POP_VALUE, EXCEPTION_HANDLER };
struct fblockinfo {
enum fblocktype fb_type;
{
struct fblockinfo *f;
if (c->u->u_nfblocks >= CO_MAXBLOCKS) {
- PyErr_SetString(PyExc_SyntaxError,
- "too many statically nested blocks");
- return 0;
+ return compiler_error(c, "too many statically nested blocks");
}
f = &c->u->u_fblock[c->u->u_nfblocks++];
f->fb_type = t;
{
switch (info->fb_type) {
case WHILE_LOOP:
+ case EXCEPTION_HANDLER:
return 1;
case FOR_LOOP:
ADDOP(c, POP_TOP);
return 1;
- case EXCEPT:
+ case TRY_EXCEPT:
ADDOP(c, POP_BLOCK);
return 1;
return 0;
ADDOP_JREL(c, SETUP_FINALLY, except);
compiler_use_next_block(c, body);
- if (!compiler_push_fblock(c, EXCEPT, body, NULL, NULL))
+ if (!compiler_push_fblock(c, TRY_EXCEPT, body, NULL, NULL))
return 0;
VISIT_SEQ(c, stmt, s->v.Try.body);
ADDOP(c, POP_BLOCK);
- compiler_pop_fblock(c, EXCEPT, body);
+ compiler_pop_fblock(c, TRY_EXCEPT, body);
ADDOP_JREL(c, JUMP_FORWARD, orelse);
n = asdl_seq_LEN(s->v.Try.handlers);
compiler_use_next_block(c, except);
+ /* Runtime will push a block here, so we need to account for that */
+ if (!compiler_push_fblock(c, EXCEPTION_HANDLER, NULL, NULL, NULL))
+ return 0;
for (i = 0; i < n; i++) {
excepthandler_ty handler = (excepthandler_ty)asdl_seq_GET(
s->v.Try.handlers, i);
}
compiler_use_next_block(c, except);
}
+ compiler_pop_fblock(c, EXCEPTION_HANDLER, NULL);
ADDOP(c, RERAISE);
compiler_use_next_block(c, orelse);
VISIT_SEQ(c, stmt, s->v.Try.orelse);
ERRBUF_APPEND(message[i]);
ERRBUF_APPEND("\n");
}
- errbuf[strlen(errbuf)-1] = '\0'; /* trim off last newline */
- pathname_ob = PyUnicode_FromString(pathname);
- errbuf_ob = PyUnicode_FromString(errbuf);
- PyErr_SetImportError(errbuf_ob, NULL, pathname);
+ /* Subtract 1 from the length to trim off trailing newline */
+ errbuf_ob = PyUnicode_DecodeLocaleAndSize(errbuf, strlen(errbuf)-1, "surrogateescape");
+ if (errbuf_ob == NULL)
+ return;
+ pathname_ob = PyUnicode_DecodeFSDefault(pathname);
+ if (pathname_ob == NULL) {
+ Py_DECREF(errbuf_ob);
+ return;
+ }
+ PyErr_SetImportError(errbuf_ob, NULL, pathname_ob);
Py_DECREF(pathname_ob);
Py_DECREF(errbuf_ob);
return;
char buf[256];
PyOS_snprintf(buf, sizeof(buf), "Failed to load %.200s",
pathname);
- PyObject *buf_ob = PyUnicode_FromString(buf);
+ PyObject *buf_ob = PyUnicode_DecodeFSDefault(buf);
+ if (buf_ob == NULL)
+ return NULL;
PyObject *shortname_ob = PyUnicode_FromString(shortname);
- PyObject *pathname_ob = PyUnicode_FromString(pathname);
+ if (shortname_ob == NULL) {
+ Py_DECREF(buf_ob);
+ return NULL;
+ }
+ PyObject *pathname_ob = PyUnicode_DecodeFSDefault(pathname);
+ if (pathname_ob == NULL) {
+ Py_DECREF(buf_ob);
+ Py_DECREF(shortname_ob);
+ return NULL;
+ }
PyErr_SetImportError(buf_ob, shortname_ob, pathname_ob);
Py_DECREF(buf_ob);
Py_DECREF(shortname_ob);
const char *error = dlerror();
if (error == NULL)
error = "unknown dlopen() error";
- error_ob = PyUnicode_FromString(error);
+ error_ob = PyUnicode_DecodeLocale(error, "surrogateescape");
if (error_ob == NULL)
return NULL;
mod_name = PyUnicode_FromString(shortname);
Py_DECREF(error_ob);
return NULL;
}
- path = PyUnicode_FromString(pathname);
+ path = PyUnicode_DecodeFSDefault(pathname);
if (path == NULL) {
Py_DECREF(error_ob);
Py_DECREF(mod_name);
assert(decimal_point != NULL);
assert(thousands_sep != NULL);
+#ifndef MS_WINDOWS
int change_locale = 0;
if ((strlen(lc->decimal_point) > 1 || ((unsigned char)lc->decimal_point[0]) > 127)) {
change_locale = 1;
}
}
+#define GET_LOCALE_STRING(ATTR) PyUnicode_DecodeLocale(lc->ATTR, NULL)
+#else /* MS_WINDOWS */
+/* Use _W_* fields of Windows strcut lconv */
+#define GET_LOCALE_STRING(ATTR) PyUnicode_FromWideChar(lc->_W_ ## ATTR, -1)
+#endif /* MS_WINDOWS */
+
int res = -1;
- *decimal_point = PyUnicode_DecodeLocale(lc->decimal_point, NULL);
+ *decimal_point = GET_LOCALE_STRING(decimal_point);
if (*decimal_point == NULL) {
goto done;
}
- *thousands_sep = PyUnicode_DecodeLocale(lc->thousands_sep, NULL);
+ *thousands_sep = GET_LOCALE_STRING(thousands_sep);
if (*thousands_sep == NULL) {
goto done;
}
res = 0;
done:
+#ifndef MS_WINDOWS
if (loc != NULL) {
setlocale(LC_CTYPE, oldloc);
}
PyMem_Free(oldloc);
+#endif
return res;
+
+#undef GET_LOCALE_STRING
}
}
-/* Remove name from sys.modules, if it's there. */
+/* Remove name from sys.modules, if it's there.
+ * Can be called with an exception raised.
+ * If fail to remove name a new exception will be chained with the old
+ * exception, otherwise the old exception is preserved.
+ */
static void
remove_module(PyThreadState *tstate, PyObject *name)
{
_PyErr_Fetch(tstate, &type, &value, &traceback);
PyObject *modules = tstate->interp->modules;
- if (!PyMapping_HasKey(modules, name)) {
- goto out;
+ if (PyDict_CheckExact(modules)) {
+ PyObject *mod = _PyDict_Pop(modules, name, Py_None);
+ Py_XDECREF(mod);
}
- if (PyMapping_DelItem(modules, name) < 0) {
- _PyErr_SetString(tstate, PyExc_RuntimeError,
- "deleting key in sys.modules failed");
- _PyErr_ChainExceptions(type, value, traceback);
- return;
+ else if (PyMapping_DelItem(modules, name) < 0) {
+ if (_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) {
+ _PyErr_Clear(tstate);
+ }
}
-out:
- _PyErr_Restore(tstate, type, value, traceback);
+ _PyErr_ChainExceptions(type, value, traceback);
}
and comparing bytes/bytearray with str. (-bb: issue errors)\n\
-B : don't write .pyc files on import; also PYTHONDONTWRITEBYTECODE=x\n\
-c cmd : program passed in as string (terminates option list)\n\
--d : debug output from parser; also PYTHONDEBUG=x\n\
+-d : turn on parser debugging output (for experts only, only works on\n\
+ debug builds); also PYTHONDEBUG=x\n\
-E : ignore PYTHON* environment variables (such as PYTHONPATH)\n\
-h : print this help message and exit (also --help)\n\
";
#define UNCONDITIONAL_JUMP(op) (op==JUMP_ABSOLUTE || op==JUMP_FORWARD)
#define CONDITIONAL_JUMP(op) (op==POP_JUMP_IF_FALSE || op==POP_JUMP_IF_TRUE \
- || op==JUMP_IF_FALSE_OR_POP || op==JUMP_IF_TRUE_OR_POP || op==JUMP_IF_NOT_EXC_MATCH)
+ || op==JUMP_IF_FALSE_OR_POP || op==JUMP_IF_TRUE_OR_POP)
#define ABSOLUTE_JUMP(op) (op==JUMP_ABSOLUTE \
|| op==POP_JUMP_IF_FALSE || op==POP_JUMP_IF_TRUE \
|| op==JUMP_IF_FALSE_OR_POP || op==JUMP_IF_TRUE_OR_POP || op==JUMP_IF_NOT_EXC_MATCH)
static PyStatus init_import_site(void);
static PyStatus init_set_builtins_open(void);
static PyStatus init_sys_streams(PyThreadState *tstate);
-static PyStatus init_signals(PyThreadState *tstate);
static void call_py_exitfuncs(PyThreadState *tstate);
static void wait_for_thread_shutdown(PyThreadState *tstate);
static void call_ll_exitfuncs(_PyRuntimeState *runtime);
}
if (is_main_interp) {
- if (config->install_signal_handlers) {
- status = init_signals(tstate);
- if (_PyStatus_EXCEPTION(status)) {
- return status;
- }
+ if (_PySignal_Init(config->install_signal_handlers) < 0) {
+ return _PyStatus_ERR("can't initialize signals");
}
if (_PyTraceMalloc_Init(config->tracemalloc) < 0) {
/* Get current thread state and interpreter pointer */
PyThreadState *tstate = _PyRuntimeState_GetThreadState(runtime);
- PyInterpreterState *interp = tstate->interp;
// Wrap up existing "threading"-module-created, non-daemon threads.
wait_for_thread_shutdown(tstate);
/* Copy the core config, PyInterpreterState_Delete() free
the core config memory */
#ifdef Py_REF_DEBUG
- int show_ref_count = interp->config.show_ref_count;
+ int show_ref_count = tstate->interp->config.show_ref_count;
#endif
#ifdef Py_TRACE_REFS
- int dump_refs = interp->config.dump_refs;
+ int dump_refs = tstate->interp->config.dump_refs;
#endif
#ifdef WITH_PYMALLOC
- int malloc_stats = interp->config.malloc_stats;
+ int malloc_stats = tstate->interp->config.malloc_stats;
#endif
/* Remaining daemon threads will automatically exit
exit(sts);
}
-static PyStatus
-init_signals(PyThreadState *tstate)
-{
-#ifdef SIGPIPE
- PyOS_setsig(SIGPIPE, SIG_IGN);
-#endif
-#ifdef SIGXFZ
- PyOS_setsig(SIGXFZ, SIG_IGN);
-#endif
-#ifdef SIGXFSZ
- PyOS_setsig(SIGXFSZ, SIG_IGN);
-#endif
- PyOS_InitInterrupts(); /* May imply init_signals() */
- if (_PyErr_Occurred(tstate)) {
- return _PyStatus_ERR("can't import signal");
- }
- return _PyStatus_OK();
-}
-
/* Restore signals that the interpreter has called SIG_IGN on to SIG_DFL.
*
#if defined(__APPLE__)
#include <mach/mach_time.h> /* mach_absolute_time(), mach_timebase_info() */
+
+#if defined(__APPLE__) && defined(__has_builtin)
+# if __has_builtin(__builtin_available)
+# define HAVE_CLOCK_GETTIME_RUNTIME __builtin_available(macOS 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *)
+# endif
+#endif
#endif
#define _PyTime_check_mul_overflow(a, b) \
#else /* MS_WINDOWS */
int err;
-#ifdef HAVE_CLOCK_GETTIME
+#if defined(HAVE_CLOCK_GETTIME)
struct timespec ts;
-#else
+#endif
+
+#if !defined(HAVE_CLOCK_GETTIME) || defined(__APPLE__)
struct timeval tv;
#endif
assert(info == NULL || raise);
#ifdef HAVE_CLOCK_GETTIME
+
+#ifdef HAVE_CLOCK_GETTIME_RUNTIME
+ if (HAVE_CLOCK_GETTIME_RUNTIME) {
+#endif
+
err = clock_gettime(CLOCK_REALTIME, &ts);
if (err) {
if (raise) {
info->resolution = 1e-9;
}
}
-#else /* HAVE_CLOCK_GETTIME */
+
+#ifdef HAVE_CLOCK_GETTIME_RUNTIME
+ } else {
+#endif
+
+#endif
+
+#if !defined(HAVE_CLOCK_GETTIME) || defined(HAVE_CLOCK_GETTIME_RUNTIME)
/* test gettimeofday() */
err = gettimeofday(&tv, (struct timezone *)NULL);
info->monotonic = 0;
info->adjustable = 1;
}
+
+#if defined(HAVE_CLOCK_GETTIME_RUNTIME) && defined(HAVE_CLOCK_GETTIME)
+ } /* end of availibity block */
+#endif
+
#endif /* !HAVE_CLOCK_GETTIME */
#endif /* !MS_WINDOWS */
return 0;
-This is Python version 3.9.0
+This is Python version 3.9.1
============================
.. image:: https://travis-ci.org/python/cpython.svg?branch=3.9
def iter_files(root, suffix=None, relparent=None, *,
- get_files=os.walk,
+ get_files=None,
_glob=glob_tree,
_walk=walk_tree,
):
if "relparent" is provided then it is used to resolve each
filename as a relative path.
"""
+ if get_files is None:
+ get_files = os.walk
if not isinstance(root, str):
roots = root
for root in roots:
# The callable should not call builtins.print.
return_converters = {}
+
+def write_file(filename, new_contents):
+ try:
+ with open(filename, 'r', encoding="utf-8") as fp:
+ old_contents = fp.read()
+
+ if old_contents == new_contents:
+ # no change: avoid modifying the file modification time
+ return
+ except FileNotFoundError:
+ pass
+
+ # Atomic write using a temporary file and os.replace()
+ filename_new = f"{filename}.new"
+ with open(filename_new, "w", encoding="utf-8") as fp:
+ fp.write(new_contents)
+
+ try:
+ os.replace(filename_new, filename)
+ except:
+ os.unlink(filename_new)
+ raise
+
+
clinic = None
class Clinic:
"""
- def __init__(self, language, printer=None, *, force=False, verify=True, filename=None):
+ def __init__(self, language, printer=None, *, verify=True, filename=None):
# maps strings to Parser objects.
# (instantiated from the "parsers" global.)
self.parsers = {}
fail("Custom printers are broken right now")
self.printer = printer or BlockPrinter(language)
self.verify = verify
- self.force = force
self.filename = filename
self.modules = collections.OrderedDict()
self.classes = collections.OrderedDict()
block.input = 'preserve\n'
printer_2 = BlockPrinter(self.language)
printer_2.print_block(block)
- with open(destination.filename, "wt") as f:
- f.write(printer_2.f.getvalue())
+ write_file(destination.filename, printer_2.f.getvalue())
continue
text = printer.f.getvalue()
return module, cls
-def parse_file(filename, *, force=False, verify=True, output=None, encoding='utf-8'):
+def parse_file(filename, *, verify=True, output=None):
+ if not output:
+ output = filename
+
extension = os.path.splitext(filename)[1][1:]
if not extension:
fail("Can't extract file type for file " + repr(filename))
except KeyError:
fail("Can't identify file type for file " + repr(filename))
- with open(filename, 'r', encoding=encoding) as f:
+ with open(filename, 'r', encoding="utf-8") as f:
raw = f.read()
# exit quickly if there are no clinic markers in the file
if not find_start_re.search(raw):
return
- clinic = Clinic(language, force=force, verify=verify, filename=filename)
+ clinic = Clinic(language, verify=verify, filename=filename)
cooked = clinic.parse(raw)
- if (cooked == raw) and not force:
- return
-
- directory = os.path.dirname(filename) or '.'
- with tempfile.TemporaryDirectory(prefix="clinic", dir=directory) as tmpdir:
- bytes = cooked.encode(encoding)
- tmpfilename = os.path.join(tmpdir, os.path.basename(filename))
- with open(tmpfilename, "wb") as f:
- f.write(bytes)
- os.replace(tmpfilename, output or filename)
+ write_file(output, cooked)
def compute_checksum(input, length=None):
path = os.path.join(root, filename)
if ns.verbose:
print(path)
- parse_file(path, force=ns.force, verify=not ns.force)
+ parse_file(path, verify=not ns.force)
return
if not ns.filename:
for filename in ns.filename:
if ns.verbose:
print(filename)
- parse_file(filename, output=ns.output, force=ns.force, verify=not ns.force)
+ parse_file(filename, output=ns.output, verify=not ns.force)
if __name__ == "__main__":
foreach ($a in $files) {
if ($certsha1) {
- SignTool sign /sha1 $certsha1 /fd sha256 /t http://timestamp.verisign.com/scripts/timestamp.dll /d $description $a
+ SignTool sign /sha1 $certsha1 /fd sha256 /tr http://timestamp.digicert.com/ /td sha256 /d $description $a
} elseif ($certname) {
- SignTool sign /a /n $certname /fd sha256 /t http://timestamp.verisign.com/scripts/timestamp.dll /d $description $a
+ SignTool sign /a /n $certname /fd sha256 /tr http://timestamp.digicert.com/ /td sha256 /d $description $a
} elseif ($certfile) {
- SignTool sign /f $certfile /fd sha256 /t http://timestamp.verisign.com/scripts/timestamp.dll /d $description $a
+ SignTool sign /f $certfile /fd sha256 /tr http://timestamp.digicert.com/ /td sha256 /d $description $a
}
}
}
-<?xml version="1.0" encoding="UTF-8"?>
+<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
- <?define exts=_testcapi;_ctypes_test;_testbuffer;_testimportmultiple;_testmultiphase;_testconsole ?>
+ <?define exts=_testcapi;_ctypes_test;_testbuffer;_testimportmultiple;_testmultiphase;_testconsole;_testinternalcapi ?>
<Fragment>
<ComponentGroup Id="test_extensions">
<?foreach ext in $(var.exts)?>
</metadata>
<files>
<file src="**\*" exclude="python.props" target="tools" />
- <file src="python.props" target="build\native" />
+ <file src="python.props" target="build\native\python.props" />
</files>
</package>
</metadata>
<files>
<file src="**\*" exclude="python.props" target="tools" />
- <file src="python.props" target="build\native" />
+ <file src="python.props" target="build\native\python.props" />
+ <file src="python.props" target="build\native\pythonarm32.props" />
</files>
</package>
</metadata>
<files>
<file src="**\*" exclude="python.props" target="tools" />
- <file src="python.props" target="build\native" />
+ <file src="python.props" target="build\native\python.props" />
+ <file src="python.props" target="build\native\pythondaily.props" />
</files>
</package>
</metadata>
<files>
<file src="**\*" exclude="python.props" target="tools" />
- <file src="python.props" target="build\native" />
+ <file src="python.props" target="build\native\python.props" />
+ <file src="python.props" target="build\native\pythonx86.props" />
</files>
</package>
)
self.print("p->mark = _mark;")
self.print(f"void *_raw = {node.name}_raw(p);")
+ self.print("if (p->error_indicator)")
+ with self.indent():
+ self.print("return NULL;")
self.print("if (_raw == NULL || p->mark <= _resmark)")
with self.indent():
self.print("break;")
def visit_Alt(
self, node: Alt, is_loop: bool, is_gather: bool, rulename: Optional[str]
) -> None:
- self.print(f"{{ // {node}")
+ if len(node.items) == 1 and str(node.items[0]).startswith('invalid_'):
+ self.print(f"if (p->call_invalid_rules) {{ // {node}")
+ else:
+ self.print(f"{{ // {node}")
with self.indent():
self._check_for_errors()
node_str = str(node).replace('"', '\\"')
import os
import sys
import time
-import traceback
import tokenize
-<<<<<<< HEAD
import _peg_parser
-from glob import glob
-=======
from glob import glob, escape
->>>>>>> 9355868458... bpo-41043: Escape literal part of the path for glob(). (GH-20994)
from pathlib import PurePath
from typing import List, Optional, Any, Tuple
specify the kind of universal binary that should be
created. this option is only valid when
--enable-universalsdk is set; options are:
- ("32-bit", "64-bit", "3-way", "intel", "intel-32",
- "intel-64", or "all") see Mac/README.rst
+ ("universal2", "32-bit", "64-bit", "3-way", "intel",
+ "intel-32", "intel-64", or "all") see Mac/README.rst
--with-framework-name=FRAMEWORK
specify the name for the python framework on macOS
only valid when --enable-framework is set. see
-# The -arch flags for universal builds on OSX
+# The -arch flags for universal builds on macOS
UNIVERSAL_ARCH_FLAGS=
LIPO_32BIT_FLAGS="-extract ppc7400 -extract i386"
ARCH_RUN_32BIT="/usr/bin/arch -i386 -ppc"
;;
+ universal2)
+ UNIVERSAL_ARCH_FLAGS="-arch arm64 -arch x86_64"
+ LIPO_32BIT_FLAGS=""
+ ARCH_RUN_32BIT="true"
+ ;;
intel)
UNIVERSAL_ARCH_FLAGS="-arch i386 -arch x86_64"
LIPO_32BIT_FLAGS="-extract i386"
ARCH_RUN_32BIT="/usr/bin/arch -i386 -ppc"
;;
*)
- as_fn_error $? "proper usage is --with-universal-arch=32-bit|64-bit|all|intel|3-way" "$LINENO" 5
+ as_fn_error $? "proper usage is --with-universal-arch=universal2|32-bit|64-bit|all|intel|3-way" "$LINENO" 5
;;
esac
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MACOSX_DEPLOYMENT_TARGET" >&5
$as_echo "$MACOSX_DEPLOYMENT_TARGET" >&6; }
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if specified universal architectures work" >&5
+$as_echo_n "checking if specified universal architectures work... " >&6; }
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdio.h>
+int
+main ()
+{
+printf("%d", 42);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ as_fn_error $? "check config.log and use the '--with-universal-archs' option" "$LINENO" 5
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+
# end of Darwin* tests
;;
esac
MACOSX_DEFAULT_ARCH="ppc"
;;
*)
- as_fn_error $? "Unexpected output of 'arch' on OSX" "$LINENO" 5
+ as_fn_error $? "Unexpected output of 'arch' on macOS" "$LINENO" 5
;;
esac
else
;;
ppc)
MACOSX_DEFAULT_ARCH="ppc64"
+ ;;
+ arm64)
+ MACOSX_DEFAULT_ARCH="arm64"
;;
*)
- as_fn_error $? "Unexpected output of 'arch' on OSX" "$LINENO" 5
+ as_fn_error $? "Unexpected output of 'arch' on macOS" "$LINENO" 5
;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for _dyld_shared_cache_contains_path" >&5
+$as_echo_n "checking for _dyld_shared_cache_contains_path... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <mach-o/dyld.h>
+int
+main ()
+{
+void *x=_dyld_shared_cache_contains_path
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+$as_echo "#define HAVE_DYLD_SHARED_CACHE_CONTAINS_PATH 1" >>confdefs.h
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for memfd_create" >&5
$as_echo_n "checking for memfd_create... " >&6; }
AS_HELP_STRING([--with-universal-archs=ARCH],
[specify the kind of universal binary that should be created. this option is
only valid when --enable-universalsdk is set; options are:
- ("32-bit", "64-bit", "3-way", "intel", "intel-32", "intel-64", or "all")
+ ("universal2", "32-bit", "64-bit", "3-way", "intel", "intel-32", "intel-64", or "all")
see Mac/README.rst]),
[
UNIVERSAL_ARCHS="$withval"
AC_SUBST(CFLAGS_NODIST)
AC_SUBST(LDFLAGS_NODIST)
-# The -arch flags for universal builds on OSX
+# The -arch flags for universal builds on macOS
UNIVERSAL_ARCH_FLAGS=
AC_SUBST(UNIVERSAL_ARCH_FLAGS)
LIPO_32BIT_FLAGS="-extract ppc7400 -extract i386"
ARCH_RUN_32BIT="/usr/bin/arch -i386 -ppc"
;;
+ universal2)
+ UNIVERSAL_ARCH_FLAGS="-arch arm64 -arch x86_64"
+ LIPO_32BIT_FLAGS=""
+ ARCH_RUN_32BIT="true"
+ ;;
intel)
UNIVERSAL_ARCH_FLAGS="-arch i386 -arch x86_64"
LIPO_32BIT_FLAGS="-extract i386"
ARCH_RUN_32BIT="/usr/bin/arch -i386 -ppc"
;;
*)
- AC_MSG_ERROR([proper usage is --with-universal-arch=32-bit|64-bit|all|intel|3-way])
+ AC_MSG_ERROR([proper usage is --with-universal-arch=universal2|32-bit|64-bit|all|intel|3-way])
;;
esac
EXPORT_MACOSX_DEPLOYMENT_TARGET=''
AC_MSG_RESULT($MACOSX_DEPLOYMENT_TARGET)
+ AC_MSG_CHECKING(if specified universal architectures work)
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <stdio.h>]], [[printf("%d", 42);]])],
+ [AC_MSG_RESULT(yes)],
+ [AC_MSG_RESULT(no)
+ AC_MSG_ERROR(check config.log and use the '--with-universal-archs' option)
+ ])
+
# end of Darwin* tests
;;
esac
MACOSX_DEFAULT_ARCH="ppc"
;;
*)
- AC_MSG_ERROR([Unexpected output of 'arch' on OSX])
+ AC_MSG_ERROR([Unexpected output of 'arch' on macOS])
;;
esac
else
;;
ppc)
MACOSX_DEFAULT_ARCH="ppc64"
+ ;;
+ arm64)
+ MACOSX_DEFAULT_ARCH="arm64"
;;
*)
- AC_MSG_ERROR([Unexpected output of 'arch' on OSX])
+ AC_MSG_ERROR([Unexpected output of 'arch' on macOS])
;;
esac
AC_MSG_RESULT(yes)],
[AC_MSG_RESULT(no)
])
+AC_MSG_CHECKING(for _dyld_shared_cache_contains_path)
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <mach-o/dyld.h>]], [[void *x=_dyld_shared_cache_contains_path]])],
+ [AC_DEFINE(HAVE_DYLD_SHARED_CACHE_CONTAINS_PATH, 1, Define if you have the '_dyld_shared_cache_contains_path' function.)
+ AC_MSG_RESULT(yes)],
+ [AC_MSG_RESULT(no)
+])
AC_MSG_CHECKING(for memfd_create)
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
/* Define if you have the 'prlimit' functions. */
#undef HAVE_PRLIMIT
+/* Define if you have the '_dyld_shared_cache_contains_path' function. */
+#undef HAVE_DYLD_SHARED_CACHE_CONTAINS_PATH
+
/* Define to 1 if you have the <process.h> header file. */
#undef HAVE_PROCESS_H
import sys
import sysconfig
from glob import glob, escape
+import _osx_support
try:
MACOS_SDK_ROOT = m.group(1)
MACOS_SDK_SPECIFIED = MACOS_SDK_ROOT != '/'
else:
- MACOS_SDK_ROOT = '/'
+ MACOS_SDK_ROOT = _osx_support._default_sysroot(
+ sysconfig.get_config_var('CC'))
MACOS_SDK_SPECIFIED = False
- cc = sysconfig.get_config_var('CC')
- tmpfile = '/tmp/setup_sdk_root.%d' % os.getpid()
- try:
- os.unlink(tmpfile)
- except:
- pass
- ret = run_command('%s -E -v - </dev/null 2>%s 1>/dev/null' % (cc, tmpfile))
- in_incdirs = False
- try:
- if ret == 0:
- with open(tmpfile) as fp:
- for line in fp.readlines():
- if line.startswith("#include <...>"):
- in_incdirs = True
- elif line.startswith("End of search list"):
- in_incdirs = False
- elif in_incdirs:
- line = line.strip()
- if line == '/usr/include':
- MACOS_SDK_ROOT = '/'
- elif line.endswith(".sdk/usr/include"):
- MACOS_SDK_ROOT = line[:-12]
- finally:
- os.unlink(tmpfile)
return MACOS_SDK_ROOT
or path.startswith('/Library/') )
+def grep_headers_for(function, headers):
+ for header in headers:
+ with open(header, 'r', errors='surrogateescape') as f:
+ if function in f.read():
+ return True
+ return False
+
def find_file(filename, std_dirs, paths):
"""Searches for the directory where a given file is located,
and returns a possibly-empty list of additional directories, or None
os_release = int(os.uname()[2].split('.')[0])
dep_target = sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET')
if (dep_target and
- (tuple(int(n) for n in dep_target.split('.')[0:2])
+ (tuple(int(n) for n in str(dep_target).split('.')[0:2])
< (10, 5) ) ):
os_release = 8
if os_release < 9:
# you want to build and link with a framework build of Tcl and Tk
# that is not in /Library/Frameworks, say, in your private
# $HOME/Library/Frameworks directory or elsewhere. It turns
- # out to be difficult to make that work automtically here
+ # out to be difficult to make that work automatically here
# without bringing into play more tools and magic. That case
- # can be hamdled using a recipe with the right arguments
+ # can be handled using a recipe with the right arguments
# to detect_tkinter_explicitly().
#
# Note also that the fallback case here is to try to use the
# be forewarned that they are deprecated by Apple and typically
# out-of-date and buggy; their use should be avoided if at
# all possible by installing a newer version of Tcl and Tk in
- # /Library/Frameworks before bwfore building Python without
+ # /Library/Frameworks before building Python without
# an explicit SDK or by configuring build arguments explicitly.
from os.path import join, exists
else:
# Use case #1: no explicit SDK selected.
# Search the local system-wide /Library/Frameworks,
- # not the one in the default SDK, othewise fall back to
+ # not the one in the default SDK, otherwise fall back to
# /System/Library/Frameworks whose header files may be in
# the default SDK or, on older systems, actually installed.
framework_dirs = [
if not exists(join(F, fw + '.framework')):
break
else:
- # ok, F is now directory with both frameworks. Continure
+ # ok, F is now directory with both frameworks. Continue
# building
break
else:
library_dirs=added_lib_dirs))
return True
- def configure_ctypes_darwin(self, ext):
- # Darwin (OS X) uses preconfigured files, in
- # the Modules/_ctypes/libffi_osx directory.
- ffi_srcdir = os.path.abspath(os.path.join(self.srcdir, 'Modules',
- '_ctypes', 'libffi_osx'))
- sources = [os.path.join(ffi_srcdir, p)
- for p in ['ffi.c',
- 'x86/darwin64.S',
- 'x86/x86-darwin.S',
- 'x86/x86-ffi_darwin.c',
- 'x86/x86-ffi64.c',
- 'powerpc/ppc-darwin.S',
- 'powerpc/ppc-darwin_closure.S',
- 'powerpc/ppc-ffi_darwin.c',
- 'powerpc/ppc64-darwin_closure.S',
- ]]
-
- # Add .S (preprocessed assembly) to C compiler source extensions.
- self.compiler.src_extensions.append('.S')
-
- include_dirs = [os.path.join(ffi_srcdir, 'include'),
- os.path.join(ffi_srcdir, 'powerpc')]
- ext.include_dirs.extend(include_dirs)
- ext.sources.extend(sources)
- return True
-
def configure_ctypes(self, ext):
- if not self.use_system_libffi:
- if MACOS:
- return self.configure_ctypes_darwin(ext)
- print('INFO: Could not locate ffi libs and/or headers')
- return False
return True
def detect_ctypes(self):
# Thomas Heller's _ctypes module
- self.use_system_libffi = False
+
+ if (not sysconfig.get_config_var("LIBFFI_INCLUDEDIR") and MACOS):
+ self.use_system_libffi = True
+ else:
+ self.use_system_libffi = '--with-system-ffi' in sysconfig.get_config_var("CONFIG_ARGS")
+
include_dirs = []
extra_compile_args = ['-DPy_BUILD_CORE_MODULE']
extra_link_args = []
if MACOS:
sources.append('_ctypes/malloc_closure.c')
- sources.append('_ctypes/darwin/dlfcn_simple.c')
+ extra_compile_args.append('-DUSING_MALLOC_CLOSURE_DOT_C=1')
extra_compile_args.append('-DMACOSX')
include_dirs.append('_ctypes/darwin')
- # XXX Is this still needed?
- # extra_link_args.extend(['-read_only_relocs', 'warning'])
elif HOST_PLATFORM == 'sunos5':
# XXX This shouldn't be necessary; it appears that some
sources=['_ctypes/_ctypes_test.c'],
libraries=['m']))
+ ffi_inc = sysconfig.get_config_var("LIBFFI_INCLUDEDIR")
+ ffi_lib = None
+
ffi_inc_dirs = self.inc_dirs.copy()
if MACOS:
- if '--with-system-ffi' not in sysconfig.get_config_var("CONFIG_ARGS"):
- return
- # OS X 10.5 comes with libffi.dylib; the include files are
- # in /usr/include/ffi
- ffi_inc_dirs.append('/usr/include/ffi')
-
- ffi_inc = [sysconfig.get_config_var("LIBFFI_INCLUDEDIR")]
- if not ffi_inc or ffi_inc[0] == '':
- ffi_inc = find_file('ffi.h', [], ffi_inc_dirs)
- if ffi_inc is not None:
- ffi_h = ffi_inc[0] + '/ffi.h'
+ ffi_in_sdk = os.path.join(macosx_sdk_root(), "usr/include/ffi")
+
+ if not ffi_inc:
+ if os.path.exists(ffi_in_sdk):
+ ext.extra_compile_args.append("-DUSING_APPLE_OS_LIBFFI=1")
+ ffi_inc = ffi_in_sdk
+ ffi_lib = 'ffi'
+ else:
+ # OS X 10.5 comes with libffi.dylib; the include files are
+ # in /usr/include/ffi
+ ffi_inc_dirs.append('/usr/include/ffi')
+
+ if not ffi_inc:
+ found = find_file('ffi.h', [], ffi_inc_dirs)
+ if found:
+ ffi_inc = found[0]
+ if ffi_inc:
+ ffi_h = ffi_inc + '/ffi.h'
if not os.path.exists(ffi_h):
ffi_inc = None
print('Header file {} does not exist'.format(ffi_h))
- ffi_lib = None
- if ffi_inc is not None:
+ if ffi_lib is None and ffi_inc:
for lib_name in ('ffi', 'ffi_pic'):
if (self.compiler.find_library_file(self.lib_dirs, lib_name)):
ffi_lib = lib_name
break
if ffi_inc and ffi_lib:
- ext.include_dirs.extend(ffi_inc)
+ ffi_headers = glob(os.path.join(ffi_inc, '*.h'))
+ if grep_headers_for('ffi_prep_cif_var', ffi_headers):
+ ext.extra_compile_args.append("-DHAVE_FFI_PREP_CIF_VAR=1")
+ if grep_headers_for('ffi_prep_closure_loc', ffi_headers):
+ ext.extra_compile_args.append("-DHAVE_FFI_PREP_CLOSURE_LOC=1")
+ if grep_headers_for('ffi_closure_alloc', ffi_headers):
+ ext.extra_compile_args.append("-DHAVE_FFI_CLOSURE_ALLOC=1")
+
+ ext.include_dirs.append(ffi_inc)
ext.libraries.append(ffi_lib)
self.use_system_libffi = True