modwire 9.2.3__tar.gz → 9.2.4__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.
Files changed (371) hide show
  1. {modwire-9.2.3 → modwire-9.2.4}/.dev/modwire.egg-info/SOURCES.txt +2 -1
  2. {modwire-9.2.3 → modwire-9.2.4}/PKG-INFO +1 -1
  3. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/extraction/dependency/application.py +5 -3
  4. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/extraction/dependency/domain.py +4 -2
  5. modwire-9.2.3/src/modwire/extraction/dependency/services/suffix_index.py → modwire-9.2.4/src/modwire/extraction/dependency/services/import_identity_index.py +7 -2
  6. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/extraction/dependency/services/import_resolver.py +37 -14
  7. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/extraction/extractors/application.py +7 -1
  8. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/extraction/extractors/domain.py +6 -0
  9. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/extraction/extractors/services/php_extractor.py +5 -0
  10. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/extraction/extractors/services/python_extractor.py +9 -0
  11. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/extraction/extractors/services/type_script_extractor.py +5 -0
  12. modwire-9.2.4/tests/extraction/cache_benchmark/benchmark_process_timeout.py +6 -0
  13. {modwire-9.2.3 → modwire-9.2.4}/tests/extraction/cache_benchmark/run.py +1 -7
  14. {modwire-9.2.3 → modwire-9.2.4}/tests/extraction/dependency/test_02_invariants.py +74 -3
  15. {modwire-9.2.3 → modwire-9.2.4}/.github/workflows/ci.yml +0 -0
  16. {modwire-9.2.3 → modwire-9.2.4}/.github/workflows/release.yml +0 -0
  17. {modwire-9.2.3 → modwire-9.2.4}/.gitignore +0 -0
  18. {modwire-9.2.3 → modwire-9.2.4}/AGENTS.md +0 -0
  19. {modwire-9.2.3 → modwire-9.2.4}/LICENSE +0 -0
  20. {modwire-9.2.3 → modwire-9.2.4}/MANIFEST.in +0 -0
  21. {modwire-9.2.3 → modwire-9.2.4}/Makefile +0 -0
  22. {modwire-9.2.3 → modwire-9.2.4}/README.md +0 -0
  23. {modwire-9.2.3 → modwire-9.2.4}/docs/target-language-ownership.md +0 -0
  24. {modwire-9.2.3 → modwire-9.2.4}/pyproject.toml +0 -0
  25. {modwire-9.2.3 → modwire-9.2.4}/scripts/check_extractors.py +0 -0
  26. {modwire-9.2.3 → modwire-9.2.4}/scripts/generate_docs.py +0 -0
  27. {modwire-9.2.3 → modwire-9.2.4}/scripts/verify_consumer.py +0 -0
  28. {modwire-9.2.3 → modwire-9.2.4}/setup.cfg +0 -0
  29. {modwire-9.2.3 → modwire-9.2.4}/setup.py +0 -0
  30. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/__init__.py +0 -0
  31. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/__main__.py +0 -0
  32. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/application.py +0 -0
  33. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/__init__.py +0 -0
  34. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/boundaries/__init__.py +0 -0
  35. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/boundaries/application.py +0 -0
  36. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/boundaries/domain.py +0 -0
  37. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/boundaries/models/__init__.py +0 -0
  38. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/boundaries/models/edge_rule_violation.py +0 -0
  39. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/boundaries/models/flow_report.py +0 -0
  40. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/boundaries/models/flow_violation.py +0 -0
  41. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/boundaries/models/types.py +0 -0
  42. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/boundaries/services/__init__.py +0 -0
  43. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/boundaries/services/backward_flow_analyzer.py +0 -0
  44. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/boundaries/services/boundaries_flow_analyzer.py +0 -0
  45. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/boundaries/services/module_boundary_analyzer.py +0 -0
  46. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/boundaries/services/no_cycles_flow_analyzer.py +0 -0
  47. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/boundaries/services/no_reentry_flow_analyzer.py +0 -0
  48. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/config/__init__.py +0 -0
  49. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/config/application.py +0 -0
  50. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/config/models/__init__.py +0 -0
  51. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/config/models/architecture_config.py +0 -0
  52. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/config/models/boundaries_config.py +0 -0
  53. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/config/models/boundary_rule.py +0 -0
  54. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/config/models/configuration_value.py +0 -0
  55. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/config/models/flow_realm.py +0 -0
  56. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/config/models/flow_rules.py +0 -0
  57. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/config/models/shape_config.py +0 -0
  58. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/config/models/shape_realm.py +0 -0
  59. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/config/models/shape_rules.py +0 -0
  60. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/config/models/tag_rule.py +0 -0
  61. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/facade.py +0 -0
  62. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/insights/__init__.py +0 -0
  63. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/insights/application.py +0 -0
  64. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/insights/domain.py +0 -0
  65. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/insights/models/__init__.py +0 -0
  66. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/insights/models/callable_report_entry.py +0 -0
  67. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/insights/models/callables_report.py +0 -0
  68. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/insights/models/clusters_report.py +0 -0
  69. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/insights/models/clusters_report_item.py +0 -0
  70. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/insights/models/coherence_report.py +0 -0
  71. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/insights/models/exports_report.py +0 -0
  72. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/insights/models/exports_report_item.py +0 -0
  73. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/insights/models/hotspots_report.py +0 -0
  74. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/insights/models/hotspots_report_item.py +0 -0
  75. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/insights/models/insight_report.py +0 -0
  76. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/insights/services/__init__.py +0 -0
  77. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/insights/services/callables_reporter.py +0 -0
  78. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/insights/services/clusters_reporter.py +0 -0
  79. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/insights/services/coherence_reporter.py +0 -0
  80. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/insights/services/exports_reporter.py +0 -0
  81. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/insights/services/hotspots_reporter.py +0 -0
  82. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/insights/services/insight_report_field_map.py +0 -0
  83. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/map/__init__.py +0 -0
  84. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/map/application.py +0 -0
  85. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/map/domain.py +0 -0
  86. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/map/models/__init__.py +0 -0
  87. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/map/models/architecture_map.py +0 -0
  88. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/map/models/architecture_realm.py +0 -0
  89. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/map/models/tag_map.py +0 -0
  90. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/map/models/tag_match.py +0 -0
  91. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/map/services/__init__.py +0 -0
  92. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/map/services/architecture_map_loader.py +0 -0
  93. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/map/services/tag_matcher.py +0 -0
  94. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/report/__init__.py +0 -0
  95. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/report/application.py +0 -0
  96. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/report/domain.py +0 -0
  97. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/report/models/__init__.py +0 -0
  98. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/report/models/architecture_group.py +0 -0
  99. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/report/models/map_report.py +0 -0
  100. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/report/models/report_catalog.py +0 -0
  101. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/report/models/report_descriptor.py +0 -0
  102. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/report/models/report_item.py +0 -0
  103. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/report/models/report_metadata.py +0 -0
  104. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/report/models/report_node.py +0 -0
  105. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/report/models/report_section.py +0 -0
  106. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/report/services/__init__.py +0 -0
  107. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/report/services/map_report_collector.py +0 -0
  108. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/shape/__init__.py +0 -0
  109. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/shape/application.py +0 -0
  110. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/shape/domain.py +0 -0
  111. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/shape/models/__init__.py +0 -0
  112. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/shape/models/shape_realm_architecture_map.py +0 -0
  113. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/shape/models/shape_report.py +0 -0
  114. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/shape/models/shape_violation.py +0 -0
  115. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/shape/services/__init__.py +0 -0
  116. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/shape/services/abstract_class_resolver.py +0 -0
  117. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/shape/services/callable_resolver.py +0 -0
  118. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/shape/services/class_resolver.py +0 -0
  119. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/shape/services/file_resolver.py +0 -0
  120. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/shape/services/import_resolver.py +0 -0
  121. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/shape/services/property_resolver.py +0 -0
  122. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/shape/services/signature_resolver.py +0 -0
  123. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/architecture/shape/services/symbol_resolver.py +0 -0
  124. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/autowiring.py +0 -0
  125. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/__init__.py +0 -0
  126. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/cache/__init__.py +0 -0
  127. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/cache/application.py +0 -0
  128. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/cache/domain.py +0 -0
  129. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/cache/models/__init__.py +0 -0
  130. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/cache/models/cache_entry.py +0 -0
  131. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/cache/models/cache_key.py +0 -0
  132. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/cache/models/cache_options.py +0 -0
  133. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/cache/models/cache_outcome.py +0 -0
  134. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/cache/models/cache_plan.py +0 -0
  135. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/cache/models/cache_stage.py +0 -0
  136. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/cache/models/cache_storage_state.py +0 -0
  137. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/cache/models/cached_result.py +0 -0
  138. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/cache/models/source_cache_entry.py +0 -0
  139. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/cache/services/__init__.py +0 -0
  140. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/cache/services/cache_codec.py +0 -0
  141. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/cache/services/cache_identity.py +0 -0
  142. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/cache/services/filesystem_cache_storage.py +0 -0
  143. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/documentation/__init__.py +0 -0
  144. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/documentation/application.py +0 -0
  145. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/documentation/services/__init__.py +0 -0
  146. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/documentation/services/documentation_generator.py +0 -0
  147. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/facade.py +0 -0
  148. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/initialization/__init__.py +0 -0
  149. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/initialization/application.py +0 -0
  150. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/initialization/models/__init__.py +0 -0
  151. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/initialization/models/initialization_result.py +0 -0
  152. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/initialization/services/__init__.py +0 -0
  153. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/initialization/services/initialization_service.py +0 -0
  154. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/pipeline/__init__.py +0 -0
  155. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/pipeline/application.py +0 -0
  156. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/pipeline/domain.py +0 -0
  157. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/pipeline/models/__init__.py +0 -0
  158. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/pipeline/models/command_request.py +0 -0
  159. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/pipeline/models/extractor_batch_input.py +0 -0
  160. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/pipeline/models/extractor_command_input.py +0 -0
  161. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/pipeline/models/extractor_source_input.py +0 -0
  162. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/pipeline/models/report_pipeline_context.py +0 -0
  163. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/pipeline/models/scan_policy.py +0 -0
  164. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/pipeline/models/source_entry.py +0 -0
  165. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/pipeline/models/source_inventory.py +0 -0
  166. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/pipeline/services/__init__.py +0 -0
  167. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/pipeline/services/batch_source_reader.py +0 -0
  168. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/pipeline/services/callables_insight.py +0 -0
  169. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/pipeline/services/clusters_insight.py +0 -0
  170. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/pipeline/services/coherence_insight.py +0 -0
  171. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/pipeline/services/command_line.py +0 -0
  172. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/pipeline/services/configuration_loader.py +0 -0
  173. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/pipeline/services/extractor_command.py +0 -0
  174. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/pipeline/services/flow_violations.py +0 -0
  175. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/pipeline/services/hotspots_insight.py +0 -0
  176. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/pipeline/services/map_tree.py +0 -0
  177. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/pipeline/services/output_console.py +0 -0
  178. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/pipeline/services/shape_violations.py +0 -0
  179. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/pipeline/services/success.py +0 -0
  180. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/pipeline/services/unknown_files_warning.py +0 -0
  181. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/pipeline/services/unused_exports_insight.py +0 -0
  182. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/resources/__init__.py +0 -0
  183. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/resources/application.py +0 -0
  184. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/resources/models/__init__.py +0 -0
  185. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/resources/models/defaults.py +0 -0
  186. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/resources/models/init_asset.py +0 -0
  187. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/resources/templates/AGENTS.md +0 -0
  188. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/resources/templates/ARCHITECTURE.md +0 -0
  189. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/resources/templates/INDEX.md +0 -0
  190. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/resources/templates/MODWIRE.md +0 -0
  191. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/resources/templates/RULES.md +0 -0
  192. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/resources/templates/TESTING.md +0 -0
  193. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/resources/templates/WORKFLOW.md +0 -0
  194. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/cli/resources/templates/architecture.yaml +0 -0
  195. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/extraction/__init__.py +0 -0
  196. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/extraction/dependency/__init__.py +0 -0
  197. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/extraction/dependency/services/__init__.py +0 -0
  198. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/extraction/dependency/services/graph_builder.py +0 -0
  199. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/extraction/extractors/__init__.py +0 -0
  200. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/extraction/extractors/models/__init__.py +0 -0
  201. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/extraction/extractors/models/batch_config.py +0 -0
  202. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/extraction/extractors/models/extraction_request.py +0 -0
  203. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/extraction/extractors/models/extractor_resource.py +0 -0
  204. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/extraction/extractors/models/extractor_runtime.py +0 -0
  205. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/extraction/extractors/models/python_call_context.py +0 -0
  206. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/extraction/extractors/resources/__init__.py +0 -0
  207. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/extraction/extractors/resources/php/build.php +0 -0
  208. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/extraction/extractors/resources/php/build.py +0 -0
  209. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/extraction/extractors/resources/php/composer.json +0 -0
  210. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/extraction/extractors/resources/php/composer.lock +0 -0
  211. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/extraction/extractors/resources/php/script.php +0 -0
  212. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/extraction/extractors/resources/php/script.src.php +0 -0
  213. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/extraction/extractors/resources/python/__init__.py +0 -0
  214. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/extraction/extractors/resources/python/script.py +0 -0
  215. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/extraction/extractors/resources/typescript/build.mjs +0 -0
  216. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/extraction/extractors/resources/typescript/build.py +0 -0
  217. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/extraction/extractors/resources/typescript/package-lock.json +0 -0
  218. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/extraction/extractors/resources/typescript/package.json +0 -0
  219. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/extraction/extractors/resources/typescript/script.js +0 -0
  220. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/extraction/extractors/resources/typescript/script.ts +0 -0
  221. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/extraction/extractors/resources/typescript/tsconfig.json +0 -0
  222. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/extraction/extractors/services/__init__.py +0 -0
  223. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/extraction/extractors/services/python_call_reader.py +0 -0
  224. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/extraction/extractors/services/python_syntax_parser.py +0 -0
  225. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/extraction/facade.py +0 -0
  226. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/py.typed +0 -0
  227. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/shared/__init__.py +0 -0
  228. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/shared/code/__init__.py +0 -0
  229. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/shared/code/application.py +0 -0
  230. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/shared/code/domain.py +0 -0
  231. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/shared/code/models/__init__.py +0 -0
  232. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/shared/code/models/code_map.py +0 -0
  233. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/shared/code/models/code_package.py +0 -0
  234. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/shared/code/models/dependency_edge_result.py +0 -0
  235. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/shared/code/models/dependency_graph.py +0 -0
  236. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/shared/code/models/dependency_node_result.py +0 -0
  237. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/shared/code/models/duplicate_identity_error.py +0 -0
  238. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/shared/code/models/edge.py +0 -0
  239. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/shared/code/models/edge_resolution.py +0 -0
  240. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/shared/code/models/identity.py +0 -0
  241. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/shared/code/models/node.py +0 -0
  242. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/shared/code/models/query_builder.py +0 -0
  243. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/shared/code/models/query_types.py +0 -0
  244. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/shared/code/models/queryable_code_map.py +0 -0
  245. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/shared/code/models/source_abstract_class.py +0 -0
  246. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/shared/code/models/source_call.py +0 -0
  247. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/shared/code/models/source_callable.py +0 -0
  248. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/shared/code/models/source_callable_symbol.py +0 -0
  249. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/shared/code/models/source_class.py +0 -0
  250. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/shared/code/models/source_class_method.py +0 -0
  251. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/shared/code/models/source_class_property.py +0 -0
  252. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/shared/code/models/source_export.py +0 -0
  253. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/shared/code/models/source_extraction.py +0 -0
  254. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/shared/code/models/source_file.py +0 -0
  255. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/shared/code/models/source_file_result.py +0 -0
  256. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/shared/code/models/source_function.py +0 -0
  257. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/shared/code/models/source_import.py +0 -0
  258. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/shared/code/models/source_imported_symbol.py +0 -0
  259. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/shared/code/models/source_interface.py +0 -0
  260. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/shared/code/models/source_item_result.py +0 -0
  261. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/shared/code/models/source_parameter.py +0 -0
  262. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/shared/code/models/source_signature.py +0 -0
  263. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/shared/code/models/source_symbol.py +0 -0
  264. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/shared/code/models/source_type.py +0 -0
  265. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/shared/code/models/source_value.py +0 -0
  266. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/shared/code/models/source_value_scope.py +0 -0
  267. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/shared/code/models/types.py +0 -0
  268. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/shared/code/services/__init__.py +0 -0
  269. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/shared/code/services/glob_path_matcher.py +0 -0
  270. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/shared/code/services/identity_resolver.py +0 -0
  271. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/shared/values/__init__.py +0 -0
  272. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/shared/values/models/__init__.py +0 -0
  273. {modwire-9.2.3 → modwire-9.2.4}/src/modwire/shared/values/models/value_model.py +0 -0
  274. {modwire-9.2.3 → modwire-9.2.4}/tests/__init__.py +0 -0
  275. {modwire-9.2.3 → modwire-9.2.4}/tests/application/__init__.py +0 -0
  276. {modwire-9.2.3 → modwire-9.2.4}/tests/application/base_test.py +0 -0
  277. {modwire-9.2.3 → modwire-9.2.4}/tests/application/test_01_attacks.py +0 -0
  278. {modwire-9.2.3 → modwire-9.2.4}/tests/application/test_06_happy_path.py +0 -0
  279. {modwire-9.2.3 → modwire-9.2.4}/tests/application/test_07_cache.py +0 -0
  280. {modwire-9.2.3 → modwire-9.2.4}/tests/architecture/__init__.py +0 -0
  281. {modwire-9.2.3 → modwire-9.2.4}/tests/architecture/base_test.py +0 -0
  282. {modwire-9.2.3 → modwire-9.2.4}/tests/architecture/boundaries/__init__.py +0 -0
  283. {modwire-9.2.3 → modwire-9.2.4}/tests/architecture/boundaries/base_test.py +0 -0
  284. {modwire-9.2.3 → modwire-9.2.4}/tests/architecture/boundaries/test_01_attacks.py +0 -0
  285. {modwire-9.2.3 → modwire-9.2.4}/tests/architecture/boundaries/test_02_invariants.py +0 -0
  286. {modwire-9.2.3 → modwire-9.2.4}/tests/architecture/boundaries/test_03_public_api.py +0 -0
  287. {modwire-9.2.3 → modwire-9.2.4}/tests/architecture/boundaries/test_04_paths.py +0 -0
  288. {modwire-9.2.3 → modwire-9.2.4}/tests/architecture/config/__init__.py +0 -0
  289. {modwire-9.2.3 → modwire-9.2.4}/tests/architecture/config/test_01_attacks.py +0 -0
  290. {modwire-9.2.3 → modwire-9.2.4}/tests/architecture/config/test_02_invariants.py +0 -0
  291. {modwire-9.2.3 → modwire-9.2.4}/tests/architecture/insights/__init__.py +0 -0
  292. {modwire-9.2.3 → modwire-9.2.4}/tests/architecture/insights/base_test.py +0 -0
  293. {modwire-9.2.3 → modwire-9.2.4}/tests/architecture/insights/test_02_invariants.py +0 -0
  294. {modwire-9.2.3 → modwire-9.2.4}/tests/architecture/map/__init__.py +0 -0
  295. {modwire-9.2.3 → modwire-9.2.4}/tests/architecture/map/test_02_patterns.py +0 -0
  296. {modwire-9.2.3 → modwire-9.2.4}/tests/architecture/report/__init__.py +0 -0
  297. {modwire-9.2.3 → modwire-9.2.4}/tests/architecture/report/test_02_invariants.py +0 -0
  298. {modwire-9.2.3 → modwire-9.2.4}/tests/architecture/report_benchmark/__init__.py +0 -0
  299. {modwire-9.2.3 → modwire-9.2.4}/tests/architecture/report_benchmark/benchmark_process_timeout.py +0 -0
  300. {modwire-9.2.3 → modwire-9.2.4}/tests/architecture/report_benchmark/run.py +0 -0
  301. {modwire-9.2.3 → modwire-9.2.4}/tests/architecture/shape/__init__.py +0 -0
  302. {modwire-9.2.3 → modwire-9.2.4}/tests/architecture/shape/base_test.py +0 -0
  303. {modwire-9.2.3 → modwire-9.2.4}/tests/architecture/shape/test_01_limits.py +0 -0
  304. {modwire-9.2.3 → modwire-9.2.4}/tests/architecture/shape/test_02_invariants.py +0 -0
  305. {modwire-9.2.3 → modwire-9.2.4}/tests/cli/__init__.py +0 -0
  306. {modwire-9.2.3 → modwire-9.2.4}/tests/cli/base_test.py +0 -0
  307. {modwire-9.2.3 → modwire-9.2.4}/tests/cli/documentation/__init__.py +0 -0
  308. {modwire-9.2.3 → modwire-9.2.4}/tests/cli/documentation/test_02_invariants.py +0 -0
  309. {modwire-9.2.3 → modwire-9.2.4}/tests/cli/initialization/__init__.py +0 -0
  310. {modwire-9.2.3 → modwire-9.2.4}/tests/cli/initialization/test_01_attacks.py +0 -0
  311. {modwire-9.2.3 → modwire-9.2.4}/tests/cli/initialization/test_02_invariants.py +0 -0
  312. {modwire-9.2.3 → modwire-9.2.4}/tests/cli/initialization/test_03_interruption.py +0 -0
  313. {modwire-9.2.3 → modwire-9.2.4}/tests/cli/initialization/test_04_cleanup.py +0 -0
  314. {modwire-9.2.3 → modwire-9.2.4}/tests/cli/initialization/test_05_recovery.py +0 -0
  315. {modwire-9.2.3 → modwire-9.2.4}/tests/cli/pipeline/__init__.py +0 -0
  316. {modwire-9.2.3 → modwire-9.2.4}/tests/cli/pipeline/base_test.py +0 -0
  317. {modwire-9.2.3 → modwire-9.2.4}/tests/cli/pipeline/test_01_attacks.py +0 -0
  318. {modwire-9.2.3 → modwire-9.2.4}/tests/cli/pipeline/test_02_invariants.py +0 -0
  319. {modwire-9.2.3 → modwire-9.2.4}/tests/cli/pipeline/test_03_interruption.py +0 -0
  320. {modwire-9.2.3 → modwire-9.2.4}/tests/cli/pipeline/test_04_command_transport.py +0 -0
  321. {modwire-9.2.3 → modwire-9.2.4}/tests/cli/pipeline/test_05_recovery.py +0 -0
  322. {modwire-9.2.3 → modwire-9.2.4}/tests/cli/pipeline/test_06_happy_path.py +0 -0
  323. {modwire-9.2.3 → modwire-9.2.4}/tests/conftest.py +0 -0
  324. {modwire-9.2.3 → modwire-9.2.4}/tests/extraction/__init__.py +0 -0
  325. {modwire-9.2.3 → modwire-9.2.4}/tests/extraction/base_test.py +0 -0
  326. {modwire-9.2.3 → modwire-9.2.4}/tests/extraction/big_projects/__init__.py +0 -0
  327. {modwire-9.2.3 → modwire-9.2.4}/tests/extraction/big_projects/project.py +0 -0
  328. {modwire-9.2.3 → modwire-9.2.4}/tests/extraction/big_projects/projects.json +0 -0
  329. {modwire-9.2.3 → modwire-9.2.4}/tests/extraction/big_projects/resolution_results.json +0 -0
  330. {modwire-9.2.3 → modwire-9.2.4}/tests/extraction/big_projects/results.json +0 -0
  331. {modwire-9.2.3 → modwire-9.2.4}/tests/extraction/big_projects/run.py +0 -0
  332. {modwire-9.2.3 → modwire-9.2.4}/tests/extraction/cache_benchmark/__init__.py +0 -0
  333. {modwire-9.2.3 → modwire-9.2.4}/tests/extraction/dependency/__init__.py +0 -0
  334. {modwire-9.2.3 → modwire-9.2.4}/tests/extraction/extractors/__init__.py +0 -0
  335. {modwire-9.2.3 → modwire-9.2.4}/tests/extraction/extractors/test_01_attacks.py +0 -0
  336. {modwire-9.2.3 → modwire-9.2.4}/tests/extraction/extractors/test_02_invariants.py +0 -0
  337. {modwire-9.2.3 → modwire-9.2.4}/tests/extraction/extractors/test_03_native_symbols.py +0 -0
  338. {modwire-9.2.3 → modwire-9.2.4}/tests/extraction/scan_benchmark/__init__.py +0 -0
  339. {modwire-9.2.3 → modwire-9.2.4}/tests/extraction/scan_benchmark/prepare.py +0 -0
  340. {modwire-9.2.3 → modwire-9.2.4}/tests/extraction/scan_benchmark/results.json +0 -0
  341. {modwire-9.2.3 → modwire-9.2.4}/tests/extraction/scan_benchmark/run.py +0 -0
  342. {modwire-9.2.3 → modwire-9.2.4}/tests/fixtures/languages/php/ignored/example_generated.php +0 -0
  343. {modwire-9.2.3 → modwire-9.2.4}/tests/fixtures/languages/php/src/example_application/example_actions/example_action.php +0 -0
  344. {modwire-9.2.3 → modwire-9.2.4}/tests/fixtures/languages/php/src/example_domain/example_model/example_record.php +0 -0
  345. {modwire-9.2.3 → modwire-9.2.4}/tests/fixtures/languages/php/src/example_domain/example_services/example_policy.php +0 -0
  346. {modwire-9.2.3 → modwire-9.2.4}/tests/fixtures/languages/php/src/example_interfaces/example_http/example_controller.php +0 -0
  347. {modwire-9.2.3 → modwire-9.2.4}/tests/fixtures/languages/python/ignored/example_generated.py +0 -0
  348. {modwire-9.2.3 → modwire-9.2.4}/tests/fixtures/languages/python/src/example_application/example_actions/example_action.py +0 -0
  349. {modwire-9.2.3 → modwire-9.2.4}/tests/fixtures/languages/python/src/example_domain/example_model/example_record.py +0 -0
  350. {modwire-9.2.3 → modwire-9.2.4}/tests/fixtures/languages/python/src/example_domain/example_services/example_policy.py +0 -0
  351. {modwire-9.2.3 → modwire-9.2.4}/tests/fixtures/languages/python/src/example_interfaces/example_http/example_controller.py +0 -0
  352. {modwire-9.2.3 → modwire-9.2.4}/tests/fixtures/languages/typescript/ignored/example_generated.ts +0 -0
  353. {modwire-9.2.3 → modwire-9.2.4}/tests/fixtures/languages/typescript/src/example_application/example_actions/example_action.ts +0 -0
  354. {modwire-9.2.3 → modwire-9.2.4}/tests/fixtures/languages/typescript/src/example_domain/example_model/example_record.ts +0 -0
  355. {modwire-9.2.3 → modwire-9.2.4}/tests/fixtures/languages/typescript/src/example_domain/example_model/example_view.tsx +0 -0
  356. {modwire-9.2.3 → modwire-9.2.4}/tests/fixtures/languages/typescript/src/example_domain/example_services/example_audit.js +0 -0
  357. {modwire-9.2.3 → modwire-9.2.4}/tests/fixtures/languages/typescript/src/example_domain/example_services/example_callables.ts +0 -0
  358. {modwire-9.2.3 → modwire-9.2.4}/tests/fixtures/languages/typescript/src/example_domain/example_services/example_policy.ts +0 -0
  359. {modwire-9.2.3 → modwire-9.2.4}/tests/fixtures/languages/typescript/src/example_interfaces/example_http/example_controller.ts +0 -0
  360. {modwire-9.2.3 → modwire-9.2.4}/tests/fixtures/languages/typescript/src/example_interfaces/example_http/example_view.jsx +0 -0
  361. {modwire-9.2.3 → modwire-9.2.4}/tests/fixtures/syntax/php/example_shapes.php +0 -0
  362. {modwire-9.2.3 → modwire-9.2.4}/tests/fixtures/syntax/python/example_shapes.py +0 -0
  363. {modwire-9.2.3 → modwire-9.2.4}/tests/fixtures/syntax/typescript/example_shapes.ts +0 -0
  364. {modwire-9.2.3 → modwire-9.2.4}/tests/shared/__init__.py +0 -0
  365. {modwire-9.2.3 → modwire-9.2.4}/tests/shared/code/__init__.py +0 -0
  366. {modwire-9.2.3 → modwire-9.2.4}/tests/shared/code/test_02_invariants.py +0 -0
  367. {modwire-9.2.3 → modwire-9.2.4}/tests/support/__init__.py +0 -0
  368. {modwire-9.2.3 → modwire-9.2.4}/tests/support/base_test.py +0 -0
  369. {modwire-9.2.3 → modwire-9.2.4}/tests/support/code_map.py +0 -0
  370. {modwire-9.2.3 → modwire-9.2.4}/tests/support/service_test.py +0 -0
  371. {modwire-9.2.3 → modwire-9.2.4}/uv.lock +0 -0
