Command line interface to the freedesktop.org trashcan.
This report summarizes scanner evidence for andreafrancia/trash-cli, a Python project with 4,601 GitHub stars. SynthScan examined 19,900 lines of code across 568 source files, recording 825 pattern matches distributed across 6 syntactic categories. The legacy adjusted pattern signal is 47.4 (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? 462 finding(s).
Are imports declared and package/API names verified? 359 finding(s).
Are wrappers, guards, and repeated structures necessary? 457 finding(s).
Which changes need focused human review? 825 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 825 distinct pattern matches across 6 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_empty/cmd/test_empty_cmd_fs_fake.py | 40 | def test_trash_empty_will_skip_unreadable_dir(self): | CODE |
| LOW | tests/test_empty/cmd/test_empty_cmd_fs_real.py | 42 | def test_trash_empty_will_skip_unreadable_dir(self): | CODE |
| LOW | …ty/cmd/test_empty_cmd_with_multiple_volumes_fs_real.py | 58 | def test_it_removes_trashinfo_from_specified_trash_dir(self): | CODE |
| LOW | …ty/cmd/test_empty_cmd_with_multiple_volumes_fs_fake.py | 57 | def test_it_removes_trashinfo_from_specified_trash_dir(self): | CODE |
| LOW | …mpty/components/test_empty_end_to_end_with_argument.py | 50 | def test_it_should_kept_files_with_invalid_deletion_date(self): | CODE |
| LOW | tests/test_empty/components/test_guard.py | 28 | def test_it_just_calls_the_emptier(self): | CODE |
| LOW | tests/test_empty/components/test_empty_end_to_end.py | 77 | def test_on_trash_date_not_parsable(self): | STRING |
| LOW⚡ | tests/test_empty/components/test_make_parser.py | 16 | def test_non_interactive_default_is_non_interactive(self): | CODE |
| LOW⚡ | tests/test_empty/components/test_make_parser.py | 22 | def test_interactive_default_is_interactive(self): | CODE |
| LOW⚡ | tests/test_empty/components/test_make_parser.py | 28 | def test_interactive_made_non_interactive(self): | CODE |
| LOW | …ts/test_empty/components/test_existing_file_remover.py | 9 | def test_remove_file_if_exists_fails_when_file_does_not_exists(self): | CODE |
| LOW | …pty/components/test_empty_end_to_end_with_trash_dir.py | 46 | def test_non_trash_info_is_not_deleted(self): | CODE |
| LOW | tests/test_empty/components/test_clock.py | 27 | def test_return_true_now_whe_fake_time_is_invalid(self): | CODE |
| LOW | …ools/test_make_scripts/test_list_of_created_scripts.py | 11 | def test_is_empty_on_start_up(self): | CODE |
| LOW | …ools/test_make_scripts/test_list_of_created_scripts.py | 14 | def test_collect_added_script(self): | CODE |
| LOW⚡ | …s/test_dev_tools/test_make_scripts/test_make_script.py | 28 | def test_should_set_executable_permission(self): | CODE |
| LOW⚡ | …s/test_dev_tools/test_make_scripts/test_make_script.py | 31 | def test_should_write_the_script(self): | CODE |
| LOW⚡ | …s/test_dev_tools/test_make_scripts/test_make_script.py | 35 | def test_the_script_should_call_the_right_function_from_the_right_module(self): | CODE |
| LOW | tests/test_dev_tools/cmds/test_bump_cmd.py | 39 | def test_when_clean_and_dry_run(self): | CODE |
| LOW | tests/test_dev_tools/cmds/test_set_dev_version_cmd.py | 41 | def test_ref_with_hyphens_is_sanitized(self, capsys): | CODE |
| LOW⚡ | …ts/test_dev_tools/components/test_version_from_date.py | 17 | def test_replaces_hyphens_with_dots(self): | CODE |
| LOW⚡ | …ts/test_dev_tools/components/test_version_from_date.py | 21 | def test_collapses_consecutive_separators_into_one_dot(self): | CODE |
| LOW⚡ | …ts/test_dev_tools/components/test_version_from_date.py | 26 | def test_sanitizes_hyphens_in_ref(self): | CODE |
| LOW | …test_fs/test_what_python_raise_on_non_existent_file.py | 11 | def test_reading_an_existing_file(self): | CODE |
| LOW | tests/test_list/cmd/test_version.py | 9 | def test_should_output_the_version(self, user): | CODE |
| LOW | tests/test_list/cmd/test_debug_volumes.py | 7 | def test_prints_physical_and_virtual_partitions_and_df_output(self, user): | CODE |
| LOW | tests/test_list/cmd/test_debug_volumes.py | 25 | def test_when_there_are_no_partitions(self, user): | CODE |
| LOW | tests/test_list/cmd/test_list_trash_dirs.py | 13 | def test_lists_the_home_trash_dir(self, user): | CODE |
| LOW | tests/test_list/cmd/test_list_trash_dirs.py | 18 | def test_lists_the_trash_dirs_of_a_volume(self, user): | CODE |
| LOW⚡ | tests/test_list/cmd/test_list_trash_dirs.py | 30 | def test_does_not_list_the_trash_dirs_that_does_not_exist(self, user): | CODE |
| LOW⚡ | tests/test_list/cmd/test_list_trash_dirs.py | 38 | def test_reports_when_the_parent_is_not_sticky(self, user): | CODE |
| LOW⚡ | tests/test_list/cmd/test_list_trash_dirs.py | 48 | def test_reports_when_the_parent_is_a_symlink_to_a_sticky_dir(self, user): | CODE |
| LOW | tests/test_list/cmd/test_list_trash_dirs.py | 59 | def test_lists_only_the_trash_dirs_specified_by_the_user(self, user): | CODE |
| LOW⚡ | tests/test_list/cmd/test_trash_list.py | 9 | def test_should_output_nothing_when_trashcan_is_empty(self, user): | CODE |
| LOW⚡ | tests/test_list/cmd/test_trash_list.py | 14 | def test_should_output_deletion_date_and_path(self, user): | CODE |
| LOW⚡ | tests/test_list/cmd/test_trash_list.py | 22 | def test_should_output_info_for_multiple_files(self, user): | CODE |
| LOW⚡ | tests/test_list/cmd/test_trash_list.py | 33 | def test_should_output_unknown_dates_with_question_marks(self, user): | CODE |
| LOW⚡ | tests/test_list/cmd/test_trash_list.py | 40 | def test_should_output_invalid_dates_using_question_marks(self, user): | CODE |
| LOW⚡ | tests/test_list/cmd/test_trash_list.py | 49 | def test_should_warn_about_empty_trashinfos(self, user): | CODE |
| LOW⚡ | tests/test_list/cmd/test_trash_list.py | 58 | def test_should_warn_about_unreadable_trashinfo(self, user): | CODE |
| LOW⚡ | tests/test_list/cmd/test_trash_list.py | 68 | def test_should_warn_about_unexistent_path_entry(self, user): | CODE |
| LOW⚡ | tests/test_list/cmd/test_with_a_top_trash_dir.py | 15 | def test_should_list_its_contents_if_parent_is_sticky(self, user): | CODE |
| LOW⚡ | tests/test_list/cmd/test_with_a_top_trash_dir.py | 23 | def test_and_should_warn_if_parent_is_not_sticky(self, user): | CODE |
| LOW⚡ | tests/test_list/cmd/test_with_a_top_trash_dir.py | 32 | def test_but_it_should_not_warn_when_the_parent_is_unsticky_but_there_is_no_trashdir( | CODE |
| LOW⚡ | tests/test_list/cmd/test_with_a_top_trash_dir.py | 41 | def test_should_ignore_trash_from_a_unsticky_topdir(self, user): | CODE |
| LOW⚡ | tests/test_list/cmd/test_with_a_top_trash_dir.py | 50 | def test_it_should_skip_a_symlink(self, user): | CODE |
| LOW | …st_list/cmd/test_trash_list_sanitizes_control_chars.py | 16 | def test_on_a_terminal_the_name_is_shell_escaped(trash_list_user): | CODE |
| LOW | …st_list/cmd/test_trash_list_sanitizes_control_chars.py | 29 | def test_when_piped_the_name_is_printed_raw(trash_list_user): | CODE |
| LOW | …s/test_list/components/test_deletion_date_extractor.py | 11 | def test_extract_attribute_default(self): | CODE |
| LOW | …s/test_list/components/test_deletion_date_extractor.py | 15 | def test_extract_attribute_value(self): | CODE |
| LOW | tests/test_list/components/test_trash_list_parser.py | 18 | def test_trash_dir_not_specified(self): | CODE |
| LOW | tests/test_rm/cmd/test_trash_rm.py | 33 | def test_without_pattern_argument(self): | CODE |
| LOW | tests/test_rm/components/test_file_remover.py | 14 | def test_remove_file_fails_when_file_does_not_exists(self): | CODE |
| LOW | tests/test_rm/components/test_filter.py | 20 | def test_example_with_star_dot_o(self): | CODE |
| LOW | …s/test_put/cmd/test_put_undeletable_file_is_refused.py | 17 | def test_a_file_that_cannot_be_deleted_is_not_trashed_or_copied(self): | CODE |
| LOW⚡ | tests/test_put/cmd/test_put_option_shaped_filename.py | 15 | def test_it_refuses_an_existing_file_that_looks_like_an_option(self): | CODE |
| LOW⚡ | tests/test_put/cmd/test_put_option_shaped_filename.py | 23 | def test_the_double_dash_separator_still_lets_you_trash_such_a_file(self): | CODE |
| LOW⚡ | tests/test_put/cmd/test_put_option_shaped_filename.py | 32 | def test_a_real_option_is_unaffected_when_no_such_file_exists(self): | CODE |
| LOW⚡ | tests/test_put/cmd/test_put.py | 31 | def test_when_needs_a_different_suffix(self): | CODE |
| LOW⚡ | tests/test_put/cmd/test_put.py | 39 | def test_when_needs_a_random_suffix(self): | CODE |
| 390 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/test_empty/components/test_make_parser.py | 2 | CODE | |
| LOW | tests/test_dev_tools/support/run_set_dev_version.py | 6 | CODE | |
| LOW | tests/test_list/cmd/support/trash_list_user.py | 13 | CODE | |
| LOW | tests/test_put/cmd/test_put.py | 1 | CODE | |
| LOW | tests/test_put/cmd/test_put.py | 2 | CODE | |
| LOW | tests/test_put/cmd/test_put.py | 13 | CODE | |
| LOW | tests/test_put/cmd/e2e/test_on_symbolic_links.py | 6 | CODE | |
| LOW | tests/test_put/cmd/e2e/test_on_symbolic_links.py | 9 | CODE | |
| LOW | tests/test_put/cmd/e2e/run_trash_put/put_result.py | 3 | CODE | |
| LOW | …sts/test_put/cmd/e2e/run_trash_put/directory_layout.py | 1 | CODE | |
| LOW | …sts/test_put/cmd/e2e/run_trash_put/directory_layout.py | 3 | CODE | |
| LOW | tests/test_put/cmd/e2e/run_trash_put/__init__.py | 1 | CODE | |
| LOW | tests/test_put/cmd/e2e/run_trash_put/__init__.py | 2 | CODE | |
| LOW | tests/test_put/cmd/e2e/run_trash_put/__init__.py | 5 | CODE | |
| LOW | tests/test_put/cmd/e2e/run_trash_put/__init__.py | 6 | CODE | |
| LOW | tests/test_put/cmd/e2e/run_trash_put/__init__.py | 8 | CODE | |
| LOW | tests/test_put/cmd/e2e/run_trash_put/__init__.py | 9 | CODE | |
| LOW | tests/test_put/components/test_move_file.py | 3 | CODE | |
| LOW | …ts/test_put/components/test_restore_fs_like_real_fs.py | 6 | CODE | |
| LOW | tests/test_put/support/result.py | 1 | CODE | |
| LOW | tests/test_put/support/result.py | 2 | CODE | |
| LOW | tests/test_put/support/result.py | 4 | CODE | |
| LOW | tests/test_put/support/result.py | 5 | CODE | |
| LOW | tests/test_put/support/logs.py | 5 | CODE | |
| LOW | tests/test_put/support/recording_backend.py | 1 | CODE | |
| LOW | tests/test_put/support/recording_backend.py | 3 | CODE | |
| LOW | tests/test_put/support/recording_backend.py | 7 | CODE | |
| LOW | tests/test_put/support/recording_backend.py | 8 | CODE | |
| LOW | …i_lib/test_invalid_utf8_path/test_format_trash_info.py | 6 | CODE | |
| LOW | tests/support/make_scripts.py | 3 | CODE | |
| LOW | tests/support/py2mock.py | 5 | CODE | |
| LOW | tests/support/py2mock.py | 5 | CODE | |
| LOW | tests/support/py2mock.py | 5 | CODE | |
| LOW | tests/support/py2mock.py | 5 | CODE | |
| LOW | tests/support/py2mock.py | 7 | CODE | |
| LOW | tests/support/py2mock.py | 7 | CODE | |
| LOW | tests/support/py2mock.py | 7 | CODE | |
| LOW | tests/support/py2mock.py | 7 | CODE | |
| LOW | tests/support/cmd/capture_exit_code2.py | 1 | CODE | |
| LOW | tests/support/cmd/capture_exit_code2.py | 1 | CODE | |
| LOW | tests/support/tools/version_from_date.py | 1 | CODE | |
| LOW | tests/support/tools/set_dev_version.py | 1 | CODE | |
| LOW | tests/support/tools/bump_main.py | 1 | CODE | |
| LOW | tests/support/put/fake_random.py | 1 | CODE | |
| LOW | tests/support/put/fake_fs/inode.py | 3 | CODE | |
| LOW | tests/support/put/fake_fs/directory.py | 2 | CODE | |
| LOW | tests/support/put/fake_fs/directory.py | 3 | CODE | |
| LOW | tests/support/put/fake_fs/fake_fs.py | 3 | CODE | |
| LOW | tests/support/put/fake_fs/fake_fs.py | 8 | CODE | |
| LOW | tests/support/put/fake_fs/fake_fs.py | 10 | CODE | |
| LOW | tests/support/fakes/fake_is_mount.py | 2 | CODE | |
| LOW | tests/support/fakes/fake_volume_of.py | 1 | CODE | |
| LOW | tests/support/fakes/fake_disk_partitions_fs.py | 1 | CODE | |
| LOW | tests/support/fakes/fake_disk_partitions_fs.py | 1 | CODE | |
| LOW | tests/support/fakes/fake_trash_dir.py | 4 | CODE | |
| LOW | tests/support/fakes/fake_trash_dir.py | 4 | CODE | |
| LOW | tests/support/fakes/fake_trash_dir.py | 7 | CODE | |
| LOW | tests/support/trash_dirs/given_trash.py | 3 | CODE | |
| LOW | tests/support/trash_dirs/given_trash.py | 5 | CODE | |
| LOW | tests/support/dirs/my_path.py | 3 | CODE | |
| 299 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | trashcli/trash_dirs_scanner.py | 86 | CODE | |
| LOW | trashcli/put/describer.py | 8 | CODE | |
| LOW | trashcli/put/janitor_tools/info_file_persister.py | 77 | CODE | |
| LOW | trashcli/list/list_trash_action.py | 98 | CODE | |
| LOW | trashcli/list/minor_actions/list_trash_dirs.py | 26 | CODE | |
| LOW | trashcli/restore/trashed_files.py | 29 | CODE | |
| LOW | trashcli/restore/trashed_files.py | 46 | CODE | |
| LOW | trashcli/restore/real_output.py | 30 | CODE | |
| LOW | trashcli/rm/rm_cmd.py | 39 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | trashcli/restore/info_files.py | 23 | except OSError: # when directory does not exist | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/support/capture_error.py | 4 | except Exception as e: | CODE |
| MEDIUM | tests/support/capture_error.py | 1 | def capture_error(callable): | CODE |
| LOW | trashcli/lib/sanitize.py | 51 | except Exception: | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/test_put/cmd/e2e/run_trash_put/__init__.py | 55 | CODE | |
| LOW | tests/support/put/fake_fs/failing_fake_fs.py | 39 | CODE | |
| LOW | trashcli/lib/printable.py | 9 | CODE |