forward-netbox 2.0.2__tar.gz → 2.0.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 (263) hide show
  1. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/PKG-INFO +4 -2
  2. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/README.md +3 -1
  3. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/__init__.py +1 -1
  4. forward_netbox-2.0.4/forward_netbox/tests/test_module_readiness_rollup.py +89 -0
  5. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/tests/test_sync.py +26 -538
  6. forward_netbox-2.0.4/forward_netbox/utilities/fast_bootstrap_executor.py +81 -0
  7. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/sync.py +10 -0
  8. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/sync_inventory_module.py +2 -0
  9. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/sync_reporting.py +51 -4
  10. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/sync_runner_contracts.py +4 -1
  11. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/pyproject.toml +1 -1
  12. forward_netbox-2.0.2/forward_netbox/utilities/fast_bootstrap_executor.py +0 -248
  13. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/LICENSE +0 -0
  14. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/api/__init__.py +0 -0
  15. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/api/serializers.py +0 -0
  16. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/api/urls.py +0 -0
  17. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/api/views.py +0 -0
  18. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/choices.py +0 -0
  19. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/exceptions.py +0 -0
  20. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/filtersets.py +0 -0
  21. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/forms.py +0 -0
  22. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/jobs.py +0 -0
  23. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/management/__init__.py +0 -0
  24. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/management/commands/__init__.py +0 -0
  25. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/management/commands/forward_apic_cimc_readiness_audit.py +0 -0
  26. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/management/commands/forward_blocker_audit.py +0 -0
  27. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/management/commands/forward_collection_gap_alert.py +0 -0
  28. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/management/commands/forward_device_scope_reconciliation_audit.py +0 -0
  29. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/management/commands/forward_module_readiness.py +0 -0
  30. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/management/commands/forward_pushdown_profile.py +0 -0
  31. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/management/commands/forward_query_diff_coverage_audit.py +0 -0
  32. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/management/commands/forward_seed_ui_harness.py +0 -0
  33. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/management/commands/forward_validation_org_query_audit.py +0 -0
  34. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/migrations/0001_initial.py +0 -0
  35. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/migrations/0002_add_coalesce_fields.py +0 -0
  36. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/migrations/0003_forwardingestionissue_context_fields.py +0 -0
  37. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/migrations/0004_forwardingestion_baseline_fields.py +0 -0
  38. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/migrations/0005_validation_and_reporting.py +0 -0
  39. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/migrations/0006_alter_forwardnqemap_netbox_model.py +0 -0
  40. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/migrations/0007_forwardingestion_persisted_change_counters.py +0 -0
  41. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/migrations/0008_alter_forwardnqemap_netbox_model.py +0 -0
  42. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/migrations/0009_alter_forwardnqemap_netbox_model.py +0 -0
  43. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/migrations/0010_forwardvalidationrun_override_applied_and_more.py +0 -0
  44. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/migrations/0011_forwardingestion_change_request_id.py +0 -0
  45. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/migrations/0012_forwardnqemap_query_reference.py +0 -0
  46. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/migrations/0013_execution_run_step.py +0 -0
  47. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/migrations/0014_execution_step_fetch_scope.py +0 -0
  48. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/migrations/0015_execution_step_apply_engine.py +0 -0
  49. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/migrations/0016_execution_step_query_metrics.py +0 -0
  50. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/migrations/0017_execution_step_row_counters.py +0 -0
  51. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/migrations/0018_execution_run_reconciliation_events.py +0 -0
  52. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/migrations/0019_forwardexecutionstep_query_parameters.py +0 -0
  53. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/migrations/0020_execution_step_operation.py +0 -0
  54. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/migrations/0021_add_fhrpgroup_nqe_map_choice.py +0 -0
  55. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/migrations/0022_alter_forwardnqemap_netbox_model.py +0 -0
  56. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/migrations/0023_split_ip_address_maps.py +0 -0
  57. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/migrations/0024_forwarddeviceanalysis.py +0 -0
  58. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/migrations/0025_device_analysis_netboxmodel.py +0 -0
  59. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/migrations/0026_forwarddeviceanalysis_collection_result.py +0 -0
  60. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/migrations/0027_alter_forwardexecutionrun_backend.py +0 -0
  61. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/migrations/0028_remove_forwardexecutionstep_run_and_more.py +0 -0
  62. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/migrations/__init__.py +0 -0
  63. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/models.py +0 -0
  64. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/navigation.py +0 -0
  65. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/queries/__init__.py +0 -0
  66. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/queries/forward_aci_apic_cimc_inventory.nqe +0 -0
  67. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/queries/forward_aci_apic_nodes.nqe +0 -0
  68. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/queries/forward_aci_app_profiles.nqe +0 -0
  69. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/queries/forward_aci_bridge_domains.nqe +0 -0
  70. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/queries/forward_aci_command_inventory.nqe +0 -0
  71. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/queries/forward_aci_contracts.nqe +0 -0
  72. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/queries/forward_aci_endpoint_groups.nqe +0 -0
  73. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/queries/forward_aci_fabrics.nqe +0 -0
  74. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/queries/forward_aci_filters.nqe +0 -0
  75. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/queries/forward_aci_l3outs.nqe +0 -0
  76. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/queries/forward_aci_nodes.nqe +0 -0
  77. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/queries/forward_aci_pods.nqe +0 -0
  78. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/queries/forward_aci_static_port_bindings.nqe +0 -0
  79. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/queries/forward_aci_tenants.nqe +0 -0
  80. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/queries/forward_aci_vrfs.nqe +0 -0
  81. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/queries/forward_bgp_address_families.nqe +0 -0
  82. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/queries/forward_bgp_peer_address_families.nqe +0 -0
  83. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/queries/forward_bgp_peers.nqe +0 -0
  84. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/queries/forward_device_analysis.nqe +0 -0
  85. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/queries/forward_device_feature_tags.nqe +0 -0
  86. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/queries/forward_device_feature_tags_with_rules.nqe +0 -0
  87. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/queries/forward_device_models.nqe +0 -0
  88. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/queries/forward_device_models_with_netbox_aliases.nqe +0 -0
  89. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/queries/forward_device_types.nqe +0 -0
  90. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/queries/forward_device_vendors.nqe +0 -0
  91. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/queries/forward_devices.nqe +0 -0
  92. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/queries/forward_devices_with_netbox_aliases.nqe +0 -0
  93. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/queries/forward_hsrp_groups.nqe +0 -0
  94. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/queries/forward_inferred_interface_cables.nqe +0 -0
  95. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/queries/forward_interfaces.nqe +0 -0
  96. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/queries/forward_inventory_items.nqe +0 -0
  97. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/queries/forward_ip_addresses_ipv4.nqe +0 -0
  98. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/queries/forward_ip_addresses_ipv6.nqe +0 -0
  99. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/queries/forward_ip_addresses_unassignable_diagnostics.nqe +0 -0
  100. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/queries/forward_locations.nqe +0 -0
  101. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/queries/forward_mac_addresses.nqe +0 -0
  102. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/queries/forward_modules.nqe +0 -0
  103. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/queries/forward_ospf_areas.nqe +0 -0
  104. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/queries/forward_ospf_instances.nqe +0 -0
  105. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/queries/forward_ospf_interfaces.nqe +0 -0
  106. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/queries/forward_peering_sessions.nqe +0 -0
  107. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/queries/forward_platforms.nqe +0 -0
  108. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/queries/forward_prefixes_ipv4.nqe +0 -0
  109. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/queries/forward_prefixes_ipv6.nqe +0 -0
  110. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/queries/forward_routing_import_diagnostics.nqe +0 -0
  111. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/queries/forward_virtual_chassis.nqe +0 -0
  112. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/queries/forward_vlans.nqe +0 -0
  113. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/queries/forward_vrfs.nqe +0 -0
  114. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/queries/netbox_utilities.nqe +0 -0
  115. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/signals.py +0 -0
  116. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/tables.py +0 -0
  117. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/template_content.py +0 -0
  118. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/templates/forward_netbox/forwarddriftpolicy.html +0 -0
  119. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/templates/forward_netbox/forwardingestion.html +0 -0
  120. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/templates/forward_netbox/forwardnqemap.html +0 -0
  121. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/templates/forward_netbox/forwardsource.html +0 -0
  122. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/templates/forward_netbox/forwardsync.html +0 -0
  123. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/templates/forward_netbox/forwardsync_dependency_preview.html +0 -0
  124. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/templates/forward_netbox/forwardsync_drift_report.html +0 -0
  125. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/templates/forward_netbox/forwardsync_health.html +0 -0
  126. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/templates/forward_netbox/forwardsync_module_readiness.html +0 -0
  127. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/templates/forward_netbox/forwardsync_scope_reconciliation.html +0 -0
  128. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/templates/forward_netbox/forwardvalidationrun.html +0 -0
  129. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/templates/forward_netbox/inc/device_analysis_panel.html +0 -0
  130. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/templates/forward_netbox/inc/diff.html +0 -0
  131. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/templates/forward_netbox/inc/execution_insights.html +0 -0
  132. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/templates/forward_netbox/inc/logs_pending.html +0 -0
  133. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/templates/forward_netbox/inc/merge_form.html +0 -0
  134. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/templates/forward_netbox/inc/validation_force_allow_form.html +0 -0
  135. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/templates/forward_netbox/partials/change_explainability.html +0 -0
  136. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/templates/forward_netbox/partials/ingestion_all.html +0 -0
  137. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/templates/forward_netbox/partials/ingestion_merge_button.html +0 -0
  138. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/templates/forward_netbox/partials/ingestion_progress.html +0 -0
  139. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/templates/forward_netbox/partials/ingestion_statistics.html +0 -0
  140. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/templates/forward_netbox/partials/ingestion_status.html +0 -0
  141. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/templates/forward_netbox/partials/job_logs.html +0 -0
  142. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/templates/forward_netbox/partials/object_tabs.html +0 -0
  143. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/templates/forward_netbox/partials/stage_switcher_buttons.html +0 -0
  144. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/templates/forward_netbox/partials/validation_force_allow_button.html +0 -0
  145. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/templatetags/__init__.py +0 -0
  146. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/templatetags/forward_netbox_helpers.py +0 -0
  147. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/tests/__init__.py +0 -0
  148. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/tests/fixtures/aci_command_inventory_expected.json +0 -0
  149. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/tests/fixtures/aci_discovery_expected.json +0 -0
  150. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/tests/scenarios.py +0 -0
  151. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/tests/test_api_usage.py +0 -0
  152. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/tests/test_api_views.py +0 -0
  153. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/tests/test_apic_cimc_readiness_audit_command.py +0 -0
  154. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/tests/test_apply_engine.py +0 -0
  155. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/tests/test_branching.py +0 -0
  156. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/tests/test_bulk_adapter_parity.py +0 -0
  157. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/tests/test_bulk_merge.py +0 -0
  158. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/tests/test_bulk_merge_scale.py +0 -0
  159. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/tests/test_device_scope_reconciliation_audit_command.py +0 -0
  160. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/tests/test_device_scope_tagging.py +0 -0
  161. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/tests/test_forms.py +0 -0
  162. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/tests/test_forward_api.py +0 -0
  163. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/tests/test_health.py +0 -0
  164. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/tests/test_ingestion_merge.py +0 -0
  165. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/tests/test_interface_naming.py +0 -0
  166. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/tests/test_ipaddress_dup_global.py +0 -0
  167. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/tests/test_issue_rendering.py +0 -0
  168. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/tests/test_job_compat.py +0 -0
  169. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/tests/test_job_liveness.py +0 -0
  170. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/tests/test_jobs.py +0 -0
  171. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/tests/test_log_export.py +0 -0
  172. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/tests/test_logging.py +0 -0
  173. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/tests/test_models.py +0 -0
  174. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/tests/test_module_readiness.py +0 -0
  175. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/tests/test_plugin_integrations.py +0 -0
  176. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/tests/test_primary_ip.py +0 -0
  177. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/tests/test_primary_ip_integration.py +0 -0
  178. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/tests/test_query_binding.py +0 -0
  179. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/tests/test_query_diff_coverage_audit_command.py +0 -0
  180. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/tests/test_query_registry.py +0 -0
  181. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/tests/test_release_readiness_audit.py +0 -0
  182. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/tests/test_runtime_dependency_check.py +0 -0
  183. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/tests/test_scope_matched_tags.py +0 -0
  184. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/tests/test_scope_module_ui.py +0 -0
  185. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/tests/test_sensitive_content.py +0 -0
  186. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/tests/test_stability_hardening.py +0 -0
  187. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/tests/test_sync_aci.py +0 -0
  188. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/tests/test_sync_facade.py +0 -0
  189. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/tests/test_sync_orchestration.py +0 -0
  190. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/tests/test_sync_runner_contracts.py +0 -0
  191. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/tests/test_sync_state.py +0 -0
  192. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/tests/test_synthetic_scenarios.py +0 -0
  193. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/tests/test_validation_org_query_audit_command.py +0 -0
  194. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/urls.py +0 -0
  195. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/__init__.py +0 -0
  196. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/api_usage.py +0 -0
  197. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/apply_engine.py +0 -0
  198. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/apply_engine_bulk.py +0 -0
  199. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/apply_engine_decision.py +0 -0
  200. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/branch_budget.py +0 -0
  201. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/branching.py +0 -0
  202. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/bulk_merge.py +0 -0
  203. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/change_explainability.py +0 -0
  204. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/density_learning.py +0 -0
  205. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/device_analysis.py +0 -0
  206. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/direct_changes.py +0 -0
  207. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/drift_report.py +0 -0
  208. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/execution_ledger.py +0 -0
  209. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/execution_telemetry.py +0 -0
  210. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/fetch_artifacts.py +0 -0
  211. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/forward_api.py +0 -0
  212. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/forward_api_impl.py +0 -0
  213. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/health.py +0 -0
  214. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/health_apply_fetch.py +0 -0
  215. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/health_checks.py +0 -0
  216. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/health_summary_blocks.py +0 -0
  217. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/ingestion_issues.py +0 -0
  218. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/ingestion_merge.py +0 -0
  219. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/ingestion_presentation.py +0 -0
  220. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/interface_naming.py +0 -0
  221. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/job_compat.py +0 -0
  222. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/job_liveness.py +0 -0
  223. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/json_safe.py +0 -0
  224. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/logging.py +0 -0
  225. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/merge.py +0 -0
  226. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/model_contracts.py +0 -0
  227. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/model_validation.py +0 -0
  228. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/module_readiness.py +0 -0
  229. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/multi_branch_lifecycle.py +0 -0
  230. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/plugin_integrations/__init__.py +0 -0
  231. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/plugin_integrations/registry.py +0 -0
  232. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/primary_ip.py +0 -0
  233. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/query_binding.py +0 -0
  234. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/query_binding_resolution.py +0 -0
  235. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/query_diagnostics.py +0 -0
  236. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/query_fetch.py +0 -0
  237. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/query_fetch_execution.py +0 -0
  238. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/query_registry.py +0 -0
  239. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/runtime_guidance.py +0 -0
  240. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/scope_reconciliation.py +0 -0
  241. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/sensitive_content.py +0 -0
  242. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/single_branch_executor.py +0 -0
  243. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/snapshot_freshness.py +0 -0
  244. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/support_bundle_archive.py +0 -0
  245. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/sync_aci.py +0 -0
  246. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/sync_cable.py +0 -0
  247. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/sync_contracts.py +0 -0
  248. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/sync_core_models.py +0 -0
  249. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/sync_device.py +0 -0
  250. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/sync_events.py +0 -0
  251. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/sync_execution.py +0 -0
  252. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/sync_facade.py +0 -0
  253. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/sync_interface.py +0 -0
  254. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/sync_ipam.py +0 -0
  255. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/sync_orchestration.py +0 -0
  256. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/sync_primitives.py +0 -0
  257. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/sync_routing.py +0 -0
  258. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/sync_routing_impl.py +0 -0
  259. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/sync_runner_adapters.py +0 -0
  260. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/sync_state.py +0 -0
  261. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/validation.py +0 -0
  262. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/utilities/validation_org_query.py +0 -0
  263. {forward_netbox-2.0.2 → forward_netbox-2.0.4}/forward_netbox/views.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: forward-netbox