@@ -187,8 +187,8 @@ src/modwire/extraction/dependency/application.py
187
187
  src/modwire/extraction/dependency/domain.py
188
188
  src/modwire/extraction/dependency/services/__init__.py
189
189
  src/modwire/extraction/dependency/services/graph_builder.py
190
+ src/modwire/extraction/dependency/services/import_identity_index.py
190
191
  src/modwire/extraction/dependency/services/import_resolver.py
191
- src/modwire/extraction/dependency/services/suffix_index.py
192
192
  src/modwire/extraction/extractors/__init__.py
193
193
  src/modwire/extraction/extractors/application.py
194
194
  src/modwire/extraction/extractors/domain.py
@@ -326,6 +326,7 @@ tests/extraction/big_projects/resolution_results.json
326
326
  tests/extraction/big_projects/results.json
327
327
  tests/extraction/big_projects/run.py
328
328
  tests/extraction/cache_benchmark/__init__.py
329
+ tests/extraction/cache_benchmark/benchmark_process_timeout.py
329
330
  tests/extraction/cache_benchmark/run.py
330
331
  tests/extraction/dependency/__init__.py
331
332
  tests/extraction/dependency/test_02_invariants.py
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modwire
3
- Version: 9.2.3
3
+ Version: 9.2.4
4
4
  Summary: Code extraction, architecture analysis and the Modwire CLI.
