modwire 9.2.0__tar.gz → 9.2.1__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 (364) hide show
  1. {modwire-9.2.0 → modwire-9.2.1}/PKG-INFO +1 -1
  2. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/boundaries/services/no_reentry_flow_analyzer.py +34 -11
  3. modwire-9.2.1/tests/architecture/boundaries/test_04_paths.py +143 -0
  4. modwire-9.2.0/tests/architecture/boundaries/test_04_paths.py +0 -66
  5. {modwire-9.2.0 → modwire-9.2.1}/.dev/modwire.egg-info/SOURCES.txt +0 -0
  6. {modwire-9.2.0 → modwire-9.2.1}/.github/workflows/ci.yml +0 -0
  7. {modwire-9.2.0 → modwire-9.2.1}/.github/workflows/release.yml +0 -0
  8. {modwire-9.2.0 → modwire-9.2.1}/.gitignore +0 -0
  9. {modwire-9.2.0 → modwire-9.2.1}/AGENTS.md +0 -0
  10. {modwire-9.2.0 → modwire-9.2.1}/LICENSE +0 -0
  11. {modwire-9.2.0 → modwire-9.2.1}/MANIFEST.in +0 -0
  12. {modwire-9.2.0 → modwire-9.2.1}/Makefile +0 -0
  13. {modwire-9.2.0 → modwire-9.2.1}/README.md +0 -0
  14. {modwire-9.2.0 → modwire-9.2.1}/docs/target-language-ownership.md +0 -0
  15. {modwire-9.2.0 → modwire-9.2.1}/pyproject.toml +0 -0
  16. {modwire-9.2.0 → modwire-9.2.1}/scripts/check_extractors.py +0 -0
  17. {modwire-9.2.0 → modwire-9.2.1}/scripts/generate_docs.py +0 -0
  18. {modwire-9.2.0 → modwire-9.2.1}/scripts/verify_consumer.py +0 -0
  19. {modwire-9.2.0 → modwire-9.2.1}/setup.cfg +0 -0
  20. {modwire-9.2.0 → modwire-9.2.1}/setup.py +0 -0
  21. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/__init__.py +0 -0
  22. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/__main__.py +0 -0
  23. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/application.py +0 -0
  24. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/__init__.py +0 -0
  25. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/boundaries/__init__.py +0 -0
  26. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/boundaries/application.py +0 -0
  27. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/boundaries/domain.py +0 -0
  28. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/boundaries/models/__init__.py +0 -0
  29. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/boundaries/models/edge_rule_violation.py +0 -0
  30. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/boundaries/models/flow_report.py +0 -0
  31. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/boundaries/models/flow_violation.py +0 -0
  32. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/boundaries/models/types.py +0 -0
  33. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/boundaries/services/__init__.py +0 -0
  34. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/boundaries/services/backward_flow_analyzer.py +0 -0
  35. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/boundaries/services/boundaries_flow_analyzer.py +0 -0
  36. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/boundaries/services/module_boundary_analyzer.py +0 -0
  37. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/boundaries/services/no_cycles_flow_analyzer.py +0 -0
  38. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/config/__init__.py +0 -0
  39. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/config/application.py +0 -0
  40. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/config/models/__init__.py +0 -0
  41. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/config/models/architecture_config.py +0 -0
  42. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/config/models/boundaries_config.py +0 -0
  43. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/config/models/boundary_rule.py +0 -0
  44. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/config/models/configuration_value.py +0 -0
  45. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/config/models/flow_realm.py +0 -0
  46. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/config/models/flow_rules.py +0 -0
  47. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/config/models/shape_config.py +0 -0
  48. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/config/models/shape_realm.py +0 -0
  49. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/config/models/shape_rules.py +0 -0
  50. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/config/models/tag_rule.py +0 -0
  51. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/facade.py +0 -0
  52. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/insights/__init__.py +0 -0
  53. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/insights/application.py +0 -0
  54. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/insights/domain.py +0 -0
  55. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/insights/models/__init__.py +0 -0
  56. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/insights/models/callable_report_entry.py +0 -0
  57. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/insights/models/callables_report.py +0 -0
  58. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/insights/models/clusters_report.py +0 -0
  59. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/insights/models/clusters_report_item.py +0 -0
  60. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/insights/models/coherence_report.py +0 -0
  61. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/insights/models/exports_report.py +0 -0
  62. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/insights/models/exports_report_item.py +0 -0
  63. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/insights/models/hotspots_report.py +0 -0
  64. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/insights/models/hotspots_report_item.py +0 -0
  65. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/insights/models/insight_report.py +0 -0
  66. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/insights/services/__init__.py +0 -0
  67. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/insights/services/callables_reporter.py +0 -0
  68. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/insights/services/clusters_reporter.py +0 -0
  69. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/insights/services/coherence_reporter.py +0 -0
  70. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/insights/services/exports_reporter.py +0 -0
  71. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/insights/services/hotspots_reporter.py +0 -0
  72. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/insights/services/insight_report_field_map.py +0 -0
  73. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/map/__init__.py +0 -0
  74. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/map/application.py +0 -0
  75. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/map/domain.py +0 -0
  76. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/map/models/__init__.py +0 -0
  77. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/map/models/architecture_map.py +0 -0
  78. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/map/models/architecture_realm.py +0 -0
  79. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/map/models/tag_map.py +0 -0
  80. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/map/models/tag_match.py +0 -0
  81. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/map/services/__init__.py +0 -0
  82. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/map/services/architecture_map_loader.py +0 -0
  83. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/map/services/tag_matcher.py +0 -0
  84. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/report/__init__.py +0 -0
  85. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/report/application.py +0 -0
  86. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/report/domain.py +0 -0
  87. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/report/models/__init__.py +0 -0
  88. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/report/models/architecture_group.py +0 -0
  89. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/report/models/map_report.py +0 -0
  90. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/report/models/report_catalog.py +0 -0
  91. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/report/models/report_descriptor.py +0 -0
  92. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/report/models/report_item.py +0 -0
  93. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/report/models/report_metadata.py +0 -0
  94. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/report/models/report_node.py +0 -0
  95. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/report/models/report_section.py +0 -0
  96. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/report/services/__init__.py +0 -0
  97. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/report/services/map_report_collector.py +0 -0
  98. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/shape/__init__.py +0 -0
  99. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/shape/application.py +0 -0
  100. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/shape/domain.py +0 -0
  101. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/shape/models/__init__.py +0 -0
  102. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/shape/models/shape_realm_architecture_map.py +0 -0
  103. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/shape/models/shape_report.py +0 -0
  104. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/shape/models/shape_violation.py +0 -0
  105. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/shape/services/__init__.py +0 -0
  106. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/shape/services/abstract_class_resolver.py +0 -0
  107. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/shape/services/callable_resolver.py +0 -0
  108. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/shape/services/class_resolver.py +0 -0
  109. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/shape/services/file_resolver.py +0 -0
  110. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/shape/services/import_resolver.py +0 -0
  111. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/shape/services/property_resolver.py +0 -0
  112. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/shape/services/signature_resolver.py +0 -0
  113. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/architecture/shape/services/symbol_resolver.py +0 -0
  114. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/autowiring.py +0 -0
  115. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/__init__.py +0 -0
  116. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/cache/__init__.py +0 -0
  117. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/cache/application.py +0 -0
  118. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/cache/domain.py +0 -0
  119. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/cache/models/__init__.py +0 -0
  120. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/cache/models/cache_entry.py +0 -0
  121. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/cache/models/cache_key.py +0 -0
  122. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/cache/models/cache_options.py +0 -0
  123. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/cache/models/cache_outcome.py +0 -0
  124. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/cache/models/cached_result.py +0 -0
  125. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/cache/models/extraction_snapshot.py +0 -0
  126. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/cache/models/source_entry.py +0 -0
  127. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/cache/models/source_inventory.py +0 -0
  128. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/cache/services/__init__.py +0 -0
  129. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/cache/services/cache_codec.py +0 -0
  130. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/cache/services/cache_identity.py +0 -0
  131. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/cache/services/filesystem_cache_storage.py +0 -0
  132. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/documentation/__init__.py +0 -0
  133. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/documentation/application.py +0 -0
  134. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/documentation/services/__init__.py +0 -0
  135. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/documentation/services/documentation_generator.py +0 -0
  136. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/facade.py +0 -0
  137. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/initialization/__init__.py +0 -0
  138. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/initialization/application.py +0 -0
  139. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/initialization/models/__init__.py +0 -0
  140. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/initialization/models/initialization_result.py +0 -0
  141. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/initialization/services/__init__.py +0 -0
  142. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/initialization/services/initialization_service.py +0 -0
  143. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/pipeline/__init__.py +0 -0
  144. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/pipeline/application.py +0 -0
  145. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/pipeline/domain.py +0 -0
  146. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/pipeline/models/__init__.py +0 -0
  147. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/pipeline/models/command_request.py +0 -0
  148. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/pipeline/models/extractor_batch_input.py +0 -0
  149. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/pipeline/models/extractor_command_input.py +0 -0
  150. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/pipeline/models/extractor_source_input.py +0 -0
  151. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/pipeline/models/report_pipeline_context.py +0 -0
  152. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/pipeline/models/scan_policy.py +0 -0
  153. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/pipeline/services/__init__.py +0 -0
  154. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/pipeline/services/batch_source_reader.py +0 -0
  155. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/pipeline/services/callables_insight.py +0 -0
  156. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/pipeline/services/clusters_insight.py +0 -0
  157. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/pipeline/services/coherence_insight.py +0 -0
  158. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/pipeline/services/command_line.py +0 -0
  159. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/pipeline/services/configuration_loader.py +0 -0
  160. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/pipeline/services/extractor_command.py +0 -0
  161. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/pipeline/services/flow_violations.py +0 -0
  162. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/pipeline/services/hotspots_insight.py +0 -0
  163. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/pipeline/services/map_tree.py +0 -0
  164. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/pipeline/services/output_console.py +0 -0
  165. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/pipeline/services/shape_violations.py +0 -0
  166. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/pipeline/services/success.py +0 -0
  167. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/pipeline/services/unknown_files_warning.py +0 -0
  168. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/pipeline/services/unused_exports_insight.py +0 -0
  169. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/resources/__init__.py +0 -0
  170. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/resources/application.py +0 -0
  171. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/resources/models/__init__.py +0 -0
  172. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/resources/models/defaults.py +0 -0
  173. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/resources/models/init_asset.py +0 -0
  174. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/resources/templates/AGENTS.md +0 -0
  175. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/resources/templates/ARCHITECTURE.md +0 -0
  176. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/resources/templates/INDEX.md +0 -0
  177. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/resources/templates/MODWIRE.md +0 -0
  178. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/resources/templates/RULES.md +0 -0
  179. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/resources/templates/TESTING.md +0 -0
  180. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/resources/templates/WORKFLOW.md +0 -0
  181. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/cli/resources/templates/architecture.yaml +0 -0
  182. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/extraction/__init__.py +0 -0
  183. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/extraction/dependency/__init__.py +0 -0
  184. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/extraction/dependency/application.py +0 -0
  185. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/extraction/dependency/domain.py +0 -0
  186. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/extraction/dependency/services/__init__.py +0 -0
  187. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/extraction/dependency/services/graph_builder.py +0 -0
  188. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/extraction/dependency/services/import_resolver.py +0 -0
  189. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/extraction/dependency/services/suffix_index.py +0 -0
  190. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/extraction/extractors/__init__.py +0 -0
  191. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/extraction/extractors/application.py +0 -0
  192. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/extraction/extractors/domain.py +0 -0
  193. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/extraction/extractors/models/__init__.py +0 -0
  194. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/extraction/extractors/models/batch_config.py +0 -0
  195. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/extraction/extractors/models/extraction_request.py +0 -0
  196. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/extraction/extractors/models/extractor_resource.py +0 -0
  197. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/extraction/extractors/models/extractor_runtime.py +0 -0
  198. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/extraction/extractors/models/python_call_context.py +0 -0
  199. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/extraction/extractors/resources/__init__.py +0 -0
  200. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/extraction/extractors/resources/php/build.php +0 -0
  201. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/extraction/extractors/resources/php/build.py +0 -0
  202. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/extraction/extractors/resources/php/composer.json +0 -0
  203. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/extraction/extractors/resources/php/composer.lock +0 -0
  204. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/extraction/extractors/resources/php/script.php +0 -0
  205. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/extraction/extractors/resources/php/script.src.php +0 -0
  206. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/extraction/extractors/resources/python/__init__.py +0 -0
  207. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/extraction/extractors/resources/python/script.py +0 -0
  208. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/extraction/extractors/resources/typescript/build.mjs +0 -0
  209. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/extraction/extractors/resources/typescript/build.py +0 -0
  210. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/extraction/extractors/resources/typescript/package-lock.json +0 -0
  211. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/extraction/extractors/resources/typescript/package.json +0 -0
  212. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/extraction/extractors/resources/typescript/script.js +0 -0
  213. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/extraction/extractors/resources/typescript/script.ts +0 -0
  214. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/extraction/extractors/resources/typescript/tsconfig.json +0 -0
  215. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/extraction/extractors/services/__init__.py +0 -0
  216. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/extraction/extractors/services/php_extractor.py +0 -0
  217. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/extraction/extractors/services/python_call_reader.py +0 -0
  218. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/extraction/extractors/services/python_extractor.py +0 -0
  219. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/extraction/extractors/services/python_syntax_parser.py +0 -0
  220. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/extraction/extractors/services/type_script_extractor.py +0 -0
  221. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/extraction/facade.py +0 -0
  222. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/py.typed +0 -0
  223. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/shared/__init__.py +0 -0
  224. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/shared/code/__init__.py +0 -0
  225. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/shared/code/application.py +0 -0
  226. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/shared/code/domain.py +0 -0
  227. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/shared/code/models/__init__.py +0 -0
  228. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/shared/code/models/code_map.py +0 -0
  229. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/shared/code/models/code_package.py +0 -0
  230. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/shared/code/models/dependency_edge_result.py +0 -0
  231. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/shared/code/models/dependency_graph.py +0 -0
  232. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/shared/code/models/dependency_node_result.py +0 -0
  233. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/shared/code/models/duplicate_identity_error.py +0 -0
  234. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/shared/code/models/edge.py +0 -0
  235. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/shared/code/models/edge_resolution.py +0 -0
  236. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/shared/code/models/identity.py +0 -0
  237. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/shared/code/models/node.py +0 -0
  238. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/shared/code/models/query_builder.py +0 -0
  239. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/shared/code/models/query_types.py +0 -0
  240. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/shared/code/models/queryable_code_map.py +0 -0
  241. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/shared/code/models/source_abstract_class.py +0 -0
  242. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/shared/code/models/source_call.py +0 -0
  243. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/shared/code/models/source_callable.py +0 -0
  244. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/shared/code/models/source_callable_symbol.py +0 -0
  245. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/shared/code/models/source_class.py +0 -0
  246. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/shared/code/models/source_class_method.py +0 -0
  247. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/shared/code/models/source_class_property.py +0 -0
  248. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/shared/code/models/source_export.py +0 -0
  249. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/shared/code/models/source_extraction.py +0 -0
  250. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/shared/code/models/source_file.py +0 -0
  251. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/shared/code/models/source_file_result.py +0 -0
  252. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/shared/code/models/source_function.py +0 -0
  253. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/shared/code/models/source_import.py +0 -0
  254. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/shared/code/models/source_imported_symbol.py +0 -0
  255. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/shared/code/models/source_interface.py +0 -0
  256. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/shared/code/models/source_item_result.py +0 -0
  257. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/shared/code/models/source_parameter.py +0 -0
  258. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/shared/code/models/source_signature.py +0 -0
  259. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/shared/code/models/source_symbol.py +0 -0
  260. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/shared/code/models/source_type.py +0 -0
  261. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/shared/code/models/source_value.py +0 -0
  262. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/shared/code/models/types.py +0 -0
  263. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/shared/code/services/__init__.py +0 -0
  264. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/shared/code/services/glob_path_matcher.py +0 -0
  265. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/shared/code/services/identity_resolver.py +0 -0
  266. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/shared/values/__init__.py +0 -0
  267. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/shared/values/models/__init__.py +0 -0
  268. {modwire-9.2.0 → modwire-9.2.1}/src/modwire/shared/values/models/value_model.py +0 -0
  269. {modwire-9.2.0 → modwire-9.2.1}/tests/__init__.py +0 -0
  270. {modwire-9.2.0 → modwire-9.2.1}/tests/application/__init__.py +0 -0
  271. {modwire-9.2.0 → modwire-9.2.1}/tests/application/base_test.py +0 -0
  272. {modwire-9.2.0 → modwire-9.2.1}/tests/application/test_01_attacks.py +0 -0
  273. {modwire-9.2.0 → modwire-9.2.1}/tests/application/test_06_happy_path.py +0 -0
  274. {modwire-9.2.0 → modwire-9.2.1}/tests/application/test_07_cache.py +0 -0
  275. {modwire-9.2.0 → modwire-9.2.1}/tests/architecture/__init__.py +0 -0
  276. {modwire-9.2.0 → modwire-9.2.1}/tests/architecture/base_test.py +0 -0
  277. {modwire-9.2.0 → modwire-9.2.1}/tests/architecture/boundaries/__init__.py +0 -0
  278. {modwire-9.2.0 → modwire-9.2.1}/tests/architecture/boundaries/base_test.py +0 -0
  279. {modwire-9.2.0 → modwire-9.2.1}/tests/architecture/boundaries/test_01_attacks.py +0 -0
  280. {modwire-9.2.0 → modwire-9.2.1}/tests/architecture/boundaries/test_02_invariants.py +0 -0
  281. {modwire-9.2.0 → modwire-9.2.1}/tests/architecture/boundaries/test_03_public_api.py +0 -0
  282. {modwire-9.2.0 → modwire-9.2.1}/tests/architecture/config/__init__.py +0 -0
  283. {modwire-9.2.0 → modwire-9.2.1}/tests/architecture/config/test_01_attacks.py +0 -0
  284. {modwire-9.2.0 → modwire-9.2.1}/tests/architecture/config/test_02_invariants.py +0 -0
  285. {modwire-9.2.0 → modwire-9.2.1}/tests/architecture/insights/__init__.py +0 -0
  286. {modwire-9.2.0 → modwire-9.2.1}/tests/architecture/insights/base_test.py +0 -0
  287. {modwire-9.2.0 → modwire-9.2.1}/tests/architecture/insights/test_02_invariants.py +0 -0
  288. {modwire-9.2.0 → modwire-9.2.1}/tests/architecture/map/__init__.py +0 -0
  289. {modwire-9.2.0 → modwire-9.2.1}/tests/architecture/map/test_02_patterns.py +0 -0
  290. {modwire-9.2.0 → modwire-9.2.1}/tests/architecture/report/__init__.py +0 -0
  291. {modwire-9.2.0 → modwire-9.2.1}/tests/architecture/report/test_02_invariants.py +0 -0
  292. {modwire-9.2.0 → modwire-9.2.1}/tests/architecture/shape/__init__.py +0 -0
  293. {modwire-9.2.0 → modwire-9.2.1}/tests/architecture/shape/base_test.py +0 -0
  294. {modwire-9.2.0 → modwire-9.2.1}/tests/architecture/shape/test_01_limits.py +0 -0
  295. {modwire-9.2.0 → modwire-9.2.1}/tests/architecture/shape/test_02_invariants.py +0 -0
  296. {modwire-9.2.0 → modwire-9.2.1}/tests/cli/__init__.py +0 -0
  297. {modwire-9.2.0 → modwire-9.2.1}/tests/cli/base_test.py +0 -0
  298. {modwire-9.2.0 → modwire-9.2.1}/tests/cli/documentation/__init__.py +0 -0
  299. {modwire-9.2.0 → modwire-9.2.1}/tests/cli/documentation/test_02_invariants.py +0 -0
  300. {modwire-9.2.0 → modwire-9.2.1}/tests/cli/initialization/__init__.py +0 -0
  301. {modwire-9.2.0 → modwire-9.2.1}/tests/cli/initialization/test_01_attacks.py +0 -0
  302. {modwire-9.2.0 → modwire-9.2.1}/tests/cli/initialization/test_02_invariants.py +0 -0
  303. {modwire-9.2.0 → modwire-9.2.1}/tests/cli/initialization/test_03_interruption.py +0 -0
  304. {modwire-9.2.0 → modwire-9.2.1}/tests/cli/initialization/test_04_cleanup.py +0 -0
  305. {modwire-9.2.0 → modwire-9.2.1}/tests/cli/initialization/test_05_recovery.py +0 -0
  306. {modwire-9.2.0 → modwire-9.2.1}/tests/cli/pipeline/__init__.py +0 -0
  307. {modwire-9.2.0 → modwire-9.2.1}/tests/cli/pipeline/base_test.py +0 -0
  308. {modwire-9.2.0 → modwire-9.2.1}/tests/cli/pipeline/test_01_attacks.py +0 -0
  309. {modwire-9.2.0 → modwire-9.2.1}/tests/cli/pipeline/test_02_invariants.py +0 -0
  310. {modwire-9.2.0 → modwire-9.2.1}/tests/cli/pipeline/test_03_interruption.py +0 -0
  311. {modwire-9.2.0 → modwire-9.2.1}/tests/cli/pipeline/test_04_command_transport.py +0 -0
  312. {modwire-9.2.0 → modwire-9.2.1}/tests/cli/pipeline/test_05_recovery.py +0 -0
  313. {modwire-9.2.0 → modwire-9.2.1}/tests/cli/pipeline/test_06_happy_path.py +0 -0
  314. {modwire-9.2.0 → modwire-9.2.1}/tests/conftest.py +0 -0
  315. {modwire-9.2.0 → modwire-9.2.1}/tests/extraction/__init__.py +0 -0
  316. {modwire-9.2.0 → modwire-9.2.1}/tests/extraction/base_test.py +0 -0
  317. {modwire-9.2.0 → modwire-9.2.1}/tests/extraction/big_projects/__init__.py +0 -0
  318. {modwire-9.2.0 → modwire-9.2.1}/tests/extraction/big_projects/project.py +0 -0
  319. {modwire-9.2.0 → modwire-9.2.1}/tests/extraction/big_projects/projects.json +0 -0
  320. {modwire-9.2.0 → modwire-9.2.1}/tests/extraction/big_projects/resolution_results.json +0 -0
  321. {modwire-9.2.0 → modwire-9.2.1}/tests/extraction/big_projects/results.json +0 -0
  322. {modwire-9.2.0 → modwire-9.2.1}/tests/extraction/big_projects/run.py +0 -0
  323. {modwire-9.2.0 → modwire-9.2.1}/tests/extraction/cache_benchmark/__init__.py +0 -0
  324. {modwire-9.2.0 → modwire-9.2.1}/tests/extraction/cache_benchmark/run.py +0 -0
  325. {modwire-9.2.0 → modwire-9.2.1}/tests/extraction/dependency/__init__.py +0 -0
  326. {modwire-9.2.0 → modwire-9.2.1}/tests/extraction/dependency/test_02_invariants.py +0 -0
  327. {modwire-9.2.0 → modwire-9.2.1}/tests/extraction/extractors/__init__.py +0 -0
  328. {modwire-9.2.0 → modwire-9.2.1}/tests/extraction/extractors/test_01_attacks.py +0 -0
  329. {modwire-9.2.0 → modwire-9.2.1}/tests/extraction/extractors/test_02_invariants.py +0 -0
  330. {modwire-9.2.0 → modwire-9.2.1}/tests/extraction/extractors/test_03_native_symbols.py +0 -0
  331. {modwire-9.2.0 → modwire-9.2.1}/tests/extraction/scan_benchmark/__init__.py +0 -0
  332. {modwire-9.2.0 → modwire-9.2.1}/tests/extraction/scan_benchmark/prepare.py +0 -0
  333. {modwire-9.2.0 → modwire-9.2.1}/tests/extraction/scan_benchmark/results.json +0 -0
  334. {modwire-9.2.0 → modwire-9.2.1}/tests/extraction/scan_benchmark/run.py +0 -0
  335. {modwire-9.2.0 → modwire-9.2.1}/tests/fixtures/languages/php/ignored/example_generated.php +0 -0
  336. {modwire-9.2.0 → modwire-9.2.1}/tests/fixtures/languages/php/src/example_application/example_actions/example_action.php +0 -0
  337. {modwire-9.2.0 → modwire-9.2.1}/tests/fixtures/languages/php/src/example_domain/example_model/example_record.php +0 -0
  338. {modwire-9.2.0 → modwire-9.2.1}/tests/fixtures/languages/php/src/example_domain/example_services/example_policy.php +0 -0
  339. {modwire-9.2.0 → modwire-9.2.1}/tests/fixtures/languages/php/src/example_interfaces/example_http/example_controller.php +0 -0
  340. {modwire-9.2.0 → modwire-9.2.1}/tests/fixtures/languages/python/ignored/example_generated.py +0 -0
  341. {modwire-9.2.0 → modwire-9.2.1}/tests/fixtures/languages/python/src/example_application/example_actions/example_action.py +0 -0
  342. {modwire-9.2.0 → modwire-9.2.1}/tests/fixtures/languages/python/src/example_domain/example_model/example_record.py +0 -0
  343. {modwire-9.2.0 → modwire-9.2.1}/tests/fixtures/languages/python/src/example_domain/example_services/example_policy.py +0 -0
  344. {modwire-9.2.0 → modwire-9.2.1}/tests/fixtures/languages/python/src/example_interfaces/example_http/example_controller.py +0 -0
  345. {modwire-9.2.0 → modwire-9.2.1}/tests/fixtures/languages/typescript/ignored/example_generated.ts +0 -0
  346. {modwire-9.2.0 → modwire-9.2.1}/tests/fixtures/languages/typescript/src/example_application/example_actions/example_action.ts +0 -0
  347. {modwire-9.2.0 → modwire-9.2.1}/tests/fixtures/languages/typescript/src/example_domain/example_model/example_record.ts +0 -0
  348. {modwire-9.2.0 → modwire-9.2.1}/tests/fixtures/languages/typescript/src/example_domain/example_model/example_view.tsx +0 -0
  349. {modwire-9.2.0 → modwire-9.2.1}/tests/fixtures/languages/typescript/src/example_domain/example_services/example_audit.js +0 -0
  350. {modwire-9.2.0 → modwire-9.2.1}/tests/fixtures/languages/typescript/src/example_domain/example_services/example_callables.ts +0 -0
  351. {modwire-9.2.0 → modwire-9.2.1}/tests/fixtures/languages/typescript/src/example_domain/example_services/example_policy.ts +0 -0
  352. {modwire-9.2.0 → modwire-9.2.1}/tests/fixtures/languages/typescript/src/example_interfaces/example_http/example_controller.ts +0 -0
  353. {modwire-9.2.0 → modwire-9.2.1}/tests/fixtures/languages/typescript/src/example_interfaces/example_http/example_view.jsx +0 -0
  354. {modwire-9.2.0 → modwire-9.2.1}/tests/fixtures/syntax/php/example_shapes.php +0 -0
  355. {modwire-9.2.0 → modwire-9.2.1}/tests/fixtures/syntax/python/example_shapes.py +0 -0
  356. {modwire-9.2.0 → modwire-9.2.1}/tests/fixtures/syntax/typescript/example_shapes.ts +0 -0
  357. {modwire-9.2.0 → modwire-9.2.1}/tests/shared/__init__.py +0 -0
  358. {modwire-9.2.0 → modwire-9.2.1}/tests/shared/code/__init__.py +0 -0
  359. {modwire-9.2.0 → modwire-9.2.1}/tests/shared/code/test_02_invariants.py +0 -0
  360. {modwire-9.2.0 → modwire-9.2.1}/tests/support/__init__.py +0 -0
  361. {modwire-9.2.0 → modwire-9.2.1}/tests/support/base_test.py +0 -0
  362. {modwire-9.2.0 → modwire-9.2.1}/tests/support/code_map.py +0 -0
  363. {modwire-9.2.0 → modwire-9.2.1}/tests/support/service_test.py +0 -0
  364. {modwire-9.2.0 → modwire-9.2.1}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modwire
