Geocoding library for Python.
This report presents the forensic synthetic code analysis of geopy/geopy, a Python project with 4,832 GitHub stars. SynthScan v2.0 examined 18,032 lines of code across 101 source files, recording 338 pattern matches distributed across 12 syntactic categories. The overall adjusted score of 25.2 places this repository in the Moderate 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 338 distinct pattern matches across 12 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_point.py | 75 | def test_point_from_string_tolerates_irrelevant_surroundings(self): | CODE |
| LOW | test/test_point.py | 82 | def test_point_from_string_rejects_overlong_input(self): | CODE |
| LOW | test/test_point.py | 94 | def test_point_format_altitude(self): | CODE |
| LOW | test/test_point.py | 114 | def test_point_from_single_number(self): | CODE |
| LOW | test/test_point.py | 129 | def test_point_from_generator(self): | CODE |
| LOW | test/test_point.py | 134 | def test_point_degrees_are_normalized(self): | CODE |
| LOW | test/test_point.py | 172 | def test_point_degrees_normalization_does_not_lose_precision(self): | CODE |
| LOW | test/test_point.py | 250 | def test_point_setitem_normalization(self): | CODE |
| LOW | test/test_point.py | 268 | def test_point_assign_coordinates(self): | CODE |
| LOW | test/test_point.py | 295 | def test_point_comparison_does_not_raise_exceptions(self): | CODE |
| LOW | test/test_point.py | 304 | def test_point_comparison_with_empty_values(self): | CODE |
| LOW | test/test_point.py | 322 | def test_point_comparison_respects_lists(self): | CODE |
| LOW | test/test_point.py | 336 | def test_point_comparison_ignores_strings(self): | CODE |
| LOW⚡ | test/conftest.py | 65 | def _is_internet_access_allowed(config): | CODE |
| LOW⚡ | test/conftest.py | 70 | def is_internet_access_allowed(request): | CODE |
| LOW⚡ | test/conftest.py | 75 | def skip_if_internet_access_is_not_allowed(is_internet_access_allowed): | CODE |
| LOW | test/conftest.py | 161 | def print_requests_monitor_report(requests_monitor): | CODE |
| LOW⚡ | test/test_distance.py | 31 | def test_should_have_length_when_only_given_length(self): | CODE |
| LOW⚡ | test/test_distance.py | 35 | def test_should_have_zero_distance_for_coincident_points(self): | CODE |
| LOW⚡ | test/test_distance.py | 38 | def test_should_have_nonzero_distance_for_distinct_points(self): | CODE |
| LOW⚡ | test/test_distance.py | 46 | def test_should_compute_distance_for_trip_between_poles(self): | CODE |
| LOW⚡ | test/test_distance.py | 51 | def test_should_compute_destination_for_trip_between_poles(self): | CODE |
| LOW⚡ | test/test_distance.py | 57 | def test_destination_bearing_east(self): | CODE |
| LOW⚡ | test/test_distance.py | 74 | def test_should_compute_distance_across_antimeridian(self): | CODE |
| LOW⚡ | test/test_distance.py | 80 | def test_should_compute_destination_across_antimeridian(self): | CODE |
| LOW⚡ | test/test_distance.py | 87 | def test_should_not_tolerate_nans(self): | CODE |
| LOW⚡ | test/test_distance.py | 96 | def test_should_compute_distance_for_multiple_points_pairwise(self): | CODE |
| LOW⚡ | test/test_distance.py | 105 | def test_should_raise_when_using_single_numbers_as_points(self): | CODE |
| LOW⚡ | test/test_distance.py | 115 | def test_should_tolerate_tuples_with_textual_numbers(self): | CODE |
| LOW⚡ | test/test_distance.py | 120 | def test_should_warn_for_mixed_up_lat_lon(self): | CODE |
| LOW⚡ | test/test_distance.py | 130 | def test_should_get_consistent_results_for_distance_calculations(self): | CODE |
| LOW⚡ | test/test_distance.py | 140 | def test_should_be_able_to_add_distances(self): | CODE |
| LOW⚡ | test/test_distance.py | 144 | def test_should_not_allow_adding_with_objects_that_arent_distances(self): | CODE |
| LOW⚡ | test/test_distance.py | 150 | def test_should_be_able_to_negate_distances(self): | CODE |
| LOW⚡ | test/test_distance.py | 155 | def test_should_be_able_to_subtract_distances(self): | CODE |
| LOW⚡ | test/test_distance.py | 159 | def test_should_be_able_to_multiply_distances_by_floats(self): | CODE |
| LOW⚡ | test/test_distance.py | 163 | def test_should_not_be_able_to_multiply_distances_by_distances(self): | CODE |
| LOW⚡ | test/test_distance.py | 167 | def test_should_not_be_able_to_divide_floats_by_distances(self): | CODE |
| LOW⚡ | test/test_distance.py | 173 | def test_should_be_able_to_divide_distances_by_distances(self): | CODE |
| LOW⚡ | test/test_distance.py | 178 | def test_should_be_able_to_floor_divide_distances_by_distances(self): | CODE |
| LOW⚡ | test/test_distance.py | 183 | def test_should_be_able_to_divide_distances_by_floats(self): | CODE |
| LOW⚡ | test/test_distance.py | 188 | def test_should_be_able_to_floor_divide_distances(self): | CODE |
| LOW⚡ | test/test_distance.py | 193 | def test_should_be_able_to_take_absolute_value_of_distances(self): | CODE |
| LOW⚡ | test/test_distance.py | 196 | def test_should_be_true_in_boolean_context_when_nonzero_length(self): | CODE |
| LOW⚡ | test/test_distance.py | 199 | def test_should_be_false_in_boolean_context_when_zero_length(self): | CODE |
| LOW⚡ | test/test_distance.py | 207 | def test_should_convert_to_kilometers(self): | CODE |
| LOW⚡ | test/test_distance.py | 210 | def test_should_convert_to_kilometers_with_abbreviation(self): | CODE |
| LOW⚡ | test/test_distance.py | 213 | def test_should_convert_to_meters(self): | CODE |
| LOW⚡ | test/test_distance.py | 216 | def test_should_convert_to_meters_with_abbreviation(self): | CODE |
| LOW⚡ | test/test_distance.py | 219 | def test_should_convert_to_miles(self): | CODE |
| LOW⚡ | test/test_distance.py | 222 | def test_should_convert_to_miles_with_abbreviation(self): | CODE |
| LOW⚡ | test/test_distance.py | 225 | def test_should_convert_to_feet(self): | CODE |
| LOW⚡ | test/test_distance.py | 228 | def test_should_convert_to_feet_with_abbreviation(self): | CODE |
| LOW⚡ | test/test_distance.py | 231 | def test_should_convert_to_nautical_miles(self): | CODE |
| LOW⚡ | test/test_distance.py | 234 | def test_should_convert_to_nautical_miles_with_abbrevation(self): | CODE |
| LOW⚡ | test/test_distance.py | 237 | def test_should_convert_from_meters(self): | CODE |
| LOW⚡ | test/test_distance.py | 240 | def test_should_convert_from_feet(self): | CODE |
| LOW⚡ | test/test_distance.py | 243 | def test_should_convert_from_miles(self): | CODE |
| LOW⚡ | test/test_distance.py | 246 | def test_should_convert_from_nautical_miles(self): | CODE |
| LOW⚡ | test/test_distance.py | 254 | def test_should_support_comparison_with_distance(self): | CODE |
| 174 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | geopy/geocoders/banfrance.py | 0 | return an address by location point. :param query: the coordinates for which you wish to obtain the closest human-readab | STRING |
| HIGH | geopy/geocoders/mapquest.py | 0 | return an address by location point. :param query: the coordinates for which you wish to obtain the closest human-readab | STRING |
| HIGH | geopy/geocoders/geokeo.py | 0 | return an address by location point. :param query: the coordinates for which you wish to obtain the closest human-readab | STRING |
| HIGH | geopy/geocoders/mapbox.py | 0 | return an address by location point. :param query: the coordinates for which you wish to obtain the closest human-readab | STRING |
| HIGH | geopy/geocoders/pelias.py | 0 | return an address by location point. :param query: the coordinates for which you wish to obtain the closest human-readab | STRING |
| HIGH | geopy/geocoders/google.py | 0 | return an address by location point. :param query: the coordinates for which you wish to obtain the closest human-readab | STRING |
| HIGH | geopy/geocoders/maptiler.py | 0 | return an address by location point. :param query: the coordinates for which you wish to obtain the closest human-readab | STRING |
| HIGH | geopy/geocoders/opencage.py | 0 | return an address by location point. :param query: the coordinates for which you wish to obtain the closest human-readab | STRING |
| HIGH | geopy/geocoders/baidu.py | 0 | return an address by location point. :param query: the coordinates for which you wish to obtain the closest human-readab | STRING |
| HIGH | geopy/geocoders/photon.py | 0 | return an address by location point. :param query: the coordinates for which you wish to obtain the closest human-readab | STRING |
| HIGH | geopy/geocoders/geocodio.py | 0 | returns location, (latitude, longitude) from json feed. | STRING |
| HIGH | geopy/geocoders/mapquest.py | 0 | returns location, (latitude, longitude) from json feed. | STRING |
| HIGH | geopy/geocoders/opencage.py | 0 | returns location, (latitude, longitude) from json feed. | STRING |
| HIGH | geopy/geocoders/mapbox.py | 0 | returns location, (latitude, longitude) from json feed. | STRING |
| HIGH | geopy/geocoders/geolake.py | 0 | returns location, (latitude, longitude) from json feed. | STRING |
| HIGH | geopy/geocoders/baidu.py | 0 | returns location, (latitude, longitude) from json feed. | STRING |
| HIGH | geopy/geocoders/geocodio.py | 0 | get the location, lat, lng from a single json place. | STRING |
| HIGH | geopy/geocoders/google.py | 0 | get the location, lat, lng from a single json place. | STRING |
| HIGH | geopy/geocoders/geokeo.py | 0 | get the location, lat, lng from a single json place. | STRING |
| HIGH | geopy/geocoders/opencage.py | 0 | get the location, lat, lng from a single json place. | STRING |
| HIGH | geopy/geocoders/baidu.py | 0 | get the location, lat, lng from a single json place. | STRING |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | test/conftest.py | 216 | except Exception as e: | CODE |
| LOW | test/conftest.py | 238 | except Exception as e: | CODE |
| LOW | test/conftest.py | 329 | except Exception: | CODE |
| LOW | test/proxy_server.py | 183 | except Exception as e: | CODE |
| LOW | test/proxy_server.py | 269 | except Exception as e: | CODE |
| LOW | geopy/adapters.py | 299 | except Exception as error: | CODE |
| LOW | geopy/adapters.py | 345 | except Exception: | CODE |
| LOW | geopy/adapters.py | 355 | except Exception: | CODE |
| LOW | geopy/adapters.py | 483 | except Exception as error: | CODE |
| LOW | geopy/adapters.py | 615 | except Exception as error: | CODE |
| MEDIUM | geopy/adapters.py | 342 | def _read_http_error_body(self, error): | CODE |
| MEDIUM | geopy/adapters.py | 480 | def _request(self, url, *, timeout, headers): | CODE |
| MEDIUM | geopy/adapters.py | 610 | def _normalize_exceptions(self): | CODE |
| LOW | geopy/geocoders/base.py | 377 | except Exception as error: | CODE |
| LOW | geopy/geocoders/base.py | 386 | except Exception as error: | CODE |
| MEDIUM | geopy/geocoders/base.py | 371 | def fut(): | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | test/test_point.py | 181 | # The issue is that there might be a loss in precision during | COMMENT |
| LOW | docs/conf.py | 1 | # | COMMENT |
| LOW | docs/conf.py | 61 | COMMENT | |
| LOW | docs/conf.py | 81 | # List of patterns, relative to source directory, that match files and | COMMENT |
| LOW | docs/conf.py | 101 | pygments_style = "default" | COMMENT |
| LOW | docs/conf.py | 121 | # Add any paths that contain custom themes here, relative to this directory. | COMMENT |
| LOW | docs/conf.py | 141 | # relative to this directory. They are copied after the builtin static files, | COMMENT |
| LOW | docs/conf.py | 161 | # Additional templates that should be rendered to pages, maps page names to | COMMENT |
| LOW | docs/conf.py | 181 | # html_show_copyright = True | COMMENT |
| LOW | docs/conf.py | 201 | #'pointsize': '10pt', | COMMENT |
| LOW | docs/conf.py | 221 | # If true, show page references after internal links. | COMMENT |
| LOW | docs/conf.py | 261 | # Documents to append as an appendix to all manuals. | COMMENT |
| LOW | geopy/distance.py | 121 | from geographiclib.geodesic import Geodesic | COMMENT |
| LOW | geopy/adapters.py | 401 | '`pip install "geopy[requests]"`.' | COMMENT |
| LOW | geopy/extra/rate_limiter.py | 101 | # | COMMENT |
| LOW | geopy/extra/__init__.py | 1 | # Extra modules are intentionally not exported here, to avoid | COMMENT |
| LOW | geopy/geocoders/base.py | 161 | default_timeout | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | test/proxy_server.py | 10 | CODE | |
| LOW | geopy/point.py | 161 | CODE | |
| LOW | geopy/adapters.py | 295 | CODE | |
| LOW | geopy/adapters.py | 480 | CODE | |
| LOW | geopy/adapters.py | 610 | CODE | |
| LOW | geopy/geocoders/bing.py | 216 | CODE | |
| LOW | geopy/geocoders/google.py | 413 | CODE | |
| LOW | geopy/geocoders/nominatim.py | 135 | CODE | |
| LOW | geopy/geocoders/here.py | 332 | CODE | |
| LOW | geopy/geocoders/geokeo.py | 189 | CODE | |
| LOW | geopy/geocoders/arcgis.py | 229 | CODE | |
| LOW | geopy/geocoders/baidu.py | 210 | CODE | |
| LOW | geopy/geocoders/base.py | 345 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | test/adapters/each_adapter.py | 45 | CODE | |
| LOW | docs/conf.py | 14 | CODE | |
| LOW | docs/conf.py | 15 | CODE | |
| LOW | geopy/__init__.py | 12 | CODE | |
| LOW | geopy/__init__.py | 13 | CODE | |
| LOW | geopy/__init__.py | 14 | CODE | |
| LOW | geopy/__init__.py | 15 | CODE | |
| LOW | geopy/__init__.py | 16 | CODE | |
| LOW | geopy/__init__.py | 16 | CODE | |
| LOW | geopy/__init__.py | 16 | CODE | |
| LOW | geopy/geocoders/osm.py | 3 | CODE | |
| LOW | geopy/geocoders/__init__.py | 228 | CODE | |
| LOW | geopy/geocoders/googlev3.py | 3 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | test/adapters/each_adapter.py | 250 | # Create an ssl context which should not allow the negotiation with | COMMENT |
| MEDIUM | test/adapters/each_adapter.py | 267 | # Create an ssl context which should not allow the negotiation with | COMMENT |
| MEDIUM | docs/conf.py | 5 | # This file is execfile()d with the current directory set to its | COMMENT |
| MEDIUM | geopy/geocoders/base.py | 189 | # Create an object which `repr` returns 'DEFAULT_SENTINEL'. Sphinx (docs) uses | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | geopy/geocoders/google.py | 38 | CODE | |
| LOW | geopy/geocoders/google.py | 174 | CODE | |
| LOW | geopy/geocoders/nominatim.py | 135 | CODE | |
| LOW | geopy/geocoders/here.py | 49 | CODE | |
| LOW | geopy/geocoders/here.py | 146 | CODE | |
| LOW | geopy/geocoders/here.py | 468 | CODE | |
| LOW | geopy/geocoders/arcgis.py | 33 | CODE | |
| LOW | geopy/geocoders/mapbox.py | 21 | CODE | |
| LOW | geopy/geocoders/ignfrance.py | 39 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW⚡ | test/geocoders/smartystreets.py | 9 | dummy_id = 'DUMMY12345' | CODE |
| LOW⚡ | test/geocoders/smartystreets.py | 10 | dummy_token = 'DUMMY67890' | CODE |
| LOW⚡ | test/geocoders/smartystreets.py | 14 | auth_id=self.dummy_id, | CODE |
| LOW⚡ | test/geocoders/smartystreets.py | 15 | auth_token=self.dummy_token, | CODE |
| LOW⚡ | test/geocoders/smartystreets.py | 22 | geocoder = LiveAddress(auth_id=self.dummy_id, auth_token=self.dummy_token) | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | geopy/geocoders/ignfrance.py | 334 | # Clean tree from namespace to facilitate XML manipulation | STRING |
| LOW | geopy/geocoders/baidu.py | 215 | # When there are no results, just return. | COMMENT |
| LOW | .github/workflows/ci.yml | 87 | # GitHub Actions cannot just pass all secrets as env vars :( | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | geopy/geocoders/__init__.py | 187 | # Also don't forget to pull up the list of geocoders | COMMENT |
| LOW | geopy/geocoders/__init__.py | 187 | # Also don't forget to pull up the list of geocoders | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | geopy/geocoders/ignfrance.py | 171 | # Check if acceptable query type | COMMENT |