classes.c32_pool

  1import random
  2import unicodedata
  3import colorama
  4import regex
  5from inspect import cleandoc
  6from typing import Literal
  7from loguru import logger
  8from icecream import ic
  9
 10from lib import files, helpers, content
 11
 12DEBUG = False
 13
 14
 15class KPool:
 16    """
 17    A pool of items with optional shuffling and case transformation utilities.
 18    """
 19
 20    def __init__(
 21        self, items: list[str], shuffle=True, defaultCase: content.TextCase = None
 22    ) -> None:
 23        """
 24        Initialize the KPool instance.
 25
 26        Args:
 27            items: List of items to pool.
 28            shuffle: Randomize items on initialization. Defaults to True.
 29            defaultCase: Default `content.TextCase` for items. If None, no case change is applied.
 30        """
 31        if shuffle:
 32            random.shuffle(items)
 33
 34        self._shuffle: bool = shuffle
 35
 36        self._items = items
 37        """Internal copy of items without case change"""
 38
 39        self.items = content.changeCase(items, defaultCase)
 40        """Items with case possibly changed (upon initialization)"""
 41
 42    @staticmethod
 43    def fromFile(
 44        filePath: str = "/usr/share/dict/words",
 45        shuffle=True,
 46        defaultCase: content.TextCase = "title",
 47    ) -> "KPool":
 48        """
 49        Create a KPool instance from a text file, where each line is an item.
 50
 51        Args:
 52            filePath: Path to the text file. Defaults to a common dictionary file.
 53            shuffle: Randomize items on initialization. Defaults to True.
 54            defaultCase: Default `content.TextCase` for items. If None, no case change is applied.
 55
 56        Returns:
 57            KPool instance with items from the file.
 58        """
 59        from classes import KTextCleaner
 60
 61        items = files.readFileLines(filePath)
 62        # ? Sanitize items to remove inappropriate content
 63        items = KTextCleaner().sanitizeForbidden(items)
 64        return KPool(items, shuffle=shuffle, defaultCase=defaultCase)
 65
 66    def __str__(self) -> str:
 67        """Returns a human-readable string representation of the KPool."""
 68        return cleandoc(
 69            f"""
 70            {colorama.Fore.BLACK}{colorama.Back.LIGHTCYAN_EX}KPool{colorama.Style.RESET_ALL} {helpers.previewList(self.items)}
 71            """
 72        )
 73
 74    def __len__(self) -> int:
 75        """Returns the number of items in the pool."""
 76        return len(self.items)
 77
 78    def __getitem__(self, index):
 79        """
 80        Make subscriptable. Allows access to items using square brackets.
 81
 82        Args:
 83            index: Index of the item.
 84
 85        Returns:
 86            Item at the given index.
 87        """
 88        return self.items[index]
 89
 90    def getRandomItem(self, alterCase: content.TextCase = None) -> str:
 91        """
 92        Get a random item from the pool, with optional case alteration.
 93
 94        Args:
 95            alterCase: Change text case for a single item.
 96
 97        Returns:
 98            Random item from the pool, possibly with altered case.
 99        """
