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.
Files changed (123) hide show
  1. _crosshair_tracers.cpython-39-darwin.so +0 -0
  2. crosshair/__init__.py +1 -1
  3. crosshair/_mark_stacks.h +51 -24
  4. crosshair/_tracers.h +9 -5
  5. crosshair/_tracers_test.py +19 -9
  6. crosshair/auditwall.py +9 -8
  7. crosshair/auditwall_test.py +31 -19
  8. crosshair/codeconfig.py +3 -2
  9. crosshair/condition_parser.py +17 -133
  10. crosshair/condition_parser_test.py +54 -96
  11. crosshair/conftest.py +1 -1
  12. crosshair/copyext.py +91 -22
  13. crosshair/copyext_test.py +33 -0
  14. crosshair/core.py +259 -203
  15. crosshair/core_and_libs.py +20 -0
  16. crosshair/core_regestered_types_test.py +82 -0
  17. crosshair/core_test.py +693 -664
  18. crosshair/diff_behavior.py +76 -21
  19. crosshair/diff_behavior_test.py +132 -23
  20. crosshair/dynamic_typing.py +128 -18
  21. crosshair/dynamic_typing_test.py +91 -4
  22. crosshair/enforce.py +1 -6
  23. crosshair/enforce_test.py +15 -23
  24. crosshair/examples/check_examples_test.py +2 -1
  25. crosshair/fnutil.py +2 -3
  26. crosshair/fnutil_test.py +0 -7
  27. crosshair/fuzz_core_test.py +70 -83
  28. crosshair/libimpl/arraylib.py +10 -7
  29. crosshair/libimpl/binascii_ch_test.py +30 -0
  30. crosshair/libimpl/binascii_test.py +67 -0
  31. crosshair/libimpl/binasciilib.py +150 -0
  32. crosshair/libimpl/bisectlib_test.py +5 -5
  33. crosshair/libimpl/builtinslib.py +1002 -682
  34. crosshair/libimpl/builtinslib_ch_test.py +108 -30
  35. crosshair/libimpl/builtinslib_test.py +431 -143
  36. crosshair/libimpl/codecslib.py +22 -2
  37. crosshair/libimpl/codecslib_test.py +41 -9
  38. crosshair/libimpl/collectionslib.py +44 -8
  39. crosshair/libimpl/collectionslib_test.py +108 -20
  40. crosshair/libimpl/copylib.py +1 -1
  41. crosshair/libimpl/copylib_test.py +18 -0
  42. crosshair/libimpl/datetimelib.py +84 -67
  43. crosshair/libimpl/datetimelib_ch_test.py +12 -7
  44. crosshair/libimpl/datetimelib_test.py +5 -6
  45. crosshair/libimpl/decimallib.py +5257 -0
  46. crosshair/libimpl/decimallib_ch_test.py +78 -0
  47. crosshair/libimpl/decimallib_test.py +76 -0
  48. crosshair/libimpl/encodings/_encutil.py +21 -11
  49. crosshair/libimpl/fractionlib.py +16 -0
  50. crosshair/libimpl/fractionlib_test.py +80 -0
  51. crosshair/libimpl/functoolslib.py +19 -7
  52. crosshair/libimpl/functoolslib_test.py +22 -6
  53. crosshair/libimpl/hashliblib.py +30 -0
  54. crosshair/libimpl/hashliblib_test.py +18 -0
  55. crosshair/libimpl/heapqlib.py +32 -5
  56. crosshair/libimpl/heapqlib_test.py +15 -12
  57. crosshair/libimpl/iolib.py +7 -4
  58. crosshair/libimpl/ipaddresslib.py +8 -0
  59. crosshair/libimpl/itertoolslib_test.py +1 -1
  60. crosshair/libimpl/mathlib.py +165 -2
  61. crosshair/libimpl/mathlib_ch_test.py +44 -0
  62. crosshair/libimpl/mathlib_test.py +59 -16
  63. crosshair/libimpl/oslib.py +7 -0
  64. crosshair/libimpl/pathliblib_test.py +10 -0
  65. crosshair/libimpl/randomlib.py +1 -0
  66. crosshair/libimpl/randomlib_test.py +6 -4
  67. crosshair/libimpl/relib.py +180 -59
  68. crosshair/libimpl/relib_ch_test.py +26 -2
  69. crosshair/libimpl/relib_test.py +77 -14
  70. crosshair/libimpl/timelib.py +35 -13
  71. crosshair/libimpl/timelib_test.py +13 -3
  72. crosshair/libimpl/typeslib.py +15 -0
  73. crosshair/libimpl/typeslib_test.py +36 -0
  74. crosshair/libimpl/unicodedatalib_test.py +3 -3
  75. crosshair/libimpl/weakreflib.py +13 -0
  76. crosshair/libimpl/weakreflib_test.py +69 -0
  77. crosshair/libimpl/zliblib.py +15 -0
  78. crosshair/libimpl/zliblib_test.py +13 -0
  79. crosshair/lsp_server.py +21 -10
  80. crosshair/main.py +48 -28
  81. crosshair/main_test.py +59 -14
  82. crosshair/objectproxy.py +39 -14
  83. crosshair/objectproxy_test.py +27 -13
  84. crosshair/opcode_intercept.py +212 -24
  85. crosshair/opcode_intercept_test.py +172 -18
  86. crosshair/options.py +0 -1
  87. crosshair/patch_equivalence_test.py +5 -21
  88. crosshair/path_cover.py +7 -5
  89. crosshair/path_search.py +6 -4
  90. crosshair/path_search_test.py +1 -2
  91. crosshair/pathing_oracle.py +53 -10
  92. crosshair/pathing_oracle_test.py +21 -0
  93. crosshair/pure_importer_test.py +5 -21
  94. crosshair/register_contract.py +16 -6
  95. crosshair/register_contract_test.py +2 -14
  96. crosshair/simplestructs.py +154 -85
  97. crosshair/simplestructs_test.py +16 -2
  98. crosshair/smtlib.py +24 -0
  99. crosshair/smtlib_test.py +14 -0
  100. crosshair/statespace.py +319 -196
  101. crosshair/statespace_test.py +45 -0
  102. crosshair/stubs_parser.py +0 -2
  103. crosshair/test_util.py +87 -25
  104. crosshair/test_util_test.py +26 -0
  105. crosshair/tools/check_init_and_setup_coincide.py +0 -3
  106. crosshair/tools/generate_demo_table.py +2 -2
  107. crosshair/tracers.py +141 -49
  108. crosshair/type_repo.py +11 -4
  109. crosshair/unicode_categories.py +1 -0
  110. crosshair/util.py +158 -76
  111. crosshair/util_test.py +13 -20
  112. crosshair/watcher.py +4 -4
  113. crosshair/z3util.py +1 -1
  114. {crosshair_tool-0.0.56.dist-info → crosshair_tool-0.0.100.dist-info}/METADATA +45 -36
  115. crosshair_tool-0.0.100.dist-info/RECORD +176 -0
  116. {crosshair_tool-0.0.56.dist-info → crosshair_tool-0.0.100.dist-info}/WHEEL +2 -1
  117. crosshair/examples/hypothesis/__init__.py +0 -2
  118. crosshair/examples/hypothesis/bugs_detected/simple_strategies.py +0 -74
  119. crosshair_tool-0.0.56.dist-info/RECORD +0 -152
  120. /crosshair/{examples/hypothesis/bugs_detected/__init__.py → py.typed} +0 -0
  121. {crosshair_tool-0.0.56.dist-info → crosshair_tool-0.0.100.dist-info}/entry_points.txt +0 -0
  122. {crosshair_tool-0.0.56.dist-info → crosshair_tool-0.0.100.dist-info/licenses}/LICENSE +0 -0
  123. {crosshair_tool-0.0.56.dist-info → crosshair_tool-0.0.100.dist-info}/top_level.txt +0 -0