5
5
  Author: Tomasz Szpak
6
6
  License-Expression: MIT
@@ -3,7 +3,7 @@ from dataclasses import dataclass
3
3
  from wireup import injectable
4
4
 
5
5
  from ...shared.code.models.dependency_graph import DependencyGraph
6
- from ...shared.code.models.identity import FileId
6
+ from ...shared.code.models.identity import FileId, ModuleId
7
7
  from ...shared.code.models.source_file import SourceFile
8
8
  from .domain import GraphBuilder, ImportResolver
9
9
 
@@ -17,5 +17,7 @@ class DependencyApplication:
17
17
  def build(self, files: dict[FileId, SourceFile]) -> DependencyGraph:
18
18
  return self.builder.build(files)
19
19
 
20
- def resolve(self, files: dict[FileId, SourceFile]) -> dict[FileId, SourceFile]:
21
- return self.resolver.resolve(files)
20
+ def resolve(
21
+ self, files: dict[FileId, SourceFile], identities: dict[FileId, tuple[ModuleId, ...]]
22
+ ) -> dict[FileId, SourceFile]:
23
+ return self.resolver.resolve(files, identities)
@@ -1,7 +1,7 @@
1
1
  from abc import ABC, abstractmethod
2
2
 
3
3
  from ...shared.code.models.dependency_graph import DependencyGraph
