Source code for flexicon.code.System.context_collection
#
# context_collection.py
#
# Class: ContextCollection
# Smart collection for phonological contexts with type-aware filtering
# and unified access across multiple concrete types.
#
# Platform: Python.NET
# FieldWorks Version 9+
#
# Copyright 2025
#
"""
Smart collection class for phonological contexts.
This module provides ContextCollection, a smart collection that manages
phonological contexts while showing type diversity and supporting unified
operations across the multiple concrete types:
- PhSimpleContextSeg
- PhSimpleContextNC
- PhComplexContextSeg
- PhComplexContextNC
- PhBoundaryContext
Problem:
GetAll() or input_contexts returns objects with multiple concrete implementations.
Users need to:
- See which types are in the collection
- Filter by type if they want to
- Work with all types together without manual casting
- Filter by common properties that work across all types
Solution:
ContextCollection provides:
- __str__() showing type breakdown
- by_type() filtering to specific concrete types
- filter() for common criteria (context_name, type)
- Convenience methods (simple_contexts(), complex_contexts(), boundary_contexts())
- Chainable filtering: contexts.simple_contexts().filter(name_contains='word')
Example::
from flexlibs2.code.System.context_collection import ContextCollection
# Rule's input contexts now wrapped in ContextCollection
contexts = rule.input_contexts # Returns ContextCollection
print(contexts) # Shows type breakdown
# ContextCollection (8 total)
# PhSimpleContextSeg: 4 (50%)
# PhBoundaryContext: 3 (37%)
# PhSimpleContextNC: 1 (13%)
# Filter by type
simple_only = contexts.simple_contexts()
print(len(simple_only)) # 5
# Filter by name
word_contexts = contexts.filter(name_contains='word')
# Chain filters
simple_word = contexts.simple_contexts().filter(name_contains='word')
# Iterate
for context in contexts:
print(context.context_name)
"""
from ..Shared.smart_collection import SmartCollection
from .phonological_context import PhonologicalContext
[docs]
class ContextCollection(SmartCollection):
"""
Smart collection for phonological contexts with type-aware filtering.
Manages collections of phonological contexts (PhonologicalContext wrapper objects)
with type-aware display and filtering capabilities. Supports filtering by
common properties (name, type) and by concrete type.
Attributes:
_items: List of PhonologicalContext wrapper objects
Example::
contexts = rule.input_contexts # Returns ContextCollection
print(contexts) # Shows type breakdown
simple = contexts.simple_contexts() # Filter to simple contexts
word = contexts.filter(name_contains='word') # Name filter
both = contexts.simple_contexts().filter(name_contains='word') # Chain
"""
def __init__(self, items=None):
"""
Initialize a ContextCollection.
Args:
items: Iterable of PhonologicalContext objects, or None for empty.
Example::
collection = ContextCollection()
collection = ContextCollection([context1, context2, context3])
"""
super().__init__(items)
[docs]
def filter(self, name_contains=None, where=None):
"""
Filter the collection by common context properties.
Supports filtering by properties that work across all context types
(name). For complex filtering, use where().
Args:
name_contains (str, optional): Filter to contexts whose name contains
this string (case-sensitive).
where (callable, optional): Custom predicate function. If provided,
other criteria are ignored.
Returns:
ContextCollection: New collection with filtered items.
Example::
# Filter by name
word_contexts = contexts.filter(name_contains='word')
# Custom filtering
simple_word = contexts.where(
lambda c: c.is_simple_context and 'word' in c.context_name
)
# Chain filters
simple_word = contexts.simple_contexts().filter(name_contains='word')
Notes:
- name_contains is case-sensitive
- where() takes precedence over other criteria
- Returns new collection (doesn't modify original)
- Use where() for complex custom filtering
"""
# If custom predicate provided, use it
if where is not None:
filtered = [item for item in self._items if where(item)]
return ContextCollection(filtered)
# Apply criteria filters
filtered = self._items
if name_contains is not None:
filtered = [ctx for ctx in filtered if name_contains in (ctx.context_name or "")]
return ContextCollection(filtered)
[docs]
def where(self, predicate):
"""
Filter using a custom predicate function.
For filtering by complex criteria or properties not supported by filter().
Args:
predicate (callable): Function that takes a PhonologicalContext and
returns True to include it in the result.
Returns:
ContextCollection: New collection with items matching the predicate.
Example::
# Complex predicate: simple segment contexts only
simple_segs = contexts.where(lambda c: c.is_simple_context_seg)
# Combining conditions
simple_with_name = contexts.where(
lambda c: c.is_simple_context and c.context_name
)
Notes:
- Predicate receives each PhonologicalContext object
- Return True to include in result, False to exclude
- For simple filters (name), use filter() instead
"""
filtered = [ctx for ctx in self._items if predicate(ctx)]
return ContextCollection(filtered)
[docs]
def simple_contexts(self):
"""
Get only the simple contexts (segment or natural class).
Convenience method for filtering to simple contexts (either
PhSimpleContextSeg or PhSimpleContextNC).
Returns:
ContextCollection: New collection with only simple context objects.
Example::
simple = contexts.simple_contexts()
print(f"Found {len(simple)} simple contexts")
# Chain with other filters
simple_word = contexts.simple_contexts().filter(name_contains='word')
Notes:
- Includes both PhSimpleContextSeg and PhSimpleContextNC
- Use simple_context_seg() or simple_context_nc() to distinguish
"""
filtered = [ctx for ctx in self._items if ctx.is_simple_context]
return ContextCollection(filtered)
[docs]
def simple_context_seg(self):
"""
Get only the simple segment contexts.
Convenience method for filtering to PhSimpleContextSeg objects only.
Returns:
ContextCollection: New collection with only simple segment contexts.
Example::
segs = contexts.simple_context_seg()
for seg_ctx in segs:
segment = seg_ctx.segment
print(f"Segment: {segment}")
Notes:
- Simple segment contexts represent a single segment
- Equivalent to by_type('PhSimpleContextSeg')
"""
return self.by_type("PhSimpleContextSeg")
[docs]
def simple_context_nc(self):
"""
Get only the simple natural class contexts.
Convenience method for filtering to PhSimpleContextNC objects only.
Returns:
ContextCollection: New collection with only simple natural class contexts.
Example::
ncs = contexts.simple_context_nc()
for nc_ctx in ncs:
nc = nc_ctx.natural_class
print(f"Natural Class: {nc}")
Notes:
- Simple natural class contexts represent a natural class
- Equivalent to by_type('PhSimpleContextNC')
"""
return self.by_type("PhSimpleContextNC")
[docs]
def complex_contexts(self):
"""
Get only the complex contexts (segment or natural class).
Convenience method for filtering to complex contexts (either
PhComplexContextSeg or PhComplexContextNC).
Returns:
ContextCollection: New collection with only complex context objects.
Example::
complex = contexts.complex_contexts()
print(f"Found {len(complex)} complex contexts")
# Chain with other filters
complex_word = contexts.complex_contexts().filter(name_contains='word')
Notes:
- Includes both PhComplexContextSeg and PhComplexContextNC
- Use complex_context_seg() or complex_context_nc() to distinguish
"""
filtered = [ctx for ctx in self._items if ctx.is_complex_context]
return ContextCollection(filtered)
[docs]
def complex_context_seg(self):
"""
Get only the complex segment contexts.
Convenience method for filtering to PhComplexContextSeg objects only.
Returns:
ContextCollection: New collection with only complex segment contexts.
Example::
segs = contexts.complex_context_seg()
print(f"Found {len(segs)} complex segment contexts")
Notes:
- Equivalent to by_type('PhComplexContextSeg')
- Complex segment contexts have multiple segment specifications
"""
return self.by_type("PhComplexContextSeg")
[docs]
def complex_context_nc(self):
"""
Get only the complex natural class contexts.
Convenience method for filtering to PhComplexContextNC objects only.
Returns:
ContextCollection: New collection with only complex natural class contexts.
Example::
ncs = contexts.complex_context_nc()
print(f"Found {len(ncs)} complex natural class contexts")
Notes:
- Equivalent to by_type('PhComplexContextNC')
- Complex natural class contexts have multiple natural class specifications
"""
return self.by_type("PhComplexContextNC")
[docs]
def boundary_contexts(self):
"""
Get only the boundary contexts.
Convenience method for filtering to PhBoundaryContext objects only.
Returns:
ContextCollection: New collection with only boundary context objects.
Example::
boundaries = contexts.boundary_contexts()
for bctx in boundaries:
btype = bctx.boundary_type
print(f"Boundary type: {btype}")
Notes:
- Boundary contexts represent word/morpheme boundaries
- Equivalent to by_type('PhBoundaryContext')
"""
return self.by_type("PhBoundaryContext")
def __repr__(self):
"""Technical representation."""
return f"ContextCollection({len(self._items)} contexts)"