Skip to content

Commit 99aea33

Browse files
rmad17sentrivana
andauthored
Remove utcnow, utcfromtimestamp deprecated in Python 3.12 (#2415)
--------- Co-authored-by: Ivana Kellyerova <[email protected]>
1 parent 59a67d3 commit 99aea33

File tree

11 files changed

+54
-33
lines changed

11 files changed

+54
-33
lines changed

sentry_sdk/_compat.py

+16
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import sys
22
import contextlib
3+
from datetime import datetime
34
from functools import wraps
45

56
from sentry_sdk._types import TYPE_CHECKING
@@ -32,6 +33,12 @@
3233
iteritems = lambda x: x.iteritems() # noqa: B301
3334
binary_sequence_types = (bytearray, memoryview)
3435

36+
def datetime_utcnow():
37+
return datetime.utcnow()
38+
39+
def utc_from_timestamp(timestamp):
40+
return datetime.utcfromtimestamp(timestamp)
41+
3542
def implements_str(cls):
3643
# type: (T) -> T
3744
cls.__unicode__ = cls.__str__
@@ -78,6 +85,7 @@ def when_called(*args, **kwargs):
7885
return DecoratorContextManager
7986

8087
else:
88+
from datetime import timezone
8189
import urllib.parse as urlparse # noqa
8290

8391
text_type = str
@@ -87,6 +95,14 @@ def when_called(*args, **kwargs):
8795
iteritems = lambda x: x.items()
8896
binary_sequence_types = (bytes, bytearray, memoryview)
8997

98+
def datetime_utcnow():
99+
# type: () -> datetime
100+
return datetime.now(timezone.utc)
101+
102+
def utc_from_timestamp(timestamp):
103+
# type: (float) -> datetime
104+
return datetime.fromtimestamp(timestamp, timezone.utc)
105+
90106
def implements_str(x):
91107
# type: (T) -> T
92108
return x

sentry_sdk/client.py

+3-4
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,9 @@
22
import os
33
import uuid
44
import random
5-
from datetime import datetime
65
import socket
76

8-
from sentry_sdk._compat import string_types, text_type, iteritems
7+
from sentry_sdk._compat import datetime_utcnow, string_types, text_type, iteritems
98
from sentry_sdk.utils import (
109
capture_internal_exceptions,
1110
current_stacktrace,
@@ -292,7 +291,7 @@ def _prepare_event(
292291
# type: (...) -> Optional[Event]
293292

294293
if event.get("timestamp") is None:
295-
event["timestamp"] = datetime.utcnow()
294+
event["timestamp"] = datetime_utcnow()
296295

297296
if scope is not None:
298297
is_transaction = event.get("type") == "transaction"
@@ -568,7 +567,7 @@ def capture_event(
568567
if should_use_envelope_endpoint:
569568
headers = {
570569
"event_id": event_opt["event_id"],
571-
"sent_at": format_timestamp(datetime.utcnow()),
570+
"sent_at": format_timestamp(datetime_utcnow()),
572571
}
573572

574573
if dynamic_sampling_context:

sentry_sdk/db/explain_plan/__init__.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import datetime
22

3+
from sentry_sdk._compat import datetime_utcnow
34
from sentry_sdk.consts import TYPE_CHECKING
45

56
if TYPE_CHECKING:
@@ -15,7 +16,7 @@ def cache_statement(statement, options):
1516
# type: (str, dict[str, Any]) -> None
1617
global EXPLAIN_CACHE
1718

18-
now = datetime.datetime.utcnow()
19+
now = datetime_utcnow()
1920
explain_cache_timeout_seconds = options.get(
2021
"explain_cache_timeout_seconds", EXPLAIN_CACHE_TIMEOUT_SECONDS
2122
)
@@ -31,7 +32,7 @@ def remove_expired_cache_items():
3132
"""
3233
global EXPLAIN_CACHE
3334

34-
now = datetime.datetime.utcnow()
35+
now = datetime_utcnow()
3536

3637
for key, expiration_time in EXPLAIN_CACHE.items():
3738
expiration_in_the_past = expiration_time < now

sentry_sdk/hub.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
import copy
22
import sys
33

4-
from datetime import datetime
54
from contextlib import contextmanager
65

7-
from sentry_sdk._compat import with_metaclass
6+
from sentry_sdk._compat import datetime_utcnow, with_metaclass
87
from sentry_sdk.consts import INSTRUMENTER
98
from sentry_sdk.scope import Scope
109
from sentry_sdk.client import Client
@@ -439,7 +438,7 @@ def add_breadcrumb(self, crumb=None, hint=None, **kwargs):
439438
hint = dict(hint or ()) # type: Hint
440439

441440
if crumb.get("timestamp") is None:
442-
crumb["timestamp"] = datetime.utcnow()
441+
crumb["timestamp"] = datetime_utcnow()
443442
if crumb.get("type") is None:
444443
crumb["type"] = "default"
445444

sentry_sdk/integrations/aws_lambda.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import sys
22
from copy import deepcopy
3-
from datetime import datetime, timedelta
3+
from datetime import timedelta
44
from os import environ
55

66
from sentry_sdk.api import continue_trace
@@ -16,10 +16,11 @@
1616
)
1717
from sentry_sdk.integrations import Integration
1818
from sentry_sdk.integrations._wsgi_common import _filter_headers
19-
from sentry_sdk._compat import reraise
19+
from sentry_sdk._compat import datetime_utcnow, reraise
2020
from sentry_sdk._types import TYPE_CHECKING
2121

2222
if TYPE_CHECKING:
23+
from datetime import datetime
2324
from typing import Any
2425
from typing import TypeVar
2526
from typing import Callable
@@ -323,7 +324,7 @@ def get_lambda_bootstrap():
323324

324325
def _make_request_event_processor(aws_event, aws_context, configured_timeout):
325326
# type: (Any, Any, Any) -> EventProcessor
326-
start_time = datetime.utcnow()
327+
start_time = datetime_utcnow()
327328

328329
def event_processor(sentry_event, hint, start_time=start_time):
329330
# type: (Event, Hint, datetime) -> Optional[Event]
@@ -428,7 +429,7 @@ def _get_cloudwatch_logs_url(aws_context, start_time):
428429
log_group=aws_context.log_group_name,
429430
log_stream=aws_context.log_stream_name,
430431
start_time=(start_time - timedelta(seconds=1)).strftime(formatstring),
431-
end_time=(datetime.utcnow() + timedelta(seconds=2)).strftime(formatstring),
432+
end_time=(datetime_utcnow() + timedelta(seconds=2)).strftime(formatstring),
432433
)
433434

434435
return url

sentry_sdk/integrations/gcp.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import sys
22
from copy import deepcopy
3-
from datetime import datetime, timedelta
3+
from datetime import timedelta
44
from os import environ
55

66
from sentry_sdk.api import continue_trace
77
from sentry_sdk.consts import OP
88
from sentry_sdk.hub import Hub, _should_send_default_pii
99
from sentry_sdk.tracing import TRANSACTION_SOURCE_COMPONENT
10-
from sentry_sdk._compat import reraise
10+
from sentry_sdk._compat import datetime_utcnow, reraise
1111
from sentry_sdk.utils import (
1212
AnnotatedValue,
1313
capture_internal_exceptions,
@@ -25,6 +25,7 @@
2525
MILLIS_TO_SECONDS = 1000.0
2626

2727
if TYPE_CHECKING:
28+
from datetime import datetime
2829
from typing import Any
2930
from typing import TypeVar
3031
from typing import Callable
@@ -57,7 +58,7 @@ def sentry_func(functionhandler, gcp_event, *args, **kwargs):
5758

5859
configured_time = int(configured_time)
5960

60-
initial_time = datetime.utcnow()
61+
initial_time = datetime_utcnow()
6162

6263
with hub.push_scope() as scope:
6364
with capture_internal_exceptions():
@@ -154,7 +155,7 @@ def _make_request_event_processor(gcp_event, configured_timeout, initial_time):
154155
def event_processor(event, hint):
155156
# type: (Event, Hint) -> Optional[Event]
156157

157-
final_time = datetime.utcnow()
158+
final_time = datetime_utcnow()
158159
time_diff = final_time - initial_time
159160

160161
execution_duration_in_millis = time_diff.microseconds / MILLIS_TO_SECONDS

sentry_sdk/integrations/logging.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
from __future__ import absolute_import
22

33
import logging
4-
import datetime
54
from fnmatch import fnmatch
65

76
from sentry_sdk.hub import Hub
@@ -12,7 +11,7 @@
1211
capture_internal_exceptions,
1312
)
1413
from sentry_sdk.integrations import Integration
15-
from sentry_sdk._compat import iteritems
14+
from sentry_sdk._compat import iteritems, utc_from_timestamp
1615

1716
from sentry_sdk._types import TYPE_CHECKING
1817

@@ -282,6 +281,6 @@ def _breadcrumb_from_record(self, record):
282281
"level": self._logging_to_event_level(record),
283282
"category": record.name,
284283
"message": record.message,
285-
"timestamp": datetime.datetime.utcfromtimestamp(record.created),
284+
"timestamp": utc_from_timestamp(record.created),
286285
"data": self._extra_from_record(record),
287286
}

sentry_sdk/session.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import uuid
2-
from datetime import datetime
32

3+
from sentry_sdk._compat import datetime_utcnow
44
from sentry_sdk._types import TYPE_CHECKING
55
from sentry_sdk.utils import format_timestamp
66

77
if TYPE_CHECKING:
8+
from datetime import datetime
89
from typing import Optional
910
from typing import Union
1011
from typing import Any
@@ -48,7 +49,7 @@ def __init__(
4849
if sid is None:
4950
sid = uuid.uuid4()
5051
if started is None:
51-
started = datetime.utcnow()
52+
started = datetime_utcnow()
5253
if status is None:
5354
status = "ok"
5455
self.status = status
@@ -108,7 +109,7 @@ def update(
108109
if did is not None:
109110
self.did = str(did)
110111
if timestamp is None:
111-
timestamp = datetime.utcnow()
112+
timestamp = datetime_utcnow()
112113
self.timestamp = timestamp
113114
if started is not None:
114115
self.started = started

sentry_sdk/tracing.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
11
import uuid
22
import random
33

4-
from datetime import datetime, timedelta
4+
from datetime import timedelta
55

66
import sentry_sdk
77
from sentry_sdk.consts import INSTRUMENTER
88
from sentry_sdk.utils import is_valid_sample_rate, logger, nanosecond_time
9-
from sentry_sdk._compat import PY2
9+
from sentry_sdk._compat import datetime_utcnow, PY2
1010
from sentry_sdk.consts import SPANDATA
1111
from sentry_sdk._types import TYPE_CHECKING
1212

1313

1414
if TYPE_CHECKING:
1515
import typing
1616

17+
from datetime import datetime
1718
from typing import Any
1819
from typing import Dict
1920
from typing import Iterator
@@ -145,7 +146,7 @@ def __init__(
145146
self._tags = {} # type: Dict[str, str]
146147
self._data = {} # type: Dict[str, Any]
147148
self._containing_transaction = containing_transaction
148-
self.start_timestamp = start_timestamp or datetime.utcnow()
149+
self.start_timestamp = start_timestamp or datetime_utcnow()
149150
try:
150151
# profiling depends on this value and requires that
151152
# it is measured in nanoseconds
@@ -469,7 +470,7 @@ def finish(self, hub=None, end_timestamp=None):
469470
microseconds=elapsed / 1000
470471
)
471472
except AttributeError:
472-
self.timestamp = datetime.utcnow()
473+
self.timestamp = datetime_utcnow()
473474

474475
maybe_create_breadcrumbs_from_span(hub, self)
475476
return None

sentry_sdk/transport.py

+7-5
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,18 @@
66
import gzip
77
import time
88

9-
from datetime import datetime, timedelta
9+
from datetime import timedelta
1010
from collections import defaultdict
1111

1212
from sentry_sdk.utils import Dsn, logger, capture_internal_exceptions, json_dumps
1313
from sentry_sdk.worker import BackgroundWorker
1414
from sentry_sdk.envelope import Envelope, Item, PayloadRef
1515

16+
from sentry_sdk._compat import datetime_utcnow
1617
from sentry_sdk._types import TYPE_CHECKING
1718

1819
if TYPE_CHECKING:
20+
from datetime import datetime
1921
from typing import Any
2022
from typing import Callable
2123
from typing import Dict
@@ -122,7 +124,7 @@ def __del__(self):
122124
def _parse_rate_limits(header, now=None):
123125
# type: (Any, Optional[datetime]) -> Iterable[Tuple[DataCategory, datetime]]
124126
if now is None:
125-
now = datetime.utcnow()
127+
now = datetime_utcnow()
126128

127129
for limit in header.split(","):
128130
try:
@@ -209,7 +211,7 @@ def _update_rate_limits(self, response):
209211
# sentries if a proxy in front wants to globally slow things down.
210212
elif response.status == 429:
211213
logger.warning("Rate-limited via 429")
212-
self._disabled_until[None] = datetime.utcnow() + timedelta(
214+
self._disabled_until[None] = datetime_utcnow() + timedelta(
213215
seconds=self._retry.get_retry_after(response) or 60
214216
)
215217

@@ -316,13 +318,13 @@ def _check_disabled(self, category):
316318
def _disabled(bucket):
317319
# type: (Any) -> bool
318320
ts = self._disabled_until.get(bucket)
319-
return ts is not None and ts > datetime.utcnow()
321+
return ts is not None and ts > datetime_utcnow()
320322

321323
return _disabled(category) or _disabled(None)
322324

323325
def _is_rate_limited(self):
324326
# type: () -> bool
325-
return any(ts > datetime.utcnow() for ts in self._disabled_until.values())
327+
return any(ts > datetime_utcnow() for ts in self._disabled_until.values())
326328

327329
def _is_worker_full(self):
328330
# type: () -> bool

tests/test_transport.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from pytest_localserver.http import WSGIServer
1414

1515
from sentry_sdk import Hub, Client, add_breadcrumb, capture_message, Scope
16+
from sentry_sdk._compat import datetime_utcnow
1617
from sentry_sdk.transport import _parse_rate_limits
1718
from sentry_sdk.envelope import Envelope, parse_json
1819
from sentry_sdk.integrations.logging import LoggingIntegration
@@ -118,7 +119,7 @@ def test_transport_works(
118119
Hub.current.bind_client(client)
119120
request.addfinalizer(lambda: Hub.current.bind_client(None))
120121

121-
add_breadcrumb(level="info", message="i like bread", timestamp=datetime.utcnow())
122+
add_breadcrumb(level="info", message="i like bread", timestamp=datetime_utcnow())
122123
capture_message("löl")
123124

124125
getattr(client, client_flush_method)()

0 commit comments

Comments
 (0)