4
- from ...shared.code.models.identity import FileId
4
+ from ...shared.code.models.identity import FileId, ModuleId
5
5
  from ...shared.code.models.source_file import SourceFile
6
6
 
7
7
 
@@ -13,5 +13,7 @@ class GraphBuilder(ABC):
13
13
 
14
14
  class ImportResolver(ABC):
15
15
  @abstractmethod
16
- def resolve(self, files: dict[FileId, SourceFile]) -> dict[FileId, SourceFile]:
16
+ def resolve(
17
+ self, files: dict[FileId, SourceFile], identities: dict[FileId, tuple[ModuleId, ...]]
18
+ ) -> dict[FileId, SourceFile]:
17
19
  raise NotImplementedError
@@ -1,14 +1,16 @@
1
1
  from ....shared.code.models.identity import FileId
2
2
 
3
3
 
4
- class SuffixIndex:
4
+ class ImportIdentityIndex:
5
5
  def __init__(self) -> None:
6
+ self._exact: dict[tuple[str, str], set[FileId]] = {}
6
7
  self._empty: dict[str, set[FileId]] = {}
7
8
  self._terminal: dict[tuple[str, str], set[FileId]] = {}
8
9
  self._singleton: dict[tuple[str, str], set[FileId]] = {}
9
10
  self._terminal_pair: dict[tuple[str, str, str], set[FileId]] = {}
