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,76 @@
1
+ """Tests for macro_loader.validate_and_call_macro."""
2
+
3
+ import pytest
4
+
5
+ from .macro_loader import validate_and_call_macro
6
+ from .diagnostics import SemanticError
7
+
8
+
9
+ class _FakeLoc:
10
+ """Minimal loc object for test errors."""
11
+ def __init__(self):
12
+ self.lineno = 1
13
+ self.col_offset = 0
14
+ self.end_lineno = 1
15
+ self.end_col_offset = 0
16
+
17
+
18
+ _LOC = _FakeLoc()
19
+
20
+
21
+ def _make_macro(fn):
22
+ fn._is_class_macro = True
23
+ return fn
24
+
25
+
26
+ class TestValidateAndCallMacro:
27
+ def test_unknown_kwarg(self):
28
+ def my_macro(cls, *, x: int = 0):
29
+ pass
30
+ with pytest.raises(SemanticError, match="unknown keyword argument 'y'"):
31
+ validate_and_call_macro(my_macro, None, {"y": 1}, "test.my_macro", _LOC)
32
+
33
+ def test_unknown_kwarg_no_params(self):
34
+ def my_macro(cls):
35
+ pass
36
+ with pytest.raises(SemanticError, match="takes no keyword arguments"):
37
+ validate_and_call_macro(my_macro, None, {"x": 1}, "test.my_macro", _LOC)
38
+
39
+ def test_missing_required_kwarg(self):
40
+ def my_macro(cls, *, required: str):
41
+ pass
42
+ with pytest.raises(SemanticError, match="missing required keyword argument 'required'"):
43
+ validate_and_call_macro(my_macro, None, {}, "test.my_macro", _LOC)
44
+
45
+ def test_type_mismatch(self):
46
+ def my_macro(cls, *, flag: bool = False):
47
+ pass
48
+ with pytest.raises(SemanticError, match="'flag' must be bool, got str"):
49
+ validate_and_call_macro(my_macro, None, {"flag": "yes"}, "test.my_macro", _LOC)
50
+
51
+ def test_unexpected_exception_wrapped(self):
52
+ def my_macro(cls):
53
+ raise ValueError("something broke")
54
+ with pytest.raises(SemanticError, match="macro raised ValueError: something broke"):
55
+ validate_and_call_macro(my_macro, None, {}, "test.my_macro", _LOC)
56
+
57
+ def test_semantic_error_not_wrapped(self):
58
+ def my_macro(cls):
59
+ raise SemanticError("custom error", _LOC)
60
+ with pytest.raises(SemanticError, match="custom error"):
61
+ validate_and_call_macro(my_macro, None, {}, "test.my_macro", _LOC)
62
+
63
+ def test_var_keyword_allows_unknown(self):
64
+ received = {}
65
+ def my_macro(cls, **kw):
66
+ received.update(kw)
67
+ validate_and_call_macro(my_macro, None, {"anything": 42}, "test.my_macro", _LOC)
68
+ assert received == {"anything": 42}
69
+
70
+ def test_valid_call(self):
71
+ results = {}
72
+ def my_macro(cls, *, frozen: bool = False, order: bool = False):
73
+ results["frozen"] = frozen
74
+ results["order"] = order
75
+ validate_and_call_macro(my_macro, "fake_cls", {"frozen": True}, "test.my_macro", _LOC)
76
+ assert results == {"frozen": True, "order": False}
@@ -0,0 +1,254 @@
1
+ """Tests for sema.method_expansion.
2
+
3
+ The per-record entry point (`expand_methods_for_record`) is invoked from
4
+ `register_record` after macros run, so macro-added methods flow through
5
+ the same self-flag derivation / wrapping / cloning pipeline as
6
+ source-authored methods (Phase F.3b.6.5). These tests pin the
7
+ idempotency contract that the per-record call relies on.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import pytest
13
+
14
+ from .parse.nodes import TpyFunction, TpyRecord, RecordLinkage
15
+ from .diagnostics import SemanticError
16
+ from .sema.method_expansion import expand_methods_for_record
17
+ from .typesys import (
18
+ AutoReadonlyType,
19
+ AutoOwnType,
20
+ OwnType,
21
+ SelfType,
22
+ NominalType,
23
+ SELF,
24
+ VOID,
25
+ INT32,
26
+ )
27
+
28
+
29
+ def _make_record(methods: list[TpyFunction]) -> TpyRecord:
30
+ return TpyRecord(
31
+ name="R",
32
+ fields=[],
33
+ methods=methods,
34
+ bases=[],
35
+ linkage=RecordLinkage.DEFAULT,
36
+ )
37
+
38
+
39
+ def _make_method(**kwargs) -> TpyFunction:
40
+ return TpyFunction(
41
+ name=kwargs.pop("name", "m"),
42
+ params=kwargs.pop("params", []),
43
+ return_type=kwargs.pop("return_type", VOID),
44
+ body=[],
45
+ is_method=True,
46
+ **kwargs,
47
+ )
48
+
49
+
50
+ class TestAutoReadonlyDecoratorExpansion:
51
+ def test_decorator_expands_to_mutable_and_const_clones(self):
52
+ method = _make_method(
53
+ name="get",
54
+ return_type=INT32,
55
+ has_auto_readonly_decorator=True,
56
+ )
57
+ record = _make_record([method])
58
+
59
+ expand_methods_for_record(record)
60
+
61
+ assert len(record.methods) == 2
62
+ mutable, const = record.methods
63
+ assert mutable.is_auto_readonly_mutable_clone
64
+ assert not mutable.is_readonly
65
+ assert not const.is_auto_readonly_mutable_clone
66
+ assert const.is_readonly
67
+ # Both clones are "expansion done" and carry no derivation source.
68
+ assert mutable.self_annotation is None
69
+ assert const.self_annotation is None
70
+ assert not mutable.has_auto_readonly_decorator
71
+ assert not const.has_auto_readonly_decorator
72
+
73
+ def test_decorator_expansion_is_idempotent(self):
74
+ method = _make_method(
75
+ name="get",
76
+ return_type=INT32,
77
+ has_auto_readonly_decorator=True,
78
+ )
79
+ record = _make_record([method])
80
+
81
+ expand_methods_for_record(record)
82
+ first_count = len(record.methods)
83
+ expand_methods_for_record(record)
84
+ assert len(record.methods) == first_count
85
+
86
+
87
+ class TestAutoReadonlySelfExpansion:
88
+ def test_self_auto_readonly_clones_and_strips_annotation(self):
89
+ method = _make_method(
90
+ name="m",
91
+ self_annotation=AutoReadonlyType(SELF),
92
+ )
93
+ record = _make_record([method])
94
+
95
+ expand_methods_for_record(record)
96
+
97
+ assert len(record.methods) == 2
98
+ # A second expansion must not re-clone -- self_annotation is nulled
99
+ # on both halves so _derive_self_flags doesn't re-set auto_readonly.
100
+ expand_methods_for_record(record)
101
+ assert len(record.methods) == 2
102
+
103
+
104
+ class TestAutoOwnSelfExpansion:
105
+ def test_self_auto_own_clones_and_strips_annotation(self):
106
+ method = _make_method(
107
+ name="take",
108
+ self_annotation=AutoOwnType(SELF),
109
+ return_type=AutoOwnType(NominalType("R")),
110
+ )
111
+ record = _make_record([method])
112
+
113
+ expand_methods_for_record(record)
114
+
115
+ assert len(record.methods) == 2
116
+ borrowing, consuming = record.methods
117
+ assert borrowing.is_auto_own_borrowing_clone
118
+ assert not borrowing.is_consuming
119
+ assert consuming.is_consuming
120
+ assert borrowing.self_annotation is None
121
+ assert consuming.self_annotation is None
122
+
123
+ expand_methods_for_record(record)
124
+ assert len(record.methods) == 2
125
+
126
+
127
+ class TestConsumingSelfNotCloned:
128
+ def test_own_self_sets_is_consuming_no_clone(self):
129
+ method = _make_method(
130
+ name="take",
131
+ self_annotation=OwnType(SELF),
132
+ )
133
+ record = _make_record([method])
134
+
135
+ expand_methods_for_record(record)
136
+
137
+ assert len(record.methods) == 1
138
+ assert record.methods[0].is_consuming
139
+ # self_annotation is cleared after derivation so a second pass
140
+ # doesn't re-fire `_derive_self_flags` on it (symmetric with the
141
+ # clone paths).
142
+ assert record.methods[0].self_annotation is None
143
+
144
+ expand_methods_for_record(record)
145
+ assert len(record.methods) == 1
146
+ assert record.methods[0].is_consuming
147
+
148
+
149
+ class TestSelfAnnotationValidation:
150
+ def test_own_self_on_init_raises_semantic_error(self):
151
+ method = _make_method(
152
+ name="__init__",
153
+ self_annotation=OwnType(SELF),
154
+ )
155
+ record = _make_record([method])
156
+
157
+ with pytest.raises(SemanticError, match="Own\\[Self\\] is not allowed on '__init__'"):
158
+ expand_methods_for_record(record)
159
+
160
+ def test_own_self_on_del_raises_semantic_error(self):
161
+ method = _make_method(
162
+ name="__del__",
163
+ self_annotation=OwnType(SELF),
164
+ )
165
+ record = _make_record([method])
166
+
167
+ with pytest.raises(SemanticError, match="Own\\[Self\\] is not allowed on '__del__'"):
168
+ expand_methods_for_record(record)
169
+
170
+ def test_auto_readonly_self_on_init_raises_semantic_error(self):
171
+ method = _make_method(
172
+ name="__init__",
173
+ self_annotation=AutoReadonlyType(SELF),
174
+ )
175
+ record = _make_record([method])
176
+
177
+ with pytest.raises(SemanticError, match="auto_readonly\\[Self\\] is not allowed on '__init__'"):
178
+ expand_methods_for_record(record)
179
+
180
+ def test_own_self_with_readonly_raises_semantic_error(self):
181
+ method = _make_method(
182
+ name="m",
183
+ self_annotation=OwnType(SELF),
184
+ is_readonly=True,
185
+ )
186
+ record = _make_record([method])
187
+
188
+ with pytest.raises(SemanticError, match="Own\\[Self\\] cannot be combined with @readonly"):
189
+ expand_methods_for_record(record)
190
+
191
+
192
+ class TestPerParamAutoReadonlyTriggersCloning:
193
+ """Per-param `auto_readonly[T]` annotation alone (no decorator, no self:
194
+ auto_readonly[Self]) must still set `auto_readonly=True` in sema and
195
+ trigger cloning. Regression path for F.3b.6.2 which moved the per-param
196
+ detection out of the parser.
197
+ """
198
+
199
+ def test_per_param_auto_readonly_clones(self):
200
+ # Method with a param whose type carries AutoReadonlyType.
201
+ method = _make_method(
202
+ name="pick",
203
+ params=[("x", AutoReadonlyType(NominalType("T")))],
204
+ return_type=INT32,
205
+ )
206
+ record = _make_record([method])
207
+
208
+ expand_methods_for_record(record)
209
+
210
+ # Cloned into mutable + const halves.
211
+ assert len(record.methods) == 2
212
+ mutable, const = record.methods
213
+ assert mutable.is_auto_readonly_mutable_clone
214
+ assert not mutable.is_readonly
215
+ assert not const.is_auto_readonly_mutable_clone
216
+ assert const.is_readonly
217
+ # Mutable clone strips the AutoReadonlyType; const clone applies it.
218
+ from .typesys import ReadonlyType, strip_auto_readonly, apply_auto_readonly
219
+ _, mut_ptype = mutable.params[0]
220
+ _, const_ptype = const.params[0]
221
+ assert not isinstance(mut_ptype, AutoReadonlyType)
222
+ assert isinstance(const_ptype, ReadonlyType)
223
+
224
+
225
+ class TestMacroAddedMethodExpansion:
226
+ """Simulates the macro-added method flow: add a method post-parse and
227
+ verify it flows through the same pipeline when the per-record entry
228
+ point runs. This is the regression the F.3b.6.5 change protects.
229
+ """
230
+
231
+ def test_method_added_after_initial_expansion_gets_expanded(self):
232
+ # First method: already expanded form (simulates parser output
233
+ # that the module-level caller might have processed before
234
+ # macros add theirs). It stays put.
235
+ existing = _make_method(name="existing", return_type=INT32)
236
+ record = _make_record([existing])
237
+ expand_methods_for_record(record)
238
+ assert len(record.methods) == 1
239
+
240
+ # Macro adds a new method with @auto_readonly decorator flag.
241
+ new_method = _make_method(
242
+ name="new_method",
243
+ return_type=INT32,
244
+ has_auto_readonly_decorator=True,
245
+ )
246
+ record.methods.append(new_method)
247
+
248
+ expand_methods_for_record(record)
249
+
250
+ # existing stays as 1 method; new_method cloned into 2. Total 3.
251
+ assert len(record.methods) == 3
252
+ names = [m.name for m in record.methods]
253
+ assert names.count("existing") == 1
254
+ assert names.count("new_method") == 2
@@ -0,0 +1,182 @@
1
+ """Pin the qname-aware nominal identity invariants.
2
+
3
+ Three concerns the test guards against:
4
+
5
+ 1. `NominalType` equality + hash includes `_module_qname` -- two
6
+ records with the same short name from different modules are
7
+ distinct in sets / dicts / unions, and set dedup is insertion-
8
+ order independent (proper equivalence relation).
9
+ 2. `TypeRegistry.get_record_for_type` is qname-first -- when the
10
+ NominalType carries a qname, the lookup routes to the matching
11
+ record even if a locally-registered record shadows the short name.
12
+ Covers both records registered via `register_record(info, name)`
13
+ and records that land in the registry only via `register_module`.
14
+ 3. `TypeRegistry.is_subclass_of` works for cross-module child/base
15
+ pairs whose short names are shadowed by local records.
16
+ """
17
+ from __future__ import annotations
18
+
19
+ import pytest
20
+
21
+ from tpyc.typesys import (
22
+ ModuleInfo, NominalType, RecordInfo, TypeRegistry,
23
+ make_union, UnionType, same_nominal_symbol_loose,
24
+ )
25
+ from tpyc.type_def_registry import (
26
+ attach_dynamic_type_def, TypeCategory, clear_dynamic_type_defs,
27
+ )
28
+
29
+
30
+ @pytest.fixture(autouse=True)
31
+ def _cleanup():
32
+ yield
33
+ clear_dynamic_type_defs()
34
+
35
+
36
+ def _attach_record_td(info: RecordInfo) -> None:
37
+ """Attach a TypeDef.record entry so `is_user_record` resolves --
38
+ mirrors what sema's `register_record` does in production."""
39
+ attach_dynamic_type_def(
40
+ info.qualified_name(),
41
+ TypeCategory.RECORD,
42
+ record=info,
43
+ is_value_type=False,
44
+ )
45
+
46
+
47
+ # ---------------------------------------------------------------------------
48
+ # 1. Equality / hash invariant
49
+ # ---------------------------------------------------------------------------
50
+
51
+ class TestNominalEquality:
52
+ def test_cross_module_same_name_unequal(self) -> None:
53
+ a = NominalType("Foo", _module_qname="pkg_a.Foo")
54
+ b = NominalType("Foo", _module_qname="pkg_b.Foo")
55
+ assert a != b
56
+ assert hash(a) != hash(b) or a != b # hashes may collide, equality must not
57
+
58
+ def test_bare_and_qname_bearing_unequal(self) -> None:
59
+ # Strict contract: bare != qname-bearing. Transitional sites
60
+ # that want the loose bridge must call
61
+ # `same_nominal_symbol_loose` explicitly.
62
+ bare = NominalType("Foo")
63
+ qn = NominalType("Foo", _module_qname="mod.Foo")
64
+ assert bare != qn
65
+
66
+ def test_set_dedup_order_independent(self) -> None:
67
+ a = NominalType("Foo", _module_qname="pkg_a.Foo")
68
+ b = NominalType("Foo", _module_qname="pkg_b.Foo")
69
+ c = NominalType("Foo")
70
+ # Three pairwise-unequal elements -> always 3 in the set
71
+ # regardless of insertion order (guards against the non-
72
+ # transitive-equality trap).
73
+ assert len({a, b, c}) == 3
74
+ assert len({c, a, b}) == 3
75
+ assert len({b, c, a}) == 3
76
+
77
+ def test_make_union_keeps_cross_module_distinct(self) -> None:
78
+ a = NominalType("Foo", _module_qname="pkg_a.Foo")
79
+ b = NominalType("Foo", _module_qname="pkg_b.Foo")
80
+ u = make_union(a, b)
81
+ assert isinstance(u, UnionType)
82
+ assert len(u.members) == 2
83
+
84
+ def test_same_qname_equal(self) -> None:
85
+ a = NominalType("Foo", _module_qname="mod.Foo")
86
+ b = NominalType("Foo", _module_qname="mod.Foo")
87
+ assert a == b
88
+ assert hash(a) == hash(b)
89
+
90
+
91
+ # ---------------------------------------------------------------------------
92
+ # 2. same_nominal_symbol_loose -- transitional bridging helper
93
+ # ---------------------------------------------------------------------------
94
+
95
+ class TestLooseBridging:
96
+ def test_bare_matches_qname_bearing(self) -> None:
97
+ bare = NominalType("Foo")
98
+ qn = NominalType("Foo", _module_qname="mod.Foo")
99
+ assert same_nominal_symbol_loose(bare, qn)
100
+ assert same_nominal_symbol_loose(qn, bare)
101
+
102
+ def test_different_qnames_still_unequal(self) -> None:
103
+ # loose must NOT paper over cross-module collisions.
104
+ a = NominalType("Foo", _module_qname="pkg_a.Foo")
105
+ b = NominalType("Foo", _module_qname="pkg_b.Foo")
106
+ assert not same_nominal_symbol_loose(a, b)
107
+
108
+ def test_rejects_structural_differences(self) -> None:
109
+ # Different name / type_args / is_protocol -> False regardless
110
+ # of qname state.
111
+ bare_a = NominalType("Foo")
112
+ bare_b = NominalType("Bar")
113
+ assert not same_nominal_symbol_loose(bare_a, bare_b)
114
+
115
+
116
+ # ---------------------------------------------------------------------------
117
+ # 3. Qname-aware lookup on TypeRegistry
118
+ # ---------------------------------------------------------------------------
119
+
120
+ class TestRegistryLookup:
121
+ def _make_registry_with_shadow(self) -> tuple[TypeRegistry, RecordInfo, RecordInfo]:
122
+ """A registry where short name "Foo" is shadowed:
123
+ - `__main__.Foo` registered via `register_record` (local).
124
+ - `pkg.Foo` registered via `register_module` (import-only).
125
+ """
126
+ reg = TypeRegistry()
127
+ main_foo = RecordInfo(name="Foo", fields=[], module="__main__")
128
+ pkg_foo = RecordInfo(name="Foo", fields=[], module="pkg")
129
+ reg.register_record(main_foo)
130
+ reg.register_module(ModuleInfo(name="pkg", records={"Foo": pkg_foo}))
131
+ _attach_record_td(main_foo)
132
+ _attach_record_td(pkg_foo)
133
+ return reg, main_foo, pkg_foo
134
+
135
+ def test_qname_routes_to_cross_module_record(self) -> None:
136
+ reg, main_foo, pkg_foo = self._make_registry_with_shadow()
137
+ n = NominalType("Foo", _module_qname="pkg.Foo")
138
+ assert reg.get_record_for_type(n) is pkg_foo
139
+
140
+ def test_qname_routes_to_local_record(self) -> None:
141
+ reg, main_foo, pkg_foo = self._make_registry_with_shadow()
142
+ n = NominalType("Foo", _module_qname="__main__.Foo")
143
+ assert reg.get_record_for_type(n) is main_foo
144
+
145
+ def test_bare_falls_back_to_short_name(self) -> None:
146
+ reg, main_foo, pkg_foo = self._make_registry_with_shadow()
147
+ # Bare placeholder still resolves to whatever is in
148
+ # `self.records[name]` (here: the local __main__.Foo). This
149
+ # is the transient parse/resolve behavior; callers that need
150
+ # stricter semantics should pass a qname-bearing NominalType.
151
+ n = NominalType("Foo")
152
+ assert reg.get_record_for_type(n) is main_foo
153
+
154
+ def test_is_subclass_of_cross_module(self) -> None:
155
+ # Local `Base` shadows `pkg.Base`, and `pkg.Child` extends
156
+ # `pkg.Base`. Qname-aware lookup must walk the pkg chain
157
+ # rather than the locally-registered `Base`.
158
+ reg = TypeRegistry()
159
+ main_base = RecordInfo(name="Base", fields=[], module="__main__")
160
+ reg.register_record(main_base)
161
+ _attach_record_td(main_base)
162
+
163
+ pkg_base = RecordInfo(name="Base", fields=[], module="pkg")
164
+ base_ref = NominalType("Base", _module_qname="pkg.Base")
165
+ pkg_child = RecordInfo(
166
+ name="Child", fields=[], module="pkg",
167
+ parents=[base_ref],
168
+ mro_ancestors=[base_ref],
169
+ )
170
+ reg.register_module(ModuleInfo(
171
+ name="pkg", records={"Base": pkg_base, "Child": pkg_child},
172
+ ))
173
+ _attach_record_td(pkg_base)
174
+ _attach_record_td(pkg_child)
175
+
176
+ child_n = NominalType("Child", _module_qname="pkg.Child")
177
+ base_n = NominalType("Base", _module_qname="pkg.Base")
178
+ assert reg.is_subclass_of(child_n, base_n)
179
+
180
+ # Sanity: local __main__.Base is NOT a parent of pkg.Child.
181
+ main_base_n = NominalType("Base", _module_qname="__main__.Base")
182
+ assert not reg.is_subclass_of(child_n, main_base_n)