100        if not self.items:
101            return "Blank"
102
103        item = random.choice(self.items)
104        if isinstance(alterCase, str):
105            item = content.changeCase(item, alterCase)
106
107        self._removeItem(item)
108        return item
109
110    def getItemByWidth(
111        self,
112        width: int,
113        alterCase: content.TextCase = None,
114        avoidShape: content.WordShape = None,
115        threshold: float = 0.995,
116    ) -> str:
117        """
118        Get an item matching the specified width, with optional case and shape filtering.
119
120        Args:
121            width: Target width for the item.
122            alterCase: Change text case for a single phrase.
123            avoidShape: Exclude items with this shape.
124            threshold: Matching threshold for the width.
125        Returns:
126            Item matching the criteria, or `Blank` if none found.
127        """
128        if isinstance(alterCase, str):
129            items = content.changeCase(self.items, alterCase)
130        else:
131            items = self.items
132
133        if avoidShape:
134            items = content.filterByShape(items, avoidShape)
135
136        if not items:
137            return "Blank"
138
139        if self._shuffle:
140            random.shuffle(items)  # Shuffle on each run
141
142        match = content.getStringForWidth(items, width, threshold)
143
144        self._removeItem(match)
145        return match
146
147    def getItemForDimensions(
148        self,
149        dimensions: tuple[float, float],
150        threshold: float = 0.85,
151        optimalLastLineRatio: float = 1,
152    ):
153        """Get an item matching the specified dimensions, with optional threshold and last line ratio. See `lib.content.getStringForDimensions` for details."""
154        match = content.getStringForDimensions(
155            self.items,
156            dimensions,
157            threshold=threshold,
158            optimalLastLineRatio=optimalLastLineRatio,
159        )
160        self._removeItem(match)
161        return match
162
163    def setCase(self, case: content.TextCase):
164        """
165        Change the text case of all items at the instance level.
166
167        Args:
168            case: Desired text case.
169
170        Returns:
171            The modified KPool instance.
172        """
173        self.items = content.changeCase(self.items, case)
174        return self
175
176    def filterPrefix(self, pattern: str | list[str], mode: helpers.Strategy = "pick"):
177        """
178        Return a filtered instance with items (not) starting with the given pattern(s).
179
180        Args:
181            pattern: Single string or multiple patterns.
182            mode: Which filtering strategy to use:
183                - `pick`: include items of pattern only
184                - `omit`: remove pattern from items
185
186        Returns:
187            Filtered KPool instance.
188        """
189
190        def _process(string: str):
191            def _isMatch(item: str) -> bool:
192                found = item.startswith(string)
193                return found if mode == "pick" else not found
194
195            return [
196                item for item in self.items if _isMatch(item)
197            ]  # Process items to preserve textCase
198
199        intersected = helpers.intersect(
200            [_process(p) for p in helpers.coerceList(pattern)]
201        )
202        return KPool(
203            intersected,
204            shuffle=self._shuffle,
205        )
206
207    def filterTokens(self, tokens: list[content.CharacterToken] = ["word", "nonword"]):
208        """
209        Return a filtered instance with items of certain Unicode tokens. See `lib.content.filterByTokens`.
210
211        Args:
212            tokens: Tokens to filter by.
213
214        Returns:
215            Filtered KPool instance.
216        """
217        return KPool(
218            content.filterByTokens(self.items, tokens), shuffle=self._shuffle
219        )  # Process items to preserve textCase
220
221    def filterWithRegex(self, pattern: str):
222        """
223        Return a filtered KPool instance with items matching the given regex pattern.
224
225        Examples:
226            - `[^bdfhkl]+` => filter ascenders
227            - `[^Qgjpqy]+` => filter descenders
228
229        Args:
230            pattern: Regex pattern to match.
231
232        Returns:
233            Filtered KPool instance.
234        """
235        return KPool(
236            list(filter(lambda item: regex.search(f"^{pattern}$", item), self.items)),
237            shuffle=self._shuffle,
238        )  # Process items to preserve textCase
239
240    def shuffle(self) -> "KPool":
241        """Shuffle the items in place and return self."""
242        random.shuffle(self.items)
243        return self
244
245    def stripChars(self, chars: str = ".,:;-+−'’") -> None:
246        """
247        Remove specified characters from all items.
248
249        Args:
250            chars: Characters to strip. Defaults to commonly used symbols and punctuation.
251        """
252        self.items = [item.strip(chars) for item in self.items]
253
254    def prioritize(self, mode: Literal["accented"] = "accented") -> "KPool":
255        """Reorder items in place by priority mode.
256
257        Current modes:
258            - accented: items containing accented/diacritic characters come first.
259        """
260        if mode != "accented":
261            raise ValueError(f"Unsupported prioritize mode: {mode}")
262
263        def _hasAccents(item: str) -> bool:
264            normalized = unicodedata.normalize("NFD", item)
265            return any(unicodedata.combining(char) for char in normalized)
266
267        # Stable sort keeps relative order within each priority group.
268        self.items.sort(key=lambda item: not _hasAccents(item))
269        return self
270
271    def _removeItem(self, match: str):
272        """
273        Remove an item by value (case-insensitive).
274
275        Args:
276            match: Item to remove.
277
278        Returns:
279            The modified KPool instance.
280        """
281        poolLen = f"{len(self.items)}\t"
282        try:
283            if DEBUG:
284                logger.debug("[{} About to remove]\t{}", poolLen, match)
285            matchInsensitive = match.casefold()
286            itemsInsensitive = [item.casefold() for item in self.items]
287            index = itemsInsensitive.index(matchInsensitive)
288            value = self.items[index]
289            if DEBUG:
290                logger.debug("[{} Removing]\t{}", poolLen, value)
291            self.items.pop(index)
292        except ValueError as e:
293            logger.warning("[{} Error removing item]\t{}: {}", poolLen, match, e)
294        return self
DEBUG = False
class KPool:
 16class KPool:
 17    """
 18    A pool of items with optional shuffling and case transformation utilities.
 19    """
 20
 21    def __init__(
 22        self, items: list[str], shuffle=True, defaultCase: content.TextCase = None
 23    ) -> None:
 24        """
 25        Initialize the KPool instance.
 26
 27        Args:
 28            items: List of items to pool.
 29            shuffle: Randomize items on initialization. Defaults to True.
 30            defaultCase: Default `content.TextCase` for items. If None, no case change is applied.
 31        """
 32        if shuffle:
 33            random.shuffle(items)
 34
 35        self._shuffle: bool = shuffle
 36
 37        self._items = items
 38        """Internal copy of items without case change"""
 39
 40        self.items = content.changeCase(items, defaultCase)
 41        """Items with case possibly changed (upon initialization)"""
 42
 43    @staticmethod
 44    def fromFile(
 45        filePath: str = "/usr/share/dict/words",
 46        shuffle=True,
 47        defaultCase: content.TextCase = "title",
 48    ) -> "KPool":
 49        """
 50        Create a KPool instance from a text file, where each line is an item.
 51
 52        Args:
 53            filePath: Path to the text file. Defaults to a common dictionary file.
 54            shuffle: Randomize items on initialization. Defaults to True.
 55            defaultCase: Default `content.TextCase` for items. If None, no case change is applied.
 56
 57        Returns:
 58            KPool instance with items from the file.
 59        """
 60        from classes import KTextCleaner
 61
 62        items = files.readFileLines(filePath)
 63        # ? Sanitize items to remove inappropriate content
 64        items = KTextCleaner().sanitizeForbidden(items)
 65        return KPool(items, shuffle=shuffle, defaultCase=defaultCase)
 66
 67    def __str__(self) -> str:
 68        """Returns a human-readable string representation of the KPool."""
 69        return cleandoc(
 70            f"""
 71            {colorama.Fore.BLACK}{colorama.Back.LIGHTCYAN_EX}KPool{colorama.Style.RESET_ALL} {helpers.previewList(self.items)}
 72            """
 73        )
 74
 75    def __len__(self) -> int:
 76        """Returns the number of items in the pool."""
 77        return len(self.items)
 78
 79    def __getitem__(self, index):
 80        """
 81        Make subscriptable. Allows access to items using square brackets.
 82
 83        Args:
 84            index: Index of the item.
 85
 86        Returns:
 87            Item at the given index.
 88        """
 89        return self.items[index]
 90
 91    def getRandomItem(self, alterCase: content.TextCase = None) -> str:
 92        """
 93        Get a random item from the pool, with optional case alteration.
 94
 95        Args:
 96            alterCase: Change text case for a single item.
 97
 98        Returns:
 99            Random item from the pool, possibly with altered case.
100        """
101        if not self.items:
102            return "Blank"
103
104        item = random.choice(self.items)
105        if isinstance(alterCase, str):
106            item = content.changeCase(item, alterCase)
107
108        self._removeItem(item)
109        return item
110
111    def getItemByWidth(
112        self,
113        width: int,
114        alterCase: content.TextCase = None,
115        avoidShape: content.WordShape = None,
116        threshold: float = 0.995,
117    ) -> str:
118        """
119        Get an item matching the specified width, with optional case and shape filtering.
120
121        Args:
122            width: Target width for the item.
123            alterCase: Change text case for a single phrase.
124            avoidShape: Exclude items with this shape.
125            threshold: Matching threshold for the width.
126        Returns:
127            Item matching the criteria, or `Blank` if none found.
128        """
129        if isinstance(alterCase, str):
130            items = content.changeCase(self.items, alterCase)
131        else:
132            items = self.items
133
134        if avoidShape:
135            items = content.filterByShape(items, avoidShape)
136
137        if not items:
138            return "Blank"
139
140        if self._shuffle:
141            random.shuffle(items)  # Shuffle on each run
142
143        match = content.getStringForWidth(items, width, threshold)
144
145        self._removeItem(match)
146        return match
147
148    def getItemForDimensions(
149        self,
150        dimensions: tuple[float, float],
151        threshold: float = 0.85,
152        optimalLastLineRatio: float = 1,
153    ):
154        """Get an item matching the specified dimensions, with optional threshold and last line ratio. See `lib.content.getStringForDimensions` for details."""
155        match = content.getStringForDimensions(
156            self.items,
157            dimensions,
158            threshold=threshold,
159            optimalLastLineRatio=optimalLastLineRatio,
160        )
161        self._removeItem(match)
162        return match
163
164    def setCase(self, case: content.TextCase):
165        """
166        Change the text case of all items at the instance level.
167
168        Args:
169            case: Desired text case.
170
171        Returns:
172            The modified KPool instance.
173        """
174        self.items = content.changeCase(self.items, case)
175        return self
176
177    def filterPrefix(self, pattern: str | list[str], mode: helpers.Strategy = "pick"):
178        """
179        Return a filtered instance with items (not) starting with the given pattern(s).
180
181        Args:
182            pattern: Single string or multiple patterns.
183            mode: Which filtering strategy to use:
184                - `pick`: include items of pattern only
185                - `omit`: remove pattern from items
186
187        Returns:
188            Filtered KPool instance.
189        """
190
191        def _process(string: str):
192            def _isMatch(item: str) -> bool:
193                found = item.startswith(string)
194                return found if mode == "pick" else not found
195
196            return [
197                item for item in self.items if _isMatch(item)
198            ]  # Process items to preserve textCase
199
200        intersected = helpers.intersect(
201            [_process(p) for p in helpers.coerceList(pattern)]
202        )
203        return KPool(
204            intersected,
205            shuffle=self._shuffle,
206        )
207
208    def filterTokens(self, tokens: list[content.CharacterToken] = ["word", "nonword"]):
209        """
210        Return a filtered instance with items of certain Unicode tokens. See `lib.content.filterByTokens`.
211
212        Args:
213            tokens: Tokens to filter by.
214
215        Returns:
216            Filtered KPool instance.
217        """
218        return KPool(
219            content.filterByTokens(self.items, tokens), shuffle=self._shuffle
220        )  # Process items to preserve textCase
221
222    def filterWithRegex(self, pattern: str):
223        """
224        Return a filtered KPool instance with items matching the given regex pattern.
225
226        Examples:
227            - `[^bdfhkl]+` => filter ascenders
228            - `[^Qgjpqy]+` => filter descenders
229
230        Args:
231            pattern: Regex pattern to match.
232
233        Returns:
234            Filtered KPool instance.
235        """
236        return KPool(
237            list(filter(lambda item: regex.search(f"^{pattern}$", item), self.items)),
238            shuffle=self._shuffle,
239        )  # Process items to preserve textCase
240
241    def shuffle(self) -> "KPool":
242        """Shuffle the items in place and return self."""
243        random.shuffle(self.items)
244        return self
245
246    def stripChars(self, chars: str = ".,:;-+−'’") -> None:
247        """
248        Remove specified characters from all items.
249
250        Args:
251            chars: Characters to strip. Defaults to commonly used symbols and punctuation.
252        """
253        self.items = [item.strip(chars) for item in self.items]
254
255    def prioritize(self, mode: Literal["accented"] = "accented") -> "KPool":
256        """Reorder items in place by priority mode.
257
258        Current modes:
259            - accented: items containing accented/diacritic characters come first.
260        """
261        if mode != "accented":
262            raise ValueError(f"Unsupported prioritize mode: {mode}")
263
264        def _hasAccents(item: str) -> bool:
265            normalized = unicodedata.normalize("NFD", item)
266            return any(unicodedata.combining(char) for char in normalized)
267
268        # Stable sort keeps relative order within each priority group.
269        self.items.sort(key=lambda item: not _hasAccents(item))
270        return self
271
272    def _removeItem(self, match: str):
273        """
274        Remove an item by value (case-insensitive).
275
276        Args:
277            match: Item to remove.
278
279        Returns:
280            The modified KPool instance.
281        """
282        poolLen = f"{len(self.items)}\t"
283        try:
284            if DEBUG:
285                logger.debug("[{} About to remove]\t{}", poolLen, match)
286            matchInsensitive = match.casefold()
287            itemsInsensitive = [item.casefold() for item in self.items]
288            index = itemsInsensitive.index(matchInsensitive)
289            value = self.items[index]
290            if DEBUG:
291                logger.debug("[{} Removing]\t{}", poolLen, value)
292            self.items.pop(index)
293        except ValueError as e:
294            logger.warning("[{} Error removing item]\t{}: {}", poolLen, match, e)
295        return self

