Skip to content

Commit

Permalink
Merge branch 'main' into isolate-io/1-heap-types
Browse files Browse the repository at this point in the history
  • Loading branch information
kumaraditya303 committed Feb 19, 2023
2 parents 39e0a89 + 0729359 commit 86a6dbc
Show file tree
Hide file tree
Showing 44 changed files with 444 additions and 182 deletions.
2 changes: 1 addition & 1 deletion Doc/c-api/function.rst
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ There are a few functions specific to Python functions.
before the modification to *func* takes place, so the prior state of *func*
can be inspected. The runtime is permitted to optimize away the creation of
function objects when possible. In such cases no event will be emitted.
Although this creates the possitibility of an observable difference of
Although this creates the possibility of an observable difference of
runtime behavior depending on optimization decisions, it does not change
the semantics of the Python code being executed.
Expand Down
4 changes: 2 additions & 2 deletions Doc/c-api/module.rst
Original file line number Diff line number Diff line change
Expand Up @@ -388,15 +388,15 @@ objects dynamically. Note that both ``PyModule_FromDefAndSpec`` and
.. c:function:: PyObject * PyModule_FromDefAndSpec(PyModuleDef *def, PyObject *spec)
Create a new module object, given the definition in *module* and the
Create a new module object, given the definition in *def* and the
ModuleSpec *spec*. This behaves like :c:func:`PyModule_FromDefAndSpec2`
with *module_api_version* set to :const:`PYTHON_API_VERSION`.
.. versionadded:: 3.5
.. c:function:: PyObject * PyModule_FromDefAndSpec2(PyModuleDef *def, PyObject *spec, int module_api_version)
Create a new module object, given the definition in *module* and the
Create a new module object, given the definition in *def* and the
ModuleSpec *spec*, assuming the API version *module_api_version*.
If that version does not match the version of the running interpreter,
a :exc:`RuntimeWarning` is emitted.
Expand Down
2 changes: 1 addition & 1 deletion Doc/library/argparse.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1867,7 +1867,7 @@ Sub-commands
...
>>> # create the top-level parser
>>> parser = argparse.ArgumentParser()
>>> subparsers = parser.add_subparsers()
>>> subparsers = parser.add_subparsers(required=True)
>>>
>>> # create the parser for the "foo" command
>>> parser_foo = subparsers.add_parser('foo')
Expand Down
12 changes: 10 additions & 2 deletions Doc/library/asyncio-stream.rst
Original file line number Diff line number Diff line change
Expand Up @@ -206,12 +206,20 @@ StreamReader

.. coroutinemethod:: read(n=-1)

Read up to *n* bytes. If *n* is not provided, or set to ``-1``,
read until EOF and return all read bytes.
Read up to *n* bytes from the stream.

If *n* is not provided or set to ``-1``,
read until EOF, then return all read :class:`bytes`.
If EOF was received and the internal buffer is empty,
return an empty ``bytes`` object.

If *n* is ``0``, return an empty ``bytes`` object immediately.

If *n* is positive, return at most *n* available ``bytes``
as soon as at least 1 byte is available in the internal buffer.
If EOF is received before any byte is read, return an empty
``bytes`` object.

.. coroutinemethod:: readline()

Read one line, where "line" is a sequence of bytes
Expand Down
2 changes: 1 addition & 1 deletion Doc/library/csv.rst
Original file line number Diff line number Diff line change
Expand Up @@ -458,7 +458,7 @@ Reader objects have the following public attributes:

DictReader objects have the following public attribute:

.. attribute:: csvreader.fieldnames
.. attribute:: DictReader.fieldnames

If not passed as a parameter when creating the object, this attribute is
initialized upon first access or when the first record is read from the
Expand Down
17 changes: 8 additions & 9 deletions Doc/library/enum.rst
Original file line number Diff line number Diff line change
Expand Up @@ -696,10 +696,9 @@ Data Types

.. attribute:: STRICT

Out-of-range values cause a :exc:`ValueError` to be raised. This is the
default for :class:`Flag`::
Out-of-range values cause a :exc:`ValueError` to be raised::

>>> from enum import Flag, STRICT
>>> from enum import Flag, STRICT, auto
>>> class StrictFlag(Flag, boundary=STRICT):
... RED = auto()
... GREEN = auto()
Expand All @@ -715,9 +714,9 @@ Data Types
.. attribute:: CONFORM

Out-of-range values have invalid values removed, leaving a valid *Flag*
value::
value. This is the default for :class:`Flag`::

>>> from enum import Flag, CONFORM
>>> from enum import Flag, CONFORM, auto
>>> class ConformFlag(Flag, boundary=CONFORM):
... RED = auto()
... GREEN = auto()
Expand All @@ -731,7 +730,7 @@ Data Types
Out-of-range values lose their *Flag* membership and revert to :class:`int`.
This is the default for :class:`IntFlag`::

