crosshair-tool 0.0.56__cp39-cp39-macosx_11_0_arm64.whl → 0.0.100__cp39-cp39-macosx_11_0_arm64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- _crosshair_tracers.cpython-39-darwin.so +0 -0
- crosshair/__init__.py +1 -1
- crosshair/_mark_stacks.h +51 -24
- crosshair/_tracers.h +9 -5
- crosshair/_tracers_test.py +19 -9
- crosshair/auditwall.py +9 -8
- crosshair/auditwall_test.py +31 -19
- crosshair/codeconfig.py +3 -2
- crosshair/condition_parser.py +17 -133
- crosshair/condition_parser_test.py +54 -96
- crosshair/conftest.py +1 -1
- crosshair/copyext.py +91 -22
- crosshair/copyext_test.py +33 -0
- crosshair/core.py +259 -203
- crosshair/core_and_libs.py +20 -0
- crosshair/core_regestered_types_test.py +82 -0
- crosshair/core_test.py +693 -664
- crosshair/diff_behavior.py +76 -21
- crosshair/diff_behavior_test.py +132 -23
- crosshair/dynamic_typing.py +128 -18
- crosshair/dynamic_typing_test.py +91 -4
- crosshair/enforce.py +1 -6
- crosshair/enforce_test.py +15 -23
- crosshair/examples/check_examples_test.py +2 -1
- crosshair/fnutil.py +2 -3
- crosshair/fnutil_test.py +0 -7
- crosshair/fuzz_core_test.py +70 -83
- crosshair/libimpl/arraylib.py +10 -7
- crosshair/libimpl/binascii_ch_test.py +30 -0
- crosshair/libimpl/binascii_test.py +67 -0
- crosshair/libimpl/binasciilib.py +150 -0
- crosshair/libimpl/bisectlib_test.py +5 -5
- crosshair/libimpl/builtinslib.py +1002 -682
- crosshair/libimpl/builtinslib_ch_test.py +108 -30
- crosshair/libimpl/builtinslib_test.py +431 -143
- crosshair/libimpl/codecslib.py +22 -2
- crosshair/libimpl/codecslib_test.py +41 -9
- crosshair/libimpl/collectionslib.py +44 -8
- crosshair/libimpl/collectionslib_test.py +108 -20
- crosshair/libimpl/copylib.py +1 -1
- crosshair/libimpl/copylib_test.py +18 -0
- crosshair/libimpl/datetimelib.py +84 -67
- crosshair/libimpl/datetimelib_ch_test.py +12 -7
- crosshair/libimpl/datetimelib_test.py +5 -6
- crosshair/libimpl/decimallib.py +5257 -0
- crosshair/libimpl/decimallib_ch_test.py +78 -0
- crosshair/libimpl/decimallib_test.py +76 -0
- crosshair/libimpl/encodings/_encutil.py +21 -11
- crosshair/libimpl/fractionlib.py +16 -0
- crosshair/libimpl/fractionlib_test.py +80 -0
- crosshair/libimpl/functoolslib.py +19 -7
- crosshair/libimpl/functoolslib_test.py +22 -6
- crosshair/libimpl/hashliblib.py +30 -0
- crosshair/libimpl/hashliblib_test.py +18 -0
- crosshair/libimpl/heapqlib.py +32 -5
- crosshair/libimpl/heapqlib_test.py +15 -12
- crosshair/libimpl/iolib.py +7 -4
- crosshair/libimpl/ipaddresslib.py +8 -0
- crosshair/libimpl/itertoolslib_test.py +1 -1
- crosshair/libimpl/mathlib.py +165 -2
- crosshair/libimpl/mathlib_ch_test.py +44 -0
- crosshair/libimpl/mathlib_test.py +59 -16
- crosshair/libimpl/oslib.py +7 -0
- crosshair/libimpl/pathliblib_test.py +10 -0
- crosshair/libimpl/randomlib.py +1 -0
- crosshair/libimpl/randomlib_test.py +6 -4
- crosshair/libimpl/relib.py +180 -59
- crosshair/libimpl/relib_ch_test.py +26 -2
- crosshair/libimpl/relib_test.py +77 -14
- crosshair/libimpl/timelib.py +35 -13
- crosshair/libimpl/timelib_test.py +13 -3
- crosshair/libimpl/typeslib.py +15 -0
- crosshair/libimpl/typeslib_test.py +36 -0
- crosshair/libimpl/unicodedatalib_test.py +3 -3
- crosshair/libimpl/weakreflib.py +13 -0
- crosshair/libimpl/weakreflib_test.py +69 -0
- crosshair/libimpl/zliblib.py +15 -0
- crosshair/libimpl/zliblib_test.py +13 -0
- crosshair/lsp_server.py +21 -10
- crosshair/main.py +48 -28
- crosshair/main_test.py +59 -14
- crosshair/objectproxy.py +39 -14
- crosshair/objectproxy_test.py +27 -13
- crosshair/opcode_intercept.py +212 -24
- crosshair/opcode_intercept_test.py +172 -18
- crosshair/options.py +0 -1
- crosshair/patch_equivalence_test.py +5 -21
- crosshair/path_cover.py +7 -5
- crosshair/path_search.py +6 -4
- crosshair/path_search_test.py +1 -2
- crosshair/pathing_oracle.py +53 -10
- crosshair/pathing_oracle_test.py +21 -0
- crosshair/pure_importer_test.py +5 -21
- crosshair/register_contract.py +16 -6
- crosshair/register_contract_test.py +2 -14
- crosshair/simplestructs.py +154 -85
- crosshair/simplestructs_test.py +16 -2
- crosshair/smtlib.py +24 -0
- crosshair/smtlib_test.py +14 -0
- crosshair/statespace.py +319 -196
- crosshair/statespace_test.py +45 -0
- crosshair/stubs_parser.py +0 -2
- crosshair/test_util.py +87 -25
- crosshair/test_util_test.py +26 -0
- crosshair/tools/check_init_and_setup_coincide.py +0 -3
- crosshair/tools/generate_demo_table.py +2 -2
- crosshair/tracers.py +141 -49
- crosshair/type_repo.py +11 -4
- crosshair/unicode_categories.py +1 -0
- crosshair/util.py +158 -76
- crosshair/util_test.py +13 -20
- crosshair/watcher.py +4 -4
- crosshair/z3util.py +1 -1
- {crosshair_tool-0.0.56.dist-info → crosshair_tool-0.0.100.dist-info}/METADATA +45 -36
- crosshair_tool-0.0.100.dist-info/RECORD +176 -0
- {crosshair_tool-0.0.56.dist-info → crosshair_tool-0.0.100.dist-info}/WHEEL +2 -1
- crosshair/examples/hypothesis/__init__.py +0 -2
- crosshair/examples/hypothesis/bugs_detected/simple_strategies.py +0 -74
- crosshair_tool-0.0.56.dist-info/RECORD +0 -152
- /crosshair/{examples/hypothesis/bugs_detected/__init__.py → py.typed} +0 -0
- {crosshair_tool-0.0.56.dist-info → crosshair_tool-0.0.100.dist-info}/entry_points.txt +0 -0
- {crosshair_tool-0.0.56.dist-info → crosshair_tool-0.0.100.dist-info/licenses}/LICENSE +0 -0
- {crosshair_tool-0.0.56.dist-info → crosshair_tool-0.0.100.dist-info}/top_level.txt +0 -0
crosshair/libimpl/datetimelib.py
CHANGED
|
@@ -65,7 +65,7 @@ def _is_leap(year):
|
|
|
65
65
|
return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0)
|
|
66
66
|
|
|
67
67
|
|
|
68
|
-
import z3
|
|
68
|
+
import z3 # type: ignore
|
|
69
69
|
|
|
70
70
|
|
|
71
71
|
def _smt_is_leap(smt_year):
|
|
@@ -440,7 +440,7 @@ def _check_utc_offset(name, offset):
|
|
|
440
440
|
assert name in ("utcoffset", "dst")
|
|
441
441
|
if offset is None:
|
|
442
442
|
return
|
|
443
|
-
if not isinstance(offset,
|
|
443
|
+
if not isinstance(offset, any_timedelta):
|
|
444
444
|
raise TypeError(
|
|
445
445
|
"tzinfo.%s() must return None "
|
|
446
446
|
"or timedelta, not '%s'" % (name, type(offset))
|
|
@@ -486,7 +486,7 @@ def _check_time_fields(hour, minute, second, microsecond, fold):
|
|
|
486
486
|
|
|
487
487
|
|
|
488
488
|
def _check_tzinfo_arg(tz):
|
|
489
|
-
if tz is not None and not isinstance(tz,
|
|
489
|
+
if tz is not None and not isinstance(tz, any_tzinfo):
|
|
490
490
|
raise TypeError("tzinfo argument must be None or of a tzinfo subclass")
|
|
491
491
|
|
|
492
492
|
|
|
@@ -627,9 +627,7 @@ class timedelta:
|
|
|
627
627
|
|
|
628
628
|
def total_seconds(self):
|
|
629
629
|
"""Total seconds in the duration."""
|
|
630
|
-
return (
|
|
631
|
-
(self.days * 86400 + self.seconds) * 10**6 + self.microseconds
|
|
632
|
-
) / 10**6
|
|
630
|
+
return ((self.days * 86400 + self.seconds) * 10**6 + self.microseconds) / 10**6
|
|
633
631
|
|
|
634
632
|
# Read-only field accessors
|
|
635
633
|
@property
|
|
@@ -648,7 +646,7 @@ class timedelta:
|
|
|
648
646
|
return self._microseconds
|
|
649
647
|
|
|
650
648
|
def __add__(self, other):
|
|
651
|
-
if isinstance(other,
|
|
649
|
+
if isinstance(other, any_timedelta):
|
|
652
650
|
# for CPython compatibility, we cannot use
|
|
653
651
|
# our __class__ here, but need a real timedelta
|
|
654
652
|
return timedelta(
|
|
@@ -656,16 +654,16 @@ class timedelta:
|
|
|
656
654
|
self._seconds + other.seconds,
|
|
657
655
|
self._microseconds + other.microseconds,
|
|
658
656
|
)
|
|
659
|
-
elif isinstance(other,
|
|
657
|
+
elif isinstance(other, any_datetime):
|
|
660
658
|
return datetime.fromdatetime(other).__add__(self)
|
|
661
|
-
elif isinstance(other,
|
|
659
|
+
elif isinstance(other, any_date):
|
|
662
660
|
return date.fromdate(other).__add__(self)
|
|
663
661
|
return NotImplemented
|
|
664
662
|
|
|
665
663
|
__radd__ = __add__
|
|
666
664
|
|
|
667
665
|
def __sub__(self, other):
|
|
668
|
-
if isinstance(other,
|
|
666
|
+
if isinstance(other, any_timedelta):
|
|
669
667
|
# for CPython compatibility, we cannot use
|
|
670
668
|
# our __class__ here, but need a real timedelta
|
|
671
669
|
return timedelta(
|
|
@@ -673,14 +671,14 @@ class timedelta:
|
|
|
673
671
|
self._seconds - other.seconds,
|
|
674
672
|
self._microseconds - other.microseconds,
|
|
675
673
|
)
|
|
676
|
-
elif isinstance(other,
|
|
674
|
+
elif isinstance(other, any_date):
|
|
677
675
|
return date.fromdate(other).__add__(self)
|
|
678
|
-
elif isinstance(other,
|
|
676
|
+
elif isinstance(other, any_datetime):
|
|
679
677
|
return datetime.fromdatetime(other).__add__(self)
|
|
680
678
|
return NotImplemented
|
|
681
679
|
|
|
682
680
|
def __rsub__(self, other):
|
|
683
|
-
if isinstance(other,
|
|
681
|
+
if isinstance(other, any_timedelta):
|
|
684
682
|
return -self + other
|
|
685
683
|
return NotImplemented
|
|
686
684
|
|
|
@@ -714,19 +712,19 @@ class timedelta:
|
|
|
714
712
|
__rmul__ = __mul__
|
|
715
713
|
|
|
716
714
|
def __floordiv__(self, other):
|
|
717
|
-
if not isinstance(other, (int,
|
|
715
|
+
if not isinstance(other, (int, any_timedelta)):
|
|
718
716
|
return NotImplemented
|
|
719
717
|
usec = _timedelta_to_microseconds(self)
|
|
720
|
-
if isinstance(other,
|
|
718
|
+
if isinstance(other, any_timedelta):
|
|
721
719
|
return usec // _timedelta_to_microseconds(other)
|
|
722
720
|
if isinstance(other, int):
|
|
723
721
|
return timedelta(0, 0, usec // other)
|
|
724
722
|
|
|
725
723
|
def __truediv__(self, other):
|
|
726
|
-
if not isinstance(other, (int, float,
|
|
724
|
+
if not isinstance(other, (int, float, any_timedelta)):
|
|
727
725
|
return NotImplemented
|
|
728
726
|
usec = _timedelta_to_microseconds(self)
|
|
729
|
-
if isinstance(other,
|
|
727
|
+
if isinstance(other, any_timedelta):
|
|
730
728
|
return usec / _timedelta_to_microseconds(other)
|
|
731
729
|
if isinstance(other, int):
|
|
732
730
|
return timedelta(0, 0, _divide_and_round(usec, other))
|
|
@@ -735,13 +733,13 @@ class timedelta:
|
|
|
735
733
|
return timedelta(0, 0, _divide_and_round(b * usec, a))
|
|
736
734
|
|
|
737
735
|
def __mod__(self, other):
|
|
738
|
-
if isinstance(other,
|
|
736
|
+
if isinstance(other, any_timedelta):
|
|
739
737
|
r = _timedelta_to_microseconds(self) % _timedelta_to_microseconds(other)
|
|
740
738
|
return timedelta(0, 0, r)
|
|
741
739
|
return NotImplemented
|
|
742
740
|
|
|
743
741
|
def __divmod__(self, other):
|
|
744
|
-
if isinstance(other,
|
|
742
|
+
if isinstance(other, any_timedelta):
|
|
745
743
|
q, r = divmod(
|
|
746
744
|
_timedelta_to_microseconds(self), _timedelta_to_microseconds(other)
|
|
747
745
|
)
|
|
@@ -751,37 +749,37 @@ class timedelta:
|
|
|
751
749
|
# Comparisons of timedelta objects with other.
|
|
752
750
|
|
|
753
751
|
def __eq__(self, other):
|
|
754
|
-
if isinstance(other,
|
|
752
|
+
if isinstance(other, any_timedelta):
|
|
755
753
|
return self._cmp(other) == 0
|
|
756
754
|
else:
|
|
757
755
|
return NotImplemented
|
|
758
756
|
|
|
759
757
|
def __le__(self, other):
|
|
760
|
-
if isinstance(other,
|
|
758
|
+
if isinstance(other, any_timedelta):
|
|
761
759
|
return self._cmp(other) <= 0
|
|
762
760
|
else:
|
|
763
761
|
return NotImplemented
|
|
764
762
|
|
|
765
763
|
def __lt__(self, other):
|
|
766
|
-
if isinstance(other,
|
|
764
|
+
if isinstance(other, any_timedelta):
|
|
767
765
|
return self._cmp(other) < 0
|
|
768
766
|
else:
|
|
769
767
|
return NotImplemented
|
|
770
768
|
|
|
771
769
|
def __ge__(self, other):
|
|
772
|
-
if isinstance(other,
|
|
770
|
+
if isinstance(other, any_timedelta):
|
|
773
771
|
return self._cmp(other) >= 0
|
|
774
772
|
else:
|
|
775
773
|
return NotImplemented
|
|
776
774
|
|
|
777
775
|
def __gt__(self, other):
|
|
778
|
-
if isinstance(other,
|
|
776
|
+
if isinstance(other, any_timedelta):
|
|
779
777
|
return self._cmp(other) > 0
|
|
780
778
|
else:
|
|
781
779
|
return NotImplemented
|
|
782
780
|
|
|
783
781
|
def _cmp(self, other):
|
|
784
|
-
assert isinstance(other,
|
|
782
|
+
assert isinstance(other, any_timedelta)
|
|
785
783
|
return _cmp(_timedelta_getstate(self), _timedelta_getstate(other))
|
|
786
784
|
|
|
787
785
|
def __hash__(self):
|
|
@@ -811,6 +809,8 @@ class timedelta:
|
|
|
811
809
|
return real_timedelta
|
|
812
810
|
|
|
813
811
|
|
|
812
|
+
any_timedelta = (timedelta, real_timedelta)
|
|
813
|
+
|
|
814
814
|
timedelta.min = timedelta(-999999999) # type: ignore
|
|
815
815
|
timedelta.max = timedelta( # type: ignore
|
|
816
816
|
days=999999999, hours=23, minutes=59, seconds=59, microseconds=999999
|
|
@@ -855,7 +855,7 @@ class date:
|
|
|
855
855
|
|
|
856
856
|
"""
|
|
857
857
|
|
|
858
|
-
def __init__(self, year, month, day):
|
|
858
|
+
def __init__(self, year, month=None, day=None):
|
|
859
859
|
"""
|
|
860
860
|
Constructor.
|
|
861
861
|
|
|
@@ -863,7 +863,13 @@ class date:
|
|
|
863
863
|
:param month: month, starting at 1
|
|
864
864
|
:param day: day, starting at 1
|
|
865
865
|
"""
|
|
866
|
-
|
|
866
|
+
if month is None:
|
|
867
|
+
# We can receive a string/bytes single argument when unpickling a concrete date
|
|
868
|
+
with NoTracing():
|
|
869
|
+
dt = real_date(realize(year)) # type: ignore
|
|
870
|
+
year, month, day = dt.year, dt.month, dt.day
|
|
871
|
+
else:
|
|
872
|
+
year, month, day = _check_date_fields(year, month, day)
|
|
867
873
|
self._year = year
|
|
868
874
|
self._month = month
|
|
869
875
|
self._day = day
|
|
@@ -1044,32 +1050,32 @@ class date:
|
|
|
1044
1050
|
# Comparisons of date objects with other.
|
|
1045
1051
|
|
|
1046
1052
|
def __eq__(self, other):
|
|
1047
|
-
if isinstance(other,
|
|
1053
|
+
if isinstance(other, any_date):
|
|
1048
1054
|
return self._cmp(other) == 0
|
|
1049
1055
|
return NotImplemented
|
|
1050
1056
|
|
|
1051
1057
|
def __le__(self, other):
|
|
1052
|
-
if isinstance(other,
|
|
1058
|
+
if isinstance(other, any_date):
|
|
1053
1059
|
return self._cmp(other) <= 0
|
|
1054
1060
|
return NotImplemented
|
|
1055
1061
|
|
|
1056
1062
|
def __lt__(self, other):
|
|
1057
|
-
if isinstance(other,
|
|
1063
|
+
if isinstance(other, any_date):
|
|
1058
1064
|
return self._cmp(other) < 0
|
|
1059
1065
|
return NotImplemented
|
|
1060
1066
|
|
|
1061
1067
|
def __ge__(self, other):
|
|
1062
|
-
if isinstance(other,
|
|
1068
|
+
if isinstance(other, any_date):
|
|
1063
1069
|
return self._cmp(other) >= 0
|
|
1064
1070
|
return NotImplemented
|
|
1065
1071
|
|
|
1066
1072
|
def __gt__(self, other):
|
|
1067
|
-
if isinstance(other,
|
|
1073
|
+
if isinstance(other, any_date):
|
|
1068
1074
|
return self._cmp(other) > 0
|
|
1069
1075
|
return NotImplemented
|
|
1070
1076
|
|
|
1071
1077
|
def _cmp(self, other):
|
|
1072
|
-
assert isinstance(other,
|
|
1078
|
+
assert isinstance(other, any_date)
|
|
1073
1079
|
y, m, d = self._year, self._month, self._day
|
|
1074
1080
|
y2, m2, d2 = other.year, other.month, other.day
|
|
1075
1081
|
return _cmp((y, m, d), (y2, m2, d2))
|
|
@@ -1083,7 +1089,7 @@ class date:
|
|
|
1083
1089
|
|
|
1084
1090
|
def __add__(self, other):
|
|
1085
1091
|
"""Add a date to a timedelta."""
|
|
1086
|
-
if isinstance(other,
|
|
1092
|
+
if isinstance(other, any_timedelta):
|
|
1087
1093
|
o = self.toordinal() + other.days
|
|
1088
1094
|
if 0 < o <= _MAXORDINAL:
|
|
1089
1095
|
return date.fromordinal(o)
|
|
@@ -1094,9 +1100,9 @@ class date:
|
|
|
1094
1100
|
|
|
1095
1101
|
def __sub__(self, other):
|
|
1096
1102
|
"""Subtract two dates, or a date and a timedelta."""
|
|
1097
|
-
if isinstance(other,
|
|
1103
|
+
if isinstance(other, any_timedelta):
|
|
1098
1104
|
return self + timedelta(-other.days)
|
|
1099
|
-
if isinstance(other,
|
|
1105
|
+
if isinstance(other, any_date):
|
|
1100
1106
|
days1 = self.toordinal()
|
|
1101
1107
|
days2 = other.toordinal()
|
|
1102
1108
|
return timedelta(days1 - days2)
|
|
@@ -1149,6 +1155,8 @@ class date:
|
|
|
1149
1155
|
return real_date
|
|
1150
1156
|
|
|
1151
1157
|
|
|
1158
|
+
any_date = (date, real_date)
|
|
1159
|
+
|
|
1152
1160
|
_date_class = date # so functions w/ args named "date" can get at the class
|
|
1153
1161
|
|
|
1154
1162
|
date.min = date(1, 1, 1) # type: ignore
|
|
@@ -1182,7 +1190,7 @@ class tzinfo:
|
|
|
1182
1190
|
|
|
1183
1191
|
def fromutc(self, dt):
|
|
1184
1192
|
"""datetime in UTC -> datetime in local time."""
|
|
1185
|
-
if not isinstance(dt,
|
|
1193
|
+
if not isinstance(dt, any_datetime):
|
|
1186
1194
|
raise TypeError("fromutc() requires a datetime argument")
|
|
1187
1195
|
if dt.tzinfo is not self:
|
|
1188
1196
|
raise ValueError("dt.tzinfo is not self")
|
|
@@ -1226,6 +1234,9 @@ class tzinfo:
|
|
|
1226
1234
|
return real_tzinfo
|
|
1227
1235
|
|
|
1228
1236
|
|
|
1237
|
+
any_tzinfo = (tzinfo, real_tzinfo)
|
|
1238
|
+
|
|
1239
|
+
|
|
1229
1240
|
class IsoCalendarDate(tuple):
|
|
1230
1241
|
def __new__(cls, year, week, weekday):
|
|
1231
1242
|
return super().__new__(cls, (year, week, weekday))
|
|
@@ -1339,37 +1350,37 @@ class time:
|
|
|
1339
1350
|
# Comparisons of time objects with other.
|
|
1340
1351
|
|
|
1341
1352
|
def __eq__(self, other):
|
|
1342
|
-
if isinstance(other,
|
|
1353
|
+
if isinstance(other, any_time):
|
|
1343
1354
|
return self._cmp(other, allow_mixed=True) == 0
|
|
1344
1355
|
else:
|
|
1345
1356
|
return NotImplemented
|
|
1346
1357
|
|
|
1347
1358
|
def __le__(self, other):
|
|
1348
|
-
if isinstance(other,
|
|
1359
|
+
if isinstance(other, any_time):
|
|
1349
1360
|
return self._cmp(other) <= 0
|
|
1350
1361
|
else:
|
|
1351
1362
|
return NotImplemented
|
|
1352
1363
|
|
|
1353
1364
|
def __lt__(self, other):
|
|
1354
|
-
if isinstance(other,
|
|
1365
|
+
if isinstance(other, any_time):
|
|
1355
1366
|
return self._cmp(other) < 0
|
|
1356
1367
|
else:
|
|
1357
1368
|
return NotImplemented
|
|
1358
1369
|
|
|
1359
1370
|
def __ge__(self, other):
|
|
1360
|
-
if isinstance(other,
|
|
1371
|
+
if isinstance(other, any_time):
|
|
1361
1372
|
return self._cmp(other) >= 0
|
|
1362
1373
|
else:
|
|
1363
1374
|
return NotImplemented
|
|
1364
1375
|
|
|
1365
1376
|
def __gt__(self, other):
|
|
1366
|
-
if isinstance(other,
|
|
1377
|
+
if isinstance(other, any_time):
|
|
1367
1378
|
return self._cmp(other) > 0
|
|
1368
1379
|
else:
|
|
1369
1380
|
return NotImplemented
|
|
1370
1381
|
|
|
1371
1382
|
def _cmp(self, other, allow_mixed=False):
|
|
1372
|
-
assert isinstance(other,
|
|
1383
|
+
assert isinstance(other, any_time)
|
|
1373
1384
|
mytz = self._tzinfo
|
|
1374
1385
|
ottz = other.tzinfo
|
|
1375
1386
|
myoff = otoff = None
|
|
@@ -1582,6 +1593,8 @@ class time:
|
|
|
1582
1593
|
return real_time
|
|
1583
1594
|
|
|
1584
1595
|
|
|
1596
|
+
any_time = (time, real_time)
|
|
1597
|
+
|
|
1585
1598
|
_time_class = time # so functions w/ args named "time" can get at the class
|
|
1586
1599
|
|
|
1587
1600
|
time.min = time(0, 0, 0) # type: ignore
|
|
@@ -1741,9 +1754,9 @@ class datetime(date):
|
|
|
1741
1754
|
@classmethod
|
|
1742
1755
|
def combine(cls, date, time, tzinfo=True):
|
|
1743
1756
|
"""Construct a datetime from a given date and a given time."""
|
|
1744
|
-
if not isinstance(date,
|
|
1757
|
+
if not isinstance(date, any_date):
|
|
1745
1758
|
raise TypeError("date argument must be a date instance")
|
|
1746
|
-
if not isinstance(time,
|
|
1759
|
+
if not isinstance(time, any_time):
|
|
1747
1760
|
raise TypeError("time argument must be a time instance")
|
|
1748
1761
|
if tzinfo is True:
|
|
1749
1762
|
tzinfo = time.tzinfo
|
|
@@ -1935,7 +1948,7 @@ class datetime(date):
|
|
|
1935
1948
|
def astimezone(self, tz=None):
|
|
1936
1949
|
if tz is None:
|
|
1937
1950
|
tz = self._local_timezone()
|
|
1938
|
-
elif not isinstance(tz,
|
|
1951
|
+
elif not isinstance(tz, any_tzinfo):
|
|
1939
1952
|
raise TypeError("tz argument must be an instance of tzinfo")
|
|
1940
1953
|
|
|
1941
1954
|
mytz = self.tzinfo
|
|
@@ -2046,7 +2059,7 @@ class datetime(date):
|
|
|
2046
2059
|
|
|
2047
2060
|
def _realized_if_concrete_tzinfo(self):
|
|
2048
2061
|
with NoTracing():
|
|
2049
|
-
if isinstance(self._tzinfo,
|
|
2062
|
+
if isinstance(self._tzinfo, any_tzinfo):
|
|
2050
2063
|
return realize(self)
|
|
2051
2064
|
return self
|
|
2052
2065
|
|
|
@@ -2094,47 +2107,47 @@ class datetime(date):
|
|
|
2094
2107
|
# Comparisons of datetime objects with other.
|
|
2095
2108
|
|
|
2096
2109
|
def __eq__(self, other):
|
|
2097
|
-
if isinstance(other,
|
|
2110
|
+
if isinstance(other, any_datetime):
|
|
2098
2111
|
return self._cmp(other, allow_mixed=True) == 0
|
|
2099
|
-
elif not isinstance(other,
|
|
2112
|
+
elif not isinstance(other, any_date):
|
|
2100
2113
|
return NotImplemented
|
|
2101
2114
|
else:
|
|
2102
2115
|
return False
|
|
2103
2116
|
|
|
2104
2117
|
def __le__(self, other):
|
|
2105
|
-
if isinstance(other,
|
|
2118
|
+
if isinstance(other, any_datetime):
|
|
2106
2119
|
return self._cmp(other) <= 0
|
|
2107
|
-
elif not isinstance(other,
|
|
2120
|
+
elif not isinstance(other, any_date):
|
|
2108
2121
|
return NotImplemented
|
|
2109
2122
|
else:
|
|
2110
2123
|
_cmperror(self, other)
|
|
2111
2124
|
|
|
2112
2125
|
def __lt__(self, other):
|
|
2113
|
-
if isinstance(other,
|
|
2126
|
+
if isinstance(other, any_datetime):
|
|
2114
2127
|
return self._cmp(other) < 0
|
|
2115
|
-
elif not isinstance(other,
|
|
2128
|
+
elif not isinstance(other, any_date):
|
|
2116
2129
|
return NotImplemented
|
|
2117
2130
|
else:
|
|
2118
2131
|
_cmperror(self, other)
|
|
2119
2132
|
|
|
2120
2133
|
def __ge__(self, other):
|
|
2121
|
-
if isinstance(other,
|
|
2134
|
+
if isinstance(other, any_datetime):
|
|
2122
2135
|
return self._cmp(other) >= 0
|
|
2123
|
-
elif not isinstance(other,
|
|
2136
|
+
elif not isinstance(other, any_date):
|
|
2124
2137
|
return NotImplemented
|
|
2125
2138
|
else:
|
|
2126
2139
|
_cmperror(self, other)
|
|
2127
2140
|
|
|
2128
2141
|
def __gt__(self, other):
|
|
2129
|
-
if isinstance(other,
|
|
2142
|
+
if isinstance(other, any_datetime):
|
|
2130
2143
|
return self._cmp(other) > 0
|
|
2131
|
-
elif not isinstance(other,
|
|
2144
|
+
elif not isinstance(other, any_date):
|
|
2132
2145
|
return NotImplemented
|
|
2133
2146
|
else:
|
|
2134
2147
|
_cmperror(self, other)
|
|
2135
2148
|
|
|
2136
2149
|
def _cmp(self, other, allow_mixed=False):
|
|
2137
|
-
assert isinstance(other,
|
|
2150
|
+
assert isinstance(other, any_datetime)
|
|
2138
2151
|
mytz = self._tzinfo
|
|
2139
2152
|
ottz = other.tzinfo
|
|
2140
2153
|
myoff = otoff = None
|
|
@@ -2186,7 +2199,7 @@ class datetime(date):
|
|
|
2186
2199
|
|
|
2187
2200
|
def __add__(self, other):
|
|
2188
2201
|
"""Add a datetime and a timedelta."""
|
|
2189
|
-
if not isinstance(other,
|
|
2202
|
+
if not isinstance(other, any_timedelta):
|
|
2190
2203
|
return NotImplemented
|
|
2191
2204
|
delta = timedelta(
|
|
2192
2205
|
self.toordinal(),
|
|
@@ -2209,8 +2222,8 @@ class datetime(date):
|
|
|
2209
2222
|
|
|
2210
2223
|
def __sub__(self, other):
|
|
2211
2224
|
"""Subtract two datetimes, or a datetime and a timedelta."""
|
|
2212
|
-
if not isinstance(other,
|
|
2213
|
-
if isinstance(other,
|
|
2225
|
+
if not isinstance(other, any_datetime):
|
|
2226
|
+
if isinstance(other, any_timedelta):
|
|
2214
2227
|
return self + -other
|
|
2215
2228
|
return NotImplemented
|
|
2216
2229
|
|
|
@@ -2265,6 +2278,8 @@ class datetime(date):
|
|
|
2265
2278
|
return real_datetime
|
|
2266
2279
|
|
|
2267
2280
|
|
|
2281
|
+
any_datetime = (datetime, real_datetime)
|
|
2282
|
+
|
|
2268
2283
|
datetime.min = datetime(1, 1, 1) # type: ignore
|
|
2269
2284
|
datetime.max = datetime(9999, 12, 31, 23, 59, 59, 999999) # type: ignore
|
|
2270
2285
|
datetime.resolution = timedelta(microseconds=1) # type: ignore
|
|
@@ -2289,7 +2304,7 @@ class timezone(tzinfo):
|
|
|
2289
2304
|
_Omitted = Omitted.value
|
|
2290
2305
|
|
|
2291
2306
|
def __new__(cls, offset: real_timedelta, name: Union[str, Omitted] = _Omitted):
|
|
2292
|
-
if not isinstance(offset,
|
|
2307
|
+
if not isinstance(offset, any_timedelta):
|
|
2293
2308
|
raise TypeError("offset must be a timedelta")
|
|
2294
2309
|
if name == cls._Omitted:
|
|
2295
2310
|
if not offset:
|
|
@@ -2319,7 +2334,7 @@ class timezone(tzinfo):
|
|
|
2319
2334
|
return (self._offset, self._name)
|
|
2320
2335
|
|
|
2321
2336
|
def __eq__(self, other):
|
|
2322
|
-
if isinstance(other,
|
|
2337
|
+
if isinstance(other, any_timezone):
|
|
2323
2338
|
return self.utcoffset(None) == other.utcoffset(None)
|
|
2324
2339
|
return NotImplemented
|
|
2325
2340
|
|
|
@@ -2346,24 +2361,24 @@ class timezone(tzinfo):
|
|
|
2346
2361
|
return self.tzname(None)
|
|
2347
2362
|
|
|
2348
2363
|
def utcoffset(self, dt):
|
|
2349
|
-
if isinstance(dt,
|
|
2364
|
+
if isinstance(dt, any_datetime) or dt is None:
|
|
2350
2365
|
return self._offset
|
|
2351
2366
|
raise TypeError("utcoffset() argument must be a datetime instance" " or None")
|
|
2352
2367
|
|
|
2353
2368
|
def tzname(self, dt):
|
|
2354
|
-
if isinstance(dt,
|
|
2369
|
+
if isinstance(dt, any_datetime) or dt is None:
|
|
2355
2370
|
if self._name is None:
|
|
2356
2371
|
return self._name_from_offset(self._offset)
|
|
2357
2372
|
return self._name
|
|
2358
2373
|
raise TypeError("tzname() argument must be a datetime instance" " or None")
|
|
2359
2374
|
|
|
2360
2375
|
def dst(self, dt):
|
|
2361
|
-
if isinstance(dt,
|
|
2376
|
+
if isinstance(dt, any_datetime) or dt is None:
|
|
2362
2377
|
return None
|
|
2363
2378
|
raise TypeError("dst() argument must be a datetime instance" " or None")
|
|
2364
2379
|
|
|
2365
2380
|
def fromutc(self, dt):
|
|
2366
|
-
if isinstance(dt,
|
|
2381
|
+
if isinstance(dt, any_datetime):
|
|
2367
2382
|
if dt.tzinfo is not self:
|
|
2368
2383
|
raise ValueError("fromutc: dt.tzinfo " "is not self")
|
|
2369
2384
|
return dt + self._offset
|
|
@@ -2407,6 +2422,8 @@ class timezone(tzinfo):
|
|
|
2407
2422
|
return real_timezone
|
|
2408
2423
|
|
|
2409
2424
|
|
|
2425
|
+
any_timezone = (timezone, real_timezone)
|
|
2426
|
+
|
|
2410
2427
|
timezone.utc = timezone._create(timedelta(0)) # type: ignore
|
|
2411
2428
|
# bpo-37642: These attributes are rounded to the nearest minute for backwards
|
|
2412
2429
|
# compatibility, even though the constructor will accept a wider range of
|
|
@@ -6,7 +6,7 @@ from typing import Tuple, Union
|
|
|
6
6
|
import pytest # type: ignore
|
|
7
7
|
|
|
8
8
|
from crosshair.core_and_libs import MessageType, analyze_function, run_checkables
|
|
9
|
-
from crosshair.test_util import ResultComparison, compare_results
|
|
9
|
+
from crosshair.test_util import ResultComparison, compare_results, compare_returns
|
|
10
10
|
|
|
11
11
|
# crosshair: max_uninteresting_iterations=10
|
|
12
12
|
|
|
@@ -29,7 +29,7 @@ def check_datetimelib_lt(
|
|
|
29
29
|
Tuple[timedelta, timedelta],
|
|
30
30
|
Tuple[date, datetime],
|
|
31
31
|
Tuple[datetime, datetime],
|
|
32
|
-
]
|
|
32
|
+
],
|
|
33
33
|
) -> ResultComparison:
|
|
34
34
|
"""post: _"""
|
|
35
35
|
return compare_results(operator.lt, *p)
|
|
@@ -40,7 +40,7 @@ def check_datetimelib_add(
|
|
|
40
40
|
Tuple[timedelta, timedelta],
|
|
41
41
|
Tuple[date, timedelta],
|
|
42
42
|
Tuple[timedelta, datetime],
|
|
43
|
-
]
|
|
43
|
+
],
|
|
44
44
|
) -> ResultComparison:
|
|
45
45
|
"""post: _"""
|
|
46
46
|
return compare_results(operator.add, *p)
|
|
@@ -52,14 +52,14 @@ def check_datetimelib_subtract(
|
|
|
52
52
|
Tuple[date, timedelta],
|
|
53
53
|
Tuple[datetime, timedelta],
|
|
54
54
|
Tuple[datetime, datetime],
|
|
55
|
-
]
|
|
55
|
+
],
|
|
56
56
|
) -> ResultComparison:
|
|
57
57
|
"""post: _"""
|
|
58
58
|
return compare_results(operator.sub, *p)
|
|
59
59
|
|
|
60
60
|
|
|
61
61
|
def check_datetimelib_str(
|
|
62
|
-
obj: Union[timedelta, timezone, date, time, datetime]
|
|
62
|
+
obj: Union[timedelta, timezone, date, time, datetime],
|
|
63
63
|
) -> ResultComparison:
|
|
64
64
|
"""post: _"""
|
|
65
65
|
return compare_results(_invoker("__str__"), obj)
|
|
@@ -67,7 +67,7 @@ def check_datetimelib_str(
|
|
|
67
67
|
|
|
68
68
|
def check_datetimelib_repr(
|
|
69
69
|
# TODO: re-enable time, datetime repr checking after fixing in Python 3.11
|
|
70
|
-
obj: Union[timedelta, timezone, date]
|
|
70
|
+
obj: Union[timedelta, timezone, date],
|
|
71
71
|
) -> ResultComparison:
|
|
72
72
|
"""post: _"""
|
|
73
73
|
return compare_results(_invoker("__repr__"), obj)
|
|
@@ -87,7 +87,7 @@ def check_timedelta_new(
|
|
|
87
87
|
"""post: _"""
|
|
88
88
|
if days % 1 != 0 or secs % 1 != 0 or microsecs % 1 != 0:
|
|
89
89
|
pass
|
|
90
|
-
return
|
|
90
|
+
return compare_returns(lambda *a: timedelta(*a), days, secs, microsecs)
|
|
91
91
|
|
|
92
92
|
|
|
93
93
|
def check_timedelta_bool(td: timedelta) -> ResultComparison:
|
|
@@ -280,6 +280,11 @@ def check_datetime_ctime(dt: datetime) -> ResultComparison:
|
|
|
280
280
|
|
|
281
281
|
def check_datetime_strftime(dt: datetime, fmt: str) -> ResultComparison:
|
|
282
282
|
"""post: _"""
|
|
283
|
+
# not using skipIf because this is invoked via `test_builtin`:
|
|
284
|
+
if sys.version_info < (3, 13):
|
|
285
|
+
# strftime null character handling aligned between python and C
|
|
286
|
+
# implementations in https://github.com/python/cpython/pull/125657
|
|
287
|
+
return True
|
|
283
288
|
return compare_results(_invoker("strftime"), dt, fmt)
|
|
284
289
|
|
|
285
290
|
|
|
@@ -2,8 +2,7 @@ import datetime
|
|
|
2
2
|
|
|
3
3
|
import pytest
|
|
4
4
|
|
|
5
|
-
from crosshair.
|
|
6
|
-
from crosshair.statespace import CANNOT_CONFIRM, EXEC_ERR, POST_FAIL
|
|
5
|
+
from crosshair.statespace import CONFIRMED, EXEC_ERR, POST_FAIL
|
|
7
6
|
from crosshair.test_util import check_states
|
|
8
7
|
|
|
9
8
|
|
|
@@ -63,21 +62,21 @@ def test_timedelta_fail() -> None:
|
|
|
63
62
|
check_states(f, POST_FAIL)
|
|
64
63
|
|
|
65
64
|
|
|
66
|
-
def
|
|
65
|
+
def test_date_plus_delta_fail() -> None:
|
|
67
66
|
def f(delta: datetime.timedelta) -> datetime.date:
|
|
68
67
|
"""
|
|
69
|
-
post: _.year !=
|
|
68
|
+
post: _.year != 2033
|
|
70
69
|
raises: OverflowError
|
|
71
70
|
"""
|
|
72
71
|
return datetime.date(2000, 1, 1) + delta
|
|
73
72
|
|
|
74
|
-
check_states(f,
|
|
73
|
+
check_states(f, POST_FAIL)
|
|
75
74
|
|
|
76
75
|
|
|
77
76
|
def test_date_plus_delta_overflow_err() -> None:
|
|
78
77
|
def f(delta: datetime.timedelta) -> datetime.date:
|
|
79
78
|
"""
|
|
80
|
-
post:
|
|
79
|
+
post: True
|
|
81
80
|
"""
|
|
82
81
|
return datetime.date(2000, 1, 1) + delta
|
|
83
82
|
|