roadmap-cli 0.1.1__py3-none-any.whl
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.
- roadmap/__init__.py +27 -0
- roadmap/adapters/__init__.py +1 -0
- roadmap/adapters/base_paginated_adapter.py +117 -0
- roadmap/adapters/cli/__init__.py +249 -0
- roadmap/adapters/cli/analysis/__init__.py +5 -0
- roadmap/adapters/cli/analysis/commands.py +370 -0
- roadmap/adapters/cli/analysis/presenter.py +125 -0
- roadmap/adapters/cli/archive_operations.py +86 -0
- roadmap/adapters/cli/cli_command_helpers.py +109 -0
- roadmap/adapters/cli/cli_confirmations.py +74 -0
- roadmap/adapters/cli/cli_error_handlers.py +146 -0
- roadmap/adapters/cli/cli_validators.py +39 -0
- roadmap/adapters/cli/commands/sync_status.py +308 -0
- roadmap/adapters/cli/comment/__init__.py +5 -0
- roadmap/adapters/cli/comment/commands.py +106 -0
- roadmap/adapters/cli/config/__init__.py +5 -0
- roadmap/adapters/cli/config/commands.py +198 -0
- roadmap/adapters/cli/console_exports.py +10 -0
- roadmap/adapters/cli/core.py +26 -0
- roadmap/adapters/cli/crud/__init__.py +47 -0
- roadmap/adapters/cli/crud/base_archive.py +208 -0
- roadmap/adapters/cli/crud/base_create.py +154 -0
- roadmap/adapters/cli/crud/base_delete.py +155 -0
- roadmap/adapters/cli/crud/base_restore.py +283 -0
- roadmap/adapters/cli/crud/base_update.py +193 -0
- roadmap/adapters/cli/crud/crud_helpers.py +206 -0
- roadmap/adapters/cli/crud/crud_utils.py +152 -0
- roadmap/adapters/cli/crud/entity_builders.py +374 -0
- roadmap/adapters/cli/data/__init__.py +8 -0
- roadmap/adapters/cli/data/commands.py +149 -0
- roadmap/adapters/cli/decorators.py +208 -0
- roadmap/adapters/cli/dtos/__init__.py +155 -0
- roadmap/adapters/cli/exception_handler.py +105 -0
- roadmap/adapters/cli/git/__init__.py +8 -0
- roadmap/adapters/cli/git/commands.py +475 -0
- roadmap/adapters/cli/git/handlers/__init__.py +1 -0
- roadmap/adapters/cli/git/handlers/git_authentication_handler.py +124 -0
- roadmap/adapters/cli/git/handlers/git_branch_handler.py +238 -0
- roadmap/adapters/cli/git/handlers/git_connectivity_handler.py +122 -0
- roadmap/adapters/cli/git/handlers/git_hooks_handler.py +105 -0
- roadmap/adapters/cli/git/hooks_config.py +327 -0
- roadmap/adapters/cli/git/status_display.py +158 -0
- roadmap/adapters/cli/health/__init__.py +8 -0
- roadmap/adapters/cli/health/db_integrity.py +204 -0
- roadmap/adapters/cli/health/enhancer.py +227 -0
- roadmap/adapters/cli/health/fixer.py +295 -0
- roadmap/adapters/cli/health/fixers/__init__.py +10 -0
- roadmap/adapters/cli/health/fixers/corrupted_comments_fixer.py +231 -0
- roadmap/adapters/cli/health/fixers/data_integrity_fixer.py +137 -0
- roadmap/adapters/cli/health/fixers/duplicate_issues_fixer.py +138 -0
- roadmap/adapters/cli/health/fixers/folder_structure_fixer.py +114 -0
- roadmap/adapters/cli/health/fixers/label_normalization_fixer.py +162 -0
- roadmap/adapters/cli/health/fixers/milestone_name_normalization_fixer.py +181 -0
- roadmap/adapters/cli/health/fixers/milestone_naming_compliance_fixer.py +244 -0
- roadmap/adapters/cli/health/fixers/milestone_parse_error_fixer.py +162 -0
- roadmap/adapters/cli/health/fixers/milestone_validation_fixer.py +211 -0
- roadmap/adapters/cli/health/fixers/old_backups_fixer.py +135 -0
- roadmap/adapters/cli/health/fixers/orphaned_issues_fixer.py +252 -0
- roadmap/adapters/cli/health/formatter.py +250 -0
- roadmap/adapters/cli/health/formatters.py +427 -0
- roadmap/adapters/cli/health/scan.py +293 -0
- roadmap/adapters/cli/init/__init__.py +5 -0
- roadmap/adapters/cli/init/commands.py +587 -0
- roadmap/adapters/cli/init.py +9 -0
- roadmap/adapters/cli/issues/__init__.py +70 -0
- roadmap/adapters/cli/issues/archive.py +137 -0
- roadmap/adapters/cli/issues/archive_class.py +253 -0
- roadmap/adapters/cli/issues/block.py +39 -0
- roadmap/adapters/cli/issues/close.py +216 -0
- roadmap/adapters/cli/issues/comment.py +178 -0
- roadmap/adapters/cli/issues/create.py +162 -0
- roadmap/adapters/cli/issues/delete.py +31 -0
- roadmap/adapters/cli/issues/deps.py +161 -0
- roadmap/adapters/cli/issues/issue_status_helpers.py +111 -0
- roadmap/adapters/cli/issues/link.py +308 -0
- roadmap/adapters/cli/issues/list.py +402 -0
- roadmap/adapters/cli/issues/lookup.py +96 -0
- roadmap/adapters/cli/issues/progress.py +102 -0
- roadmap/adapters/cli/issues/restore.py +96 -0
- roadmap/adapters/cli/issues/restore_class.py +57 -0
- roadmap/adapters/cli/issues/start.py +165 -0
- roadmap/adapters/cli/issues/sync_status.py +374 -0
- roadmap/adapters/cli/issues/unblock.py +43 -0
- roadmap/adapters/cli/issues/unlink.py +104 -0
- roadmap/adapters/cli/issues/update.py +120 -0
- roadmap/adapters/cli/issues/view.py +36 -0
- roadmap/adapters/cli/layout.py +220 -0
- roadmap/adapters/cli/mappers.py +200 -0
- roadmap/adapters/cli/milestones/__init__.py +52 -0
- roadmap/adapters/cli/milestones/archive.py +125 -0
- roadmap/adapters/cli/milestones/archive_class.py +236 -0
- roadmap/adapters/cli/milestones/assign.py +62 -0
- roadmap/adapters/cli/milestones/close.py +177 -0
- roadmap/adapters/cli/milestones/create.py +131 -0
- roadmap/adapters/cli/milestones/delete.py +27 -0
- roadmap/adapters/cli/milestones/kanban.py +123 -0
- roadmap/adapters/cli/milestones/list.py +87 -0
- roadmap/adapters/cli/milestones/recalculate.py +79 -0
- roadmap/adapters/cli/milestones/restore.py +87 -0
- roadmap/adapters/cli/milestones/restore_class.py +99 -0
- roadmap/adapters/cli/milestones/update.py +61 -0
- roadmap/adapters/cli/milestones/view.py +142 -0
- roadmap/adapters/cli/output_manager.py +319 -0
- roadmap/adapters/cli/presentation/base_presenter.py +121 -0
- roadmap/adapters/cli/presentation/cleanup_presenter.py +235 -0
- roadmap/adapters/cli/presentation/core_initialization_presenter.py +277 -0
- roadmap/adapters/cli/presentation/crud_presenter.py +134 -0
- roadmap/adapters/cli/presentation/daily_summary_presenter.py +266 -0
- roadmap/adapters/cli/presentation/issue_presenter.py +258 -0
- roadmap/adapters/cli/presentation/milestone_list_presenter.py +135 -0
- roadmap/adapters/cli/presentation/milestone_presenter.py +297 -0
- roadmap/adapters/cli/presentation/project_presenter.py +233 -0
- roadmap/adapters/cli/presentation/project_status_presenter.py +186 -0
- roadmap/adapters/cli/presentation/table_builders.py +95 -0
- roadmap/adapters/cli/projects/__init__.py +42 -0
- roadmap/adapters/cli/projects/archive.py +127 -0
- roadmap/adapters/cli/projects/archive_class.py +96 -0
- roadmap/adapters/cli/projects/close.py +94 -0
- roadmap/adapters/cli/projects/create.py +50 -0
- roadmap/adapters/cli/projects/delete.py +27 -0
- roadmap/adapters/cli/projects/list.py +227 -0
- roadmap/adapters/cli/projects/restore.py +87 -0
- roadmap/adapters/cli/projects/restore_class.py +56 -0
- roadmap/adapters/cli/projects/update.py +57 -0
- roadmap/adapters/cli/projects/view.py +157 -0
- roadmap/adapters/cli/services/__init__.py +1 -0
- roadmap/adapters/cli/services/daily_summary_service.py +313 -0
- roadmap/adapters/cli/services/export_manager.py +268 -0
- roadmap/adapters/cli/services/milestone_list_service.py +266 -0
- roadmap/adapters/cli/services/project_initialization_service.py +29 -0
- roadmap/adapters/cli/services/project_status_service.py +462 -0
- roadmap/adapters/cli/services/sync_service.py +62 -0
- roadmap/adapters/cli/status.py +408 -0
- roadmap/adapters/cli/styling.py +21 -0
- roadmap/adapters/cli/sync.py +1117 -0
- roadmap/adapters/cli/sync_context.py +432 -0
- roadmap/adapters/cli/sync_handlers/__init__.py +77 -0
- roadmap/adapters/cli/sync_handlers/apply_ops.py +522 -0
- roadmap/adapters/cli/sync_handlers/baseline_ops.py +366 -0
- roadmap/adapters/cli/sync_handlers/conflict_ops.py +161 -0
- roadmap/adapters/cli/sync_handlers/dry_run_display.py +237 -0
- roadmap/adapters/cli/sync_handlers/interactive_resolver.py +396 -0
- roadmap/adapters/cli/sync_handlers/progress_tracker.py +128 -0
- roadmap/adapters/cli/sync_metrics_command.py +190 -0
- roadmap/adapters/cli/sync_presenter.py +58 -0
- roadmap/adapters/cli/sync_validation.py +295 -0
- roadmap/adapters/cli/today.py +52 -0
- roadmap/adapters/cli/utils/click_options.py +38 -0
- roadmap/adapters/git/__init__.py +1 -0
- roadmap/adapters/git/git.py +208 -0
- roadmap/adapters/git/git_branch_manager.py +400 -0
- roadmap/adapters/git/git_command_executor.py +56 -0
- roadmap/adapters/git/git_commit_analyzer.py +334 -0
- roadmap/adapters/git/git_hooks.py +22 -0
- roadmap/adapters/git/git_hooks_manager.py +455 -0
- roadmap/adapters/git/git_repository_info.py +65 -0
- roadmap/adapters/git/hook_installer.py +106 -0
- roadmap/adapters/git/hook_registry.py +97 -0
- roadmap/adapters/git/hook_script_generator.py +58 -0
- roadmap/adapters/git/sync_monitor.py +409 -0
- roadmap/adapters/git/workflow_automation.py +286 -0
- roadmap/adapters/github/__init__.py +1 -0
- roadmap/adapters/github/github.py +360 -0
- roadmap/adapters/github/handlers/__init__.py +17 -0
- roadmap/adapters/github/handlers/base.py +337 -0
- roadmap/adapters/github/handlers/collaborators.py +165 -0
- roadmap/adapters/github/handlers/comments.py +118 -0
- roadmap/adapters/github/handlers/issues.py +150 -0
- roadmap/adapters/github/handlers/labels.py +164 -0
- roadmap/adapters/github/handlers/milestones.py +104 -0
- roadmap/adapters/persistence/__init__.py +35 -0
- roadmap/adapters/persistence/conflict_resolver.py +190 -0
- roadmap/adapters/persistence/database_manager.py +492 -0
- roadmap/adapters/persistence/entity_sync_coordinators.py +672 -0
- roadmap/adapters/persistence/file_locking.py +348 -0
- roadmap/adapters/persistence/file_parser.py +92 -0
- roadmap/adapters/persistence/file_synchronizer.py +107 -0
- roadmap/adapters/persistence/focused_managers.py +140 -0
- roadmap/adapters/persistence/git_history.py +330 -0
- roadmap/adapters/persistence/parser/__init__.py +20 -0
- roadmap/adapters/persistence/parser/frontmatter.py +152 -0
- roadmap/adapters/persistence/parser/issue.py +245 -0
- roadmap/adapters/persistence/parser/milestone.py +146 -0
- roadmap/adapters/persistence/parser/project.py +106 -0
- roadmap/adapters/persistence/persistence.py +288 -0
- roadmap/adapters/persistence/repositories/__init__.py +15 -0
- roadmap/adapters/persistence/repositories/issue_repository.py +223 -0
- roadmap/adapters/persistence/repositories/milestone_repository.py +140 -0
- roadmap/adapters/persistence/repositories/project_repository.py +168 -0
- roadmap/adapters/persistence/repositories/remote_link_repository.py +355 -0
- roadmap/adapters/persistence/repositories/sync_state_repository.py +66 -0
- roadmap/adapters/persistence/storage/__init__.py +36 -0
- roadmap/adapters/persistence/storage/conflicts.py +101 -0
- roadmap/adapters/persistence/storage/connection_manager.py +79 -0
- roadmap/adapters/persistence/storage/issue_storage.py +89 -0
- roadmap/adapters/persistence/storage/milestone_storage.py +80 -0
- roadmap/adapters/persistence/storage/project_storage.py +102 -0
- roadmap/adapters/persistence/storage/queries.py +227 -0
- roadmap/adapters/persistence/storage/state_manager.py +652 -0
- roadmap/adapters/persistence/storage/sync_state_storage.py +207 -0
- roadmap/adapters/persistence/sync_metrics_repository.py +342 -0
- roadmap/adapters/persistence/sync_orchestrator.py +293 -0
- roadmap/adapters/persistence/sync_state_tracker.py +86 -0
- roadmap/adapters/persistence/yaml_repositories.py +711 -0
- roadmap/adapters/sync/__init__.py +21 -0
- roadmap/adapters/sync/backend_factory.py +108 -0
- roadmap/adapters/sync/backends/__init__.py +15 -0
- roadmap/adapters/sync/backends/converters.py +209 -0
- roadmap/adapters/sync/backends/github_backend_helpers.py +380 -0
- roadmap/adapters/sync/backends/github_client.py +99 -0
- roadmap/adapters/sync/backends/github_sync_backend.py +792 -0
- roadmap/adapters/sync/backends/github_sync_ops.py +908 -0
- roadmap/adapters/sync/backends/services/__init__.py +1 -0
- roadmap/adapters/sync/backends/services/github_authentication_service.py +105 -0
- roadmap/adapters/sync/backends/services/github_issue_delete_service.py +423 -0
- roadmap/adapters/sync/backends/services/github_issue_dependency_service.py +63 -0
- roadmap/adapters/sync/backends/services/github_issue_fetch_service.py +158 -0
- roadmap/adapters/sync/backends/services/github_label_sync_service.py +126 -0
- roadmap/adapters/sync/backends/services/github_local_issue_sync_service.py +229 -0
- roadmap/adapters/sync/backends/services/github_milestone_fetch_service.py +204 -0
- roadmap/adapters/sync/backends/vanilla_git_sync_backend.py +198 -0
- roadmap/adapters/sync/services/__init__.py +11 -0
- roadmap/adapters/sync/services/baseline_state_handler.py +83 -0
- roadmap/adapters/sync/services/conflict_converter.py +85 -0
- roadmap/adapters/sync/services/issue_persistence_service.py +263 -0
- roadmap/adapters/sync/services/issue_state_service.py +243 -0
- roadmap/adapters/sync/services/local_change_filter.py +129 -0
- roadmap/adapters/sync/services/pull_result_processor.py +71 -0
- roadmap/adapters/sync/services/remote_issue_creation_service.py +112 -0
- roadmap/adapters/sync/services/sync_analysis_service.py +250 -0
- roadmap/adapters/sync/services/sync_authentication_service.py +57 -0
- roadmap/adapters/sync/services/sync_data_fetch_service.py +212 -0
- roadmap/adapters/sync/services/sync_linking_service.py +329 -0
- roadmap/adapters/sync/services/sync_report_service.py +62 -0
- roadmap/adapters/sync/services/sync_state_update_service.py +51 -0
- roadmap/adapters/sync/sync_cache_orchestrator.py +454 -0
- roadmap/adapters/sync/sync_merge_engine.py +416 -0
- roadmap/adapters/sync/sync_merge_orchestrator.py +1313 -0
- roadmap/adapters/sync/sync_retrieval_orchestrator.py +810 -0
- roadmap/application/services/__init__.py +1 -0
- roadmap/application/services/deduplicate_service.py +517 -0
- roadmap/application/use_cases/__init__.py +1 -0
- roadmap/common/__init__.py +308 -0
- roadmap/common/cache.py +209 -0
- roadmap/common/cli_errors.py +147 -0
- roadmap/common/configuration/__init__.py +33 -0
- roadmap/common/configuration/config_loader.py +264 -0
- roadmap/common/configuration/config_manager.py +164 -0
- roadmap/common/configuration/config_schema.py +145 -0
- roadmap/common/configuration/github/__init__.py +9 -0
- roadmap/common/configuration/github/config_manager.py +154 -0
- roadmap/common/configuration/github/token_resolver.py +84 -0
- roadmap/common/console.py +184 -0
- roadmap/common/constants.py +134 -0
- roadmap/common/datetime_parser.py +319 -0
- roadmap/common/error_formatter.py +84 -0
- roadmap/common/errors/__init__.py +143 -0
- roadmap/common/errors/error_base.py +73 -0
- roadmap/common/errors/error_file.py +82 -0
- roadmap/common/errors/error_git.py +67 -0
- roadmap/common/errors/error_handler.py +166 -0
- roadmap/common/errors/error_network.py +90 -0
- roadmap/common/errors/error_security.py +78 -0
- roadmap/common/errors/error_standards.py +561 -0
- roadmap/common/errors/error_validation.py +111 -0
- roadmap/common/errors/exceptions.py +432 -0
- roadmap/common/formatters/__init__.py +29 -0
- roadmap/common/formatters/base_table_formatter.py +96 -0
- roadmap/common/formatters/export/__init__.py +7 -0
- roadmap/common/formatters/export/issue_exporter.py +97 -0
- roadmap/common/formatters/helpers.py +28 -0
- roadmap/common/formatters/kanban/__init__.py +9 -0
- roadmap/common/formatters/kanban/layout.py +48 -0
- roadmap/common/formatters/kanban/organizer.py +81 -0
- roadmap/common/formatters/output/__init__.py +15 -0
- roadmap/common/formatters/tables/__init__.py +11 -0
- roadmap/common/formatters/tables/column_factory.py +312 -0
- roadmap/common/formatters/tables/issue_table.py +276 -0
- roadmap/common/formatters/tables/milestone_table.py +247 -0
- roadmap/common/formatters/tables/project_table.py +195 -0
- roadmap/common/formatters/text/__init__.py +57 -0
- roadmap/common/formatters/text/basic.py +217 -0
- roadmap/common/formatters/text/display.py +42 -0
- roadmap/common/formatters/text/duration.py +36 -0
- roadmap/common/formatters/text/operations.py +325 -0
- roadmap/common/formatters/text/status_badges.py +57 -0
- roadmap/common/initialization/github/__init__.py +11 -0
- roadmap/common/initialization/github/setup_service.py +238 -0
- roadmap/common/initialization/github/setup_validator.py +78 -0
- roadmap/common/logging/__init__.py +113 -0
- roadmap/common/logging/audit_logging.py +5 -0
- roadmap/common/logging/correlation.py +45 -0
- roadmap/common/logging/decorators.py +267 -0
- roadmap/common/logging/error_logging.py +217 -0
- roadmap/common/logging/formatters.py +124 -0
- roadmap/common/logging/loggers.py +68 -0
- roadmap/common/logging/performance_tracking.py +267 -0
- roadmap/common/logging/utils.py +335 -0
- roadmap/common/models/__init__.py +44 -0
- roadmap/common/models/cli_models.py +118 -0
- roadmap/common/models/config_models.py +199 -0
- roadmap/common/models/output_models.py +381 -0
- roadmap/common/observability/__init__.py +28 -0
- roadmap/common/observability/instrumentation.py +103 -0
- roadmap/common/observability/observability.py +76 -0
- roadmap/common/observability/otel_init.py +109 -0
- roadmap/common/output_formatter.py +393 -0
- roadmap/common/progress.py +379 -0
- roadmap/common/result.py +396 -0
- roadmap/common/security/__init__.py +48 -0
- roadmap/common/security/exceptions.py +13 -0
- roadmap/common/security/export_cleanup.py +79 -0
- roadmap/common/security/file_operations.py +104 -0
- roadmap/common/security/filename_sanitization.py +54 -0
- roadmap/common/security/logging.py +27 -0
- roadmap/common/security/path_validation.py +137 -0
- roadmap/common/security/temp_files.py +41 -0
- roadmap/common/services/__init__.py +65 -0
- roadmap/common/services/decorators.py +183 -0
- roadmap/common/services/logging_utils.py +208 -0
- roadmap/common/services/metrics.py +161 -0
- roadmap/common/services/performance.py +219 -0
- roadmap/common/services/profiling.py +288 -0
- roadmap/common/services/retry.py +288 -0
- roadmap/common/status_style_manager.py +114 -0
- roadmap/common/union_find.py +88 -0
- roadmap/common/update_constants.py +13 -0
- roadmap/common/utils/__init__.py +65 -0
- roadmap/common/utils/cli_helpers.py +381 -0
- roadmap/common/utils/file_utils.py +440 -0
- roadmap/common/utils/path_utils.py +38 -0
- roadmap/common/utils/status_utils.py +130 -0
- roadmap/common/utils/timezone_utils.py +480 -0
- roadmap/common/validation/__init__.py +37 -0
- roadmap/common/validation/field_validator.py +104 -0
- roadmap/common/validation/result.py +37 -0
- roadmap/common/validation/roadmap_validator.py +310 -0
- roadmap/common/validation/schema_validator.py +36 -0
- roadmap/common/validation/validators.py +50 -0
- roadmap/core/__init__.py +1 -0
- roadmap/core/domain/__init__.py +30 -0
- roadmap/core/domain/comment.py +24 -0
- roadmap/core/domain/health.py +15 -0
- roadmap/core/domain/issue.py +274 -0
- roadmap/core/domain/milestone.py +173 -0
- roadmap/core/domain/ports/__init__.py +1 -0
- roadmap/core/domain/ports/baseline_repository.py +24 -0
- roadmap/core/domain/ports/issue_repository.py +34 -0
- roadmap/core/domain/ports/remote_backend_port.py +31 -0
- roadmap/core/domain/project.py +130 -0
- roadmap/core/interfaces/__init__.py +109 -0
- roadmap/core/interfaces/assignee_validator.py +40 -0
- roadmap/core/interfaces/backend_factory.py +175 -0
- roadmap/core/interfaces/github.py +102 -0
- roadmap/core/interfaces/parsers.py +140 -0
- roadmap/core/interfaces/persistence.py +45 -0
- roadmap/core/interfaces/repositories.py +174 -0
- roadmap/core/interfaces/state_managers.py +111 -0
- roadmap/core/interfaces/state_storage.py +64 -0
- roadmap/core/interfaces/sync_backend.py +275 -0
- roadmap/core/interfaces/sync_services.py +119 -0
- roadmap/core/interfaces/sync_validators.py +180 -0
- roadmap/core/models/__init__.py +31 -0
- roadmap/core/models/sync_models.py +162 -0
- roadmap/core/models.py +115 -0
- roadmap/core/observability/__init__.py +17 -0
- roadmap/core/observability/sync_metrics.py +699 -0
- roadmap/core/repositories.py +200 -0
- roadmap/core/services/__init__.py +313 -0
- roadmap/core/services/baseline/__init__.py +1 -0
- roadmap/core/services/baseline/baseline_builder_progress.py +274 -0
- roadmap/core/services/baseline/baseline_retriever.py +63 -0
- roadmap/core/services/baseline/baseline_selector.py +248 -0
- roadmap/core/services/baseline/baseline_state_retriever.py +284 -0
- roadmap/core/services/baseline/optimized_baseline_builder.py +425 -0
- roadmap/core/services/comment/__init__.py +1 -0
- roadmap/core/services/comment/comment_service.py +277 -0
- roadmap/core/services/git/__init__.py +1 -0
- roadmap/core/services/git/git_hook_auto_sync_service.py +403 -0
- roadmap/core/services/github/__init__.py +1 -0
- roadmap/core/services/github/github_change_detector.py +162 -0
- roadmap/core/services/github/github_config_validator.py +148 -0
- roadmap/core/services/github/github_conflict_detector.py +179 -0
- roadmap/core/services/github/github_entity_classifier.py +51 -0
- roadmap/core/services/github/github_integration_service.py +439 -0
- roadmap/core/services/github/github_issue_client.py +346 -0
- roadmap/core/services/health/__init__.py +1 -0
- roadmap/core/services/health/backup_cleanup_service.py +202 -0
- roadmap/core/services/health/data_integrity_validator_service.py +90 -0
- roadmap/core/services/health/entity_health_scanner.py +460 -0
- roadmap/core/services/health/file_repair_service.py +193 -0
- roadmap/core/services/health/health_check_service.py +166 -0
- roadmap/core/services/health/health_models.py +80 -0
- roadmap/core/services/health/infrastructure_validator_service.py +328 -0
- roadmap/core/services/health/issue_health_scanner.py +263 -0
- roadmap/core/services/helpers/__init__.py +18 -0
- roadmap/core/services/helpers/status_change_helpers.py +88 -0
- roadmap/core/services/initialization/__init__.py +19 -0
- roadmap/core/services/initialization/utils.py +104 -0
- roadmap/core/services/initialization/validator.py +78 -0
- roadmap/core/services/initialization/workflow.py +182 -0
- roadmap/core/services/initialization_service.py +111 -0
- roadmap/core/services/issue/__init__.py +1 -0
- roadmap/core/services/issue/assignee_validation_service.py +312 -0
- roadmap/core/services/issue/issue_creation_service.py +309 -0
- roadmap/core/services/issue/issue_filter_service.py +302 -0
- roadmap/core/services/issue/issue_matching_service.py +127 -0
- roadmap/core/services/issue/issue_service.py +765 -0
- roadmap/core/services/issue/issue_update_service.py +144 -0
- roadmap/core/services/issue/start_issue_service.py +174 -0
- roadmap/core/services/issue_helpers/__init__.py +18 -0
- roadmap/core/services/issue_helpers/issue_filters.py +296 -0
- roadmap/core/services/milestone_service.py +438 -0
- roadmap/core/services/project/__init__.py +1 -0
- roadmap/core/services/project/project_service.py +434 -0
- roadmap/core/services/project/project_status_service.py +125 -0
- roadmap/core/services/project_init/__init__.py +22 -0
- roadmap/core/services/project_init/context_detection.py +146 -0
- roadmap/core/services/project_init/creation.py +76 -0
- roadmap/core/services/project_init/detection.py +51 -0
- roadmap/core/services/project_init/template.py +228 -0
- roadmap/core/services/status_change_service.py +88 -0
- roadmap/core/services/sync/__init__.py +1 -0
- roadmap/core/services/sync/batch_processor.py +290 -0
- roadmap/core/services/sync/conflict_resolver.py +154 -0
- roadmap/core/services/sync/dependency_resolver.py +367 -0
- roadmap/core/services/sync/duplicate_detector.py +771 -0
- roadmap/core/services/sync/duplicate_resolver.py +315 -0
- roadmap/core/services/sync/error_classification.py +470 -0
- roadmap/core/services/sync/performance.py +263 -0
- roadmap/core/services/sync/sync_change_computer.py +211 -0
- roadmap/core/services/sync/sync_checkpoint.py +348 -0
- roadmap/core/services/sync/sync_conflict_detector.py +147 -0
- roadmap/core/services/sync/sync_conflict_resolver.py +448 -0
- roadmap/core/services/sync/sync_errors.py +383 -0
- roadmap/core/services/sync/sync_key_normalizer.py +222 -0
- roadmap/core/services/sync/sync_metadata_service.py +361 -0
- roadmap/core/services/sync/sync_plan.py +171 -0
- roadmap/core/services/sync/sync_plan_executor.py +447 -0
- roadmap/core/services/sync/sync_report.py +296 -0
- roadmap/core/services/sync/sync_state.py +173 -0
- roadmap/core/services/sync/sync_state_comparator.py +690 -0
- roadmap/core/services/sync/sync_state_manager.py +431 -0
- roadmap/core/services/sync/sync_state_normalizer.py +98 -0
- roadmap/core/services/sync/sync_three_way.py +78 -0
- roadmap/core/services/sync/three_way_merger.py +178 -0
- roadmap/core/services/utils/__init__.py +1 -0
- roadmap/core/services/utils/configuration_service.py +113 -0
- roadmap/core/services/utils/critical_path_calculator.py +418 -0
- roadmap/core/services/utils/dependency_analyzer.py +360 -0
- roadmap/core/services/utils/field_conflict_detector.py +126 -0
- roadmap/core/services/utils/remote_fetcher.py +202 -0
- roadmap/core/services/utils/remote_state_normalizer.py +110 -0
- roadmap/core/services/utils/retry_policy.py +51 -0
- roadmap/core/services/validator_base.py +130 -0
- roadmap/core/services/validators/__init__.py +28 -0
- roadmap/core/services/validators/_utils.py +20 -0
- roadmap/core/services/validators/archivable_issues_validator.py +71 -0
- roadmap/core/services/validators/archivable_milestones_validator.py +69 -0
- roadmap/core/services/validators/backup_validator.py +89 -0
- roadmap/core/services/validators/data_integrity_validator.py +84 -0
- roadmap/core/services/validators/duplicate_issues_validator.py +75 -0
- roadmap/core/services/validators/duplicate_milestones_validator.py +141 -0
- roadmap/core/services/validators/folder_structure_validator.py +165 -0
- roadmap/core/services/validators/health_status_utils.py +28 -0
- roadmap/core/services/validators/milestone_naming_validator.py +146 -0
- roadmap/core/services/validators/missing_headlines_validator.py +97 -0
- roadmap/core/services/validators/orphaned_issues_validator.py +142 -0
- roadmap/core/services/validators/orphaned_milestones_validator.py +85 -0
- roadmap/core/utils/git_remote_parser.py +83 -0
- roadmap/core/utils/github_urls.py +66 -0
- roadmap/domain/validation.py +30 -0
- roadmap/infrastructure/__init__.py +55 -0
- roadmap/infrastructure/coordination/__init__.py +8 -0
- roadmap/infrastructure/coordination/coordinator_params.py +82 -0
- roadmap/infrastructure/coordination/core.py +446 -0
- roadmap/infrastructure/coordination/git_coordinator.py +160 -0
- roadmap/infrastructure/coordination/initialization.py +348 -0
- roadmap/infrastructure/coordination/issue_coordinator.py +154 -0
- roadmap/infrastructure/coordination/issue_operations.py +456 -0
- roadmap/infrastructure/coordination/milestone_coordinator.py +135 -0
- roadmap/infrastructure/coordination/milestone_operations.py +201 -0
- roadmap/infrastructure/coordination/project_coordinator.py +113 -0
- roadmap/infrastructure/coordination/project_operations.py +144 -0
- roadmap/infrastructure/coordination/team_coordinator.py +107 -0
- roadmap/infrastructure/coordination/user_operations.py +150 -0
- roadmap/infrastructure/coordination/validation_coordinator.py +249 -0
- roadmap/infrastructure/coordination_gateway.py +152 -0
- roadmap/infrastructure/git/__init__.py +6 -0
- roadmap/infrastructure/git/git_integration_ops.py +234 -0
- roadmap/infrastructure/git_gateway.py +35 -0
- roadmap/infrastructure/github_gateway.py +52 -0
- roadmap/infrastructure/maintenance/__init__.py +5 -0
- roadmap/infrastructure/maintenance/cleanup.py +483 -0
- roadmap/infrastructure/observability/__init__.py +7 -0
- roadmap/infrastructure/observability/health.py +196 -0
- roadmap/infrastructure/observability/health_formatter.py +73 -0
- roadmap/infrastructure/observability/specialized_health_checkers.py +188 -0
- roadmap/infrastructure/persistence_gateway.py +164 -0
- roadmap/infrastructure/security/__init__.py +1 -0
- roadmap/infrastructure/security/credentials.py +489 -0
- roadmap/infrastructure/sync_gateway.py +94 -0
- roadmap/infrastructure/validation/__init__.py +7 -0
- roadmap/infrastructure/validation/file_enumeration.py +219 -0
- roadmap/infrastructure/validation/github_assignee_validator.py +47 -0
- roadmap/infrastructure/validation/github_validator.py +101 -0
- roadmap/infrastructure/validation/milestone_consistency_validator.py +96 -0
- roadmap/infrastructure/validation/vanilla_assignee_validator.py +37 -0
- roadmap/infrastructure/validation_gateway.py +96 -0
- roadmap/presentation/formatters/sync_metrics_formatter.py +355 -0
- roadmap/settings.py +345 -0
- roadmap/templates/github_workflows/ci-cd-roadmap.yml +241 -0
- roadmap/templates/github_workflows/issue-lifecycle.yml +236 -0
- roadmap/templates/github_workflows/roadmap-integration.yml +137 -0
- roadmap/templates/github_workflows/roadmap-starter.yml +59 -0
- roadmap/version.py +381 -0
- roadmap_cli-0.1.1.dist-info/METADATA +448 -0
- roadmap_cli-0.1.1.dist-info/RECORD +521 -0
- roadmap_cli-0.1.1.dist-info/WHEEL +4 -0
- roadmap_cli-0.1.1.dist-info/entry_points.txt +2 -0
- roadmap_cli-0.1.1.dist-info/licenses/LICENSE.md +21 -0
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
"""Shared CRUD operation helpers and utilities.
|
|
2
|
+
|
|
3
|
+
This module provides common functionality for Create, Update, Delete,
|
|
4
|
+
Archive, and Restore operations across all entity types.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from enum import StrEnum
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from typing import Any
|
|
10
|
+
|
|
11
|
+
from roadmap.common.console import get_console
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class EntityType(StrEnum):
|
|
15
|
+
"""Entity types for CRUD operations."""
|
|
16
|
+
|
|
17
|
+
ISSUE = "issue"
|
|
18
|
+
MILESTONE = "milestone"
|
|
19
|
+
PROJECT = "project"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class CRUDOperation(StrEnum):
|
|
23
|
+
"""CRUD operation types.
|
|
24
|
+
|
|
25
|
+
Note: Individual operation values are not currently used.
|
|
26
|
+
This enum exists for potential future feature development.
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
pass
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def format_entity_title(entity_type: EntityType, entity: Any) -> str:
|
|
33
|
+
"""Get display title for entity (handles different entity types).
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
entity_type: The type of entity
|
|
37
|
+
entity: The entity object
|
|
38
|
+
|
|
39
|
+
Returns:
|
|
40
|
+
Formatted title string
|
|
41
|
+
"""
|
|
42
|
+
if entity_type == EntityType.ISSUE:
|
|
43
|
+
return entity.title
|
|
44
|
+
elif entity_type == EntityType.MILESTONE:
|
|
45
|
+
return entity.name
|
|
46
|
+
elif entity_type == EntityType.PROJECT:
|
|
47
|
+
return entity.name
|
|
48
|
+
return str(entity)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def format_entity_id(entity_type: EntityType, entity: Any) -> str:
|
|
52
|
+
"""Get display ID for entity.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
entity_type: The type of entity
|
|
56
|
+
entity: The entity object
|
|
57
|
+
|
|
58
|
+
Returns:
|
|
59
|
+
Entity ID string
|
|
60
|
+
"""
|
|
61
|
+
return getattr(entity, "id", str(entity))
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def validate_entity_exists(
|
|
65
|
+
core: Any,
|
|
66
|
+
entity_type: EntityType,
|
|
67
|
+
entity_id: str,
|
|
68
|
+
console: Any = None,
|
|
69
|
+
) -> tuple[bool, str | None]:
|
|
70
|
+
"""Check if entity exists.
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
core: The core application context
|
|
74
|
+
entity_type: The type of entity to check
|
|
75
|
+
entity_id: The ID of the entity
|
|
76
|
+
console: Optional console for output
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
Tuple of (exists: bool, error_message: Optional[str])
|
|
80
|
+
"""
|
|
81
|
+
try:
|
|
82
|
+
if entity_type == EntityType.ISSUE:
|
|
83
|
+
entity = core.issues.get(entity_id)
|
|
84
|
+
elif entity_type == EntityType.MILESTONE:
|
|
85
|
+
entity = core.milestones.get(entity_id)
|
|
86
|
+
elif entity_type == EntityType.PROJECT:
|
|
87
|
+
entity = core.projects.get(entity_id)
|
|
88
|
+
else:
|
|
89
|
+
return False, f"Unknown entity type: {entity_type}"
|
|
90
|
+
|
|
91
|
+
if entity is None:
|
|
92
|
+
return False, f"{entity_type.value.title()} '{entity_id}' not found"
|
|
93
|
+
|
|
94
|
+
return True, None
|
|
95
|
+
except Exception as e:
|
|
96
|
+
return False, f"Error checking {entity_type.value}: {str(e)}"
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def collect_archive_files(
|
|
100
|
+
archive_dir: Path,
|
|
101
|
+
entity_type: EntityType,
|
|
102
|
+
) -> list[Path]:
|
|
103
|
+
"""Collect all archived files of a specific entity type.
|
|
104
|
+
|
|
105
|
+
Args:
|
|
106
|
+
archive_dir: Path to the archive directory
|
|
107
|
+
entity_type: The type of entity to collect
|
|
108
|
+
|
|
109
|
+
Returns:
|
|
110
|
+
List of archive file paths
|
|
111
|
+
"""
|
|
112
|
+
if not archive_dir.exists():
|
|
113
|
+
return []
|
|
114
|
+
|
|
115
|
+
# For issues, search recursively (may be in subfolders)
|
|
116
|
+
if entity_type == EntityType.ISSUE:
|
|
117
|
+
return list(archive_dir.rglob("*.md"))
|
|
118
|
+
|
|
119
|
+
# For milestones and projects, search in root
|
|
120
|
+
return list(archive_dir.glob("*.md"))
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def get_archive_dir(entity_type: EntityType) -> Path:
|
|
124
|
+
"""Get archive directory for entity type.
|
|
125
|
+
|
|
126
|
+
Args:
|
|
127
|
+
entity_type: The type of entity
|
|
128
|
+
|
|
129
|
+
Returns:
|
|
130
|
+
Path to archive directory
|
|
131
|
+
"""
|
|
132
|
+
roadmap_dir = Path.cwd() / ".roadmap"
|
|
133
|
+
entity_name = entity_type.value # "issue", "milestone", "project"
|
|
134
|
+
return roadmap_dir / "archive" / (entity_name + "s") # pluralize
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def get_active_dir(entity_type: EntityType) -> Path:
|
|
138
|
+
"""Get active directory for entity type.
|
|
139
|
+
|
|
140
|
+
Args:
|
|
141
|
+
entity_type: The type of entity
|
|
142
|
+
|
|
143
|
+
Returns:
|
|
144
|
+
Path to active directory
|
|
145
|
+
"""
|
|
146
|
+
roadmap_dir = Path.cwd() / ".roadmap"
|
|
147
|
+
entity_name = entity_type.value # "issue", "milestone", "project"
|
|
148
|
+
return roadmap_dir / (entity_name + "s") # pluralize
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def display_archive_success(
|
|
152
|
+
entity_type: EntityType,
|
|
153
|
+
archived_count: int,
|
|
154
|
+
skipped_count: int,
|
|
155
|
+
console: Any = None,
|
|
156
|
+
) -> None:
|
|
157
|
+
"""Display success message for archive operation.
|
|
158
|
+
|
|
159
|
+
Args:
|
|
160
|
+
entity_type: The type of entity
|
|
161
|
+
archived_count: Number of archived items
|
|
162
|
+
skipped_count: Number of skipped items
|
|
163
|
+
console: Optional console for output
|
|
164
|
+
"""
|
|
165
|
+
if console is None:
|
|
166
|
+
console = get_console()
|
|
167
|
+
|
|
168
|
+
plural = "s" if archived_count != 1 else ""
|
|
169
|
+
console.print(
|
|
170
|
+
f"✅ Archived {archived_count} {entity_type.value}{plural}",
|
|
171
|
+
style="green",
|
|
172
|
+
)
|
|
173
|
+
if skipped_count > 0:
|
|
174
|
+
console.print(
|
|
175
|
+
f"⚠️ Skipped {skipped_count} (already archived or errors)",
|
|
176
|
+
style="yellow",
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def display_restore_success(
|
|
181
|
+
entity_type: EntityType,
|
|
182
|
+
restored_count: int,
|
|
183
|
+
failed_count: int,
|
|
184
|
+
console: Any = None,
|
|
185
|
+
) -> None:
|
|
186
|
+
"""Display success message for restore operation.
|
|
187
|
+
|
|
188
|
+
Args:
|
|
189
|
+
entity_type: The type of entity
|
|
190
|
+
restored_count: Number of restored items
|
|
191
|
+
failed_count: Number of failed restorations
|
|
192
|
+
console: Optional console for output
|
|
193
|
+
"""
|
|
194
|
+
if console is None:
|
|
195
|
+
console = get_console()
|
|
196
|
+
|
|
197
|
+
plural = "s" if restored_count != 1 else ""
|
|
198
|
+
console.print(
|
|
199
|
+
f"✅ Restored {restored_count} {entity_type.value}{plural}",
|
|
200
|
+
style="green",
|
|
201
|
+
)
|
|
202
|
+
if failed_count > 0:
|
|
203
|
+
console.print(
|
|
204
|
+
f"❌ Failed to restore {failed_count} {entity_type.value}(s)",
|
|
205
|
+
style="red",
|
|
206
|
+
)
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"""Shared utilities for CRUD operations across all entity types.
|
|
2
|
+
|
|
3
|
+
This module consolidates duplicate patterns from base_create, base_update,
|
|
4
|
+
and base_delete to eliminate code duplication.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
from roadmap.adapters.cli.crud.crud_helpers import EntityType
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def get_entity_by_type(
|
|
13
|
+
core: Any, entity_type: EntityType, entity_id: str
|
|
14
|
+
) -> Any | None:
|
|
15
|
+
"""Get entity from core service by type.
|
|
16
|
+
|
|
17
|
+
Consolidates the repeated _get_entity pattern from base_create,
|
|
18
|
+
base_update, and base_delete.
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
core: The core application context
|
|
22
|
+
entity_type: The type of entity to retrieve
|
|
23
|
+
entity_id: The entity ID
|
|
24
|
+
|
|
25
|
+
Returns:
|
|
26
|
+
Entity object or None if not found
|
|
27
|
+
"""
|
|
28
|
+
if entity_type == EntityType.ISSUE:
|
|
29
|
+
return core.issues.get(entity_id)
|
|
30
|
+
elif entity_type == EntityType.MILESTONE:
|
|
31
|
+
return core.milestones.get(entity_id)
|
|
32
|
+
elif entity_type == EntityType.PROJECT:
|
|
33
|
+
return core.projects.get(entity_id)
|
|
34
|
+
return None
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def update_entity_by_type(
|
|
38
|
+
core: Any, entity_type: EntityType, entity_id: str, update_dict: dict[str, Any]
|
|
39
|
+
) -> Any | None:
|
|
40
|
+
"""Update entity via appropriate service by type.
|
|
41
|
+
|
|
42
|
+
Consolidates the repeated _update_entity pattern from base_create,
|
|
43
|
+
base_update, and base_delete.
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
core: The core application context
|
|
47
|
+
entity_type: The type of entity to update
|
|
48
|
+
entity_id: The entity ID
|
|
49
|
+
update_dict: Dictionary of fields to update
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
Updated entity or None if failed
|
|
53
|
+
"""
|
|
54
|
+
if entity_type == EntityType.ISSUE:
|
|
55
|
+
return core.issues.update(entity_id, **update_dict)
|
|
56
|
+
elif entity_type == EntityType.MILESTONE:
|
|
57
|
+
return core.milestones.update(entity_id, **update_dict)
|
|
58
|
+
elif entity_type == EntityType.PROJECT:
|
|
59
|
+
return core.projects.update(entity_id, **update_dict)
|
|
60
|
+
return None
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def create_entity_by_type(
|
|
64
|
+
core: Any, entity_type: EntityType, create_dict: dict[str, Any]
|
|
65
|
+
) -> Any | None:
|
|
66
|
+
"""Create entity via appropriate service by type.
|
|
67
|
+
|
|
68
|
+
Args:
|
|
69
|
+
core: The core application context
|
|
70
|
+
entity_type: The type of entity to create
|
|
71
|
+
create_dict: Dictionary of fields for new entity
|
|
72
|
+
|
|
73
|
+
Returns:
|
|
74
|
+
Created entity or None if failed
|
|
75
|
+
"""
|
|
76
|
+
if entity_type == EntityType.ISSUE:
|
|
77
|
+
return core.issues.create(**create_dict)
|
|
78
|
+
elif entity_type == EntityType.MILESTONE:
|
|
79
|
+
return core.milestones.create(**create_dict)
|
|
80
|
+
elif entity_type == EntityType.PROJECT:
|
|
81
|
+
return core.projects.create(**create_dict)
|
|
82
|
+
return None
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def delete_entity_by_type(core: Any, entity_type: EntityType, entity_id: str) -> bool:
|
|
86
|
+
"""Delete entity via appropriate service by type.
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
core: The core application context
|
|
90
|
+
entity_type: The type of entity to delete
|
|
91
|
+
entity_id: The entity ID
|
|
92
|
+
|
|
93
|
+
Returns:
|
|
94
|
+
True if deletion succeeded, False otherwise
|
|
95
|
+
"""
|
|
96
|
+
if entity_type == EntityType.ISSUE:
|
|
97
|
+
return core.issues.delete(entity_id)
|
|
98
|
+
elif entity_type == EntityType.MILESTONE:
|
|
99
|
+
return core.milestones.delete(entity_id)
|
|
100
|
+
elif entity_type == EntityType.PROJECT:
|
|
101
|
+
return core.projects.delete(entity_id)
|
|
102
|
+
return False
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def get_entity_title(entity: Any) -> str:
|
|
106
|
+
"""Get entity title/name.
|
|
107
|
+
|
|
108
|
+
Consolidates the repeated _get_title pattern from base_create,
|
|
109
|
+
base_update, and base_delete.
|
|
110
|
+
|
|
111
|
+
Args:
|
|
112
|
+
entity: The entity object
|
|
113
|
+
|
|
114
|
+
Returns:
|
|
115
|
+
Title or name string
|
|
116
|
+
"""
|
|
117
|
+
if hasattr(entity, "title"):
|
|
118
|
+
return entity.title
|
|
119
|
+
elif hasattr(entity, "name"):
|
|
120
|
+
return entity.name
|
|
121
|
+
return str(entity)
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def get_entity_id(entity: Any) -> str:
|
|
125
|
+
"""Get entity ID.
|
|
126
|
+
|
|
127
|
+
Consolidates the repeated _get_id pattern from base_create,
|
|
128
|
+
base_update, and base_delete.
|
|
129
|
+
|
|
130
|
+
Args:
|
|
131
|
+
entity: The entity object
|
|
132
|
+
|
|
133
|
+
Returns:
|
|
134
|
+
Entity ID string
|
|
135
|
+
"""
|
|
136
|
+
return getattr(entity, "id", str(entity))
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def format_entity_not_found_error(entity_type: EntityType, entity_id: str) -> str:
|
|
140
|
+
"""Format error message for entity not found.
|
|
141
|
+
|
|
142
|
+
Consolidates the repeated entity-not-found error message pattern
|
|
143
|
+
from base_update and base_delete.
|
|
144
|
+
|
|
145
|
+
Args:
|
|
146
|
+
entity_type: The type of entity that was not found
|
|
147
|
+
entity_id: The entity ID that was not found
|
|
148
|
+
|
|
149
|
+
Returns:
|
|
150
|
+
Formatted error message string
|
|
151
|
+
"""
|
|
152
|
+
return f"❌ {entity_type.value.title()} '{entity_id}' not found"
|