Documentation Index
Fetch the complete documentation index at: https://docs.myspellchecker.com/llms.txt
Use this file to discover all available pages before exploring further.
Components like providers, validators, and the grammar engine are wired together through a central ServiceContainer rather than hard-coded imports. This makes it straightforward to swap implementations for testing or customize the validation pipeline.
Overview
The DI system consists of:
- ServiceContainer: Central registry for services
- Factory Functions: Create components with dependencies
- ComponentFactory: High-level factory for spell checker components
ServiceContainer
The ServiceContainer manages component lifecycle through factory functions:
from myspellchecker.core.di.container import ServiceContainer
from myspellchecker.core.config import SpellCheckerConfig
config = SpellCheckerConfig()
container = ServiceContainer(config)
Registering Services
Register factory functions that create services:
def create_provider(container):
"""Factory function for provider."""
config = container.get_config()
return SQLiteProvider(database_path=config.provider_config.database_path)
# Register as singleton (default)
container.register_factory("provider", create_provider, singleton=True)
# Register as transient (new instance each time)
container.register_factory("temp_service", create_temp, singleton=False)
Retrieving Services
Services are created lazily on first access:
# First call creates the instance
provider = container.get("provider")
# Subsequent calls return cached instance (for singletons)
provider2 = container.get("provider")
assert provider is provider2 # Same instance
Available Services
The default container provides these services:
| Service Name | Type | Description |
|---|
provider | DictionaryProvider | Dictionary storage backend |
segmenter | Segmenter | Text segmentation |
phonetic_hasher | PhoneticHasher | Phonetic matching (optional) |
symspell | SymSpell | SymSpell algorithm |
context_checker | NgramContextChecker | N-gram checking (optional) |
suggestion_strategy | CompositeSuggestionStrategy | Unified suggestion pipeline aggregating SymSpell, morphology, and compound sources |
syllable_validator | SyllableValidator | Syllable validation |
word_validator | WordValidator | Word validation |
context_validator | ContextValidator | Context validation (full: 12 strategies) |
context_validator_minimal | ContextValidator | Context validation (fast: tone, syntactic, question only) |
tone_disambiguator | ToneDisambiguator | Context-aware tone mark correction (optional) |
syntactic_rule_checker | SyntacticRuleChecker | Grammar rule checking (optional) |
viterbi_tagger | ViterbiTagger | HMM-based POS tagging (optional) |
homophone_checker | HomophoneChecker | Homophone detection (optional) |
semantic_checker | SemanticChecker | AI-powered semantic analysis (optional) |
name_heuristic | NameHeuristic | Named entity recognition heuristic (optional) |
Thread Safety
Singleton creation is thread-safe using double-checked locking:
# Safe to call from multiple threads
from concurrent.futures import ThreadPoolExecutor
with ThreadPoolExecutor(max_workers=4) as executor:
futures = [executor.submit(container.get, "provider") for _ in range(10)]
providers = [f.result() for f in futures]
# All return the same instance
assert all(p is providers[0] for p in providers)
Container Operations
# Check if service is registered
if container.has_service("provider"):
provider = container.get("provider")
# List all registered services
services = container.list_services()
print(services) # ['context_checker', 'phonetic_hasher', 'provider', ...]
# Clear cached instances (forces recreation)
container.clear_cache()
Component Factories
Individual component factories create specific services:
ProviderFactory
ProviderFactory is a type alias for Callable[[ServiceContainer], DictionaryProvider].
Use create_provider_factory() to get the factory function:
from myspellchecker.core.factories.provider_factory import create_provider_factory
factory_fn = create_provider_factory()
container.register_factory("provider", factory_fn)
provider = container.get("provider")
SymSpellFactory
SymSpellFactory is a type alias for Callable[[ServiceContainer], SymSpell].
Use create_symspell_factory() to get the factory function:
from myspellchecker.core.factories.symspell_factory import create_symspell_factory
factory_fn = create_symspell_factory()
container.register_factory("symspell", factory_fn)
symspell = container.get("symspell")
ValidatorsFactory
ValidatorFactory is a type alias for Callable[[ServiceContainer], Validator].
create_validators_factory() returns a dict of named factory functions:
from myspellchecker.core.factories.validators_factory import create_validators_factory
validator_factories = create_validators_factory()
# Keys are "syllable", "word", "context"
for name, factory_fn in validator_factories.items():
container.register_factory(f"{name}_validator", factory_fn)
syllable_validator = container.get("syllable_validator")
word_validator = container.get("word_validator")
context_validator = container.get("context_validator")
SegmenterFactory
SegmenterFactory is a type alias for Callable[[ServiceContainer], Segmenter].
Use create_segmenter_factory() to get the factory function:
from myspellchecker.core.factories.segmenter_factory import create_segmenter_factory
factory_fn = create_segmenter_factory()
container.register_factory("segmenter", factory_fn)
segmenter = container.get("segmenter")
RankerFactory
The ranker factory uses create_base_ranker() which takes a RankerConfig directly
(not the container pattern):
from myspellchecker.core.factories.ranker_factory import create_base_ranker
from myspellchecker.core.config import RankerConfig
ranker_config = RankerConfig()
ranker = create_base_ranker(ranker_config)
PhoneticFactory
PhoneticHasherFactory is a type alias for Callable[[ServiceContainer], Optional[PhoneticHasher]].
Use create_phonetic_hasher_factory() to get the factory function:
from myspellchecker.core.factories.phonetic_factory import create_phonetic_hasher_factory
factory_fn = create_phonetic_hasher_factory()
container.register_factory("phonetic_hasher", factory_fn)
hasher = container.get("phonetic_hasher") # Returns None if disabled
ContextCheckerFactory
ContextCheckerFactory is a type alias for Callable[[ServiceContainer], Optional[NgramContextChecker]].
Use create_context_checker_factory() to get the factory function:
from myspellchecker.core.factories.context_checker_factory import create_context_checker_factory
factory_fn = create_context_checker_factory()
container.register_factory("context_checker", factory_fn)
checker = container.get("context_checker") # Returns None if disabled
ContextValidatorFactory
ContextValidatorFactory is a type alias for Callable[[ServiceContainer], ContextValidator].
Use create_context_validator_factory() to create a ContextValidator wired with all validation strategies (tone, syntactic, POS sequence, question structure, homophone, n-gram, semantic):
from myspellchecker.core.factories.context_validator_factory import create_context_validator_factory
factory_fn = create_context_validator_factory()
container.register_factory("context_validator", factory_fn)
validator = container.get("context_validator")
A minimal variant is also available via create_context_validator_minimal_factory() for fast mode (only tone, syntactic, and question structure strategies).
OptionalServicesFactory
The optional_services_factory module provides factory functions for services that enable advanced validation but are not required for basic spell checking. Each returns None if dependencies are unavailable (graceful degradation):
from myspellchecker.core.factories.optional_services_factory import (
create_tone_disambiguator_factory,
create_syntactic_rule_checker_factory,
create_viterbi_tagger_factory,
create_homophone_checker_factory,
create_semantic_checker_factory,
create_name_heuristic_factory,
)
container.register_factory("tone_disambiguator", create_tone_disambiguator_factory())
container.register_factory("syntactic_rule_checker", create_syntactic_rule_checker_factory())
container.register_factory("viterbi_tagger", create_viterbi_tagger_factory())
container.register_factory("homophone_checker", create_homophone_checker_factory())
container.register_factory("semantic_checker", create_semantic_checker_factory())
container.register_factory("name_heuristic", create_name_heuristic_factory())
SuggestionStrategyFactory
SuggestionStrategyFactory is a type alias for Callable[[ServiceContainer], Optional[SuggestionStrategy]].
Use create_suggestion_strategy_factory() to create a CompositeSuggestionStrategy that aggregates suggestions from multiple sources (SymSpell, morphology, compound) with unified ranking:
from myspellchecker.core.factories.suggestion_strategy_factory import create_suggestion_strategy_factory
factory_fn = create_suggestion_strategy_factory()
container.register_factory("suggestion_strategy", factory_fn)
strategy = container.get("suggestion_strategy") # Returns None if required deps unavailable
Dependencies are resolved in order: provider -> symspell -> context_checker (optional). If context checking is enabled, the composite is wrapped in ContextSuggestionStrategy for context-aware re-ranking.
ComponentFactory
The high-level ComponentFactory orchestrates component creation:
from myspellchecker.core.component_factory import ComponentFactory
from myspellchecker.core.config import SpellCheckerConfig
config = SpellCheckerConfig()
factory = ComponentFactory(config)
# Create all components (requires provider and segmenter)
components = factory.create_all(provider, segmenter)
# Access individual components
viterbi_tagger = components.get("viterbi_tagger")
joint_tagger = components.get("joint_segment_tagger")
semantic_checker = components.get("semantic_checker")
Creating Custom Factories
Implement the ComponentFactoryProtocol to provide custom component construction:
from myspellchecker.core.component_factory import ComponentFactoryProtocol
from myspellchecker import SpellChecker
class MyCustomFactory:
"""Custom factory following ComponentFactoryProtocol."""
def __init__(self, config):
self.config = config
def create_all(self, provider, segmenter):
"""Create all components with custom logic."""
return {
"symspell": MyCustomSymSpell(provider),
# ... other components
}
# Pass custom factory to SpellChecker
checker = SpellChecker(factory=MyCustomFactory(config))
Register with the container using a factory function:
def create_my_component(container):
config = container.get_config()
provider = container.get("provider")
return MyCustomComponent(provider=provider, option=config.my_option)
container.register_factory("my_component", create_my_component)
Dependency Resolution
Dependencies are resolved through the container:
def create_word_validator(container: ServiceContainer):
"""Factory with dependencies."""
config = container.get_config()
# Resolve dependencies
provider = container.get("provider")
syllable_validator = container.get("syllable_validator")
symspell = container.get("symspell")
return WordValidator(
config=config,
segmenter=container.get("segmenter"),
word_repository=provider, # Provider implements WordRepository protocol
syllable_repository=provider, # Provider implements SyllableRepository protocol
symspell=symspell,
context_checker=container.get("context_checker"),
suggestion_strategy=container.get("suggestion_strategy"),
)
Testing with DI
DI makes testing easier by allowing mock injection:
from unittest.mock import Mock
# Create container with config
config = SpellCheckerConfig()
container = ServiceContainer(config)
# Register mock provider
mock_provider = Mock()
mock_provider.is_valid_word.return_value = True
container.register_factory("provider", lambda c: mock_provider)
# Component uses mock
validator = container.get("word_validator")
# validator uses mock_provider internally
Service Registration
The ServiceContainer provides service registration and discovery:
from myspellchecker.core.di import ServiceContainer
config = SpellCheckerConfig()
container = ServiceContainer(config)
# Register a factory function for a service
def create_provider(container):
return SQLiteProvider(database_path="mydict.db")
container.register_factory("provider", create_provider)
# Get service instance (lazy initialization)
provider = container.get("provider")
Best Practices
- Singleton for expensive resources: Use singleton=True for database connections, caches
- Transient for stateful services: Use singleton=False for services with request-specific state
- Factory functions: Keep factory functions simple and focused
- Dependency declaration: Explicitly resolve dependencies in factory functions
- Configuration access: Use
container.get_config() for configuration values
Architecture
+------------------------------------------------------+
| SpellChecker |
| |
| +------------------------------------------------+ |
| | ServiceContainer | |
| | | |
| | +------------------+ +------------------+ | |
| | | Provider Factory | | SymSpell Factory | | |
| | +------------------+ +------------------+ | |
| | | |
| | +--------------------+ +------------------+ | |
| | | Segmenter Factory | | Validators | | |
| | | | | Factory | | |
| | +--------------------+ +------------------+ | |
| | | |
| | +------------------+ +--------------------+ | |
| | | Context Factory | | Optional Services | | |
| | +------------------+ +--------------------+ | |
| | | |
| +------------------------------------------------+ |
| |
+------------------------------------------------------+
See Also