X Tutup
Skip to content

ast.NodeVisitor for import tracking#7229

Merged
youknowone merged 1 commit intoRustPython:mainfrom
ShaharNaveh:deps-nodevisitor
Feb 26, 2026
Merged

ast.NodeVisitor for import tracking#7229
youknowone merged 1 commit intoRustPython:mainfrom
ShaharNaveh:deps-nodevisitor

Conversation

@ShaharNaveh
Copy link
Contributor

@ShaharNaveh ShaharNaveh commented Feb 26, 2026

New output:

  • [no deps] abc (18 dependents) | 2025-06-29
    • test_abc (1 TODO)
  • [no deps] struct (17 dependents) | 2026-01-21
    • test_struct (7 TODO)
  • [no deps] stat (13 dependents) | 2026-02-14
    • test_stat
  • [no deps] operator (7 dependents) | 2026-01-23
    • test_operator
  • [no deps] enum (7 dependents) | 2026-02-15
    • test_enum (4 TODO)
  • [no deps] signal (6 dependents) | 2024-04-26
    • test_signal (1 TODO)
  • [no deps] selectors (6 dependents) | 2025-07-20
    • test_selectors
  • [no deps] keyword (5 dependents) | 2024-06-21
    • test_keyword
  • [no deps] token (5 dependents) | 2026-01-22
  • [no deps] shlex (4 dependents) | 2026-02-02
    • test_shlex (4 TODO)
  • [no deps] __future__ (3 dependents) | 2024-04-23
    • test_future_stmt (8 TODO)
  • [no deps] bisect (3 dependents) | 2023-12-24
    • test_bisect
  • [no deps] numbers (3 dependents) | 2025-09-11
    • test_abstract_numbers
  • [no deps] reprlib (3 dependents) | 2026-01-21
    • test_reprlib (2 TODO)
  • [no deps] annotationlib (2 dependents) | 2026-02-24
    • test_annotationlib
  • [no deps] tty (2 dependents) | 2026-01-05
    • test_tty (2 TODO)
  • [no deps] cmd (2 dependents) | 2026-01-24
    • test_cmd
  • [no deps] stringprep (1 dependents) | 2019-12-21
    • test_stringprep
  • [no deps] _ios_support (1 dependents) | 2025-03-10
  • [no deps] __hello__ | 2023-02-25
  • [no deps] __phello__ | 2023-02-25
  • [no deps] colorsys | 2025-04-21
    • test_colorsys
  • [no deps] this | 2019-06-22
  • [no deps] graphlib | 2026-01-18
    • test_graphlib
  • [no deps] opcode | 2026-01-26 Δ313
    • test__opcode (2 TODO)
    • test_opcodes
  • [0/4 deps] re (59 dependents) | 2026-01-20
    • test_re (14 TODO)
  • [0/7 deps] argparse (26 dependents) | 2026-02-07
    • test_argparse
  • [0/3 deps] functools (26 dependents) | 2026-01-20
    • test_functools (9 TODO)
  • [0/2 deps] types (25 dependents) | 2026-02-18
    • test_types (10 TODO)
  • [0/2 deps] threading (20 dependents) | 2026-01-18
    • test_threading (18 TODO)
    • test_threadedtempfile
    • test_threading_local (3 TODO)
  • [0/3 deps] socket (17 dependents) | 2026-02-01
    • test_socket (16 TODO)
  • [0/3 deps] contextlib (16 dependents) | 2025-08-01
    • test_contextlib (2 TODO)
    • test_contextlib_async (2 TODO)
  • [0/4 deps] collections (15 dependents) | 2026-02-14 Δ61
    • test_collections (3 TODO)
    • test_deque (3 TODO)
    • test_defaultdict (1 TODO)
    • test_ordered_dict (8 TODO)
  • [0/1 deps] weakref (14 dependents) | 2026-01-30
    • test_weakref (20 TODO)
    • test_weakset
  • [0/2 deps] copy (11 dependents) | 2026-02-10
    • test_copy
  • [0/3 deps] base64 (10 dependents) | 2026-01-19
    • test_base64
  • [0/1 deps] getopt (10 dependents) | 2026-02-08
    • test_getopt
  • [0/7 deps] tempfile (10 dependents) | 2026-01-04 Δ26
    • test_tempfile (1 TODO)
  • [0/4 deps] posixpath (9 dependents) | 2026-02-13
    • test_posixpath
  • [0/5 deps] pickle (8 dependents) | 2026-02-05 Δ8
    • test_pickle (21 TODO)
    • test_picklebuffer (12 TODO)
    • test_pickletools (8 TODO)
  • [0/4 deps] ssl (8 dependents) | 2025-10-28 Δ4
    • test_ssl (21 TODO)
  • [0/1 deps] textwrap (7 dependents) | 2026-01-30
    • test_textwrap
  • [0/2 deps] codecs (7 dependents) | 2026-01-31
    • test_codecs (12 TODO)
    • test_codeccallbacks (9 TODO)
    • test_codecencodings_cn (4 TODO)
    • test_codecencodings_hk (1 TODO)
    • test_codecencodings_iso2022 (5 TODO)
    • test_codecencodings_jp (7 TODO)
    • test_codecencodings_kr (3 TODO)
    • test_codecencodings_tw (1 TODO)
    • test_codecmaps_cn (3 TODO)
    • test_codecmaps_hk (1 TODO)
    • test_codecmaps_jp (6 TODO)
    • test_codecmaps_kr (3 TODO)
    • test_codecmaps_tw (3 TODO)
    • test_charmapcodec
    • test_multibytecodec (untracked)
  • [0/6 deps] locale (7 dependents) | 2025-08-20 Δ11
    • test_locale
    • test__locale
  • [0/3 deps] ast (7 dependents) | 2026-02-02
    • test_ast (54 TODO)
    • test_unparse
    • test_type_comments (15 TODO)
  • [0/4 deps] fnmatch (6 dependents) | 2026-02-13
    • test_fnmatch
  • [0/2 deps] bz2 (6 dependents) | 2026-01-19
    • test_bz2 (1 TODO)
  • [0/2 deps] runpy (5 dependents) | 2025-09-11
    • test_runpy (2 TODO)
  • [0/3 deps] json (5 dependents) | 2026-01-18 Δ14
    • test_json (14 TODO)
  • [0/2 deps] random (5 dependents) | 2024-11-11 Δ149
    • test_random
  • [0/2 deps] copyreg (4 dependents) | 2026-01-24
    • test_copyreg
  • [0/1 deps] difflib (4 dependents) | 2026-02-08
    • test_difflib
  • [0/2 deps] lzma (4 dependents) | 2026-01-19
    • test_lzma (49 TODO)
  • [0/2 deps] queue (4 dependents) | 2026-02-04
    • test_queue
  • [0/1 deps] _colorize (4 dependents) | 2026-01-17
    • test__colorize
  • [0/1 deps] heapq (3 dependents) | 2026-01-18
    • test_heapq
  • [0/2 deps] hmac (3 dependents) | 2026-02-15
    • test_hmac (14 TODO)
  • [0/1 deps] string (3 dependents) | 2026-01-17
    • test_string
    • test_userstring
  • [0/1 deps] contextvars (3 dependents) | 2026-01-18
  • [0/5 deps] socketserver (3 dependents) | 2026-01-03
    • test_socketserver (1 TODO)
  • [0/5 deps] gzip (3 dependents) | 2026-01-19
    • test_gzip
  • [0/5 deps] pkgutil (3 dependents) | 2026-01-04 Δ57
    • test_pkgutil (1 TODO)
  • [0/15 deps] zipfile (3 dependents) | 2026-02-24
    • test_zipfile (15 TODO)
    • test_zipfile64
  • [0/3 deps] ntpath (3 dependents) | 2026-01-25
    • test_ntpath
  • [0/7 deps] pathlib (3 dependents) | 2026-02-13
    • test_pathlib
  • [0/2 deps] codeop (2 dependents) | 2026-02-07
    • test_codeop (4 TODO)
  • [0/2 deps] genericpath (2 dependents) | 2025-08-04
    • test_genericpath
  • [0/8 deps] glob (2 dependents) | 2026-02-13
    • test_glob
  • [0/2 deps] html (2 dependents) | 2026-02-15
    • test_html
    • test_htmlparser
  • [0/6 deps] plistlib (2 dependents) | 2026-01-04 Δ2
    • test_plistlib (6 TODO)
  • [0/2 deps] code (2 dependents) | 2026-02-01
    • test_code (11 TODO)
    • test_code_module (3 TODO)
  • [0/4 deps] py_compile (2 dependents) | 2026-01-30
    • test_py_compile (3 TODO)
  • [0/1 deps] quopri (2 dependents) | 2026-01-24
    • test_quopri
  • [0/8 deps] bdb (2 dependents) | 2025-12-30 Δ271
    • test_bdb (33 TODO)
  • [0/2 deps] mimetypes (2 dependents) | 2026-01-21
    • test_mimetypes
  • [0/3 deps] pstats (2 dependents)
    • test_pstats (untracked)
  • [0/6 deps] encodings (2 dependents) | 2026-02-06
  • [0/2 deps] ipaddress (1 dependents) | 2026-01-18
    • test_ipaddress
  • [0/2 deps] netrc (1 dependents) | 2025-08-20
    • test_netrc
  • [0/2 deps] pyclbr (1 dependents) | 2025-07-25
    • test_pyclbr (2 TODO)
  • [0/1 deps] secrets (1 dependents) | 2025-07-17
    • test_secrets
  • [0/2 deps] site (1 dependents) | 2026-01-17 Δ29
    • test_site (4 TODO)
  • [0/3 deps] filecmp (1 dependents) | 2026-01-03
    • test_filecmp
  • [0/7 deps] dataclasses (1 dependents) | 2026-02-08
    • test_dataclasses (10 TODO)
  • [0/4 deps] getpass (1 dependents) | 2026-02-08
    • test_getpass
  • [0/4 deps] rlcompleter (1 dependents) | 2025-07-17
    • test_rlcompleter (1 TODO)
  • [0/5 deps] configparser (1 dependents) | 2026-02-07
    • test_configparser
  • [0/6 deps] dbm (1 dependents) | 2026-01-01
    • test_dbm (2 TODO)
    • test_dbm_dumb
    • test_dbm_gnu (untracked)
    • test_dbm_ndbm (untracked)
    • test_dbm_sqlite3
  • [0/2 deps] sqlite3 (1 dependents) | 2026-01-19
    • test_sqlite3 (82 TODO)
  • [0/2 deps] zipimport (1 dependents) | 2026-01-24
    • test_zipimport (2 TODO)
    • test_zipimport_support (untracked)
  • [0/11 deps] tarfile (1 dependents) | 2025-05-07 Δ527
    • test_tarfile (3 TODO)
  • [0/2 deps] csv (1 dependents) | 2026-02-18
    • test_csv (27 TODO)
  • [0/1 deps] _apple_support | 2025-03-10
  • [0/2 deps] nturl2path | 2026-01-25
    • test_nturl2path
  • [0/7 deps] zipapp | 2025-08-06 Δ14
    • test_zipapp
  • [0/6 deps] fileinput | 2025-04-30
    • test_fileinput
  • [0/4 deps] fractions | 2026-01-30
    • test_fractions (2 TODO)
  • [0/2 deps] optparse | 2026-01-30
    • test_optparse
  • [0/3 deps] wave | 2026-02-13
    • test_wave
  • [0/1 deps] _android_support | 2025-10-22 Δ7
  • [0/4 deps] modulefinder
    • test_modulefinder (untracked)
  • [0/2 deps] sched | 2025-04-21
    • test_sched
  • [0/2 deps] shelve | 2026-01-01
    • test_shelve
  • [0/5 deps] timeit | 2026-02-01
    • test_timeit
  • [0/1 deps] curses
    • test_curses (untracked)
  • [0/2 deps] pty | 2026-01-05 Δ51
    • test_pty (4 TODO)
  • [0/9 deps] xmlrpc | 2026-02-14
    • test_xmlrpc (5 TODO)
    • test_docxmlrpc
  • [0/5 deps] compression | 2026-01-19
  • [0/2 deps] symtable | 2026-01-30
    • test_symtable (17 TODO)
  • [0/2 deps] tomllib | 2026-02-08
    • test_tomllib
  • [1/7 deps] os (84 dependents) | 2026-02-03
    • test_os (3 TODO)
    • test_popen
  • [1/6 deps] warnings (53 dependents) | 2026-01-18
    • test_warnings (12 TODO)
  • [1/6 deps] io (42 dependents) | 2026-02-13
    • test_io (21 TODO)
    • test_bufio
    • test_fileio (1 TODO)
    • test_memoryio (28 TODO)
  • [1/11 deps] traceback (17 dependents) | 2026-02-06
    • test_traceback (34 TODO)
  • [1/13 deps] inspect (14 dependents) | 2026-02-07
    • test_inspect (46 TODO)
  • [1/9 deps] subprocess (14 dependents) | 2026-02-04 Δ2
    • test_subprocess (4 TODO)
  • [1/2 deps] linecache (12 dependents) | 2026-02-09
    • test_linecache
  • [1/5 deps] tokenize (11 dependents) | 2022-08-09 Δ357
    • test_tokenize (2 TODO)
  • [1/6 deps] datetime (7 dependents) | 2026-02-24
    • test_datetime
    • test_strptime (untracked)
  • [1/4 deps] calendar (5 dependents) | 2026-01-17
    • test_calendar
  • [1/1 deps] hashlib (5 dependents) | 2026-02-14
    • test_hashlib (7 TODO)
  • [1/4 deps] dis (5 dependents) | 2026-01-26
    • test_dis (43 TODO)
  • [1/7 deps] webbrowser (4 dependents) | 2025-04-21 Δ49
    • test_webbrowser
  • [1/3 deps] pprint (3 dependents) | 2026-02-06
    • test_pprint
  • [1/11 deps] email (3 dependents) | 2026-01-17 Δ238
    • test_email (12 TODO)
  • [1/10 deps] typing (2 dependents) | 2026-02-11
    • test_typing (4 TODO)
    • test_type_aliases
    • test_type_annotations (1 TODO)
    • test_type_params (6 TODO)
    • test_genericalias
  • [1/3 deps] tabnanny (1 dependents) | 2026-02-02
    • test_tabnanny (5 TODO)
  • [1/4 deps] ftplib (1 dependents) | 2026-02-02
    • test_ftplib (4 TODO)
  • [1/8 deps] smtplib (1 dependents) | 2025-12-19 Δ11
    • test_smtplib
    • test_smtpnet
  • [1/4 deps] profile (1 dependents)
    • test_profile (untracked)
    • test_cprofile (untracked)
  • [1/3 deps] tracemalloc (1 dependents)
    • test_tracemalloc (untracked)
  • [1/2 deps] antigravity | 2023-02-28
  • [1/4 deps] poplib
    • test_poplib (untracked)
  • [1/5 deps] pickletools | 2026-02-06
  • [1/6 deps] gettext | 2026-01-30
    • test_gettext (7 TODO)
  • [1/7 deps] compileall | 2026-02-25
    • test_compileall (2 TODO)
  • [1/8 deps] mailbox | 2026-02-14
    • test_mailbox
  • [1/5 deps] decimal | 2026-01-30
    • test_decimal (1 TODO)
  • [1/5 deps] wsgiref | 2026-01-03 Δ7
    • test_wsgiref (1 TODO)
  • [1/2 deps] statistics | 2026-02-11
    • test_statistics (1 TODO)
  • [1/11 deps] xml | 2025-08-21 Δ35
    • test_xml_etree (55 TODO)
    • test_xml_etree_c
    • test_minidom (untracked)
    • test_pulldom (4 TODO)
    • test_pyexpat (28 TODO)
    • test_sax (untracked)
    • test_xml_dom_minicompat
    • test_xml_dom_xmlbuilder
  • [2/9 deps] shutil (12 dependents) | 2026-02-15
    • test_shutil
  • [2/9 deps] tkinter (2 dependents) | 2025-04-06 Δ279
    • test_tkinter (untracked)
    • test_ttk (untracked)
    • test_ttk_textonly (untracked)
    • test_tcl (untracked)
    • test_idle (untracked)
  • [2/12 deps] doctest (1 dependents) | 2026-02-11
    • test_doctest (9 TODO)
  • [2/5 deps] cProfile
  • [3/11 deps] sysconfig (6 dependents) | 2025-10-22 Δ265
    • test_sysconfig (8 TODO)
    • test__osx_support
  • [3/11 deps] platform (4 dependents) | 2026-01-04 Δ124
    • test_platform
  • [3/9 deps] ctypes (3 dependents) | 2026-02-18
    • test_ctypes (11 TODO)
    • test_stable_abi_ctypes
  • [3/9 deps] uuid (1 dependents) | 2026-02-02
    • test_uuid
  • [3/8 deps] venv | 2026-01-17 Δ29
    • test_venv (4 TODO)
  • [3/12 deps] trace | 2025-07-25 Δ15
    • test_trace (14 TODO)
  • [3/5 deps] ensurepip | 2026-01-17
    • test_ensurepip
  • [3/10 deps] imaplib | 2026-02-01
    • test_imaplib (1 TODO)
  • [3/11 deps] zoneinfo | 2025-09-07 Δ24
    • test_zoneinfo (3 TODO)
  • [3/23 deps] http | 2026-01-16 Δ198
    • test_httplib
    • test_http_cookiejar
    • test_http_cookies
    • test_httpservers (1 TODO)
  • [3/7 deps] turtle
    • test_turtle (untracked)
  • [4/19 deps] logging (7 dependents) | 2025-07-20 Δ77
    • test_logging (5 TODO)
  • [4/20 deps] unittest (2 dependents) | 2026-01-18 Δ102
    • test_unittest (15 TODO)
  • [4/19 deps] urllib (1 dependents) | 2026-02-13
    • test_urllib
    • test_urllib2
    • test_urllib2_localnet
    • test_urllib2net
    • test_urllibnet
    • test_urlparse
    • test_urllib_response
    • test_robotparser
  • [4/10 deps] concurrent | 2026-01-09 Δ1012
    • test_concurrent_futures (18 TODO)
    • test_interpreters (untracked)
    • test__interpreters (untracked)
    • test__interpchannels (untracked)
    • test_crossinterp (untracked)
  • [5/15 deps] pydoc (4 dependents) | 2026-02-13
    • test_pydoc (36 TODO)
  • [5/21 deps] importlib (4 dependents) | 2026-02-05
    • test_importlib (16 TODO)
  • [5/27 deps] multiprocessing (2 dependents) | 2026-02-04 Δ314
    • test_multiprocessing_fork (35 TODO)
    • test_multiprocessing_forkserver (10 TODO)
    • test_multiprocessing_spawn (13 TODO)
    • test_multiprocessing_main_handling
  • [5/32 deps] pdb (1 dependents) | 2026-02-11 Δ2601
    • test_pdb (untracked)
  • [5/25 deps] _pyrepl | 2025-04-11 Δ2534
  • [7/32 deps] asyncio (2 dependents) | 2026-02-02 Δ26
    • test_asyncio (38 TODO)
  • [10/39 deps] idlelib