A pool of items with optional shuffling and case transformation utilities.

KPool( items: list[str], shuffle=True, defaultCase: Literal['UPPER', 'lower', 'title', 'title-force'] = None)
21    def __init__(
22        self, items: list[str], shuffle=True, defaultCase: content.TextCase = None
23    ) -> None:
24        """
25        Initialize the KPool instance.
26
27        Args:
28            items: List of items to pool.
29            shuffle: Randomize items on initialization. Defaults to True.
30            defaultCase: Default `content.TextCase` for items. If None, no case change is applied.
31        """
32        if shuffle:
33            random.shuffle(items)
34
35        self._shuffle: bool = shuffle
36
37        self._items = items
38        """Internal copy of items without case change"""
39
40        self.items = content.changeCase(items, defaultCase)
41        """Items with case possibly changed (upon initialization)"""

Initialize the KPool instance.

Arguments:
  • items: List of items to pool.
  • shuffle: Randomize items on initialization. Defaults to True.
  • defaultCase: Default content.TextCase for items. If None, no case change is applied.
items

Items with case possibly changed (upon initialization)

@staticmethod
def fromFile( filePath: str = '/usr/share/dict/words', shuffle=True, defaultCase: Literal['UPPER', 'lower', 'title', 'title-force'] = 'title') -> KPool:
43    @staticmethod
44    def fromFile(
45        filePath: str = "/usr/share/dict/words",
46        shuffle=True,
47        defaultCase: content.TextCase = "title",
48    ) -> "KPool":
49        """
50        Create a KPool instance from a text file, where each line is an item.
51
52        Args:
53            filePath: Path to the text file. Defaults to a common dictionary file.
54            shuffle: Randomize items on initialization. Defaults to True.
55            defaultCase: Default `content.TextCase` for items. If None, no case change is applied.
56
57        Returns:
58            KPool instance with items from the file.
59        """
60        from classes import KTextCleaner
61
62        items = files.readFileLines(filePath)
63        # ? Sanitize items to remove inappropriate content
64        items = KTextCleaner().sanitizeForbidden(items)
65        return KPool(items, shuffle=shuffle, defaultCase=defaultCase)

