Skip to content

Commit

Permalink
Merge branch 'main' into fix-exeptions-append-after-cancel-async-stagger
Browse files Browse the repository at this point in the history
  • Loading branch information
graingert authored Jan 4, 2025
2 parents 4a4c027 + fd94c6a commit dd55eae
Show file tree
Hide file tree
Showing 5 changed files with 276 additions and 240 deletions.
118 changes: 70 additions & 48 deletions Doc/library/json.rst
Original file line number Diff line number Diff line change
Expand Up @@ -151,69 +151,91 @@ Basic Usage
sort_keys=False, **kw)
Serialize *obj* as a JSON formatted stream to *fp* (a ``.write()``-supporting
:term:`file-like object`) using this :ref:`conversion table
:term:`file-like object`) using this :ref:`Python-to-JSON conversion table
<py-to-json-table>`.

If *skipkeys* is true (default: ``False``), then dict keys that are not
of a basic type (:class:`str`, :class:`int`, :class:`float`, :class:`bool`,
``None``) will be skipped instead of raising a :exc:`TypeError`.

The :mod:`json` module always produces :class:`str` objects, not
:class:`bytes` objects. Therefore, ``fp.write()`` must support :class:`str`
input.

If *ensure_ascii* is true (the default), the output is guaranteed to
have all incoming non-ASCII characters escaped. If *ensure_ascii* is
false, these characters will be output as-is.
To use a custom :class:`JSONEncoder` subclass (for example, one that overrides the
:meth:`~JSONEncoder.default` method to serialize additional types), specify it with the
*cls* keyword argument; otherwise :class:`JSONEncoder` is used.

If *check_circular* is false (default: ``True``), then the circular
reference check for container types will be skipped and a circular reference
will result in a :exc:`RecursionError` (or worse).
.. note::

If *allow_nan* is false (default: ``True``), then it will be a
:exc:`ValueError` to serialize out of range :class:`float` values (``nan``,
``inf``, ``-inf``) in strict compliance of the JSON specification.
If *allow_nan* is true, their JavaScript equivalents (``NaN``,
``Infinity``, ``-Infinity``) will be used.
Unlike :mod:`pickle` and :mod:`marshal`, JSON is not a framed protocol,
so trying to serialize multiple objects with repeated calls to
:func:`dump` using the same *fp* will result in an invalid JSON file.

If *indent* is a non-negative integer or string, then JSON array elements and
object members will be pretty-printed with that indent level. An indent level
of 0, negative, or ``""`` will only insert newlines. ``None`` (the default)
selects the most compact representation. Using a positive integer indent
indents that many spaces per level. If *indent* is a string (such as ``"\t"``),
that string is used to indent each level.
:param object obj:
The Python object to be serialized.

:param fp:
The file-like object *obj* will be serialized to.
The :mod:`!json` module always produces :class:`str` objects,
not :class:`bytes` objects,
therefore ``fp.write()`` must support :class:`str` input.
:type fp: :term:`file-like object`

:param bool skipkeys:
If ``True``, keys that are not of a basic type
(:class:`str`, :class:`int`, :class:`float`, :class:`bool`, ``None``)
will be skipped instead of raising a :exc:`TypeError`.
Default ``False``.

:param bool ensure_ascii:
If ``True`` (the default), the output is guaranteed to
have all incoming non-ASCII characters escaped.
If ``False``, these characters will be outputted as-is.

:param bool check_circular:
If ``False``, the circular reference check for container types is skipped
and a circular reference will result in a :exc:`RecursionError` (or worse).
Default ``True``.

:param bool allow_nan:
If ``False``, serialization of out-of-range :class:`float` values
(``nan``, ``inf``, ``-inf``) will result in a :exc:`ValueError`,
in strict compliance with the JSON specification.
If ``True`` (the default), their JavaScript equivalents
(``NaN``, ``Infinity``, ``-Infinity``) are used.

:param indent:
If a positive integer or string, JSON array elements and
object members will be pretty-printed with that indent level.
A positive integer indents that many spaces per level;
a string (such as ``"\t"``) is used to indent each level.
If zero, negative, or ``""`` (the empty string),
only newlines are inserted.
If ``None`` (the default), the most compact representation is used.
:type indent: int | str | None

:param separators:
A two-tuple: ``(item_separator, key_separator)``.
If ``None`` (the default), *separators* defaults to
``(', ', ': ')`` if *indent* is ``None``,
and ``(',', ': ')`` otherwise.
For the most compact JSON,
specify ``(',', ':')`` to eliminate whitespace.
:type separators: tuple | None

:param default:
A function that is called for objects that can't otherwise be serialized.
It should return a JSON encodable version of the object
or raise a :exc:`TypeError`.
If ``None`` (the default), :exc:`!TypeError` is raised.
:type default: :term:`callable` | None

:param sort_keys:
If ``True``, dictionaries will be outputted sorted by key.
Default ``False``.

.. versionchanged:: 3.2
Allow strings for *indent* in addition to integers.

If specified, *separators* should be an ``(item_separator, key_separator)``
tuple. The default is ``(', ', ': ')`` if *indent* is ``None`` and
``(',', ': ')`` otherwise. To get the most compact JSON representation,
you should specify ``(',', ':')`` to eliminate whitespace.

.. versionchanged:: 3.4
Use ``(',', ': ')`` as default if *indent* is not ``None``.

If specified, *default* should be a function that gets called for objects that
can't otherwise be serialized. It should return a JSON encodable version of
the object or raise a :exc:`TypeError`. If not specified, :exc:`TypeError`
is raised.

If *sort_keys* is true (default: ``False``), then the output of
dictionaries will be sorted by key.

To use a custom :class:`JSONEncoder` subclass (e.g. one that overrides the
:meth:`~JSONEncoder.default` method to serialize additional types), specify it with the
*cls* kwarg; otherwise :class:`JSONEncoder` is used.

.. versionchanged:: 3.6
All optional parameters are now :ref:`keyword-only <keyword-only_parameter>`.

.. note::

Unlike :mod:`pickle` and :mod:`marshal`, JSON is not a framed protocol,
so trying to serialize multiple objects with repeated calls to
:func:`dump` using the same *fp* will result in an invalid JSON file.

.. function:: dumps(obj, *, skipkeys=False, ensure_ascii=True, \
check_circular=True, allow_nan=True, cls=None, \
Expand Down
27 changes: 0 additions & 27 deletions Lib/pathlib/_abc.py
Original file line number Diff line number Diff line change
Expand Up @@ -573,30 +573,3 @@ def copy_into(self, target_dir, *, follow_symlinks=True,
return self.copy(target, follow_symlinks=follow_symlinks,
dirs_exist_ok=dirs_exist_ok,
preserve_metadata=preserve_metadata)

def _delete(self):
"""
Delete this file or directory (including all sub-directories).
"""
raise NotImplementedError

def move(self, target):
"""
Recursively move this file or directory tree to the given destination.
"""
target = self.copy(target, follow_symlinks=False, preserve_metadata=True)
self._delete()
return target

def move_into(self, target_dir):
"""
Move this file or directory tree into the given existing directory.
"""
name = self.name
if not name:
raise ValueError(f"{self!r} has an empty name")
elif isinstance(target_dir, PathBase):
target = target_dir / name
else:
target = self.with_segments(target_dir, name)
return self.move(target)
38 changes: 30 additions & 8 deletions Lib/pathlib/_local.py
Original file line number Diff line number Diff line change
Expand Up @@ -1128,16 +1128,38 @@ def move(self, target):
"""
Recursively move this file or directory tree to the given destination.
"""
if not isinstance(target, PathBase):
target = self.with_segments(target)
target.copy._ensure_different_file(self)
# Use os.replace() if the target is os.PathLike and on the same FS.
try:
return self.replace(target)
except OSError as err:
if err.errno != EXDEV:
raise
target_str = os.fspath(target)
except TypeError:
pass
else:
if not isinstance(target, PathBase):
target = self.with_segments(target_str)
target.copy._ensure_different_file(self)
try:
os.replace(self, target_str)
return target
except OSError as err:
if err.errno != EXDEV:
raise
# Fall back to copy+delete.
return PathBase.move(self, target)
target = self.copy(target, follow_symlinks=False, preserve_metadata=True)
self._delete()
return target

def move_into(self, target_dir):
"""
Move this file or directory tree into the given existing directory.
"""
name = self.name
if not name:
raise ValueError(f"{self!r} has an empty name")
elif isinstance(target_dir, PathBase):
target = target_dir / name
else:
target = self.with_segments(target_dir, name)
return self.move(target)

if hasattr(os, "symlink"):
def symlink_to(self, target, target_is_directory=False):
Expand Down
Loading

0 comments on commit dd55eae

Please sign in to comment.