国家中小学智慧教育平台 电子课本下载工具,帮助您从智慧教育平台中获取电子课本的 PDF 文件网址并进行下载,让您更方便地获取课本内容。
This report summarizes scanner evidence for happycola233/tchMaterial-parser, a Python project with 7,093 GitHub stars. SynthScan examined 6,852 lines of code across 50 source files, recording 188 pattern matches distributed across 7 syntactic categories. The legacy adjusted pattern signal is 36.1 (High pattern signal); it is not an authorship estimate.
Use the findings to ask whether maintainers can explain intent, verify dependencies, simplify unnecessary scaffolding, and focus review effort. Risk Payload v1 adds ownership, supply-chain, over-engineering, and review-effort vectors when available. These are prompts for human verification, not probabilities, security findings, or measured maintenance costs.
Use each vector to guide manual verification of the underlying findings.
Can maintainers explain intent, assumptions, and trade-offs? 146 finding(s).
Are imports declared and package/API names verified? 1 finding(s).
Are wrappers, guards, and repeated structures necessary? 170 finding(s).
Which changes need focused human review? 188 finding(s).
This chart tracks the legacy adjusted pattern score across scan runs. Changes can reflect source changes, scan coverage, or detector/scoring versions; they do not measure AI adoption or prove that a team refactored code. Compare runs only when their scoring versions are compatible. The dashed line tracks the raw pattern-hit count.
Groups findings by configured severity weight. Severity is not a confidence estimate, security rating, or proof that a package is missing. Verify imports against the project's manifests and inspect each finding in its local design context.
This horizontal bar chart shows where configured pattern scores accumulate across directories. Treat the bars as locations to inspect, not as evidence of authorship or code quality. Use the file-level findings to decide whether a directory needs a focused ownership, dependency, complexity, or review check.
The scanner identified 188 distinct pattern matches across 7 syntactic categories. Each entry below represents a discrete location in the source code where the engine recorded a detector match to inspect in context. Expand any category row to inspect the individual file paths, line numbers, code snippets, and the lexical context (CODE, COMMENT, or STRING) in which each match was detected.
Reading the findings table: The Severity column indicates the configured finding weight (CRITICAL / HIGH / MEDIUM / LOW). The Context column identifies whether the match occurred inside executable code, an inline comment, or a string literal — legacy comment-context matches receive a ×1.5 score weight. The ⚡ bolt icon marks clustered matches: three or more patterns within a 10-line window, each receiving an additional ×1.5 density multiplier under the legacy scoring model.
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW⚡ | tests/test_resource_urls.py | 59 | def test_builds_detail_url_for_regular_book(self) -> None: | CODE |
| LOW⚡ | tests/test_resource_urls.py | 66 | def test_falls_back_to_default_type_and_path_id(self) -> None: | CODE |
| LOW⚡ | tests/test_resource_urls.py | 71 | def test_builds_sync_classroom_url_for_teaching_materials(self) -> None: | CODE |
| LOW⚡ | tests/test_resource_urls.py | 76 | def test_prepare_lesson_root_adds_prepare_path(self) -> None: | CODE |
| LOW⚡ | tests/test_resource_urls.py | 83 | def test_collects_all_leaf_urls_under_subject(self) -> None: | CODE |
| LOW⚡ | tests/test_resource_urls.py | 88 | def test_single_edition_only_collects_its_own_books(self) -> None: | CODE |
| LOW⚡ | tests/test_resource_urls.py | 95 | def test_empty_category_collects_nothing(self) -> None: | CODE |
| LOW⚡ | tests/test_download.py | 67 | def test_reports_server_errors_unrelated_to_the_token(self) -> None: | CODE |
| LOW⚡ | tests/test_download.py | 70 | def test_appends_a_token_hint_to_authentication_failures(self) -> None: | CODE |
| LOW⚡ | tests/test_download.py | 79 | def test_asks_for_token_when_anonymous_request_requires_authentication(self) -> None: | CODE |
| LOW⚡ | tests/test_download.py | 86 | def test_keeps_token_out_of_private_request_url(self) -> None: | CODE |
| LOW | tests/test_download.py | 106 | def test_signs_private_download_when_mac_key_is_present(self) -> None: | CODE |
| LOW | tests/test_download.py | 121 | def test_retries_private_download_on_the_next_mirror(self) -> None: | CODE |
| LOW | tests/test_download.py | 177 | def test_does_not_retry_authentication_failures_or_public_urls(self) -> None: | CODE |
| LOW | tests/test_download.py | 191 | def test_explains_private_storage_authentication_errors(self) -> None: | CODE |
| LOW | tests/test_download.py | 207 | def test_redacts_token_from_network_exceptions(self) -> None: | CODE |
| LOW⚡ | tests/test_resource_check.py | 48 | def test_yields_paths_and_data_of_all_leaf_nodes(self) -> None: | CODE |
| LOW⚡ | tests/test_resource_check.py | 57 | def test_yields_only_leaves_under_given_parent_path(self) -> None: | CODE |
| LOW⚡ | tests/test_resource_check.py | 62 | def test_treats_empty_children_as_leaf(self) -> None: # 与 count_resource_items 的口径一致:children 为空字典的节点视为末级资源 | CODE |
| LOW⚡ | tests/test_resource_check.py | 69 | def test_locates_node_by_colon_path(self) -> None: | CODE |
| LOW⚡ | tests/test_resource_check.py | 74 | def test_locates_category_and_root_nodes(self) -> None: | CODE |
| LOW⚡ | tests/test_resource_check.py | 78 | def test_returns_none_for_unknown_path(self) -> None: | CODE |
| LOW⚡ | tests/test_resource_check.py | 86 | def test_returns_unchecked_when_no_leaf_is_checked(self) -> None: | CODE |
| LOW⚡ | tests/test_resource_check.py | 90 | def test_returns_partial_when_some_leaves_are_checked(self) -> None: | CODE |
| LOW⚡ | tests/test_resource_check.py | 95 | def test_returns_checked_when_all_leaves_are_checked(self) -> None: | CODE |
| LOW⚡ | tests/test_resource_check.py | 100 | def test_ignores_checked_items_outside_the_category(self) -> None: | CODE |
| LOW⚡ | tests/test_resource_check.py | 109 | def test_checks_when_not_all_leaves_are_checked(self) -> None: | CODE |
| LOW⚡ | tests/test_resource_check.py | 113 | def test_unchecks_when_all_leaves_are_already_checked(self) -> None: | CODE |
| LOW⚡ | tests/test_resource_check.py | 118 | def test_draws_all_states_on_transparent_canvas(self) -> None: | CODE |
| LOW | tests/test_resource_check.py | 131 | def test_edges_are_antialiased_in_both_themes_at_common_scales(self) -> None: | CODE |
| LOW | tests/test_resource_check.py | 142 | def test_checkmark_has_smooth_color_transitions(self) -> None: | CODE |
| LOW⚡ | tests/test_resource_search.py | 53 | def test_searches_across_the_full_category_path(self) -> None: | CODE |
| LOW⚡ | tests/test_resource_search.py | 59 | def test_category_search_keeps_all_matching_resources(self) -> None: | CODE |
| LOW⚡ | tests/test_resource_search.py | 64 | def test_empty_query_returns_all_resources(self) -> None: | CODE |
| LOW⚡ | tests/test_resource_search.py | 68 | def test_unknown_keyword_returns_an_empty_tree(self) -> None: | CODE |
| LOW⚡ | tests/test_resource_search.py | 73 | def test_centers_portrait_cover_on_fixed_canvas(self) -> None: | CODE |
| LOW⚡ | tests/test_auth.py | 17 | def test_reads_json_credentials(self) -> None: | CODE |
| LOW⚡ | tests/test_auth.py | 21 | def test_reads_pretty_printed_json(self) -> None: | CODE |
| LOW⚡ | tests/test_auth.py | 25 | def test_reads_json_string_wrapper(self) -> None: | CODE |
| LOW⚡ | tests/test_auth.py | 29 | def test_accepts_numeric_string_diff(self) -> None: | CODE |
| LOW⚡ | tests/test_auth.py | 33 | def test_rejects_raw_access_token(self) -> None: | CODE |
| LOW⚡ | tests/test_auth.py | 37 | def test_empty_input_clears_credentials(self) -> None: | CODE |
| LOW⚡ | tests/test_auth.py | 40 | def test_rejects_json_missing_fields(self) -> None: | CODE |
| LOW⚡ | tests/test_auth.py | 46 | def test_rejects_empty_mac_key(self) -> None: | CODE |
| LOW⚡ | tests/test_auth.py | 50 | def test_rejects_nested_local_storage_blob(self) -> None: | CODE |
| LOW⚡ | tests/test_auth.py | 55 | def test_format_token_json_backfills_old_fields(self) -> None: | CODE |
| LOW⚡ | tests/test_auth.py | 63 | def test_falls_back_to_placeholder_without_mac_key(self) -> None: | CODE |
| LOW⚡ | tests/test_auth.py | 73 | def test_matches_official_uc_sdk_signature(self) -> None: | CODE |
| LOW⚡ | tests/test_parse_collection.py | 13 | def test_callback_annotations_can_be_evaluated(self) -> None: | CODE |
| LOW⚡ | tests/test_parse_collection.py | 18 | def test_flattens_multiple_resources_per_url(self) -> None: | CODE |
| LOW⚡ | tests/test_parse_collection.py | 27 | def test_deduplicates_by_resource_url_across_urls(self) -> None: | CODE |
| LOW⚡ | tests/test_parse_collection.py | 36 | def test_collects_urls_that_fail_to_parse(self) -> None: | CODE |
| LOW⚡ | tests/test_parse_collection.py | 45 | def test_reports_progress_for_each_url(self) -> None: | CODE |
| LOW | tests/test_token_script.py | 11 | def test_selects_token_suffix_not_first_auth_key(self) -> None: | CODE |
| LOW | tests/test_token_script.py | 18 | def test_readme_script_uses_the_same_token_key_rule(self) -> None: | CODE |
| LOW⚡ | tests/test_network.py | 49 | def test_defaults_cover_details_mapping_chapters_and_audio(self): | CODE |
| LOW⚡ | tests/test_network.py | 58 | def test_explicit_timeout_is_preserved(self): | CODE |
| LOW⚡ | tests/test_network.py | 62 | def test_timeout_does_not_block_remaining_urls_or_completion_callback(self): | CODE |
| LOW | tests/test_audio_parse.py | 95 | def test_textbook_without_audio_returns_only_pdf(self) -> None: | CODE |
| LOW | tests/test_audio_parse.py | 151 | def test_audio_playback_ignores_source_order_and_falls_back_to_clip(self) -> None: | CODE |
| 69 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | src/tchmaterial_parser/config.py | 69 | except Exception as e: | CODE |
| LOW | src/tchmaterial_parser/config.py | 91 | except Exception as e: | CODE |
| LOW | src/tchmaterial_parser/api.py | 303 | except Exception as e: | CODE |
| LOW | src/tchmaterial_parser/api.py | 344 | except Exception: # 音频资源不是必需的,获取失败时直接跳过 | CODE |
| LOW | src/tchmaterial_parser/api.py | 349 | except Exception as e: | CODE |
| LOW | src/tchmaterial_parser/platform_utils.py | 25 | except Exception as e: | CODE |
| LOW | src/tchmaterial_parser/images.py | 34 | except Exception: | CODE |
| LOW | src/tchmaterial_parser/images.py | 91 | except Exception as e: | CODE |
| LOW | src/tchmaterial_parser/app.py | 41 | except Exception: # Windows 8 或更老 | CODE |
| LOW | src/tchmaterial_parser/app.py | 51 | except Exception as e: | CODE |
| LOW | src/tchmaterial_parser/app.py | 67 | except Exception: | CODE |
| LOW⚡ | src/tchmaterial_parser/app.py | 121 | except Exception: # 进程可能已经结束 | CODE |
| LOW⚡ | src/tchmaterial_parser/app.py | 126 | except Exception: | CODE |
| LOW⚡ | src/tchmaterial_parser/app.py | 128 | except Exception: # 获取子进程失败,直接退出当前进程 | CODE |
| LOW⚡ | src/tchmaterial_parser/app.py | 131 | except Exception: | CODE |
| LOW | src/tchmaterial_parser/bookmarks.py | 47 | except Exception as e: | CODE |
| LOW | src/tchmaterial_parser/ui/theme.py | 55 | except Exception: | CODE |
| LOW | src/tchmaterial_parser/ui/theme.py | 64 | except Exception: | CODE |
| LOW | src/tchmaterial_parser/ui/theme.py | 103 | except Exception as e: | CODE |
| LOW | src/tchmaterial_parser/ui/theme.py | 121 | except Exception as e: | CODE |
| LOW | src/tchmaterial_parser/ui/theme.py | 175 | except Exception as e: | CODE |
| LOW | src/tchmaterial_parser/ui/token_window.py | 178 | except Exception as error: | CODE |
| MEDIUM | src/tchmaterial_parser/ui/token_window.py | 174 | def open_login_page() -> None: | CODE |
| LOW | src/tchmaterial_parser/ui/runtime.py | 29 | except Exception: | CODE |
| LOW | src/tchmaterial_parser/ui/widgets.py | 41 | except Exception: # 再尝试使用鼠标指针位置(如果有) | CODE |
| LOW | src/tchmaterial_parser/ui/download_panel.py | 334 | except Exception as error: | CODE |
| LOW | src/tchmaterial_parser/ui/download_panel.py | 394 | except Exception as e: | CODE |
| LOW | src/tchmaterial_parser/ui/download_panel.py | 553 | except Exception as error: | CODE |
| LOW | src/tchmaterial_parser/ui/download_panel.py | 629 | except Exception as e: | CODE |
| LOW | src/tchmaterial_parser/ui/download_panel.py | 646 | except Exception as error: | CODE |
| LOW | src/tchmaterial_parser/ui/about_window.py | 24 | except Exception as e: | CODE |
| LOW | src/tchmaterial_parser/ui/resource_tree.py | 239 | except Exception as e: | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | tests/test_download_manager.py | 324 | except OSError: | CODE |
| HIGH | src/tchmaterial_parser/api.py | 344 | except Exception: # 音频资源不是必需的,获取失败时直接跳过 | CODE |
| HIGH | src/tchmaterial_parser/images.py | 34 | except Exception: | CODE |
| HIGH | src/tchmaterial_parser/app.py | 126 | except Exception: | CODE |
| HIGH | src/tchmaterial_parser/app.py | 121 | except Exception: # 进程可能已经结束 | CODE |
| HIGH | src/tchmaterial_parser/app.py | 131 | except Exception: | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/test_resource_check.py | 131 | CODE | |
| LOW | src/tchmaterial_parser/catalog.py | 17 | CODE | |
| LOW | src/tchmaterial_parser/catalog.py | 51 | CODE | |
| LOW | src/tchmaterial_parser/catalog.py | 87 | CODE | |
| LOW | src/tchmaterial_parser/config.py | 51 | CODE | |
| LOW | src/tchmaterial_parser/api.py | 87 | CODE | |
| LOW | src/tchmaterial_parser/api.py | 183 | CODE | |
| LOW | src/tchmaterial_parser/images.py | 11 | CODE | |
| LOW | src/tchmaterial_parser/images.py | 51 | CODE | |
| LOW | src/tchmaterial_parser/ui/theme.py | 80 | CODE | |
| LOW | src/tchmaterial_parser/ui/download_manager.py | 53 | CODE | |
| LOW | src/tchmaterial_parser/ui/download_panel.py | 75 | CODE | |
| LOW | src/tchmaterial_parser/ui/download_panel.py | 412 | CODE | |
| LOW | src/tchmaterial_parser/ui/download_panel.py | 566 | CODE | |
| LOW | src/tchmaterial_parser/ui/download_panel.py | 436 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | src/tchmaterial_parser/app.py | 163 | def update_theme_button() -> None: # 更新按钮文字与图标,使其表示点击后将切换到的主题 | CODE |
| LOW | src/tchmaterial_parser/ui/resource_tree.py | 301 | def update_checked_count() -> None: # 更新已勾选教材数量提示 | CODE |
| LOW | src/tchmaterial_parser/ui/resource_tree.py | 318 | def set_items_checked(leafs: list[tuple[str, dict]], checked: bool) -> None: # 批量更新末级资源勾选状态,级联刷新图标并同步 URL 输入框 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | src/tchmaterial_parser/auth.py | 1 | # -*- coding: utf-8 -*- | COMMENT |
| LOW | src/tchmaterial_parser/ui/__init__.py | 1 | # -*- coding: utf-8 -*- | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | src/tchmaterial_parser/images.py | 9 | CODE |