crosshair-tool 0.0.86__cp310-cp310-macosx_10_9_universal2.whl → 0.0.88__cp310-cp310-macosx_10_9_universal2.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.

Potentially problematic release.


This version of crosshair-tool might be problematic. Click here for more details.

Binary file
crosshair/__init__.py CHANGED
@@ -15,7 +15,7 @@ from crosshair.statespace import StateSpace
15
15
  from crosshair.tracers import NoTracing, ResumedTracing
16
16
  from crosshair.util import IgnoreAttempt, debug
17
17
 
18
- __version__ = "0.0.86" # Do not forget to update in setup.py!
18
+ __version__ = "0.0.88" # Do not forget to update in setup.py!
19
19
  __author__ = "Phillip Schanely"
20
20
  __license__ = "MIT"
21
21
  __status__ = "Alpha"
crosshair/_mark_stacks.h CHANGED
@@ -538,23 +538,6 @@ static const uint8_t _ch_DE_INSTRUMENT[256] = {
538
538
  #endif
539
539
  #endif
540
540
 
541
- /* Get the underlying opcode, stripping instrumentation */
542
- int _ch_Py_GetBaseOpcode(PyCodeObject *code, int i)
543
- {
544
- int opcode = _PyCode_CODE(code)[i].op.code;
545
- if (opcode == INSTRUMENTED_LINE) {
546
- opcode = code->_co_monitoring->lines[i].original_opcode;
547
- }
548
- if (opcode == INSTRUMENTED_INSTRUCTION) {
549
- opcode = code->_co_monitoring->per_instruction_opcodes[i];
550
- }
551
- int deinstrumented = _ch_DE_INSTRUMENT[opcode];
552
- if (deinstrumented) {
553
- return deinstrumented;
554
- }
555
- return _ch_PyOpcode_Deopt[opcode];
556
- }
557
-
558
541
  static int64_t *
559
542
  _ch_mark_stacks(PyCodeObject *code_obj, int len)
560
543
  {
@@ -602,14 +585,14 @@ _ch_mark_stacks(PyCodeObject *code_obj, int len)
602
585
  /* Scan instructions */
603
586
  for (i = 0; i < len;) {
604
587
  int64_t next_stack = stacks[i];
605
- opcode = _ch_Py_GetBaseOpcode(code_obj, i);
588
+ opcode = code[i].op.code;
606
589
  uint8_t trace_enabled_here = _ch_TRACABLE_INSTRUCTIONS[opcode];
607
590
  enabled_tracing[i] |= trace_enabled_here;
608
591
  int oparg = 0;
609
592
  while (opcode == EXTENDED_ARG) {
610
593
  oparg = (oparg << 8) | code[i].op.arg;
611
594
  i++;
612
- opcode = _ch_Py_GetBaseOpcode(code_obj, i);
595
+ opcode = code[i].op.code;
613
596
  stacks[i] = next_stack;
614
597
  }
615
598
  int next_i = i + _ch_PyOpcode_Caches[opcode] + 1;
crosshair/_tracers.h CHANGED
@@ -50,10 +50,11 @@ typedef struct HandlerTable {
50
50
  } HandlerTable;
51
51
 
52
52
 
53
- typedef struct FrameAndCallback {
54
- PyObject* frame;
53
+ typedef struct FrameNextIandCallback {
54
+ PyFrameObject* frame;
55
+ int expected_i;
55
56
  PyObject* callback;
56
- } FrameAndCallback;
57
+ } FrameNextIandCallback;
57
58
 
58
59
 
59
60
  typedef struct CodeAndStacks {
@@ -62,7 +63,7 @@ typedef struct CodeAndStacks {
62
63
  } CodeAndStacks;
63
64
 
64
65
 
65
- DEFINE_VEC(FrameAndCallbackVec, FrameAndCallback, init_framecbvec, push_framecb);
66
+ DEFINE_VEC(FrameNextIandCallbackVec, FrameNextIandCallback, init_framecbvec, push_framecb);
66
67
  DEFINE_VEC(ModuleVec, PyObject*, init_modulevec, push_module);
67
68
  DEFINE_VEC(TableVec, HandlerTable, init_tablevec, push_table_entry)
68
69
 
@@ -70,7 +71,7 @@ typedef struct CTracer {
70
71
  PyObject_HEAD
71
72
  ModuleVec modules;
72
73
  TableVec handlers;
73
- FrameAndCallbackVec postop_callbacks;
74
+ FrameNextIandCallbackVec postop_callbacks;
74
75
  BOOL enabled;
75
76
  BOOL handling;
76
77
  BOOL trace_all_opcodes;
crosshair/auditwall.py CHANGED
@@ -1,4 +1,5 @@
1
1
  import importlib
2
+ import inspect
2
3
  import os
3
4
  import sys
4
5
  import traceback
@@ -28,9 +29,10 @@ def reject(event: str, args: Tuple) -> None:
28
29
 
29
30
 
30
31
  def inside_module(modules: Iterable[ModuleType]) -> bool:
31
- files = {m.__file__ for m in modules}
32
- for frame, lineno in traceback.walk_stack(None):
33
- if frame.f_code.co_filename in files:
32
+ """Checks whether the current call stack is inside one of the given modules."""
33
+ for frame, _lineno in traceback.walk_stack(None):
34
+ frame_module = inspect.getmodule(frame)
35
+ if frame_module and frame_module in modules:
34
36
  return True
35
37
  return False
36
38
 
@@ -60,7 +62,7 @@ def check_msvcrt_open(event: str, args: Tuple) -> None:
60
62
  _MODULES_THAT_CAN_POPEN: Optional[Set[ModuleType]] = None
61
63
 
62
64
 
63
- def modules_with_allowed_popen():
65
+ def modules_with_allowed_subprocess():
64
66
  global _MODULES_THAT_CAN_POPEN
65
67
  if _MODULES_THAT_CAN_POPEN is None:
66
68
  allowed_module_names = ("_aix_support", "ctypes", "platform", "uuid")
@@ -74,13 +76,14 @@ def modules_with_allowed_popen():
74
76
 
75
77
 
76
78
  def check_subprocess(event: str, args: Tuple) -> None:
77
- if not inside_module(modules_with_allowed_popen()):
79
+ if not inside_module(modules_with_allowed_subprocess()):
78
80
  reject(event, args)
79
81
 
80
82
 
81
83
  _SPECIAL_HANDLERS = {
82
84
  "open": check_open,
83
85
  "subprocess.Popen": check_subprocess,
86
+ "os.posix_spawn": check_subprocess,
84
87
  "msvcrt.open_osfhandle": check_msvcrt_open,
85
88
  }
86
89
 
@@ -267,7 +267,7 @@ class SymbolicValue(CrossHairValue):
267
267
  self.snapshot = SnapshotRef(-1)
268
268
  self.python_type = typ
269
269
  if type(smtvar) is str:
270
- self.var = self.__init_var__(typ, smtvar)
270
+ self.var: Any = self.__init_var__(typ, smtvar)
271
271
  else:
272
272
  self.var = smtvar
273
273
  # TODO test that smtvar's sort matches expected?
@@ -838,19 +838,6 @@ def setup_binops():
838
838
 
839
839
  setup_binop(_, {ops.lshift, ops.rshift})
840
840
 
841
- _AND_MASKS_TO_MOD = {
842
- # It's common to use & to mask low bits. We can avoid realization by converting
843
- # these situations into mod operations.
844
- 0x01: 2,
845
- 0x03: 4,
846
- 0x07: 8,
847
- 0x0F: 16,
848
- 0x1F: 32,
849
- 0x3F: 64,
850
- 0x7F: 128,
851
- 0xFF: 256,
852
- }
853
-
854
841
  def _(op: BinFn, a: Integral, b: Integral):
855
842
  with NoTracing():
856
843
  if isinstance(b, SymbolicInt):
@@ -861,9 +848,12 @@ def setup_binops():
861
848
  b = realize(b)
862
849
  if b == 0:
863
850
  return 0
864
- mask_mod = _AND_MASKS_TO_MOD.get(b)
865
- if mask_mod and isinstance(a, SymbolicInt):
866
- if context_statespace().smt_fork(a.var >= 0, probability_true=0.75):
851
+ # It's common to use & to mask low bits. We can avoid realization by converting
852
+ # these situations into mod operations.
853
+ mask_mod = b + 1
854
+ if b > 0 and mask_mod & b == 0 and isinstance(a, SymbolicInt): # type: ignore
855
+ space = context_statespace()
856
+ if space.smt_fork(a.var >= 0, probability_true=0.75):
867
857
  return SymbolicInt(a.var % mask_mod)
868
858
  else:
869
859
  return SymbolicInt(b - ((-a.var - 1) % mask_mod))
@@ -1435,6 +1425,10 @@ class PreciseIeeeSymbolicFloat(SymbolicFloat):
1435
1425
  # __hash__ has to be explicitly reassigned because we define __eq__
1436
1426
  __hash__ = SymbolicFloat.__hash__
1437
1427
 
1428
+ def __bool__(self):
1429
+ with NoTracing():
1430
+ return not SymbolicBool(z3.fpIsZero(self.var))
1431
+
1438
1432
  def __ne__(self, other):
1439
1433
  with NoTracing():
1440
1434
  coerced = type(self)._coerce_to_smt_sort(other)
@@ -85,7 +85,6 @@ from crosshair.util import (
85
85
  CrossHairValue,
86
86
  IgnoreAttempt,
87
87
  UnknownSatisfiability,
88
- set_debug,
89
88
  )
90
89
 
91
90
 
@@ -3618,18 +3617,29 @@ def test_deep_realization(space, typ):
3618
3617
  assert concrete == symbolic
3619
3618
 
3620
3619
 
3621
- def TODO_test_float_precision_issues(a, b):
3622
- # Does not yet work: floating point is modeled with infinite precision at the moment
3623
- def f(a: int, b: int):
3624
- """
3625
- pre: b !=0
3626
- post: a == b * _
3620
+ def test_float_round_to_zero(space):
3621
+ space.extra(ModelingDirector).global_representations[
3622
+ float
3623
+ ] = PreciseIeeeSymbolicFloat
3624
+ n = proxy_for_type(float, "n")
3625
+ d = proxy_for_type(float, "d")
3626
+ with ResumedTracing():
3627
+ space.add(d != 0.0)
3628
+ # This is possible for floats, but not reals:
3629
+ assert space.is_possible(n / d != 0.0)
3630
+ assert space.is_possible(n / d == 0.0)
3627
3631
 
3628
- Postcondition holds in a math-sense, but not when floating point precision
3629
- comes into play (e.g. it's false for 13 / 99)
3630
- """
3631
3632
 
3632
- return a / b
3633
+ def test_float_neg_zero_is_falsey(space):
3634
+ space.extra(ModelingDirector).global_representations[
3635
+ float
3636
+ ] = PreciseIeeeSymbolicFloat
3637
+ x = proxy_for_type(float, "x")
3638
+ with ResumedTracing():
3639
+ space.add(x == -10.0)
3640
+ negzero = x / math.inf
3641
+ assert not space.is_possible(negzero != 0.0)
3642
+ assert bool(negzero) is False
3633
3643
 
3634
3644
 
3635
3645
  def TODO_test_int_mod_float():
@@ -0,0 +1,18 @@
1
+ import copy
2
+ import datetime
3
+
4
+ from crosshair.core import proxy_for_type
5
+ from crosshair.statespace import StateSpace
6
+ from crosshair.tracers import ResumedTracing
7
+ from crosshair.util import debug
8
+
9
+
10
+ def test_date_copy(space: StateSpace) -> None:
11
+ concrete_date = datetime.date(2000, 2, 3)
12
+ symbolic_date = proxy_for_type(datetime.date, "d")
13
+ with ResumedTracing():
14
+ copied_symbolic = copy.deepcopy(symbolic_date)
15
+ copied_concrete = copy.deepcopy(concrete_date)
16
+ assert not space.is_possible(copied_concrete != concrete_date)
17
+ assert not space.is_possible(copied_concrete != datetime.date(2000, 2, 3))
18
+ assert not space.is_possible(copied_symbolic != symbolic_date)
@@ -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
crosshair/main_test.py CHANGED
@@ -515,7 +515,7 @@ def test_mypycrosshair_command():
515
515
  capture_output=True,
516
516
  text=True,
517
517
  )
518
- assert completion.stderr.strip() == ""
518
+ assert completion.stderr.strip() == "", f"stderr was '''{completion.stderr}'''"
519
519
  if completion.returncode != 1:
520
520
  print(completion.stdout)
521
521
  assert False, f"Return code was {completion.returncode}"
@@ -286,3 +286,19 @@ def test_identity_operator_does_not_realize_on_differing_types():
286
286
  fourty_two = 42 # assignment just to avoid lint errors
287
287
  b1 is fourty_two
288
288
  assert len(space.choices_made) == choices_made_at_start
289
+
290
+
291
+ class IExplodeOnRepr:
292
+ def __repr__(self):
293
+ raise ValueError("boom")
294
+
295
+
296
+ def test_postop_callback_skipped_on_exception_handler_jump(space):
297
+ with ResumedTracing():
298
+ elements = IExplodeOnRepr()
299
+ try:
300
+ ret = f"these are them: {elements!r}"
301
+ except ValueError: # pragma: no cover
302
+ ret = None
303
+ # need to do something(anything) with elements so that it's on the stack:
304
+ type(elements)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: crosshair-tool
3
- Version: 0.0.86
3
+ Version: 0.0.88
4
4
  Summary: Analyze Python code for correctness using symbolic execution.
5
5
  Home-page: https://github.com/pschanely/CrossHair
6
6
  Author: Phillip Schanely
@@ -46,7 +46,7 @@ Requires-Dist: pytest-xdist; extra == "dev"
46
46
  Requires-Dist: setuptools; extra == "dev"
47
47
  Requires-Dist: sphinx>=3.4.3; extra == "dev"
48
48
  Requires-Dist: sphinx-rtd-theme>=0.5.1; extra == "dev"
49
- Requires-Dist: wheel; extra == "dev"
49
+ Requires-Dist: rst2pdf>=0.102; extra == "dev"
50
50
  Dynamic: author
51
51
  Dynamic: author-email
52
52
  Dynamic: classifier
@@ -1,4 +1,4 @@
1
- _crosshair_tracers.cpython-310-darwin.so,sha256=qdqiH87cuBiJHAiPReJoTtSAI54O1tkwbXTIwELiz8M,89680
1
+ _crosshair_tracers.cpython-310-darwin.so,sha256=FWCsrOIUmi8w1c0deefXhOCmJiz0ioTmLAvhaOSecH4,89680
2
2
  crosshair/_tracers_pycompat.h,sha256=6IYnbQxrYkhBsLDAHSX25DPOwo1oYHCZUVWZ8c7YCnQ,14356
3
3
  crosshair/pure_importer.py,sha256=-t4eowrZOQmfqK1N2tjI5POoaxRGavytwMmbRivelFg,878
4
4
  crosshair/options.py,sha256=htQNgnrpoRjSNq6rfLBAF8nos-NNIwmP6tQYyI8ugsM,6775
@@ -17,13 +17,13 @@ crosshair/util.py,sha256=eddHHvkn9NnsfYahpuIF4Xp03kIiQ8EJUaliFEO4XG4,22124
17
17
  crosshair/dynamic_typing.py,sha256=jbI9FXv5-WXREQjeDtlDQladv-xCW21TUOM3qErJaJ4,11998
18
18
  crosshair/register_contract.py,sha256=EnDAxngJhKvJLFdw5kVgqaYDQ5hAZXKwAGBdXpot-AQ,10386
19
19
  crosshair/tracers.py,sha256=_jaSDgZ_pYdqacWE_msXn7W7CoSdQ_-7hlrxa891oHo,17139
20
- crosshair/_tracers.h,sha256=qaDWd-_eCZckSbezrXXst6lppzFiM2kD2AcZgvVQm18,2124
20
+ crosshair/_tracers.h,sha256=QFBklLqMWmIpUzBIn_A4SKdpjwHs-N7ttx-F5jtWWCQ,2174
21
21
  crosshair/type_repo.py,sha256=dqMnDNgBqchRwsbXJcZmPyPHfiQC9kqFAB7z-zoA_0I,4649
22
22
  crosshair/fnutil.py,sha256=X80bD2Lh4QAh-rF561r3JRxjxcuZepF3hJaxaj1GG9s,13123
23
23
  crosshair/unicode_categories.py,sha256=g4pnUPanx8KkpwI06ZUGx8GR8Myruf_EpTjyti_V4z8,333519
24
24
  crosshair/copyext.py,sha256=GBGQP9YAHoezLXwb_M59Hh1VXSou5EQt4ZmmUA0T_og,4899
25
25
  crosshair/_tracers_test.py,sha256=KpCGspjOUeZuhwTYgn_RxI4M4wMbT5rldusFDgneQ6M,3596
26
- crosshair/__init__.py,sha256=BqE2fB9um9PltLa0yX7EVsyAzVpgDe5EBvIiEhQ2exI,936
26
+ crosshair/__init__.py,sha256=SSP_9GXeo_0ypAR-f-Zt32yVGvXY3tEY9SWKDgy_m_A,936
27
27
  crosshair/core.py,sha256=K7147xrvcvtrP1T9oIRywq2uHMMsIu8ZwFZWBQXPozg,63634
28
28
  crosshair/path_cover.py,sha256=wV0Vy8IPDzqXQ2VI8a94FxltS9p-Y1oF17OKePjvpgs,6710
29
29
  crosshair/enforce_test.py,sha256=C6CQ4P1FjkdIJeJg3aJynp1iLDCE6BFCEVtSqXbvmQk,4665
@@ -32,7 +32,7 @@ crosshair/core_test.py,sha256=H6qZFBFuUhgh9qWgxxc1Cs7xuC8s6FYvewmTYUh0Dpg,32200
32
32
  crosshair/codeconfig.py,sha256=GgF-ND8Ha3FysSTQ-JuezHjlhGVBbo5aCJov1Ps3VSE,3959
33
33
  crosshair/util_test.py,sha256=_KTQ0O4cLhF1pAeB8Y8Cyqbd0UyZf5KxJUaiA-ew-tE,4676
34
34
  crosshair/watcher_test.py,sha256=Ef1YSwy68wWPR5nPjwvEKPqxltI9pE9lTbnesmDy3Bk,2764
35
- crosshair/auditwall.py,sha256=FjpeqM6HxsKYEfVJ20CRzkQu1I2zt1dpzwejrDp-W9U,4975
35
+ crosshair/auditwall.py,sha256=sqOmfXQLgmGfWS7b8SmVv66eFM2owaGn-4Ppq453VLI,5138
36
36
  crosshair/simplestructs_test.py,sha256=6uDdrSISHLhwnFuESkR8mUGw7m1llM6vCNDFChkfSs8,8639
37
37
  crosshair/z3util_test.py,sha256=CZovn4S9mYcG_yQegcxm80VHrvUdvNei0gvGTF9TOrk,173
38
38
  crosshair/diff_behavior.py,sha256=_5X_pTN0_-rSPrh8dfpODJG_phFMn7fWc-_zLgO3UTk,11253
@@ -43,7 +43,7 @@ crosshair/stubs_parser_test.py,sha256=0itTT0Udul_51RJXNv6KB97z44gYze6NZfKJL7yIDz
43
43
  crosshair/options_test.py,sha256=lzA-XtwEwQPa4wV1wwhCRKhyLOvIhThU9WK5QRaRbxQ,379
44
44
  crosshair/patch_equivalence_test.py,sha256=mvYpsbHZS2AiQra-jK8T8QywAG1gNNCUNQPPWI9k5t8,2506
45
45
  crosshair/abcstring.py,sha256=ROU8LzS7kfEU2L_D3QfhVxIjrYr1VctwUWfylC7KlCc,6549
46
- crosshair/_mark_stacks.h,sha256=rvIET5OGjKMcUZxEtIb9RhxRDveAfPXb3HLZZWfM3Bs,29261
46
+ crosshair/_mark_stacks.h,sha256=j86qubOUvVhoR19d74iQ084RrTEq8M6oT4wJsGQUySY,28678
47
47
  crosshair/fuzz_core_test.py,sha256=q7WsZt6bj5OJrXaVsT3JaRYWWnL8X_1flSfty4Z7CcA,16903
48
48
  crosshair/unicode_categories_test.py,sha256=ZAU37IDGm9PDvwy_CGFcrF9Waa8JuUNdI4aq74wkB6c,739
49
49
  crosshair/statespace_test.py,sha256=LOblIarBbcB9oD_gVR5kK_4P2PWQymVGgJr3wNqP3Fs,2621
@@ -54,8 +54,8 @@ crosshair/auditwall_test.py,sha256=VPcw_OW3nl3BkOZY4wEEtVDyTamdgqD4IjRccI2p5vI,2
54
54
  crosshair/smtlib_test.py,sha256=edzEn19u2YYHxSzG9RrMiu2HTiEexAuehC3IlG9LuJM,511
55
55
  crosshair/register_contract_test.py,sha256=DhvKIcF3LgQfHfUSCccoA11ctCdFaQR263Pc4YUuxyk,4970
56
56
  crosshair/statespace.py,sha256=KeIIBwBKxDgQO0ML2LvYXhS5DgmelaYF-RRXopR9lqA,41794
57
- crosshair/opcode_intercept_test.py,sha256=hBf04VwhaIzPdoAaqQmQJfx36yaznD9sm9x1Lb9VDm8,8790
58
- crosshair/main_test.py,sha256=DFXtE--616vCF1WAS576SHXO19K0LsDPzJIWNT5vuXM,14383
57
+ crosshair/opcode_intercept_test.py,sha256=Si3rJQR5cs5d4uB8uwE2K8MjP8rE1a4yHkjXzhfS10A,9241
58
+ crosshair/main_test.py,sha256=eEoK4LHKSaX-6iJx3tAVbwCaBJc0ri3VoCPtLD5em2U,14424
59
59
  crosshair/codeconfig_test.py,sha256=RnC-RnNpr6If4eHmOepDZ33MCmfyhup08dzHKCm5xWA,3350
60
60
  crosshair/watcher.py,sha256=kCCMlLe2KhW5MbEbMmixNRjRAvu5CypIAGd1V_YZ9QM,10048
61
61
  crosshair/test_util_test.py,sha256=FIOWVBMiF-zyq0pGsDQ8W6lB6_E9sGpD80dioHHETyQ,512
@@ -100,6 +100,7 @@ crosshair/examples/icontract/bugs_detected/__init__.py,sha256=47DEQpj8HBSa-_TImW
100
100
  crosshair/examples/icontract/bugs_detected/showcase.py,sha256=L4iL1JCWCpOISbEc5yce5bW_Th5eAjYVKRzsykb7m9M,1248
101
101
  crosshair/libimpl/collectionslib.py,sha256=VuDIOUOGORiUT9J0tDVECr6oC-yUR3WAiFnMeVGzi-o,8583
102
102
  crosshair/libimpl/zliblib_test.py,sha256=mckg9PnZrBUTStzMzHIoZl8JPuAzsIfrEruNKNDpYiE,388
103
+ crosshair/libimpl/copylib_test.py,sha256=VpS9ICvIjzKw0kccsl1v5FB1chHHEIWdOAerEQ_pGMw,705
103
104
  crosshair/libimpl/unicodedatalib.py,sha256=q5LoCaEbHJrUwVWtUrlS3n_X21yp15xTS42l-9AQ6Us,3103
104
105
  crosshair/libimpl/datetimelib_test.py,sha256=v9Cg512AXIGy7_dsN2y_ZD7W7fqfSSz07eiCUZukM60,2659
105
106
  crosshair/libimpl/heapqlib_test.py,sha256=NdwTihD0xGy4qIDaS5a9-t3q437rP47GNdtceEBquNA,537
@@ -107,13 +108,13 @@ crosshair/libimpl/binascii_test.py,sha256=LOBqLAJ77Kx8vorjVTaT3X0Z93zw4P5BvwUapM
107
108
  crosshair/libimpl/collectionslib_test.py,sha256=3h7XTToKWauMhjrEwLXVI0jT8FZKBlkvlw0oiPMmuKM,9164
108
109
  crosshair/libimpl/timelib.py,sha256=MXEFOZjFGa1-yLvmB3l3DFTLF9PSluOlmRK-ZJaA_oI,2409
109
110
  crosshair/libimpl/jsonlib_test.py,sha256=U40WJf-69dtflz75sIsl5zA3IV5R6Ltc4Z9jv_Fh-Fw,1382
110
- crosshair/libimpl/builtinslib.py,sha256=9qAV1xZ2oZrIrpfWQ3BXgnY0nK2Gjov4v207x43lTq4,171629
111
+ crosshair/libimpl/builtinslib.py,sha256=0NRP8l_weL0kh050cOKMrqK8y-glh3NySYLJYjdHVz8,171622
111
112
  crosshair/libimpl/mathlib_test.py,sha256=QShLCXHdv3tx5PQxcSoR0MHeZ1huaiV6d3u7C2mGOn4,1861
112
113
  crosshair/libimpl/fractionlib.py,sha256=qdbiAHHC480YdKq3wYK_piZ3UD7oT64YfuNclypMUfQ,458
113
114
  crosshair/libimpl/binascii_ch_test.py,sha256=hFqSfF1Q8jl2LNBIWaQ6vBJIIshPOmSwrR0T1Ko4Leo,1009
114
115
  crosshair/libimpl/jsonlib.py,sha256=xFTvqGKzQcCgPme1WIpNMjBPfNHVZBMNuNx0uKMYXj0,28805
115
116
  crosshair/libimpl/typeslib_test.py,sha256=qCeUU_c-zmuvfwHEsaYqic9wdGzs9XbDZNr6bF2Xp58,1129
116
- crosshair/libimpl/builtinslib_test.py,sha256=Q0DvH7Q_Ja0Tg83enhB_y_Pdau_S-bA6ztorjvgl4Mw,90275
117
+ crosshair/libimpl/builtinslib_test.py,sha256=Y_jRe5J6pPaJ_Nuk1lJ1biP5yczsfCj--NgNhwcbAfQ,90654
117
118
  crosshair/libimpl/zliblib.py,sha256=XymJTKYbplpYJZ-P7GKVSY3V_8HPy5lqRFsCH1zezIk,357
118
119
  crosshair/libimpl/decimallib.py,sha256=zBKDrDZcg45oCKUkf6SIDuVpjA1Web7tD1MEQo5cjxI,177348
119
120
  crosshair/libimpl/relib_ch_test.py,sha256=zvSBF82mNQR5yEOMwwcaBOh8OpJkQeiVl85pgYVvJRA,5235
@@ -147,7 +148,7 @@ crosshair/libimpl/copylib.py,sha256=icHJWeFK_tsPSdJhvlS5fVcBwlh0uJh0nzXsRJCGtzs,
147
148
  crosshair/libimpl/hashliblib_test.py,sha256=HhPdm5CBTAeqrs41NpCxkexWYWyIf1JiA4cls72WQfM,406
148
149
  crosshair/libimpl/binasciilib.py,sha256=9w4C37uxRNOmz9EUuhJduHlMKn0f7baY5fwwdvx1uto,5070
149
150
  crosshair/libimpl/typeslib.py,sha256=5qWrHZZN8jQZoHPiQtkaFolR8qTYCQtJw3HRWCrCKQI,468
150
- crosshair/libimpl/datetimelib.py,sha256=osysXCLJCgyCj0gR8e0iyCeulgUvJ9rrO60kz1gudAY,78869
151
+ crosshair/libimpl/datetimelib.py,sha256=kVWcoHMX-dPW-un7XoEIURfWlVOst6h_JFmjrhFiE1U,79168
151
152
  crosshair/libimpl/relib.py,sha256=3DhrbGqJcfpj5JNfcD8Pf4xsA4WEegxbukwgKoPLP3o,29256
152
153
  crosshair/libimpl/iolib.py,sha256=FbvqTfQRPaML5u0hHnrFZLrk3jYC-x4OO6eJujvFJaY,6983
153
154
  crosshair/libimpl/urlliblib_test.py,sha256=UcSmwRdJFkzXvkaV-jmrP6G4zhbu7X2NNjM7ePsYxRs,503
@@ -166,9 +167,9 @@ crosshair/libimpl/encodings/ascii.py,sha256=Cz1xraTkXdQ5aBKDkorX4rAvrmf877_EqzC9
166
167
  crosshair/libimpl/encodings/__init__.py,sha256=5LTEj1M-S00eZ4rfQWczAixg57vyh_9vZ5m5EKB5Ksc,680
167
168
  crosshair/libimpl/encodings/latin_1.py,sha256=ftUsPjUb9L7UKXKi9P7OAqOl9FkNP98M9jMAvseXBCQ,1242
168
169
  crosshair/libimpl/encodings/_encutil.py,sha256=nwVWqcGM1f7-hAC3Z46KnfrLzAjhfy4zaTa11uVBk6M,6828
169
- crosshair_tool-0.0.86.dist-info/RECORD,,
170
- crosshair_tool-0.0.86.dist-info/WHEEL,sha256=nvWlBq2MeWbEyf6rrV6pi6XGCjSQq3svhelVdCE-G64,141
171
- crosshair_tool-0.0.86.dist-info/entry_points.txt,sha256=u5FIPVn1jqn4Kzg5K_iNnbP6L4hQw5FWjQ0UMezG2VE,96
172
- crosshair_tool-0.0.86.dist-info/top_level.txt,sha256=2jLWtM-BWg_ZYNbNfrcds0HFZD62a6J7ZIbcgcQrRk4,29
173
- crosshair_tool-0.0.86.dist-info/METADATA,sha256=8n0ualxjh4y_waUzDZfliJjet2bID8tHk6kQIiwX2-M,6717
174
- crosshair_tool-0.0.86.dist-info/licenses/LICENSE,sha256=NVyMvNqn1pH6RSHs6RWRcJyJvORnpgGFBlF73buqYJ0,4459
170
+ crosshair_tool-0.0.88.dist-info/RECORD,,
171
+ crosshair_tool-0.0.88.dist-info/WHEEL,sha256=nc924w4TUhRiaM6-2LHWgVO2LgkOLXLUotVVlNPrJ7M,141
172
+ crosshair_tool-0.0.88.dist-info/entry_points.txt,sha256=u5FIPVn1jqn4Kzg5K_iNnbP6L4hQw5FWjQ0UMezG2VE,96
173
+ crosshair_tool-0.0.88.dist-info/top_level.txt,sha256=2jLWtM-BWg_ZYNbNfrcds0HFZD62a6J7ZIbcgcQrRk4,29
174
+ crosshair_tool-0.0.88.dist-info/METADATA,sha256=fb65F1neoaCfY1YaRda8cocX3gOjjCWW5it7Xn2DXto,6726
175
+ crosshair_tool-0.0.88.dist-info/licenses/LICENSE,sha256=NVyMvNqn1pH6RSHs6RWRcJyJvORnpgGFBlF73buqYJ0,4459
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (78.1.0)
2
+ Generator: setuptools (80.9.0)
3
3
  Root-Is-Purelib: false
4
4
  Tag: cp310-cp310-macosx_10_9_universal2
5
5
  Generator: delocate 0.13.0