3
- Version: 9.2.0
3
+ Version: 9.2.1
4
4
  Summary: Code extraction, architecture analysis and the Modwire CLI.
5
5
  Author: Tomasz Szpak
6
6
  License-Expression: MIT
@@ -9,6 +9,12 @@ from ..domain import BaseFlowAnalyzer, FlowAnalyzerInterface
9
9
  from ..models.flow_violation import FlowViolation
10
10
 
11
11
 
12
+ @dataclass(frozen=True)
13
+ class NoReentryTraversalState:
14
+ source_id: str
15
+ exited_modules: frozenset[str]
16
+
17
+
12
18
  @injectable(as_type=FlowAnalyzerInterface, qualifier="no_reentry")
13
19
  @dataclass(frozen=True)
14
20
  class NoReentryFlowAnalyzer(FlowAnalyzerInterface, BaseFlowAnalyzer):
@@ -24,12 +30,14 @@ class NoReentryFlowAnalyzer(FlowAnalyzerInterface, BaseFlowAnalyzer):
24
30
  if not architecture_map.realm.module_tag:
25
31
  return ()
26
32
  violations: list[FlowViolation] = []
33
+ visited: set[NoReentryTraversalState] = set()
27
34
  for root in self.roots(architecture_map):
28
35
  self.walk_dependencies(
29
36
  architecture_map=architecture_map,
30
37
  source_id=root,
31
38
  path=(root,),
32
39
  exited_modules=frozenset(),
40
+ visited=visited,
33
41
  violations=violations,
34
42
  )