Create a KPool instance from a text file, where each line is an item.

Arguments:
  • filePath: Path to the text file. Defaults to a common dictionary file.
  • shuffle: Randomize items on initialization. Defaults to True.
  • defaultCase: Default content.TextCase for items. If None, no case change is applied.
Returns:

KPool instance with items from the file.

def getRandomItem( self, alterCase: Literal['UPPER', 'lower', 'title', 'title-force'] = None) -> str:
 91    def getRandomItem(self, alterCase: content.TextCase = None) -> str:
 92        """
 93        Get a random item from the pool, with optional case alteration.
 94
 95        Args:
 96            alterCase: Change text case for a single item.
 97
 98        Returns:
 99            Random item from the pool, possibly with altered case.
100        """
101        if not self.items:
102            return "Blank"
103
104        item = random.choice(self.items)
105        if isinstance(alterCase, str):
106            item = content.changeCase(item, alterCase)
107
108        self._removeItem(item)
109        return item

Get a random item from the pool, with optional case alteration.

Arguments:
  • alterCase: Change text case for a single item.
Returns:

Random item from the pool, possibly with altered case.

def getItemByWidth( self, width: int, alterCase: Literal['UPPER', 'lower', 'title', 'title-force'] = None, avoidShape: Literal['descender', 'ascender', 'caps'] = None, threshold: float = 0.995) -> str:
111    def getItemByWidth(
112        self,
113        width: int,
114        alterCase: content.TextCase = None,
115        avoidShape: content.WordShape = None,
116        threshold: float = 0.995,
117    ) -> str:
118        """
119        Get an item matching the specified width, with optional case and shape filtering.
120
121        Args:
122            width: Target width for the item.
123            alterCase: Change text case for a single phrase.
124            avoidShape: Exclude items with this shape.
125            threshold: Matching threshold for the width.
126        Returns:
127            Item matching the criteria, or `Blank` if none found.
128        """
129        if isinstance(alterCase, str):
130            items = content.changeCase(self.items, alterCase)
131        else:
132            items = self.items
133
134        if avoidShape:
135            items = content.filterByShape(items, avoidShape)
136
137        if not items:
138            return "Blank"
139
140        if self._shuffle:
141            random.shuffle(items)  # Shuffle on each run
142
143        match = content.getStringForWidth(items, width, threshold)
144
145        self._removeItem(match)
146        return match