Standalone Tests

  • test_atexit
    • _test_atexit
  • test_eintr
    • _test_eintr (6 TODO)
  • _test_embed_structseq (untracked)
  • _test_gc_fast_cycles (untracked)
  • _test_monitoring_shutdown (untracked)
  • _test_multiprocessing (15 TODO)
  • _test_venv_multiprocessing
  • test___all__
  • test_android
  • test_apple
  • test_array (55 TODO)
  • test_asdl_parser (untracked)
  • test_asyncgen (4 TODO)
  • test_audit
  • test_augassign
  • test_exceptions (25 TODO)
    • test_baseexception
    • test_except_star (1 TODO)
    • test_exception_group (3 TODO)
    • test_exception_hierarchy (2 TODO)
    • test_exception_variations
  • test_bigaddrspace
  • test_bigmem (4 TODO)
  • test_binascii (1 TODO)
  • test_binop
  • test_bool
  • test_buffer (11 TODO)
  • test_build_details (untracked)
  • test_builtin (25 TODO)
  • test_bytes (17 TODO)
  • test_c_locale_coercion
  • test_call (1 TODO)
  • test_capi (untracked)
  • test_cext (untracked)
  • test_class (15 TODO)
    • test_genericclass
    • test_subclassinit
  • test_clinic (untracked)
  • test_cmath
  • test_cmd_line (24 TODO)
  • test_cmd_line_script (15 TODO)
  • test_compare
  • test_compile (24 TODO)
    • test_compiler_assemble
    • test_compiler_codegen
    • test_peepholer (31 TODO)
  • test_complex (2 TODO)
  • test_contains (1 TODO)
  • test_context (6 TODO)
  • test_coroutines (19 TODO)
  • test_cppext (untracked)
  • test_decorators (1 TODO)
  • test_descr (47 TODO)
    • test_descrtut (3 TODO)
  • test_devpoll
  • test_dict (6 TODO)
    • test_dictcomps (1 TODO)
    • test_dictviews (2 TODO)
    • test_userdict
  • test_dtrace (8 TODO)
  • test_dynamic (1 TODO)
  • test_dynamicclassattribute
  • test_embed (untracked)
  • test_enumerate
  • test_eof (6 TODO)
  • test_epoll
  • test_errno
  • test_extcall (8 TODO)
  • test_external_inspection (untracked)
  • test_faulthandler (4 TODO)
  • test_fcntl
    • test_ioctl
  • test_file
    • test_largefile
  • test_file_eintr (1 TODO)
  • test_fileutils (untracked)
  • test_finalization (untracked)
  • test_float (6 TODO)
    • test_strtod (6 TODO)
  • test_flufl (4 TODO)
  • test_fork1 (1 TODO)
  • test_format (5 TODO)
  • test_frame (untracked)
  • test_free_threading (untracked)
  • test_frozen
  • test_str (16 TODO)
    • test_fstring (19 TODO)
    • test_string_literals (5 TODO)
  • test_funcattrs (6 TODO)
  • test_gc
  • test_gdb (untracked)
  • test_generated_cases (untracked)
  • test_generators (12 TODO)
    • test_genexps (untracked)
    • test_generator_stop (untracked)
    • test_yield_from (6 TODO)
  • test_getpath (untracked)
  • test_global (3 TODO)
  • test_grammar (18 TODO)
  • test_grp
  • test_hash (4 TODO)
  • test_import (3 TODO)
  • test_index
  • test_int (7 TODO)
    • test_long (4 TODO)
    • test_int_literal
  • test_isinstance
  • test_iter (1 TODO)
  • test_iterlen
  • test_itertools (6 TODO)
  • test_keywordonlyarg
  • test_kqueue
  • test_launcher
  • test_list (5 TODO)
    • test_listcomps (1 TODO)
    • test_userlist (1 TODO)
  • test_lltrace (untracked)
  • test_longexp
  • test_marshal (21 TODO)
  • test_math
    • test_math_property
  • test_memoryview (9 TODO)
  • test_metaclass (10 TODO)
  • test_mmap (2 TODO)
  • test_module (4 TODO)
  • test_monitoring (untracked)
  • test_msvcrt
  • test_named_expressions (12 TODO)
  • test_numeric_tower
  • test_opcache
  • test_openpty
  • test_optimizer (untracked)
  • test_osx_env
  • test_patma (20 TODO)
  • test_peg_generator (untracked)
  • test_pep646_syntax (12 TODO)
  • test_perf_profiler (untracked)
  • test_perfmaps (untracked)
  • test_pkg
  • test_select (3 TODO)
    • test_poll (1 TODO)
  • test_positional_only_arg (4 TODO)
  • test_posix (4 TODO)
  • test_pow
  • test_print (6 TODO)
  • test_property
  • test_pwd
  • test_pyrepl (untracked)
    • test_repl
  • test_raise
  • test_range (1 TODO)
  • test_readline (untracked)
  • test_regrtest (10 TODO)
  • test_remote_pdb (untracked)
  • test_resource (2 TODO)
  • test_richcmp
  • test_scope (1 TODO)
  • test_support (3 TODO)
    • test_script_helper
  • test_set (5 TODO)
  • test_setcomps
  • test_slice (1 TODO)
  • test_sort (2 TODO)
  • test_source_encoding (untracked)
  • test_startfile (untracked)
  • test_time
    • test_strftime
  • test_structseq
  • test_sundry
  • test_super (4 TODO)
  • test_syntax (26 TODO)
  • test_sys (8 TODO)
    • test_syslog (2 TODO)
    • test_sys_setprofile (14 TODO)
    • test_sys_settrace (85 TODO)
  • test_termios (15 TODO)
  • test_thread
    • test_thread_local_bytecode (untracked)
    • test_threadsignals
  • test_timeout
  • test_tools
  • test_tstring (5 TODO)
  • test_tuple (1 TODO)
  • test_type_cache (untracked)
  • test_typechecks
  • test_unicodedata (9 TODO)
    • test_unicode_file
    • test_unicode_file_functions
    • test_unicode_identifiers (1 TODO)
    • test_ucn (3 TODO)
  • test_unary
  • test_univnewlines
  • test_unpack (1 TODO)
    • test_unpack_ex (11 TODO)
  • test_utf8_mode (6 TODO)
  • test_utf8source (2 TODO)
  • test_wait3
  • test_wait4
  • test_winapi
  • test_winconsoleio
  • test_winreg
  • test_winsound
  • test_with (1 TODO)
  • test_wmi
  • test_xpickle (untracked)
  • test_xxlimited (untracked)
  • test_xxtestfuzz (untracked)
  • test_zlib (2 TODO)
  • test_zstd