>>> from enum import Flag, EJECT
>>> from enum import Flag, EJECT, auto
>>> class EjectFlag(Flag, boundary=EJECT):
... RED = auto()
... GREEN = auto()
Expand All @@ -742,10 +741,10 @@ Data Types

.. attribute:: KEEP

Out-of-range values are kept, and the *Flag* membership is kept. This is
used for some stdlib flags:
Out-of-range values are kept, and the *Flag* membership is kept. This is
used for some stdlib flags::

>>> from enum import Flag, KEEP
>>> from enum import Flag, KEEP, auto
>>> class KeepFlag(Flag, boundary=KEEP):
... RED = auto()
... GREEN = auto()
Expand Down
3 changes: 3 additions & 0 deletions Doc/library/functions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1635,6 +1635,9 @@ are always available. They are listed here in alphabetical order.
example: ``a[start:stop:step]`` or ``a[start:stop, i]``. See
:func:`itertools.islice` for an alternate version that returns an iterator.

.. versionchanged:: 3.12
Slice objects are now :term:`hashable` (provided :attr:`~slice.start`,
:attr:`~slice.stop`, and :attr:`~slice.step` are hashable).

.. function:: sorted(iterable, /, *, key=None, reverse=False)

Expand Down
21 changes: 15 additions & 6 deletions Doc/library/plistlib.rst
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,9 @@ Examples

Generating a plist::

import datetime
import plistlib

pl = dict(
aString = "Doodah",
aList = ["A", "B", 12, 32.1, [1, 2, 3]],
Expand All @@ -172,13 +175,19 @@ Generating a plist::
),
someData = b"<binary gunk>",
someMoreData = b"<lots of binary gunk>" * 10,
aDate = datetime.datetime.fromtimestamp(time.mktime(time.gmtime())),
aDate = datetime.datetime.now()
)
with open(fileName, 'wb') as fp:
dump(pl, fp)
print(plistlib.dumps(pl).decode())

Parsing a plist::

with open(fileName, 'rb') as fp:
pl = load(fp)
print(pl["aKey"])
import plistlib

plist = b"""<plist version="1.0">
<dict>
<key>foo</key>
<string>bar</string>
</dict>
</plist>"""
pl = plistlib.loads(plist)
print(pl["foo"])
13 changes: 12 additions & 1 deletion Doc/library/urllib.error.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,19 @@ The following exceptions are raised by :mod:`urllib.error` as appropriate:
of :exc:`IOError`.


.. exception:: HTTPError
.. exception:: HTTPError(url, code, msg, hdrs, fp)

Though being an exception (a subclass of :exc:`URLError`), an
:exc:`HTTPError` can also function as a non-exceptional file-like return
value (the same thing that :func:`~urllib.request.urlopen` returns). This
is useful when handling exotic HTTP errors, such as requests for
authentication.

.. attribute:: url

Contains the request URL.
An alias for *filename* attribute.

.. attribute:: code

An HTTP status code as defined in :rfc:`2616`. This numeric value corresponds
Expand All @@ -48,14 +53,20 @@ The following exceptions are raised by :mod:`urllib.error` as appropriate:
.. attribute:: reason

This is usually a string explaining the reason for this error.
An alias for *msg* attribute.

.. attribute:: headers

The HTTP response headers for the HTTP request that caused the
:exc:`HTTPError`.
An alias for *hdrs* attribute.

.. versionadded:: 3.4

.. attribute:: fp

A file-like object where the HTTP error body can be read from.

.. exception:: ContentTooShortError(msg, content)

