Skip to content

Feature Request: Refactor Configuration Architecture for Better CLI/Library Separation #12

Description

@rahlk

Summary

Refactor the current parameter-passing approach to use a layered configuration pattern that cleanly separates CLI concerns from core analysis configuration, improving both library usability and maintainability.

Current State

The Codeanalyzer class currently accepts individual parameters in its constructor:

withCodeanalyzer(
input, analysis_level, using_codeql, rebuild_analysis, cache_dir, clear_cache
) asanalyzer:

This approach has several limitations:

  • Library users must pass CLI-specific parameters (like clear_cache)
  • Parameter explosion as new options are added
  • Tight coupling between CLI and core analysis logic
  • Hard to test - requires mocking many individual parameters
  • No validation of parameter combinations
  • No config file support - difficult to extend

Proposed Solution

1. Core Configuration Object

Create an AnalysisOptions class that contains only analysis-relevant settings:

@dataclassclassAnalysisOptions:
input_path: Pathanalysis_level: int=1using_codeql: bool=Falserebuild_analysis: bool=Falsecache_dir: Optional[Path] =Nonedefvalidate(self):
# Centralized validation logicpass@classmethoddeffrom_dict(cls, config: dict):
# Support for config filespass

2. CLI Configuration Layer

Create a CLIOptions class for CLI-specific concerns:

@dataclassclassCLIOptions:
output_dir: Optional[Path] =Noneoutput_format: OutputFormat=OutputFormat.JSONverbosity: int=0clear_cache: bool=Truedefsetup_logging(self):
# Handle CLI-specific setuppass

3. Updated Core Interface

Modify Codeanalyzer to accept the configuration object:

classCodeanalyzer:
def__init__(self, options: AnalysisOptions):
self.options=options# Clean, single source of configuration

Benefits

For Library Users

  • Clean API: Single configuration object instead of many parameters
  • Type Safety: Better IDE support and validation
  • Extensibility: Easy to add new options without breaking existing code
  • Testability: Simple to create test configurations
# Clean library usageoptions=AnalysisOptions(
input_path=Path("my_project"),
analysis_level=2,
using_codeql=True
)
withCodeanalyzer(options) asanalyzer:
results=analyzer.analyze()

For CLI Users

  • No breaking changes: CLI interface remains the same
  • Better error messages: Centralized validation
  • Future extensibility: Config file support, presets, etc.

For Maintainers

  • Separation of concerns: CLI logic separate from analysis logic
  • Easier testing: Mock configuration objects instead of individual parameters
  • Better validation: Centralized parameter validation and type checking
  • Extensibility: Easy to add features like config files, environment variables

Backward Compatibility

  • CLI interface remains unchanged
  • Library interface change is breaking, but provides clear migration path
  • Consider deprecation warnings for old constructor signature

Testing Strategy

  • Unit tests for configuration validation
  • Integration tests for CLI/library interfaces
  • Test configuration serialization/deserialization
  • Test error handling and validation

Success Metrics

  • Reduced coupling between CLI and core analysis
  • Improved library API usability
  • Foundation for future configuration enhancements
  • Better test coverage of configuration logic

References

Similar patterns used successfully in:

  • MyPy (mypy.options.Options)
  • Black (black.FileMode)
  • Pylint (pylint.config.Configuration)
  • WALA (AnalysisOptions)

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions