Skip to content

Commit

Permalink
Fixed failing doctests on Python 3.7 due to changed repr of datetime.…
Browse files Browse the repository at this point in the history
…timedelta
  • Loading branch information
runfalk committed Jan 31, 2018
1 parent 9a75a85 commit 1bab1c5
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 1 deletion.
32 changes: 32 additions & 0 deletions spans/_compat.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
"""Compatibility module for python 3"""

import re
import sys

__all__ = [
"add_metaclass",
"fix_timedelta_repr",
"is_python2",
"iter_range",
"bstr",
Expand Down Expand Up @@ -62,3 +64,33 @@ def wrapper(cls):

return metaclass(cls.__name__, cls.__bases__, orig_vars)
return wrapper


def fix_timedelta_repr(func):
"""
Account repr change for timedelta in Python 3.7 and above in docstrings.
This is needed to make some doctests pass on Python 3.7 and above. This
change was introduced by `bpo-30302 <https://bugs.python.org/issue30302>`_
"""
# We don't need to do anything if we're not on 3.7 or above
if version < (3, 7):
return func

def fix_timedelta(match):
values = match.group(1).split(", ")
param_repr = ", ".join(
"{}={}".format(param, value)
for param, value in zip(("days", "seconds", "microseconds"), values)
if value != "0"
)

# If we have a zero length timedelta it should be represented as
# timedelta(0), i.e. without named parameters
if not param_repr:
param_repr = "0"

return "timedelta({})".format(param_repr)

func.__doc__ = re.sub(r"timedelta\(([^)]+)\)", fix_timedelta, func.__doc__)
return func
3 changes: 2 additions & 1 deletion spans/settypes.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from itertools import chain

from ._compat import add_metaclass
from ._compat import add_metaclass, fix_timedelta_repr
from ._utils import PartialOrderingMixin
from .types import Range
from .types import *
Expand Down Expand Up @@ -666,6 +666,7 @@ class datetimerangeset(RangeSet):
type = datetimerange


@fix_timedelta_repr
class timedeltarangeset(RangeSet):
"""
Range set that operates on :class:`~spans.types.timedeltarange`.
Expand Down
1 change: 1 addition & 0 deletions spans/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -1320,6 +1320,7 @@ class datetimerange(Range, OffsetableRangeMixin):
offset_type = timedelta


@fix_timedelta_repr
class timedeltarange(Range, OffsetableRangeMixin):
"""
Range that operates on datetime's timedelta class.
Expand Down
24 changes: 24 additions & 0 deletions tests/test_compat.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import pytest
import sys

from spans._compat import fix_timedelta_repr


@pytest.mark.parametrize("original, patched", [
("timedelta(0)", "timedelta(0)"),
("timedelta(1)", "timedelta(days=1)"),
("timedelta(2)", "timedelta(days=2)"),
("timedelta(1, 2, 3)", "timedelta(days=1, seconds=2, microseconds=3)"),
("timedelta(0, 1)", "timedelta(seconds=1)"),
("timedelta(0, 0, 1)", "timedelta(microseconds=1)"),
("foobar", "foobar"),
])
def test_timedelta_repr_fix(original, patched):
class Example(object):
__doc__ = original

if sys.version_info < (3, 7):
# Ensure that docstrings are left as they are on version 3.6 and below
assert fix_timedelta_repr(Example).__doc__ == original
else:
assert fix_timedelta_repr(Example).__doc__ == patched

0 comments on commit 1bab1c5

Please sign in to comment.