PEP 615: Changes to TZPATH and str, plus minor tweaks (#1323)
* Change fallback behavior for __str__ Per Petr's suggestion in the discourse thread. Turns out this was basically what the reference implementation does anyway. * Rename `set_tzpath` to `reset_tzpath` * Adjust TZPATH strategy Partially in response to Petr's comment on the discourse thread, and partially from further reflection. * Fix typo in RFC 8536 reference * Add path traversal to security implications. Seems like a minor concern, but possibly worth noting.
This commit is contained in:
parent
6b5dd00bf1
commit
37a7083660
107
pep-0615.rst
107
pep-0615.rst
|
@ -210,13 +210,15 @@ An example:
|
||||||
'Pacific/Kwajalein'
|
'Pacific/Kwajalein'
|
||||||
|
|
||||||
When a ``key`` is not specified, the ``str`` operation should not fail, but
|
When a ``key`` is not specified, the ``str`` operation should not fail, but
|
||||||
should return the empty string::
|
should return the file's ``__repr__``::
|
||||||
|
|
||||||
>>> with open("/dev/null", "w") as f:
|
|
||||||
... zone = ZoneInfo.from_file(f)
|
|
||||||
|
|
||||||
|
>>> zone = ZoneInfo.from_file(f)
|
||||||
>>> str(zone)
|
>>> str(zone)
|
||||||
''
|
'ZoneInfo.from_file(<_io.BytesIO object at ...>)'
|
||||||
|
|
||||||
|
The ``__repr__`` for a ``ZoneInfo`` is implementation-defined and not
|
||||||
|
necessarily stable between versions, but it must not be a valid ``ZoneInfo``
|
||||||
|
key.
|
||||||
|
|
||||||
Pickle serialization
|
Pickle serialization
|
||||||
####################
|
####################
|
||||||
|
@ -363,7 +365,7 @@ customize it. This PEP provides for three such avenues for customization:
|
||||||
|
|
||||||
1. Global configuration via a compile-time option
|
1. Global configuration via a compile-time option
|
||||||
2. Per-run configuration via environment variables
|
2. Per-run configuration via environment variables
|
||||||
3. Runtime configuration change via a ``set_tzpath`` function
|
3. Runtime configuration change via a ``reset_tzpath`` function
|
||||||
|
|
||||||
Compile-time options
|
Compile-time options
|
||||||
####################
|
####################
|
||||||
|
@ -379,16 +381,13 @@ listing possible locations for the time zone data to be deployed (e.g.
|
||||||
Environment variables
|
Environment variables
|
||||||
#####################
|
#####################
|
||||||
|
|
||||||
When initializing ``TZPATH`` (and whenever ``set_tzpath`` is called with no
|
When initializing ``TZPATH`` (and whenever ``reset_tzpath`` is called with no
|
||||||
arguments), the ``zoneinfo`` module will use two environment variables,
|
arguments), the ``zoneinfo`` module will use the environment variable
|
||||||
``PYTHONTZPATH`` and ``PYTHONTZPATH_APPEND``, if they exist, to set the search
|
``PYTHONTZPATH``, if it exists, to set the search path.
|
||||||
path.
|
|
||||||
|
|
||||||
Both are ``os.pathsep`` delimited strings. ``PYTHONTZPATH`` *replaces* the
|
``PYTHONTZPATH`` is an ``os.pathsep``-delimited string which *replaces* (rather
|
||||||
default time zone path, whereas ``PYTHONTZPATH_APPEND`` appends to the end of
|
than augments) the default time zone path. Some examples of the proposed
|
||||||
the time zone path.
|
semantics::
|
||||||
|
|
||||||
Some examples of the proposed semantics::
|
|
||||||
|
|
||||||
$ python print_tzpath.py
|
$ python print_tzpath.py
|
||||||
("/usr/share/zoneinfo",
|
("/usr/share/zoneinfo",
|
||||||
|
@ -403,23 +402,24 @@ Some examples of the proposed semantics::
|
||||||
$ PYTHONTZPATH="" python print_tzpath.py
|
$ PYTHONTZPATH="" python print_tzpath.py
|
||||||
()
|
()
|
||||||
|
|
||||||
$ PYTHONTZPATH_APPEND="/my/directory" python print_tzpath.py
|
This provides no built-in mechanism for prepending or appending to the default
|
||||||
("/usr/share/zoneinfo",
|
search path, as these use cases are likely to be somewhat more niche. It should
|
||||||
"/usr/lib/zoneinfo",
|
be possible to populate an environment variable with the default search path
|
||||||
"/usr/share/lib/zoneinfo",
|
fairly easily::
|
||||||
"/etc/zoneinfo",
|
|
||||||
"/my/directory")
|
|
||||||
|
|
||||||
``set_tzpath`` function
|
$ export DEFAULT_TZPATH=$(python -c \
|
||||||
#######################
|
"import os, zoneinfo; print(os.pathsep.join(zoneinfo.TZPATH))")
|
||||||
|
|
||||||
``zoneinfo`` provides a ``set_tzpath`` function that allows for changing the
|
``reset_tzpath`` function
|
||||||
|
#########################
|
||||||
|
|
||||||
|
``zoneinfo`` provides a ``reset_tzpath`` function that allows for changing the
|
||||||
search path at runtime.
|
search path at runtime.
|
||||||
|
|
||||||
.. code-block::
|
.. code-block::
|
||||||
|
|
||||||
def set_tzpath(
|
def reset_tzpath(
|
||||||
tzpaths: Optional[Sequence[Union[str, os.PathLike]]] = None
|
to: Optional[Sequence[Union[str, os.PathLike]]] = None
|
||||||
) -> None:
|
) -> None:
|
||||||
...
|
...
|
||||||
|
|
||||||
|
@ -430,7 +430,7 @@ configuration.
|
||||||
|
|
||||||
This is likely to be primarily useful for (permanently or temporarily)
|
This is likely to be primarily useful for (permanently or temporarily)
|
||||||
disabling the use of system time zone paths and forcing the module to use the
|
disabling the use of system time zone paths and forcing the module to use the
|
||||||
``tzdata`` package. It is not likely that ``set_tzpath`` will be a common
|
``tzdata`` package. It is not likely that ``reset_tzpath`` will be a common
|
||||||
operation, save perhaps in test functions sensitive to time zone configuration,
|
operation, save perhaps in test functions sensitive to time zone configuration,
|
||||||
but it seems preferable to provide an official mechanism for changing this
|
but it seems preferable to provide an official mechanism for changing this
|
||||||
rather than allowing a proliferation of hacks around the immutability of
|
rather than allowing a proliferation of hacks around the immutability of
|
||||||
|
@ -451,9 +451,9 @@ cache is implementation-defined. This means that the behavior of the
|
||||||
when used with the same ``key`` under different values of ``TZPATH``. For
|
when used with the same ``key`` under different values of ``TZPATH``. For
|
||||||
example::
|
example::
|
||||||
|
|
||||||
>>> set_tzpath(["/my/custom/tzdb"])
|
>>> reset_tzpath(to=["/my/custom/tzdb"])
|
||||||
>>> a = ZoneInfo("My/Custom/Zone")
|
>>> a = ZoneInfo("My/Custom/Zone")
|
||||||
>>> set_tzpath()
|
>>> reset_tzpath()
|
||||||
>>> b = ZoneInfo("My/Custom/Zone")
|
>>> b = ZoneInfo("My/Custom/Zone")
|
||||||
>>> del a
|
>>> del a
|
||||||
>>> del b
|
>>> del b
|
||||||
|
@ -488,6 +488,11 @@ but potentially from user-supplied data. Errors in the implementation
|
||||||
(particularly the C code) could cause potential security issues, but there is
|
(particularly the C code) could cause potential security issues, but there is
|
||||||
no special risk relative to parsing other file types.
|
no special risk relative to parsing other file types.
|
||||||
|
|
||||||
|
Because the time zone data keys are essentially paths relative to some time
|
||||||
|
zone root, implementations should take care to avoid path traversal attacks.
|
||||||
|
Requesting keys such as ``../../../path/to/something`` should not reveal
|
||||||
|
anything about the state of the file system outside of the time zone path.
|
||||||
|
|
||||||
Reference Implementation
|
Reference Implementation
|
||||||
========================
|
========================
|
||||||
|
|
||||||
|
@ -691,25 +696,32 @@ so great that it overwhelms the practical implementation concerns, but this
|
||||||
still requires some discussion.
|
still requires some discussion.
|
||||||
|
|
||||||
|
|
||||||
Structure of the ``PYTHON_TZPATH`` environment variables
|
Structure of the ``PYTHON_TZPATH`` environment variable
|
||||||
========================================================
|
=======================================================
|
||||||
|
|
||||||
This PEP proposes two variables to set the time zone path: ``PYTHONTZPATH`` and
|
This PEP proposes to use a single environment variable: ``PYTHONTZPATH``.
|
||||||
``PYTHONTZPATH_APPEND``. This is based on the assumption that the majority of
|
This is based on the assumption that the majority of
|
||||||
users who would want to manipulate the time zone path would want to fully
|
users who would want to manipulate the time zone path would want to fully
|
||||||
replace it (e.g. "I know exactly where my time zone data is"), and a smaller
|
replace it (e.g. "I know exactly where my time zone data is"), and other
|
||||||
fraction would want to use the standard time zone paths wherever possible, but
|
use cases like prepending to the existing search path would be less common.
|
||||||
add additional locations (possibly containing custom time zones).
|
|
||||||
|
|
||||||
There are several other schemes that were considered and weakly rejected:
|
There are several other schemes that were considered and weakly rejected:
|
||||||
|
|
||||||
1. Separate these into a ``DEFAULT_PYTHONTZPATH`` and ``PYTHONTZPATH``
|
1. Separate ``PYTHON_TZPATH`` into two environment variables:
|
||||||
variable, where ``PYTHONTZPATH`` would contain values to append (or prepend)
|
``DEFAULT_PYTHONTZPATH`` and ``PYTHONTZPATH``, where ``PYTHONTZPATH`` would
|
||||||
to the default time zone path, and ``DEFAULT_PYTHONTZPATH`` would *replace*
|
contain values to append (or prepend) to the default time zone path, and
|
||||||
the default time zone path. This was rejected because it would likely lead
|
``DEFAULT_PYTHONTZPATH`` would *replace* the default time zone path. This
|
||||||
to user confusion if the primary use case is to replace rather than augment.
|
was rejected because it would likely lead to user confusion if the primary
|
||||||
|
use case is to replace rather than augment.
|
||||||
|
|
||||||
2. Use *only* the ``PYTHONTZPATH`` variable, but provide a custom special value
|
2. Adding either ``PYTHONTZPATH_PREPEND``, ``PYTHONTZPATH_APPEND`` or both, so
|
||||||
|
that users can augment the search path on either end without attempting to
|
||||||
|
determine what the default time zone path is. This was rejected as likely to
|
||||||
|
be unnecessary, and because it could easily be added in a
|
||||||
|
backwards-compatible manner in future updates if there is much demand for
|
||||||
|
such a feature.
|
||||||
|
|
||||||
|
3. Use only the ``PYTHONTZPATH`` variable, but provide a custom special value
|
||||||
that represents the default time zone path, e.g. ``<<DEFAULT_TZPATH>>``, so
|
that represents the default time zone path, e.g. ``<<DEFAULT_TZPATH>>``, so
|
||||||
users could append to the time zone path with, e.g.
|
users could append to the time zone path with, e.g.
|
||||||
``PYTHONTZPATH=<<DEFAULT_TZPATH>>:/my/path`` could be used to append
|
``PYTHONTZPATH=<<DEFAULT_TZPATH>>:/my/path`` could be used to append
|
||||||
|
@ -719,6 +731,11 @@ There are several other schemes that were considered and weakly rejected:
|
||||||
usually found in ``PATH``-like variables, and it would be hard to discover
|
usually found in ``PATH``-like variables, and it would be hard to discover
|
||||||
mistakes in your implementation.
|
mistakes in your implementation.
|
||||||
|
|
||||||
|
One advantage to this scheme would be that it would add a natural extension
|
||||||
|
point for specifying non-file-based elements on the search path, such as
|
||||||
|
changing the priority of ``tzdata`` if it exists, or if native support for
|
||||||
|
TZDIST [#rfc7808]_ were to be added to the library in the future.
|
||||||
|
|
||||||
Windows support via Microsoft's ICU API
|
Windows support via Microsoft's ICU API
|
||||||
=======================================
|
=======================================
|
||||||
|
|
||||||
|
@ -780,8 +797,12 @@ References
|
||||||
RFC 6557: Procedures for Maintaining the Time Zone Database
|
RFC 6557: Procedures for Maintaining the Time Zone Database
|
||||||
https://tools.ietf.org/html/rfc6557
|
https://tools.ietf.org/html/rfc6557
|
||||||
|
|
||||||
|
.. [#rfc7808]
|
||||||
|
RFC 7808: Time Zone Data Distribution Service
|
||||||
|
https://tools.ietf.org/html/rfc7808
|
||||||
|
|
||||||
.. [#rfc8536]
|
.. [#rfc8536]
|
||||||
RFC 8636: The Time Zone Information Format (TZif)
|
RFC 8536: The Time Zone Information Format (TZif)
|
||||||
https://tools.ietf.org/html/rfc8536
|
https://tools.ietf.org/html/rfc8536
|
||||||
|
|
||||||
.. [#nontransitive_comp]
|
.. [#nontransitive_comp]
|
||||||
|
|
Loading…
Reference in New Issue