cg-code-graph 0.21.0__tar.gz → 0.21.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {cg_code_graph-0.21.0/cg_code_graph.egg-info → cg_code_graph-0.21.2}/PKG-INFO +3 -1
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/README.md +2 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/__init__.py +1 -1
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/cli.py +48 -20
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/core/redact.py +46 -21
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/coverage.py +47 -10
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/external.py +37 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/mcp_install.py +1 -1
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/mcp_server.py +131 -50
- cg_code_graph-0.21.2/cg_code_graph/plugins/laravel/massassign.py +286 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/laravel/plugin.py +143 -21
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/laravel/values.py +2 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/query.py +366 -33
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/routes.py +5 -4
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/surface.py +2 -2
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2/cg_code_graph.egg-info}/PKG-INFO +3 -1
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph.egg-info/SOURCES.txt +10 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph.egg-info/entry_points.txt +1 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/pyproject.toml +1 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_affected.py +3 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_bridges.py +3 -1
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_coverage.py +4 -4
- cg_code_graph-0.21.2/tests/test_db_connections.py +280 -0
- cg_code_graph-0.21.2/tests/test_issue_192.py +60 -0
- cg_code_graph-0.21.2/tests/test_issue_203.py +52 -0
- cg_code_graph-0.21.2/tests/test_issue_207.py +58 -0
- cg_code_graph-0.21.2/tests/test_issue_209.py +42 -0
- cg_code_graph-0.21.2/tests/test_issue_211.py +45 -0
- cg_code_graph-0.21.2/tests/test_listing_files.py +45 -0
- cg_code_graph-0.21.2/tests/test_mass_assignment.py +164 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_mcp_install.py +10 -7
- cg_code_graph-0.21.2/tests/test_readers_writers_specs.py +211 -0
- cg_code_graph-0.21.2/tests/test_redact_salt.py +235 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_routes_search_explain.py +3 -2
- cg_code_graph-0.21.0/tests/test_redact_salt.py +0 -97
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/LICENSE +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/MANIFEST.in +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/__main__.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/affected.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/agent_rules.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/agents.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/aitools.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/android_ipc.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/apple_ipc.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/apps.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/blindspots.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/bridges.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/brokers.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/concepts.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/config.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/core/__init__.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/core/cache.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/core/detect.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/core/env.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/core/extractors.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/core/fsutil.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/core/generated.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/core/model.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/core/paths.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/core/plugin.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/core/store.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/core/syntax_errors.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/dart_isolates.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/doctor.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/explore.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/graphql.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/guard_facts.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/hooks.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/indexer.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/insecure_transport.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/jobs.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/link.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/lint_async.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/local_ipc.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/local_sockets.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/parity.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/parity_structure.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/payload.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plans.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/platform_scan.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/platforms.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/__init__.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/astro/__init__.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/astro/content.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/astro/plugin.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/cfamily/__init__.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/cfamily/plugin.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/cfamily/syntax.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/dart/__init__.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/dart/bridges.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/dart/extractor/bin/extract.dart +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/dart/extractor/pubspec.lock +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/dart/extractor/pubspec.yaml +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/dart/http.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/dart/models.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/dart/plugin.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/dart/program.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/django/__init__.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/django/extras.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/django/models.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/django/plugin.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/django/schemas.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/django/shapes.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/django/urls.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/express/__init__.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/express/plugin.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/flutter/__init__.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/flutter/plugin.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/java/__init__.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/java/exact.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/java/plugin.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/jvm/__init__.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/jvm/interop.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/jvm/spring.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/kotlin/__init__.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/kotlin/exact.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/kotlin/plugin.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/kotlin/reparse.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/laravel/__init__.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/laravel/broadcast.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/laravel/tests.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/native/__init__.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/native/gates.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/native/runner.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/native/scipread.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/native/ts.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/nest/__init__.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/nest/plugin.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/nextjs/__init__.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/nextjs/plugin.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/nuxt/__init__.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/nuxt/plugin.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/php/__init__.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/php/external.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/php/extractor/composer.json +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/php/extractor/composer.lock +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/php/extractor/extract.php +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/php/gating.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/php/http_client.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/php/inline_guards.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/php/plugin.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/php/strings.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/python/__init__.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/python/aitools.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/python/external.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/python/fields.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/python/plugin.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/python/refs.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/python/roots.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/python/socketio.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/python/subproc.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/python/tests.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/python/values.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/pyweb/__init__.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/pyweb/plugin.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/pyweb/values.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/rust/__init__.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/rust/cargo.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/rust/plugin.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/rust/syntax.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/scip/__init__.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/scip/importer.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/scip/scip.proto +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/scip/scip_pb2.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/stubs/__init__.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/stubs/plugins.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/swift/__init__.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/swift/baseurl.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/swift/exact.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/swift/indexstore.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/swift/packages.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/swift/plugin.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/ts/__init__.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/ts/baseurl.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/ts/extractor/extract.mjs +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/ts/extractor/fw.mjs +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/ts/extractor/package-lock.json +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/ts/extractor/package.json +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/ts/extractor/rr.mjs +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/ts/nav.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/ts/plugin.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/ts/react_router.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/tsweb/__init__.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/tsweb/common.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/plugins/tsweb/data.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/presets/__init__.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/presets/c_cpp.yaml +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/presets/common.yaml +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/presets/dart.yaml +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/presets/django-ninja.yaml +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/presets/django.yaml +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/presets/djangorestframework.yaml +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/presets/express.yaml +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/presets/java.yaml +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/presets/kotlin.yaml +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/presets/laravel.yaml +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/presets/nest.yaml +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/presets/nextjs.yaml +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/presets/nuxt.yaml +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/presets/php.yaml +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/presets/python.yaml +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/presets/react-router.yaml +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/presets/rust.yaml +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/presets/spring.yaml +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/presets/swift.yaml +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/presets/typescript.yaml +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/process_runs.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/protocols/__init__.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/protocols/builtin.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/protocols/matchers.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/protocols/view.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/realtime.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/realtime_events.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/realtime_native.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/realtime_ws.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/roundtrip.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/rpc.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/sdk_systems.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/sockets.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/ssrf_input.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/starters.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/tests_index.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/udp_apps.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/viz/__init__.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/viz/graph.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/viz/server.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/viz/static/app.css +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/viz/static/app.js +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/viz/static/index.html +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/viz/static/layered.js +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/viz/static/vendor/VERSIONS.txt +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/viz/static/vendor/cose-base.js +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/viz/static/vendor/cytoscape-fcose.js +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/viz/static/vendor/cytoscape.min.js +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/viz/static/vendor/layout-base.js +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/viz/tools/package-lock.json +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/viz/tools/package.json +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/viz/tools/shoot.mjs +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/watch.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/webhook_subs.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/webhooks.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph/xcode.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph.egg-info/dependency_links.txt +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph.egg-info/requires.txt +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/cg_code_graph.egg-info/top_level.txt +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/setup.cfg +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_agents_install.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_agents_md.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_ai_tools.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_android_ipc.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_apple_ipc.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_astro.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_astro_content.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_astro_server.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_bridges_pigeon_monorepo.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_brokers.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_cache_clean.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_cache_invalidation.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_cache_migration.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_channels_tests.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_cli_output.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_completeness.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_config_extras.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_coverage_ts_hint.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_dart_isolates.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_dispatch_interfaces.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_django_flutter.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_docs_languages.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_docs_links.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_echo_ref.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_echo_wrapper.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_elysia.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_enum_constants.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_env.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_explore.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_external.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_fp_batch.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_gating.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_generated.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_graphql.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_hooks.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_impact_overrides.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_index_isolation.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_inherited_overrides.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_inline_guards.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_java.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_java_exact.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_jobs.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_js_refs.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_js_runtime.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_kotlin.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_kotlin_binding.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_kotlin_exact.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_kotlin_fields.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_kotlin_mixed.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_kotlin_nav_consts.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_kotlin_props.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_laravel_determinism.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_laravel_resources.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_lint_async.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_local_ipc.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_local_sockets.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_mcp.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_mcp_index.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_native_cfamily.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_native_concurrency.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_native_rust.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_nuxt_import_dirs.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_nuxt_rootsrc.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_packaging.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_parity.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_parity_structure.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_php_http.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_php_props.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_plain_js.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_plans.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_platform_gaps.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_platform_type_variants.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_platforms.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_platforms_apple.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_presets_config.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_process_ipc.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_process_runs.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_protocols.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_python_app_tests_module.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_python_collection_chains.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_python_compat.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_python_entry_refs.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_python_fields.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_python_infer_cycles.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_python_roots.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_python_subprocess_tests.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_python_tests.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_python_web_hosts.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_python_web_routes.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_python_web_routes_more.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_react_router.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_realtime.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_realtime_native.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_request_keys.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_roundtrip.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_route_tables.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_rpc.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_scip_health.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_sdk_external.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_sdk_external_infra.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_sdk_external_mail.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_snippet.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_sockets.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_spring.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_ssrf.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_starters_budget.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_surface.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_surface_transport.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_swift.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_swift_binding.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_swift_exact.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_swift_facts.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_swift_fields.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_swift_modules.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_swift_more.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_swift_nav_values.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_swift_parse_errors.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_swift_props.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_swift_sdk.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_swift_testing.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_swift_values.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_tests_scope.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_ts_fields.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_ts_fields_js_vue.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_ts_file_specs.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_ts_frameworks.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_ts_node_http.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_ts_nuxt.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_ts_src_tsconfig.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_unguarded.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_values.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_viz.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_vue_nav.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_watch.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_webhooks.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_webhooks_152.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_webhooks_152b.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_websockets.py +0 -0
- {cg_code_graph-0.21.0 → cg_code_graph-0.21.2}/tests/test_workspace_link.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cg-code-graph
|
|
3
|
-
Version: 0.21.
|
|
3
|
+
Version: 0.21.2
|
|
4
4
|
Summary: cg: a code graph of routes, calls, data access and platform boundaries for agents and humans (CLI + MCP server)
|
|
5
5
|
Author: cyberchronos00
|
|
6
6
|
License-Expression: MIT
|
|
@@ -33,6 +33,8 @@ Dynamic: license-file
|
|
|
33
33
|
|
|
34
34
|
For you and your AI agent (CLI + MCP). No LLM in the graph.
|
|
35
35
|
|
|
36
|
+
<!-- mcp-name: io.github.cyberchronos00/cg-code-graph -->
|
|
37
|
+
|
|
36
38
|
[](https://pypi.org/project/cg-code-graph/) [](https://pepy.tech/project/cg-code-graph) [](https://pypi.org/project/cg-code-graph/) [](https://github.com/cyberchronos00/code-graph/blob/main/LICENSE) [](https://code-graph.cyberchronos00.workers.dev/)
|
|
37
39
|
|
|
38
40
|
[Docs](https://code-graph.cyberchronos00.workers.dev/) · [Quick start](https://code-graph.cyberchronos00.workers.dev/docs/quickstart) · [CLI](https://code-graph.cyberchronos00.workers.dev/docs/cli) · [MCP](https://code-graph.cyberchronos00.workers.dev/docs/mcp) · [Changelog](https://github.com/cyberchronos00/code-graph/blob/main/CHANGELOG.md)
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
|
|
7
7
|
For you and your AI agent (CLI + MCP). No LLM in the graph.
|
|
8
8
|
|
|
9
|
+
<!-- mcp-name: io.github.cyberchronos00/cg-code-graph -->
|
|
10
|
+
|
|
9
11
|
[](https://pypi.org/project/cg-code-graph/) [](https://pepy.tech/project/cg-code-graph) [](https://pypi.org/project/cg-code-graph/) [](https://github.com/cyberchronos00/code-graph/blob/main/LICENSE) [](https://code-graph.cyberchronos00.workers.dev/)
|
|
10
12
|
|
|
11
13
|
[Docs](https://code-graph.cyberchronos00.workers.dev/) · [Quick start](https://code-graph.cyberchronos00.workers.dev/docs/quickstart) · [CLI](https://code-graph.cyberchronos00.workers.dev/docs/cli) · [MCP](https://code-graph.cyberchronos00.workers.dev/docs/mcp) · [Changelog](https://github.com/cyberchronos00/code-graph/blob/main/CHANGELOG.md)
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"""code-graph: deterministic code knowledge graph (beta)."""
|
|
2
|
-
__version__ = "0.21.
|
|
2
|
+
__version__ = "0.21.2"
|
|
@@ -75,6 +75,20 @@ def _add_install_parser(sub, uninstall: bool):
|
|
|
75
75
|
p.add_argument("--yes", action="store_true", help="skip the confirmation prompt")
|
|
76
76
|
|
|
77
77
|
|
|
78
|
+
def _impact_labels(rows: list[dict], name_of, group_of) -> list[str]:
|
|
79
|
+
"""Display names for one impact listing. Same-name rows in one group gain a file suffix."""
|
|
80
|
+
from collections import defaultdict
|
|
81
|
+
groups = defaultdict(list)
|
|
82
|
+
for i, row in enumerate(rows):
|
|
83
|
+
groups[group_of(row)].append(i)
|
|
84
|
+
labels = [name_of(row) for row in rows]
|
|
85
|
+
for idxs in groups.values():
|
|
86
|
+
named = Q.disambiguated([labels[i] for i in idxs], [rows[i].get("file") for i in idxs])
|
|
87
|
+
for i, lab in zip(idxs, named):
|
|
88
|
+
labels[i] = lab
|
|
89
|
+
return labels
|
|
90
|
+
|
|
91
|
+
|
|
78
92
|
def main(argv=None):
|
|
79
93
|
from . import __version__
|
|
80
94
|
ap = argparse.ArgumentParser(prog="cg")
|
|
@@ -321,8 +335,8 @@ def main(argv=None):
|
|
|
321
335
|
p.add_argument("--quiet", action="store_true", help="pass --quiet to each refresh")
|
|
322
336
|
helps = {"reaches": "everything that depends on the targets, grouped by entry classification",
|
|
323
337
|
"siblings": "code related to a symbol: class hierarchy, the same method in sibling classes, shared resources, co-callers",
|
|
324
|
-
"writers": "code that writes a table
|
|
325
|
-
"readers": "code that reads a stored property `Type.prop`
|
|
338
|
+
"writers": "code that writes a table, a column (`table.column`) or a stored property `Type.prop`",
|
|
339
|
+
"readers": "code that reads a table, a column (`table.column`) or a stored property `Type.prop`",
|
|
326
340
|
"impact": "callers of a method up to their entry points (reverse walk), overrides listed apart",
|
|
327
341
|
"stats": "node / edge counts of a graph DB",
|
|
328
342
|
"node": "one node's details and its incoming / outgoing edges",
|
|
@@ -342,6 +356,9 @@ def main(argv=None):
|
|
|
342
356
|
p.add_argument("--no-paths", action="store_true")
|
|
343
357
|
p.add_argument("--max-depth", type=int, default=30)
|
|
344
358
|
p.add_argument("--gate", default="auto", help="gate scenario for live/gated split (default: the one indexed; 'none' to disable)")
|
|
359
|
+
if name in ("reaches", "writers", "readers"):
|
|
360
|
+
p.add_argument("--connection", help="only the table / column edges that go to this database connection "
|
|
361
|
+
"(a dynamic name by its pattern, e.g. 'legacy_{store.id}'; docs/cli.md)")
|
|
345
362
|
if name in ("reaches", "impact", "downstream"):
|
|
346
363
|
p.add_argument("--platform", help="only code built for this target (windows, linux, macos, ios, android, web; see docs/platforms.md)")
|
|
347
364
|
if name == "impact":
|
|
@@ -646,7 +663,7 @@ def main(argv=None):
|
|
|
646
663
|
return
|
|
647
664
|
if a.cmd == "reaches":
|
|
648
665
|
res = Q.reaches(st, a.specs, min_conf=a.min_confidence, max_depth=a.max_depth, gate=None if a.gate == "none" else a.gate,
|
|
649
|
-
platform=a.platform)
|
|
666
|
+
platform=a.platform, connection=a.connection)
|
|
650
667
|
res["completeness"] = _completeness(st, [x for t in res["targets"].values() for x in t] + [i["id"] for i in res["items"]])
|
|
651
668
|
print(json.dumps(res, indent=1, default=str) if a.json else Q.render_reaches(res, show_paths=not a.no_paths))
|
|
652
669
|
_note(res["completeness"], a.json)
|
|
@@ -664,20 +681,26 @@ def main(argv=None):
|
|
|
664
681
|
if not res["targets"]:
|
|
665
682
|
print(f"no method matches {a.spec!r}; try `search` with part of the name"); return
|
|
666
683
|
if a.platform and res["targets"] and set(res["platform"]["targets_not_built"]) == set(res["targets"]):
|
|
667
|
-
|
|
668
|
-
|
|
684
|
+
msg = f"{a.spec} is not built for {a.platform}: nothing calls it there"
|
|
685
|
+
if Q.divergence_lists(st, a.platform, res["targets"]):
|
|
686
|
+
msg += (f" (`cg platforms divergence --target {a.platform}` lists references to it that would not build)")
|
|
687
|
+
print(msg); return
|
|
669
688
|
for line in Q.override_lines(res):
|
|
670
689
|
print(line)
|
|
690
|
+
if res.get("connections"):
|
|
691
|
+
print(Q.connections_line(res["connections"]))
|
|
671
692
|
if not res["callers"] and not res["entry_points"]:
|
|
672
693
|
print(Q.explain_no_callers(st, a.spec, res["targets"], a.min_confidence)); return
|
|
673
694
|
print(f"callers (transitive): {len(res['callers'])}")
|
|
674
|
-
|
|
695
|
+
caller_names = _impact_labels(res["callers"], lambda c: c.get("fqn") or c["id"], lambda c: c.get("module") or c.get("kind"))
|
|
696
|
+
for c, nm in zip(res["callers"], caller_names):
|
|
675
697
|
loc = f" @ {c['file']}:{c['line']}" if Q.NATIVE_FILE_RE.search(c.get("file") or "") else ""
|
|
676
|
-
print(f" d={c['depth']} [{c['module'] or c['kind']}] {
|
|
698
|
+
print(f" d={c['depth']} [{c['module'] or c['kind']}] {nm}{loc}{Q.caller_label(c)}")
|
|
677
699
|
print(f"entry points: {len(res['entry_points'])}")
|
|
678
|
-
|
|
700
|
+
entry_names = _impact_labels(res["entry_points"], lambda e: e["name"], lambda e: e.get("entry_kind"))
|
|
701
|
+
for e, nm0 in zip(res["entry_points"], entry_names):
|
|
679
702
|
native = Q.NATIVE_FILE_RE.search(e.get("file") or "")
|
|
680
|
-
nm = f"{e.get('fqn') or e['name']} @ {e['file']}:{e['line']}" if native else
|
|
703
|
+
nm = f"{e.get('fqn') or e['name']} @ {e['file']}:{e['line']}" if native else nm0
|
|
681
704
|
print(f" {e['entry_kind']:16} {nm} conf={e['path_confidence']}{Q.CANDIDATE_LABEL if e.get('candidate') else ''}"
|
|
682
705
|
f"{Q.generated_label(e)}{Q.platform_label(e)}")
|
|
683
706
|
if not a.no_paths:
|
|
@@ -702,17 +725,14 @@ def main(argv=None):
|
|
|
702
725
|
res = RT.roundtrip(st, a.spec, include_tests=a.tests)
|
|
703
726
|
print(RT.to_json(res) if a.json else RT.render(res))
|
|
704
727
|
elif a.cmd in ("writers", "readers"):
|
|
705
|
-
|
|
728
|
+
groups = Q.access(st, a.spec, a.cmd, a.connection)
|
|
729
|
+
rows = [r for g in groups for r in g["rows"]]
|
|
706
730
|
if a.json:
|
|
707
731
|
print(json.dumps(rows, indent=1)); return
|
|
708
732
|
if not rows:
|
|
709
|
-
print(Q.explain_no_writers(st, a.spec, a.cmd))
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
ex = {k: v for k, v in (r.get("attrs") or {}).items() if k in ("receiver", "accessor", "storage")}
|
|
713
|
-
extra = (" " + " ".join(f"{k}={v}" for k, v in ex.items())) if ex else ""
|
|
714
|
-
kind = f"{r['kind']}({r['attrs']['orig']})" if r.get("test") else r['kind']
|
|
715
|
-
print(f"[{r['module']}] {r['fqn']} {kind} {r['dst']} @{r['file']}:{r['line']} ({r['confidence']}){extra} entries: {ek}")
|
|
733
|
+
print(Q.explain_no_connection(st, a.spec, a.connection, a.cmd) if a.connection else Q.explain_no_writers(st, a.spec, a.cmd))
|
|
734
|
+
return
|
|
735
|
+
print("\n".join(Q.render_access(groups)))
|
|
716
736
|
verb = "write" if a.cmd == "writers" else "read"
|
|
717
737
|
nt = sum(1 for r in rows if r.get("test"))
|
|
718
738
|
print(f"{len(rows)} {verb} edges, {len({r['src'] for r in rows})} {a.cmd}" + (f" ({nt} from test code)" if nt else ""))
|
|
@@ -773,6 +793,14 @@ def node_doc(st, nid: str) -> dict:
|
|
|
773
793
|
return {"node": n, "out": edges("src", "dst"), "in": edges("dst", "src")}
|
|
774
794
|
|
|
775
795
|
|
|
796
|
+
def _mass_note(e: dict) -> str:
|
|
797
|
+
"""` via update(validated()) keys from UpdateBookRequest::rules ∩ Book::$fillable` for a mass-assignment column write (#177)."""
|
|
798
|
+
at = e.get("attrs") or {}
|
|
799
|
+
if e["kind"] != "WRITES_COLUMN" or not at.get("mass_assignment"):
|
|
800
|
+
return ""
|
|
801
|
+
return f" via {at.get('via')}" + (f" keys from {' ∩ '.join(at['keys_from'])}" if at.get("keys_from") else "")
|
|
802
|
+
|
|
803
|
+
|
|
776
804
|
def render_node(d: dict) -> str:
|
|
777
805
|
"""`cg node` text: the node's location, kind and attrs, then its edges; the same edge from one site (one row per
|
|
778
806
|
gate scenario or accessor) is listed once with a count."""
|
|
@@ -801,10 +829,10 @@ def render_node(d: dict) -> str:
|
|
|
801
829
|
out.append(f" {'outgoing' if key == 'out' else 'incoming'} ({len(es)}):" if es else f" {'outgoing' if key == 'out' else 'incoming'}: none")
|
|
802
830
|
seen: dict = {}
|
|
803
831
|
for e in es:
|
|
804
|
-
k = (e["kind"], e[other], e["file"], e["line"], e["confidence"])
|
|
832
|
+
k = (e["kind"], e[other], e["file"], e["line"], e["confidence"], _mass_note(e))
|
|
805
833
|
seen[k] = seen.get(k, 0) + 1
|
|
806
|
-
for (kind, o, f, line, conf), c in seen.items():
|
|
807
|
-
out.append(f" {arrow} {kind} {o} @{f}:{line} {conf}" + (f" ×{c}" if c > 1 else ""))
|
|
834
|
+
for (kind, o, f, line, conf, note), c in seen.items():
|
|
835
|
+
out.append(f" {arrow} {kind} {o} @{f}:{line} {conf}{note}" + (f" ×{c}" if c > 1 else ""))
|
|
808
836
|
return "\n".join(out)
|
|
809
837
|
|
|
810
838
|
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"""Secret values never reach the graph database (#47).
|
|
2
2
|
|
|
3
|
-
A literal that belongs to a credential-looking key (password, secret,
|
|
4
|
-
|
|
3
|
+
A literal that belongs to a credential-looking key (its last word is password, secret, dsn, ..., or an
|
|
4
|
+
explicit compound such as api_key; a bare `key` / `token` counts unless a known non-secret word precedes it
|
|
5
|
+
(`primary_key`, `cache.key`), whatever the value looks like; `AUTH_GUARD` or `..._TOKEN_TABLE`
|
|
6
|
+
do not count) is stored as `redacted:hmac:<first 8 hex of HMAC-SHA-256(graph salt, value)>`: enough to see that
|
|
5
7
|
a literal exists and to tell two values apart within one graph, not enough to recover one, and not recognisable by
|
|
6
8
|
hashing a common password. The salt is `secrets.token_hex(16)`, created on the first index of a graph DB, kept in its
|
|
7
9
|
`meta` table (`redact_salt`) and carried over by a re-index or refresh of that DB; a new DB gets a new salt, so markers
|
|
@@ -20,29 +22,52 @@ import secrets
|
|
|
20
22
|
|
|
21
23
|
MARK = "redacted:hmac:"
|
|
22
24
|
LEGACY_MARK = "redacted:sha256:"
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
_SECRET_LAST = {"password", "passwd", "pwd", "pass", "passphrase", "secret", "dsn"}
|
|
26
|
+
_SECRET_COMPOUNDS = {("api", "key"), ("apikey",), ("access", "key"), ("secret", "key"), ("private", "key"),
|
|
27
|
+
("signing", "key"), ("encryption", "key"), ("client", "secret"), ("webhook", "secret"),
|
|
28
|
+
("auth", "token"), ("api", "token"), ("access", "token"), ("refresh", "token"), ("bearer", "token")}
|
|
29
|
+
_BARE_LAST = {"key", "token"}
|
|
30
|
+
SECRET_WORDS = tuple(sorted({w.upper() for w in _SECRET_LAST} | {"_".join(c).upper() for c in _SECRET_COMPOUNDS}
|
|
31
|
+
| {w.upper() for w in _BARE_LAST}))
|
|
32
|
+
_NON_SECRET_BEFORE = {"primary", "foreign", "sort", "partition", "route", "cache", "idempotency", "remember", "csrf",
|
|
33
|
+
"xsrf", "public", "i18n", "translation", "lookup", "unique", "index", "storage", "prefix"}
|
|
27
34
|
_URL_PW = re.compile(r"(?P<head>\b[A-Za-z][\w+.-]*://[^/\s:@'\"]*:)(?P<pw>[^@/\s'\"]+)(?P<tail>@)")
|
|
28
35
|
_PLACEHOLDER = ("${", "{{", "%(", "<", "$")
|
|
29
36
|
|
|
30
37
|
|
|
31
|
-
def
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
def _words(segment: str) -> list[str]:
|
|
39
|
+
spaced = re.sub(r"([a-z])([A-Z])", r"\1_\2", segment)
|
|
40
|
+
return [w for w in re.split(r"[^A-Za-z0-9]+", spaced.lower()) if w]
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def secret_key(key: str, value=None) -> bool:
|
|
44
|
+
"""Whether a config key / env name holds a credential, from the words of the name (split on `.`, `_`, `-` and
|
|
45
|
+
camelCase). A credential when the last word is password, passwd, pwd, pass, passphrase, secret or dsn, when the
|
|
46
|
+
name ends in an explicit compound (api_key, access_key, signing_key, client_secret, auth_token, refresh_token, ...),
|
|
47
|
+
or for Laravel's `app.key` / `APP_KEY`. A bare `key` or `token` as last word is a credential by default, as it
|
|
48
|
+
was in 0.21.0, and is kept only when the word before it (a dotted segment counts) is a known non-secret one
|
|
49
|
+
(primary, foreign, sort, partition, route, cache, idempotency, remember, csrf, xsrf, public, i18n, translation,
|
|
50
|
+
lookup, unique, index, storage, prefix). The value never decides: a token can be any shape (lowercase words,
|
|
51
|
+
dotted, `key-` prefixed), so `value` is accepted for the callers' signature only. A credential word earlier in the name never counts
|
|
52
|
+
(`AUTH_GUARD`, `AUTH_PASSWORD_BROKER`, `AUTH_PASSWORD_RESET_TOKEN_TABLE`, `try_it_credentials_policy`), and
|
|
53
|
+
`*_PUBLIC_KEY`, `*_KEY_ID`, `*_KEY_PATH`, `*_KEY_FILE` are not credentials."""
|
|
54
|
+
key = str(key)
|
|
55
|
+
words = _words(key.rsplit(".", 1)[-1])
|
|
56
|
+
if not words:
|
|
57
|
+
return False
|
|
58
|
+
all_words = _words(key)
|
|
59
|
+
if all_words == ["app", "key"]:
|
|
40
60
|
return True
|
|
41
|
-
|
|
42
|
-
words = [w for w in re.split(r"[^A-Za-z0-9]+", spaced.upper()) if w]
|
|
43
|
-
if any(w in _EXTRA_WORDS for w in words):
|
|
61
|
+
if words[-1] in _SECRET_LAST or any(tuple(words[-n:]) in _SECRET_COMPOUNDS for n in (1, 2) if len(words) >= n):
|
|
44
62
|
return True
|
|
45
|
-
|
|
63
|
+
if words[-1] not in _BARE_LAST:
|
|
64
|
+
return False
|
|
65
|
+
if len(all_words) > 1 and all_words[-2] in _NON_SECRET_BEFORE:
|
|
66
|
+
return False
|
|
67
|
+
return True
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
looks_secret = secret_key
|
|
46
71
|
|
|
47
72
|
|
|
48
73
|
def is_redacted(v) -> bool:
|
|
@@ -79,7 +104,7 @@ def redact(value, key: str | None, salt: str):
|
|
|
79
104
|
by one, anything else unchanged. Non-strings and placeholders pass through."""
|
|
80
105
|
if not isinstance(value, str):
|
|
81
106
|
return value
|
|
82
|
-
if key is not None and looks_secret(key) and not placeholder(value):
|
|
107
|
+
if key is not None and looks_secret(key, value) and not placeholder(value):
|
|
83
108
|
return marker(value, salt)
|
|
84
109
|
return redact_url(value, salt)
|
|
85
110
|
|
|
@@ -100,7 +125,7 @@ def _holds_secret(d: dict, k: str) -> bool:
|
|
|
100
125
|
if k.lower() in _DIRECT:
|
|
101
126
|
return not _REFERENCE.match(str(d[k]))
|
|
102
127
|
if k in _VALUE_KEYS:
|
|
103
|
-
return any(isinstance(d.get(nk), str) and looks_secret(d[nk]) for nk in _NAME_KEYS)
|
|
128
|
+
return any(isinstance(d.get(nk), str) and looks_secret(d[nk], d.get(k)) for nk in _NAME_KEYS)
|
|
104
129
|
return False
|
|
105
130
|
|
|
106
131
|
|
|
@@ -233,9 +233,20 @@ def file_completeness(discovered: list[str], report: dict) -> dict:
|
|
|
233
233
|
for b in BUCKETS:
|
|
234
234
|
res[b] = len(out[b])
|
|
235
235
|
res["paths"] = {b: v[:MAX_PATHS] for b, v in out.items() if v}
|
|
236
|
+
if out["excluded"]:
|
|
237
|
+
res["exclude_reasons"] = {f: _exclude_reason(f) for f in out["excluded"]}
|
|
236
238
|
return res
|
|
237
239
|
|
|
238
240
|
|
|
241
|
+
def _exclude_reason(path: str) -> str:
|
|
242
|
+
"""Why a discovered file was left out of the graph: tool config, a test file, or a `.cg.yaml` exclude."""
|
|
243
|
+
if _TOOL_FILE.search(path):
|
|
244
|
+
return "tool config"
|
|
245
|
+
if _TEST_NAME.search(path):
|
|
246
|
+
return "test file"
|
|
247
|
+
return ".cg.yaml exclude"
|
|
248
|
+
|
|
249
|
+
|
|
239
250
|
def missing_files(e: dict) -> int:
|
|
240
251
|
"""Discovered files of a language entry that are not in the graph for a reason other than a deliberate exclusion."""
|
|
241
252
|
return sum(e.get(b, 0) for b in ("parse_failed", "skipped_oversize", "unmapped"))
|
|
@@ -308,6 +319,8 @@ def compute(root: str | Path, plugins: dict, scip_imported: bool = False, report
|
|
|
308
319
|
status, reason = _status(lang, st)
|
|
309
320
|
e = {"language": lang, "files": n, "status": status,
|
|
310
321
|
"by_ext": {x: files[x] for x in exts if files[x]}}
|
|
322
|
+
if lang == "typescript" and not any(x in e["by_ext"] for x in (".ts", ".tsx", ".mts", ".cts")):
|
|
323
|
+
e["label"] = "javascript"
|
|
311
324
|
if reason:
|
|
312
325
|
e["reason"] = reason
|
|
313
326
|
if status in ("skipped", "heuristic", "not_indexed"):
|
|
@@ -495,16 +508,22 @@ def blind_spots(cov: dict | None) -> list[dict]:
|
|
|
495
508
|
return list((cov or {}).get("blind_spots") or [])
|
|
496
509
|
|
|
497
510
|
|
|
511
|
+
def _shown_lang(e: dict) -> str:
|
|
512
|
+
"""Display name. A TypeScript-plugin entry with no .ts/.tsx/.mts/.cts files reads as javascript; JSON keeps `language`."""
|
|
513
|
+
return e.get("label") or e["language"]
|
|
514
|
+
|
|
515
|
+
|
|
498
516
|
def _entry_text(e: dict) -> str:
|
|
499
517
|
"""'php 18 exact' / 'python 4 discovered, 2 indexed (exact parser): 1 parse failed, 1 unmapped' /
|
|
500
|
-
'
|
|
518
|
+
'javascript 12 discovered, 2 indexed (exact parser): 9 unmapped, 1 excluded'."""
|
|
501
519
|
pe = e.get("parsed_with_errors")
|
|
502
520
|
errs = f", {pe} parsed with syntax errors" if pe else ""
|
|
521
|
+
name = _shown_lang(e)
|
|
503
522
|
if e.get("files_complete") is False:
|
|
504
|
-
parts = [f"{e[b]} {BUCKET_SHORT[b]}" for b in
|
|
505
|
-
return (f"{
|
|
523
|
+
parts = [f"{e[b]} {BUCKET_SHORT[b]}" for b in BUCKETS if e.get(b)]
|
|
524
|
+
return (f"{name} {e['files']} discovered, {e['indexed']} indexed ({e['status'].replace('_', ' ')} parser)"
|
|
506
525
|
+ (": " + ", ".join(parts) if parts else "") + errs)
|
|
507
|
-
return f"{
|
|
526
|
+
return f"{name} {e['files']} {e['status'].replace('_', ' ')}{errs}"
|
|
508
527
|
|
|
509
528
|
|
|
510
529
|
def realtime_unresolved_lines(e: dict, indent: str = " ") -> list[str]:
|
|
@@ -579,11 +598,16 @@ def _paths_lines(e: dict, all_files: bool, indent: str = " ") -> list[str]:
|
|
|
579
598
|
out = []
|
|
580
599
|
for b in BUCKETS:
|
|
581
600
|
ps = (e.get("paths") or {}).get(b) or []
|
|
582
|
-
if not ps
|
|
601
|
+
if not ps:
|
|
583
602
|
continue
|
|
584
603
|
show = ps if all_files else ps[:SHOW_PATHS]
|
|
585
604
|
more = e.get(b, len(ps)) - len(show)
|
|
586
|
-
|
|
605
|
+
if b == "excluded":
|
|
606
|
+
reasons = e.get("exclude_reasons") or {}
|
|
607
|
+
body = ", ".join(f"{p} ({reasons.get(p) or _exclude_reason(p)})" for p in show)
|
|
608
|
+
else:
|
|
609
|
+
body = ", ".join(show)
|
|
610
|
+
out.append(f"{indent}{BUCKET_SHORT[b]}: " + body + (f" … +{more} more (--all-files)" if more > 0 else ""))
|
|
587
611
|
return out
|
|
588
612
|
|
|
589
613
|
|
|
@@ -720,11 +744,12 @@ def render(covs: dict[str, dict | None], all_files: bool = False) -> str:
|
|
|
720
744
|
for e in gaps(cov):
|
|
721
745
|
any_gap = True
|
|
722
746
|
exts = ", ".join(f"{k} {v}" for k, v in sorted(e["by_ext"].items()))
|
|
747
|
+
shown = _shown_lang(e)
|
|
723
748
|
if e.get("files_complete") is False:
|
|
724
749
|
parts = [f"{e[b]} {BUCKET_SHORT[b]}" for b in BUCKETS if e.get(b)]
|
|
725
|
-
line = f" {
|
|
750
|
+
line = f" {shown}: {e['files']} files ({exts}) {e['indexed']} indexed, " + ", ".join(parts)
|
|
726
751
|
else:
|
|
727
|
-
line = f" {
|
|
752
|
+
line = f" {shown}: {e['files']} files ({exts}) {e['status'].replace('_', ' ')}"
|
|
728
753
|
if e.get("reason"):
|
|
729
754
|
line += f": {e['reason']}"
|
|
730
755
|
out.append(line)
|
|
@@ -795,7 +820,7 @@ def note(covs: dict[str, dict | None]) -> str:
|
|
|
795
820
|
for e in gaps(c):
|
|
796
821
|
what = (f"{e['indexed']} of {e['files']} files indexed" if e.get("files_complete") is False
|
|
797
822
|
else f"{e['files']} files, {e['status'].replace('_', ' ')}")
|
|
798
|
-
bad.append(f"{e
|
|
823
|
+
bad.append(f"{_shown_lang(e)} ({what}{', ' + r if len(covs) > 1 else ''})")
|
|
799
824
|
bs = [b for c in covs.values() for b in blind_spots(c)]
|
|
800
825
|
bs_txt = f"; blind spots: {_bs_count(bs)} (see coverage)" if bs else ""
|
|
801
826
|
nerr = sum(e.get("syntax_error_files", 0) for c in covs.values() for e in (c or {}).get("languages", []))
|
|
@@ -956,6 +981,18 @@ def completeness_for(store, node_ids=None, categories=("route", "handler"), whol
|
|
|
956
981
|
categories=categories, ids=set(node_ids), files=sc["files"], **kw)
|
|
957
982
|
|
|
958
983
|
|
|
984
|
+
def _unsupported_text(uns: dict) -> str:
|
|
985
|
+
"""`unsupported: sh 3`. A single-repo DB drops a `shop/sh` prefix; a combined graph keeps `api/sh`."""
|
|
986
|
+
keys = list(uns)
|
|
987
|
+
prefixes = {k.partition("/")[0] for k in keys if "/" in k}
|
|
988
|
+
drop = len(prefixes) <= 1
|
|
989
|
+
parts = []
|
|
990
|
+
for k, v in sorted(uns.items()):
|
|
991
|
+
label = k.partition("/")[2] if drop and "/" in k else k
|
|
992
|
+
parts.append(f"{label} {v}")
|
|
993
|
+
return "unsupported: " + ", ".join(parts)
|
|
994
|
+
|
|
995
|
+
|
|
959
996
|
def possibly_more(comp: dict) -> str:
|
|
960
997
|
"""'1 unmodelled route registration, 2 Python files not indexed' for an incomplete answer, '' when complete."""
|
|
961
998
|
if comp.get("complete"):
|
|
@@ -990,7 +1027,7 @@ def possibly_more(comp: dict) -> str:
|
|
|
990
1027
|
parts.append(f"{len(se)} file{'s' if len(se) != 1 else ''} with syntax errors ({x['file']}{pos}"
|
|
991
1028
|
+ (f" +{len(se) - 1}" if len(se) > 1 else "") + ")")
|
|
992
1029
|
if comp.get("unsupported"):
|
|
993
|
-
parts.append(
|
|
1030
|
+
parts.append(_unsupported_text(comp["unsupported"]))
|
|
994
1031
|
if comp.get("recorded") is False:
|
|
995
1032
|
parts.append("coverage not recorded")
|
|
996
1033
|
return ", ".join(parts)
|
|
@@ -292,8 +292,35 @@ def read_spring_datasources(root: Path) -> list:
|
|
|
292
292
|
out.append(fact)
|
|
293
293
|
return out
|
|
294
294
|
|
|
295
|
+
|
|
296
|
+
CONNECTION_EDGE_KINDS = ("READS_TABLE", "WRITES_TABLE", "READS_COLUMN", "WRITES_COLUMN", "MENTIONS_COLUMN")
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
def table_connections(builder) -> int:
|
|
300
|
+
"""`attrs.connections` of a table node: `{connection: edge count}` over its table / column edges that carry
|
|
301
|
+
`attrs.connection` (most used first). One table name used on several connections stays one node. Not tied to an ORM:
|
|
302
|
+
a plugin only has to set `attrs.connection` on its table / column edges."""
|
|
303
|
+
counts: dict[str, dict[str, int]] = {}
|
|
304
|
+
for e in builder.edges.values():
|
|
305
|
+
conn = (e.attrs or {}).get("connection")
|
|
306
|
+
if e.kind not in CONNECTION_EDGE_KINDS or not conn:
|
|
307
|
+
continue
|
|
308
|
+
key = e.dst.split(":", 1)[1]
|
|
309
|
+
tid = f"table:{key}" if e.dst.startswith("table:") else f"table:{key.rsplit('.', 1)[0]}"
|
|
310
|
+
counts.setdefault(tid, {})
|
|
311
|
+
counts[tid][conn] = counts[tid].get(conn, 0) + 1
|
|
312
|
+
n = 0
|
|
313
|
+
for tid, c in counts.items():
|
|
314
|
+
node = builder.nodes.get(tid)
|
|
315
|
+
if node is not None:
|
|
316
|
+
node.attrs["connections"] = dict(sorted(c.items(), key=lambda kv: (-kv[1], kv[0])))
|
|
317
|
+
n += 1
|
|
318
|
+
return n
|
|
319
|
+
|
|
320
|
+
|
|
295
321
|
def attach(builder, root: Path) -> dict:
|
|
296
322
|
root = Path(root)
|
|
323
|
+
table_connections(builder)
|
|
297
324
|
envs = {n.id[len("env:"):]: n for n in builder.nodes.values() if n.kind == "env"}
|
|
298
325
|
conns = [n for n in builder.nodes.values() if n.kind == "connection"]
|
|
299
326
|
# Spring datasources before the empty-check so a repo with only application*.properties still indexes (#41)
|
|
@@ -646,6 +673,16 @@ def attach(builder, root: Path) -> dict:
|
|
|
646
673
|
(builder.nodes[nid].attrs or {}).get("confidence") or "resolved",
|
|
647
674
|
op="table", via="laravel connection")
|
|
648
675
|
st["tables"] = st.get("tables", 0) + 1
|
|
676
|
+
# a table used on several connections: one CONNECTS_TO per connection that maps to a system, not only the first
|
|
677
|
+
for n in builder.nodes.values():
|
|
678
|
+
if n.kind != "table":
|
|
679
|
+
continue
|
|
680
|
+
for cname in (n.attrs or {}).get("connections") or {}:
|
|
681
|
+
nid = conn_ext.get(f"connection:{cname}")
|
|
682
|
+
if nid:
|
|
683
|
+
builder.add_edge(n.id, nid, "CONNECTS_TO", n.file, n.line,
|
|
684
|
+
(builder.nodes[nid].attrs or {}).get("confidence") or "resolved",
|
|
685
|
+
op="table", via=f"connection {cname}")
|
|
649
686
|
|
|
650
687
|
# ---- ORM tables without a datasource block: attach to the sole SQL system of the project (#41 step 2)
|
|
651
688
|
# Immich (Kysely + DB_URL), Nest TypeORM (@Entity + DATABASE_URL) when no DataSource fact named them.
|
|
@@ -161,7 +161,7 @@ def has_type(host: str) -> bool:
|
|
|
161
161
|
|
|
162
162
|
def config_path(host: str, scope: str, root: Path) -> Path:
|
|
163
163
|
"""Filesystem path for a host and scope. Claude Code global has no file cg edits."""
|
|
164
|
-
root =
|
|
164
|
+
root = _child(root)
|
|
165
165
|
if host == "claude" and scope == "global":
|
|
166
166
|
raise InstallError("Claude Code global scope is changed with the claude CLI, not a file")
|
|
167
167
|
if host == "claude-desktop" and scope == "project":
|