10
11
 
11
12
  def add(self, group: str, identity: str, file_id: FileId) -> None:
13
+ self._exact.setdefault((group, identity), set()).add(file_id)
12
14
  if not identity:
13
15
  self._empty.setdefault(group, set()).add(file_id)
14
16
  return
@@ -19,7 +21,10 @@ class SuffixIndex:
19
21
  return
20
22
  self._terminal_pair.setdefault((group, parts[-2], parts[-1]), set()).add(file_id)
21
23
 
22
- def find(self, group: str, identity: str) -> set[FileId]:
24
+ def exact(self, group: str, identity: str) -> set[FileId]:
25
+ return set(self._exact.get((group, identity), ()))
26
+
27
+ def suffix(self, group: str, identity: str) -> set[FileId]:
23
28
  if not identity:
24
29
  return set(self._empty.get(group, ()))
25
30
  parts = identity.split("/")
@@ -3,22 +3,25 @@ from dataclasses import dataclass
3
3
 
4
4
  from wireup import injectable
5
5
 
6
- from ....shared.code.models.identity import FileId
6
+ from ....shared.code.models.identity import FileId, ModuleId
7
7
  from ....shared.code.models.source_file import SourceFile
8
8
  from ....shared.code.models.source_import import SourceImport
9
9
  from ..domain import ImportResolver
10
- from .suffix_index import SuffixIndex
10
+ from .import_identity_index import ImportIdentityIndex
11
11
 
12
12
 
13
13
  @injectable(as_type=ImportResolver)
14
14
  @dataclass(frozen=True)
15
15
  class SourceImportResolver(ImportResolver):
16
- def resolve(self, files: dict[FileId, SourceFile]) -> dict[FileId, SourceFile]:
17
- modules = SuffixIndex()
18
- symbols = SuffixIndex()
16
+ def resolve(
17
+ self, files: dict[FileId, SourceFile], identities: dict[FileId, tuple[ModuleId, ...]]
18
+ ) -> dict[FileId, SourceFile]:
19
+ modules = ImportIdentityIndex()
20
+ symbols = ImportIdentityIndex()
19
21
  for file_id, source_file in files.items():
20
22
  module = self._normalize(source_file.module_id)
21
- modules.add("", module, file_id)
23
+ for identity in identities[file_id]:
24
+ modules.add("", self._normalize(identity), file_id)
22
25
  parent = module.rsplit("/", 1)[0] if "/" in module else ""
23
26
  for exported in source_file.exports:
24
27
  symbols.add(exported.name.casefold(), parent, file_id)
@@ -31,14 +34,10 @@ class SourceImportResolver(ImportResolver):
31
34
  for file_id, source_file in files.items()
32
35
  }
33
36
 
34
- def _resolve_import(self, imported: SourceImport, modules: SuffixIndex, symbols: SuffixIndex) -> SourceImport:
35
- specifier = self._normalize(imported.normalized_path)
36
- candidates = modules.find("", specifier)
37
- if imported.crossing_type == "symbol" and imported.imported_symbols:
38
- symbol_names = {symbol.name.casefold() for symbol in imported.imported_symbols}
39
- imported_parent = self._normalize(imported.join_key)
40
- for symbol_name in symbol_names:
41
- candidates.update(symbols.find(symbol_name, imported_parent))
37
+ def _resolve_import(
38
+ self, imported: SourceImport, modules: ImportIdentityIndex, symbols: ImportIdentityIndex
39
+ ) -> SourceImport:
40
+ candidates = self._candidates(imported, modules, symbols)
42
41
  if len(candidates) == 1:
43
42
  return imported.model_copy(update={"resolution": "resolved", "target_file_id": next(iter(candidates))})
44
43
  return imported.model_copy(
@@ -48,6 +47,30 @@ class SourceImportResolver(ImportResolver):
48
47
  }
49
48
  )
50
49
 
