domd 2.2.1__tar.gz → 2.2.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. {domd-2.2.1 → domd-2.2.2}/PKG-INFO +1 -1
  2. {domd-2.2.1 → domd-2.2.2}/pyproject.toml +1 -1
  3. {domd-2.2.1 → domd-2.2.2}/src/domd/core/project_detection/detector.py +64 -28
  4. {domd-2.2.1 → domd-2.2.2}/LICENSE +0 -0
  5. {domd-2.2.1 → domd-2.2.2}/README.md +0 -0
  6. {domd-2.2.1 → domd-2.2.2}/src/domd/__init__.py +0 -0
  7. {domd-2.2.1 → domd-2.2.2}/src/domd/adapters/__init__.py +0 -0
  8. {domd-2.2.1 → domd-2.2.2}/src/domd/adapters/api/__init__.py +0 -0
  9. {domd-2.2.1 → domd-2.2.2}/src/domd/adapters/api/flask_api.py +0 -0
  10. {domd-2.2.1 → domd-2.2.2}/src/domd/adapters/cli/__init__.py +0 -0
  11. {domd-2.2.1 → domd-2.2.2}/src/domd/adapters/cli/command_presenter.py +0 -0
  12. {domd-2.2.1 → domd-2.2.2}/src/domd/adapters/formatters/__init__.py +0 -0
  13. {domd-2.2.1 → domd-2.2.2}/src/domd/adapters/formatters/markdown_formatter.py +0 -0
  14. {domd-2.2.1 → domd-2.2.2}/src/domd/adapters/persistence/__init__.py +0 -0
  15. {domd-2.2.1 → domd-2.2.2}/src/domd/adapters/persistence/in_memory_command_repository.py +0 -0
  16. {domd-2.2.1 → domd-2.2.2}/src/domd/adapters/persistence/shell_command_executor.py +0 -0
  17. {domd-2.2.1 → domd-2.2.2}/src/domd/api.py +0 -0
  18. {domd-2.2.1 → domd-2.2.2}/src/domd/application/__init__.py +0 -0
  19. {domd-2.2.1 → domd-2.2.2}/src/domd/application/factory.py +0 -0
  20. {domd-2.2.1 → domd-2.2.2}/src/domd/cli.py +0 -0
  21. {domd-2.2.1 → domd-2.2.2}/src/domd/command_execution/__init__.py +0 -0
  22. {domd-2.2.1 → domd-2.2.2}/src/domd/core/__init__.py +0 -0
  23. {domd-2.2.1 → domd-2.2.2}/src/domd/core/command_execution/__init__.py +0 -0
  24. {domd-2.2.1 → domd-2.2.2}/src/domd/core/command_execution/command_executor.py +0 -0
  25. {domd-2.2.1 → domd-2.2.2}/src/domd/core/command_execution/command_recorder.py +0 -0
  26. {domd-2.2.1 → domd-2.2.2}/src/domd/core/command_execution/command_runner.py +0 -0
  27. {domd-2.2.1 → domd-2.2.2}/src/domd/core/command_execution/environment_detector.py +0 -0
  28. {domd-2.2.1 → domd-2.2.2}/src/domd/core/command_execution/executor.py +0 -0
  29. {domd-2.2.1 → domd-2.2.2}/src/domd/core/commands/__init__.py +0 -0
  30. {domd-2.2.1 → domd-2.2.2}/src/domd/core/commands/command.py +0 -0
  31. {domd-2.2.1 → domd-2.2.2}/src/domd/core/commands/executor.py +0 -0
  32. {domd-2.2.1 → domd-2.2.2}/src/domd/core/detector.py +0 -0
  33. {domd-2.2.1 → domd-2.2.2}/src/domd/core/domain/__init__.py +0 -0
  34. {domd-2.2.1 → domd-2.2.2}/src/domd/core/domain/command.py +0 -0
  35. {domd-2.2.1 → domd-2.2.2}/src/domd/core/parsers/__init__.py +0 -0
  36. {domd-2.2.1 → domd-2.2.2}/src/domd/core/parsers/ansible_galaxy.py +0 -0
  37. {domd-2.2.1 → domd-2.2.2}/src/domd/core/parsers/ansible_inventory.py +0 -0
  38. {domd-2.2.1 → domd-2.2.2}/src/domd/core/parsers/ansible_playbook.py +0 -0
  39. {domd-2.2.1 → domd-2.2.2}/src/domd/core/parsers/ansible_role.py +0 -0
  40. {domd-2.2.1 → domd-2.2.2}/src/domd/core/parsers/ansible_vault.py +0 -0
  41. {domd-2.2.1 → domd-2.2.2}/src/domd/core/parsers/base.py +0 -0
  42. {domd-2.2.1 → domd-2.2.2}/src/domd/core/parsers/cargo_toml.py +0 -0
  43. {domd-2.2.1 → domd-2.2.2}/src/domd/core/parsers/composer_json.py +0 -0
  44. {domd-2.2.1 → domd-2.2.2}/src/domd/core/parsers/go_mod.py +0 -0
  45. {domd-2.2.1 → domd-2.2.2}/src/domd/core/parsers/makefile.py +0 -0
  46. {domd-2.2.1 → domd-2.2.2}/src/domd/core/parsers/package_json.py +0 -0
  47. {domd-2.2.1 → domd-2.2.2}/src/domd/core/parsers/pyproject_toml.py +0 -0
  48. {domd-2.2.1 → domd-2.2.2}/src/domd/core/parsers/tox_ini.py +0 -0
  49. {domd-2.2.1 → domd-2.2.2}/src/domd/core/parsing/__init__.py +0 -0
  50. {domd-2.2.1 → domd-2.2.2}/src/domd/core/parsing/base.py +0 -0
  51. {domd-2.2.1 → domd-2.2.2}/src/domd/core/parsing/file_processor.py +0 -0
  52. {domd-2.2.1 → domd-2.2.2}/src/domd/core/parsing/parser_registry.py +0 -0
  53. {domd-2.2.1 → domd-2.2.2}/src/domd/core/parsing/pattern_matcher.py +0 -0
  54. {domd-2.2.1 → domd-2.2.2}/src/domd/core/ports/__init__.py +0 -0
  55. {domd-2.2.1 → domd-2.2.2}/src/domd/core/ports/command_executor.py +0 -0
  56. {domd-2.2.1 → domd-2.2.2}/src/domd/core/ports/command_repository.py +0 -0
  57. {domd-2.2.1 → domd-2.2.2}/src/domd/core/ports/report_formatter.py +0 -0
  58. {domd-2.2.1 → domd-2.2.2}/src/domd/core/project_detection/__init__.py +0 -0
  59. {domd-2.2.1 → domd-2.2.2}/src/domd/core/project_detection/command_handling.py +0 -0
  60. {domd-2.2.1 → domd-2.2.2}/src/domd/core/project_detection/config_files.py +0 -0
  61. {domd-2.2.1 → domd-2.2.2}/src/domd/core/project_detection/virtualenv.py +0 -0
  62. {domd-2.2.1 → domd-2.2.2}/src/domd/core/reporters/__init__.py +0 -0
  63. {domd-2.2.1 → domd-2.2.2}/src/domd/core/reporters/base.py +0 -0
  64. {domd-2.2.1 → domd-2.2.2}/src/domd/core/reporters/done_md.py +0 -0
  65. {domd-2.2.1 → domd-2.2.2}/src/domd/core/reporters/todo_md.py +0 -0
  66. {domd-2.2.1 → domd-2.2.2}/src/domd/core/reporting/__init__.py +0 -0
  67. {domd-2.2.1 → domd-2.2.2}/src/domd/core/reporting/formatters.py +0 -0
  68. {domd-2.2.1 → domd-2.2.2}/src/domd/core/reporting/reporter.py +0 -0
  69. {domd-2.2.1 → domd-2.2.2}/src/domd/core/services/__init__.py +0 -0
  70. {domd-2.2.1 → domd-2.2.2}/src/domd/core/services/command_service.py +0 -0
  71. {domd-2.2.1 → domd-2.2.2}/src/domd/core/services/report_service.py +0 -0
  72. {domd-2.2.1 → domd-2.2.2}/src/domd/core/utils/__init__.py +0 -0
  73. {domd-2.2.1 → domd-2.2.2}/src/domd/core/utils/command_utils.py +0 -0
  74. {domd-2.2.1 → domd-2.2.2}/src/domd/core/utils/environment.py +0 -0
  75. {domd-2.2.1 → domd-2.2.2}/src/domd/core/utils/file_utils.py +0 -0
  76. {domd-2.2.1 → domd-2.2.2}/src/domd/core/utils/logging_utils.py +0 -0
  77. {domd-2.2.1 → domd-2.2.2}/src/domd/core/utils/virtualenv.py +0 -0
  78. {domd-2.2.1 → domd-2.2.2}/src/domd/parsers/__init__.py +0 -0
  79. {domd-2.2.1 → domd-2.2.2}/src/domd/parsers/ansible.py +0 -0
  80. {domd-2.2.1 → domd-2.2.2}/src/domd/parsers/base.py +0 -0
  81. {domd-2.2.1 → domd-2.2.2}/src/domd/parsers/build_systems.py +0 -0
  82. {domd-2.2.1 → domd-2.2.2}/src/domd/parsers/ci_cd.py +0 -0
  83. {domd-2.2.1 → domd-2.2.2}/src/domd/parsers/docker/__init__.py +0 -0
  84. {domd-2.2.1 → domd-2.2.2}/src/domd/parsers/docker/docker_compose.py +0 -0
  85. {domd-2.2.1 → domd-2.2.2}/src/domd/parsers/docker/dockerfile.py +0 -0
  86. {domd-2.2.1 → domd-2.2.2}/src/domd/parsers/docker.py +0 -0
  87. {domd-2.2.1 → domd-2.2.2}/src/domd/parsers/javascript/__init__.py +0 -0
  88. {domd-2.2.1 → domd-2.2.2}/src/domd/parsers/javascript.py +0 -0
  89. {domd-2.2.1 → domd-2.2.2}/src/domd/parsers/package_json.py +0 -0
  90. {domd-2.2.1 → domd-2.2.2}/src/domd/parsers/python.py +0 -0
  91. {domd-2.2.1 → domd-2.2.2}/src/domd/parsers/test_build_systems.py +0 -0
  92. {domd-2.2.1 → domd-2.2.2}/src/domd/parsers/test_ci_cd.py +0 -0
  93. {domd-2.2.1 → domd-2.2.2}/src/domd/parsers/test_docker.py +0 -0
  94. {domd-2.2.1 → domd-2.2.2}/src/domd/parsers/test_javascript.py +0 -0
  95. {domd-2.2.1 → domd-2.2.2}/src/domd/parsers/test_python.py +0 -0
  96. {domd-2.2.1 → domd-2.2.2}/src/domd/parsing/__init__.py +0 -0
  97. {domd-2.2.1 → domd-2.2.2}/src/domd/parsing/base.py +0 -0
  98. {domd-2.2.1 → domd-2.2.2}/src/domd/reporters/__init__.py +0 -0
  99. {domd-2.2.1 → domd-2.2.2}/src/domd/reporters/console.py +0 -0
  100. {domd-2.2.1 → domd-2.2.2}/src/domd/reporters/json_reporter.py +0 -0
  101. {domd-2.2.1 → domd-2.2.2}/src/domd/reporters/test_console.py +0 -0
  102. {domd-2.2.1 → domd-2.2.2}/src/domd/reporters/test_json_reporter.py +0 -0
  103. {domd-2.2.1 → domd-2.2.2}/src/domd/reporters/test_todo_md.py +0 -0
  104. {domd-2.2.1 → domd-2.2.2}/src/domd/reporters/todo_md.py +0 -0
  105. {domd-2.2.1 → domd-2.2.2}/src/domd/reporting/__init__.py +0 -0
  106. {domd-2.2.1 → domd-2.2.2}/src/domd/utils/__init__.py +0 -0
  107. {domd-2.2.1 → domd-2.2.2}/src/domd/utils/command_runner.py +0 -0
  108. {domd-2.2.1 → domd-2.2.2}/src/domd/utils/file_utils.py +0 -0
  109. {domd-2.2.1 → domd-2.2.2}/src/domd/utils/test_command_runner.py +0 -0
  110. {domd-2.2.1 → domd-2.2.2}/src/domd/utils/test_file_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: domd
