Turn your Python application into an Android APK
This report presents the forensic synthetic code analysis of kivy/python-for-android, a Python project with 8,904 GitHub stars. SynthScan v2.0 examined 33,366 lines of code across 323 source files, recording 330 pattern matches distributed across 15 syntactic categories. The overall adjusted score of 11.6 places this repository in the Low AI signal band.
The scanner applied 160+ deterministic lexical heuristics, multi-line block detectors, abstract syntax tree depth profilers, and a cross-file Jaccard similarity matrix to construct a statistically normalised synthetic code estimate. All matches are individually weighted by severity coefficient and contextual multiplier before summation, and the resulting headline score is temporally discounted to account for the repository's development history relative to the commercial emergence of large language model coding tooling (November 2022 onward).
Longitudinal tracking requires multiple scan runs. Once this repository is re-scanned after new commits land, this chart will visualise how the synthetic code signal evolves over time — enabling you to detect whether AI authorship is growing, stabilising, or being actively corrected by human engineers.
Classifies detected patterns by their diagnostic confidence and structural impact. CRITICAL patterns (coefficient 10) represent definitive synthetic signatures — hallucinated imports, explicit LLM attribution metadata — virtually never produced by human authors. HIGH (5) indicates strong structural tells such as cross-file repetition or cross-linguistic idioms. MEDIUM (2) covers recognisable conversational padding and AI-specific vocabulary. LOW (1) captures subtle indicators like tautological comments and generic boilerplate that require density to carry independent signal.
This horizontal bar chart decomposes the repository's raw synthetic code score by top-level directory, allowing you to pinpoint precisely which modules or components carry the highest AI authorship density. Directories with disproportionately high scores relative to their size warrant targeted manual review: concentrated AI signatures often trace back to mass-generated configuration layers, auto-ported test suites, LLM-scaffolded boilerplate classes, or entire subsystems authored under heavy copilot assistance. Use this view to prioritise your human code-review effort.
The scanner identified 330 distinct pattern matches across 15 syntactic categories. Each entry below represents a discrete location in the source code where the engine recorded a statistically significant AI authorship indicator. 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 diagnostic confidence level (CRITICAL / HIGH / MEDIUM / LOW). The Context column identifies whether the match occurred inside executable code, an inline comment, or a string literal — comment-context matches receive a ×1.5 weight because LLMs systematically over-annotate. The ⚡ bolt icon marks clustered matches: three or more patterns within a 10-line window, each receiving an additional ×1.5 density multiplier as dense clusters constitute far stronger evidence of synthetic authorship than isolated hits.
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | testapps/on_device_unit_tests/test_app/tools.py | 19 | def run_test_suites_into_buffer(suites): | CODE |
| LOW | testapps/on_device_unit_tests/test_app/tools.py | 26 | def get_images_with_extension(path=APP_PATH, extension='*.png'): | CODE |
| LOW | testapps/on_device_unit_tests/test_app/tools.py | 63 | def get_failed_unittests_from(unittests_output, set_of_tests): | CODE |
| LOW | testapps/on_device_unit_tests/test_app/tools.py | 72 | def skip_if_not_running_from_android_device(func): | CODE |
| LOW | testapps/on_device_unit_tests/test_app/tools.py | 94 | def get_android_python_activity(): | CODE |
| LOW | testapps/on_device_unit_tests/test_app/tools.py | 166 | def setup_lifecycle_callbacks(): | CODE |
| LOW | testapps/on_device_unit_tests/test_app/app_flask.py | 39 | def get_html_for_tested_modules(tested_modules, failed_tests): | CODE |
| LOW | testapps/on_device_unit_tests/test_app/app_kivy.py | 103 | def set_color_for_tested_modules(self, restart=False): | STRING |
| LOW | testapps/on_device_unit_tests/test_app/app_kivy.py | 136 | def test_vibration_with_pyjnius(self, *args): | STRING |
| LOW | tests/test_toolchain.py | 14 | def patch_argparse_print_help(): | CODE |
| LOW⚡ | tests/test_prerequisites.py | 28 | def test_is_mandatory_on_darwin(self): | CODE |
| LOW⚡ | tests/test_prerequisites.py | 31 | def test_is_mandatory_on_linux(self): | CODE |
| LOW⚡ | tests/test_prerequisites.py | 34 | def test_installer_is_supported_on_darwin(self): | CODE |
| LOW⚡ | tests/test_prerequisites.py | 40 | def test_installer_is_supported_on_linux(self): | CODE |
| LOW⚡ | tests/test_prerequisites.py | 46 | def test_darwin_pkg_config_location(self): | CODE |
| LOW⚡ | tests/test_prerequisites.py | 49 | def test_linux_pkg_config_location(self): | CODE |
| LOW⚡ | tests/test_prerequisites.py | 53 | def test_pkg_config_location_property__darwin(self): | CODE |
| LOW⚡ | tests/test_prerequisites.py | 60 | def test_pkg_config_location_property__linux(self): | CODE |
| LOW⚡ | tests/test_prerequisites.py | 351 | def test_checker_calls_linux_checker(self, mock_linux_checker): | CODE |
| LOW⚡ | tests/test_prerequisites.py | 361 | def test_checker_calls_darwin_checker(self, mock_darwin_checker): | CODE |
| LOW⚡ | tests/test_prerequisites.py | 370 | def test_checker_raises_on_unsupported_platform(self): | CODE |
| LOW⚡ | tests/test_prerequisites.py | 382 | def test_ask_to_install_user_accepts(self, mock_input): | CODE |
| LOW⚡ | tests/test_prerequisites.py | 392 | def test_ask_to_install_user_declines(self, mock_input): | CODE |
| LOW⚡ | tests/test_prerequisites.py | 402 | def test_ask_to_install_non_interactive(self, mock_info): | CODE |
| LOW⚡ | tests/test_prerequisites.py | 426 | def test_install_when_user_accepts_darwin(self, mock_installer, mock_ask): | CODE |
| LOW⚡ | tests/test_prerequisites.py | 436 | def test_install_when_user_declines(self, mock_info, mock_ask): | CODE |
| LOW⚡ | tests/test_prerequisites.py | 445 | def test_install_is_supported(self): | CODE |
| LOW | tests/test_prerequisites.py | 132 | def test_darwin_pkg_config_location(self, _darwin_get_brew_formula_location_prefix): | CODE |
| LOW | tests/test_prerequisites.py | 279 | def test_default_darwin_prerequisites_set(self): | CODE |
| LOW | tests/test_prerequisites.py | 297 | def test_default_linux_prerequisites_set(self): | CODE |
| LOW | tests/test_prerequisites.py | 324 | def test_is_valid_when_not_met_non_mandatory(self, mock_checker, mock_warning): | CODE |
| LOW | tests/test_prerequisites.py | 338 | def test_is_valid_when_not_met_mandatory(self, mock_checker, mock_error): | CODE |
| LOW | tests/test_prerequisites.py | 415 | def test_install_when_user_accepts_linux(self, mock_info, mock_installer, mock_ask): | CODE |
| LOW | tests/test_prerequisites.py | 458 | def test_darwin_jdk_is_supported_valid_version(self, mock_exists, mock_popen): | CODE |
| LOW | tests/test_prerequisites.py | 474 | def test_darwin_jdk_is_supported_invalid_version(self, mock_exists, mock_popen): | CODE |
| LOW | tests/test_prerequisites.py | 488 | def test_darwin_jdk_is_supported_no_javac(self, mock_exists): | CODE |
| LOW | tests/test_prerequisites.py | 496 | def test_darwin_get_libexec_jdk_path(self, mock_run): | CODE |
| LOW | tests/test_prerequisites.py | 509 | def test_darwin_checker_uses_java_home_env(self, mock_is_supported): | CODE |
| LOW | tests/test_prerequisites.py | 523 | def test_darwin_get_brew_formula_location_prefix_success(self, mock_popen): | CODE |
| LOW | tests/test_prerequisites.py | 539 | def test_darwin_get_brew_formula_location_prefix_failure(self, mock_error, mock_popen): | CODE |
| LOW | tests/test_prerequisites.py | 552 | def test_darwin_get_brew_formula_location_prefix_with_installed_flag(self, mock_popen): | CODE |
| LOW | tests/test_prerequisites.py | 568 | def test_check_and_install_all_met(self, mock_get_prereqs): | CODE |
| LOW | tests/test_prerequisites.py | 589 | def test_check_and_install_some_not_met(self, mock_get_prereqs): | CODE |
| LOW | tests/test_pythonpackage_basic.py | 51 | def test__extract_info_from_package(): | CODE |
| LOW | tests/test_pythonpackage_basic.py | 86 | def test_get_dep_names_of_package(): | STRING |
| LOW | tests/test_pythonpackage_basic.py | 157 | def test_transform_dep_for_pip(): | STRING |
| LOW | tests/test_pythonpackage_basic.py | 195 | def test_parse_as_folder_reference(): | STRING |
| LOW | tests/test_pythonpackage_basic.py | 213 | def test_parse_as_folder_reference_edge_cases(input_ref, expected): | STRING |
| LOW | tests/test_pythonpackage_basic.py | 230 | def test_is_filesystem_path_edge_cases(path, expected): | CODE |
| LOW⚡ | tests/test_pythonpackage_basic.py | 241 | def test_transform_dep_for_pip_with_special_urls(input_dep, expected): | CODE |
| LOW⚡ | tests/test_pythonpackage_basic.py | 246 | def test_transform_dep_for_pip_passthrough(): | CODE |
| LOW⚡ | tests/test_pythonpackage_basic.py | 252 | def test_get_package_name_with_error(): | CODE |
| LOW⚡ | tests/test_pythonpackage_basic.py | 264 | def test_get_dep_names_error_handling(): | CODE |
| LOW⚡ | tests/test_pythonpackage_basic.py | 276 | def test_extract_info_from_package_missing_metadata(): | CODE |
| LOW | tests/test_pythonpackage_basic.py | 317 | def run__get_system_python_executable(self, pybin): | CODE |
| LOW | tests/test_patching.py | 42 | def test_is_platform_case_insensitive(self, mock_uname): | CODE |
| LOW | tests/test_patching.py | 49 | def test_is_platform_mismatch(self, mock_uname): | CODE |
| LOW | tests/test_kivy_bootstrap.py | 56 | def test_get_activity_reflects_the_configured_class(kivy_bootstrap): | CODE |
| LOW⚡ | tests/test_kivy_bootstrap.py | 72 | def test_get_activity_honours_custom_activity_class_name(): | CODE |
| LOW⚡ | tests/test_kivy_bootstrap.py | 81 | def test_get_activity_may_return_none(kivy_bootstrap): | CODE |
| 157 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | distribute.sh | 3 | # This file is just a shim to report an error messaage if some tool | COMMENT |
| MEDIUM⚡ | tests/test_pythonpackage_basic.py | 268 | # Create a setup.py that will fail | COMMENT |
| MEDIUM | tests/test_util.py | 240 | # Create a test module file | COMMENT |
| MEDIUM | tests/test_logger.py | 142 | # Create a mock error with required attributes | COMMENT |
| MEDIUM | tests/test_logger.py | 187 | # Create a proper exception class that mimics sh.ErrorReturnCode | COMMENT |
| MEDIUM | doc/source/conf.py | 6 | # This file is execfile()d with the current directory set to its | COMMENT |
| MEDIUM | pythonforandroid/pythonpackage.py | 124 | # This function is required by get_package_as_folder() to work | COMMENT |
| MEDIUM | pythonforandroid/pythonpackage.py | 267 | # Create a venv to install into: | COMMENT |
| MEDIUM | pythonforandroid/recipes/hostpython3/__init__.py | 159 | # Create a subdirectory to actually perform the build | COMMENT |
| MEDIUM | pythonforandroid/recipes/hostpython3/__init__.py | 176 | # Create the Setup file. This copying from Setup.dist is | COMMENT |
| MEDIUM | pythonforandroid/recipes/python3/__init__.py | 350 | # Create a subdirectory to actually perform the build | COMMENT |
| MEDIUM | pythonforandroid/recipes/android/src/android/mixer.py | 1 | # This module is, as much a possible, a clone of the pygame | COMMENT |
| MEDIUM | pythonforandroid/recipes/librt/__init__.py | 23 | # Create a temporary folder to add to link path with a fake librt.so: | COMMENT |
| MEDIUM | pythonforandroid/recipes/libpthread/__init__.py | 22 | # Create a temporary folder to add to link path with a fake libpthread.so: | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/test_checkdependencies.py | 11 | CODE | |
| LOW | tests/test_checkdependencies.py | 21 | CODE | |
| LOW | pythonforandroid/bootstrap.py | 20 | CODE | |
| LOW | pythonforandroid/bootstrap.py | 453 | CODE | |
| LOW | pythonforandroid/bootstrap.py | 112 | CODE | |
| LOW | pythonforandroid/bootstrap.py | 251 | CODE | |
| LOW | pythonforandroid/build.py | 567 | CODE | |
| LOW | pythonforandroid/build.py | 822 | CODE | |
| LOW | pythonforandroid/build.py | 1037 | CODE | |
| LOW | pythonforandroid/bdistapk.py | 35 | CODE | |
| LOW | pythonforandroid/util.py | 51 | CODE | |
| LOW | pythonforandroid/graph.py | 146 | CODE | |
| LOW | pythonforandroid/logger.py | 131 | CODE | |
| LOW | pythonforandroid/toolchain.py | 198 | CODE | |
| LOW | pythonforandroid/toolchain.py | 942 | CODE | |
| LOW | pythonforandroid/toolchain.py | 1002 | CODE | |
| LOW | pythonforandroid/toolchain.py | 1073 | CODE | |
| LOW | pythonforandroid/recipe.py | 206 | CODE | |
| LOW | pythonforandroid/recipe.py | 324 | CODE | |
| LOW | pythonforandroid/recipe.py | 394 | CODE | |
| LOW | pythonforandroid/recipe.py | 459 | CODE | |
| LOW | pythonforandroid/recipe.py | 558 | CODE | |
| LOW | pythonforandroid/recipe.py | 711 | CODE | |
| LOW | pythonforandroid/recipe.py | 723 | CODE | |
| LOW | pythonforandroid/recipe.py | 1545 | CODE | |
| LOW | pythonforandroid/pythonpackage.py | 120 | CODE | |
| LOW | pythonforandroid/pythonpackage.py | 246 | CODE | |
| LOW | pythonforandroid/pythonpackage.py | 381 | CODE | |
| LOW | pythonforandroid/pythonpackage.py | 472 | CODE | |
| LOW | pythonforandroid/pythonpackage.py | 571 | CODE | |
| LOW | …thonforandroid/recipes/android/src/android/activity.py | 38 | CODE | |
| LOW | …thonforandroid/recipes/android/src/android/activity.py | 52 | CODE | |
| LOW | pythonforandroid/recipes/reportlab/__init__.py | 15 | CODE | |
| LOW | pythonforandroid/recipes/scipy/wrapper.py | 32 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | testapps/on_device_unit_tests/test_app/app_kivy.py | 161 | except Exception as err: | STRING |
| LOW | pythonforandroid/build.py | 466 | except Exception: | CODE |
| LOW | pythonforandroid/build.py | 707 | except Exception: | CODE |
| LOW | pythonforandroid/build.py | 732 | except Exception: | CODE |
| LOW | pythonforandroid/build.py | 760 | except Exception as e: | CODE |
| LOW | pythonforandroid/build.py | 767 | except Exception: | CODE |
| LOW | pythonforandroid/logger.py | 123 | except Exception: | CODE |
| MEDIUM | pythonforandroid/logger.py | 112 | def get_console_width(): | CODE |
| LOW | pythonforandroid/recipe.py | 201 | except Exception as ex: | CODE |
| LOW | pythonforandroid/recipe.py | 1279 | except Exception: | CODE |
| LOW | pythonforandroid/recipe.py | 1337 | except Exception: | CODE |
| LOW | pythonforandroid/recipe.py | 1481 | except Exception: | CODE |
| LOW | …randroid/recipes/android/src/android/display_cutout.py | 67 | except Exception as e: | CODE |
| LOW | …randroid/recipes/android/src/android/display_cutout.py | 91 | except Exception: | CODE |
| LOW | …randroid/recipes/android/src/android/display_cutout.py | 103 | except Exception: | CODE |
| LOW | …randroid/recipes/android/src/android/display_cutout.py | 126 | except Exception: | CODE |
| LOW | …randroid/recipes/android/src/android/display_cutout.py | 227 | except Exception: | CODE |
| MEDIUM | …randroid/recipes/android/src/android/display_cutout.py | 55 | def onApplyWindowInsets(self, view, insets): | CODE |
| LOW | …honforandroid/recipes/android/src/android/broadcast.py | 88 | except Exception as e: | CODE |
| MEDIUM | …honforandroid/recipes/android/src/android/broadcast.py | 84 | def stop(self): | CODE |
| LOW | pythonforandroid/recipes/primp/__init__.py | 27 | except Exception: | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | doc/source/conf.py | 1 | # -*- coding: utf-8 -*- | COMMENT |
| LOW | doc/source/conf.py | 81 | version = get_version() | COMMENT |
| LOW | doc/source/conf.py | 101 | COMMENT | |
| LOW | doc/source/conf.py | 121 | #modindex_common_prefix = [] | COMMENT |
| LOW | doc/source/conf.py | 141 | # Add any paths that contain custom themes here, relative to this directory. | COMMENT |
| LOW | doc/source/conf.py | 161 | # relative to this directory. They are copied after the builtin static files, | COMMENT |
| LOW | doc/source/conf.py | 181 | # Additional templates that should be rendered to pages, maps page names to | COMMENT |
| LOW | doc/source/conf.py | 201 | #html_show_copyright = True | COMMENT |
| LOW | doc/source/conf.py | 221 | # The name of a javascript file (relative to the configuration directory) that | COMMENT |
| LOW | doc/source/conf.py | 241 | #'figure_align': 'htbp', | COMMENT |
| LOW | …onforandroid/includes/arm64-v8a/machine/cpu-features.h | 1 | #ifndef _ARM64_CPU_FEATURES | COMMENT |
| LOW | pythonforandroid/recipes/tflite-runtime/__init__.py | 1 | from pythonforandroid.recipe import PythonRecipe, current_directory, \ | COMMENT |
| LOW | pythonforandroid/recipes/libxml2/glob.c | 81 | #include <dirent.h> | COMMENT |
| LOW | pythonforandroid/recipes/libxml2/glob.c | 101 | #define RBRACKET ']' | COMMENT |
| LOW | pythonforandroid/recipes/libxml2/glob.c | 121 | COMMENT | |
| LOW | pythonforandroid/recipes/libxml2/glob.h | 81 | #define GLOB_ABORTED (-2) /* Unignored error. */ | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | testapps/testapp_vispy/main.py | 14 | CODE | |
| LOW | …_device_unit_tests/test_app/tests/test_requirements.py | 20 | CODE | |
| LOW | …_device_unit_tests/test_app/tests/test_requirements.py | 61 | CODE | |
| LOW | …_device_unit_tests/test_app/tests/test_requirements.py | 103 | CODE | |
| LOW | …_device_unit_tests/test_app/tests/test_requirements.py | 262 | CODE | |
| LOW | …_device_unit_tests/test_app/tests/test_requirements.py | 273 | CODE | |
| LOW | testapps/testapp_sqlite_openssl/main.py | 30 | CODE | |
| LOW | testapps/testapp_sqlite_openssl/main.py | 32 | CODE | |
| LOW | testapps/testapp_sqlite_openssl/main.py | 47 | CODE | |
| LOW | tests/test_pythonpackage_basic.py | 52 | CODE | |
| LOW | …thonforandroid/recipes/android/src/android/__init__.py | 8 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | ci/run_emulator_tests.sh | 34 | # Check if all success patterns are present | COMMENT |
| LOW | pythonforandroid/bootstrap.py | 266 | # Check if the bootstap's dependencies have an internal conflict: | COMMENT |
| LOW | pythonforandroid/bootstrap.py | 272 | # Check if bootstrap's dependencies conflict with chosen | COMMENT |
| LOW | pythonforandroid/build.py | 852 | # Output messages about what we're going to do: | COMMENT |
| LOW | pythonforandroid/pythonpackage.py | 462 | # Check if this is either not an url, or a file URL: | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | pythonforandroid/toolchain.py | 1067 | # WARNING: We should make sure to clean the build directory before building. | COMMENT |
| LOW | pythonforandroid/recipe.py | 880 | .. warning:: don't forget to call `super().__init__()` in any recipe's | STRING |
| LOW | pythonforandroid/recipes/freetype/__init__.py | 127 | # we will make sure to only install it when the library exists | COMMENT |
| LOW | pythonforandroid/recipes/librt/__init__.py | 31 | # Set symlinks, and make sure to update them on every build run: | COMMENT |
| LOW | pythonforandroid/recipes/libpthread/__init__.py | 30 | # Set symlinks, and make sure to update them on every build run: | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | …nforandroid/recipes/android/src/android/permissions.py | 564 | Requests Android permissions. Args: permissions (str): A list of permissions to requests (str) call | STRING |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | …honforandroid/recipes/android/src/android/broadcast.py | 1 | # ------------------------------------------------------------------- | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | pythonforandroid/recipes/pyzmq/__init__.py | 50 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/test_pythonpackage_basic.py | 45 | Lorem Ipsum""" | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/test_util.py | 244 | f.write("def test_function():\n") | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | …nforandroid/recipes/android/src/android/permissions.py | 621 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | …thonforandroid/recipes/android/src/android/darkmode.py | 35 | def set_dark_mode_listener(on_dark_mode_changed: Callable[[bool], None] | None) -> None: | CODE |