Module bases.alphabet
Module containing classes for alphabets.
To access existing alphabets, use the get()
function:
>>> from bases import encoding
>>> alphabet.get("base16")
StringAlphabet('0123456789ABCDEF')
To create new alphabets, use the make()
function:
>>> alphabet.make("0123456789abcdef")
StringAlphabet('0123456789abcdef')
To register new alphabets, use the register()
function:
>>> myalpha = alphabet.make("0123456789abcdef")
>>> alphabet.register(base16lower=myalpha)
Alternatively, use the optional "name"
argument of the make()
function:
>>> alphabet.make("0123456789abcdef", name="base16lower")
StringAlphabet('0123456789abcdef')
>>> alphabet.get("base16lower")
StringAlphabet('0123456789abcdef')
To list alphabets (with optional filtering), use table()
:
>>> dict(alphabet.table(prefix="base32"))
{'base32': StringAlphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567', case_sensitive=False),
'base32hex': StringAlphabet('0123456789ABCDEFGHIJKLMNOPQRSTUV', case_sensitive=False),
'base32z': StringAlphabet('ybndrfg8ejkmcpqxot1uwisza345h769', case_sensitive=False)}
Expand source code
"""
Module containing classes for alphabets.
To access existing alphabets, use the `get` function:
```py
>>> from bases import encoding
>>> alphabet.get("base16")
StringAlphabet('0123456789ABCDEF')
```
To create new alphabets, use the `make` function:
```py
>>> alphabet.make("0123456789abcdef")
StringAlphabet('0123456789abcdef')
```
To register new alphabets, use the `register` function:
```py
>>> myalpha = alphabet.make("0123456789abcdef")
>>> alphabet.register(base16lower=myalpha)
```
Alternatively, use the optional `"name"` argument of the `make` function:
```py
>>> alphabet.make("0123456789abcdef", name="base16lower")
StringAlphabet('0123456789abcdef')
>>> alphabet.get("base16lower")
StringAlphabet('0123456789abcdef')
```
To list alphabets (with optional filtering), use `table`:
```py
>>> dict(alphabet.table(prefix="base32"))
{'base32': StringAlphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567', case_sensitive=False),
'base32hex': StringAlphabet('0123456789ABCDEFGHIJKLMNOPQRSTUV', case_sensitive=False),
'base32z': StringAlphabet('ybndrfg8ejkmcpqxot1uwisza345h769', case_sensitive=False)}
```
"""
import re
from typing import Collection, Dict, Iterator, Optional, overload, Tuple, Union
from typing_extensions import Literal
from typing_validation import validate
from .abstract import Alphabet as Alphabet
from .string_alphabet import StringAlphabet as StringAlphabet
from .range_alphabet import RangeAlphabet as RangeAlphabet
_alphabets: Dict[str, Alphabet] = {}
def get(name: str) -> Alphabet:
"""
Gets an alphabet by name, raising `KeyError` if none exists.
Example usage:
```py
>>> alphabet.get("base16")
StringAlphabet('0123456789ABCDEF')
```
"""
validate(name, str)
if name not in _alphabets:
raise KeyError(f"Alphabet named {repr(name)} does not exist.")
return _alphabets[name]
def has(name: str) -> bool:
"""
Checks whether an alphabet with the given name exists.
Example usage:
```py
>>> from bases import alphabet
>>> alphabet.has("base32")
True
```
"""
validate(name, str)
return name in _alphabets
def register(**kwargs: Alphabet) -> None:
"""
Registers any number of new alphabets by name.
Raises `KeyError` is an alphabet with one of the given name already exists.
Example usage:
```py
>>> from bases import alphabet
>>> alphabet.register(base16lower=alphabet.base16.lower())
>>> alphabet.get("base16lower")
StringAlphabet('0123456789abcdef')
```
Alphabet names must conform with:
```py
re.match(r"^base[0-9][a-zA-Z0-9_]*$", name)
```
"""
for arg in kwargs.values():
validate(arg, Alphabet)
for name, alphabet in kwargs.items():
if not re.match(r"^base[0-9][a-zA-Z0-9_]*$", name):
raise ValueError(f"Invalid alphabet name {repr(name)}")
if not isinstance(alphabet, Alphabet):
raise TypeError()
if name in _alphabets:
raise ValueError(f"Alphabet named {repr(name)} already exists.")
_alphabets[name] = alphabet
def unregister(*names: str) -> None:
"""
Unregisters any number of existing alphabets by name.
Raises `KeyError` is an alphabet with one of the given names doesn't exist.
Example usage:
```py
>>> from bases import alphabet
>>> alphabet.unregister("base16", "base32")
>>> alphabet.has("base16")
False
>>> alphabet.get("base16")
KeyError: "Alphabet named 'base16' does not exist."
```
Note that pre-defined constants are unaffected by this:
```py
>>> alphabet.base16
StringAlphabet('0123456789ABCDEF')
```
"""
for name in names:
validate(name, str)
for name in names:
if name not in _alphabets:
raise KeyError(f"Alphabet named {repr(name)} does not exist.")
del _alphabets[name]
def table(*, prefix: str = "") -> Iterator[Tuple[str, Alphabet]]:
"""
Iterates over all registered alphabets, optionally restricting to those with given prefix.
Example usage:
```py
>>> from bases import alphabet
>>> dict(alphabet.table(prefix="base32"))
{'base32': StringAlphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567', case_sensitive=False),
'base32hex': StringAlphabet('0123456789ABCDEFGHIJKLMNOPQRSTUV', case_sensitive=False),
'base32z': StringAlphabet('ybndrfg8ejkmcpqxot1uwisza345h769', case_sensitive=False)}
```
"""
validate(prefix, str)
alphabets = [(name, alphabet) for name, alphabet in _alphabets.items()
if name.startswith(prefix)]
alphabets = sorted(alphabets, key=lambda pair: pair[0])
return iter(alphabets)
@overload
def make(chars: str, *, case_sensitive: bool = True, name: Optional[str] = None) -> StringAlphabet:
...
@overload
def make(chars: range, *, case_sensitive: bool = True, name: Optional[str] = None) -> RangeAlphabet:
...
def make(chars: Union[str, range], *, case_sensitive: bool = True, name: Optional[str] = None) -> Union[StringAlphabet, RangeAlphabet]:
"""
Utility function to create custom alphabets.
Automatically creates an instance of `bases.alphabet.string_alphabet.StringAlphabet`
or `bases.alphabet.range_alphabet.RangeAlphabet` based on whether a string or range is passed.
Example usage with string (case-insensitive base-16):
```py
>>> alphabet.make("0123456789ABCDEF", case_sensitive=False)
StringAlphabet('0123456789ABCDEF', case_sensitive=False)
```
Example usage with range (extended ASCII):
```py
>>> alphabet.make(range(0x00, 0x100))
RangeAlphabet(range(0x00, 0x100))
```
If the optional keyword argument `name` is specified, the alphabet is automatically registered using `register`.
"""
validate(chars, Union[str, range])
validate(case_sensitive, bool)
validate(name, Optional[str])
if isinstance(chars, str):
string_alphabet = StringAlphabet(chars, case_sensitive=case_sensitive)
if name is not None:
register(**{name: string_alphabet})
return string_alphabet
if isinstance(chars, range):
range_alphabet = RangeAlphabet(chars, case_sensitive=case_sensitive)
if name is not None:
register(**{name: range_alphabet})
return range_alphabet
raise NotImplementedError(f"Character type {type(chars)} not supported.")
base2 = make("01", name="base2")
""" Base-2 alphabet. """
base8 = make("01234567", name="base8")
""" Base-8 alphabet. """
base16 = make("0123456789ABCDEF", case_sensitive=False, name="base16")
""" Uppercase case-insensitive base-16 alphabet. """
base32 = make("ABCDEFGHIJKLMNOPQRSTUVWXYZ234567", case_sensitive=False, name="base32")
""" Uppercase case-insensitive base-32 alphabet from [rfc4648](https://datatracker.ietf.org/doc/html/rfc4648). """
base32hex = make("0123456789ABCDEFGHIJKLMNOPQRSTUV", case_sensitive=False, name="base32hex")
""" Uppercase case-insensitive hex base-32 alphabet from [rfc4648](https://datatracker.ietf.org/doc/html/rfc4648). """
base32z = make("ybndrfg8ejkmcpqxot1uwisza345h769", case_sensitive=False, name="base32z")
"""
Lowercase case-insensitive human-oriented base-32 alphabet from https://philzimmermann.com/docs/human-oriented-base-32-encoding.txt
"""
base64 = make("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", name="base64")
""" Uppercase case-insensitive base-64 alphabet from [rfc4648](https://datatracker.ietf.org/doc/html/rfc4648). """
base64url = make("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_", name="base64url")
""" Uppercase case-insensitive url-safe base-64 alphabet from [rfc4648](https://datatracker.ietf.org/doc/html/rfc4648). """
base10 = make("0123456789", name="base10")
""" Base-10 alphabet. """
base36 = make("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ", case_sensitive=False, name="base36")
""" Uppercase case-insensitive base-36 alphabet. """
base58btc = make("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz", name="base58btc")
""" Case-sensitive base-58 alphabet used by Bitcoin. """
base58flickr = make("123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ", name="base58flickr")
""" Case-sensitive base-58 alphabet used by Flickr. """
base58ripple = make("rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz", name="base58ripple")
""" Case-sensitive base-58 alphabet used by Ripple. """
base45 = make("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:", case_sensitive=False, name="base45")
"""
Uppercase case-insensitive base-45 alphabet from https://datatracker.ietf.org/doc/draft-faltstrom-base45/
"""
Sub-modules
bases.alphabet.abstract
-
Abstract alphabets.
bases.alphabet.range_alphabet
-
Alphabets implicitly specified by Unicode codepoint range.
bases.alphabet.string_alphabet
-
Alphabets explicitly specified by strings.
Global variables
var base10
-
Base-10 alphabet.
var base16
-
Uppercase case-insensitive base-16 alphabet.
var base2
-
Base-2 alphabet.
var base32
-
Uppercase case-insensitive base-32 alphabet from rfc4648.
var base32hex
-
Uppercase case-insensitive hex base-32 alphabet from rfc4648.
var base32z
-
Lowercase case-insensitive human-oriented base-32 alphabet from https://philzimmermann.com/docs/human-oriented-base-32-encoding.txt
var base36
-
Uppercase case-insensitive base-36 alphabet.
var base45
-
Uppercase case-insensitive base-45 alphabet from https://datatracker.ietf.org/doc/draft-faltstrom-base45/
var base58btc
-
Case-sensitive base-58 alphabet used by Bitcoin.
var base58flickr
-
Case-sensitive base-58 alphabet used by Flickr.
var base58ripple
-
Case-sensitive base-58 alphabet used by Ripple.
var base64
-
Uppercase case-insensitive base-64 alphabet from rfc4648.
var base64url
-
Uppercase case-insensitive url-safe base-64 alphabet from rfc4648.
var base8
-
Base-8 alphabet.
Functions
def get(name: str) ‑> Alphabet
-
Gets an alphabet by name, raising
KeyError
if none exists.Example usage:
>>> alphabet.get("base16") StringAlphabet('0123456789ABCDEF')
Expand source code
def get(name: str) -> Alphabet: """ Gets an alphabet by name, raising `KeyError` if none exists. Example usage: ```py >>> alphabet.get("base16") StringAlphabet('0123456789ABCDEF') ``` """ validate(name, str) if name not in _alphabets: raise KeyError(f"Alphabet named {repr(name)} does not exist.") return _alphabets[name]
def has(name: str) ‑> bool
-
Checks whether an alphabet with the given name exists.
Example usage:
>>> from bases import alphabet >>> alphabet.has("base32") True
Expand source code
def has(name: str) -> bool: """ Checks whether an alphabet with the given name exists. Example usage: ```py >>> from bases import alphabet >>> alphabet.has("base32") True ``` """ validate(name, str) return name in _alphabets
def make(chars: Union[str, range], *, case_sensitive: bool = True, name: Optional[str] = None) ‑> Union[StringAlphabet, RangeAlphabet]
-
Utility function to create custom alphabets. Automatically creates an instance of
StringAlphabet
orRangeAlphabet
based on whether a string or range is passed.Example usage with string (case-insensitive base-16):
>>> alphabet.make("0123456789ABCDEF", case_sensitive=False) StringAlphabet('0123456789ABCDEF', case_sensitive=False)
Example usage with range (extended ASCII):
>>> alphabet.make(range(0x00, 0x100)) RangeAlphabet(range(0x00, 0x100))
If the optional keyword argument
name
is specified, the alphabet is automatically registered usingregister()
.Expand source code
def make(chars: Union[str, range], *, case_sensitive: bool = True, name: Optional[str] = None) -> Union[StringAlphabet, RangeAlphabet]: """ Utility function to create custom alphabets. Automatically creates an instance of `bases.alphabet.string_alphabet.StringAlphabet` or `bases.alphabet.range_alphabet.RangeAlphabet` based on whether a string or range is passed. Example usage with string (case-insensitive base-16): ```py >>> alphabet.make("0123456789ABCDEF", case_sensitive=False) StringAlphabet('0123456789ABCDEF', case_sensitive=False) ``` Example usage with range (extended ASCII): ```py >>> alphabet.make(range(0x00, 0x100)) RangeAlphabet(range(0x00, 0x100)) ``` If the optional keyword argument `name` is specified, the alphabet is automatically registered using `register`. """ validate(chars, Union[str, range]) validate(case_sensitive, bool) validate(name, Optional[str]) if isinstance(chars, str): string_alphabet = StringAlphabet(chars, case_sensitive=case_sensitive) if name is not None: register(**{name: string_alphabet}) return string_alphabet if isinstance(chars, range): range_alphabet = RangeAlphabet(chars, case_sensitive=case_sensitive) if name is not None: register(**{name: range_alphabet}) return range_alphabet raise NotImplementedError(f"Character type {type(chars)} not supported.")
def register(**kwargs: Alphabet) ‑> None
-
Registers any number of new alphabets by name. Raises
KeyError
is an alphabet with one of the given name already exists.Example usage:
>>> from bases import alphabet >>> alphabet.register(base16lower=alphabet.base16.lower()) >>> alphabet.get("base16lower") StringAlphabet('0123456789abcdef')
Alphabet names must conform with:
re.match(r"^base[0-9][a-zA-Z0-9_]*$", name)
Expand source code
def register(**kwargs: Alphabet) -> None: """ Registers any number of new alphabets by name. Raises `KeyError` is an alphabet with one of the given name already exists. Example usage: ```py >>> from bases import alphabet >>> alphabet.register(base16lower=alphabet.base16.lower()) >>> alphabet.get("base16lower") StringAlphabet('0123456789abcdef') ``` Alphabet names must conform with: ```py re.match(r"^base[0-9][a-zA-Z0-9_]*$", name) ``` """ for arg in kwargs.values(): validate(arg, Alphabet) for name, alphabet in kwargs.items(): if not re.match(r"^base[0-9][a-zA-Z0-9_]*$", name): raise ValueError(f"Invalid alphabet name {repr(name)}") if not isinstance(alphabet, Alphabet): raise TypeError() if name in _alphabets: raise ValueError(f"Alphabet named {repr(name)} already exists.") _alphabets[name] = alphabet
def table(*, prefix: str = '') ‑> Iterator[Tuple[str, Alphabet]]
-
Iterates over all registered alphabets, optionally restricting to those with given prefix.
Example usage:
>>> from bases import alphabet >>> dict(alphabet.table(prefix="base32")) {'base32': StringAlphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567', case_sensitive=False), 'base32hex': StringAlphabet('0123456789ABCDEFGHIJKLMNOPQRSTUV', case_sensitive=False), 'base32z': StringAlphabet('ybndrfg8ejkmcpqxot1uwisza345h769', case_sensitive=False)}
Expand source code
def table(*, prefix: str = "") -> Iterator[Tuple[str, Alphabet]]: """ Iterates over all registered alphabets, optionally restricting to those with given prefix. Example usage: ```py >>> from bases import alphabet >>> dict(alphabet.table(prefix="base32")) {'base32': StringAlphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567', case_sensitive=False), 'base32hex': StringAlphabet('0123456789ABCDEFGHIJKLMNOPQRSTUV', case_sensitive=False), 'base32z': StringAlphabet('ybndrfg8ejkmcpqxot1uwisza345h769', case_sensitive=False)} ``` """ validate(prefix, str) alphabets = [(name, alphabet) for name, alphabet in _alphabets.items() if name.startswith(prefix)] alphabets = sorted(alphabets, key=lambda pair: pair[0]) return iter(alphabets)
def unregister(*names: str) ‑> None
-
Unregisters any number of existing alphabets by name. Raises
KeyError
is an alphabet with one of the given names doesn't exist.Example usage:
>>> from bases import alphabet >>> alphabet.unregister("base16", "base32") >>> alphabet.has("base16") False >>> alphabet.get("base16") KeyError: "Alphabet named 'base16' does not exist."
Note that pre-defined constants are unaffected by this:
>>> alphabet.base16 StringAlphabet('0123456789ABCDEF')
Expand source code
def unregister(*names: str) -> None: """ Unregisters any number of existing alphabets by name. Raises `KeyError` is an alphabet with one of the given names doesn't exist. Example usage: ```py >>> from bases import alphabet >>> alphabet.unregister("base16", "base32") >>> alphabet.has("base16") False >>> alphabet.get("base16") KeyError: "Alphabet named 'base16' does not exist." ``` Note that pre-defined constants are unaffected by this: ```py >>> alphabet.base16 StringAlphabet('0123456789ABCDEF') ``` """ for name in names: validate(name, str) for name in names: if name not in _alphabets: raise KeyError(f"Alphabet named {repr(name)} does not exist.") del _alphabets[name]