50
+ def _candidates(
51
+ self, imported: SourceImport, modules: ImportIdentityIndex, symbols: ImportIdentityIndex
52
+ ) -> set[FileId]:
53
+ specifier = self._normalize(imported.normalized_path)
54
+ candidates = modules.exact("", specifier)
55
+ if candidates:
56
+ return candidates
57
+ if imported.crossing_type == "symbol" and imported.imported_symbols:
58
+ symbol_names = {symbol.name.casefold() for symbol in imported.imported_symbols}
59
+ imported_parent = self._normalize(imported.join_key)
60
+ for symbol_name in symbol_names:
61
+ candidates.update(symbols.exact(symbol_name, imported_parent))
62
+ if candidates:
63
+ return candidates
64
+ candidates = modules.suffix("", specifier)
65
+ if candidates:
66
+ return candidates
67
+ if imported.crossing_type == "symbol" and imported.imported_symbols:
68
+ symbol_names = {symbol.name.casefold() for symbol in imported.imported_symbols}
69
+ imported_parent = self._normalize(imported.join_key)
70
+ for symbol_name in symbol_names:
71
+ candidates.update(symbols.suffix(symbol_name, imported_parent))
72
+ return candidates
73
+
51
74
  def _normalize(self, value: str) -> str:
52
75
  parts = str(value).replace("\\", "/").strip("/").split("/")
53
76
  return "/".join(re.sub("[^a-z0-9]", "", part.casefold()) for part in parts)
@@ -32,7 +32,13 @@ class ExtractorsApplication:
32
32
  return ExtractionRequest(root=root, runtime=extractor.runtime, batch_config=extractor.batch_config)
33
33
 
34
34
  def generate_map(self, language: str, extraction: SourceExtraction) -> CodeMap:
35
- files = self.dependency.resolve(extraction.files)
35
+ if language not in self.extractors:
36
+ raise ValueError(f"Language is not supported: {language}")
37
+ extractor = self.extractors[language]
38
+ identities = {
39
+ file_id: extractor.module_identities(source_file) for file_id, source_file in extraction.files.items()
40
+ }
41
+ files = self.dependency.resolve(extraction.files, identities)
36
42
  resolved = extraction.model_copy(update={"files": files})
37
43
  return CodeMap(language=language, extraction=resolved, dependency_graph=self.dependency.build(files))
38
44
 
@@ -1,6 +1,8 @@
1
1
  import ast
2
2
  from abc import ABC, abstractmethod
3
3
 
4
+ from ...shared.code.models.identity import ModuleId
5
+ from ...shared.code.models.source_file import SourceFile
4
6
  from .models.batch_config import BatchConfig
5
7
  from .models.extractor_runtime import ExtractorRuntime
6
8
  from .models.python_call_context import PythonCallContext
@@ -28,3 +30,7 @@ class SourceExtractor(ABC):
28
30
  @abstractmethod
29
31
  def batch_config(self) -> BatchConfig:
30
32
  raise NotImplementedError
33
+
34
+ @abstractmethod
35
+ def module_identities(self, source_file: SourceFile) -> tuple[ModuleId, ...]:
36
+ raise NotImplementedError
@@ -2,6 +2,8 @@ from dataclasses import dataclass
2
2
 
3
3
  from wireup import injectable
4
4
 
5
+ from ....shared.code.models.identity import ModuleId
6
+ from ....shared.code.models.source_file import SourceFile
5
7
  from ..domain import SourceExtractor
6
8
  from ..models.batch_config import BatchConfig
7
9
  from ..models.extractor_resource import ExtractorResource
@@ -24,3 +26,6 @@ class PhpExtractor(SourceExtractor):
24
26
  @property
25
27
  def batch_config(self) -> BatchConfig:
26
28
  return BatchConfig(size=500, parallel_threshold=500, parallel_size=500, max_workers=16, output_format="jsonl")
29
+
30
+ def module_identities(self, source_file: SourceFile) -> tuple[ModuleId, ...]:
31
+ return (source_file.module_id,)
@@ -3,6 +3,8 @@ from dataclasses import dataclass
3
3
 
4
4
  from wireup import injectable
5
5
 
6
+ from ....shared.code.models.identity import ModuleId
7
+ from ....shared.code.models.source_file import SourceFile
6
8
  from ..domain import SourceExtractor
7
9
  from ..models.batch_config import BatchConfig
8
10
  from ..models.extractor_resource import ExtractorResource
@@ -25,3 +27,10 @@ class PythonExtractor(SourceExtractor):
25
27
  @property
26
28
  def batch_config(self) -> BatchConfig:
27
29
  return BatchConfig(size=500, output_format="json")
30
+
31
+ def module_identities(self, source_file: SourceFile) -> tuple[ModuleId, ...]:
32
+ module_id = source_file.module_id
33
+ value = str(module_id)
34
+ if value == "__init__" or not value.endswith("/__init__"):
35
+ return (module_id,)
36
+ return (module_id, ModuleId(value.rsplit("/", 1)[0]))
@@ -2,6 +2,8 @@ from dataclasses import dataclass
2
2
 
3
3
  from wireup import injectable
4
4
 
5
+ from ....shared.code.models.identity import ModuleId
6
+ from ....shared.code.models.source_file import SourceFile
5
7
  from ..domain import SourceExtractor
6
8
  from ..models.batch_config import BatchConfig
7
9
  from ..models.extractor_resource import ExtractorResource
@@ -24,3 +26,6 @@ class TypeScriptExtractor(SourceExtractor):
24
26
  @property
25
27
  def batch_config(self) -> BatchConfig:
26
28
  return BatchConfig(size=500, parallel_threshold=1000, parallel_size=500, max_workers=16, output_format="jsonl")
29
+
30
+ def module_identities(self, source_file: SourceFile) -> tuple[ModuleId, ...]:
31
+ return (source_file.module_id,)
@@ -0,0 +1,6 @@
1
+ class BenchmarkProcessTimeout(RuntimeError):
2
+ def __init__(self, scenario: str, phase: str, limit_seconds: float) -> None:
3
+ self.scenario = scenario
4
+ self.phase = phase
5
+ self.limit_seconds = limit_seconds
6
+ super().__init__(f"benchmark exceeded its {limit_seconds:.3f}s process budget during {scenario}.{phase}")
@@ -12,13 +12,7 @@ from typing import Any
12
12
 
13
13
  from modwire.application import CacheOptions, ModwireApplication, ScanPolicy
14
14
 