@@ -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, real_timedelta):
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, real_tzinfo):
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, real_timedelta):
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, real_datetime):
657
+ elif isinstance(other, any_datetime):
660
658
  return datetime.fromdatetime(other).__add__(self)
661
- elif isinstance(other, real_date):
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, real_timedelta):
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, real_date):
674
+ elif isinstance(other, any_date):
677
675
  return date.fromdate(other).__add__(self)
678
- elif isinstance(other, real_datetime):
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, real_timedelta):
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, real_timedelta)):
715
+ if not isinstance(other, (int, any_timedelta)):
718
716
  return NotImplemented
719
717
  usec = _timedelta_to_microseconds(self)
720
- if isinstance(other, real_timedelta):
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, real_timedelta)):
724
+ if not isinstance(other, (int, float, any_timedelta)):
727
725
  return NotImplemented
728
726
  usec = _timedelta_to_microseconds(self)
729
- if isinstance(other, real_timedelta):
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, real_timedelta):
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, real_timedelta):
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, real_timedelta):
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, real_timedelta):
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, real_timedelta):
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, real_timedelta):
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, real_timedelta):
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, real_timedelta)
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
- year, month, day = _check_date_fields(year, month, day)
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, real_date):
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, real_date):
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, real_date):
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, real_date):
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, real_date):
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, real_date)
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, real_timedelta):
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, real_timedelta):
1103
+ if isinstance(other, any_timedelta):
1098
1104
  return self + timedelta(-other.days)
1099
- if isinstance(other, real_date):
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, real_datetime):
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, real_time):
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, real_time):
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, real_time):
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, real_time):
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, real_time):
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, real_time)
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, real_date):
1757
+ if not isinstance(date, any_date):
1745
1758
  raise TypeError("date argument must be a date instance")
1746
- if not isinstance(time, real_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, real_tzinfo):
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, real_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, real_datetime):
2110
+ if isinstance(other, any_datetime):
2098
2111
  return self._cmp(other, allow_mixed=True) == 0
2099
- elif not isinstance(other, real_date):
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, real_datetime):
2118
+ if isinstance(other, any_datetime):
2106
2119
  return self._cmp(other) <= 0
2107
- elif not isinstance(other, real_date):
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, real_datetime):
2126
+ if isinstance(other, any_datetime):
2114
2127
  return self._cmp(other) < 0
2115
- elif not isinstance(other, real_date):
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, real_datetime):
2134
+ if isinstance(other, any_datetime):
2122
2135
  return self._cmp(other) >= 0
2123
- elif not isinstance(other, real_date):
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, real_datetime):
2142
+ if isinstance(other, any_datetime):
2130
2143
  return self._cmp(other) > 0
2131
- elif not isinstance(other, real_date):
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, real_datetime)
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, real_timedelta):
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, real_datetime):
2213
- if isinstance(other, real_timedelta):
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, real_timedelta):
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, real_timezone):
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, real_datetime) or dt is None:
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, real_datetime) or dt is None:
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, real_datetime) or dt is None:
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, real_datetime):
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 compare_results(lambda *a: timedelta(*a), days, secs, microsecs)
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.options import AnalysisOptionSet
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 test_date_plus_delta_unknown() -> None:
65
+ def test_date_plus_delta_fail() -> None:
67
66
  def f(delta: datetime.timedelta) -> datetime.date:
68
67
  """
69
- post: _.year != -9999
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, CANNOT_CONFIRM)
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: _.year != -9999
79
+ post: True
81
80
  """
82
81
  return datetime.date(2000, 1, 1) + delta
83
82