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.
- tpy_lang-0.3.0.dev0.dist-info/METADATA +151 -0
- tpy_lang-0.3.0.dev0.dist-info/RECORD +333 -0
- tpy_lang-0.3.0.dev0.dist-info/WHEEL +4 -0
- tpy_lang-0.3.0.dev0.dist-info/entry_points.txt +3 -0
- tpyc/__init__.py +104 -0
- tpyc/__main__.py +6 -0
- tpyc/_buildinfo.py +1 -0
- tpyc/_data/docs/LANGUAGE_FEATURES.md +6278 -0
- tpyc/_data/docs/STDLIB_ROADMAP.md +1258 -0
- tpyc/_data/docs/TPY_FOR_AGENTS.md +556 -0
- tpyc/_data/lib/tpy/_bindings/__init__.py +6 -0
- tpyc/_data/lib/tpy/_bindings/pcre2.py +173 -0
- tpyc/_data/lib/tpy/_bindings/posix_socket.py +161 -0
- tpyc/_data/lib/tpy/_functools_macros.py +80 -0
- tpyc/_data/lib/tpy/_macro_helpers.py +161 -0
- tpyc/_data/lib/tpy/argparse.py +2062 -0
- tpyc/_data/lib/tpy/asyncio/__init__.py +744 -0
- tpyc/_data/lib/tpy/asyncio/_executor.py +515 -0
- tpyc/_data/lib/tpy/base64.py +410 -0
- tpyc/_data/lib/tpy/bisect.py +39 -0
- tpyc/_data/lib/tpy/builtins.py +38 -0
- tpyc/_data/lib/tpy/dataclasses.py +354 -0
- tpyc/_data/lib/tpy/enum.py +23 -0
- tpyc/_data/lib/tpy/functools.py +33 -0
- tpyc/_data/lib/tpy/hashlib.py +206 -0
- tpyc/_data/lib/tpy/heapq.py +118 -0
- tpyc/_data/lib/tpy/io.py +395 -0
- tpyc/_data/lib/tpy/json.py +221 -0
- tpyc/_data/lib/tpy/math.py +406 -0
- tpyc/_data/lib/tpy/random.py +597 -0
- tpyc/_data/lib/tpy/re.py +467 -0
- tpyc/_data/lib/tpy/socket.py +379 -0
- tpyc/_data/lib/tpy/struct.py +178 -0
- tpyc/_data/lib/tpy/sys.py +40 -0
- tpyc/_data/lib/tpy/time.py +39 -0
- tpyc/_data/lib/tpy/tpy/__init__.py +78 -0
- tpyc/_data/lib/tpy/tpy/_bootstrap/__init__.py +10 -0
- tpyc/_data/lib/tpy/tpy/_bootstrap/_decorators.py +37 -0
- tpyc/_data/lib/tpy/tpy/_bootstrap/_extern.py +64 -0
- tpyc/_data/lib/tpy/tpy/_builtins/__init__.py +11 -0
- tpyc/_data/lib/tpy/tpy/_builtins/_bytes.py +378 -0
- tpyc/_data/lib/tpy/tpy/_builtins/_dict.py +151 -0
- tpyc/_data/lib/tpy/tpy/_builtins/_exceptions.py +125 -0
- tpyc/_data/lib/tpy/tpy/_builtins/_funcs.py +681 -0
- tpyc/_data/lib/tpy/tpy/_builtins/_io.py +97 -0
- tpyc/_data/lib/tpy/tpy/_builtins/_list.py +127 -0
- tpyc/_data/lib/tpy/tpy/_builtins/_range.py +52 -0
- tpyc/_data/lib/tpy/tpy/_builtins/_set.py +139 -0
- tpyc/_data/lib/tpy/tpy/_builtins/_super.py +11 -0
- tpyc/_data/lib/tpy/tpy/_builtins/_types.py +661 -0
- tpyc/_data/lib/tpy/tpy/_core/__init__.py +23 -0
- tpyc/_data/lib/tpy/tpy/_core/_bytes_view.py +129 -0
- tpyc/_data/lib/tpy/tpy/_core/_containers.py +137 -0
- tpyc/_data/lib/tpy/tpy/_core/_functions.py +40 -0
- tpyc/_data/lib/tpy/tpy/_core/_types.py +2061 -0
- tpyc/_data/lib/tpy/tpy/_typing/__init__.py +77 -0
- tpyc/_data/lib/tpy/tpy/_version.py +29 -0
- tpyc/_data/lib/tpy/tpy/bits.py +28 -0
- tpyc/_data/lib/tpy/tpy/coro/__init__.py +127 -0
- tpyc/_data/lib/tpy/tpy/extern.py +8 -0
- tpyc/_data/lib/tpy/tpy/mem.py +49 -0
- tpyc/_data/lib/tpy/tpy/unsafe.py +195 -0
- tpyc/_data/lib/tpy/tpy/version.py +21 -0
- tpyc/_data/lib/tpy/typing.py +13 -0
- tpyc/_data/runtime/cpp/include/tpy/any.hpp +461 -0
- tpyc/_data/runtime/cpp/include/tpy/as_ostream.hpp +117 -0
- tpyc/_data/runtime/cpp/include/tpy/async.hpp +76 -0
- tpyc/_data/runtime/cpp/include/tpy/bigint.hpp +1343 -0
- tpyc/_data/runtime/cpp/include/tpy/builtins.hpp +400 -0
- tpyc/_data/runtime/cpp/include/tpy/bytes_ops.hpp +469 -0
- tpyc/_data/runtime/cpp/include/tpy/container_ops.hpp +487 -0
- tpyc/_data/runtime/cpp/include/tpy/copy_iter.hpp +82 -0
- tpyc/_data/runtime/cpp/include/tpy/core.hpp +558 -0
- tpyc/_data/runtime/cpp/include/tpy/dict_ops.hpp +289 -0
- tpyc/_data/runtime/cpp/include/tpy/dunder.hpp +750 -0
- tpyc/_data/runtime/cpp/include/tpy/dynamic.hpp +44 -0
- tpyc/_data/runtime/cpp/include/tpy/enum.hpp +40 -0
- tpyc/_data/runtime/cpp/include/tpy/file.hpp +245 -0
- tpyc/_data/runtime/cpp/include/tpy/fixed_int.hpp +317 -0
- tpyc/_data/runtime/cpp/include/tpy/format.hpp +954 -0
- tpyc/_data/runtime/cpp/include/tpy/frame_slot.hpp +120 -0
- tpyc/_data/runtime/cpp/include/tpy/generator.hpp +47 -0
- tpyc/_data/runtime/cpp/include/tpy/iterable_ops.hpp +122 -0
- tpyc/_data/runtime/cpp/include/tpy/itertools.hpp +749 -0
- tpyc/_data/runtime/cpp/include/tpy/next_iter.hpp +82 -0
- tpyc/_data/runtime/cpp/include/tpy/ordered_map.hpp +518 -0
- tpyc/_data/runtime/cpp/include/tpy/ordered_set.hpp +337 -0
- tpyc/_data/runtime/cpp/include/tpy/own_iter.hpp +54 -0
- tpyc/_data/runtime/cpp/include/tpy/pascal_graph_sdl.hpp +192 -0
- tpyc/_data/runtime/cpp/include/tpy/printing.hpp +302 -0
- tpyc/_data/runtime/cpp/include/tpy/protocols.hpp +61 -0
- tpyc/_data/runtime/cpp/include/tpy/range.hpp +115 -0
- tpyc/_data/runtime/cpp/include/tpy/ranges.hpp +212 -0
- tpyc/_data/runtime/cpp/include/tpy/set_ops.hpp +265 -0
- tpyc/_data/runtime/cpp/include/tpy/slice.hpp +47 -0
- tpyc/_data/runtime/cpp/include/tpy/span_iter.hpp +42 -0
- tpyc/_data/runtime/cpp/include/tpy/stdlib/math.hpp +41 -0
- tpyc/_data/runtime/cpp/include/tpy/stdlib/pcre2_h.hpp +96 -0
- tpyc/_data/runtime/cpp/include/tpy/stdlib/random.hpp +25 -0
- tpyc/_data/runtime/cpp/include/tpy/stdlib/socket_h.hpp +145 -0
- tpyc/_data/runtime/cpp/include/tpy/stdlib/time.hpp +62 -0
- tpyc/_data/runtime/cpp/include/tpy/system.hpp +121 -0
- tpyc/_data/runtime/cpp/include/tpy/throwable.hpp +55 -0
- tpyc/_data/runtime/cpp/include/tpy/tpy.hpp +156 -0
- tpyc/_data/runtime/cpp/include/tpy/type_name.hpp +77 -0
- tpyc/_data/runtime/cpp/include/tpy/type_traits.hpp +240 -0
- tpyc/_data/runtime/cpp/include/tpy/uninit_array_storage.hpp +250 -0
- tpyc/_data/runtime/cpp/include/tpy/uninit_heap_storage.hpp +277 -0
- tpyc/_data/runtime/cpp/include/tpy/varargs.hpp +174 -0
- tpyc/_data/runtime/cpp/include/tpy/variant_ref.hpp +118 -0
- tpyc/_data/runtime/cpp/src/stdlib/socket_impl.cpp +104 -0
- tpyc/_data/runtime/cpp/third_party/README.md +58 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/AUTHORS +36 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/CMakeLists.txt +1233 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/COPYING +5 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/ChangeLog +3097 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/HACKING +853 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/INSTALL +368 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/LICENCE +94 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/NEWS +492 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/NON-AUTOTOOLS-BUILD +430 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/README +956 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/cmake/COPYING-CMAKE-SCRIPTS +22 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/cmake/FindEditline.cmake +16 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/cmake/FindPackageHandleStandardArgs.cmake +58 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/cmake/FindReadline.cmake +29 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/cmake/pcre2-config-version.cmake.in +15 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/cmake/pcre2-config.cmake.in +148 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/config-cmake.h.in +56 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/libpcre2-16.pc.in +13 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/libpcre2-32.pc.in +13 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/libpcre2-8.pc.in +13 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/libpcre2-posix.pc.in +13 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/pcre2-config.in +121 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/config.h +483 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/config.h.generic +483 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/config.h.in +460 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2.h +1010 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2.h.generic +1010 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2.h.in +1010 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_auto_possess.c +1371 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_chartables.c +196 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_chartables.c.dist +196 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_chkdint.c +96 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_compile.c +11001 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_config.c +252 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_context.c +510 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_convert.c +1189 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_dfa_match.c +4119 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_dftables.c +297 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_error.c +345 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_extuni.c +162 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_find_bracket.c +219 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_fuzzsupport.c +792 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_internal.h +2084 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_intmodedep.h +940 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_jit_compile.c +14972 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_jit_match.c +200 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_jit_misc.c +234 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_jit_neon_inc.h +354 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_jit_simd_inc.h +2355 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_jit_test.c +2528 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_maketables.c +165 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_match.c +7777 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_match_data.c +185 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_newline.c +243 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_ord2utf.c +120 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_pattern_info.c +432 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_printint.c +886 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_script_run.c +344 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_serialize.c +286 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_string_utils.c +237 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_study.c +1915 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_substitute.c +1009 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_substring.c +550 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_tables.c +234 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_ucd.c +5460 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_ucp.h +396 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_ucptables.c +1533 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_valid_utf.c +398 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_xclass.c +308 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2demo.c +497 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2grep.c +4606 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2posix.c +425 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2posix.h +187 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2posix_test.c +209 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2test.c +9708 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/allocator_src/sljitExecAllocatorApple.c +137 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/allocator_src/sljitExecAllocatorCore.c +327 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/allocator_src/sljitExecAllocatorFreeBSD.c +89 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/allocator_src/sljitExecAllocatorPosix.c +62 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/allocator_src/sljitExecAllocatorWindows.c +40 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/allocator_src/sljitProtExecAllocatorNetBSD.c +72 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/allocator_src/sljitProtExecAllocatorPosix.c +172 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/allocator_src/sljitWXExecAllocatorPosix.c +141 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/allocator_src/sljitWXExecAllocatorWindows.c +102 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitConfig.h +142 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitConfigCPU.h +188 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitConfigInternal.h +907 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitLir.c +3561 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitLir.h +2466 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeARM_32.c +4636 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeARM_64.c +3491 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeARM_T2_32.c +4302 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeLOONGARCH_64.c +3765 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeMIPS_32.c +472 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeMIPS_64.c +387 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeMIPS_common.c +4259 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativePPC_32.c +485 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativePPC_64.c +719 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativePPC_common.c +3161 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeRISCV_32.c +142 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeRISCV_64.c +222 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeRISCV_common.c +3121 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeS390X.c +4526 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeX86_32.c +1685 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeX86_64.c +1398 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeX86_common.c +5001 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitSerialize.c +516 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitUtils.c +344 -0
- tpyc/_data/runtime/cpp/third_party/pcre2.sources.txt +54 -0
- tpyc/_data/runtime/cpp/third_party/pcre2.vendor.json +7 -0
- tpyc/build/__init__.py +7 -0
- tpyc/build/pcre2.py +122 -0
- tpyc/build/third_party.py +413 -0
- tpyc/cli.py +822 -0
- tpyc/codegen_cpp/__init__.py +18 -0
- tpyc/codegen_cpp/builtins.py +484 -0
- tpyc/codegen_cpp/context.py +2064 -0
- tpyc/codegen_cpp/expressions.py +5940 -0
- tpyc/codegen_cpp/functions.py +1913 -0
- tpyc/codegen_cpp/gen_async.py +3258 -0
- tpyc/codegen_cpp/gen_generators.py +657 -0
- tpyc/codegen_cpp/generator.py +2258 -0
- tpyc/codegen_cpp/match.py +1997 -0
- tpyc/codegen_cpp/param_const.py +172 -0
- tpyc/codegen_cpp/protocols.py +907 -0
- tpyc/codegen_cpp/records.py +1654 -0
- tpyc/codegen_cpp/resumable_cfg.py +1651 -0
- tpyc/codegen_cpp/statements.py +4963 -0
- tpyc/codegen_cpp/string_dispatch.py +76 -0
- tpyc/codegen_cpp/test_context.py +46 -0
- tpyc/codegen_cpp/test_param_const.py +113 -0
- tpyc/codegen_cpp/test_resumable_cfg.py +182 -0
- tpyc/codegen_cpp/type_resolution.py +53 -0
- tpyc/codegen_cpp/types.py +436 -0
- tpyc/codegen_cpp/variant_access.py +135 -0
- tpyc/coercions.py +749 -0
- tpyc/compilation_context.py +57 -0
- tpyc/compiler.py +3945 -0
- tpyc/cycle_detection.py +358 -0
- tpyc/diagnostics.py +135 -0
- tpyc/dump_types.py +353 -0
- tpyc/frontend_diagnostics.py +47 -0
- tpyc/frontend_ir/__init__.py +140 -0
- tpyc/frontend_ir/lower.py +1098 -0
- tpyc/frontend_ir/nodes.py +718 -0
- tpyc/frontend_ir/resolver_adapter.py +151 -0
- tpyc/frontend_plugin.py +209 -0
- tpyc/install_docs.py +81 -0
- tpyc/liveness.py +756 -0
- tpyc/macro_api.py +1724 -0
- tpyc/macro_loader.py +497 -0
- tpyc/module_names.py +64 -0
- tpyc/modules/__init__.py +31 -0
- tpyc/modules/defs.py +89 -0
- tpyc/modules/registry.py +36 -0
- tpyc/modules/resolver.py +192 -0
- tpyc/modules/type_resolution.py +629 -0
- tpyc/namespace.py +172 -0
- tpyc/parse/__init__.py +84 -0
- tpyc/parse/imports.py +490 -0
- tpyc/parse/nodes.py +1732 -0
- tpyc/parse/parser.py +4043 -0
- tpyc/parse/resolve_refs.py +466 -0
- tpyc/parse/type_resolver.py +1060 -0
- tpyc/prescan.py +254 -0
- tpyc/qnames.py +149 -0
- tpyc/repl.py +529 -0
- tpyc/repl_backends.py +848 -0
- tpyc/sema/__init__.py +21 -0
- tpyc/sema/analyzer.py +3625 -0
- tpyc/sema/bound_check.py +72 -0
- tpyc/sema/builder_trace.py +684 -0
- tpyc/sema/calls.py +5406 -0
- tpyc/sema/compatibility.py +2107 -0
- tpyc/sema/context.py +1243 -0
- tpyc/sema/expressions.py +3737 -0
- tpyc/sema/flow_facts.py +199 -0
- tpyc/sema/init_tracker.py +150 -0
- tpyc/sema/list_literals.py +69 -0
- tpyc/sema/literal_utils.py +27 -0
- tpyc/sema/local_deduction.py +1088 -0
- tpyc/sema/macros.py +179 -0
- tpyc/sema/match.py +1177 -0
- tpyc/sema/method_expansion.py +347 -0
- tpyc/sema/methods.py +2197 -0
- tpyc/sema/mutation_propagation.py +268 -0
- tpyc/sema/narrowing.py +857 -0
- tpyc/sema/numeric_lattice.py +160 -0
- tpyc/sema/operators.py +402 -0
- tpyc/sema/overloads.py +841 -0
- tpyc/sema/protocols.py +1209 -0
- tpyc/sema/reach_analysis.py +202 -0
- tpyc/sema/registration.py +3156 -0
- tpyc/sema/scope_tracker.py +193 -0
- tpyc/sema/statements.py +4426 -0
- tpyc/sema/type_ops.py +1879 -0
- tpyc/sema/value_range.py +181 -0
- tpyc/symbol_binding.py +259 -0
- tpyc/test_c3_mro.py +208 -0
- tpyc/test_cli_argv.py +52 -0
- tpyc/test_compiler.py +559 -0
- tpyc/test_contains_type_param.py +101 -0
- tpyc/test_cycle_detection.py +221 -0
- tpyc/test_dump_types.py +225 -0
- tpyc/test_install_docs.py +65 -0
- tpyc/test_local_cpp_form.py +135 -0
- tpyc/test_macro_loader.py +76 -0
- tpyc/test_method_expansion.py +254 -0
- tpyc/test_nominal_identity.py +182 -0
- tpyc/test_overloads.py +410 -0
- tpyc/test_parse.py +303 -0
- tpyc/test_parse_type_ref.py +506 -0
- tpyc/test_parse_version_info.py +58 -0
- tpyc/test_reach_analysis.py +72 -0
- tpyc/test_ref_type.py +216 -0
- tpyc/test_send_sync_substitution.py +276 -0
- tpyc/test_tuple_mutation_propagation.py +206 -0
- tpyc/test_type_def_registry.py +1729 -0
- tpyc/test_union_types.py +195 -0
- tpyc/type_def_registry.py +975 -0
- 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
|