python-dateutil 2.9.0__py2.py3-none-any.whl → 3.0.0__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
dateutil/__init__.py CHANGED
@@ -6,19 +6,21 @@ try:
6
6
  except ImportError:
7
7
  __version__ = 'unknown'
8
8
 
9
- __all__ = ['easter', 'parser', 'relativedelta', 'rrule', 'tz',
10
- 'utils', 'zoneinfo']
9
+ __all__ = ["easter", "parser", "relativedelta", "rrule", "tz", "utils"]
10
+
11
11
 
12
12
  def __getattr__(name):
13
13
  import importlib
14
14
 
15
- if name in __all__:
15
+ if name in __all__ or name == "zoneinfo":
16
16
  return importlib.import_module("." + name, __name__)
17
17
  raise AttributeError(
18
- "module {!r} has not attribute {!r}".format(__name__, name)
18
+ "module {!r} has no attribute {!r}".format(__name__, name)
19
19
  )
20
20
 
21
21
 
22
22
  def __dir__():
23
23
  # __dir__ should include all the lazy-importable modules as well.
24
- return [x for x in globals() if x not in sys.modules] + __all__
24
+ return (
25
+ [x for x in globals() if x not in sys.modules] + __all__ + ["zoneinfo"]
26
+ )
@@ -0,0 +1,147 @@
1
+ """This is an implementation of functions that interact with the tzdata module.
2
+
3
+ It will only live as long as :mod:`dateutil.zoneinfo` lives; when the
4
+ ``dateutil.zoneinfo`` module is removed, this can all move under :mod:`tz`.
5
+ """
6
+
7
+ import contextlib
8
+ import importlib
9
+ import io
10
+ import os
11
+ import pkgutil
12
+ import sys
13
+
14
+ import six
15
+
16
+ if six.PY2:
17
+ _TZDATA_LOAD_EXCEPTIONS = (
18
+ ImportError,
19
+ IOError,
20
+ UnicodeEncodeError,
21
+ ValueError,
22
+ )
23
+ else:
24
+ _TZDATA_LOAD_EXCEPTIONS = (
25
+ ImportError,
26
+ FileNotFoundError,
27
+ UnicodeEncodeError,
28
+ IsADirectoryError,
29
+ ValueError,
30
+ )
31
+
32
+ if sys.version_info < (3, 8):
33
+ _nullcontext = getattr(contextlib, "nullcontext", None)
34
+ if _nullcontext is None:
35
+
36
+ @contextlib.contextmanager
37
+ def _nullcontext(v):
38
+ yield v
39
+
40
+ def _get_data(package, resource):
41
+ # pkgutil.get_data returns None rather than raising when the package
42
+ # cannot be found (and on Python 2 raises AttributeError if the
43
+ # package has been blocked by setting sys.modules[name] = None), so
44
+ # import the package first to get the ImportError the callers expect
45
+ # from the importlib.resources versions of these functions.
46
+ importlib.import_module(package)
47
+
48
+ pkg_data = pkgutil.get_data(package, resource)
49
+ if pkg_data is None:
50
+ raise ImportError("No package named %r" % package)
51
+
52
+ return pkg_data
53
+
54
+ def _open_text(package, resource):
55
+ str_package_data = _get_data(package, resource).decode("utf-8")
56
+
57
+ return _nullcontext(io.StringIO(str_package_data))
58
+
59
+ def _open_binary(package, resource):
60
+ return io.BytesIO(_get_data(package, resource))
61
+
62
+ else:
63
+ import importlib.resources
64
+
65
+ if sys.version_info >= (3, 9):
66
+
67
+ def _open_text(package, resource):
68
+ return (
69
+ importlib.resources.files(package)
70
+ .joinpath(resource)
71
+ .open("r", encoding="utf-8")
72
+ )
73
+
74
+ def _open_binary(package, resource):
75
+ return (
76
+ importlib.resources.files(package).joinpath(resource).open("rb")
77
+ )
78
+
79
+ else:
80
+ _open_text = importlib.resources.open_text
81
+ _open_binary = importlib.resources.open_binary
82
+
83
+
84
+ def _is_package_directory(package, resource):
85
+ """Whether ``resource`` names a directory inside ``package``.
86
+
87
+ Opening a directory raises IsADirectoryError on POSIX but PermissionError
88
+ on Windows, and on Python < 3.9 there is no portable way to ask the
89
+ resource API, so check the package's search path directly (the tzdata
90
+ package is a regular directory-backed package).
91
+ """
92
+ try:
93
+ pkg = importlib.import_module(package)
94
+ except ImportError:
95
+ return False
96
+
97
+ for base in getattr(pkg, "__path__", ()):
98
+ if os.path.isdir(os.path.join(base, resource)):
99
+ return True
100
+
101
+ return False
102
+
103
+
104
+ def _load_tzdata(key):
105
+ components = key.split("/")
106
+ package_name = ".".join(["tzdata.zoneinfo"] + components[:-1])
107
+ resource_name = components[-1]
108
+
109
+ # Empty or relative path components cannot name a zone, and they produce
110
+ # module names that the import machinery handles inconsistently across
111
+ # versions, so treat them as not found up front. A key naming a directory
112
+ # (a subpackage) is not a zone either, and opening it raises a
113
+ # platform-dependent error, see CPython gh-85702.
114
+ if any(c in ("", ".", "..") for c in components) or _is_package_directory(
115
+ package_name, resource_name
116
+ ):
117
+ raise TZFileNotFound("Time zone not found: %s", zone_key=key)
118
+
119
+ try:
120
+ return _open_binary(package_name, resource_name)
121
+ except _TZDATA_LOAD_EXCEPTIONS:
122
+ # ImportError: package does not exist (or tzdata is not installed)
123
+ # FileNotFoundError: the key is not a file in the package
124
+ # UnicodeEncodeError: the key is not encodable as a filename
125
+ # IsADirectoryError: the key names a package rather than a resource
126
+ # ValueError: the key is not a valid path (e.g. contains a NUL byte)
127
+ six.raise_from(
128
+ TZFileNotFound("Time zone not found: %s", zone_key=key), None
129
+ )
130
+
131
+
132
+ def _load_tzdata_keys():
133
+ with _open_text("tzdata", "zones") as f:
134
+ return list(filter(None, (l.strip() for l in f)))
135
+
136
+
137
+ class TZFileNotFound(ValueError):
138
+ """Indicates that a time zone file isn't present in tzdata."""
139
+
140
+ def __init__(self, msg, *args, **kwargs):
141
+ # TODO: Use keyword-only argument when this is Python 3-only
142
+ zone_key = kwargs.pop("zone_key", None)
143
+ if zone_key is None: # pragma: nocover
144
+ raise TypeError("Required keyword argument missing: zone_key")
145
+
146
+ super(TZFileNotFound, self).__init__(msg % zone_key, *args)
147
+ self.zone_key = zone_key
dateutil/_version.py CHANGED
@@ -1,16 +1,4 @@
1
1
  # file generated by setuptools_scm