Get an item matching the specified width, with optional case and shape filtering.

Arguments:
  • width: Target width for the item.
  • alterCase: Change text case for a single phrase.
  • avoidShape: Exclude items with this shape.
  • threshold: Matching threshold for the width.
Returns:

Item matching the criteria, or Blank if none found.

def getItemForDimensions( self, dimensions: tuple[float, float], threshold: float = 0.85, optimalLastLineRatio: float = 1):
148    def getItemForDimensions(
149        self,
150        dimensions: tuple[float, float],
151        threshold: float = 0.85,
152        optimalLastLineRatio: float = 1,
153    ):
154        """Get an item matching the specified dimensions, with optional threshold and last line ratio. See `lib.content.getStringForDimensions` for details."""
155        match = content.getStringForDimensions(
156            self.items,
157            dimensions,
158            threshold=threshold,
159            optimalLastLineRatio=optimalLastLineRatio,
160        )
161        self._removeItem(match)
162        return match

Get an item matching the specified dimensions, with optional threshold and last line ratio. See lib.content.getStringForDimensions for details.

def setCase(self, case: Literal['UPPER', 'lower', 'title', 'title-force']):
164    def setCase(self, case: content.TextCase):
165        """
166        Change the text case of all items at the instance level.
167
168        Args:
169            case: Desired text case.
170
171        Returns:
172            The modified KPool instance.
173        """
174        self.items = content.changeCase(self.items, case)
175        return self