3
- Version: 2.2.1
3
+ Version: 2.2.2
4
4
  Summary: Project Command Detector - Automatically detects and tests project commands, generates TODO.md for failed commands
5
5
  License: Apache-2.0
6
6
  Author: Tom Sapletta
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "domd"
3
- version = "2.2.1"
3
+ version = "2.2.2"
4
4
  description = "Project Command Detector - Automatically detects and tests project commands, generates TODO.md for failed commands"
5
5
  authors = ["Tom Sapletta <info@softreck.dev>"]
6
6
  maintainers = ["WRONAI Team"]
@@ -213,6 +213,47 @@ class ProjectCommandDetector:
213
213
  """
214
214
  return get_virtualenv_environment(self.venv_info)
215
215
 
216
+ def _process_directory_readme(
217
+ self, directory: Path, all_commands: list, parent_dir: str = None
218
+ ) -> None:
219
+ """Process a README.md file in a directory and update command metadata.
220
+
221
+ Args:
222
+ directory: Directory containing the README.md
223
+ all_commands: List to append found commands to
224
+ parent_dir: Name of parent directory (for second-level directories)
225
+ """
226
+ readme_path = directory / "README.md"
227
+ if not readme_path.exists() or not readme_path.is_file():
228
+ return
229
+
230
+ # Determine display path for logging and source
231
+ if parent_dir:
232
+ display_path = f"{parent_dir}/{directory.name}/README.md"
233
+ else:
234
+ display_path = f"{directory.name}/README.md"
235
+
236
+ logger.info(f"Found README.md: {display_path}")
237
+
238
+ # Process README.md in directory
239
+ commands = self._process_file_commands(readme_path)
240
+
241
+ # Update command metadata with directory context
242
+ for cmd in commands:
243
+ if isinstance(cmd, dict):
244
+ cmd_metadata = cmd.setdefault("metadata", {})
245
+ cmd_metadata["cwd"] = str(directory)
246
+ cmd_metadata["source"] = display_path
247
+ elif hasattr(cmd, "metadata"):
248
+ if not hasattr(cmd.metadata, "get") or not callable(cmd.metadata.get):
249
+ cmd.metadata = {"original_metadata": cmd.metadata}
250
+ cmd.metadata["cwd"] = str(directory)
251
+ if not getattr(cmd, "source", None):
252
+ cmd.source = display_path
253
+
254
+ all_commands.extend(commands)
255
+ logger.info(f"Found {len(commands)} commands in {display_path}")
256
+
216
257
  def _process_file_commands(self, file_path: Path) -> List[Dict]:
217
258
  """Process a single file and extract commands.