Untracked Files

  • site-packages/README.txt

Original Files

  • PSF-LICENSE
  • README.md
  • _dummy_os.py
  • _dummy_thread.py
  • _pycodecs.py
  • dummy_threading.py

Summary by CodeRabbit

  • Refactor
    • Improved test dependency mapping to accurately handle edge-case naming conventions, ensuring correct library associations and proper test execution ordering.
    • Enhanced import detection mechanism for more reliable identification of library and test dependencies.
    • Optimized TODO marker tracking system for simplified maintenance workflows and clearer project status visibility.

@ShaharNaveh ShaharNaveh added the skip:ci Skip running the ci label Feb 26, 2026
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 26, 2026

📝 Walkthrough

Walkthrough

The pull request refactors import parsing logic in scripts/update_lib/deps.py from regex-based to AST-based methods via an ImportVisitor class, introduces a TODO_MARKER constant for rustpython TODO tracking, and adjusts lib_name extraction logic in scripts/update_lib/cmd_todo.py to handle additional test name patterns.

Changes

Cohort / File(s) Summary
Test library mapping
scripts/update_lib/cmd_todo.py
Enhanced lib_name extraction in compute_test_todo_list to strip both "test_" prefix and "_test" suffix variants, improving handling of edge-case test names.
Import parsing refactor
scripts/update_lib/deps.py
Replaced regex-based import parsing with AST-based ImportVisitor class; added special handling for test.support and test.findfile; introduced TODO_MARKER constant and refactored TODO counting logic; removed legacy regex helpers.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • moreal
  • youknowone

Poem

🐰 With AST in paw, the parser bounds,
No regex strings can hold it down—
Import paths dance through visitor nodes,
While lib_names map all test codes,
A rabbit's refactor, clean and sound! ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly describes the main change: introducing AST-based import tracking using ast.NodeVisitor to replace regex-based parsing in the codebase.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@ShaharNaveh ShaharNaveh marked this pull request as ready for review February 26, 2026 12:27
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@scripts/update_lib/cmd_todo.py`:
- Line 337: The code that derives lib_name from test_name using chained
removeprefix calls produces a leftover leading underscore for names like
"_test_atexit" (e.g., test_name -> lib_name via lib_name =
test_name.removeprefix("test_").removeprefix("_test")), causing lib_status
lookups to fail; fix by normalizing test_name first (strip leading underscores
or check both "test_" and "_test_" patterns) and then remove the correct prefix
so that lib_name becomes "atexit" (update the logic around lib_name derivation
where test_name is processed, ensuring downstream lib_status and DEPENDENCIES
lookups receive the cleaned library name).

In `@scripts/update_lib/deps.py`:
- Around line 140-142: The docstring for count_rustpython_todo says “Count lines
containing RustPython TODO markers” but the implementation returns
content.count(TODO_MARKER) (counting occurrences); update one to match the
other: either change the docstring to “Count occurrences of TODO_MARKER in
content” or change the implementation in count_rustpython_todo to perform a
line-based count (e.g., iterate over content.splitlines() and sum 1 for lines
that contain TODO_MARKER) so the behavior matches the docstring; references:
function count_rustpython_todo and symbol TODO_MARKER.
- Around line 96-102: In visit_Call, guard access to node.args[0] by first
checking that node.args is non-empty and then ensure the constant's value is a
string before calling endswith; specifically, before "arg = node.args[0]" check
"if not node.args: return" and after confirming isinstance(arg, ast.Constant)
verify "isinstance(arg.value, str)" (or similar) before assigning target/using
target.endswith(".py") so non-string constants or missing args won't raise
IndexError or AttributeError.
- Around line 51-55: The code currently strips module roots by using
name.split(".",1)[-1] and also constructs from-import entries as "module.alias"
which breaks for relative imports (module is None); change the import parsing so
Import names use the top-level component (use name.split(".",1)[0] for
real_name) and change the ImportFrom handling to: if node.module is None
(relative import) use the alias name as the import key, otherwise use the full
module (or module + "." + alias if you need the specific attribute) instead of
blindly synthesizing "module.alias"; update where real_name is added to
self.test_imports / self.lib_imports accordingly.

ℹ️ Review info

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 457d328 and 66a9988.

📒 Files selected for processing (2)
  • scripts/update_lib/cmd_todo.py
  • scripts/update_lib/deps.py

else:
# Extract lib name from test name (test_foo -> foo)
lib_name = test_name.removeprefix("test_")
lib_name = test_name.removeprefix("test_").removeprefix("_test")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cat -n scripts/update_lib/cmd_todo.py | sed -n '330,345p'

Repository: RustPython/RustPython

Length of output: 1000


🏁 Script executed:

cat -n scripts/update_lib/cmd_todo.py | sed -n '320,360p'

Repository: RustPython/RustPython

Length of output: 1932


🏁 Script executed:

find . -name "*.py" -type f | xargs grep -l "_test_atexit\|_test_eintr" 2>/dev/null | head -10

Repository: RustPython/RustPython

Length of output: 144


🏁 Script executed:

cat -n scripts/update_lib/deps.py | grep -A 5 -B 5 "atexit\|eintr" | head -30

Repository: RustPython/RustPython

Length of output: 964


🏁 Script executed:

python3 <<'PY'
# Test the actual behavior
cases = [
    "test_os",
    "test_atexit", 
    "_test_atexit",
    "_test_eintr",
    "test_code",
    "_test_code"
]

print("Testing current implementation:")
for t in cases:
    result = t.removeprefix("test_").removeprefix("_test")
    print(f"  {t:20} → {result:15}")

print("\nTesting proposed fix:")
for t in cases:
    result = t.removeprefix("test_").removeprefix("_test_")
    print(f"  {t:20} → {result:15}")
PY

Repository: RustPython/RustPython

Length of output: 611


🏁 Script executed:

grep -A 200 "DEPENDENCIES = {" scripts/update_lib/deps.py | head -100

Repository: RustPython/RustPython

Length of output: 2702


Fix _test_* prefix fallback mapping to correctly extract library name.

At line 337, tests with _test_ prefix (e.g., _test_atexit) fail to map correctly. The current chained removeprefix leaves a leading underscore: _test_atexit_atexit instead of atexit. This causes subsequent lib_status lookup at line 342 to miss the correct library entry, breaking todo prioritization and scoring for these edge-case tests that exist in the DEPENDENCIES mapping but not in the primary test-to-library lookup.

Suggested fix
-            lib_name = test_name.removeprefix("test_").removeprefix("_test")
+            lib_name = test_name.removeprefix("test_").removeprefix("_test_")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
lib_name = test_name.removeprefix("test_").removeprefix("_test")
lib_name = test_name.removeprefix("test_").removeprefix("_test_")
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/update_lib/cmd_todo.py` at line 337, The code that derives lib_name
from test_name using chained removeprefix calls produces a leftover leading
underscore for names like "_test_atexit" (e.g., test_name -> lib_name via
lib_name = test_name.removeprefix("test_").removeprefix("_test")), causing
lib_status lookups to fail; fix by normalizing test_name first (strip leading
underscores or check both "test_" and "_test_" patterns) and then remove the
correct prefix so that lib_name becomes "atexit" (update the logic around
lib_name derivation where test_name is processed, ensuring downstream lib_status
and DEPENDENCIES lookups receive the cleaned library name).

Comment on lines +51 to +55
real_name = name.split(".", 1)[-1]
if name.startswith("test."):
self.test_imports.add(real_name)
else:
self.lib_imports.add(real_name)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Import parsing currently loses module roots and misclassifies from imports.

At Lines 51-55, name.split(".", 1)[-1] turns os.path into path; at Lines 61-70, from imports are synthesized as module.alias, which also yields bad entries for relative imports (module is None). This will skew dependency resolution broadly.

💡 Suggested fix
     def add_import(self, name: str) -> None:
@@
-        real_name = name.split(".", 1)[-1]
-        if name.startswith("test."):
-            self.test_imports.add(real_name)
-        else:
-            self.lib_imports.add(real_name)
+        if name.startswith("test."):
+            # Keep first component under test.* (e.g. test.test_foo.bar -> test_foo)
+            rest = name.removeprefix("test.")
+            self.test_imports.add(rest.split(".", 1)[0])
+            return
+        # Track top-level stdlib module (e.g. os.path -> os)
+        self.lib_imports.add(name.split(".", 1)[0])
@@
     def visit_ImportFrom(self, node):
-        try:
-            module = node.module
-        except AttributeError:
-            # Ignore `from . import my_internal_module`
-            return
-
-        for name in node.names:
-            self.add_import(f"{module}.{name}")
+        # Ignore relative-only imports like: from . import foo
+        if not node.module:
+            return
+        # Keep module-level dependency; alias names are often attributes, not modules
+        self.add_import(node.module)
#!/bin/bash
python - <<'PY'
import ast

