From 60ff7c3beb27c85059f5cda45046510ca3d43d8c Mon Sep 17 00:00:00 2001
From: Erik Cederstrand Module
INITIAL_RETRY_POLICY = FailFast()
RETRY_WAIT = 10 # Seconds to wait before retry on connection errors
MAX_REDIRECTS = 10 # Maximum number of URL redirects before we give up
+ DNS_RESOLVER_ATTRS = {
+ 'timeout': AutodiscoverProtocol.TIMEOUT,
+ }
def __init__(self, email, credentials=None, auth_type=None, retry_policy=None):
"""
@@ -177,7 +180,8 @@ exchangelib.autodiscover.discovery
Module
@threaded_cached_property
def resolver(self):
resolver = dns.resolver.Resolver()
- resolver.timeout = AutodiscoverProtocol.TIMEOUT
+ for k, v in self.DNS_RESOLVER_ATTRS.items():
+ setattr(resolver, k, v)
return resolver
def _build_response(self, ad_response):
@@ -715,6 +719,9 @@ exchangelib.autodiscover.discovery
Args
INITIAL_RETRY_POLICY = FailFast()
RETRY_WAIT = 10 # Seconds to wait before retry on connection errors
MAX_REDIRECTS = 10 # Maximum number of URL redirects before we give up
+ DNS_RESOLVER_ATTRS = {
+ 'timeout': AutodiscoverProtocol.TIMEOUT,
+ }
def __init__(self, email, credentials=None, auth_type=None, retry_policy=None):
"""
@@ -789,7 +796,8 @@ Args
@threaded_cached_property
def resolver(self):
resolver = dns.resolver.Resolver()
- resolver.timeout = AutodiscoverProtocol.TIMEOUT
+ for k, v in self.DNS_RESOLVER_ATTRS.items():
+ setattr(resolver, k, v)
return resolver
def _build_response(self, ad_response):
@@ -1211,6 +1219,10 @@ Args
Class variables
+
var DNS_RESOLVER_ATTRS
var INITIAL_RETRY_POLICY
Index
Autodiscovery
+
DNS_RESOLVER_ATTRS
INITIAL_RETRY_POLICY
MAX_REDIRECTS
RETRY_WAIT
Args
INITIAL_RETRY_POLICY = FailFast()
RETRY_WAIT = 10 # Seconds to wait before retry on connection errors
MAX_REDIRECTS = 10 # Maximum number of URL redirects before we give up
+ DNS_RESOLVER_ATTRS = {
+ 'timeout': AutodiscoverProtocol.TIMEOUT,
+ }
def __init__(self, email, credentials=None, auth_type=None, retry_policy=None):
"""
@@ -466,7 +469,8 @@ Args
@threaded_cached_property
def resolver(self):
resolver = dns.resolver.Resolver()
- resolver.timeout = AutodiscoverProtocol.TIMEOUT
+ for k, v in self.DNS_RESOLVER_ATTRS.items():
+ setattr(resolver, k, v)
return resolver
def _build_response(self, ad_response):
@@ -888,6 +892,10 @@ Args
Class variables
+
var DNS_RESOLVER_ATTRS
var INITIAL_RETRY_POLICY
Autodiscovery
+
DNS_RESOLVER_ATTRS
INITIAL_RETRY_POLICY
MAX_REDIRECTS
RETRY_WAIT
Module
import logging
import warnings
-import dateutil.parser
try:
import zoneinfo
except ImportError:
@@ -176,10 +175,8 @@ exchangelib.ewsdatetime
Module
# This is probably a naive datetime. Don't allow this, but signal caller with an appropriate error
local_dt = super().strptime(date_string, '%Y-%m-%dT%H:%M:%S')
raise NaiveDateTimeNotAllowed(local_dt)
- # This is probably a datetime value with timezone information. This comes in the form '+/-HH:MM' but the Python
- # strptime '%z' directive cannot yet handle full ISO8601 formatted timezone information (see
- # http://bugs.python.org/issue15873). Use the 'dateutil' package instead.
- aware_dt = dateutil.parser.parse(date_string).astimezone(UTC).replace(tzinfo=UTC)
+ # This is probably a datetime value with timezone information. This comes in the form '+/-HH:MM'.
+ aware_dt = datetime.datetime.fromisoformat(date_string).astimezone(UTC).replace(tzinfo=UTC)
if isinstance(aware_dt, cls):
return aware_dt
return cls.from_datetime(aware_dt)
@@ -581,10 +578,8 @@ exchangelib.ewsdatetime
Methods
# This is probably a naive datetime. Don't allow this, but signal caller with an appropriate error
local_dt = super().strptime(date_string, '%Y-%m-%dT%H:%M:%S')
raise NaiveDateTimeNotAllowed(local_dt)
- # This is probably a datetime value with timezone information. This comes in the form '+/-HH:MM' but the Python
- # strptime '%z' directive cannot yet handle full ISO8601 formatted timezone information (see
- # http://bugs.python.org/issue15873). Use the 'dateutil' package instead.
- aware_dt = dateutil.parser.parse(date_string).astimezone(UTC).replace(tzinfo=UTC)
+ # This is probably a datetime value with timezone information. This comes in the form '+/-HH:MM'.
+ aware_dt = datetime.datetime.fromisoformat(date_string).astimezone(UTC).replace(tzinfo=UTC)
if isinstance(aware_dt, cls):
return aware_dt
return cls.from_datetime(aware_dt)
@@ -671,10 +666,8 @@ Static methods
# This is probably a naive datetime. Don't allow this, but signal caller with an appropriate error
local_dt = super().strptime(date_string, '%Y-%m-%dT%H:%M:%S')
raise NaiveDateTimeNotAllowed(local_dt)
- # This is probably a datetime value with timezone information. This comes in the form '+/-HH:MM' but the Python
- # strptime '%z' directive cannot yet handle full ISO8601 formatted timezone information (see
- # http://bugs.python.org/issue15873). Use the 'dateutil' package instead.
- aware_dt = dateutil.parser.parse(date_string).astimezone(UTC).replace(tzinfo=UTC)
+ # This is probably a datetime value with timezone information. This comes in the form '+/-HH:MM'.
+ aware_dt = datetime.datetime.fromisoformat(date_string).astimezone(UTC).replace(tzinfo=UTC)
if isinstance(aware_dt, cls):
return aware_dt
return cls.from_datetime(aware_dt)
diff --git a/docs/exchangelib/fields.html b/docs/exchangelib/fields.html
index dde82b8e..22b2e2eb 100644
--- a/docs/exchangelib/fields.html
+++ b/docs/exchangelib/fields.html
@@ -35,8 +35,6 @@ Module
from importlib import import_module
import logging
-import dateutil.parser
-
from .errors import ErrorInvalidServerVersion
from .ewsdatetime import EWSDateTime, EWSDate, EWSTimeZone, NaiveDateTimeNotAllowed, UnknownTimeZone, UTC
from .util import create_element, get_xml_attrs, set_xml_value, value_to_xml_text, is_iterable, safe_b64decode, TNS
@@ -666,7 +664,7 @@ exchangelib.fields
Module
# before converting to date. EWSDateTime.from_string() insists on converting to UTC, but we don't have an
# EWSTimeZone we can convert the timezone info to. Instead, parse the string manually when we have a
# datetime string with timezone info.
- return EWSDate.from_date(dateutil.parser.parse(val).date())
+ return EWSDate.from_date(datetime.datetime.fromisoformat(val).date())
# Revert to default parsing of datetime strings
res = self._datetime_field.from_xml(elem=elem, account=account)
if res is None:
@@ -2846,7 +2844,7 @@ exchangelib.fields
Inherited members
# before converting to date. EWSDateTime.from_string() insists on converting to UTC, but we don't have an
# EWSTimeZone we can convert the timezone info to. Instead, parse the string manually when we have a
# datetime string with timezone info.
- return EWSDate.from_date(dateutil.parser.parse(val).date())
+ return EWSDate.from_date(datetime.datetime.fromisoformat(val).date())
# Revert to default parsing of datetime strings
res = self._datetime_field.from_xml(elem=elem, account=account)
if res is None:
@@ -2901,7 +2899,7 @@ Methods
# before converting to date. EWSDateTime.from_string() insists on converting to UTC, but we don't have an
# EWSTimeZone we can convert the timezone info to. Instead, parse the string manually when we have a
# datetime string with timezone info.
- return EWSDate.from_date(dateutil.parser.parse(val).date())
+ return EWSDate.from_date(datetime.datetime.fromisoformat(val).date())
# Revert to default parsing of datetime strings
res = self._datetime_field.from_xml(elem=elem, account=account)
if res is None:
@@ -4810,7 +4808,7 @@ Class variables
The base defaults to 10.
Valid bases are 0 and 2-36.
Base 0 means to interpret the base from the string as an integer literal.
>>> int('0b100', base=0)
+>>> int('0b100', base=0)
4
diff --git a/docs/exchangelib/index.html b/docs/exchangelib/index.html
index e212df6e..8cd60263 100644
--- a/docs/exchangelib/index.html
+++ b/docs/exchangelib/index.html
@@ -26,7 +26,9 @@ Package exchangelib
Expand source code
-from .account import Account, Identity
+import sys
+
+from .account import Account, Identity
from .attachments import FileAttachment, ItemAttachment
from .autodiscover import discover
from .configuration import Configuration
@@ -44,7 +46,7 @@ Package exchangelib
from .transport import BASIC, DIGEST, NTLM, GSSAPI, SSPI, OAUTH2, CBA
from .version import Build, Version
-__version__ = '3.3.0'
+__version__ = '3.3.1'
__all__ = [
'__version__',
@@ -70,6 +72,11 @@ Package exchangelib
import requests.utils
BaseProtocol.USERAGENT = "%s/%s (%s)" % (__name__, __version__, requests.utils.default_user_agent())
+# Support fromisoformat() in Python < 3.7
+if sys.version_info[:2] < (3, 7):
+ from backports.datetime_fromisoformat import MonkeyPatch
+ MonkeyPatch.patch_fromisoformat()
+
def close_connections():
from .autodiscover import close_connections as close_autodiscover_connections
@@ -5463,10 +5470,8 @@ Methods
# This is probably a naive datetime. Don't allow this, but signal caller with an appropriate error
local_dt = super().strptime(date_string, '%Y-%m-%dT%H:%M:%S')
raise NaiveDateTimeNotAllowed(local_dt)
- # This is probably a datetime value with timezone information. This comes in the form '+/-HH:MM' but the Python
- # strptime '%z' directive cannot yet handle full ISO8601 formatted timezone information (see
- # http://bugs.python.org/issue15873). Use the 'dateutil' package instead.
- aware_dt = dateutil.parser.parse(date_string).astimezone(UTC).replace(tzinfo=UTC)
+ # This is probably a datetime value with timezone information. This comes in the form '+/-HH:MM'.
+ aware_dt = datetime.datetime.fromisoformat(date_string).astimezone(UTC).replace(tzinfo=UTC)
if isinstance(aware_dt, cls):
return aware_dt
return cls.from_datetime(aware_dt)
@@ -5553,10 +5558,8 @@ Static methods
# This is probably a naive datetime. Don't allow this, but signal caller with an appropriate error
local_dt = super().strptime(date_string, '%Y-%m-%dT%H:%M:%S')
raise NaiveDateTimeNotAllowed(local_dt)
- # This is probably a datetime value with timezone information. This comes in the form '+/-HH:MM' but the Python
- # strptime '%z' directive cannot yet handle full ISO8601 formatted timezone information (see
- # http://bugs.python.org/issue15873). Use the 'dateutil' package instead.
- aware_dt = dateutil.parser.parse(date_string).astimezone(UTC).replace(tzinfo=UTC)
+ # This is probably a datetime value with timezone information. This comes in the form '+/-HH:MM'.
+ aware_dt = datetime.datetime.fromisoformat(date_string).astimezone(UTC).replace(tzinfo=UTC)
if isinstance(aware_dt, cls):
return aware_dt
return cls.from_datetime(aware_dt)
diff --git a/exchangelib/__init__.py b/exchangelib/__init__.py
index 843d9a4d..99fc9987 100644
--- a/exchangelib/__init__.py
+++ b/exchangelib/__init__.py
@@ -18,7 +18,7 @@
from .transport import BASIC, DIGEST, NTLM, GSSAPI, SSPI, OAUTH2, CBA
from .version import Build, Version
-__version__ = '3.3.0'
+__version__ = '3.3.1'
__all__ = [
'__version__',