2
2
  # don't change, don't track in version control
3
- TYPE_CHECKING = False
4
- if TYPE_CHECKING:
5
- from typing import Tuple, Union
6
- VERSION_TUPLE = Tuple[Union[int, str], ...]
7
- else:
8
- VERSION_TUPLE = object
9
-
10
- version: str
11
- __version__: str
12
- __version_tuple__: VERSION_TUPLE
13
- version_tuple: VERSION_TUPLE
14
-
15
- __version__ = version = '2.9.0'
16
- __version_tuple__ = version_tuple = (2, 9, 0)
3
+ __version__ = version = '3.0.0'
4
+ __version_tuple__ = version_tuple = (3, 0, 0)
dateutil/relativedelta.py CHANGED
@@ -564,9 +564,6 @@ class relativedelta(object):
564
564
  self.microsecond,
565
565
  ))
566
566
 
567
- def __ne__(self, other):
568
- return not self.__eq__(other)
569
-
570
567
  def __div__(self, other):
571
568
  try:
572
569
  reciprocal = 1 / float(other)
dateutil/rrule.py CHANGED
@@ -102,6 +102,30 @@ class rrulebase(object):
102
102
  self._cache_complete = False
103
103
  self._len = None
104
104
 
105
+ def __reduce_ex__(self, protocol):
106
+ rv = super(rrulebase, self).__reduce_ex__(protocol)
107
+ state, slots = rv[2], None
108
+ if isinstance(state, tuple):
109
+ state, slots = state
110
+ if self._cache is not None:
111
+ state = dict(state)
112
+ state.pop("_cache_lock", None)
113
+ state.pop("_cache_gen", None)
114
+ state["_cache"] = []
115
+ if slots is not None:
116
+ state = (state, slots)
117
+ return rv[:2] + (state,) + rv[3:]
118
+
119
+ def __setstate__(self, state):
120
+ if isinstance(state, tuple):
121
+ state, slots = state
122
+ for name, value in slots.items():
123
+ setattr(self, name, value)
124
+ self.__dict__.update(state)
125
+ if self._cache is not None:
126
+ self._cache_lock = _thread.allocate_lock()
127
+ self._invalidate_cache()
128
+
105
129
  def __iter__(self):