35
43
  return self.dedupe(violations)
@@ -41,8 +49,8 @@ class NoReentryFlowAnalyzer(FlowAnalyzerInterface, BaseFlowAnalyzer):
41
49
  if architecture_map.code_map.incoming_dependencies(FileId(source_id)).count() == 0
42
50
  )
43
51
  if roots:
44
- return roots
45
- return architecture_map.code_map.source_ids()
52
+ return tuple(sorted(roots))
53
+ return tuple(sorted(architecture_map.code_map.source_ids()))
46
54
 
47
55
  def walk_dependencies(
48
56
  self,
@@ -50,10 +58,23 @@ class NoReentryFlowAnalyzer(FlowAnalyzerInterface, BaseFlowAnalyzer):
50
58
  source_id: str,
51
59
  path: tuple[str, ...],
52
60
  exited_modules: frozenset[str],
61
+ visited: set[NoReentryTraversalState],
53
62
  violations: list[FlowViolation],
54
63
  ) -> None:
64
+ state = NoReentryTraversalState(source_id=source_id, exited_modules=exited_modules)
65
+ if state in visited:
66
+ return
67
+ visited.add(state)
55
68
  source_module = self.module_for(architecture_map, source_id)
56
- for dependency in architecture_map.code_map.outgoing_dependencies(FileId(source_id)).all():
69
+ dependencies = sorted(
70
+ architecture_map.code_map.outgoing_dependencies(FileId(source_id)).all(),
71
+ key=lambda dependency: (
72
+ dependency.edge.to_id or "",
73
+ dependency.edge.specifier,
74
+ dependency.edge.kind,
75
+ ),
76
+ )
77
+ for dependency in dependencies:
57
78
  target_id = dependency.edge.to_id