Change the text case of all items at the instance level.

Arguments:
  • case: Desired text case.
Returns:

The modified KPool instance.

def filterPrefix( self, pattern: str | list[str], mode: Literal['pick', 'omit'] = 'pick'):
177    def filterPrefix(self, pattern: str | list[str], mode: helpers.Strategy = "pick"):
178        """
179        Return a filtered instance with items (not) starting with the given pattern(s).
180
181        Args:
182            pattern: Single string or multiple patterns.
183            mode: Which filtering strategy to use:
184                - `pick`: include items of pattern only
185                - `omit`: remove pattern from items
186
187        Returns:
188            Filtered KPool instance.
189        """
190
191        def _process(string: str):
192            def _isMatch(item: str) -> bool:
193                found = item.startswith(string)
194                return found if mode == "pick" else not found
195
196            return [
197                item for item in self.items if _isMatch(item)
198            ]  # Process items to preserve textCase
199
200        intersected = helpers.intersect(
201            [_process(p) for p in helpers.coerceList(pattern)]
202        )
203        return KPool(
204            intersected,
205            shuffle=self._shuffle,
206        )

Return a filtered instance with items (not) starting with the given pattern(s).

Arguments:
  • pattern: Single string or multiple patterns.
  • mode: Which filtering strategy to use:
    • pick: include items of pattern only
    • omit: remove pattern from items