106
130
  if self._cache_complete:
107
131
  return iter(self._cache)
@@ -1672,7 +1696,10 @@ class _rrulestr(object):
1672
1696
  parms = parms[1:]
1673
1697
  if name == "RRULE":
1674
1698
  for parm in parms:
1675
- raise ValueError("unsupported RRULE parm: "+parm)
1699
+ if parm.startswith("X-"):
1700
+ # Experimental random vendor features; safe to ignore
1701
+ continue
1702
+ raise ValueError("unsupported RRULE parm: " + parm)
1676
1703
  rrulevals.append(value)
1677
1704
  elif name == "RDATE":
1678
1705
  for parm in parms:
dateutil/tz/__init__.py CHANGED
@@ -1,11 +1,59 @@
1
1
  # -*- coding: utf-8 -*-
2
+ import sys
3
+
4
+ from . import _tzpath
5
+ from ._tzpath import reset_tzpath
2
6
  from .tz import *
3
7
  from .tz import __doc__
4
8
 
5
- __all__ = ["tzutc", "tzoffset", "tzlocal", "tzfile", "tzrange",
6
- "tzstr", "tzical", "tzwin", "tzwinlocal", "gettz",
7
- "enfold", "datetime_ambiguous", "datetime_exists",
8
- "resolve_imaginary", "UTC", "DeprecatedTzFormatWarning"]
9
+ __all__ = [
10
+ "tzutc",
11
+ "tzoffset",
12
+ "tzlocal",
13
+ "tzfile",
14
+ "tzrange",
15
+ "tzstr",
16
+ "tzical",
17
+ "tzwin",
18
+ "tzwinlocal",
19
+ "gettz",
20
+ "enfold",
21
+ "datetime_ambiguous",
22
+ "datetime_exists",
23
+ "resolve_imaginary",
24
+ "available_iana_timezones",
25
+ "UTC",
26
+ "TZPATH",
27
+ "reset_tzpath",
28
+ "DeprecatedTzFormatWarning",
29
+ "DeprecatedTzKeyWarning",
30
+ ]
31
+
32
+ if sys.version_info < (3, 7):
33
+ # Module-level __getattr__ was added in Python 3.7, so instead of lazily
34
+ # populating TZPATH on every access, we will register a callback with
35
+ # reset_tzpath to update the top-level tuple.
36
+ TZPATH = _tzpath.TZPATH
37
+
38
+ def _tzpath_callback(new_tzpath):
39
+ global TZPATH
40
+ TZPATH = new_tzpath
41
+
42
+ _tzpath.TZPATH_CALLBACKS.append(_tzpath_callback)
43
+
44
+ else:
45
+
46
+ def __getattr__(name):
47
+ if name == "TZPATH":
48
+ return _tzpath.TZPATH
49
+ else:
50
+ raise AttributeError(
51
+ "Module %s has no attribute %s" % (repr(__name__), repr(name))
52
+ )
53
+
54
+
55
+ def __dir__():
56
+ return sorted(list(globals()) + ["TZPATH"])
9
57
 
10
58
 
11
59
  class DeprecatedTzFormatWarning(Warning):