tpy-lang 0.3.0.dev0__py3-none-any.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 (333) hide show
  1. tpy_lang-0.3.0.dev0.dist-info/METADATA +151 -0
  2. tpy_lang-0.3.0.dev0.dist-info/RECORD +333 -0
  3. tpy_lang-0.3.0.dev0.dist-info/WHEEL +4 -0
  4. tpy_lang-0.3.0.dev0.dist-info/entry_points.txt +3 -0
  5. tpyc/__init__.py +104 -0
  6. tpyc/__main__.py +6 -0
  7. tpyc/_buildinfo.py +1 -0
  8. tpyc/_data/docs/LANGUAGE_FEATURES.md +6278 -0
  9. tpyc/_data/docs/STDLIB_ROADMAP.md +1258 -0
  10. tpyc/_data/docs/TPY_FOR_AGENTS.md +556 -0
  11. tpyc/_data/lib/tpy/_bindings/__init__.py +6 -0
  12. tpyc/_data/lib/tpy/_bindings/pcre2.py +173 -0
  13. tpyc/_data/lib/tpy/_bindings/posix_socket.py +161 -0
  14. tpyc/_data/lib/tpy/_functools_macros.py +80 -0
  15. tpyc/_data/lib/tpy/_macro_helpers.py +161 -0
  16. tpyc/_data/lib/tpy/argparse.py +2062 -0
  17. tpyc/_data/lib/tpy/asyncio/__init__.py +744 -0
  18. tpyc/_data/lib/tpy/asyncio/_executor.py +515 -0
  19. tpyc/_data/lib/tpy/base64.py +410 -0
  20. tpyc/_data/lib/tpy/bisect.py +39 -0
  21. tpyc/_data/lib/tpy/builtins.py +38 -0
  22. tpyc/_data/lib/tpy/dataclasses.py +354 -0
  23. tpyc/_data/lib/tpy/enum.py +23 -0
  24. tpyc/_data/lib/tpy/functools.py +33 -0
  25. tpyc/_data/lib/tpy/hashlib.py +206 -0
  26. tpyc/_data/lib/tpy/heapq.py +118 -0
  27. tpyc/_data/lib/tpy/io.py +395 -0
  28. tpyc/_data/lib/tpy/json.py +221 -0
  29. tpyc/_data/lib/tpy/math.py +406 -0
  30. tpyc/_data/lib/tpy/random.py +597 -0
  31. tpyc/_data/lib/tpy/re.py +467 -0
  32. tpyc/_data/lib/tpy/socket.py +379 -0
  33. tpyc/_data/lib/tpy/struct.py +178 -0
  34. tpyc/_data/lib/tpy/sys.py +40 -0
  35. tpyc/_data/lib/tpy/time.py +39 -0
  36. tpyc/_data/lib/tpy/tpy/__init__.py +78 -0
  37. tpyc/_data/lib/tpy/tpy/_bootstrap/__init__.py +10 -0
  38. tpyc/_data/lib/tpy/tpy/_bootstrap/_decorators.py +37 -0
  39. tpyc/_data/lib/tpy/tpy/_bootstrap/_extern.py +64 -0
  40. tpyc/_data/lib/tpy/tpy/_builtins/__init__.py +11 -0
  41. tpyc/_data/lib/tpy/tpy/_builtins/_bytes.py +378 -0
  42. tpyc/_data/lib/tpy/tpy/_builtins/_dict.py +151 -0
  43. tpyc/_data/lib/tpy/tpy/_builtins/_exceptions.py +125 -0
  44. tpyc/_data/lib/tpy/tpy/_builtins/_funcs.py +681 -0
  45. tpyc/_data/lib/tpy/tpy/_builtins/_io.py +97 -0
  46. tpyc/_data/lib/tpy/tpy/_builtins/_list.py +127 -0
  47. tpyc/_data/lib/tpy/tpy/_builtins/_range.py +52 -0
  48. tpyc/_data/lib/tpy/tpy/_builtins/_set.py +139 -0
  49. tpyc/_data/lib/tpy/tpy/_builtins/_super.py +11 -0
  50. tpyc/_data/lib/tpy/tpy/_builtins/_types.py +661 -0
  51. tpyc/_data/lib/tpy/tpy/_core/__init__.py +23 -0
  52. tpyc/_data/lib/tpy/tpy/_core/_bytes_view.py +129 -0
  53. tpyc/_data/lib/tpy/tpy/_core/_containers.py +137 -0
  54. tpyc/_data/lib/tpy/tpy/_core/_functions.py +40 -0
  55. tpyc/_data/lib/tpy/tpy/_core/_types.py +2061 -0
  56. tpyc/_data/lib/tpy/tpy/_typing/__init__.py +77 -0
  57. tpyc/_data/lib/tpy/tpy/_version.py +29 -0
  58. tpyc/_data/lib/tpy/tpy/bits.py +28 -0
  59. tpyc/_data/lib/tpy/tpy/coro/__init__.py +127 -0
  60. tpyc/_data/lib/tpy/tpy/extern.py +8 -0
  61. tpyc/_data/lib/tpy/tpy/mem.py +49 -0
  62. tpyc/_data/lib/tpy/tpy/unsafe.py +195 -0
  63. tpyc/_data/lib/tpy/tpy/version.py +21 -0
  64. tpyc/_data/lib/tpy/typing.py +13 -0
  65. tpyc/_data/runtime/cpp/include/tpy/any.hpp +461 -0
  66. tpyc/_data/runtime/cpp/include/tpy/as_ostream.hpp +117 -0
  67. tpyc/_data/runtime/cpp/include/tpy/async.hpp +76 -0
  68. tpyc/_data/runtime/cpp/include/tpy/bigint.hpp +1343 -0
  69. tpyc/_data/runtime/cpp/include/tpy/builtins.hpp +400 -0
  70. tpyc/_data/runtime/cpp/include/tpy/bytes_ops.hpp +469 -0
  71. tpyc/_data/runtime/cpp/include/tpy/container_ops.hpp +487 -0
  72. tpyc/_data/runtime/cpp/include/tpy/copy_iter.hpp +82 -0
  73. tpyc/_data/runtime/cpp/include/tpy/core.hpp +558 -0
  74. tpyc/_data/runtime/cpp/include/tpy/dict_ops.hpp +289 -0
  75. tpyc/_data/runtime/cpp/include/tpy/dunder.hpp +750 -0
  76. tpyc/_data/runtime/cpp/include/tpy/dynamic.hpp +44 -0
  77. tpyc/_data/runtime/cpp/include/tpy/enum.hpp +40 -0
  78. tpyc/_data/runtime/cpp/include/tpy/file.hpp +245 -0
  79. tpyc/_data/runtime/cpp/include/tpy/fixed_int.hpp +317 -0
  80. tpyc/_data/runtime/cpp/include/tpy/format.hpp +954 -0
  81. tpyc/_data/runtime/cpp/include/tpy/frame_slot.hpp +120 -0
  82. tpyc/_data/runtime/cpp/include/tpy/generator.hpp +47 -0
  83. tpyc/_data/runtime/cpp/include/tpy/iterable_ops.hpp +122 -0
  84. tpyc/_data/runtime/cpp/include/tpy/itertools.hpp +749 -0
  85. tpyc/_data/runtime/cpp/include/tpy/next_iter.hpp +82 -0
  86. tpyc/_data/runtime/cpp/include/tpy/ordered_map.hpp +518 -0
  87. tpyc/_data/runtime/cpp/include/tpy/ordered_set.hpp +337 -0
  88. tpyc/_data/runtime/cpp/include/tpy/own_iter.hpp +54 -0
  89. tpyc/_data/runtime/cpp/include/tpy/pascal_graph_sdl.hpp +192 -0
  90. tpyc/_data/runtime/cpp/include/tpy/printing.hpp +302 -0
  91. tpyc/_data/runtime/cpp/include/tpy/protocols.hpp +61 -0
  92. tpyc/_data/runtime/cpp/include/tpy/range.hpp +115 -0
  93. tpyc/_data/runtime/cpp/include/tpy/ranges.hpp +212 -0
  94. tpyc/_data/runtime/cpp/include/tpy/set_ops.hpp +265 -0
  95. tpyc/_data/runtime/cpp/include/tpy/slice.hpp +47 -0
  96. tpyc/_data/runtime/cpp/include/tpy/span_iter.hpp +42 -0
  97. tpyc/_data/runtime/cpp/include/tpy/stdlib/math.hpp +41 -0
  98. tpyc/_data/runtime/cpp/include/tpy/stdlib/pcre2_h.hpp +96 -0
  99. tpyc/_data/runtime/cpp/include/tpy/stdlib/random.hpp +25 -0
  100. tpyc/_data/runtime/cpp/include/tpy/stdlib/socket_h.hpp +145 -0
  101. tpyc/_data/runtime/cpp/include/tpy/stdlib/time.hpp +62 -0
  102. tpyc/_data/runtime/cpp/include/tpy/system.hpp +121 -0
  103. tpyc/_data/runtime/cpp/include/tpy/throwable.hpp +55 -0
  104. tpyc/_data/runtime/cpp/include/tpy/tpy.hpp +156 -0
  105. tpyc/_data/runtime/cpp/include/tpy/type_name.hpp +77 -0
  106. tpyc/_data/runtime/cpp/include/tpy/type_traits.hpp +240 -0
  107. tpyc/_data/runtime/cpp/include/tpy/uninit_array_storage.hpp +250 -0
  108. tpyc/_data/runtime/cpp/include/tpy/uninit_heap_storage.hpp +277 -0
  109. tpyc/_data/runtime/cpp/include/tpy/varargs.hpp +174 -0
  110. tpyc/_data/runtime/cpp/include/tpy/variant_ref.hpp +118 -0
  111. tpyc/_data/runtime/cpp/src/stdlib/socket_impl.cpp +104 -0
  112. tpyc/_data/runtime/cpp/third_party/README.md +58 -0
  113. tpyc/_data/runtime/cpp/third_party/pcre2/AUTHORS +36 -0
  114. tpyc/_data/runtime/cpp/third_party/pcre2/CMakeLists.txt +1233 -0
  115. tpyc/_data/runtime/cpp/third_party/pcre2/COPYING +5 -0
  116. tpyc/_data/runtime/cpp/third_party/pcre2/ChangeLog +3097 -0
  117. tpyc/_data/runtime/cpp/third_party/pcre2/HACKING +853 -0
  118. tpyc/_data/runtime/cpp/third_party/pcre2/INSTALL +368 -0
  119. tpyc/_data/runtime/cpp/third_party/pcre2/LICENCE +94 -0
  120. tpyc/_data/runtime/cpp/third_party/pcre2/NEWS +492 -0
  121. tpyc/_data/runtime/cpp/third_party/pcre2/NON-AUTOTOOLS-BUILD +430 -0
  122. tpyc/_data/runtime/cpp/third_party/pcre2/README +956 -0
  123. tpyc/_data/runtime/cpp/third_party/pcre2/cmake/COPYING-CMAKE-SCRIPTS +22 -0
  124. tpyc/_data/runtime/cpp/third_party/pcre2/cmake/FindEditline.cmake +16 -0
  125. tpyc/_data/runtime/cpp/third_party/pcre2/cmake/FindPackageHandleStandardArgs.cmake +58 -0
  126. tpyc/_data/runtime/cpp/third_party/pcre2/cmake/FindReadline.cmake +29 -0
  127. tpyc/_data/runtime/cpp/third_party/pcre2/cmake/pcre2-config-version.cmake.in +15 -0
  128. tpyc/_data/runtime/cpp/third_party/pcre2/cmake/pcre2-config.cmake.in +148 -0
  129. tpyc/_data/runtime/cpp/third_party/pcre2/config-cmake.h.in +56 -0
  130. tpyc/_data/runtime/cpp/third_party/pcre2/libpcre2-16.pc.in +13 -0
  131. tpyc/_data/runtime/cpp/third_party/pcre2/libpcre2-32.pc.in +13 -0
  132. tpyc/_data/runtime/cpp/third_party/pcre2/libpcre2-8.pc.in +13 -0
  133. tpyc/_data/runtime/cpp/third_party/pcre2/libpcre2-posix.pc.in +13 -0
  134. tpyc/_data/runtime/cpp/third_party/pcre2/pcre2-config.in +121 -0
  135. tpyc/_data/runtime/cpp/third_party/pcre2/src/config.h +483 -0
  136. tpyc/_data/runtime/cpp/third_party/pcre2/src/config.h.generic +483 -0
  137. tpyc/_data/runtime/cpp/third_party/pcre2/src/config.h.in +460 -0
  138. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2.h +1010 -0
  139. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2.h.generic +1010 -0
  140. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2.h.in +1010 -0
  141. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_auto_possess.c +1371 -0
  142. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_chartables.c +196 -0
  143. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_chartables.c.dist +196 -0
  144. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_chkdint.c +96 -0
  145. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_compile.c +11001 -0
  146. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_config.c +252 -0
  147. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_context.c +510 -0
  148. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_convert.c +1189 -0
  149. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_dfa_match.c +4119 -0
  150. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_dftables.c +297 -0
  151. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_error.c +345 -0
  152. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_extuni.c +162 -0
  153. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_find_bracket.c +219 -0
  154. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_fuzzsupport.c +792 -0
  155. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_internal.h +2084 -0
  156. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_intmodedep.h +940 -0
  157. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_jit_compile.c +14972 -0
  158. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_jit_match.c +200 -0
  159. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_jit_misc.c +234 -0
  160. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_jit_neon_inc.h +354 -0
  161. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_jit_simd_inc.h +2355 -0
  162. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_jit_test.c +2528 -0
  163. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_maketables.c +165 -0
  164. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_match.c +7777 -0
  165. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_match_data.c +185 -0
  166. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_newline.c +243 -0
  167. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_ord2utf.c +120 -0
  168. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_pattern_info.c +432 -0
  169. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_printint.c +886 -0
  170. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_script_run.c +344 -0
  171. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_serialize.c +286 -0
  172. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_string_utils.c +237 -0
  173. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_study.c +1915 -0
  174. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_substitute.c +1009 -0
  175. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_substring.c +550 -0
  176. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_tables.c +234 -0
  177. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_ucd.c +5460 -0
  178. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_ucp.h +396 -0
  179. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_ucptables.c +1533 -0
  180. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_valid_utf.c +398 -0
  181. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_xclass.c +308 -0
  182. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2demo.c +497 -0
  183. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2grep.c +4606 -0
  184. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2posix.c +425 -0
  185. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2posix.h +187 -0
  186. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2posix_test.c +209 -0
  187. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2test.c +9708 -0
  188. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/allocator_src/sljitExecAllocatorApple.c +137 -0
  189. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/allocator_src/sljitExecAllocatorCore.c +327 -0
  190. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/allocator_src/sljitExecAllocatorFreeBSD.c +89 -0
  191. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/allocator_src/sljitExecAllocatorPosix.c +62 -0
  192. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/allocator_src/sljitExecAllocatorWindows.c +40 -0
  193. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/allocator_src/sljitProtExecAllocatorNetBSD.c +72 -0
  194. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/allocator_src/sljitProtExecAllocatorPosix.c +172 -0
  195. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/allocator_src/sljitWXExecAllocatorPosix.c +141 -0
  196. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/allocator_src/sljitWXExecAllocatorWindows.c +102 -0
  197. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitConfig.h +142 -0
  198. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitConfigCPU.h +188 -0
  199. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitConfigInternal.h +907 -0
  200. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitLir.c +3561 -0
  201. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitLir.h +2466 -0
  202. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeARM_32.c +4636 -0
  203. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeARM_64.c +3491 -0
  204. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeARM_T2_32.c +4302 -0
  205. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeLOONGARCH_64.c +3765 -0
  206. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeMIPS_32.c +472 -0
  207. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeMIPS_64.c +387 -0
  208. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeMIPS_common.c +4259 -0
  209. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativePPC_32.c +485 -0
  210. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativePPC_64.c +719 -0
  211. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativePPC_common.c +3161 -0
  212. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeRISCV_32.c +142 -0
  213. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeRISCV_64.c +222 -0
  214. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeRISCV_common.c +3121 -0
  215. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeS390X.c +4526 -0
  216. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeX86_32.c +1685 -0
  217. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeX86_64.c +1398 -0
  218. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeX86_common.c +5001 -0
  219. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitSerialize.c +516 -0
  220. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitUtils.c +344 -0
  221. tpyc/_data/runtime/cpp/third_party/pcre2.sources.txt +54 -0
  222. tpyc/_data/runtime/cpp/third_party/pcre2.vendor.json +7 -0
  223. tpyc/build/__init__.py +7 -0
  224. tpyc/build/pcre2.py +122 -0
  225. tpyc/build/third_party.py +413 -0
  226. tpyc/cli.py +822 -0
  227. tpyc/codegen_cpp/__init__.py +18 -0
  228. tpyc/codegen_cpp/builtins.py +484 -0
  229. tpyc/codegen_cpp/context.py +2064 -0
  230. tpyc/codegen_cpp/expressions.py +5940 -0
  231. tpyc/codegen_cpp/functions.py +1913 -0
  232. tpyc/codegen_cpp/gen_async.py +3258 -0
  233. tpyc/codegen_cpp/gen_generators.py +657 -0
  234. tpyc/codegen_cpp/generator.py +2258 -0
  235. tpyc/codegen_cpp/match.py +1997 -0
  236. tpyc/codegen_cpp/param_const.py +172 -0
  237. tpyc/codegen_cpp/protocols.py +907 -0
  238. tpyc/codegen_cpp/records.py +1654 -0
  239. tpyc/codegen_cpp/resumable_cfg.py +1651 -0
  240. tpyc/codegen_cpp/statements.py +4963 -0
  241. tpyc/codegen_cpp/string_dispatch.py +76 -0
  242. tpyc/codegen_cpp/test_context.py +46 -0
  243. tpyc/codegen_cpp/test_param_const.py +113 -0
  244. tpyc/codegen_cpp/test_resumable_cfg.py +182 -0
  245. tpyc/codegen_cpp/type_resolution.py +53 -0
  246. tpyc/codegen_cpp/types.py +436 -0
  247. tpyc/codegen_cpp/variant_access.py +135 -0
  248. tpyc/coercions.py +749 -0
  249. tpyc/compilation_context.py +57 -0
  250. tpyc/compiler.py +3945 -0
  251. tpyc/cycle_detection.py +358 -0
  252. tpyc/diagnostics.py +135 -0
  253. tpyc/dump_types.py +353 -0
  254. tpyc/frontend_diagnostics.py +47 -0
  255. tpyc/frontend_ir/__init__.py +140 -0
  256. tpyc/frontend_ir/lower.py +1098 -0
  257. tpyc/frontend_ir/nodes.py +718 -0
  258. tpyc/frontend_ir/resolver_adapter.py +151 -0
  259. tpyc/frontend_plugin.py +209 -0
  260. tpyc/install_docs.py +81 -0
  261. tpyc/liveness.py +756 -0
  262. tpyc/macro_api.py +1724 -0
  263. tpyc/macro_loader.py +497 -0
  264. tpyc/module_names.py +64 -0
  265. tpyc/modules/__init__.py +31 -0
  266. tpyc/modules/defs.py +89 -0
  267. tpyc/modules/registry.py +36 -0
  268. tpyc/modules/resolver.py +192 -0
  269. tpyc/modules/type_resolution.py +629 -0
  270. tpyc/namespace.py +172 -0
  271. tpyc/parse/__init__.py +84 -0
  272. tpyc/parse/imports.py +490 -0
  273. tpyc/parse/nodes.py +1732 -0
  274. tpyc/parse/parser.py +4043 -0
  275. tpyc/parse/resolve_refs.py +466 -0
  276. tpyc/parse/type_resolver.py +1060 -0
  277. tpyc/prescan.py +254 -0
  278. tpyc/qnames.py +149 -0
  279. tpyc/repl.py +529 -0
  280. tpyc/repl_backends.py +848 -0
  281. tpyc/sema/__init__.py +21 -0
  282. tpyc/sema/analyzer.py +3625 -0
  283. tpyc/sema/bound_check.py +72 -0
  284. tpyc/sema/builder_trace.py +684 -0
  285. tpyc/sema/calls.py +5406 -0
  286. tpyc/sema/compatibility.py +2107 -0
  287. tpyc/sema/context.py +1243 -0
  288. tpyc/sema/expressions.py +3737 -0
  289. tpyc/sema/flow_facts.py +199 -0
  290. tpyc/sema/init_tracker.py +150 -0
  291. tpyc/sema/list_literals.py +69 -0
  292. tpyc/sema/literal_utils.py +27 -0
  293. tpyc/sema/local_deduction.py +1088 -0
  294. tpyc/sema/macros.py +179 -0
  295. tpyc/sema/match.py +1177 -0
  296. tpyc/sema/method_expansion.py +347 -0
  297. tpyc/sema/methods.py +2197 -0
  298. tpyc/sema/mutation_propagation.py +268 -0
  299. tpyc/sema/narrowing.py +857 -0
  300. tpyc/sema/numeric_lattice.py +160 -0
  301. tpyc/sema/operators.py +402 -0
  302. tpyc/sema/overloads.py +841 -0
  303. tpyc/sema/protocols.py +1209 -0
  304. tpyc/sema/reach_analysis.py +202 -0
  305. tpyc/sema/registration.py +3156 -0
  306. tpyc/sema/scope_tracker.py +193 -0
  307. tpyc/sema/statements.py +4426 -0
  308. tpyc/sema/type_ops.py +1879 -0
  309. tpyc/sema/value_range.py +181 -0
  310. tpyc/symbol_binding.py +259 -0
  311. tpyc/test_c3_mro.py +208 -0
  312. tpyc/test_cli_argv.py +52 -0
  313. tpyc/test_compiler.py +559 -0
  314. tpyc/test_contains_type_param.py +101 -0
  315. tpyc/test_cycle_detection.py +221 -0
  316. tpyc/test_dump_types.py +225 -0
  317. tpyc/test_install_docs.py +65 -0
  318. tpyc/test_local_cpp_form.py +135 -0
  319. tpyc/test_macro_loader.py +76 -0
  320. tpyc/test_method_expansion.py +254 -0
  321. tpyc/test_nominal_identity.py +182 -0
  322. tpyc/test_overloads.py +410 -0
  323. tpyc/test_parse.py +303 -0
  324. tpyc/test_parse_type_ref.py +506 -0
  325. tpyc/test_parse_version_info.py +58 -0
  326. tpyc/test_reach_analysis.py +72 -0
  327. tpyc/test_ref_type.py +216 -0
  328. tpyc/test_send_sync_substitution.py +276 -0
  329. tpyc/test_tuple_mutation_propagation.py +206 -0
  330. tpyc/test_type_def_registry.py +1729 -0
  331. tpyc/test_union_types.py +195 -0
  332. tpyc/type_def_registry.py +975 -0
  333. tpyc/typesys.py +5104 -0
