Skip to content

Commit bbc9559

Browse files
committed
deprecate extracting dates in message headers
adds Session.extract_header_dates config and JUPYTER_SESSION_EXTRACT_HEADER_DATES env default unchanged, but deprecated
1 parent a66bd11 commit bbc9559

File tree

3 files changed

+50
-7
lines changed

3 files changed

+50
-7
lines changed

jupyter_client/session.py

+37-2
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
Set,
4242
TraitError,
4343
Unicode,
44+
default,
4445
observe,
4546
)
4647
from traitlets.config.configurable import Configurable, LoggingConfigurable
@@ -420,6 +421,36 @@ def _session_changed(self, change: t.Any) -> None:
420421
"message.",
421422
)
422423

424+
extract_header_dates = Bool(
425+
True,
426+
config=True,
427+
help="""
428+
Parse timestamps in message headers to datetime objects.
429+
430+
If True, `date` and other timestamp fields
431+
will be `datetime.datetime` objects.
432+
If False, they will be ISO8601 strings.
433+
434+
Parsing has a performance cost and is deprecated,
435+
but kept as default for backward compatibility.
436+
""",
437+
)
438+
439+
@default("extract_header_dates")
440+
def _extract_header_dates_default(self):
441+
msg = """Session.extract_header_dates = True is deprecated in jupyter-client 8.6
442+
443+
set cfg.Session.extract_header_dates = False
444+
or JUPYTER_SESSION_EXTRACT_HEADER_DATES=0
445+
to avoid this message.
446+
"""
447+
env_value = os.environ.get("JUPYTER_SESSION_EXTRACT_HEADER_DATES", "") != "0"
448+
if env_value:
449+
warnings.warn(msg, DeprecationWarning, stacklevel=2)
450+
return True
451+
else:
452+
return False
453+
423454
# if 0, no adapting to do.
424455
adapt_version = Integer(0)
425456

@@ -1076,10 +1107,14 @@ def deserialize(
10761107
msg = "malformed message, must have at least %i elements" % minlen
10771108
raise TypeError(msg)
10781109
header = self.unpack(msg_list[1])
1079-
message["header"] = extract_dates(header)
1110+
parent_header = self.unpack(msg_list[2])
1111+
if self.extract_header_dates:
1112+
header = extract_dates(header)
1113+
parent_header = extract_dates(parent_header)
1114+
message["header"] = header
10801115
message["msg_id"] = header["msg_id"]
10811116
message["msg_type"] = header["msg_type"]
1082-
message["parent_header"] = extract_dates(self.unpack(msg_list[2]))
1117+
message["parent_header"] = parent_header
10831118
message["metadata"] = self.unpack(msg_list[3])
10841119
if content:
10851120
message["content"] = self.unpack(msg_list[4])

pyproject.toml

+2
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,8 @@ filterwarnings= [
133133
# from python-dateutil
134134
"ignore:datetime.datetime.utcfromtimestamp:DeprecationWarning",
135135
"ignore:datetime.datetime.utcnow:DeprecationWarning",
136+
# ignore header dates warning
137+
"ignore:.*extract_header_dates.*:DeprecationWarning",
136138
]
137139

138140
[tool.coverage.report]

tests/test_session.py

+11-5
Original file line numberDiff line numberDiff line change
@@ -411,18 +411,24 @@ def _datetime_test(self, session):
411411
msg = session.msg("msg", content=content, metadata=metadata, parent=p["header"])
412412
smsg = session.serialize(msg)
413413
msg2 = session.deserialize(session.feed_identities(smsg)[1])
414-
assert isinstance(msg2["header"]["date"], datetime)
415-
self.assertEqual(msg["header"], msg2["header"])
416-
self.assertEqual(msg["parent_header"], msg2["parent_header"])
417-
self.assertEqual(msg["parent_header"], msg2["parent_header"])
414+
if session.extract_header_dates:
415+
date_type = datetime
416+
else:
417+
date_type = str
418+
assert isinstance(msg2["header"]["date"], date_type)
419+
assert isinstance(msg2["parent_header"]["date"], date_type)
420+
self.assertEqual(msg["header"], jsonutil.extract_dates(msg2["header"]))
421+
self.assertEqual(msg["parent_header"], jsonutil.extract_dates(msg2["parent_header"]))
418422
assert isinstance(msg["content"]["t"], datetime)
419423
assert isinstance(msg["metadata"]["t"], datetime)
420424
assert isinstance(msg2["content"]["t"], str)
421425
assert isinstance(msg2["metadata"]["t"], str)
422426
self.assertEqual(msg["content"], jsonutil.extract_dates(msg2["content"]))
423427
self.assertEqual(msg["content"], jsonutil.extract_dates(msg2["content"]))
424428

425-
def test_datetimes(self, session):
429+
@pytest.mark.parametrize("extract_header_dates", [True, False])
430+
def test_datetimes(self, session, extract_header_dates):
431+
session.extract_header_dates = extract_header_dates
426432
self._datetime_test(session)
427433

428434
def test_datetimes_pickle(self):

0 commit comments

Comments
 (0)