crosshair-tool 0.0.85__tar.gz → 0.0.86__tar.gz

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.

Files changed (179) hide show
  1. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/PKG-INFO +38 -3
  2. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/__init__.py +1 -1
  3. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/builtinslib.py +4 -260
  4. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/builtinslib_test.py +1 -1
  5. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/typeslib_test.py +2 -1
  6. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/opcode_intercept.py +110 -41
  7. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/opcode_intercept_test.py +85 -5
  8. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/statespace.py +9 -4
  9. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/util.py +3 -1
  10. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair_tool.egg-info/PKG-INFO +38 -3
  11. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/setup.py +1 -1
  12. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/LICENSE +0 -0
  13. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/README.md +0 -0
  14. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/__main__.py +0 -0
  15. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/_mark_stacks.h +0 -0
  16. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/_preliminaries_test.py +0 -0
  17. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/_tracers.c +0 -0
  18. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/_tracers.h +0 -0
  19. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/_tracers_pycompat.h +0 -0
  20. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/_tracers_test.py +0 -0
  21. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/abcstring.py +0 -0
  22. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/auditwall.py +0 -0
  23. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/auditwall_test.py +0 -0
  24. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/codeconfig.py +0 -0
  25. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/codeconfig_test.py +0 -0
  26. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/condition_parser.py +0 -0
  27. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/condition_parser_test.py +0 -0
  28. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/conftest.py +0 -0
  29. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/copyext.py +0 -0
  30. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/copyext_test.py +0 -0
  31. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/core.py +0 -0
  32. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/core_and_libs.py +0 -0
  33. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/core_regestered_types_test.py +0 -0
  34. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/core_test.py +0 -0
  35. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/diff_behavior.py +0 -0
  36. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/diff_behavior_test.py +0 -0
  37. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/dynamic_typing.py +0 -0
  38. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/dynamic_typing_test.py +0 -0
  39. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/enforce.py +0 -0
  40. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/enforce_test.py +0 -0
  41. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/examples/PEP316/__init__.py +0 -0
  42. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/examples/PEP316/bugs_detected/__init__.py +0 -0
  43. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/examples/PEP316/bugs_detected/getattr_magic.py +0 -0
  44. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/examples/PEP316/bugs_detected/hash_consistent_with_equals.py +0 -0
  45. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/examples/PEP316/bugs_detected/shopping_cart.py +0 -0
  46. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/examples/PEP316/bugs_detected/showcase.py +0 -0
  47. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/examples/PEP316/correct_code/__init__.py +0 -0
  48. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/examples/PEP316/correct_code/arith.py +0 -0
  49. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/examples/PEP316/correct_code/chess.py +0 -0
  50. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/examples/PEP316/correct_code/nesting_inference.py +0 -0
  51. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/examples/PEP316/correct_code/numpy_examples.py +0 -0
  52. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/examples/PEP316/correct_code/rolling_average.py +0 -0
  53. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/examples/PEP316/correct_code/showcase.py +0 -0
  54. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/examples/__init__.py +0 -0
  55. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/examples/check_examples_test.py +0 -0
  56. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/examples/deal/__init__.py +0 -0
  57. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/examples/icontract/__init__.py +0 -0
  58. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/examples/icontract/bugs_detected/__init__.py +0 -0
  59. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/examples/icontract/bugs_detected/showcase.py +0 -0
  60. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/examples/icontract/bugs_detected/wrong_sign.py +0 -0
  61. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/examples/icontract/correct_code/__init__.py +0 -0
  62. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/examples/icontract/correct_code/arith.py +0 -0
  63. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/examples/icontract/correct_code/showcase.py +0 -0
  64. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/fnutil.py +0 -0
  65. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/fnutil_test.py +0 -0
  66. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/fuzz_core_test.py +0 -0
  67. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/__init__.py +0 -0
  68. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/arraylib.py +0 -0
  69. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/binascii_ch_test.py +0 -0
  70. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/binascii_test.py +0 -0
  71. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/binasciilib.py +0 -0
  72. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/bisectlib_test.py +0 -0
  73. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/builtinslib_ch_test.py +0 -0
  74. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/codecslib.py +0 -0
  75. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/codecslib_test.py +0 -0
  76. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/collectionslib.py +0 -0
  77. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/collectionslib_ch_test.py +0 -0
  78. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/collectionslib_test.py +0 -0
  79. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/copylib.py +0 -0
  80. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/datetimelib.py +0 -0
  81. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/datetimelib_ch_test.py +0 -0
  82. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/datetimelib_test.py +0 -0
  83. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/decimallib.py +0 -0
  84. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/decimallib_ch_test.py +0 -0
  85. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/decimallib_test.py +0 -0
  86. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/encodings/__init__.py +0 -0
  87. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/encodings/_encutil.py +0 -0
  88. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/encodings/ascii.py +0 -0
  89. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/encodings/latin_1.py +0 -0
  90. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/encodings/utf_8.py +0 -0
  91. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/encodings_ch_test.py +0 -0
  92. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/fractionlib.py +0 -0
  93. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/fractionlib_test.py +0 -0
  94. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/functoolslib.py +0 -0
  95. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/functoolslib_test.py +0 -0
  96. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/hashliblib.py +0 -0
  97. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/hashliblib_test.py +0 -0
  98. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/heapqlib.py +0 -0
  99. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/heapqlib_test.py +0 -0
  100. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/importliblib.py +0 -0
  101. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/importliblib_test.py +0 -0
  102. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/iolib.py +0 -0
  103. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/iolib_ch_test.py +0 -0
  104. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/iolib_test.py +0 -0
  105. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/ipaddresslib.py +0 -0
  106. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/itertoolslib.py +0 -0
  107. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/itertoolslib_test.py +0 -0
  108. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/jsonlib.py +0 -0
  109. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/jsonlib_ch_test.py +0 -0
  110. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/jsonlib_test.py +0 -0
  111. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/mathlib.py +0 -0
  112. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/mathlib_ch_test.py +0 -0
  113. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/mathlib_test.py +0 -0
  114. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/oslib.py +0 -0
  115. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/pathliblib_test.py +0 -0
  116. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/randomlib.py +0 -0
  117. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/randomlib_test.py +0 -0
  118. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/relib.py +0 -0
  119. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/relib_ch_test.py +0 -0
  120. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/relib_test.py +0 -0
  121. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/timelib.py +0 -0
  122. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/timelib_test.py +0 -0
  123. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/typeslib.py +0 -0
  124. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/unicodedatalib.py +0 -0
  125. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/unicodedatalib_test.py +0 -0
  126. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/urlliblib.py +0 -0
  127. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/urlliblib_test.py +0 -0
  128. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/weakreflib.py +0 -0
  129. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/weakreflib_test.py +0 -0
  130. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/zliblib.py +0 -0
  131. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/libimpl/zliblib_test.py +0 -0
  132. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/lsp_server.py +0 -0
  133. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/lsp_server_test.py +0 -0
  134. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/main.py +0 -0
  135. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/main_test.py +0 -0
  136. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/objectproxy.py +0 -0
  137. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/objectproxy_test.py +0 -0
  138. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/options.py +0 -0
  139. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/options_test.py +0 -0
  140. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/patch_equivalence_test.py +0 -0
  141. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/path_cover.py +0 -0
  142. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/path_cover_test.py +0 -0
  143. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/path_search.py +0 -0
  144. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/path_search_test.py +0 -0
  145. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/pathing_oracle.py +0 -0
  146. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/pure_importer.py +0 -0
  147. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/pure_importer_test.py +0 -0
  148. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/py.typed +0 -0
  149. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/register_contract.py +0 -0
  150. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/register_contract_test.py +0 -0
  151. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/simplestructs.py +0 -0
  152. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/simplestructs_test.py +0 -0
  153. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/smtlib.py +0 -0
  154. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/smtlib_test.py +0 -0
  155. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/statespace_test.py +0 -0
  156. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/stubs_parser.py +0 -0
  157. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/stubs_parser_test.py +0 -0
  158. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/test_util.py +0 -0
  159. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/test_util_test.py +0 -0
  160. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/tools/__init__.py +0 -0
  161. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/tools/check_help_in_doc.py +0 -0
  162. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/tools/check_init_and_setup_coincide.py +0 -0
  163. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/tools/generate_demo_table.py +0 -0
  164. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/tracers.py +0 -0
  165. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/tracers_test.py +0 -0
  166. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/type_repo.py +0 -0
  167. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/unicode_categories.py +0 -0
  168. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/unicode_categories_test.py +0 -0
  169. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/util_test.py +0 -0
  170. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/watcher.py +0 -0
  171. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/watcher_test.py +0 -0
  172. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/z3util.py +0 -0
  173. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair/z3util_test.py +0 -0
  174. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair_tool.egg-info/SOURCES.txt +0 -0
  175. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair_tool.egg-info/dependency_links.txt +0 -0
  176. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair_tool.egg-info/entry_points.txt +0 -0
  177. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair_tool.egg-info/requires.txt +4 -4
  178. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/crosshair_tool.egg-info/top_level.txt +0 -0
  179. {crosshair-tool-0.0.85 → crosshair_tool-0.0.86}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: crosshair-tool