@@ -0,0 +1,506 @@
1
+ """Tests for the syntactic type-ref walker (Phase F.3b.1).
2
+
3
+ Verifies that `Parser._parse_type_ref` produces the expected TypeRefNode
4
+ shape for representative Python type annotations. The resolver
5
+ (F.3b.2+) is out of scope for this test -- here we only pin the
6
+ syntactic output.
7
+ """
8
+
9
+ from __future__ import annotations
10
+ import ast
11
+
12
+ import pytest
13
+
14
+ from .parse import (
15
+ Parser, ParseError,
16
+ TpyTypeRef, TpyUnionRef, TpyCallableRef, TpyLiteralRef,
17
+ )
18
+ from .typesys import LiteralValue, LiteralTag
19
+
20
+
21
+ def _make_parser() -> Parser:
22
+ """Create a parser with imports that enable all structural-wrapper
23
+ recognition paths plus primitive names."""
24
+ parser = Parser()
25
+ parser.parse(
26
+ "from tpy import Ptr, Own, readonly, auto_readonly, auto_own, Fn\n"
27
+ "from tpy import (Int8, Int16, Int32, Int64, UInt8, UInt16, UInt32, UInt64,\n"
28
+ " Char, Float32, String, StrView, BytesView,\n"
29
+ " basic_slice, slice, Array, Span)\n"
30
+ "from typing import Optional, Final, Callable, Literal, Self\n"
31
+ "pass\n",
32
+ module_name="test_module",
33
+ )
34
+ return parser
35
+
36
+
37
+ def _parse_ann(parser: Parser, annotation_src: str):
38
+ """Parse a type annotation source fragment into a TypeRefNode."""
39
+ tree = ast.parse(f"x: {annotation_src}\n")
40
+ ann_node = tree.body[0].annotation
41
+ return parser._parse_type_ref(ann_node)
42
+
43
+
44
+ class TestLeafNames:
45
+ def test_bare_name(self):
46
+ ref = _parse_ann(_make_parser(), "Int32")
47
+ assert isinstance(ref, TpyTypeRef)
48
+ assert ref.name == "Int32"
49
+ assert ref.args == ()
50
+
51
+ def test_user_record_name(self):
52
+ ref = _parse_ann(_make_parser(), "MyRecord")
53
+ assert isinstance(ref, TpyTypeRef)
54
+ assert ref.name == "MyRecord"
55
+ assert ref.args == ()
56
+
57
+ def test_none_constant(self):
58
+ ref = _parse_ann(_make_parser(), "None")
59
+ assert isinstance(ref, TpyTypeRef)
60
+ assert ref.name == "None"
61
+
62
+ def test_dotted_attribute(self):
63
+ ref = _parse_ann(_make_parser(), "Outer.Inner")
64
+ assert isinstance(ref, TpyTypeRef)
65
+ assert ref.name == "Outer.Inner"
66
+ assert ref.args == ()
67
+
68
+ def test_deep_dotted(self):
69
+ ref = _parse_ann(_make_parser(), "a.b.c.D")
70
+ assert isinstance(ref, TpyTypeRef)
71
+ assert ref.name == "a.b.c.D"
72
+
73
+
74
+ class TestGenerics:
75
+ def test_list_of_int(self):
76
+ ref = _parse_ann(_make_parser(), "list[Int32]")
77
+ assert isinstance(ref, TpyTypeRef)
78
+ assert ref.name == "list"
79
+ assert len(ref.args) == 1
80
+ inner = ref.args[0]
81
+ assert isinstance(inner, TpyTypeRef) and inner.name == "Int32"
82
+
83
+ def test_dict_of_str_int(self):
84
+ ref = _parse_ann(_make_parser(), "dict[str, Int32]")
85
+ assert isinstance(ref, TpyTypeRef)
86
+ assert ref.name == "dict"
87
+ assert len(ref.args) == 2
88
+ k, v = ref.args
89
+ assert isinstance(k, TpyTypeRef) and k.name == "str"
90
+ assert isinstance(v, TpyTypeRef) and v.name == "Int32"
91
+
92
+ def test_array_with_int_size(self):
93
+ ref = _parse_ann(_make_parser(), "Array[Int32, 8]")
94
+ assert isinstance(ref, TpyTypeRef)
95
+ assert ref.name == "Array"
96
+ assert len(ref.args) == 2
97
+ elem, size = ref.args
98
+ assert isinstance(elem, TpyTypeRef) and elem.name == "Int32"
99
+ assert size == 8
100
+
101
+ def test_nested_generic(self):
102
+ ref = _parse_ann(_make_parser(), "list[dict[str, Int32]]")
103
+ assert isinstance(ref, TpyTypeRef) and ref.name == "list"
104
+ outer_arg = ref.args[0]
105
+ assert isinstance(outer_arg, TpyTypeRef) and outer_arg.name == "dict"
106
+ k, v = outer_arg.args
107
+ assert isinstance(k, TpyTypeRef) and k.name == "str"
108
+ assert isinstance(v, TpyTypeRef) and v.name == "Int32"
109
+
110
+ def test_user_generic_record(self):
111
+ ref = _parse_ann(_make_parser(), "Stack[Int32]")
112
+ assert isinstance(ref, TpyTypeRef)
113
+ assert ref.name == "Stack"
114
+ assert len(ref.args) == 1
115
+ assert isinstance(ref.args[0], TpyTypeRef) and ref.args[0].name == "Int32"
116
+
117
+
118
+ class TestStructuralWrappers:
119
+ # Canonical structural wrappers use qualified names ("tpy:Ptr",
120
+ # "typing:Optional", ...) so they don't collide with raw user-source
121
+ # names like "Ptr" or "Optional" (the resolver's wrapper dispatch must
122
+ # only fire when the walker confirmed module resolution).
123
+
124
+ def test_ptr(self):
125
+ ref = _parse_ann(_make_parser(), "Ptr[Int32]")
126
+ assert isinstance(ref, TpyTypeRef)
127
+ assert ref.name == "tpy:Ptr"
128
+ assert len(ref.args) == 1
129
+ assert isinstance(ref.args[0], TpyTypeRef) and ref.args[0].name == "Int32"
130
+
131
+ def test_own(self):
132
+ ref = _parse_ann(_make_parser(), "Own[MyRecord]")
133
+ assert isinstance(ref, TpyTypeRef)
134
+ assert ref.name == "tpy:Own"
135
+
136
+ def test_readonly(self):
137
+ ref = _parse_ann(_make_parser(), "readonly[Int32]")
138
+ assert isinstance(ref, TpyTypeRef)
139
+ assert ref.name == "tpy:readonly"
140
+
141
+ def test_auto_readonly(self):
142
+ ref = _parse_ann(_make_parser(), "auto_readonly[Int32]")
143
+ assert isinstance(ref, TpyTypeRef)
144
+ assert ref.name == "tpy:auto_readonly"
145
+
146
+ def test_auto_own(self):
147
+ ref = _parse_ann(_make_parser(), "auto_own[MyRecord]")
148
+ assert isinstance(ref, TpyTypeRef)
149
+ assert ref.name == "tpy:auto_own"
150
+
151
+ def test_optional(self):
152
+ ref = _parse_ann(_make_parser(), "Optional[Int32]")
153
+ assert isinstance(ref, TpyTypeRef)
154
+ assert ref.name == "typing:Optional"
155
+
156
+ def test_final(self):
157
+ ref = _parse_ann(_make_parser(), "Final[Int32]")
158
+ assert isinstance(ref, TpyTypeRef)
159
+ assert ref.name == "typing:Final"
160
+
161
+ def test_ptr_of_readonly(self):
162
+ # Ptr[readonly[Int32]] -- readonly nested under Ptr.
163
+ # The resolver applies Ptr.is_readonly; walker just records structure.
164
+ ref = _parse_ann(_make_parser(), "Ptr[readonly[Int32]]")
165
+ assert isinstance(ref, TpyTypeRef) and ref.name == "tpy:Ptr"
166
+ inner = ref.args[0]
167
+ assert isinstance(inner, TpyTypeRef) and inner.name == "tpy:readonly"
168
+ leaf = inner.args[0]
169
+ assert isinstance(leaf, TpyTypeRef) and leaf.name == "Int32"
170
+
171
+
172
+ class TestTuple:
173
+ def test_empty_tuple_allowed_syntactically(self):
174
+ # Parser-level: tuple with no args is syntactically valid here; the
175
+ # resolver raises.
176
+ ref = _parse_ann(_make_parser(), "tuple[Int32]")
177
+ assert isinstance(ref, TpyTypeRef) and ref.name == "builtins:tuple"
178
+ assert len(ref.args) == 1
179
+
180
+ def test_tuple_multiple(self):
181
+ ref = _parse_ann(_make_parser(), "tuple[Int32, str, bool]")
182
+ assert isinstance(ref, TpyTypeRef) and ref.name == "builtins:tuple"
183
+ assert len(ref.args) == 3
184
+ assert all(isinstance(a, TpyTypeRef) for a in ref.args)
185
+
186
+
187
+ class TestUnion:
188
+ def test_simple_union(self):
189
+ ref = _parse_ann(_make_parser(), "Int32 | str")
190
+ assert isinstance(ref, TpyUnionRef)
191
+ assert len(ref.members) == 2
192
+ a, b = ref.members
193
+ assert isinstance(a, TpyTypeRef) and a.name == "Int32"
194
+ assert isinstance(b, TpyTypeRef) and b.name == "str"
195
+
196
+ def test_union_with_none(self):
197
+ ref = _parse_ann(_make_parser(), "Int32 | None")
198
+ assert isinstance(ref, TpyUnionRef)
199
+ assert len(ref.members) == 2
200
+
201
+ def test_three_way_union(self):
202
+ ref = _parse_ann(_make_parser(), "Int32 | str | bool")
203
+ assert isinstance(ref, TpyUnionRef)
204
+ assert len(ref.members) == 3
205
+
206
+
207
+ class TestCallable:
208
+ def test_callable(self):
209
+ ref = _parse_ann(_make_parser(), "Callable[[Int32, str], bool]")
210
+ assert isinstance(ref, TpyCallableRef)
211
+ assert ref.kind == "Callable"
212
+ assert len(ref.params) == 2
213
+ assert isinstance(ref.params[0], TpyTypeRef) and ref.params[0].name == "Int32"
214
+ assert isinstance(ref.params[1], TpyTypeRef) and ref.params[1].name == "str"
215
+ assert isinstance(ref.return_type, TpyTypeRef)
216
+ assert ref.return_type.name == "bool"
217
+
218
+ def test_fn(self):
219
+ ref = _parse_ann(_make_parser(), "Fn[[Int32], bool]")
220
+ assert isinstance(ref, TpyCallableRef)
221
+ assert ref.kind == "Fn"
222
+ assert len(ref.params) == 1
223
+
224
+ def test_callable_no_params(self):
225
+ ref = _parse_ann(_make_parser(), "Callable[[], None]")
226
+ assert isinstance(ref, TpyCallableRef)
227
+ assert ref.kind == "Callable"
228
+ assert ref.params == ()
229
+
230
+ def test_callable_malformed_missing_list(self):
231
+ with pytest.raises(ParseError, match="parameter types must be a list"):
232
+ _parse_ann(_make_parser(), "Callable[Int32, bool]")
233
+
234
+
235
+ class TestLiteral:
236
+ def test_str_literal(self):
237
+ ref = _parse_ann(_make_parser(), 'Literal["a", "b"]')
238
+ assert isinstance(ref, TpyLiteralRef)
239
+ assert ref.values == (LiteralValue(LiteralTag.STR, "a"), LiteralValue(LiteralTag.STR, "b"))
240
+
241
+ def test_int_literal(self):
242
+ ref = _parse_ann(_make_parser(), "Literal[1, 2, 3]")
243
+ assert isinstance(ref, TpyLiteralRef)
244
+ assert ref.values == (
245
+ LiteralValue(LiteralTag.INT, 1), LiteralValue(LiteralTag.INT, 2), LiteralValue(LiteralTag.INT, 3),
246
+ )
247
+
248
+ def test_bool_literal(self):
249
+ ref = _parse_ann(_make_parser(), "Literal[True, False]")
250
+ assert isinstance(ref, TpyLiteralRef)
251
+ assert ref.values == (LiteralValue(LiteralTag.BOOL, True), LiteralValue(LiteralTag.BOOL, False))
252
+
253
+ def test_negative_int_literal(self):
254
+ ref = _parse_ann(_make_parser(), "Literal[-5]")
255
+ assert isinstance(ref, TpyLiteralRef)
256
+ assert ref.values == (LiteralValue(LiteralTag.INT, -5),)
257
+
258
+ def test_mixed_types_rejected(self):
259
+ with pytest.raises(ParseError, match="Literal cannot mix value types"):
260
+ _parse_ann(_make_parser(), 'Literal["a", 1]')
261
+
262
+
263
+ class TestUnknownName:
264
+ def test_unknown_name_does_not_raise(self):
265
+ # The resolver is what raises "Unknown type". The walker is permissive.
266
+ ref = _parse_ann(_make_parser(), "TotallyUnknownName")
267
+ assert isinstance(ref, TpyTypeRef)
268
+ assert ref.name == "TotallyUnknownName"
269
+
270
+ def test_unknown_generic_does_not_raise(self):
271
+ ref = _parse_ann(_make_parser(), "UnknownGeneric[Int32]")
272
+ assert isinstance(ref, TpyTypeRef)
273
+ assert ref.name == "UnknownGeneric"
274
+
275
+
276
+ class TestLoc:
277
+ def test_loc_populated(self):
278
+ ref = _parse_ann(_make_parser(), "Int32")
279
+ assert ref.loc is not None
280
+ assert ref.loc.line == 1
281
+
282
+
283
+ # --- F.3b.2: equivalence of _resolve_type_ref_impl with _parse_type_annotation
284
+ # For every case below, walking + resolving a TypeRefNode must produce the
285
+ # same TpyType as the direct parse. The resolver is dead code at this point
286
+ # (no call sites), but this test pins equivalence before F.3b.3 flips the
287
+ # entry point.
288
+
289
+ def _ann_tree(annotation_src: str):
290
+ tree = ast.parse(f"x: {annotation_src}\n")
291
+ return tree.body[0].annotation
292
+
293
+
294
+ def _equiv(parser: Parser, annotation_src: str, type_param_scope=None):
295
+ """Assert _parse_type_annotation == _resolve_type_ref_impl(_parse_type_ref)."""
296
+ node = _ann_tree(annotation_src)
297
+ expected = parser._parse_type_annotation(node, type_param_scope)
298
+ ref = parser._parse_type_ref(node, type_param_scope)
299
+ actual = parser._resolve_type_ref_impl(ref, type_param_scope)
300
+ assert expected == actual, (
301
+ f"Mismatch for {annotation_src!r}:\n expected: {expected}\n actual: {actual}"
302
+ )
303
+ return expected
304
+
305
+
306
+ class TestResolverEquivalence:
307
+ @pytest.mark.parametrize("src", [
308
+ # Primitives
309
+ "Int32", "Int8", "Int16", "Int64",
310
+ "UInt8", "UInt16", "UInt32", "UInt64",
311
+ "int", "float", "Float32", "bool",
312
+ "str", "bytes", "bytearray", "String", "StrView", "BytesView",
313
+ "Char", "None",
314
+ # Slice types
315
+ "basic_slice", "slice",
316
+ ])
317
+ def test_primitives(self, src):
318
+ _equiv(_make_parser(), src)
319
+
320
+ @pytest.mark.parametrize("src", [
321
+ "list[Int32]",
322
+ "list[str]",
323
+ "dict[str, Int32]",
324
+ "dict[Int32, str]",
325
+ "set[Int32]",
326
+ "tuple[Int32]",
327
+ "tuple[Int32, str]",
328
+ "tuple[Int32, str, bool]",
329
+ "Array[Int32, 8]",
330
+ "Array[str, 16]",
331
+ "Span[Int32]",
332
+ "Span[readonly[Int32]]",
333
+ ])
334
+ def test_generics(self, src):
335
+ _equiv(_make_parser(), src)
336
+
337
+ @pytest.mark.parametrize("src", [
338
+ "Ptr[Int32]",
339
+ "Ptr[readonly[Int32]]",
340
+ "Own[list[Int32]]",
341
+ "readonly[Int32]",
342
+ "auto_readonly[Int32]",
343
+ "auto_own[list[Int32]]",
344
+ "Optional[Int32]",
345
+ "Optional[Ptr[Int32]]",
346
+ "Final[Int32]",
347
+ ])
348
+ def test_structural_wrappers(self, src):
349
+ _equiv(_make_parser(), src)
350
+
351
+ @pytest.mark.parametrize("src", [
352
+ "Int32 | str",
353
+ "Int32 | None",
354
+ "Int32 | str | bool",
355
+ "Ptr[Int32] | None",
356
+ "Optional[Int32]",
357
+ "list[Int32] | None",
358
+ ])
359
+ def test_unions(self, src):
360
+ _equiv(_make_parser(), src)
361
+
362
+ @pytest.mark.parametrize("src", [
363
+ "Callable[[Int32], bool]",
364
+ "Callable[[Int32, str], bool]",
365
+ "Callable[[], None]",
366
+ "Fn[[Int32], bool]",
367
+ "Fn[[], None]",
368
+ ])
369
+ def test_callable(self, src):
370
+ _equiv(_make_parser(), src)
371
+
372
+ @pytest.mark.parametrize("src", [
373
+ 'Literal["a", "b"]',
374
+ "Literal[1, 2, 3]",
375
+ "Literal[-5]",
376
+ "Literal[True, False]",
377
+ ])
378
+ def test_literal(self, src):
379
+ _equiv(_make_parser(), src)
380
+
381
+ @pytest.mark.parametrize("src", [
382
+ # Nested generics + wrappers
383
+ "list[Ptr[Int32]]",
384
+ "dict[str, list[Int32]]",
385
+ "Optional[list[Int32]]",
386
+ "list[tuple[Int32, str]]",
387
+ "Callable[[list[Int32]], Optional[str]]",
388
+ ])
389
+ def test_nested(self, src):
390
+ _equiv(_make_parser(), src)
391
+
392
+ def test_type_param_ref(self):
393
+ parser = _make_parser()
394
+ from .typesys import TypeParamKind
395
+ scope = {"T": TypeParamKind.TYPE}
396
+ _equiv(parser, "T", scope)
397
+ _equiv(parser, "list[T]", scope)
398
+ _equiv(parser, "Ptr[T]", scope)
399
+ _equiv(parser, "T | None", scope)
400
+ # Type params in nested / variable-arity forms
401
+ _equiv(parser, "dict[str, T]", scope)
402
+ _equiv(parser, "Optional[T]", scope)
403
+ _equiv(parser, "Fn[[T], bool]", scope)
404
+ _equiv(parser, "auto_readonly[T]", scope)
405
+ _equiv(parser, "Own[T]", scope)
406
+
407
+ def test_int_type_param_ref(self):
408
+ parser = _make_parser()
409
+ from .typesys import TypeParamKind
410
+ scope = {"T": TypeParamKind.TYPE, "N": TypeParamKind.INT}
411
+ _equiv(parser, "Array[T, N]", scope)
412
+
413
+ @pytest.mark.parametrize("src", [
414
+ "Self",
415
+ "Ptr[Self]",
416
+ "Optional[Self]",
417
+ "list[Self]",
418
+ ])
419
+ def test_self_type(self, src):
420
+ _equiv(_make_parser(), src)
421
+
422
+
423
+ class TestResolverErrors:
424
+ def test_unknown_type_raises(self):
425
+ from .typesys import TypeParamKind
426
+ parser = _make_parser()
427
+ node = _ann_tree("TotallyUnknownName")
428
+ ref = parser._parse_type_ref(node)
429
+ with pytest.raises(ParseError, match="Unknown type"):
430
+ parser._resolve_type_ref_impl(ref)
431
+
432
+ def test_unknown_generic_raises(self):
433
+ parser = _make_parser()
434
+ node = _ann_tree("UnknownGeneric[Int32]")
435
+ ref = parser._parse_type_ref(node)
436
+ with pytest.raises(ParseError, match="Unknown generic type"):
437
+ parser._resolve_type_ref_impl(ref)
438
+
439
+ def test_error_lineno_preserved(self):
440
+ """Errors raised from the resolver use ref.loc to set lineno, matching
441
+ the ast-based path."""
442
+ parser = _make_parser()
443
+ # Build annotation on line 3
444
+ tree = ast.parse("pass\npass\nx: UnknownName\n")
445
+ node = tree.body[2].annotation
446
+ # Direct parse raises with lineno=3
447
+ try:
448
+ parser._parse_type_annotation(node)
449
+ assert False, "should have raised"
450
+ except ParseError as e:
451
+ expected_lineno = e.lineno
452
+ # Resolver path raises with same lineno
453
+ ref = parser._parse_type_ref(node)
454
+ try:
455
+ parser._resolve_type_ref_impl(ref)
456
+ assert False, "should have raised"
457
+ except ParseError as e:
458
+ assert e.lineno == expected_lineno
459
+
460
+
461
+ class TestResolverLenient:
462
+ """Pin `TypeResolver.resolve_lenient` message-pattern fallback.
463
+
464
+ The lenient resolver catches three specific error message patterns
465
+ ("Unknown type", "Unknown generic type", "Unsupported qualified type")
466
+ and falls back to a NominalType placeholder. The error sites carry
467
+ LOAD-BEARING-MESSAGE markers; this test enforces the contract.
468
+ """
469
+
470
+ def test_lenient_unknown_bare_name(self):
471
+ from .typesys import NominalType
472
+ parser = _make_parser()
473
+ node = _ann_tree("TotallyUnknownName")
474
+ ref = parser._parse_type_ref(node)
475
+ # Strict resolver raises.
476
+ with pytest.raises(ParseError, match="Unknown type"):
477
+ parser._resolve_type_ref_impl(ref)
478
+ # Lenient resolver returns a NominalType placeholder.
479
+ result = parser._resolver.resolve_lenient(ref)
480
+ assert isinstance(result, NominalType)
481
+ assert result.name == "TotallyUnknownName"
482
+ assert result.type_args == ()
483
+
484
+ def test_lenient_unknown_generic_with_args(self):
485
+ from .typesys import NominalType, INT32
486
+ parser = _make_parser()
487
+ node = _ann_tree("UnknownGeneric[Int32]")
488
+ ref = parser._parse_type_ref(node)
489
+ with pytest.raises(ParseError, match="Unknown generic type"):
490
+ parser._resolve_type_ref_impl(ref)
491
+ result = parser._resolver.resolve_lenient(ref)
492
+ assert isinstance(result, NominalType)
493
+ assert result.name == "UnknownGeneric"
494
+ # Inner Int32 resolves normally through strict path inside the
495
+ # lenient recursion, so type_args carries the real singleton.
496
+ assert result.type_args == (INT32,)
497
+
498
+ def test_lenient_still_raises_structural_errors(self):
499
+ """Structural errors (not name-resolution) still propagate."""
500
+ parser = _make_parser()
501
+ # Fn with wrong arity is a structural error raised by the walker,
502
+ # not the resolver. The walker runs first, so it raises before
503
+ # the lenient resolver even sees it.
504
+ with pytest.raises(ParseError):
505
+ node = _ann_tree("Fn[[Int32]]") # Fn requires [[params], return]
506
+ parser._parse_type_ref(node)
@@ -0,0 +1,58 @@
1
+ """Unit tests for _parse_version_info in tpyc/__init__.py."""
2
+
3
+ import pytest
4
+
5
+ from tpyc import _parse_version_info
6
+
7
+
8
+ def test_final_release():
9
+ assert _parse_version_info("0.1.0") == (0, 1, 0, "final", 0)
10
+ assert _parse_version_info("1.2.3") == (1, 2, 3, "final", 0)
11
+ assert _parse_version_info("12.34.56") == (12, 34, 56, "final", 0)
12
+
13
+
14
+ def test_alpha():
15
+ assert _parse_version_info("0.1.0a1") == (0, 1, 0, "alpha", 1)
16
+ assert _parse_version_info("2.0.0a12") == (2, 0, 0, "alpha", 12)
17
+
18
+
19
+ def test_beta():
20
+ assert _parse_version_info("0.1.0b2") == (0, 1, 0, "beta", 2)
21
+
22
+
23
+ def test_release_candidate():
24
+ assert _parse_version_info("0.1.0rc1") == (0, 1, 0, "candidate", 1)
25
+
26
+
27
+ def test_dev():
28
+ assert _parse_version_info("0.1.0.dev0") == (0, 1, 0, "dev", 0)
29
+ assert _parse_version_info("0.1.0.dev42") == (0, 1, 0, "dev", 42)
30
+
31
+
32
+ def test_invalid_raises():
33
+ with pytest.raises(ValueError):
34
+ _parse_version_info("")
35
+ with pytest.raises(ValueError):
36
+ _parse_version_info("1.2") # not enough components
37
+ with pytest.raises(ValueError):
38
+ _parse_version_info("1.2.3.4") # too many components
39
+ with pytest.raises(ValueError):
40
+ _parse_version_info("1.2.3dev0") # missing dot before dev
41
+ with pytest.raises(ValueError):
42
+ _parse_version_info("1.2.3.a1") # spurious dot before alpha
43
+ with pytest.raises(ValueError):
44
+ _parse_version_info("1.2.3x1") # unknown suffix
45
+ with pytest.raises(ValueError):
46
+ _parse_version_info("v1.2.3") # leading junk
47
+
48
+
49
+ def test_unsupported_pep440_forms_raise():
50
+ # Valid PEP 440 that tpyc doesn't ship today. If tpyc ever adopts one
51
+ # of these forms, version_info needs a new releaselevel mapping and
52
+ # this test should update accordingly.
53
+ with pytest.raises(ValueError):
54
+ _parse_version_info("1.2.3.post1") # post-release
55
+ with pytest.raises(ValueError):
56
+ _parse_version_info("1!1.2.3") # epoch
57
+ with pytest.raises(ValueError):
58
+ _parse_version_info("1.2.3+local") # local identifier
@@ -0,0 +1,72 @@
1
+ """Tests for `tpyc.module_names.module_from_qname`.
2
+
3
+ Drives `#include` emission via the reached-modules set in
4
+ `tpyc/sema/reach_analysis.py` and SCC peer detection in
5
+ `tpyc/compiler.py`. Must not prefix-walk the qname of a record whose
6
+ defining file diverges from its qname (e.g. `Poll` -- qname
7
+ `tpy.coro.Poll`, body in `tpy/_core/_types.py`).
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ from tpyc import qnames, typesys as ts
13
+ from tpyc.module_names import module_from_qname
14
+
15
+
16
+ def _registry_with_modules(names: list[str], builtin: list[str] | None = None) -> ts.TypeRegistry:
17
+ registry = ts.TypeRegistry()
18
+ builtin_set = set(builtin or [])
19
+ for name in names:
20
+ registry.register_module(
21
+ ts.ModuleInfo(name=name, is_builtin=name in builtin_set)
22
+ )
23
+ return registry
24
+
25
+
26
+ def test_record_with_divergent_qname_uses_record_module():
27
+ registry = _registry_with_modules(["tpy", "tpy.coro", "tpy._core._types"])
28
+ record = ts.RecordInfo(
29
+ name="Poll",
30
+ module="tpy",
31
+ defining_module="tpy._core._types",
32
+ builtin_type_key=qnames.POLL,
33
+ fields=[],
34
+ methods={},
35
+ )
36
+ registry.register_record(record)
37
+
38
+ assert module_from_qname(qnames.POLL, registry) == "tpy"
39
+
40
+
41
+ def test_record_with_aligned_qname_still_returns_module():
42
+ registry = _registry_with_modules(["pkg", "pkg.sub"])
43
+ record = ts.RecordInfo(
44
+ name="Widget",
45
+ module="pkg.sub",
46
+ defining_module="pkg.sub",
47
+ builtin_type_key="pkg.sub.Widget",
48
+ fields=[],
49
+ methods={},
50
+ )
51
+ registry.register_record(record)
52
+
53
+ assert module_from_qname("pkg.sub.Widget", registry) == "pkg.sub"
54
+
55
+
56
+ def test_unregistered_qname_falls_back_to_prefix_walk():
57
+ registry = _registry_with_modules(["pkg", "pkg.sub"])
58
+
59
+ assert module_from_qname("pkg.sub.Outer.Inner", registry) == "pkg.sub"
60
+ assert module_from_qname("pkg.Foo", registry) == "pkg"
61
+
62
+
63
+ def test_unregistered_qname_with_no_module_ancestor_falls_to_first_component():
64
+ registry = _registry_with_modules([])
65
+
66
+ assert module_from_qname("foo.Bar", registry) == "foo"
67
+
68
+
69
+ def test_single_component_qname_returns_none():
70
+ registry = _registry_with_modules([])
71
+
72
+ assert module_from_qname("BareName", registry) is None