Rust bindings for the Python interpreter
This report summarizes scanner evidence for PyO3/pyo3, a Rust project with 16,220 GitHub stars. SynthScan examined 166,760 lines of code across 726 source files, recording 742 pattern matches distributed across 17 syntactic categories. The legacy adjusted pattern signal is 4.6 (Low 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? 710 finding(s).
Are imports declared and package/API names verified? 15 finding(s).
Are wrappers, guards, and repeated structures necessary? 74 finding(s).
Which changes need focused human review? 742 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 742 distinct pattern matches across 17 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 | typos.toml | 1 | [files] | COMMENT |
| LOW | typos.toml | 21 | # | ^^^ | COMMENT |
| LOW | typos.toml | 41 | # error: `placehold` should be `placeholder` | COMMENT |
| LOW | typos.toml | 61 | # | | COMMENT |
| LOW | guide/src/class.md | 241 | ) -> PyResult<()> { | COMMENT |
| LOW | guide/src/class.md | 261 | # }); | COMMENT |
| LOW | guide/src/class.md | 501 | if val % 2 == 0 { | COMMENT |
| LOW | guide/src/class.md | 841 | - For details on `parameter-list`, see the documentation of `Method arguments` section. | COMMENT |
| LOW | guide/src/class.md | 1081 | #[classmethod] | COMMENT |
| LOW | guide/src/class.md | 1101 | # let doc: String = class.getattr("__doc__")?.extract()?; | COMMENT |
| LOW | guide/src/class.md | 1121 | # let sig: String = inspect | COMMENT |
| LOW | guide/src/class.md | 1141 | # let method = class.getattr("my_static_method")?; | COMMENT |
| LOW | guide/src/parallelism.md | 41 | ``` | COMMENT |
| LOW | guide/src/parallelism.md | 61 | ``` | COMMENT |
| LOW | guide/src/function.md | 141 | # let warnings = py.import("warnings")?; | COMMENT |
| LOW | guide/src/function.md | 161 | # for (warning, (category, message)) in list.iter().zip(expected_warnings) { | COMMENT |
| LOW | guide/src/migration.md | 501 | # use pyo3::sync::GILOnceCell; | COMMENT |
| LOW | guide/src/migration.md | 1861 | ```rust | COMMENT |
| LOW | guide/src/advanced.md | 21 | For example, [`append_to_inittab!`]({{#PYO3_DOCS_URL}}/pyo3/macro.append_to_inittab.html) must be called before Python i | COMMENT |
| LOW | guide/src/trait-bounds.md | 181 | # } | COMMENT |
| LOW | guide/src/trait-bounds.md | 201 | # self.model | COMMENT |
| LOW | guide/src/trait-bounds.md | 341 | Let's modify the code performing the type conversion to give a helpful error message to the Python user: | COMMENT |
| LOW | guide/src/trait-bounds.md | 381 | # | COMMENT |
| LOW | guide/src/conversions/traits.md | 1 | # Conversion traits | COMMENT |
| LOW | guide/src/conversions/traits.md | 41 | COMMENT | |
| LOW | guide/src/conversions/traits.md | 81 | # let dict = PyDict::new(py); | COMMENT |
| LOW | guide/src/conversions/traits.md | 101 | string_attr: String, | COMMENT |
| LOW | guide/src/conversions/traits.md | 141 | bar: String, | COMMENT |
| LOW | guide/src/conversions/traits.md | 161 | Tuple structs are also supported but do not allow customizing the extraction. | COMMENT |
| LOW | guide/src/conversions/traits.md | 221 | inner: String, | COMMENT |
| LOW | guide/src/conversions/traits.md | 281 | # let rust_thing: RustyEnum<'_> = thing.extract()?; | COMMENT |
| LOW | guide/src/conversions/traits.md | 301 | # ); | COMMENT |
| LOW | guide/src/conversions/traits.md | 321 | # match rust_thing { | COMMENT |
| LOW | guide/src/conversions/traits.md | 341 | # let rust_thing: RustyEnum<'_> = instance.extract()?; | COMMENT |
| LOW | guide/src/conversions/traits.md | 361 | # )?; | COMMENT |
| LOW | guide/src/conversions/traits.md | 381 | # b"text", | COMMENT |
| LOW | guide/src/conversions/traits.md | 401 | enum RustyEnum { | COMMENT |
| LOW | guide/src/conversions/traits.md | 421 | # } | COMMENT |
| LOW | guide/src/conversions/traits.md | 501 | # // Filled case | COMMENT |
| LOW | guide/src/function/signature.md | 141 | The example below creates a function `add` which accepts two positional-only arguments `a` and `b`, where `b` has a defa | COMMENT |
| LOW | guide/src/function/signature.md | 201 | # Python::attach(|py| { | COMMENT |
| LOW | guide/src/function/signature.md | 241 | a + b | COMMENT |
| LOW | guide/src/function/error-handling.md | 161 | } | COMMENT |
| LOW | guide/src/class/numeric.md | 341 | # n = Number(0) | COMMENT |
| LOW | guide/src/class/numeric.md | 361 | # | COMMENT |
| LOW | guide/src/class/numeric.md | 381 | # import inspect | COMMENT |
| LOW | guide/src/class/object.md | 41 | COMMENT | |
| LOW | guide/src/class/object.md | 281 | self.0 == other.0 | COMMENT |
| LOW | pyo3-ffi/src/moduleobject.rs | 41 | pub fn PyModule_GetDict(arg1: *mut PyObject) -> *mut PyObject; | COMMENT |
| LOW | pyo3-ffi/src/methodobject.rs | 141 | /// Function types used to implement Python callables. | COMMENT |
| LOW | pyo3-ffi/src/lib.rs | 1 | #![no_std] | COMMENT |
| LOW | pyo3-ffi/src/lib.rs | 21 | //! - The vast majority can only be used safely while the thread is attached to the Python interpreter. | COMMENT |
| LOW | pyo3-ffi/src/lib.rs | 41 | //! PyO3 uses `rustc`'s `--cfg` flags to enable or disable code used for different Python versions. | COMMENT |
| LOW | pyo3-ffi/src/lib.rs | 61 | //! To use these attributes, add [`pyo3-build-config`] as a build dependency in | COMMENT |
| LOW | pyo3-ffi/src/lib.rs | 81 | //! - CPython 3.9 or greater | COMMENT |
| LOW | pyo3-ffi/src/lib.rs | 101 | //! # Downstream Rust code (including code in `bin/`, `examples/`, and `tests/`) will not be able | COMMENT |
| LOW | pyo3-ffi/src/lib.rs | 121 | //! **`build.rs`** | COMMENT |
| LOW | pyo3-ffi/src/lib.rs | 141 | //! m_base: PyModuleDef_HEAD_INIT, | COMMENT |
| LOW | pyo3-ffi/src/lib.rs | 161 | //! // A zeroed PyMethodDef to mark the end of the array. | COMMENT |
| LOW | pyo3-ffi/src/lib.rs | 181 | //! slot: 0, | COMMENT |
| 578 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | noxfile.py | 60 | def _parse_supported_interpreter_version( | CODE |
| LOW | noxfile.py | 74 | def _supported_interpreter_versions( | CODE |
| LOW⚡ | noxfile.py | 325 | def _clippy_additional_workspaces(session: nox.Session) -> bool: | CODE |
| LOW | noxfile.py | 644 | def test_cross_compilation_windows(session: nox.Session): | CODE |
| LOW | noxfile.py | 1312 | def set_msrv_package_versions(session: nox.Session): | STRING |
| LOW | noxfile.py | 1585 | def _iter_extern_libpython_blocks(source: str) -> Iterator[str]: | CODE |
| LOW | noxfile.py | 1610 | def _cfg_attr_is_non_cpython_only(attr: str) -> bool: | CODE |
| LOW⚡ | examples/word-count/tests/test_word_count.py | 35 | def test_word_count_rust_parallel(benchmark, contents): | STRING |
| LOW⚡ | examples/word-count/tests/test_word_count.py | 40 | def test_word_count_rust_sequential(benchmark, contents): | STRING |
| LOW⚡ | examples/word-count/tests/test_word_count.py | 45 | def test_word_count_python_sequential(benchmark, contents): | STRING |
| LOW⚡ | examples/word-count/tests/test_word_count.py | 50 | def run_rust_sequential_twice( | STRING |
| LOW⚡ | examples/word-count/tests/test_word_count.py | 60 | def test_word_count_rust_sequential_twice_with_threads(benchmark, contents): | STRING |
| LOW | pytests/tests/test_sequence.py | 9 | def test_vec_from_list_pystring(): | CODE |
| LOW | pytests/tests/test_sequence.py | 29 | def test_rust_array_from_array(): | CODE |
| LOW | pytests/tests/test_misc.py | 23 | def test_multiple_imports_same_interpreter_ok(): | CODE |
| LOW | pytests/tests/test_misc.py | 41 | def test_import_in_subinterpreter_forbidden(): | CODE |
| LOW | pytests/tests/test_misc.py | 67 | def test_type_fully_qualified_name_includes_module(): | CODE |
| LOW | pytests/tests/test_datetime_hypothesis.py | 110 | def test_datetime_from_timestamp(dt): | CODE |
| LOW | pytests/tests/test_finalization.py | 27 | def test_hammer_attaching_in_thread(): | CODE |
| LOW | pytests/tests/test_finalization.py | 35 | def test_detach_during_finalization(): | CODE |
| LOW | pytests/tests/test_enums.py | 5 | def test_complex_enum_variant_constructors(): | CODE |
| LOW | pytests/tests/test_enums.py | 39 | def test_complex_enum_variant_subclasses(variant: enums.ComplexEnum): | CODE |
| LOW | pytests/tests/test_enums.py | 43 | def test_complex_enum_field_getters(): | CODE |
| LOW | pytests/tests/test_enums.py | 74 | def test_complex_enum_desugared_match(variant: enums.ComplexEnum): | CODE |
| LOW | pytests/tests/test_enums.py | 105 | def test_complex_enum_pyfunction_in_out_desugared_match(variant: enums.ComplexEnum): | CODE |
| LOW | pytests/tests/test_enums.py | 126 | def test_tuple_enum_variant_constructors(): | CODE |
| LOW | pytests/tests/test_enums.py | 142 | def test_tuple_enum_variant_subclasses(variant: enums.TupleEnum): | CODE |
| LOW⚡ | pytests/tests/test_enums.py | 153 | def test_tuple_enum_field_getters(): | CODE |
| LOW⚡ | pytests/tests/test_enums.py | 160 | def test_tuple_enum_index_getter(): | CODE |
| LOW⚡ | pytests/tests/test_enums.py | 170 | def test_mixed_complex_enum_pyfunction_instance_nothing( | CODE |
| LOW | pytests/tests/test_enums.py | 183 | def test_mixed_complex_enum_pyfunction_instance_empty(variant: enums.MixedComplexEnum): | CODE |
| LOW | pytests/tests/test_datetime.py | 76 | def test_invalid_time_fails_overflow(args): | CODE |
| LOW | pytests/tests/test_datetime.py | 126 | def test_invalid_datetime_fails(): | CODE |
| LOW | pytests/tests/test_datetime.py | 136 | def test_datetime_from_timestamp_tzinfo(): | CODE |
| LOW | pytests/tests/test_datetime.py | 194 | def test_tz_class_introspection(): | CODE |
| LOW | pytests/tests/test_enums_match.py | 16 | def test_complex_enum_match_statement(variant: enums.ComplexEnum): | CODE |
| LOW | pytests/tests/test_enums_match.py | 44 | def test_complex_enum_pyfunction_in_out(variant: enums.ComplexEnum): | CODE |
| LOW | pytests/tests/test_enums_match.py | 68 | def test_complex_enum_partial_match(variant: enums.ComplexEnum): | CODE |
| LOW | pytests/tests/test_enums_match.py | 83 | def test_tuple_enum_match_statement(variant: enums.TupleEnum): | CODE |
| LOW | pytests/tests/test_enums_match.py | 103 | def test_simple_tuple_enum_match_statement(variant: enums.SimpleTupleEnum): | CODE |
| LOW | pytests/tests/test_enums_match.py | 119 | def test_tuple_enum_match_match_args(variant: enums.TupleEnum): | CODE |
| LOW | pytests/tests/test_enums_match.py | 136 | def test_tuple_enum_partial_match(variant: enums.TupleEnum): | CODE |
| LOW | pytests/tests/test_enums_match.py | 151 | def test_mixed_complex_enum_match_statement(variant: enums.MixedComplexEnum): | CODE |
| LOW | pytests/tests/test_pyclasses.py | 85 | def test_option_iter_type_hints() -> None: | CODE |
| LOW | pytests/tests/test_pyclasses.py | 170 | def test_no_constructor_defined_propagates_cause(cls: type, exc_message: str): | CODE |
| LOW | pytests/tests/test_pyfunctions.py | 66 | def test_simple_args_kwargs_py(benchmark): | CODE |
| LOW | pytests/tests/test_pyfunctions.py | 70 | def test_simple_args_kwargs_rs(benchmark): | CODE |
| LOW | pytests/tests/test_pyfunctions.py | 104 | def test_positional_only_batched_py(benchmark): | CODE |
| LOW | pytests/tests/test_pyfunctions.py | 118 | def test_positional_only_batched_rs(benchmark): | CODE |
| LOW | pytests/tests/test_pyfunctions.py | 146 | def many_keyword_arguments_py( | CODE |
| LOW | pytests/tests/test_pyfunctions.py | 167 | def call_with_many_keyword_arguments(f) -> Any: | CODE |
| LOW | pytests/tests/test_pyfunctions.py | 186 | def test_many_keyword_arguments_py(benchmark): | CODE |
| LOW | pytests/tests/test_pyfunctions.py | 190 | def test_many_keyword_arguments_rs(benchmark): | CODE |
| LOW | pytests/tests/test_exception.py | 4 | def test_pypy_exception_dealloc(): | CODE |
| LOW | pytests/tests/test_objstore.py | 7 | def test_objstore_doesnot_leak_memory(): | CODE |
| LOW | pytests/tests/test_path.py | 29 | def test_take_invalid_pathlike(): | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH⚡ | examples/plugin/python_plugin/gadget_init_plugin.py | 8 | g.push(1) | CODE |
| HIGH⚡ | examples/plugin/python_plugin/gadget_init_plugin.py | 9 | g.push(2) | CODE |
| HIGH⚡ | examples/plugin/python_plugin/gadget_init_plugin.py | 10 | g.push(3) | CODE |
| HIGH | examples/plugin/plugin_api/tests/test_Gadget.py | 22 | gadget.push(42) | CODE |
| HIGH | pytests/tests/test_objstore.py | 23 | store.push(message) | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW⚡ | noxfile.py | 332 | except Exception: | CODE |
| LOW⚡ | noxfile.py | 341 | except Exception: | CODE |
| LOW | noxfile.py | 403 | except Exception: | CODE |
| LOW | noxfile.py | 1108 | except Exception: | CODE |
| LOW | guide/src/migration.md | 1717 | except Exception as e: | CODE |
| LOW⚡ | guide/src/debugging.md | 318 | except Exception: | CODE |
| LOW⚡ | guide/src/debugging.md | 325 | except Exception as e: | CODE |
| MEDIUM⚡ | guide/src/debugging.md | 326 | print(f"Error updating launch.json: {e}") | CODE |
| LOW | tests/test_inheritance.rs | 229 | except Exception as e: | CODE |
| LOW | src/types/traceback.rs | 158 | except Exception as e: | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | guide/glossary_linker.py | 66 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | guide/glossary_linker.py | 68 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | guide/glossary_linker.py | 183 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | guide/glossary_linker.py | 185 | # --------------------------------------------------------------------------- | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | noxfile.py | 1 | CODE | |
| LOW | examples/plugin/plugin_api/tests/test_import.py | 2 | CODE | |
| LOW | examples/maturin-starter/maturin_starter/__init__.py | 2 | CODE | |
| LOW | examples/maturin-starter/maturin_starter/__init__.py | 5 | CODE | |
| LOW | examples/word-count/word_count/__init__.py | 1 | CODE | |
| LOW | examples/word-count/word_count/__init__.py | 1 | CODE | |
| LOW | examples/word-count/word_count/__init__.py | 1 | CODE | |
| LOW | …tools-rust-starter/setuptools_rust_starter/__init__.py | 2 | CODE | |
| LOW | …tools-rust-starter/setuptools_rust_starter/__init__.py | 5 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | noxfile.py | 812 | CODE | |
| LOW | noxfile.py | 987 | CODE | |
| LOW | noxfile.py | 1556 | CODE | |
| LOW | noxfile.py | 1585 | CODE | |
| LOW | guide/glossary_linker.py | 84 | CODE | |
| LOW | pytests/tests/test_enums.py | 74 | CODE | |
| LOW | pytests/tests/test_enums.py | 105 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | Contributing.md | 38 | We prefer that authors disclose if a contribution is generated by AI so we can take that into account without guesswork. | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | pytests/noxfile.py | 27 | except CommandFailed: | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | pyo3-macros-backend/src/py_expr.rs | 186 | _ => PyConstant::Ellipsis, // TODO: implement ByteStr and CStr | CODE |
| LOW | pyo3-macros-backend/src/frompyobject.rs | 475 | // TODO: implement using a Protocol? | COMMENT |
| LOW | pyo3-macros-backend/src/intopyobject.rs | 381 | // TODO: implement using a Protocol? | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | pytests/tests/test_enums_match.py | 1 | # This file is only collected when Python >= 3.10, because it tests match syntax. | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | noxfile.py | 224 | def set_coverage_env(session: nox.Session) -> None: | CODE |
| LOW | examples/word-count/word_count/__init__.py | 3 | __all__ = [ | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | .github/workflows/ci.yml | 878 | # Check if all needs were successful or skipped. | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | src/pyclass.rs | 66 | /// Usage example: | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | src/pycell/impl_.rs | 309 | // For `#[pyclass]` types which inherit from PyAny, we can just call tp_free | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | guide/src/python-from-rust/calling-existing-code.md | 348 | let house = house_class.call1(("123 Main Street",)).unwrap(); | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | pytests/tests/test_pyfunctions.py | 146 | CODE |