diff --git a/pep-0615.rst b/pep-0615.rst index dc8012268..9b77a8cb5 100644 --- a/pep-0615.rst +++ b/pep-0615.rst @@ -210,13 +210,15 @@ An example: 'Pacific/Kwajalein' When a ``key`` is not specified, the ``str`` operation should not fail, but -should return the empty string:: - - >>> with open("/dev/null", "w") as f: - ... zone = ZoneInfo.from_file(f) +should return the file's ``__repr__``:: + >>> zone = ZoneInfo.from_file(f) >>> 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 #################### @@ -363,7 +365,7 @@ customize it. This PEP provides for three such avenues for customization: 1. Global configuration via a compile-time option 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 #################### @@ -379,16 +381,13 @@ listing possible locations for the time zone data to be deployed (e.g. Environment variables ##################### -When initializing ``TZPATH`` (and whenever ``set_tzpath`` is called with no -arguments), the ``zoneinfo`` module will use two environment variables, -``PYTHONTZPATH`` and ``PYTHONTZPATH_APPEND``, if they exist, to set the search -path. +When initializing ``TZPATH`` (and whenever ``reset_tzpath`` is called with no +arguments), the ``zoneinfo`` module will use the environment variable +``PYTHONTZPATH``, if it exists, to set the search path. -Both are ``os.pathsep`` delimited strings. ``PYTHONTZPATH`` *replaces* the -default time zone path, whereas ``PYTHONTZPATH_APPEND`` appends to the end of -the time zone path. - -Some examples of the proposed semantics:: +``PYTHONTZPATH`` is an ``os.pathsep``-delimited string which *replaces* (rather +than augments) the default time zone path. Some examples of the proposed +semantics:: $ python print_tzpath.py ("/usr/share/zoneinfo", @@ -403,23 +402,24 @@ Some examples of the proposed semantics:: $ PYTHONTZPATH="" python print_tzpath.py () - $ PYTHONTZPATH_APPEND="/my/directory" python print_tzpath.py - ("/usr/share/zoneinfo", - "/usr/lib/zoneinfo", - "/usr/share/lib/zoneinfo", - "/etc/zoneinfo", - "/my/directory") +This provides no built-in mechanism for prepending or appending to the default +search path, as these use cases are likely to be somewhat more niche. It should +be possible to populate an environment variable with the default search path +fairly easily:: -``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. .. code-block:: - def set_tzpath( - tzpaths: Optional[Sequence[Union[str, os.PathLike]]] = None + def reset_tzpath( + to: Optional[Sequence[Union[str, os.PathLike]]] = None ) -> None: ... @@ -430,7 +430,7 @@ configuration. 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 -``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, but it seems preferable to provide an official mechanism for changing this 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 example:: - >>> set_tzpath(["/my/custom/tzdb"]) + >>> reset_tzpath(to=["/my/custom/tzdb"]) >>> a = ZoneInfo("My/Custom/Zone") - >>> set_tzpath() + >>> reset_tzpath() >>> b = ZoneInfo("My/Custom/Zone") >>> del a >>> 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 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 ======================== @@ -691,25 +696,32 @@ so great that it overwhelms the practical implementation concerns, but this 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 -``PYTHONTZPATH_APPEND``. This is based on the assumption that the majority of +This PEP proposes to use a single environment variable: ``PYTHONTZPATH``. +This is based on the assumption that the majority of 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 -fraction would want to use the standard time zone paths wherever possible, but -add additional locations (possibly containing custom time zones). +replace it (e.g. "I know exactly where my time zone data is"), and other +use cases like prepending to the existing search path would be less common. There are several other schemes that were considered and weakly rejected: -1. Separate these into a ``DEFAULT_PYTHONTZPATH`` and ``PYTHONTZPATH`` - variable, where ``PYTHONTZPATH`` would contain values to append (or prepend) - to the default time zone path, and ``DEFAULT_PYTHONTZPATH`` would *replace* - the default time zone path. This was rejected because it would likely lead - to user confusion if the primary use case is to replace rather than augment. +1. Separate ``PYTHON_TZPATH`` into two environment variables: + ``DEFAULT_PYTHONTZPATH`` and ``PYTHONTZPATH``, where ``PYTHONTZPATH`` would + contain values to append (or prepend) to the default time zone path, and + ``DEFAULT_PYTHONTZPATH`` would *replace* the default time zone path. This + 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. ``<>``, so users could append to the time zone path with, e.g. ``PYTHONTZPATH=<>:/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 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 ======================================= @@ -780,8 +797,12 @@ References RFC 6557: Procedures for Maintaining the Time Zone Database https://tools.ietf.org/html/rfc6557 +.. [#rfc7808] + RFC 7808: Time Zone Data Distribution Service + https://tools.ietf.org/html/rfc7808 + .. [#rfc8536] - RFC 8636: The Time Zone Information Format (TZif) + RFC 8536: The Time Zone Information Format (TZif) https://tools.ietf.org/html/rfc8536 .. [#nontransitive_comp]