bottle.py is a fast and simple micro-framework for python web-applications.
This report presents the forensic synthetic code analysis of bottlepy/bottle, a Python project with 8,772 GitHub stars. SynthScan v2.0 examined 9,423 lines of code across 38 source files, recording 104 pattern matches distributed across 7 syntactic categories. The overall adjusted score of 13.7 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 104 distinct pattern matches across 7 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 | test/test_plugins.py | 53 | def test_uninstall_by_instance(self): | CODE |
| LOW | test/test_plugins.py | 155 | def test_json_plugin_catches_httpresponse(self): | CODE |
| LOW | test/test_plugins.py | 196 | def test_instance_method_wrapper(self): | CODE |
| LOW | test/test_mount.py | 90 | def test_mount_wsgi_ctype_bug(self): | CODE |
| LOW⚡ | test/test_router.py | 136 | def test_dynamic_before_static_any(self): | CODE |
| LOW⚡ | test/test_router.py | 143 | def test_any_static_before_dynamic(self): | CODE |
| LOW⚡ | test/test_router.py | 150 | def test_dynamic_any_if_method_exists(self): | CODE |
| LOW | test/test_multipart.py | 183 | def test_missing_content_type(self): | CODE |
| LOW | test/test_multipart.py | 186 | def test_unsupported_content_type(self): | CODE |
| LOW⚡ | test/test_multipart.py | 198 | def test_no_newline_after_content(self): | CODE |
| LOW⚡ | test/test_multipart.py | 204 | def test_no_newline_after_middle_content(self): | CODE |
| LOW⚡ | test/test_multipart.py | 214 | def test_preamble_before_start_boundary(self): | CODE |
| LOW | test/test_multipart.py | 251 | def test_content_length_to_small(self): | CODE |
| LOW | test/test_multipart.py | 258 | def test_no_disposition_header(self): | CODE |
| LOW | test/test_stpl.py | 20 | def test_self_as_variable_name(self): | CODE |
| LOW | test/test_stpl.py | 101 | def test_newline_in_parameterlist(self): | CODE |
| LOW | test/test_stpl.py | 231 | def test_bug_no_whitespace_before_stmt(self): | CODE |
| LOW | test/test_stpl.py | 234 | def test_bug_block_keywords_eat_prefixed_code(self): | CODE |
| LOW | test/test_stpl.py | 277 | def test_multiline_ignore_eob_in_string(self): | STRING |
| LOW | test/test_stpl.py | 289 | def test_multiline_find_eob_in_comments(self): | STRING |
| LOW | test/test_stpl.py | 316 | def test_multiline_eob_after_end(self): | STRING |
| LOW | test/test_stpl.py | 327 | def test_multiline_eob_in_single_line_code(self): | STRING |
| LOW | test/test_stpl.py | 337 | def test_multiline_strings_in_code_line(self): | STRING |
| LOW | test/test_stpl.py | 348 | def test_multiline_comprehensions_in_code_line(self): | STRING |
| LOW | test/test_stpl.py | 361 | def test_end_keyword_on_same_line(self): | STRING |
| LOW | test/test_outputfilter.py | 85 | def test_json_serialization_error(self): | CODE |
| LOW⚡ | test/test_outputfilter.py | 117 | def test_empty_generator_callback(self): | CODE |
| LOW⚡ | test/test_outputfilter.py | 125 | def test_error_in_generator_callback(self): | CODE |
| LOW⚡ | test/test_outputfilter.py | 132 | def test_fatal_error_in_generator_callback(self): | CODE |
| LOW⚡ | test/test_outputfilter.py | 139 | def test_httperror_in_generator_callback(self): | CODE |
| LOW⚡ | test/test_outputfilter.py | 148 | def test_httpresponse_in_generator_callback(self): | CODE |
| LOW⚡ | test/test_outputfilter.py | 154 | def test_unicode_generator_callback(self): | CODE |
| LOW⚡ | test/test_outputfilter.py | 160 | def test_invalid_generator_callback(self): | CODE |
| LOW | test/test_wsgi.py | 353 | def test_after_request_hooks_run_after_exception(self): | CODE |
| LOW | test/test_wsgi.py | 373 | def test_after_request_hooks_run_after_exception_in_before_hook(self): | CODE |
| LOW | test/test_wsgi.py | 393 | def test_after_request_hooks_may_rise_response_exception(self): | CODE |
| LOW | test/test_wsgi.py | 410 | def test_after_response_hook_can_set_headers(self): | CODE |
| LOW | test/test_wsgi.py | 543 | def test_module_shortcuts_with_different_name(self): | CODE |
| LOW | test/test_route.py | 44 | def test_callback_inspection_multiple_args(self): | CODE |
| LOW | test/test_route.py | 66 | def test_callback_inspection_newsig(self): | CODE |
| LOW | test/test_route.py | 98 | def test_unwrap_closure_callable(self): | CODE |
| LOW | test/test_environ.py | 140 | def test_header_access_special(self): | CODE |
| LOW⚡ | test/test_environ.py | 308 | def test_chunked_not_terminated(self): | CODE |
| LOW⚡ | test/test_environ.py | 314 | def test_chunked_illegal_size(self): | CODE |
| LOW⚡ | test/test_environ.py | 317 | def test_chunked_not_chunked_at_all(self): | CODE |
| LOW | test/test_environ.py | 403 | def test_json_header_empty_body(self): | CODE |
| LOW | test/test_environ.py | 452 | def test_user_defined_attributes(self): | CODE |
| LOW | test/test_environ.py | 493 | def test_constructor_headerlist(self): | CODE |
| LOW | test/test_environ.py | 611 | def test_set_cookie_value_long_string(self): | CODE |
| LOW | test/test_environ.py | 615 | def test_set_cookie_name_long_string(self): | CODE |
| LOW | test/test_environ.py | 735 | def test_prevent_control_characters_in_headers(self): | CODE |
| LOW | test/test_environ.py | 870 | def test_redirect_preserve_cookies(self): | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | test/test_formsdict.py | 5 | CODE | |
| LOW | test/test_formsdict.py | 5 | CODE | |
| LOW | test/test_plugins.py | 2 | CODE | |
| LOW | test/test_plugins.py | 5 | CODE | |
| LOW | test/tools.py | 2 | CODE | |
| LOW | test/tools.py | 14 | CODE | |
| LOW | test/__init__.py | 1 | CODE | |
| LOW | test/__init__.py | 2 | CODE | |
| LOW | test/__init__.py | 3 | CODE | |
| LOW | test/__init__.py | 4 | CODE | |
| LOW | test/__init__.py | 4 | CODE | |
| LOW | test/test_fileupload.py | 5 | CODE | |
| LOW | test/test_fileupload.py | 6 | CODE | |
| LOW | test/test_fileupload.py | 7 | CODE | |
| LOW | test/test_oorouting.py | 14 | CODE | |
| LOW | test/test_multipart.py | 4 | CODE | |
| LOW | test/test_multipart.py | 4 | CODE | |
| LOW | test/test_multipart.py | 4 | CODE | |
| LOW | test/test_stpl.py | 2 | CODE | |
| LOW | test/test_outputfilter.py | 7 | CODE | |
| LOW | test/test_outputfilter.py | 12 | CODE | |
| LOW | test/test_wsgi.py | 2 | CODE | |
| LOW | test/test_mako.py | 1 | CODE | |
| LOW | test/test_mako.py | 54 | CODE | |
| LOW | test/test_jinja2.py | 69 | CODE | |
| LOW | test/test_jinja2.py | 43 | CODE | |
| LOW | test/test_jinja2.py | 50 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | bottle.py | 1097 | default_app.push(self) | CODE |
| HIGH | bottle.py | 2517 | return self.push() | CODE |
| HIGH | bottle.py | 3788 | tmp = default_app.push() # Create a new "default application" | CODE |
| HIGH | test/test_securecookies.py | 13 | bottle.app.push() | CODE |
| HIGH | test/tools.py | 86 | self.app = bottle.app.push() | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | bottle.py | 2901 | CODE | |
| LOW | bottle.py | 2924 | CODE | |
| LOW | bottle.py | 3800 | CODE | |
| LOW | bottle.py | 4525 | CODE | |
| LOW | bottle.py | 430 | CODE | |
| LOW | bottle.py | 534 | CODE | |
| LOW | bottle.py | 1178 | CODE | |
| LOW | bottle.py | 2621 | CODE | |
| LOW | bottle.py | 3195 | CODE | |
| LOW | bottle.py | 4291 | CODE | |
| LOW | test/test_multipart.py | 81 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | bottle.py | 130 | def _stderr(*args): | CODE |
| LOW | bottle.py | 972 | except Exception as E: | CODE |
| LOW | bottle.py | 1038 | except Exception as error: | CODE |
| LOW | bottle.py | 1076 | except Exception as E: | CODE |
| LOW | bottle.py | 2124 | except Exception: | CODE |
| LOW | bottle.py | 2555 | except Exception: | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | bottle.py | 3788 | tmp = default_app.push() # Create a new "default application" | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | bottle.py | 3800 | CODE | |
| LOW | bottle.py | 1755 | CODE |