Install and Run Python Applications in Isolated Environments
This report summarizes scanner evidence for pypa/pipx, a Python project with 12,979 GitHub stars. SynthScan examined 35,577 lines of code across 166 source files, recording 957 pattern matches distributed across 10 syntactic categories. The legacy adjusted pattern signal is 26.6 (Elevated 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? 723 finding(s).
Are imports declared and package/API names verified? 169 finding(s).
Are wrappers, guards, and repeated structures necessary? 758 finding(s).
Which changes need focused human review? 957 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 957 distinct pattern matches across 10 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_requires_python.py | 42 | def test_rejected_constraint_reads_the_backend_complaint(output: str, expected: str | None) -> None: | CODE |
| LOW | tests/test_requires_python.py | 58 | def test_unsatisfied_constraint_reports_only_a_mismatch( | CODE |
| LOW⚡ | tests/test_requires_python.py | 83 | def test_interpreter_for_takes_the_newest_installed_match(mocker: MockerFixture) -> None: | CODE |
| LOW⚡ | tests/test_requires_python.py | 89 | def test_interpreter_for_skips_a_version_the_system_lacks(mocker: MockerFixture) -> None: | CODE |
| LOW⚡ | tests/test_requires_python.py | 95 | def test_interpreter_for_accepts_a_patch_above_a_lower_bound(mocker: MockerFixture) -> None: | CODE |
| LOW⚡ | tests/test_requires_python.py | 101 | def test_interpreter_for_rejects_a_patch_above_an_upper_bound(mocker: MockerFixture) -> None: | CODE |
| LOW⚡ | tests/test_requires_python.py | 107 | def test_interpreter_for_rejects_every_patch_below_a_lower_bound(mocker: MockerFixture) -> None: | CODE |
| LOW⚡ | tests/test_requires_python.py | 114 | def test_interpreter_for_fetches_when_the_caller_allows_it(mocker: MockerFixture) -> None: | CODE |
| LOW⚡ | tests/test_requires_python.py | 120 | def test_interpreter_for_reports_a_system_without_a_match(mocker: MockerFixture) -> None: | CODE |
| LOW⚡ | tests/test_requires_python.py | 127 | def test_interpreter_for_reports_a_constraint_no_release_meets() -> None: | CODE |
| LOW | tests/test_requires_python.py | 144 | def project_excluding_this_python(tmp_path: Path) -> Path: | CODE |
| LOW | tests/test_requires_python.py | 164 | def test_install_moves_to_a_python_the_package_supports( | CODE |
| LOW | tests/test_transaction.py | 11 | def test_preserve_venv_keeps_the_backup_out_of_the_venv_namespace() -> None: | CODE |
| LOW | tests/test_transaction.py | 24 | def test_preserve_venv_restores_the_backup_on_failure() -> None: | CODE |
| LOW⚡ | tests/test_ensurepath.py | 55 | def test_ensure_path_dry_run_does_not_append(mock_userpath: FakeUserpath, capsys: pytest.CaptureFixture[str]) -> None: | CODE |
| LOW⚡ | tests/test_ensurepath.py | 65 | def test_ensure_path_dry_run_reports_prepend(mock_userpath: FakeUserpath, capsys: pytest.CaptureFixture[str]) -> None: | CODE |
| LOW⚡ | tests/test_ensurepath.py | 73 | def test_ensure_path_non_dry_run_still_appends(mock_userpath: FakeUserpath, capsys: pytest.CaptureFixture[str]) -> None: | CODE |
| LOW⚡ | tests/test_ensurepath.py | 81 | def test_ensure_pipx_paths_dry_run_footer(mock_userpath: FakeUserpath, capsys: pytest.CaptureFixture[str]) -> None: | CODE |
| LOW | tests/test_ensurepath.py | 110 | def test_ensure_pipx_paths_global_updates_system_profile( | CODE |
| LOW | tests/test_ensurepath.py | 126 | def test_ensure_pipx_paths_global_skips_userpath(mocker: MockerFixture, tmp_path: Path) -> None: | CODE |
| LOW | tests/test_ensurepath.py | 137 | def test_ensure_pipx_paths_global_dry_run_does_not_write( | CODE |
| LOW | tests/test_ensurepath.py | 150 | def test_ensure_pipx_paths_global_configuration_is_world_readable(mocker: MockerFixture, tmp_path: Path) -> None: | CODE |
| LOW | tests/test_ensurepath.py | 163 | def test_ensure_pipx_paths_global_reports_existing_configuration( | CODE |
| LOW | tests/test_ensurepath.py | 179 | def test_ensurepath_cli_global_writes_system_configuration(mocker: MockerFixture, tmp_path: Path) -> None: | CODE |
| LOW | tests/test_inject.py | 63 | def test_inject_json_reports_locked_environment( | CODE |
| LOW | tests/test_inject.py | 98 | def test_inject_json_reports_already_installed( | CODE |
| LOW | tests/test_inject.py | 130 | def test_inject_json_reports_partial_failure( | CODE |
| LOW | tests/test_inject.py | 174 | def test_inject_json_reports_no_packages( | CODE |
| LOW | tests/test_inject.py | 221 | def test_inject_rejects_pylock( | CODE |
| LOW | tests/test_inject.py | 250 | def test_inject_single_package( | CODE |
| LOW | tests/test_inject.py | 281 | def test_inject_main_package_extra( | CODE |
| LOW | tests/test_inject.py | 312 | def test_inject_simple_global() -> None: | CODE |
| LOW | tests/test_inject.py | 319 | def test_inject_simple_legacy_venv( | CODE |
| LOW | tests/test_inject.py | 353 | def test_inject_include_resources_from_dependency( | CODE |
| LOW | tests/test_inject.py | 373 | def test_inject_main_package_preserves_included_dependency( | CODE |
| LOW | tests/test_inject.py | 386 | def test_inject_force_replaces_included_dependency_resources( | CODE |
| LOW | tests/test_inject.py | 406 | def test_inject_include_resources_from_missing_dependency_rolls_back( | CODE |
| LOW | tests/test_inject.py | 434 | def test_inject_with_req_file( | CODE |
| LOW | tests/test_inject.py | 482 | def test_force_inject_reinstalls_without_storing_force(caplog: pytest.LogCaptureFixture) -> None: | STRING |
| LOW | tests/test_inject.py | 503 | def test_inject_inherits_cooldown( | STRING |
| LOW | tests/test_result_contract.py | 43 | def test_contract_success_envelope(capsys: pytest.CaptureFixture[str]) -> None: | CODE |
| LOW | tests/test_result_contract.py | 56 | def test_contract_error_envelope_names_the_failure( | CODE |
| LOW | tests/test_result_contract.py | 68 | def test_contract_dispatch_error_uses_the_envelope( | CODE |
| LOW | tests/conftest.py | 86 | def make_project_with_dependency(root: Path, tmp_path: Path) -> Callable[[str], Path]: | STRING |
| LOW | tests/conftest.py | 128 | def copied_dependency_resource( | STRING |
| LOW | tests/test_list.py | 52 | def test_list_allows_read_only_venv_lock(tmp_path: Path, mocker: MockerFixture) -> None: | CODE |
| LOW | tests/test_list.py | 143 | def test_list_returns_problem_for_corrupt_metadata(metadata: str) -> None: | CODE |
| LOW | tests/test_list.py | 152 | def test_list_suffix_legacy_venv(capsys: pytest.CaptureFixture[str], metadata_version: str) -> None: | CODE |
| LOW | tests/test_list.py | 234 | def test_list_json_rejects_human_filter( | CODE |
| LOW | tests/test_list.py | 246 | def test_list_selected_package_text(capsys: pytest.CaptureFixture[str]) -> None: | CODE |
| LOW | tests/test_list.py | 258 | def test_list_selected_packages_json(capsys: pytest.CaptureFixture[str]) -> None: | CODE |
| LOW | tests/test_list.py | 278 | def test_list_selected_package_short( | CODE |
| LOW | tests/test_list.py | 292 | def test_list_selected_package_with_suffix(capsys: pytest.CaptureFixture[str]) -> None: | CODE |
| LOW | tests/test_list.py | 302 | def test_list_selected_package_pinned(capsys: pytest.CaptureFixture[str]) -> None: | CODE |
| LOW | tests/test_list.py | 314 | def test_list_rejects_missing_selected_package( | CODE |
| LOW | tests/test_list.py | 322 | def test_list_injected_apps_without_symlinks( | CODE |
| LOW | tests/test_list.py | 337 | def test_list_waits_for_install(tmp_path: Path) -> None: | CODE |
| LOW | tests/test_list.py | 357 | def test_install_does_not_wait_for_other_environment(tmp_path: Path) -> None: | CODE |
| LOW | tests/test_list.py | 382 | def test_list_standalone_interpreter(monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]) -> None: | CODE |
| LOW | tests/test_list.py | 408 | def test_list_does_not_trigger_maintenance() -> None: | CODE |
| 629 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | get-pipx.py | 2 | CODE | |
| LOW | hatch_build.py | 1 | CODE | |
| LOW | tests/test_requires_python.py | 1 | CODE | |
| LOW | tests/test_transaction.py | 1 | CODE | |
| LOW | tests/package_info.py | 1 | CODE | |
| LOW | tests/test_ensurepath.py | 1 | CODE | |
| LOW | tests/test_inject.py | 1 | CODE | |
| LOW | tests/test_result_contract.py | 1 | CODE | |
| LOW | tests/conftest.py | 1 | CODE | |
| LOW | tests/test_list.py | 1 | CODE | |
| LOW | tests/test_uninstall.py | 1 | CODE | |
| LOW | tests/test_max_logs.py | 3 | CODE | |
| LOW | tests/test_common.py | 1 | CODE | |
| LOW | tests/test_animate.py | 1 | CODE | |
| LOW | tests/test_uninject.py | 1 | CODE | |
| LOW | tests/test_venv_inspect.py | 1 | CODE | |
| LOW | tests/test_pin.py | 1 | CODE | |
| LOW | tests/test_unpin.py | 1 | CODE | |
| LOW | tests/test_install_all.py | 1 | CODE | |
| LOW | tests/test_backends_install.py | 1 | CODE | |
| LOW | tests/test_script.py | 1 | CODE | |
| LOW | tests/test_run.py | 1 | CODE | |
| LOW | tests/test_expose.py | 1 | CODE | |
| LOW | tests/test_upgrade.py | 1 | CODE | |
| LOW | tests/test_imports.py | 1 | CODE | |
| LOW | tests/test_uninstall_all.py | 1 | CODE | |
| LOW | tests/test_reinstall.py | 1 | CODE | |
| LOW | tests/test_venv.py | 1 | CODE | |
| LOW | tests/test_completions_expose.py | 1 | CODE | |
| LOW | tests/test_shared_libs.py | 1 | CODE | |
| LOW | tests/test_execute.py | 1 | CODE | |
| LOW | tests/test_manifest.py | 1 | CODE | |
| LOW | tests/test_util.py | 1 | CODE | |
| LOW | tests/test_upgrade_shared.py | 1 | CODE | |
| LOW | tests/test_pth_encoding.py | 1 | CODE | |
| LOW | tests/test_outdated.py | 1 | CODE | |
| LOW | tests/test_standalone_interpreter.py | 1 | CODE | |
| LOW | tests/test_pipx_metadata_file.py | 1 | CODE | |
| LOW | tests/test_subprocess_env.py | 1 | CODE | |
| LOW | tests/test_upgrade_all.py | 1 | CODE | |
| LOW | tests/test_docs_urls.py | 1 | CODE | |
| LOW | tests/test_paths.py | 1 | CODE | |
| LOW | tests/test_backends.py | 1 | CODE | |
| LOW | tests/test_health.py | 1 | CODE | |
| LOW | tests/test_self_managed.py | 1 | CODE | |
| LOW | tests/test_completions.py | 1 | CODE | |
| LOW | tests/test_runpip.py | 1 | CODE | |
| LOW | tests/test_interpreter.py | 1 | CODE | |
| LOW | tests/test_reset.py | 1 | CODE | |
| LOW | tests/test_package_specifier.py | 1 | CODE | |
| LOW | tests/test_run_uv.py | 1 | CODE | |
| LOW | tests/test_reinstall_all.py | 1 | CODE | |
| LOW | tests/helpers.py | 1 | CODE | |
| LOW | tests/test_main.py | 1 | CODE | |
| LOW | tests/test_install.py | 1 | CODE | |
| LOW | tests/test_cache.py | 1 | CODE | |
| LOW | tests/test_environment.py | 1 | CODE | |
| LOW | tests/test_install_all_packages.py | 16 | CODE | |
| LOW | tests/test_emojis.py | 1 | CODE | |
| LOW | docs/conf.py | 3 | CODE | |
| 105 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | hatch_build.py | 27 | __all__ = [ | CODE |
| LOW | src/pipx/animate.py | 147 | __all__ = [ | CODE |
| LOW⚡ | src/pipx/shared_libs.py | 31 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/pipx/shared_libs.py | 236 | __all__ = [ | CODE |
| LOW | src/pipx/paths.py | 175 | __all__ = [ | CODE |
| LOW | src/pipx/util.py | 596 | __all__ = [ | STRING |
| LOW | src/pipx/package_specifier.py | 26 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/pipx/package_specifier.py | 330 | __all__ = [ | STRING |
| LOW | src/pipx/venv.py | 833 | __all__ = [ | STRING |
| LOW | src/pipx/self_install.py | 72 | __all__ = [ | CODE |
| LOW | src/pipx/pipx_metadata_file.py | 397 | __all__ = [ | STRING |
| LOW | src/pipx/emojis.py | 39 | __all__ = [ | CODE |
| LOW | src/pipx/result.py | 123 | __all__ = [ | CODE |
| LOW | src/pipx/interpreter.py | 19 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/pipx/interpreter.py | 231 | __all__ = [ | CODE |
| LOW | src/pipx/requires_python.py | 124 | __all__ = [ | CODE |
| LOW | src/pipx/standalone_python.py | 384 | __all__ = [ | CODE |
| LOW | src/pipx/main.py | 2112 | __all__ = [ | CODE |
| LOW | src/pipx/script.py | 216 | __all__ = [ | CODE |
| LOW | src/pipx/script.py | 256 | __all__ = [ | STRING |
| LOW | src/pipx/venv_inspect.py | 26 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/pipx/venv_inspect.py | 570 | __all__ = [ | CODE |
| LOW | src/pipx/backends/_base.py | 160 | __all__ = [ | CODE |
| LOW | src/pipx/backends/__init__.py | 70 | __all__ = [ | CODE |
| LOW | src/pipx/backends/uv.py | 324 | __all__ = [ | STRING |
| LOW | src/pipx/backends/pip.py | 181 | __all__ = [ | CODE |
| LOW | src/pipx/commands/pin.py | 120 | def _update_pin_info(venv: Venv, package_name: str, *, is_main_package: bool, pinned: bool) -> None: | CODE |
| LOW | src/pipx/commands/pin.py | 180 | __all__ = [ | CODE |
| LOW | src/pipx/commands/run.py | 630 | __all__ = [ | CODE |
| LOW | src/pipx/commands/list_packages.py | 20 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/pipx/commands/list_packages.py | 180 | __all__ = [ | CODE |
| LOW | src/pipx/commands/manifest.py | 473 | __all__ = [ | CODE |
| LOW | src/pipx/commands/health.py | 188 | __all__ = [ | CODE |
| LOW | src/pipx/commands/transaction.py | 44 | __all__ = [ | CODE |
| LOW | src/pipx/commands/execute.py | 65 | __all__ = [ | CODE |
| LOW | src/pipx/commands/reset.py | 127 | __all__ = [ | CODE |
| LOW | src/pipx/commands/run_uv.py | 181 | __all__ = [ | CODE |
| LOW | src/pipx/commands/cache.py | 44 | __all__ = [ | CODE |
| LOW | src/pipx/commands/__init__.py | 29 | __all__ = [ | CODE |
| LOW | src/pipx/commands/uninject.py | 39 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/pipx/commands/uninject.py | 301 | __all__ = [ | STRING |
| LOW | src/pipx/commands/run_pip.py | 135 | __all__ = [ | CODE |
| LOW | src/pipx/commands/upgrade.py | 573 | __all__ = [ | STRING |
| LOW | src/pipx/commands/inject.py | 363 | __all__ = [ | STRING |
| LOW | src/pipx/commands/interpreter.py | 215 | __all__ = [ | CODE |
| LOW | src/pipx/commands/common.py | 727 | __all__ = [ | CODE |
| LOW | src/pipx/commands/ensure_path.py | 17 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/pipx/commands/uninstall.py | 247 | __all__ = [ | CODE |
| LOW | src/pipx/commands/environment.py | 104 | __all__ = [ | CODE |
| LOW | src/pipx/commands/install.py | 932 | __all__ = [ | CODE |
| LOW | src/pipx/commands/outdated.py | 292 | __all__ = [ | CODE |
| LOW | src/pipx/commands/expose.py | 152 | __all__ = [ | CODE |
| LOW | src/pipx/commands/reinstall.py | 337 | __all__ = [ | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | src/pipx/package_specifier.py | 85 | except InvalidRequirement: | CODE |
| HIGH | src/pipx/venv_inspect.py | 154 | except FileNotFoundError: | CODE |
| HIGH | src/pipx/venv_inspect.py | 177 | except FileNotFoundError: | CODE |
| HIGH | src/pipx/backends/uv.py | 241 | except FileNotFoundError: | CODE |
| HIGH | src/pipx/commands/common.py | 210 | except (FileNotFoundError, RuntimeError): | CODE |
| HIGH | src/pipx/commands/reinstall.py | 103 | except FileNotFoundError: | CODE |
| HIGH | src/pipx/commands/reinstall.py | 144 | except ValueError: | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/conftest.py | 305 | CODE | |
| LOW | tests/helpers.py | 128 | CODE | |
| LOW | scripts/release.py | 44 | CODE | |
| LOW | scripts/update_package_cache.py | 55 | CODE | |
| LOW | src/pipx/animate.py | 83 | CODE | |
| LOW | src/pipx/venv.py | 220 | CODE | |
| LOW | src/pipx/venv.py | 385 | CODE | |
| LOW | src/pipx/venv.py | 694 | CODE | |
| LOW | src/pipx/pipx_metadata_file.py | 257 | CODE | |
| LOW | src/pipx/standalone_python.py | 152 | CODE | |
| LOW | src/pipx/standalone_python.py | 184 | CODE | |
| LOW | src/pipx/standalone_python.py | 238 | CODE | |
| LOW | src/pipx/venv_inspect.py | 72 | CODE | |
| LOW | src/pipx/commands/pin.py | 20 | CODE | |
| LOW | src/pipx/commands/list_packages.py | 97 | CODE | |
| LOW | src/pipx/commands/list_packages.py | 120 | CODE | |
| LOW | src/pipx/commands/manifest.py | 35 | CODE | |
| LOW | src/pipx/commands/manifest.py | 344 | CODE | |
| LOW | src/pipx/commands/upgrade.py | 85 | CODE | |
| LOW | src/pipx/commands/interpreter.py | 118 | CODE | |
| LOW | src/pipx/commands/install.py | 58 | CODE | |
| LOW | src/pipx/commands/install.py | 637 | CODE | |
| LOW | src/pipx/commands/outdated.py | 169 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM⚡ | tests/test_shared_libs.py | 64 | # Create a fake venv structure | COMMENT |
| MEDIUM⚡ | tests/test_shared_libs.py | 71 | # Create a pyvenv.cfg pointing to a non-existent Python | COMMENT |
| MEDIUM⚡ | tests/test_shared_libs.py | 81 | # Create a fake venv structure | COMMENT |
| MEDIUM | tests/test_shared_libs.py | 94 | # Create a pyvenv.cfg pointing to the existing Python | COMMENT |
| MEDIUM | src/pipx/interpreter.py | 141 | # The following code was copied from https://github.com/uranusjr/pipx-standalone | COMMENT |
| MEDIUM | src/pipx/main.py | 2015 | "# This file is a cache directory tag created by pipx.\n" | STRING |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | tests/test_pipx_metadata_file.py | 191 | .replace('"cooldown_days": null, ', "") | CODE |
| HIGH | scripts/release.py | 31 | repo.git.push(push_target, "HEAD:main") | CODE |
| HIGH | scripts/release.py | 32 | repo.git.push(push_target, str(tag)) | CODE |
| HIGH | src/pipx/constants.py | 134 | autoload -U compinit && compinit | STRING |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | src/pipx/shared_libs.py | 227 | except Exception: | CODE |
| LOW | src/pipx/main.py | 1716 | except Exception as error: | STRING |
| LOW | src/pipx/main.py | 2100 | except Exception: | CODE |
| MEDIUM | src/pipx/main.py | 1927 | def setup_log_file() -> Path: | CODE |
| LOW | src/pipx/commands/run.py | 624 | except Exception as error: | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | src/pipx/util.py | 191 | CODE | |
| LOW | src/pipx/commands/run.py | 88 | CODE | |
| LOW | src/pipx/commands/upgrade.py | 204 | CODE | |
| LOW | src/pipx/commands/install.py | 58 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | src/pipx/util.py | 223 | # Set PYTHONSAFEPATH to prevent adding CWD to sys.path in subprocess Python commands | COMMENT |