@@ -10,7 +10,7 @@ The dependency resolver uses a modular detector architecture where each package
1010
1111Before adding a new detector, ensure you understand:
1212
13- 1 . ** Architecture Decision Records (ADRs)** : Review ` /docs/adr/ ` for design principles
13+ 1 . ** Architecture Decision Records (ADRs)** : Review ` /docs/technical/architecture/ adr/ ` for design principles
14142 . ** Existing Detectors** : Study ` /dependency_resolver/detectors/ ` implementations
15153 . ** Interface Contracts** : Understand ` PackageManagerDetector ` in ` /dependency_resolver/core/interfaces.py `
16164 . ** Testing Patterns** : Review ` /tests/detectors/ ` structure
@@ -19,40 +19,13 @@ Before adding a new detector, ensure you understand:
1919
2020### 1.1 Create the Detector File
2121
22- Create ` /dependency_resolver/detectors/{package_manager}_detector.py ` :
22+ Create ` /dependency_resolver/detectors/{package_manager}_detector.py ` implementing the ` PackageManagerDetector ` interface with these required methods :
2323
24- ``` python
25- from typing import Optional, Any
26- from ..core.interfaces import EnvironmentExecutor, PackageManagerDetector
27-
28-
29- class {PackageManager}Detector(PackageManagerDetector):
30- """ Detector for {Package Manager Description}."""
31-
32- NAME = " {package_manager} "
33-
34- def __init__ (self , debug : bool = False ):
35- self .debug = debug
36-
37- def is_usable (self , executor : EnvironmentExecutor, working_dir : Optional[str ] = None ) -> bool :
38- """ Check if {package_manager} is usable in the environment."""
39- # Implement OS compatibility check if needed
40- # Check if package manager tool is available
41- _, _, exit_code = executor.execute_command(" {package_manager} --version" , working_dir)
42- return exit_code == 0
43-
44- def get_dependencies (self , executor : EnvironmentExecutor, working_dir : Optional[str ] = None ) -> dict[str , Any]:
45- """ Extract {package_manager} dependencies with versions."""
46- # Implement dependency extraction logic
47- # Return format: {"scope": "system|project", "location": "path", "dependencies": {}, "hash": "sha256"}
48- pass
49-
50- def has_system_scope (self , executor : EnvironmentExecutor, working_dir : Optional[str ] = None ) -> bool :
51- """ Check if this detector operates at system scope."""
52- # Return True for system-wide package managers (dpkg, apk)
53- # Return False or implement logic for project-scoped managers (pip, npm)
54- pass
55- ```
24+ - ` __init__(self, debug: bool = False) ` : Initialize detector with debug flag
25+ - ` is_usable() ` : Check if package manager is available in the environment
26+ - ` get_dependencies() ` : Extract package dependencies with versions and metadata
27+ - ` has_system_scope() ` : Determine if detector operates at system or project scope
28+ - ` get_name() ` : Return the detector name (inherited from base class)
5629
5730### 1.2 Key Implementation Considerations
5831
@@ -89,30 +62,16 @@ class {PackageManager}Detector(PackageManagerDetector):
8962
9063### 2.1 Update the Orchestrator
9164
92- Add your detector to ` /dependency_resolver/core/orchestrator.py ` :
93-
94- ``` python
95- from ..detectors.{package_manager}_detector import {PackageManager}Detector
96-
97- class Orchestrator :
98- def __init__ (self , ...):
99- # Add to detectors list in priority order
100- self .detectors: list[PackageManagerDetector] = [
101- DockerInfoDetector(),
102- DpkgDetector(),
103- ApkDetector(),
104- {PackageManager}Detector(debug = debug), # Add here
105- PipDetector(venv_path = venv_path, debug = debug),
106- NpmDetector(debug = debug),
107- ]
108- ```
65+ Add your detector to the detectors list in ` /dependency_resolver/core/orchestrator.py ` following the priority order:
10966
11067** Priority Ordering** :
11168
112691 . Container information (docker-info)
113702 . System packages (dpkg, apk, yum, etc.)
114713 . Language-specific packages (pip, npm, etc.)
11572
73+ Reference existing detectors like ` DpkgDetector ` , ` ApkDetector ` , ` PipDetector ` , and ` NpmDetector ` for import and initialization patterns.
74+
11675### 2.2 Update Package Imports
11776
11877Add to ` /dependency_resolver/detectors/__init__.py ` if needed.
@@ -132,144 +91,61 @@ Create `/docs/technical/detectors/{package_manager}_detector.md` with the follow
13291- ** Limitations** : Known limitations or edge cases
13392- ** Example Output** : JSON sample showing expected output format
13493
135- ** Example JSON Output Format:**
94+ ** Expected JSON Output Format:**
13695
137- ``` json
138- {
139- "scope" : " system" ,
140- "dependencies" : {
141- "package1" : {"version" : " 1.0.0" , "hash" : " sha256..." },
142- "package2" : {"version" : " 2.0.0" , "hash" : " sha256..." }
143- },
144- "hash" : " sha256..."
145- }
146- ```
96+ Standard output includes ` scope ` , ` dependencies ` dict with package names and versions, and optional ` hash ` and ` location ` fields. Reference existing detector documentation for specific examples.
14797
14898## Step 4: Implement Tests
14999
150100### 4.1 Test Directory Structure
151101
152- Create ` /tests/detectors/{package_manager}/ ` :
102+ Create ` /tests/detectors/{package_manager}/ ` with :
153103
154- ``` plain
155- tests/detectors/{package_manager}/
156- ├── __init__.py
157- ├── README.md
158- └── test_{package_manager}_docker_detection.py
159- ```
104+ - ` __init__.py `
105+ - ` README.md `
106+ - ` test_{package_manager}_docker_detection.py `
160107
161108### 4.2 Docker Test Implementation
162109
163- Create ` /tests/detectors/{package_manager}/test_{package_manager}_docker_detection.py ` :
164-
165- ``` python
166- """ Test {package_manager} Docker container dependency detection."""
167-
168- import os
169- import sys
170- from typing import Dict, Any
171-
172- # Add parent directory to path for imports
173- sys.path.insert(0 , os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__ )))))
174-
175- import pytest
176- from dependency_resolver.executors import DockerExecutor
177- from dependency_resolver.core.orchestrator import Orchestrator
178- from tests.common.docker_test_base import DockerTestBase
179-
180- try :
181- import docker
182- except ImportError :
183- docker = None # type: ignore
184-
185-
186- class Test{PackageManager}DockerDetection(DockerTestBase):
187- """ Test {package_manager} dependency detection using Docker container environment."""
188-
189- # Choose appropriate Docker image that has your package manager
190- TEST_IMAGE = " appropriate/docker-image"
191-
192- @pytest.mark.skipif (docker is None , reason = " Docker not available" )
193- def test_{package_manager}_docker_container_detection(self , request: pytest.FixtureRequest) -> None :
194- """ Test {package_manager} dependency detection inside a Docker container."""
110+ Create a test class inheriting from ` DockerTestBase ` in ` /tests/common/docker_test_base.py ` . Key components:
195111
196- verbose_output = self .setup_verbose_output(request)
197- container_id = None
112+ - Choose appropriate Docker image containing your package manager
113+ - Use ` DockerExecutor ` to run tests in containerized environment
114+ - Test via ` Orchestrator ` to ensure integration works correctly
115+ - Validate expected output format and required fields
116+ - Include proper cleanup and error handling
198117
199- try :
200- container_id = self .start_container(self .TEST_IMAGE , additional_args = [])
201- self .wait_for_container_ready(container_id, " {package_manager} --version" , max_wait = 60 )
202-
203- executor = DockerExecutor(container_id)
204- orchestrator = Orchestrator(debug = False , skip_system_scope = False )
205-
206- result = orchestrator.resolve_dependencies(executor)
207-
208- if verbose_output:
209- self .print_verbose_results(" DEPENDENCY RESOLVER OUTPUT:" , result)
210-
211- self ._validate_{package_manager}_dependencies(result)
212-
213- finally :
214- if container_id:
215- self .cleanup_container(container_id)
216-
217- def _validate_{package_manager}_dependencies(self , result: Dict[str , Any]) -> None :
218- """ Validate {package_manager} dependencies in the result."""
219- assert " {package_manager} " in result
220-
221- {package_manager}_result = result[" {package_manager} " ]
222- assert " scope" in {package_manager}_result
223- assert " dependencies" in {package_manager}_result
224-
225- # Add specific validations for your package manager
226- dependencies = {package_manager}_result[" dependencies" ]
227- assert isinstance (dependencies, dict )
228-
229- # Validate expected packages if known
230- # assert "expected-package" in dependencies
231- ```
118+ Reference existing detector tests in ` /tests/detectors/ ` for implementation patterns.
232119
233120### 4.3 Test README
234121
235- Create ` /tests/detectors/{package_manager}/README.md ` with :
122+ Create ` /tests/detectors/{package_manager}/README.md ` documenting :
236123
237124** Content Structure:**
238125
239126- ** Docker Test** : Description of Docker-based testing approach
240127- ** Image Used** : Document the Docker image used for testing
241- - ** Test Commands** : List the commands tested (e.g., ` {package_manager} --version ` )
128+ - ** Test Commands** : List the commands tested
242129- ** Running Tests** : Instructions for executing the tests
243130
244- ** Test Execution Commands :**
131+ ** Test Execution Patterns :**
245132
246- - Run all tests: ` pytest tests/detectors/{package_manager}/ `
247- - Verbose output: ` pytest tests/detectors/{package_manager}/ --verbose-resolver `
248- - Specific test: ` pytest tests/detectors/{package_manager}/test_{package_manager}_docker_detection.py::Test{PackageManager}DockerDetection::test_{package_manager}_docker_container_detection `
133+ Reference pytest command patterns from existing detector test READMEs for running individual tests, verbose output, and full test suites.
249134
250135## Step 5: Integration and Testing
251136
252137### 5.1 Manual Testing
253138
254139** Basic Testing Steps:**
255140
256- 1 . ** Activate environment** : ` source venv/bin/activate `
141+ 1 . ** Activate environment** : Use virtual environment activation
2571422 . ** Test detector directly** : Import and run your detector with ` debug=True `
258- 3 . ** Test via CLI** : ` python3 -m dependency_resolver --debug `
143+ 3 . ** Test via CLI** : Use debug mode to see detailed output
2591444 . ** Test in target environment** : Use appropriate executor (host/docker) for your use case
260145
261146### 5.2 Run Test Suite
262147
263- ``` bash
264- # Run your detector tests
265- pytest tests/detectors/{package_manager}/
266-
267- # Run all tests
268- pytest
269-
270- # Run linting
271- pre-commit run --files $( git diff --name-only --diff-filter=ACMR HEAD)
272- ```
148+ Run detector-specific tests, full test suite, and linting checks. Reference CLAUDE.md for specific commands and patterns.
273149
274150## Step 6: Documentation and Performance
275151
@@ -283,36 +159,23 @@ If a `performance-analysis/` directory exists, add a benchmark script following
283159
284160## Common Implementation Patterns
285161
286- ### System-Wide Detectors (dpkg, apk style)
287-
288- ``` python
289- def has_system_scope (self , executor : EnvironmentExecutor, working_dir : Optional[str ] = None ) -> bool :
290- return True # Always system scope
291-
292- def get_dependencies (self , executor : EnvironmentExecutor, working_dir : Optional[str ] = None ) -> dict[str , Any]:
293- # Extract from system package database
294- # Usually ignore working_dir for system packages
295- result = {" scope" : " system" , " dependencies" : {}}
296- ```
297-
298- ### Project-Scoped Detectors (pip, npm style)
299-
300- ``` python
301- def has_system_scope (self , executor : EnvironmentExecutor, working_dir : Optional[str ] = None ) -> bool :
302- if working_dir:
303- # Check for project files in working_dir
304- return not self ._has_project_files(executor, working_dir)
305- return True # Default to system if no working_dir
306-
307- def get_dependencies (self , executor : EnvironmentExecutor, working_dir : Optional[str ] = None ) -> dict[str , Any]:
308- if working_dir and self ._has_project_files(executor, working_dir):
309- # Extract project dependencies
310- location = self ._resolve_absolute_path(executor, working_dir)
311- return {" scope" : " project" , " location" : location, " dependencies" : {}}
312- else :
313- # Extract system dependencies
314- return {" scope" : " system" , " dependencies" : {}}
315- ```
162+ ### System-Wide Detectors
163+
164+ Reference ` DpkgDetector ` and ` ApkDetector ` implementations:
165+
166+ - Always return ` True ` for ` has_system_scope() `
167+ - Extract from system package database
168+ - Usually ignore ` working_dir ` for system packages
169+ - Return ` {"scope": "system", "dependencies": {}} `
170+
171+ ### Project-Scoped Detectors
172+
173+ Reference ` PipDetector ` and ` NpmDetector ` implementations:
174+
175+ - Check for project files in ` working_dir ` to determine scope
176+ - Extract project dependencies when project files found
177+ - Fall back to system scope when no project context
178+ - Return appropriate scope with location for project dependencies
316179
317180## Debugging Tips
318181
@@ -322,6 +185,8 @@ def get_dependencies(self, executor: EnvironmentExecutor, working_dir: Optional[
3221854 . ** Validate JSON Output** : Ensure output follows expected schema
3231865 . ** Test Both Scopes** : If supporting both project and system scope
324187
188+ Use ` python3 -m dependency_resolver --debug ` to see detailed execution flow.
189+
325190## Quality Checklist
326191
327192Before submitting your detector:
@@ -338,11 +203,19 @@ Before submitting your detector:
338203- [ ] Manual testing in target environments
339204- [ ] Performance considerations documented
340205
341- ## Support
206+ ## Support and References
207+
208+ ** Key Reference Files:**
209+
210+ - ` /dependency_resolver/detectors/ ` - Existing detector implementations
211+ - ` /dependency_resolver/core/interfaces.py ` - PackageManagerDetector interface
212+ - ` /dependency_resolver/core/orchestrator.py ` - Detector registration
213+ - ` /docs/technical/architecture/adr/ ` - Architecture decision records
214+ - ` /tests/detectors/ ` - Test patterns and examples
215+ - ` /tests/common/docker_test_base.py ` - Docker testing base class
342216
343- For questions or assistance:
217+ ** Debug Commands: **
344218
345- 1 . Review existing detector implementations in ` /dependency_resolver/detectors/ `
346- 2 . Check ADRs in ` /docs/adr/ ` for architectural decisions
347- 3 . Examine test patterns in ` /tests/detectors/ `
348- 4 . Follow the debug output with ` python3 -m dependency_resolver --debug `
219+ - ` python3 -m dependency_resolver --debug ` - Full debug output
220+ - ` source venv/bin/activate ` - Activate development environment
221+ - ` pre-commit run --files $(git diff --name-only --diff-filter=ACMR HEAD) ` - Run linting
0 commit comments