Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

deprecate extracting dates in message headers #1015

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 37 additions & 2 deletions jupyter_client/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
Set,
TraitError,
Unicode,
default,
observe,
)
from traitlets.config.configurable import Configurable, LoggingConfigurable
Expand Down Expand Up @@ -420,6 +421,36 @@ def _session_changed(self, change: t.Any) -> None:
"message.",
)

extract_header_dates = Bool(
True,
config=True,
help="""
Parse timestamps in message headers to datetime objects.

If True, `date` and other timestamp fields
will be `datetime.datetime` objects.
If False, they will be ISO8601 strings.

Parsing has a performance cost and is deprecated,
but kept as default for backward compatibility.
""",
)

@default("extract_header_dates")
def _extract_header_dates_default(self):
msg = """Session.extract_header_dates = True is deprecated in jupyter-client 8.6

set cfg.Session.extract_header_dates = False
or JUPYTER_SESSION_EXTRACT_HEADER_DATES=0
to avoid this message.
"""
env_value = os.environ.get("JUPYTER_SESSION_EXTRACT_HEADER_DATES", "") != "0"
if env_value:
warnings.warn(msg, DeprecationWarning, stacklevel=2)
return True
else:
return False

# if 0, no adapting to do.
adapt_version = Integer(0)

Expand Down Expand Up @@ -1076,10 +1107,14 @@ def deserialize(
msg = "malformed message, must have at least %i elements" % minlen
raise TypeError(msg)
header = self.unpack(msg_list[1])
message["header"] = extract_dates(header)
parent_header = self.unpack(msg_list[2])
if self.extract_header_dates:
header = extract_dates(header)
parent_header = extract_dates(parent_header)
message["header"] = header
message["msg_id"] = header["msg_id"]
message["msg_type"] = header["msg_type"]
message["parent_header"] = extract_dates(self.unpack(msg_list[2]))
message["parent_header"] = parent_header
message["metadata"] = self.unpack(msg_list[3])
if content:
message["content"] = self.unpack(msg_list[4])
Expand Down
2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ filterwarnings= [
# from python-dateutil
"ignore:datetime.datetime.utcfromtimestamp:DeprecationWarning",
"ignore:datetime.datetime.utcnow:DeprecationWarning",
# ignore header dates warning
"ignore:.*extract_header_dates.*:DeprecationWarning",
]

[tool.coverage.report]
Expand Down
16 changes: 11 additions & 5 deletions tests/test_session.py
Original file line number Diff line number Diff line change
Expand Up @@ -411,18 +411,24 @@ def _datetime_test(self, session):
msg = session.msg("msg", content=content, metadata=metadata, parent=p["header"])
smsg = session.serialize(msg)
msg2 = session.deserialize(session.feed_identities(smsg)[1])
assert isinstance(msg2["header"]["date"], datetime)
self.assertEqual(msg["header"], msg2["header"])
self.assertEqual(msg["parent_header"], msg2["parent_header"])
self.assertEqual(msg["parent_header"], msg2["parent_header"])
if session.extract_header_dates:
date_type = datetime
else:
date_type = str
assert isinstance(msg2["header"]["date"], date_type)
assert isinstance(msg2["parent_header"]["date"], date_type)
self.assertEqual(msg["header"], jsonutil.extract_dates(msg2["header"]))
self.assertEqual(msg["parent_header"], jsonutil.extract_dates(msg2["parent_header"]))
assert isinstance(msg["content"]["t"], datetime)
assert isinstance(msg["metadata"]["t"], datetime)
assert isinstance(msg2["content"]["t"], str)
assert isinstance(msg2["metadata"]["t"], str)
self.assertEqual(msg["content"], jsonutil.extract_dates(msg2["content"]))
self.assertEqual(msg["content"], jsonutil.extract_dates(msg2["content"]))

def test_datetimes(self, session):
@pytest.mark.parametrize("extract_header_dates", [True, False])
def test_datetimes(self, session, extract_header_dates):
session.extract_header_dates = extract_header_dates
self._datetime_test(session)

def test_datetimes_pickle(self):
Expand Down
Loading