3
- Version: 2.0.2
3
+ Version: 2.0.4
4
4
  Summary: NetBox plugin to sync Forward data into NetBox via built-in NQE queries
5
5
  License: MIT
6
6
  License-File: LICENSE
@@ -31,7 +31,9 @@ Forward 26.6 is the baseline for async NQE.
31
31
 
32
32
  | Plugin Release | NetBox Version | Status |
33
33
  | --- | --- | --- |
34
- | `v2.0.2` | `4.6.3` required; needs netbox-branching `1.1.0+` | Current release; Patch: apply_device_scope_tags now works with multiple include tags in `any` match mode each device is tagged with exactly the include tag(s) it carries (resolved per-device at fetch time), instead of skipping. Also silences the spurious `Skipping untagged VLAN 1` warning (VID 1 is NetBox's implicit access default and is intentionally not imported). No engine/schema changes; drop-in from `2.0.1`, no org republish |
34
+ | `v2.0.4` | `4.6.3` required; needs netbox-branching `1.1.0+` | Current release; Patch: collapse the module-sync readiness warning wall into ONE summary. When module sync is enabled before a device's module bays exist in NetBox, every module row is skipped; 2.0.3 capped the per-row lines at 3, this replaces them entirely with a single actionable line per sync (total skipped + a few examples + the `forward_module_readiness` remedy). Other skip reasons are unchanged. No engine/schema/org changes; drop-in from `2.0.3` |
35
+ | `v2.0.3` | `4.6.3` required; needs netbox-branching `1.1.0+` | Superseded by `v2.0.4`; Patch: (1) module-sync readiness warnings no longer flood the log — the per-row `module bay does not exist; run forward_module_readiness` skip is capped to a few examples plus a suppressed-count summary (was up to 20 near-identical lines per sync); (2) fixes the release `CI` gate (`CHANGELOG matches README`) that had been red since v1.7.2 — the generator no longer depends on git tag-date timing; (3) removes dead executor code (`ForwardFastBootstrapExecutor.run`) and refreshes stale internal docs. No engine/schema changes; drop-in from `2.0.2` |
36
+ | `v2.0.2` | `4.6.3` required; needs netbox-branching `1.1.0+` | Superseded by `v2.0.3`; Patch: apply_device_scope_tags now works with multiple include tags in `any` match mode — each device is tagged with exactly the include tag(s) it carries (resolved per-device at fetch time), instead of skipping. Also silences the spurious `Skipping untagged VLAN 1` warning (VID 1 is NetBox's implicit access default and is intentionally not imported). No engine/schema changes; drop-in from `2.0.1`, no org republish |
35
37
  | `v2.0.1` | `4.6.3` required; needs netbox-branching `1.1.0+` | Superseded by `v2.0.2`; Patch: fixes two 2.0.0 regressions an operator hits immediately — a false `netbox_branching is not installed; syncs will fail` startup warning (the dependency check used the wrong distribution name), and a 500 on the Sync list page (`KeyError: 'available'` from a removed execution-ledger summary). No engine or data changes; drop-in upgrade from `2.0.0` |
36
38
  | `v2.0.0` | `4.6.3` required; needs netbox-branching `1.1.0+` | Superseded by `v2.0.1`; Breaking 2.0 — single-branch is the only execution path. Removed the per-shard branching/fast-bootstrap/resumable executor, 10k-change budget sharding, and the execution-ledger run-history; dropped the backend/max-changes/scheduler-overlap selectors |
37
39
  | `v1.7.2` | `4.6.3` required (4.5.x dropped); needs netbox-branching `1.1.0+` | Superseded by `v2.0.0`; Collection-gap diagnostics: per-reason backfill breakdown + staleness, growth/trend escalation, per-device collection result, ACI delete safety valve, opt-in auto-tag |
@@ -8,7 +8,9 @@ Forward 26.6 is the baseline for async NQE.
8
8
 
9
9
  | Plugin Release | NetBox Version | Status |
10
10
  | --- | --- | --- |
11
- | `v2.0.2` | `4.6.3` required; needs netbox-branching `1.1.0+` | Current release; Patch: apply_device_scope_tags now works with multiple include tags in `any` match mode each device is tagged with exactly the include tag(s) it carries (resolved per-device at fetch time), instead of skipping. Also silences the spurious `Skipping untagged VLAN 1` warning (VID 1 is NetBox's implicit access default and is intentionally not imported). No engine/schema changes; drop-in from `2.0.1`, no org republish |
11
+ | `v2.0.4` | `4.6.3` required; needs netbox-branching `1.1.0+` | Current release; Patch: collapse the module-sync readiness warning wall into ONE summary. When module sync is enabled before a device's module bays exist in NetBox, every module row is skipped; 2.0.3 capped the per-row lines at 3, this replaces them entirely with a single actionable line per sync (total skipped + a few examples + the `forward_module_readiness` remedy). Other skip reasons are unchanged. No engine/schema/org changes; drop-in from `2.0.3` |
12
+ | `v2.0.3` | `4.6.3` required; needs netbox-branching `1.1.0+` | Superseded by `v2.0.4`; Patch: (1) module-sync readiness warnings no longer flood the log — the per-row `module bay does not exist; run forward_module_readiness` skip is capped to a few examples plus a suppressed-count summary (was up to 20 near-identical lines per sync); (2) fixes the release `CI` gate (`CHANGELOG matches README`) that had been red since v1.7.2 — the generator no longer depends on git tag-date timing; (3) removes dead executor code (`ForwardFastBootstrapExecutor.run`) and refreshes stale internal docs. No engine/schema changes; drop-in from `2.0.2` |
13
+ | `v2.0.2` | `4.6.3` required; needs netbox-branching `1.1.0+` | Superseded by `v2.0.3`; Patch: apply_device_scope_tags now works with multiple include tags in `any` match mode — each device is tagged with exactly the include tag(s) it carries (resolved per-device at fetch time), instead of skipping. Also silences the spurious `Skipping untagged VLAN 1` warning (VID 1 is NetBox's implicit access default and is intentionally not imported). No engine/schema changes; drop-in from `2.0.1`, no org republish |
12
14
  | `v2.0.1` | `4.6.3` required; needs netbox-branching `1.1.0+` | Superseded by `v2.0.2`; Patch: fixes two 2.0.0 regressions an operator hits immediately — a false `netbox_branching is not installed; syncs will fail` startup warning (the dependency check used the wrong distribution name), and a 500 on the Sync list page (`KeyError: 'available'` from a removed execution-ledger summary). No engine or data changes; drop-in upgrade from `2.0.0` |
13
15
  | `v2.0.0` | `4.6.3` required; needs netbox-branching `1.1.0+` | Superseded by `v2.0.1`; Breaking 2.0 — single-branch is the only execution path. Removed the per-shard branching/fast-bootstrap/resumable executor, 10k-change budget sharding, and the execution-ledger run-history; dropped the backend/max-changes/scheduler-overlap selectors |
14
16
  | `v1.7.2` | `4.6.3` required (4.5.x dropped); needs netbox-branching `1.1.0+` | Superseded by `v2.0.0`; Collection-gap diagnostics: per-reason backfill breakdown + staleness, growth/trend escalation, per-device collection result, ACI delete safety valve, opt-in auto-tag |
@@ -8,7 +8,7 @@ class NetboxForwardConfig(PluginConfig):
8
8
  name = "forward_netbox"
9
9
  verbose_name = "NetBox Forward Plugin"
10
10
  description = "Sync Forward data into NetBox using built-in NQE queries."
11
- version = "2.0.2"
11
+ version = "2.0.4"
12
12
  base_url = "forward"
13
13
  min_version = "4.6.3"
14
14
 
@@ -0,0 +1,89 @@
1
+ from unittest.mock import Mock
2
+
3
+ from django.test import TestCase
4
+
5
+ from forward_netbox.models import ForwardSource
6
+ from forward_netbox.models import ForwardSync
7
+ from forward_netbox.utilities.sync import ForwardSyncRunner
8
+
9
+
10
+ class ModuleReadinessRollupTest(TestCase):
11
+ """A systemic module-readiness gap (module sync enabled before the device's
12
+ module bays exist) skips every module row. Those skips must collapse into ONE
13
+ actionable summary, not a per-row wall — while ordinary per-row skip reasons
14
+ keep their first-N-then-suppressed behavior."""
15
+
16
+ def _runner(self):
17
+ source = ForwardSource.objects.create(
18
+ name=f"mr-src-{ForwardSource.objects.count()}",
19
+ type="saas",
20
+ url="https://fwd.app",
21
+ status="ready",
22
+ parameters={
23
+ "username": "u",
24
+ "password": "p",
25
+ "verify": True,
26
+ "network_id": "n",
27
+ },
28
+ )
29
+ sync = ForwardSync.objects.create(
30
+ name=f"mr-sync-{source.pk}",
31
+ source=source,
32
+ parameters={"snapshot_id": "x"},
33
+ )
34
+ return ForwardSyncRunner(sync=sync, ingestion=None, client=None, logger_=Mock())
35
+
36
+ def _warnings(self, runner):
37
+ return [c.args[0] for c in runner.logger.log_warning.call_args_list if c.args]
38
+
39
+ def test_module_bay_skips_collapse_to_one_summary(self):
40
+ runner = self._runner()
41
+ for i in range(12):
42
+ runner._record_aggregated_skip_warning(
43
+ model_string="dcim.module",
44
+ reason="missing-module-bay",
45
+ warning_message="per-row text that must NOT be logged",
46
+ sample=f"dev{i}/module 0",
47
+ )
48
+ # Nothing logged per row during the model apply.
49
+ self.assertEqual(self._warnings(runner), [])
50
+
51
+ runner._emit_aggregated_skip_warning_summaries("dcim.module")
52
+ warns = self._warnings(runner)
53
+ self.assertEqual(len(warns), 1)
54
+ summary = warns[0]
55
+ self.assertIn("Skipped 12 dcim.module row(s)", summary)
56
+ self.assertIn("forward_module_readiness", summary)
57
+ self.assertIn("dev0/module 0", summary) # an example is shown
58
+ self.assertIn("(+7 more)", summary) # 12 total - 5 sampled = 7
59
+
60
+ def test_few_skips_show_all_examples_no_more_suffix(self):
61
+ runner = self._runner()
62
+ for name in ("a", "b", "c"):
63
+ runner._record_aggregated_skip_warning(
64
+ model_string="dcim.module",
65
+ reason="missing-module-bay",
66
+ warning_message="x",
67
+ sample=f"{name}/module 0",
68
+ )
69
+ runner._emit_aggregated_skip_warning_summaries("dcim.module")
70
+ summary = self._warnings(runner)[0]
71
+ self.assertIn("Skipped 3 dcim.module row(s)", summary)
72
+ self.assertNotIn("more)", summary)
73
+
74
+ def test_non_rollup_reason_keeps_per_row_then_suppressed(self):
75
+ # Regression guard: ordinary skip reasons are unchanged by the rollup.
76
+ runner = self._runner()
77
+ for i in range(22):
78
+ runner._record_aggregated_skip_warning(
79
+ model_string="dcim.macaddress",
80
+ reason="missing-interface",
81
+ warning_message=f"skip {i}",
82
+ )
83
+ # First CONFLICT_WARNING_DETAIL_LIMIT (20) logged per row.
84
+ self.assertEqual(len(self._warnings(runner)), 20)
85
+
86
+ runner._emit_aggregated_skip_warning_summaries("dcim.macaddress")
87
+ summary = self._warnings(runner)[-1]
88
+ self.assertIn("Suppressed 2 additional", summary)
89
+ self.assertIn("missing-interface", summary)