zoneinfo: ZoneInfo raises IsADirectoryError instead of ZoneInfoNotFoundError
| BPO | 41530 |
|---|---|
| Nosy | @vstinner, @pganssle, @bijij |
| PRs |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
assignee = None
closed_at = None
created_at = <Date 2020-08-12.11:42:16.788>
labels = ['type-bug', 'library', '3.9', '3.10']
title = 'zoneinfo: ZoneInfo raises IsADirectoryError instead of ZoneInfoNotFoundError'
updated_at = <Date 2020-08-12.14:46:45.318>
user = 'https://github.com/bijij'
bugs.python.org fields:
activity = <Date 2020-08-12.14:46:45.318>
actor = 'josh.ja.butt'
assignee = 'none'
closed = False
closed_date = None
closer = None
components = ['Library (Lib)']
creation = <Date 2020-08-12.11:42:16.788>
creator = 'josh.ja.butt'
dependencies = []
files = []
hgrepos = []
issue_num = 41530
keywords = ['patch']
message_count = 10.0
messages = ['375225', '375226', '375228', '375233', '375234', '375235', '375238', '375239', '375240', '375251']
nosy_count = 4.0
nosy_names = ['vstinner', 'python-dev', 'p-ganssle', 'josh.ja.butt']
pr_nums = ['21839']
priority = 'normal'
resolution = None
stage = 'patch review'
status = 'open'
superseder = None
type = 'behavior'
url = 'https://bugs.python.org/issue41530'
versions = ['Python 3.9', 'Python 3.10']
Linked PRs
- gh-131333
Attempting to parse specific keys in zoneinfo.ZoneInfo with tzdata installed will raise unhandled exceptions
e.g. on windows
>>> import zoneinfo
>>> zoneinfo.ZoneInfo('Pacific')
PermissionError: [Errno 13] Permission denied: 'C:\\Program Files\\Python39\\lib\\site-packages\\tzdata\\zoneinfo\\Pacific'
>>> import zoneinfo
>>> zoneinfo.ZoneInfo('__init__.py')
ValueError: Invalid TZif file: magic not found
This happens when non TZif files or directories in the tzdata.zoneinfo module are used as keys.
Hi. It seems like you are running Windows.
About the permission error, how did you install tzdata? Did you install it as an admin user and do you run Python as a different user?
tzdata was installed as an admin user, however this behaviour was reproducible on a linux installation where for the ZoneInfo.('Pacific') instance an IsADirectoryError would instead be raised.
On Wed, Aug 12, 2020 at 9:50 PM STINNER Victor <[email protected]> wrote:
STINNER Victor <[email protected]> added the comment:
Hi. It seems like you are running Windows.
About the permission error, how did you install tzdata? Did you install it as an admin user and do you run Python as a different user?
---------- nosy: +vstinner
Python tracker <[email protected]> <https://bugs.python.org/issue41530>
Oh right, 'Pacific' is a directory, not a valid zone, and so ZoneInfoNotFoundError should be raised. I see.
Example:
$ ./python -m venv env
$ env/bin/python -m pip install tzdata
$ env/bin/python
# ZoneInfoNotFoundError expected, get IsADirectoryError
>>> import zoneinfo; zoneinfo.ZoneInfo('Pacific')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/vstinner/python/master/Lib/zoneinfo/_common.py", line 12, in load_tzdata
return importlib.resources.open_binary(package_name, resource_name)
File "/home/vstinner/python/master/Lib/importlib/resources.py", line 40, in open_binary
return reader.open_resource(resource)
File "/home/vstinner/python/master/Lib/importlib/abc.py", line 419, in open_resource
return self.files().joinpath(resource).open('rb')
File "/home/vstinner/python/master/Lib/pathlib.py", line 1238, in open
return io.open(self, mode, buffering, encoding, errors, newline,
IsADirectoryError: [Errno 21] Is a directory: '/home/vstinner/python/master/env/lib/python3.10/site-packages/tzdata/zoneinfo/Pacific'
# valid zone
>>> import zoneinfo; zoneinfo.ZoneInfo('Pacific/Noumea')
zoneinfo.ZoneInfo(key='Pacific/Noumea')
# raise ZoneInfoNotFoundError as expected (from FileNotFoundError)
>>> import zoneinfo; zoneinfo.ZoneInfo('xxx')
Traceback (most recent call last):
File "/home/vstinner/python/master/Lib/zoneinfo/_common.py", line 12, in load_tzdata
return importlib.resources.open_binary(package_name, resource_name)
File "/home/vstinner/python/master/Lib/importlib/resources.py", line 40, in open_binary
return reader.open_resource(resource)
File "/home/vstinner/python/master/Lib/importlib/abc.py", line 419, in open_resource
return self.files().joinpath(resource).open('rb')
File "/home/vstinner/python/master/Lib/pathlib.py", line 1238, in open
return io.open(self, mode, buffering, encoding, errors, newline,
File "/home/vstinner/python/master/Lib/pathlib.py", line 1106, in _opener
return self._accessor.open(self, flags, mode)
FileNotFoundError: [Errno 2] No such file or directory: '/home/vstinner/python/master/env/lib/python3.10/site-packages/tzdata/zoneinfo/xxx'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/vstinner/python/master/Lib/zoneinfo/_common.py", line 24, in load_tzdata
raise ZoneInfoNotFoundError(f"No time zone found with key {key}")
zoneinfo._common.ZoneInfoNotFoundError: 'No time zone found with key xxx'
On Linux, converting IsADirectoryError to ZoneInfoNotFoundError is easy.
But on Windows, I don't think that converting any PermissionError into a ZoneInfoNotFoundError is a good idea. Maybe if PermissionError happens, we should check if the path is a directory.
Pseudo-code:
try: <open and read file> except OSError as exc: if os.path.isdir(zone_path): raise ZoneInfoNotFoundError else: raise
Oh, I dislike Roundup UI. I didn't notice that a PR was submitted: PR 21839 (now closed).
I had opened a PR which just caught IsADirectoryError and PermissionError but closed it as you'd mentioned that handling PermissionError that way probably would not be the best, and I agree. I can reopen and modify to check path on OSerror if you'd like otherwise feel free to handle however you see fit.
I think that ZoneInfo('__init__.py') is also a problem, but a slightly different one. That comes from the fact that in order to support importlib.resources, each of the zoneinfo subdirectories needs an __init__.py, but the ZoneInfo constructor should probably ignore those, since they are added by tzdata and not actually part of a tzdata distribution.
By the way, it might be easiest to start with a PR against backports.zoneinfo, because I have a lot more linting, coverage and format checks set up there: https://github.com/pganssle/zoneinfo
I'll reopen the PR with an attempted resolution of the OSError related
issues however. In my quick testing it seems at least on Linux
backports.zoneinfo segfaults when trying ZoneInfo('__init__.py') so that
might be a larger issue for Paul to look into.
This is still an issue with python3.13:
>>> from zoneinfo._common import load_tzdata
>>> load_tzdata("Europe")
Traceback (most recent call last):
File "<python-input-1>", line 1, in <module>
load_tzdata("Europe")
~~~~~~~~~~~^^^^^^^^^^
File "/usr/lib/python3.13/zoneinfo/_common.py", line 12, in load_tzdata
return resources.files(package_name).joinpath(resource_name).open("rb")
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^
File "/usr/lib/python3.13/pathlib/_local.py", line 537, in open
return io.open(self, mode, buffering, encoding, errors, newline)
~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
IsADirectoryError: [Errno 21] Is a directory: '/path/to/python3.13/site-packages/tzdata/zoneinfo/Europe'
IsADirectoryError has been fixed, now just the windows specific case of PermissionError remains. We should not catch it outright, but maybe we could check if the error is for a file in tzdata, and then raise ZoneInfoNotFoundError?
IsADirectoryError has been fixed, now just the windows specific case of PermissionError remains. We should not catch it outright, but maybe we could check if the error is for a file in tzdata, and then raise ZoneInfoNotFoundError?
I created https://github.com/python/cpython/pull/136117 for the PermissionError on Windows.
Windows pr and backports have been merged. I do not know of anything else to do here, if other os-specific cases pop up in the future we can always reopen.