58
79
  if target_id is None:
59
80
  continue
@@ -69,14 +90,16 @@ class NoReentryFlowAnalyzer(FlowAnalyzerInterface, BaseFlowAnalyzer):
69
90
  violation_index=len(path),
70
91
  rule_name=self.rule_name(architecture_map),
71
92
  message="module layer re-entered after exit",
93
+ source_module=source_module,
94
+ target_module=target_module,
72
95
  )
73
96
  )
74
97
  continue
75
- if target_id not in path:
76
- self.walk_dependencies(
77
- architecture_map=architecture_map,
78
- source_id=target_id,
79
- path=(*path, target_id),
80
- exited_modules=next_exited,
81
- violations=violations,
82
- )
98
+ self.walk_dependencies(
99
+ architecture_map=architecture_map,
100
+ source_id=target_id,
101
+ path=(*path, target_id),
102
+ exited_modules=next_exited,
103
+ visited=visited,
104
+ violations=violations,
105
+ )
@@ -0,0 +1,143 @@
1
+ import time
2
+
3
+ import pytest
4
+
5
+ from .base_test import BoundaryTestCase
6
+
7
+
8
+ class TestFlowPaths(BoundaryTestCase):
9
+ @pytest.mark.parametrize("reverse", (False, True))
10
+ def test_layer_order_distinguishes_forward_and_backward_edges(self, reverse: bool) -> None:
11
+ config = self.application.configure(
12
+ {
13
+ "boundaries": {
14
+ "tags": [
15
+ {"name": "example-entry", "match": "src/example_entry"},
16
+ {"name": "example-core", "match": "src/example_core"},
17
+ ],
18
+ "flow": {
19
+ "layers": ["example-entry", "example-core"],
20
+ "analyzers": ["backward-flow"],
21
+ },
22
+ },
23
+ "shape": {"realms": [{"name": "example-source", "match": "src"}]},
24
+ }
25
+ )
26
+ paths = ("src/example_entry/example_entry.source", "src/example_core/example_core.source")
27
+ source, target = tuple(reversed(paths)) if reverse else paths
28
+ result = self.violations(config, source, target)
29
+ assert result == ((source, target),) if reverse else result == ()
30
+
31
+ @pytest.mark.parametrize("reenters", (False, True))
32
+ def test_reentry_reports_the_complete_dependency_path(self, reenters: bool) -> None:
33
+ config = self.application.configure(
34
+ {
35
+ "boundaries": {
36
+ "tags": [{"name": "example-module", "match": "src/*"}],
37
+ "flow": {"module_tag": "example-module", "analyzers": ["no-reentry"]},
38
+ },
39
+ "shape": {"realms": [{"name": "example-source", "match": "src"}]},
40
+ }
41
+ )
42
+ target_module = "example_first" if reenters else "example_third"
43
+ paths = (
44
+ "src/example_first/example_entry.source",
45
+ "src/example_second/example_middle.source",
46
+ f"src/{target_module}/example_target.source",
47
+ )
48
+ edges = tuple((paths[a], paths[b], "resolved", "example.target") for a, b in ((0, 1), (1, 2)))
49
+ report = self.report("architecture.violations.flow", config, self.queryable_map(paths, edges))
50
+ assert tuple(item.path for item in report.violations) == ((paths,) if reenters else ())
51
+ if reenters:
52
+ assert report.violations[0].violation_index == 2
53
+ assert report.violations[0].violation_type == "no-reentry"
54
+ assert report.violations[0].source_module == "example_second"
55
+ assert report.violations[0].target_module == "example_first"
56
+
57
+ def test_reentry_analysis_bounds_converging_dependency_paths(self) -> None:
58
+ config = self.application.configure(
59
+ {
60
+ "boundaries": {
61
+ "tags": [{"name": "example-module", "match": "src/*"}],
62
+ "flow": {"module_tag": "example-module", "analyzers": ["no-reentry"]},
63
+ },
64
+ "shape": {"realms": [{"name": "example-source", "match": "src"}]},
65
+ }
66
+ )
67
+ paths = ["src/example_module/example_root.source"]
68
+ levels: list[tuple[str, str]] = []
69
+ for level in range(18):
70
+ nodes = (
71
+ f"src/example_module/example_{level}_a.source",
72
+ f"src/example_module/example_{level}_b.source",
73
+ )
74
+ paths.extend(nodes)
75
+ levels.append(nodes)
76
+ paths.append("src/example_module/example_target.source")
77
+ edges: list[tuple[str, str | None, str, str]] = []
78
+ previous = (paths[0],)
79
+ for current in levels:
80
+ edges.extend((source, target, "resolved", "example.target") for source in previous for target in current)
81
+ previous = current
82
+ edges.extend((source, paths[-1], "resolved", "example.target") for source in previous)
83
+ code_map = self.queryable_map(tuple(paths), tuple(edges))
84
+ started = time.perf_counter()
85
+ report = self.report("architecture.violations.flow", config, code_map)
86
+ elapsed = time.perf_counter() - started
87
+ assert not report.violations
88
+ assert elapsed < 1.0
89
+
90
+ def test_reentry_analysis_preserves_distinct_states_across_repeated_dependencies_and_cycles(self) -> None:
91
+ config = self.application.configure(
92
+ {
93
+ "boundaries": {
94
+ "tags": [{"name": "example-module", "match": "src/*"}],
95
+ "flow": {"module_tag": "example-module", "analyzers": ["no-reentry"]},
96
+ },
97
+ "shape": {"realms": [{"name": "example-source", "match": "src"}]},
98
+ }
99
+ )
100
+ root = "src/example_entry/example_root.source"
101
+ first = "src/example_first/example_branch.source"
102
+ second = "src/example_second/example_branch.source"
103
+ shared = "src/example_shared/example_shared.source"
104
+ first_target = "src/example_first/example_target.source"
105
+ second_target = "src/example_second/example_target.source"
106
+ loop_one = "src/example_entry/example_loop_one.source"
107
+ loop_two = "src/example_entry/example_loop_two.source"
108
+ paths = (root, first, second, shared, first_target, second_target, loop_one, loop_two)
109
+ edges = (
110
+ (root, first, "resolved", "example.first"),
111
+ (root, first, "resolved", "example.first"),
112
+ (root, second, "resolved", "example.second"),
113
+ (first, shared, "resolved", "example.shared"),
114
+ (second, shared, "resolved", "example.shared"),
115
+ (shared, first_target, "resolved", "example.first_target"),
116
+ (shared, second_target, "resolved", "example.second_target"),
117
+ (root, loop_one, "resolved", "example.loop_one"),
118
+ (loop_one, loop_two, "resolved", "example.loop_two"),
119
+ (loop_two, loop_one, "resolved", "example.loop_one"),
120
+ )
121
+ report = self.report("architecture.violations.flow", config, self.queryable_map(paths, edges))
122
+ assert tuple(
123
+ (violation.path, violation.violation_index, violation.source_module, violation.target_module)
124
+ for violation in report.violations
125
+ ) == (
126
+ ((root, first, shared, first_target), 3, "example_shared", "example_first"),
127
+ ((root, second, shared, second_target), 3, "example_shared", "example_second"),
128
+ )
129
+
130
+ def test_cycles_are_reported_once_without_a_graph_root(self) -> None:
131
+ config = self.application.configure(
132
+ {
133
+ "boundaries": {
134
+ "tags": [{"name": "example-module", "match": "src/*"}],
135
+ "flow": {"module_tag": "example-module", "analyzers": ["no-cycles"]},
136
+ },
137
+ "shape": {"realms": [{"name": "example-source", "match": "src"}]},
138
+ }
139
+ )
140
+ paths = ("src/example_first/example_first.source", "src/example_second/example_second.source")
141
+ edges = tuple((paths[a], paths[b], "resolved", "example.target") for a, b in ((0, 1), (1, 0)))
142
+ report = self.report("architecture.violations.flow", config, self.queryable_map(paths, edges))
143
+ assert tuple(item.path for item in report.violations) == (("example_first", "example_second", "example_first"),)
@@ -1,66 +0,0 @@
1
- import pytest
2
-
3
- from .base_test import BoundaryTestCase
4
-
5
-
6
- class TestFlowPaths(BoundaryTestCase):
7
- @pytest.mark.parametrize("reverse", (False, True))
8
- def test_layer_order_distinguishes_forward_and_backward_edges(self, reverse: bool) -> None:
9
- config = self.application.configure(
10
- {
11
- "boundaries": {
12
- "tags": [
13
- {"name": "example-entry", "match": "src/example_entry"},
14
- {"name": "example-core", "match": "src/example_core"},
15
- ],
16
- "flow": {
17
- "layers": ["example-entry", "example-core"],
18
- "analyzers": ["backward-flow"],
19
- },
20
- },
21
- "shape": {"realms": [{"name": "example-source", "match": "src"}]},
22
- }
23
- )
24
- paths = ("src/example_entry/example_entry.source", "src/example_core/example_core.source")
25
- source, target = tuple(reversed(paths)) if reverse else paths
26
- result = self.violations(config, source, target)
27
- assert result == ((source, target),) if reverse else result == ()
28
-
29
- @pytest.mark.parametrize("reenters", (False, True))
30
- def test_reentry_reports_the_complete_dependency_path(self, reenters: bool) -> None:
31
- config = self.application.configure(
32
- {
33
- "boundaries": {
34
- "tags": [{"name": "example-module", "match": "src/*"}],
35
- "flow": {"module_tag": "example-module", "analyzers": ["no-reentry"]},
36
- },
37
- "shape": {"realms": [{"name": "example-source", "match": "src"}]},
38
- }
39
- )
40
- target_module = "example_first" if reenters else "example_third"
41
- paths = (
42
- "src/example_first/example_entry.source",
43
- "src/example_second/example_middle.source",
44
- f"src/{target_module}/example_target.source",
45
- )
46
- edges = tuple((paths[a], paths[b], "resolved", "example.target") for a, b in ((0, 1), (1, 2)))
47
- report = self.report("architecture.violations.flow", config, self.queryable_map(paths, edges))
48
- assert tuple(item.path for item in report.violations) == ((paths,) if reenters else ())
49
- if reenters:
50
- assert report.violations[0].violation_index == 2
51
- assert report.violations[0].violation_type == "no-reentry"
52
-
53
- def test_cycles_are_reported_once_without_a_graph_root(self) -> None:
54
- config = self.application.configure(
55
- {
56
- "boundaries": {
57
- "tags": [{"name": "example-module", "match": "src/*"}],
58
- "flow": {"module_tag": "example-module", "analyzers": ["no-cycles"]},
59
- },
60
- "shape": {"realms": [{"name": "example-source", "match": "src"}]},
61
- }
62
- )
63
- paths = ("src/example_first/example_first.source", "src/example_second/example_second.source")
64
- edges = tuple((paths[a], paths[b], "resolved", "example.target") for a, b in ((0, 1), (1, 0)))
65
- report = self.report("architecture.violations.flow", config, self.queryable_map(paths, edges))
66
- assert tuple(item.path for item in report.violations) == (("example_first", "example_second", "example_first"),)
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