This exception is raised when the :func:`~urllib.request.urlretrieve`
Expand Down
17 changes: 9 additions & 8 deletions Lib/asyncio/streams.py
Original file line number Diff line number Diff line change
Expand Up @@ -649,16 +649,17 @@ async def readuntil(self, separator=b'\n'):
async def read(self, n=-1):
"""Read up to `n` bytes from the stream.
If n is not provided, or set to -1, read until EOF and return all read
bytes. If the EOF was received and the internal buffer is empty, return
an empty bytes object.
If `n` is not provided or set to -1,
read until EOF, then return all read bytes.
If EOF was received and the internal buffer is empty,
return an empty bytes object.
If n is zero, return empty bytes object immediately.
If `n` is 0, return an empty bytes object immediately.
If n is positive, this function try to read `n` bytes, and may return
less or equal bytes than requested, but at least one byte. If EOF was
received before any byte is read, this function returns empty byte
object.
If `n` is positive, return at most `n` available bytes
as soon as at least 1 byte is available in the internal buffer.
If EOF is received before any byte is read, return an empty
bytes object.
Returned value is not limited with limit, configured at stream
creation.
Expand Down
4 changes: 1 addition & 3 deletions Lib/importlib/resources/_adapters.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,7 @@ def _io_wrapper(file, mode='r', *args, **kwargs):
return TextIOWrapper(file, *args, **kwargs)
elif mode == 'rb':
return file
raise ValueError(
f"Invalid mode value '{mode}', only 'r' and 'rb' are supported"
)
raise ValueError(f"Invalid mode value '{mode}', only 'r' and 'rb' are supported")


class CompatibilityFiles:
Expand Down
69 changes: 36 additions & 33 deletions Lib/importlib/resources/_itertools.py
Original file line number Diff line number Diff line change
@@ -1,35 +1,38 @@
from itertools import filterfalse
# from more_itertools 9.0
def only(iterable, default=None, too_long=None):
"""If *iterable* has only one item, return it.
If it has zero items, return *default*.
If it has more than one item, raise the exception given by *too_long*,
which is ``ValueError`` by default.
>>> only([], default='missing')
'missing'
>>> only([1])
1
>>> only([1, 2]) # doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
...
ValueError: Expected exactly one item in iterable, but got 1, 2,
and perhaps more.'
>>> only([1, 2], too_long=TypeError) # doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
...
TypeError
Note that :func:`only` attempts to advance *iterable* twice to ensure there
is only one item. See :func:`spy` or :func:`peekable` to check
iterable contents less destructively.
"""
it = iter(iterable)
first_value = next(it, default)

from typing import (
Callable,
Iterable,
Iterator,
Optional,
Set,
TypeVar,
Union,
)

# Type and type variable definitions
_T = TypeVar('_T')
_U = TypeVar('_U')


def unique_everseen(
iterable: Iterable[_T], key: Optional[Callable[[_T], _U]] = None
) -> Iterator[_T]:
"List unique elements, preserving order. Remember all elements ever seen."
# unique_everseen('AAAABBBCCDAABBB') --> A B C D
# unique_everseen('ABBCcAD', str.lower) --> A B C D
seen: Set[Union[_T, _U]] = set()
seen_add = seen.add
if key is None:
for element in filterfalse(seen.__contains__, iterable):
seen_add(element)
yield element
try:
second_value = next(it)
except StopIteration:
pass
else:
for element in iterable:
k = key(element)
if k not in seen:
seen_add(k)
yield element
msg = (
'Expected exactly one item in iterable, but got {!r}, {!r}, '
'and perhaps more.'.format(first_value, second_value)
)
raise too_long or ValueError(msg)

return first_value
36 changes: 30 additions & 6 deletions Lib/importlib/resources/readers.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import collections
import operator
import itertools
import pathlib
import operator
import zipfile

from . import abc

from ._itertools import unique_everseen
from ._itertools import only


def remove_duplicates(items):
Expand Down Expand Up @@ -41,8 +42,10 @@ def open_resource(self, resource):
raise FileNotFoundError(exc.args[0])

def is_resource(self, path):
# workaround for `zipfile.Path.is_file` returning true
# for non-existent paths.
"""
Workaround for `zipfile.Path.is_file` returning true
for non-existent paths.
"""
target = self.files().joinpath(path)
return target.is_file() and target.exists()

Expand All @@ -67,8 +70,10 @@ def __init__(self, *paths):
raise NotADirectoryError('MultiplexedPath only supports directories')

def iterdir(self):
files = (file for path in self._paths for file in path.iterdir())
return unique_everseen(files, key=operator.attrgetter('name'))
children = (child for path in self._paths for child in path.iterdir())
by_name = operator.attrgetter('name')
groups = itertools.groupby(sorted(children, key=by_name), key=by_name)
return map(self._follow, (locs for name, locs in groups))

def read_bytes(self):
raise FileNotFoundError(f'{self} is not a file')
Expand All @@ -90,6 +95,25 @@ def joinpath(self, *descendants):
# Just return something that will not exist.
return self._paths[0].joinpath(*descendants)

@classmethod
def _follow(cls, children):
"""
Construct a MultiplexedPath if needed.
If children contains a sole element, return it.
Otherwise, return a MultiplexedPath of the items.
Unless one of the items is not a Directory, then return the first.
"""
subdirs, one_dir, one_file = itertools.tee(children, 3)

try:
return only(one_dir)
except ValueError:
try:
return cls(*subdirs)
except NotADirectoryError:
return next(one_file)

def open(self, *args, **kwargs):
raise FileNotFoundError(f'{self} is not a file')

Expand Down

0 comments on commit 86a6dbc

Please sign in to comment.