Returns:

Filtered KPool instance.

def filterTokens( self, tokens: list[typing.Literal['word', 'nonword']] = ['word', 'nonword']):
208    def filterTokens(self, tokens: list[content.CharacterToken] = ["word", "nonword"]):
209        """
210        Return a filtered instance with items of certain Unicode tokens. See `lib.content.filterByTokens`.
211
212        Args:
213            tokens: Tokens to filter by.
214
215        Returns:
216            Filtered KPool instance.
217        """
218        return KPool(
219            content.filterByTokens(self.items, tokens), shuffle=self._shuffle
220        )  # Process items to preserve textCase

Return a filtered instance with items of certain Unicode tokens. See lib.content.filterByTokens.

Arguments:
  • tokens: Tokens to filter by.
Returns:

Filtered KPool instance.

def filterWithRegex(self, pattern: str):
222    def filterWithRegex(self, pattern: str):
223        """
224        Return a filtered KPool instance with items matching the given regex pattern.
225
226        Examples:
227            - `[^bdfhkl]+` => filter ascenders
228            - `[^Qgjpqy]+` => filter descenders
229
230        Args:
231            pattern: Regex pattern to match.
232
233        Returns:
234            Filtered KPool instance.
235        """
236        return KPool(
237            list(filter(lambda item: regex.search(f"^{pattern}$", item), self.items)),
238            shuffle=self._shuffle,
239        )  # Process items to preserve textCase

Return a filtered KPool instance with items matching the given regex pattern.

Examples:
  • [^bdfhkl]+ => filter ascenders
  • [^Qgjpqy]+ => filter descenders
Arguments:
  • pattern: Regex pattern to match.
Returns:

Filtered KPool instance.

def shuffle(self) -> KPool:
241    def shuffle(self) -> "KPool":
242        """Shuffle the items in place and return self."""
243        random.shuffle(self.items)
244        return self

Shuffle the items in place and return self.

def stripChars(self, chars: str = ".,:;-+−'’") -> None:
246    def stripChars(self, chars: str = ".,:;-+−'’") -> None:
247        """
248        Remove specified characters from all items.
249
250        Args:
251            chars: Characters to strip. Defaults to commonly used symbols and punctuation.
252        """
253        self.items = [item.strip(chars) for item in self.items]

Remove specified characters from all items.

Arguments:
  • chars: Characters to strip. Defaults to commonly used symbols and punctuation.
def prioritize(self, mode: Literal['accented'] = 'accented') -> KPool:
255    def prioritize(self, mode: Literal["accented"] = "accented") -> "KPool":
256        """Reorder items in place by priority mode.
257
258        Current modes:
259            - accented: items containing accented/diacritic characters come first.
260        """
261        if mode != "accented":
262            raise ValueError(f"Unsupported prioritize mode: {mode}")
263
264        def _hasAccents(item: str) -> bool:
265            normalized = unicodedata.normalize("NFD", item)
266            return any(unicodedata.combining(char) for char in normalized)
267
268        # Stable sort keeps relative order within each priority group.
269        self.items.sort(key=lambda item: not _hasAccents(item))
270        return self

Reorder items in place by priority mode.

Current modes:
  • accented: items containing accented/diacritic characters come first.