15
-
16
- class BenchmarkProcessTimeout(RuntimeError):
17
- def __init__(self, scenario: str, phase: str, limit_seconds: float) -> None:
18
- self.scenario = scenario
19
- self.phase = phase
20
- self.limit_seconds = limit_seconds
21
- super().__init__(f"benchmark exceeded its {limit_seconds:.3f}s process budget during {scenario}.{phase}")
15
+ from .benchmark_process_timeout import BenchmarkProcessTimeout
22
16
 
23
17
 
24
18
  class CacheBenchmark:
@@ -28,7 +28,16 @@ class TestDependencyInvariants(ExtractionTestCase):
28
28
  request = self.application.extraction.request(language, str(root))
29
29
  extraction = self.application.cli.extract(request, self.scan_policy())
30
30
  result = self.application.extraction.generate_map(language, extraction)
31
- modules = [(normalize(source.module_id), file_id) for file_id, source in extraction.files.items()]
31
+ modules = [
32
+ (identity, file_id)
33
+ for file_id, source in extraction.files.items()
34
+ for module in (normalize(source.module_id),)
35
+ for identity in (
36
+ (module, module.rsplit("/", 1)[0])
37
+ if language == "python" and module.endswith("/__init__")
38
+ else (module,)
39
+ )
40
+ ]
32
41
  symbols = [
33
42
  (module.rsplit("/", 1)[0] if "/" in module else "", exported.name.casefold(), file_id)
34
43
  for file_id, source in extraction.files.items()
@@ -38,8 +47,19 @@ class TestDependencyInvariants(ExtractionTestCase):
38
47
  for file_id, source in extraction.files.items():
39
48
  for actual, imported in zip(result.extraction.files[file_id].imports, source.imports, strict=True):
40
49
  specifier = normalize(imported.normalized_path)
41
- candidates = {target for module, target in modules if same_suffix(module, specifier)}
50
+ candidates = {target for module, target in modules if module == specifier}
42
51
  if imported.crossing_type == "symbol" and imported.imported_symbols:
52
+ names = {symbol.name.casefold() for symbol in imported.imported_symbols}
53
+ parent = normalize(imported.join_key)
54
+ if not candidates:
55
+ candidates.update(
56
+ target
57
+ for module_parent, symbol_name, target in symbols
58
+ if symbol_name in names and module_parent == parent
59
+ )
60
+ if not candidates:
61
+ candidates = {target for module, target in modules if same_suffix(module, specifier)}
62
+ if not candidates and imported.crossing_type == "symbol" and imported.imported_symbols:
43
63
  names = {symbol.name.casefold() for symbol in imported.imported_symbols}
44
64
  parent = normalize(imported.join_key)
45
65
  candidates.update(
@@ -57,7 +77,45 @@ class TestDependencyInvariants(ExtractionTestCase):
57
77
  )
58
78
  assert (actual.resolution, actual.target_file_id) == (expected_resolution, expected_target)
59
79
 
60
- def test_ambiguous_module_suffix_does_not_choose_an_arbitrary_target(self) -> None:
80
+ def test_exact_module_and_package_identities_win_over_suffix_candidates(self) -> None:
81
+ result = self.extract(
82
+ {
83
+ "example/widgets/api/controllers.py": """
84
+ from ...security.adapters.http import SecurityPermission
85
+ from ..services import WidgetsService
86
+ from ..services.approvals import ApprovalView
87
+ from ..services.audit.model import AuditEventPage
88
+ from ..services.facade import WidgetsService
89
+ """,
90
+ "example/widgets/services/__init__.py": "class WidgetsService:\n pass\n",
91
+ "example/widgets/services/facade.py": "class WidgetsService:\n pass\n",
92
+ "example/widgets/services/approvals/__init__.py": "class ApprovalView:\n pass\n",
93
+ "example/widgets/services/audit/model.py": "class AuditEventPage:\n pass\n",
94
+ "example/security/adapters/http/__init__.py": "class SecurityPermission:\n pass\n",
95
+ "example/security/adapters/http/permissions.py": "class SecurityPermission:\n pass\n",
96
+ "example/mcp/services/operations/adapters/http.py": "class ExampleHttpAdapter:\n pass\n",
97
+ "example/other/services/facade.py": "class ExampleService:\n pass\n",
98
+ }
99
+ )
100
+ edges = {
101
+ str(item.edge.specifier): (item.edge.resolution, item.edge.to_id)
102
+ for item in result.outgoing_dependencies("example/widgets/api/controllers.py").all()
103
+ }
104
+ assert edges == {
105
+ "example/security/adapters/http": ("resolved", "example/security/adapters/http/__init__.py"),
106
+ "example/widgets/services": ("resolved", "example/widgets/services/__init__.py"),
107
+ "example/widgets/services/approvals": (
108
+ "resolved",
109
+ "example/widgets/services/approvals/__init__.py",
110
+ ),
111
+ "example/widgets/services/audit/model": (
112
+ "resolved",
113
+ "example/widgets/services/audit/model.py",
114
+ ),
115
+ "example/widgets/services/facade": ("resolved", "example/widgets/services/facade.py"),
116
+ }
117
+
118
+ def test_exact_module_identity_wins_over_duplicate_suffix(self) -> None:
61
119
  result = self.extract(
62
120
  {
63
121
  "example_first/example_package/example_value.py": "class ExampleValue:\n pass\n",
@@ -66,6 +124,19 @@ class TestDependencyInvariants(ExtractionTestCase):
66
124
  }
67
125
  )
68
126
  edge = result.dependency_edges().first().edge
127
+ assert edge.resolution == "resolved"
128
+ assert edge.to_id == "example_first/example_package/example_value.py"
129
+ assert result.tracked_dependency_edges().count() == 1
130
+
131
+ def test_genuinely_ambiguous_module_suffix_does_not_choose_an_arbitrary_target(self) -> None:
132
+ result = self.extract(
133
+ {
134
+ "example_first/example_package/example_value.py": "class ExampleValue:\n pass\n",
135
+ "example_second/example_package/example_value.py": "class ExampleValue:\n pass\n",
136
+ "example_consumer.py": "from example_package.example_value import ExampleValue\n",
137
+ }
138
+ )
139
+ edge = result.dependency_edges().first().edge
69
140
  assert edge.resolution == "unresolved"
70
141
  assert edge.to_id is None
71
142
  assert not result.tracked_dependency_edges().all()
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes