Source code for flexicon.code.Grammar.prohibition_collection
#
# prohibition_collection.py
#
# Class: ProhibitionCollection
# Smart collection for ad hoc prohibition objects with type-aware
# filtering and unified access across multiple concrete types.
#
# Platform: Python.NET
# FieldWorks Version 9+
#
# Copyright 2025
#
"""
Smart collection class for ad hoc morphosyntactic prohibitions.
This module provides ProhibitionCollection, a smart collection that manages
ad hoc prohibitions while showing type diversity and supporting unified
operations across the three concrete types:
- MoAdhocProhibGr (Grammatical feature prohibitions)
- MoAdhocProhibMorph (Morpheme co-occurrence prohibitions)
- MoAdhocProhibAllomorph (Allomorph co-occurrence prohibitions)
Problem:
GetAllAdhocCoProhibitions() 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:
ProhibitionCollection provides:
- __str__() showing type breakdown
- by_type() filtering to specific concrete types
- filter() for filtering by prohibition type
- grammatical_prohibitions(), morpheme_prohibitions(),
allomorph_prohibitions() convenience filters
- where() for custom filtering
- Chainable filtering: prohibitions.morpheme_prohibitions()
Example::
from flexlibs2.code.Grammar.prohibition_collection import ProhibitionCollection
# GetAllAdhocCoProhibitions() now returns ProhibitionCollection
prohibitions = morphRuleOps.GetAllAdhocCoProhibitions()
print(prohibitions) # Shows type breakdown
# ProhibitionCollection (12 total)
# MoAdhocProhibGr: 5 (42%)
# MoAdhocProhibMorph: 4 (33%)
# MoAdhocProhibAllomorph: 3 (25%)
# Filter by type
morph_only = prohibitions.morpheme_prohibitions()
print(len(morph_only)) # 4
# Filter by custom predicate
named_prohibitions = prohibitions.where(lambda p: p.guid is not None)
# Chain filters
morph_with_guid = prohibitions.morpheme_prohibitions().where(
lambda p: p.guid is not None
)
# Iterate
for prohib in prohibitions:
print(prohib.prohibition_type)
"""
from ..Shared.smart_collection import SmartCollection
from .adhoc_prohibition import AdhocProhibition
[docs]
class ProhibitionCollection(SmartCollection):
"""
Smart collection for ad hoc prohibitions with type-aware filtering.
Manages collections of AdhocProhibition wrapper objects with type-aware
display and filtering capabilities. Supports filtering by prohibition
type and custom predicates.
Attributes:
_items: List of AdhocProhibition wrapper objects
Example::
prohibitions = morphRuleOps.GetAllAdhocCoProhibitions()
print(prohibitions) # Shows type breakdown
morph = prohibitions.morpheme_prohibitions() # Type filter
custom = prohibitions.where(lambda p: p.is_morpheme_prohibition)
"""
def __init__(self, items=None):
"""
Initialize a ProhibitionCollection.
Args:
items: Iterable of AdhocProhibition objects, or None for empty.
Example::
collection = ProhibitionCollection()
collection = ProhibitionCollection([prohib1, prohib2, prohib3])
"""
super().__init__(items)
[docs]
def filter(self, prohibition_type=None, where=None):
"""
Filter the collection by prohibition type.
Supports filtering by prohibition type (grammatical, morpheme,
allomorph). For complex filtering, use where().
Args:
prohibition_type (str, optional): Filter by type. Accepts:
- "Grammatical" or "grammatical"
- "Morpheme" or "morpheme"
- "Allomorph" or "allomorph"
- "Gr" (abbreviation for Grammatical)
- "Morph" (abbreviation for Morpheme)
- "Allo" (abbreviation for Allomorph)
where (callable, optional): Custom predicate function. If provided,
prohibition_type is ignored.
Returns:
ProhibitionCollection: New collection with filtered items.
Example::
# Filter by type name
morph_prohibitions = prohibitions.filter(prohibition_type="Morpheme")
# Filter by abbreviation
gr_prohibitions = prohibitions.filter(prohibition_type="Gr")
# Custom filtering
has_guid = prohibitions.where(lambda p: p.guid is not None)
# Chain filters
morph_with_guid = prohibitions.filter(
prohibition_type="Morpheme"
).where(lambda p: p.guid is not None)
Notes:
- prohibition_type is case-insensitive
- Abbreviations: "Gr", "Morph", "Allo"
- where() takes precedence over prohibition_type
- 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 ProhibitionCollection(filtered)
# Apply prohibition_type filter
if prohibition_type is not None:
# Normalize prohibition_type for comparison
prohib_type_lower = prohibition_type.lower()
filtered = []
for prohib in self._items:
prohib_type_norm = prohib.prohibition_type.lower()
# Check against full name
if prohib_type_norm == prohib_type_lower:
filtered.append(prohib)
# Check against abbreviations
elif prohib_type_lower == "gr" and prohib_type_norm == "grammatical":
filtered.append(prohib)
elif prohib_type_lower == "morph" and prohib_type_norm == "morpheme":
filtered.append(prohib)
elif prohib_type_lower == "allo" and prohib_type_norm == "allomorph":
filtered.append(prohib)
return ProhibitionCollection(filtered)
# No filter applied, return copy of all items
return ProhibitionCollection(self._items)
[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 an AdhocProhibition
and returns True to include it in the result.
Returns:
ProhibitionCollection: New collection with items matching the
predicate.
Example::
# Prohibitions with non-empty GUID
has_guid = prohibitions.where(lambda p: p.guid is not None)
# Combining conditions
morph_with_guid = prohibitions.where(
lambda p: p.is_morpheme_prohibition and p.guid is not None
)
# Type checking combined with other criteria
non_grammatical = prohibitions.where(
lambda p: p.class_type != "MoAdhocProhibGr"
)
Notes:
- Predicate receives each AdhocProhibition object
- Return True to include in result, False to exclude
- For simple filters (type), use filter() instead
"""
filtered = [prohib for prohib in self._items if predicate(prohib)]
return ProhibitionCollection(filtered)
[docs]
def grammatical_prohibitions(self):
"""
Get only the grammatical feature prohibitions from the collection.
Convenience method for filtering to MoAdhocProhibGr objects only.
Returns:
ProhibitionCollection: New collection with only MoAdhocProhibGr
objects.
Example::
grammatical = prohibitions.grammatical_prohibitions()
print(f"Found {len(grammatical)} grammatical prohibitions")
# Chain with other filters
with_guid = prohibitions.grammatical_prohibitions().where(
lambda p: p.guid is not None
)
Notes:
- Equivalent to filter(prohibition_type="Grammatical")
- Use is_grammatical_prohibition on individual items to check type
"""
return self.filter(prohibition_type="Grammatical")
[docs]
def morpheme_prohibitions(self):
"""
Get only the morpheme co-occurrence prohibitions from the collection.
Convenience method for filtering to MoAdhocProhibMorph objects only.
Returns:
ProhibitionCollection: New collection with only MoAdhocProhibMorph
objects.
Example::
morpheme = prohibitions.morpheme_prohibitions()
print(f"Found {len(morpheme)} morpheme prohibitions")
# Chain with other filters
morph_subset = prohibitions.morpheme_prohibitions().where(
lambda p: p.MorphemeRA is not None
)
Notes:
- Equivalent to filter(prohibition_type="Morpheme")
- Use is_morpheme_prohibition on individual items to check type
"""
return self.filter(prohibition_type="Morpheme")
[docs]
def allomorph_prohibitions(self):
"""
Get only the allomorph variant prohibitions from the collection.
Convenience method for filtering to MoAdhocProhibAllomorph objects
only.
Returns:
ProhibitionCollection: New collection with only
MoAdhocProhibAllomorph objects.
Example::
allomorph = prohibitions.allomorph_prohibitions()
print(f"Found {len(allomorph)} allomorph prohibitions")
# Chain with other filters
allo_subset = prohibitions.allomorph_prohibitions().where(
lambda p: p.AllomorphRA is not None
)
Notes:
- Equivalent to filter(prohibition_type="Allomorph")
- Use is_allomorph_prohibition on individual items to check type
"""
return self.filter(prohibition_type="Allomorph")
def __repr__(self):
"""Technical representation."""
return f"ProhibitionCollection({len(self._items)} items)"