samples = [
    "import os.path",
    "from xml.etree import ElementTree",
    "from . import _local",
]

for s in samples:
    n = ast.parse(s).body[0]
    if isinstance(n, ast.Import):
        name = n.names[0].name
        print(f"{s!r} -> current split gives: {name.split('.',1)[-1]!r}")
    else:
        module = n.module
        alias = n.names[0].name
        print(f"{s!r} -> synthesized: {module}.{alias}")
PY

Also applies to: 61-70

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/update_lib/deps.py` around lines 51 - 55, The code currently strips
module roots by using name.split(".",1)[-1] and also constructs from-import
entries as "module.alias" which breaks for relative imports (module is None);
change the import parsing so Import names use the top-level component (use
name.split(".",1)[0] for real_name) and change the ImportFrom handling to: if
node.module is None (relative import) use the alias name as the import key,
otherwise use the full module (or module + "." + alias if you need the specific
attribute) instead of blindly synthesizing "module.alias"; update where
real_name is added to self.test_imports / self.lib_imports accordingly.

Comment on lines +96 to +102
arg = node.args[0]
if not isinstance(arg, ast.Constant):
return

target = arg.value
if not target.endswith(".py"):
return
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# First, let's examine the file to understand the context
cat -n scripts/update_lib/deps.py | sed -n '85,110p'

Repository: RustPython/RustPython

Length of output: 951


🏁 Script executed:

#!/bin/bash
# Run the provided AST demonstration
python - <<'PY'
import ast

for src in ["support.findfile()", "support.findfile(123)", "support.findfile('_test_atexit.py')"]:
    call = ast.parse(src).body[0].value
    print(src, "args_len=", len(call.args), "arg0_type=", type(call.args[0]).__name__ if call.args else None)
PY

Repository: RustPython/RustPython

Length of output: 233


🏁 Script executed:

#!/bin/bash
# Let's check the broader context around the visit_Call method
grep -n "def visit_Call" scripts/update_lib/deps.py

Repository: RustPython/RustPython

Length of output: 107


visit_Call should validate findfile arguments to prevent crashes.

At line 96, indexing node.args[0] raises IndexError when no arguments are provided. At line 101, target.endswith(".py") assumes arg.value is a string, but ast.Constant can hold any constant type (int, float, None, etc.), causing AttributeError on non-string values.

Suggested fix
+        if not node.args:
+            return
         arg = node.args[0]
         if not isinstance(arg, ast.Constant):
             return
 
         target = arg.value
+        if not isinstance(target, str):
+            return
         if not target.endswith(".py"):
             return
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
arg = node.args[0]
if not isinstance(arg, ast.Constant):
return
target = arg.value
if not target.endswith(".py"):
return
if not node.args:
return
arg = node.args[0]
if not isinstance(arg, ast.Constant):
return
target = arg.value
if not isinstance(target, str):
return
if not target.endswith(".py"):
return
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/update_lib/deps.py` around lines 96 - 102, In visit_Call, guard
access to node.args[0] by first checking that node.args is non-empty and then
ensure the constant's value is a string before calling endswith; specifically,
before "arg = node.args[0]" check "if not node.args: return" and after
confirming isinstance(arg, ast.Constant) verify "isinstance(arg.value, str)" (or
similar) before assigning target/using target.endswith(".py") so non-string
constants or missing args won't raise IndexError or AttributeError.

Comment on lines 140 to +142
def count_rustpython_todo(content: str) -> int:
"""Count lines containing RustPython TODO markers."""
return sum(1 for line in content.splitlines() if TODO_MARKER in line)
return content.count(TODO_MARKER)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Docstring and implementation disagree on TODO semantics.

At Line 141 the doc says “Count lines…”, but Line 142 counts marker occurrences. Either update the docstring or switch to line-based counting to avoid ambiguity.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/update_lib/deps.py` around lines 140 - 142, The docstring for
count_rustpython_todo says “Count lines containing RustPython TODO markers” but
the implementation returns content.count(TODO_MARKER) (counting occurrences);
update one to match the other: either change the docstring to “Count occurrences
of TODO_MARKER in content” or change the implementation in count_rustpython_todo
to perform a line-based count (e.g., iterate over content.splitlines() and sum 1
for lines that contain TODO_MARKER) so the behavior matches the docstring;
references: function count_rustpython_todo and symbol TODO_MARKER.

@youknowone
Copy link
Member

isn't this very slow? I removed ast because it was too slow for interactive tools to parse every test files.
otherwise probably you used it in better way.

@ShaharNaveh
Copy link
Contributor Author

isn't this very slow? I removed ast because it was too slow for interactive tools to parse every test files. otherwise probably you used it in better way.

$ hyperfine --warmup 1 --command-name before --prepare 'git switch main || true' 'python scripts/update_lib/ todo --done --lib ~/Work/cpython/' --command-name after --prepare 'git switch deps-nodevisitor' 'python scripts/update_lib/ todo --done --lib ~/Work/cpython' --export-markdown ~/out.md
Command Mean [ms] Min [ms] Max [ms] Relative
before 46.6 ± 3.0 40.2 52.5 1.01 ± 0.11
after 45.9 ± 4.0 40.7 59.2 1.00

It's actually faster this way 🤷

@fanninpm
Copy link
Contributor

It's actually faster this way 🤷

It's within the margin of error.

@youknowone youknowone merged commit 804a7e4 into RustPython:main Feb 26, 2026
9 checks passed
youknowone added a commit to youknowone/RustPython that referenced this pull request Feb 26, 2026
youknowone added a commit that referenced this pull request Feb 26, 2026
@youknowone
Copy link
Member

@ShaharNaveh I reverted this in #7230 due to CI. Let's fix update_libs and merge this again. Sorry for inconvenience!

ShaharNaveh added a commit to ShaharNaveh/RustPython that referenced this pull request Feb 27, 2026
youknowone pushed a commit that referenced this pull request Feb 28, 2026
* Reapply "`ast.NodeVisitor` for import tracking (#7229)" (#7230)

This reverts commit a47572c.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

skip:ci Skip running the ci

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

X Tutup