3
- Version: 0.0.85
3
+ Version: 0.0.86
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
@@ -22,8 +22,43 @@ Classifier: Topic :: Software Development :: Quality Assurance
22
22
  Classifier: Topic :: Software Development :: Testing
23
23
  Requires-Python: >=3.8
24
24
  Description-Content-Type: text/markdown
25
- Provides-Extra: dev
26
25
  License-File: LICENSE
26
+ Requires-Dist: packaging
27
+ Requires-Dist: typing-inspect>=0.7.1
28
+ Requires-Dist: typing_extensions>=3.10.0
29
+ Requires-Dist: z3-solver>=4.13.0.0
30
+ Requires-Dist: importlib_metadata>=4.0.0
31
+ Requires-Dist: pygls>=1.0.0
32
+ Requires-Dist: typeshed-client>=2.0.5
33
+ Provides-Extra: dev
34
+ Requires-Dist: autodocsumm<1,>=0.2.2; extra == "dev"
35
+ Requires-Dist: black==22.3.0; extra == "dev"
36
+ Requires-Dist: deal>=4.13.0; extra == "dev"
37
+ Requires-Dist: icontract>=2.4.0; extra == "dev"
38
+ Requires-Dist: isort==5.11.5; extra == "dev"
39
+ Requires-Dist: mypy==0.990; extra == "dev"
40
+ Requires-Dist: numpy==1.23.4; python_version < "3.12" and extra == "dev"
41
+ Requires-Dist: numpy==1.26.0; (python_version >= "3.12" and python_version < "3.13") and extra == "dev"
42
+ Requires-Dist: numpy==2.0.1; python_version >= "3.13" and extra == "dev"
43
+ Requires-Dist: pre-commit~=2.20; extra == "dev"
44
+ Requires-Dist: pytest; extra == "dev"
45
+ Requires-Dist: pytest-xdist; extra == "dev"
46
+ Requires-Dist: setuptools; extra == "dev"
47
+ Requires-Dist: sphinx>=3.4.3; extra == "dev"
48
+ Requires-Dist: sphinx-rtd-theme>=0.5.1; extra == "dev"
49
+ Requires-Dist: wheel; extra == "dev"
50
+ Dynamic: author
51
+ Dynamic: author-email
52
+ Dynamic: classifier
53
+ Dynamic: description
54
+ Dynamic: description-content-type
55
+ Dynamic: home-page
56
+ Dynamic: license
57
+ Dynamic: license-file
58
+ Dynamic: provides-extra
59
+ Dynamic: requires-dist
60
+ Dynamic: requires-python
61
+ Dynamic: summary
27
62
 
