Module bases.alphabet.string_alphabet
Alphabets explicitly specified by strings.
Expand source code
"""
Alphabets explicitly specified by strings.
"""
from types import MappingProxyType
from typing import Any, Mapping, overload, Union
from .abstract import Alphabet
class StringAlphabet(Alphabet):
"""
Class for alphabets explicitly specified by a string of (unique) characters
and optional case sensitivity (default: case-sensitive).
Example usage:
```py
>>> from bases.alphabet import StringAlphabet
>>> StringAlphabet("0123456789abcdef", case_sensitive=False)
StringAlphabet('0123456789abcdef', case_sensitive=False)
>>> StringAlphabet("0123").case_sensitive
True
```
"""
_chars: str
_revdir: Mapping[str, int]
_case_sensitive: bool
def __init__(self, chars: str, *,
case_sensitive: bool = True):
super().__init__(case_sensitive)
self._chars = chars
revdir = {
c: idx for idx, c in enumerate(chars)
}
if not case_sensitive:
revdir.update({
c.upper(): idx for idx, c in enumerate(chars)
})
revdir.update({
c.lower(): idx for idx, c in enumerate(chars)
})
self._revdir = MappingProxyType(revdir)
self.__validate_init()
def __validate_init(self) -> None:
chars = self._chars
case_sensitive = self.case_sensitive
if len(chars) <= 1:
raise ValueError("Alphabet must have at least two characters.")
if len(chars) != len(set(chars)):
raise ValueError("Alphabet cannot contain repeated characters.")
if not case_sensitive:
chars_set_upper = {c.upper() for c in chars}
chars_set_lower = {c.lower() for c in chars}
if len(chars_set_upper) != len(chars) or len(chars_set_lower) != len(chars):
raise ValueError("Alphabet contains lowercase and uppercase versions of the same character, "
"encoding must be case-sensitive.")
@property
def chars(self) -> str:
"""
The characters that define this alphabet.
Example usage:
```py
>>> alphabet.base16.chars
'0123456789ABCDEF'
```
"""
return self._chars
@property
def revdir(self) -> Mapping[str, int]:
return self._revdir
def __len__(self) -> int:
return len(self._chars)
@overload
def __getitem__(self, idx: int) -> str:
...
@overload
def __getitem__(self, idx: slice) -> "StringAlphabet":
...
def __getitem__(self, idx: Union[int, slice]) -> Union[str, "StringAlphabet"]:
if isinstance(idx, slice):
new_chars = self._chars[idx]
return StringAlphabet(new_chars, case_sensitive=self.case_sensitive)
return self._chars[idx]
def with_case_sensitivity(self, case_sensitive: bool) -> "StringAlphabet":
if case_sensitive == self.case_sensitive:
return self
return StringAlphabet(self.chars, case_sensitive=case_sensitive)
def upper(self) -> "StringAlphabet":
chars = self.chars.upper()
if chars == self.chars:
return self
return StringAlphabet(chars, case_sensitive=self.case_sensitive)
def lower(self) -> "StringAlphabet":
chars = self.chars.lower()
if chars == self.chars:
return self
return StringAlphabet(chars, case_sensitive=self.case_sensitive)
def __eq__(self, other: Any) -> bool:
if not isinstance(other, StringAlphabet):
return NotImplemented
return self.chars == other.chars and self.case_sensitive == other.case_sensitive
def __hash__(self) -> int:
return hash((type(self), self.chars, self.case_sensitive))
def __repr__(self) -> str:
chars_str = repr(self.chars)
if self.case_sensitive:
return f"StringAlphabet({chars_str})"
case_sensitive_str = f"case_sensitive={self.case_sensitive}"
return f"StringAlphabet({chars_str}, {case_sensitive_str})"
Classes
class StringAlphabet (chars: str, *, case_sensitive: bool = True)
-
Class for alphabets explicitly specified by a string of (unique) characters and optional case sensitivity (default: case-sensitive).
Example usage:
>>> from bases.alphabet import StringAlphabet >>> StringAlphabet("0123456789abcdef", case_sensitive=False) StringAlphabet('0123456789abcdef', case_sensitive=False) >>> StringAlphabet("0123").case_sensitive True
Expand source code
class StringAlphabet(Alphabet): """ Class for alphabets explicitly specified by a string of (unique) characters and optional case sensitivity (default: case-sensitive). Example usage: ```py >>> from bases.alphabet import StringAlphabet >>> StringAlphabet("0123456789abcdef", case_sensitive=False) StringAlphabet('0123456789abcdef', case_sensitive=False) >>> StringAlphabet("0123").case_sensitive True ``` """ _chars: str _revdir: Mapping[str, int] _case_sensitive: bool def __init__(self, chars: str, *, case_sensitive: bool = True): super().__init__(case_sensitive) self._chars = chars revdir = { c: idx for idx, c in enumerate(chars) } if not case_sensitive: revdir.update({ c.upper(): idx for idx, c in enumerate(chars) }) revdir.update({ c.lower(): idx for idx, c in enumerate(chars) }) self._revdir = MappingProxyType(revdir) self.__validate_init() def __validate_init(self) -> None: chars = self._chars case_sensitive = self.case_sensitive if len(chars) <= 1: raise ValueError("Alphabet must have at least two characters.") if len(chars) != len(set(chars)): raise ValueError("Alphabet cannot contain repeated characters.") if not case_sensitive: chars_set_upper = {c.upper() for c in chars} chars_set_lower = {c.lower() for c in chars} if len(chars_set_upper) != len(chars) or len(chars_set_lower) != len(chars): raise ValueError("Alphabet contains lowercase and uppercase versions of the same character, " "encoding must be case-sensitive.") @property def chars(self) -> str: """ The characters that define this alphabet. Example usage: ```py >>> alphabet.base16.chars '0123456789ABCDEF' ``` """ return self._chars @property def revdir(self) -> Mapping[str, int]: return self._revdir def __len__(self) -> int: return len(self._chars) @overload def __getitem__(self, idx: int) -> str: ... @overload def __getitem__(self, idx: slice) -> "StringAlphabet": ... def __getitem__(self, idx: Union[int, slice]) -> Union[str, "StringAlphabet"]: if isinstance(idx, slice): new_chars = self._chars[idx] return StringAlphabet(new_chars, case_sensitive=self.case_sensitive) return self._chars[idx] def with_case_sensitivity(self, case_sensitive: bool) -> "StringAlphabet": if case_sensitive == self.case_sensitive: return self return StringAlphabet(self.chars, case_sensitive=case_sensitive) def upper(self) -> "StringAlphabet": chars = self.chars.upper() if chars == self.chars: return self return StringAlphabet(chars, case_sensitive=self.case_sensitive) def lower(self) -> "StringAlphabet": chars = self.chars.lower() if chars == self.chars: return self return StringAlphabet(chars, case_sensitive=self.case_sensitive) def __eq__(self, other: Any) -> bool: if not isinstance(other, StringAlphabet): return NotImplemented return self.chars == other.chars and self.case_sensitive == other.case_sensitive def __hash__(self) -> int: return hash((type(self), self.chars, self.case_sensitive)) def __repr__(self) -> str: chars_str = repr(self.chars) if self.case_sensitive: return f"StringAlphabet({chars_str})" case_sensitive_str = f"case_sensitive={self.case_sensitive}" return f"StringAlphabet({chars_str}, {case_sensitive_str})"
Ancestors
- Alphabet
- abc.ABC
- collections.abc.Sequence
- collections.abc.Reversible
- collections.abc.Collection
- collections.abc.Sized
- collections.abc.Iterable
- collections.abc.Container
- typing.Generic
Instance variables
var chars : str
-
The characters that define this alphabet.
Example usage:
>>> alphabet.base16.chars '0123456789ABCDEF'
Expand source code
@property def chars(self) -> str: """ The characters that define this alphabet. Example usage: ```py >>> alphabet.base16.chars '0123456789ABCDEF' ``` """ return self._chars
Inherited members