218
259
 
@@ -309,37 +350,32 @@ class ProjectCommandDetector:
309
350
  for file_path in config_files:
310
351
  all_commands.extend(self._process_file_commands(file_path))
311
352
 
312
- # 2. Scan first-level subdirectories for README.md files
353
+ # 2. Scan first and second level subdirectories for README.md files
313
354
  try:
314
- for item in self.project_path.iterdir():
315
- if item.is_dir() and not item.name.startswith("."):
316
- readme_path = item / "README.md"
317
- if readme_path.exists() and readme_path.is_file():
318
- logger.info(f"Found README.md in subdirectory: {item.name}")
319
- # Process README.md in subdirectory
320
- commands = self._process_file_commands(readme_path)
321
-
322
- # Update command metadata with subdirectory context
323
- for cmd in commands:
324
- if isinstance(cmd, dict):
325
- cmd_metadata = cmd.setdefault("metadata", {})
326
- cmd_metadata["cwd"] = str(item)
327
- cmd_metadata["source"] = f"{item.name}/README.md"
328
- elif hasattr(cmd, "metadata"):
329
- if not hasattr(cmd.metadata, "get") or not callable(
330
- cmd.metadata.get
331
- ):
332
- cmd.metadata = {"original_metadata": cmd.metadata}
333
- cmd.metadata["cwd"] = str(item)
334
- if not getattr(cmd, "source", None):
335
- cmd.source = f"{item.name}/README.md"
336
-
337
- all_commands.extend(commands)
338
- logger.info(
339
- f"Found {len(commands)} commands in {item.name}/README.md"
355
+ # First level directories
356
+ for level1_item in self.project_path.iterdir():
357
+ if not level1_item.is_dir() or level1_item.name.startswith("."):
358
+ continue
359
+
360
+ # Process level 1 README
361
+ self._process_directory_readme(level1_item, all_commands)
362
+
363
+ # Scan second level
364
+ try:
365
+ for level2_item in level1_item.iterdir():
366
+ if not level2_item.is_dir() or level2_item.name.startswith("."):
367
+ continue
368
+
369
+ # Process level 2 README
370
+ self._process_directory_readme(
371
+ level2_item, all_commands, level1_item.name
340
372
  )
373
+ except Exception as e:
374
+ logger.error(
375
+ f"Error scanning subdirectory {level1_item}: {e}", exc_info=True
376
+ )
341
377
  except Exception as e:
342
- logger.error(f"Error scanning subdirectories: {e}", exc_info=True)
378
+ logger.error(f"Error scanning directories: {e}", exc_info=True)
343
379
 
344
380
  logger.info(f"Found {len(all_commands)} commands in total")
345
381
 
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
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