28
63
  <img src="https://raw.githubusercontent.com/pschanely/CrossHair/main/doc/source/logo-gray.png" width="5%" align="left">
29
64
 
@@ -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.85" # Do not forget to update in setup.py!
18
+ __version__ = "0.0.86" # Do not forget to update in setup.py!
19
19
  __author__ = "Phillip Schanely"
20
20
  __license__ = "MIT"
21
21
  __status__ = "Alpha"
@@ -402,6 +402,10 @@ def crosshair_types_for_python_type(
402
402
  return _PYTYPE_TO_WRAPPER_TYPE.get(origin, ())
403
403
 
404
404
 
405
+ def python_types_using_atomic_symbolics() -> Iterable[Type[AtomicSymbolicValue]]:
406
+ return _PYTYPE_TO_WRAPPER_TYPE.keys()
407
+
408
+
405
409
  class ModelingDirector:
406
410
  def __init__(self, *a) -> None:
407
411
  # Maps python type to the symbolic type we've chosen to represent it (on this iteration)
@@ -3488,10 +3492,6 @@ class LazyIntSymbolicStr(AnySymbolicStr, CrossHairValue):
3488
3492
  otherpoints = [ord(ch) for ch in other]
3489
3493
  with ResumedTracing():
3490
3494
  return mypoints.__eq__(otherpoints)
3491
- elif isinstance(other, SeqBasedSymbolicStr):
3492
- with ResumedTracing():
3493
- otherpoints = [ord(ch) for ch in other]
3494
- return mypoints.__eq__(otherpoints)
3495
3495
  else:
3496
3496
  return NotImplemented
3497
3497
 
@@ -3660,257 +3660,6 @@ class LazyIntSymbolicStr(AnySymbolicStr, CrossHairValue):
3660
3660
  return self._find(substr, start, end, from_right=True)
3661
3661
 
3662
3662
 
3663
- class SeqBasedSymbolicStr(AtomicSymbolicValue, SymbolicSequence, AnySymbolicStr):
3664
- def __init__(self, smtvar: Union[str, z3.ExprRef], typ: Type = str):
3665
- assert typ == str
3666
- SymbolicValue.__init__(self, smtvar, typ)
3667
- self.item_pytype = str
3668
- if isinstance(smtvar, str):
3669
- # Constrain fresh strings to valid codepoints
3670
- space = context_statespace()
3671
- idxvar = z3.Int("idxvar" + space.uniq())
3672
- z3seq = self.var
3673
- space.add(
3674
- z3.ForAll(
3675
- [idxvar], z3.And(0 <= z3seq[idxvar], z3seq[idxvar] <= maxunicode)
3676
- )
3677
- )
3678
-
3679
- @classmethod
3680
- def _ch_smt_sort(cls) -> z3.SortRef:
3681
- return z3.SeqSort(z3.IntSort())
3682
-
3683
- @classmethod
3684
- def _pytype(cls) -> Type:
3685
- return str
3686
-
3687
- @classmethod
3688
- def _smt_promote_literal(cls, literal) -> Optional[z3.SortRef]:
3689
- if isinstance(literal, str):
3690
- if len(literal) <= 1:
3691
- if len(literal) == 0:
3692
- return z3.Empty(z3.SeqSort(z3.IntSort()))
3693
- return z3.Unit(z3IntVal(ord(literal)))
3694
- return z3.Concat([z3.Unit(z3IntVal(ord(ch))) for ch in literal])
3695
- return None
3696
-
3697
- def __ch_realize__(self) -> object:
3698
- codepoints = context_statespace().find_model_value(self.var)
3699
- return "".join(chr(x) for x in codepoints)
3700
-
3701
- def __copy__(self):
3702
- return SeqBasedSymbolicStr(self.var)
3703
-
3704
- def __hash__(self):
3705
- return hash(self.__str__())
3706
-
3707
- @staticmethod
3708
- def _concat_strings(
3709
- a: Union[str, "SeqBasedSymbolicStr"], b: Union[str, "SeqBasedSymbolicStr"]
3710
- ) -> Union[str, "SeqBasedSymbolicStr"]:
3711
- assert not is_tracing()
3712
- # Assumes at least one argument is symbolic and not tracing
3713
- if isinstance(a, SeqBasedSymbolicStr) and isinstance(b, SeqBasedSymbolicStr):
3714
- return SeqBasedSymbolicStr(a.var + b.var)
3715
- elif isinstance(a, str) and isinstance(b, SeqBasedSymbolicStr):
3716
- return SeqBasedSymbolicStr(
3717
- SeqBasedSymbolicStr._coerce_to_smt_sort(a) + b.var
3718
- )
3719
- else:
3720
- assert isinstance(a, SeqBasedSymbolicStr)
3721
- assert isinstance(b, str)
3722
- return SeqBasedSymbolicStr(
3723
- a.var + SeqBasedSymbolicStr._coerce_to_smt_sort(b)
3724
- )
3725
-
3726
- def __add__(self, other):
3727
- with NoTracing():
3728
- if isinstance(other, (SeqBasedSymbolicStr, str)):
3729
- return SeqBasedSymbolicStr._concat_strings(self, other)
3730
- if isinstance(other, AnySymbolicStr):
3731
- return NotImplemented
3732
- raise TypeError
3733
-
3734
- def __radd__(self, other):
3735
- with NoTracing():
3736
- if isinstance(other, (SeqBasedSymbolicStr, str)):
3737
- return SeqBasedSymbolicStr._concat_strings(other, self)
3738
- if isinstance(other, AnySymbolicStr):
3739
- return NotImplemented
3740
- raise TypeError
3741
-
3742
- def __mul__(self, other):
3743
- if isinstance(other, Integral):
3744
- if other <= 1:
3745
- return self if other == 1 else ""
3746
- # Note that in SymbolicInt, we attempt string multiplication via regex.
3747
- # Z3 cannot do much with a symbolic regex, so we case-split on
3748
- # the repetition count.
3749
- return SeqBasedSymbolicStr(z3.Concat(*[self.var for _ in range(other)]))
3750
- return NotImplemented
3751
-
3752
- __rmul__ = __mul__
3753
-
3754
- def __mod__(self, other):
3755
- return self.__str__() % realize(other)
3756
-
3757
- def __contains__(self, other):
3758
- with NoTracing():
3759
- forced = force_to_smt_sort(other, SeqBasedSymbolicStr)
3760
- return SymbolicBool(z3.Contains(self.var, forced))
3761
-
3762
- def __getitem__(self, i: Union[int, slice]):
3763
- with NoTracing():
3764
- idx_or_pair = process_slice_vs_symbolic_len(
3765
- context_statespace(), i, z3.Length(self.var)
3766
- )
3767
- if isinstance(idx_or_pair, tuple):
3768
- (start, stop) = idx_or_pair
3769
- smt_result = z3.Extract(self.var, start, stop - start)
3770
- else:
3771
- smt_result = z3.Unit(self.var[idx_or_pair])
3772
- return SeqBasedSymbolicStr(smt_result)
3773
-
3774
- def endswith(self, substr):
3775
- with NoTracing():
3776
- smt_substr = force_to_smt_sort(substr, SeqBasedSymbolicStr)
3777
- return SymbolicBool(z3.SuffixOf(smt_substr, self.var))
3778
-
3779
- def find(self, substr, start=None, end=None):
3780
- if not isinstance(substr, str):
3781
- raise TypeError
3782
- with NoTracing():
3783
- space = context_statespace()
3784
- smt_my_len = z3.Length(self.var)
3785
- if start is None and end is None:
3786
- smt_start = z3IntVal(0)
3787
- smt_end = smt_my_len
3788
- smt_str = self.var
3789
- if len(substr) == 0:
3790
- return 0
3791
- else:
3792
- (smt_start, smt_end) = flip_slice_vs_symbolic_len(
3793
- space, slice(start, end, None), smt_my_len
3794
- )
3795
- if len(substr) == 0:
3796
- # Add oddity of CPython. We can find the empty string when over-slicing
3797
- # off the left side of the string, but not off the right:
3798
- # ''.find('', 3, 4) == -1
3799
- # ''.find('', -4, -3) == 0
3800
- if space.smt_fork(smt_start > smt_my_len):
3801
- return -1
3802
- elif space.smt_fork(smt_start > 0):
3803
- return SymbolicInt(smt_start)
3804
- else:
3805
- return 0
3806
- (smt_start, smt_end) = clip_range_to_symbolic_len(
3807
- space, smt_start, smt_end, smt_my_len
3808
- )
3809
- smt_str = z3.SubString(self.var, smt_start, smt_end - smt_start)
3810
-
3811
- smt_sub = force_to_smt_sort(substr, SeqBasedSymbolicStr)
3812
- if space.smt_fork(z3.Contains(smt_str, smt_sub)):
3813
- return SymbolicInt(z3.IndexOf(smt_str, smt_sub, 0) + smt_start)
3814
- else:
3815
- return -1
3816
-
3817
- def partition(self, sep: str):
3818
- if not isinstance(sep, str):
3819
- raise TypeError
3820
- if len(sep) == 0:
3821
- raise ValueError
3822
- with NoTracing():
3823
- space = context_statespace()
3824
- smt_str = self.var
3825
- smt_sep = force_to_smt_sort(sep, SeqBasedSymbolicStr)
3826
- if space.smt_fork(z3.Contains(smt_str, smt_sep)):
3827
- uniq = space.uniq()
3828
- # Divide my contents into 4 concatenated parts:
3829
- prefix = SeqBasedSymbolicStr(f"prefix{uniq}")
3830
- match1 = SeqBasedSymbolicStr(
3831
- f"match1{uniq}"
3832
- ) # the first character of the match
3833
- match_tail = SeqBasedSymbolicStr(f"match_tail{uniq}")
3834
- suffix = SeqBasedSymbolicStr(f"suffix{uniq}")
3835
- space.add(z3.Length(match1.var) == 1)
3836
- space.add(smt_sep == z3.Concat(match1.var, match_tail.var))
3837
- space.add(smt_str == z3.Concat(prefix.var, smt_sep, suffix.var))
3838
- space.add(
3839
- z3.Not(z3.Contains(z3.Concat(match_tail.var, suffix.var), smt_sep))
3840
- )
3841
- return (prefix, sep, suffix)
3842
- else:
3843
- return (self, "", "")
3844
-
3845
- def rfind(self, substr, start=None, end=None) -> Union[int, SymbolicInt]:
3846
- if not isinstance(substr, str):
3847
- raise TypeError
3848
- with NoTracing():
3849
- space = context_statespace()
3850
- smt_my_len = z3.Length(self.var)
3851
- if start is None and end is None:
3852
- smt_start = z3IntVal(0)
3853
- smt_end = smt_my_len
3854
- smt_str = self.var
3855
- if len(substr) == 0:
3856
- return SymbolicInt(smt_my_len)
3857
- else:
3858
- (smt_start, smt_end) = flip_slice_vs_symbolic_len(
3859
- space, slice(start, end, None), smt_my_len
3860
- )
3861
- if len(substr) == 0:
3862
- # Add oddity of CPython. We can find the empty string when over-slicing
3863
- # off the left side of the string, but not off the right:
3864
- # ''.find('', 3, 4) == -1
3865
- # ''.find('', -4, -3) == 0
3866
- if space.smt_fork(smt_start > smt_my_len):
3867
- return -1
3868
- elif space.smt_fork(smt_end < 0):
3869
- return 0
3870
- elif space.smt_fork(smt_end < smt_my_len):
3871
- return SymbolicInt(smt_end)
3872
- else:
3873
- return SymbolicInt(smt_my_len)
3874
- (smt_start, smt_end) = clip_range_to_symbolic_len(
3875
- space, smt_start, smt_end, smt_my_len
3876
- )
3877
- smt_str = z3.SubString(self.var, smt_start, smt_end - smt_start)
3878
- smt_sub = force_to_smt_sort(substr, SeqBasedSymbolicStr)
3879
- if space.smt_fork(z3.Contains(smt_str, smt_sub)):
3880
- uniq = space.uniq()
3881
- # Divide my contents into 4 concatenated parts:
3882
- prefix = SeqBasedSymbolicStr(f"prefix{uniq}")
3883
- match1 = SeqBasedSymbolicStr(f"match1{uniq}")
3884
- match_tail = SeqBasedSymbolicStr(f"match_tail{uniq}")
3885
- suffix = SeqBasedSymbolicStr(f"suffix{uniq}")
3886
- space.add(z3.Length(match1.var) == 1)
3887
- space.add(smt_sub == z3.Concat(match1.var, match_tail.var))
3888
- space.add(smt_str == z3.Concat(prefix.var, smt_sub, suffix.var))
3889
- space.add(
3890
- z3.Not(z3.Contains(z3.Concat(match_tail.var, suffix.var), smt_sub))
3891
- )
3892
- return SymbolicInt(smt_start + z3.Length(prefix.var))
3893
- else:
3894
- return -1
3895
-
3896
- def rpartition(self, sep: str):
3897
- result = self.rsplit(sep, maxsplit=1)
3898
- if len(result) == 1:
3899
- return ("", "", self)
3900
- elif len(result) == 2:
3901
- return (result[0], sep, result[1])
3902
-
3903
- def startswith(self, substr, start=None, end=None):
3904
- if isinstance(substr, tuple):
3905
- return any(self.startswith(s, start, end) for s in substr)
3906
- smt_substr = force_to_smt_sort(substr, SeqBasedSymbolicStr)
3907
- if start is not None or end is not None:
3908
- # TODO: "".startswith("", 1) should be False, not True
3909
- return self[start:end].startswith(substr)
3910
- with NoTracing():
3911
- return SymbolicBool(z3.PrefixOf(smt_substr, self.var))
3912
-
3913
-
3914
3663
  def buffer_to_byte_seq(obj: object) -> Optional[Sequence[int]]:
3915
3664
  if isinstance(obj, (bytes, bytearray)):
3916
3665
  return list(obj)
@@ -4822,11 +4571,6 @@ def _ord(c: str) -> int:
4822
4571
  with NoTracing():
4823
4572
  if isinstance(c, LazyIntSymbolicStr):
4824
4573
  return c._codepoints[0]
4825
- elif isinstance(c, SeqBasedSymbolicStr):
4826
- space = context_statespace()
4827
- ret = SymbolicInt("ord" + space.uniq())
4828
- space.add(c.var == z3.Unit(ret.var))
4829
- return ret
4830
4574
  return ord(realize(c))
4831
4575
 
4832
4576
 
@@ -2117,7 +2117,7 @@ def test_dict___bool___ok() -> None:
2117
2117
  check_states(f, CONFIRMED)
2118
2118
 
2119
2119
 
2120
- def test_dict___iter__() -> None:
2120
+ def test_dict___iter___fail() -> None:
2121
2121
  def f(a: Dict[int, str]) -> List[int]:
2122
2122
  """
2123
2123
  post[a]: 5 in _
@@ -30,6 +30,7 @@ def test_mappingproxy_deep_realize(space):
30
30
  assert type(copy) is MappingProxyType
31
31
  with ResumedTracing():
32
32
  val_from_orig = orig[key]
33
- val_from_copy = copy[key]
33
+ realized_key = deep_realize(key)
34
+ val_from_copy = copy[realized_key]
34
35
  assert type(val_from_orig) is SymbolicInt
35
36
  assert type(val_from_copy) is int
@@ -1,10 +1,11 @@
1
1
  import dis
2
2
  import sys
3
3
  import weakref
4
+ from collections import defaultdict
4
5
  from collections.abc import MutableMapping, Set
5
6
  from sys import version_info
6
7
  from types import CodeType, FrameType
7
- from typing import Callable
8
+ from typing import Any, Callable, Iterable, Mapping, Tuple, Union
8
9
 
9
10
  from crosshair.core import (
10
11
  ATOMIC_IMMUTABLE_TYPES,
@@ -13,20 +14,29 @@ from crosshair.core import (
13
14
  )
14
15
  from crosshair.libimpl.builtinslib import (
15
16
  AnySymbolicStr,
17
+ AtomicSymbolicValue,
18
+ ModelingDirector,
16
19
  SymbolicBool,
17
20
  SymbolicInt,
18
21
  SymbolicList,
22
+ python_types_using_atomic_symbolics,
19
23
  )
20
24
  from crosshair.simplestructs import LinearSet, ShellMutableSet, SimpleDict, SliceView
21
25
  from crosshair.statespace import context_statespace
22
26
  from crosshair.tracers import (
23
27
  COMPOSITE_TRACER,
24
28
  NoTracing,
29
+ ResumedTracing,
25
30
  TracingModule,
26
31
  frame_stack_read,
27
32
  frame_stack_write,
28
33
  )
29
- from crosshair.util import CROSSHAIR_EXTRA_ASSERTS, CrossHairInternal, CrossHairValue
34
+ from crosshair.util import (
35
+ CROSSHAIR_EXTRA_ASSERTS,
36
+ CrossHairInternal,
37
+ CrossHairValue,
38
+ debug,
39
+ )
30
40
  from crosshair.z3util import z3Not, z3Or
31
41
 
32
42
  BINARY_SUBSCR = dis.opmap.get("BINARY_SUBSCR", 256)
@@ -60,13 +70,100 @@ _DEEPLY_CONCRETE_KEY_TYPES = (
60
70
  )
61
71
 
62
72
 
73
+ class MultiSubscriptableContainer:
74
+ """Used for indexing a symbolic (non-slice) key into a concrete container"""
75
+
76
+ def __init__(self, container: Union[list, tuple, dict]):
77
+ self.container = container
78
+
79
+ def __getitem__(self, key: AtomicSymbolicValue) -> object:
80
+ with NoTracing():
81
+ space = context_statespace()
82
+ container = self.container
83
+ if isinstance(container, Mapping):
84
+ kv_pairs: Iterable[Tuple[Any, Any]] = container.items()
85
+ else:
86
+ in_bounds = space.smt_fork(
87
+ z3Or(-len(container) <= key.var, key.var < len(container)),
88
+ desc=f"index_in_bounds",
89
+ probability_true=0.9,
90
+ )
91
+ if not in_bounds:
92
+ raise IndexError
93
+ kv_pairs = enumerate(container)
94
+
95
+ values_by_type = defaultdict(list)
96
+ values_by_id = {}
97
+ keys_by_value_id = defaultdict(list)
98
+ symbolic_for_pytype = space.extra(ModelingDirector).choose
99
+ for cur_key, cur_value in kv_pairs:
100
+ if (
101
+ isinstance(cur_value, AtomicSymbolicValue)
102
+ or type(cur_value) in python_types_using_atomic_symbolics()
103
+ ):
104
+ pytype = (
105
+ cur_value._pytype()
106
+ if isinstance(cur_value, AtomicSymbolicValue)
107
+ else type(cur_value)
108
+ )
109
+ # Some types like real-based float and symbolic types don't cover all values:
110
+ if (
111
+ symbolic_for_pytype(pytype)._smt_promote_literal(cur_value)
112
+ is not None
113
+ ):
114
+ values_by_type[pytype].append((cur_key, cur_value))
115
+ continue
116
+ # No symbolics cover this value, but we might still find repeated values:
117
+ values_by_id[id(cur_value)] = cur_value
118
+ keys_by_value_id[id(cur_value)].append(cur_key)
119
+ for value_type, cur_pairs in values_by_type.items():
120
+ hypothetical_result = symbolic_for_pytype(value_type)(
121
+ "item_at_" + space.uniq(), value_type
122
+ )
123
+ with ResumedTracing():
124
+ condition_pairs = []
125
+ for cur_key, cur_val in cur_pairs:
126
+ keys_equal = key == cur_key
127
+ values_equal = hypothetical_result == cur_val
128
+ with NoTracing():
129
+ if isinstance(keys_equal, SymbolicBool):
130
+ condition_pairs.append((keys_equal, values_equal))
131
+ elif keys_equal is False:
132
+ pass
133
+ else:
134
+ # (because the key must be symbolic, we don't ever expect raw True)
135
+ raise CrossHairInternal(
136
+ f"key comparison type: {type(keys_equal)} {keys_equal}"
137
+ )
138
+ if any(keys_equal for keys_equal, _ in condition_pairs):
139
+ space.add(any([all(pair) for pair in condition_pairs]))
140
+ return hypothetical_result
141
+
142
+ for (value_id, value), probability_true in with_uniform_probabilities(
143
+ values_by_id.items()
144
+ ):
145
+ keys_for_value = keys_by_value_id[value_id]
146
+ with ResumedTracing():
147
+ is_match = any([key == k for k in keys_for_value])
148
+ if isinstance(is_match, SymbolicBool):
149
+ if space.smt_fork(
150
+ is_match.var,
151
+ probability_true=probability_true,
152
+ ):
153
+ return value
154
+ elif is_match:
155
+ return value
156
+
157
+ if type(container) is dict:
158
+ raise KeyError # ( f"Key {key} not found in dict")
159
+ else:
160
+ raise IndexError # (f"Index {key} out of range for list/tuple of length {len(container)}")
161
+
162
+
63
163
  class SymbolicSubscriptInterceptor(TracingModule):
64
164
  opcodes_wanted = frozenset([BINARY_SUBSCR, BINARY_OP])
65
165
 
66
166
  def trace_op(self, frame, codeobj, codenum):
67
- # Note that because this is called from inside a Python trace handler, tracing
68
- # is automatically disabled, so there's no need for a `with NoTracing():` guard.
69
-
70
167
  if codenum == BINARY_OP:
71
168
  oparg = frame_op_arg(frame)
72
169
  if oparg != 26: # subscript operator, NB_SUBSCR
@@ -78,7 +175,14 @@ class SymbolicSubscriptInterceptor(TracingModule):
78
175
  # If we got this far, the index is likely symbolic (or perhaps a slice object)
79
176
  container = frame_stack_read(frame, -2)
80
177
  container_type = type(container)
81
- if container_type is dict:
178
+ if isinstance(key, AtomicSymbolicValue) and type(container) in (
179
+ tuple,
180
+ list,
181
+ dict,
182
+ ):
183
+ wrapped_container = MultiSubscriptableContainer(container)
184
+ frame_stack_write(frame, -2, wrapped_container)
185
+ elif container_type is dict:
82
186
  # SimpleDict won't hash the keys it's given!
83
187
  wrapped_dict = SimpleDict(list(container.items()))
84
188
  frame_stack_write(frame, -2, wrapped_dict)
@@ -90,41 +194,6 @@ class SymbolicSubscriptInterceptor(TracingModule):
90
194
  if isinstance(start, SymbolicInt) or isinstance(stop, SymbolicInt):
91
195
  view_wrapper = SliceView(container, 0, len(container))
92
196
  frame_stack_write(frame, -2, SymbolicList(view_wrapper))
93
- elif container_type is list or container_type is tuple:
94
- if not isinstance(key, SymbolicInt):
95
- return
96
- # We can't stay symbolic with a concrete list and symbolic numeric index.
97
- # But we can make the choice evenly and combine duplicate values, if any.
98
-
99
- space = context_statespace()
100
- in_bounds = space.smt_fork(
101
- z3Or(-len(container) <= key.var, key.var < len(container)),
102
- desc=f"index_in_bounds",
103
- probability_true=0.9,
104
- )
105
- if not in_bounds:
106
- return
107
- # TODO: `container` should be the same (per path node) on every run;
108
- # it would be great to cache this computation somehow.
109
- indices = {}
110
- for idx, value in enumerate(container):
111
- value_id = id(value)
112
- if value_id in indices:
113
- indices[value_id].append(idx)
114
- else:
115
- indices[value_id] = [idx]
116
- for value_id, probability_true in with_uniform_probabilities(
117
- indices.keys()
118
- ):
119
- indices_with_value = indices[value_id]
120
- if space.smt_fork(
121
- z3Or(*[key.var == i for i in indices_with_value]),
122
- desc=f"index_to_{'_or_'.join(map(str, indices_with_value))}",
123
- probability_true=probability_true,
124
- ):
125
- # avoids realization of `key` in case `container` has duplicates
126
- frame_stack_write(frame, -1, indices_with_value[0])
127
- break
128
197
 
129
198
 
130
199
  class SymbolicSliceInterceptor(TracingModule):