Module bases.random
Functions to generate random data.
The main functions are rand_bytes()
and rand_str()
:
- the function call
rand_bytes()(n)
returns an iterator yielding a stream ofn
random bytestrings - the function call
rand_bytes(n, encoding=enc)
returns an iterator yielding a stream ofn
random bytestrings valid for the encoding (i.e. they should be encoded without error) - the function call
rand_str(n, encoding=enc)
returns an iterator yielding a stream ofn
random strings valid for the encoding (i.e. they should be decoded without error) - the function call
rand_str(n, alphabet=alph)
returns an iterator yielding a stream ofn
random strings with characters from the alphabet - the function call
rand_bytes()
returns an iterator yielding an infinite stream of random bytestrings - the function call
rand_bytes(encoding=enc)
returns an iterator yielding an infinite stream of random bytestrings valid for the encoding - the function call
rand_str(encoding=enc)
returns an iterator yielding an infinite stream of random strings valid for the encoding - the function call
rand_str(alphabet=alph)
returns an iterator yielding an infinite stream of random strings with characters from the alphabet
Example usage:
>>> from bases import base10, base32
>>> from bases import random
>>> my_random_bytes = list(random.rand_bytes(4, encoding=base10))
>>> [list(b) for b in my_random_bytes]
[[0, 30, 135, 156, 223, 90, 134, 83, 6, 243, 245],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 216, 87, 1, 2],
[70, 98, 190, 187, 66, 224, 178],
[0, 96, 63]]
>>> my_random_strings = list(random.rand_str(4, encoding=base32))
>>> my_random_strings
['2CQ7ZT6WNI', 'IGQJTGA', 'V6GW3UN64QDAFZA7', 'PUEMOPJ4']
The options()
context manager is used to set options temporarily, within the scope of a with
directive:
min_bytes
andmax_bytes
bound the length of bytestrings yielded byrand_bytes()
min_chars
andmax_chars
bound the length of strings yielded byrand_str()
Options can be set with set_options()
and reset with reset_options()
. A read-only view on options can be obtained
from get_options()
, and a read-only view on default options can be obtained from default_options()
:
>>> random.default_options()
mappingproxy({'min_bytes': 0, 'max_bytes': 16,
'min_chars': 0, 'max_chars': 16})
Expand source code
"""
Functions to generate random data.
The main functions are `rand_bytes` and `rand_str`:
- the function call `rand_bytes(n)` returns an iterator yielding a stream of `n` random bytestrings
- the function call `rand_bytes(n, encoding=enc)` returns an iterator yielding a stream of `n` random bytestrings valid for the encoding
(i.e. they should be encoded without error)
- the function call `rand_str(n, encoding=enc)` returns an iterator yielding a stream of `n` random strings valid for the encoding
(i.e. they should be decoded without error)
- the function call `rand_str(n, alphabet=alph)` returns an iterator yielding a stream of `n` random strings with characters from the alphabet
- the function call `rand_bytes()` returns an iterator yielding an infinite stream of random bytestrings
- the function call `rand_bytes(encoding=enc)` returns an iterator yielding an infinite stream of random bytestrings valid for the encoding
- the function call `rand_str(encoding=enc)` returns an iterator yielding an infinite stream of random strings valid for the encoding
- the function call `rand_str(alphabet=alph)` returns an iterator yielding an infinite stream of random strings with characters from the alphabet
Example usage:
```python
>>> from bases import base10, base32
>>> from bases import random
>>> my_random_bytes = list(random.rand_bytes(4, encoding=base10))
>>> [list(b) for b in my_random_bytes]
[[0, 30, 135, 156, 223, 90, 134, 83, 6, 243, 245],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 216, 87, 1, 2],
[70, 98, 190, 187, 66, 224, 178],
[0, 96, 63]]
>>> my_random_strings = list(random.rand_str(4, encoding=base32))
>>> my_random_strings
['2CQ7ZT6WNI', 'IGQJTGA', 'V6GW3UN64QDAFZA7', 'PUEMOPJ4']
```
The `options()` context manager is used to set options temporarily, within the scope of a `with` directive:
- `min_bytes` and `max_bytes` bound the length of bytestrings yielded by `rand_bytes`
- `min_chars` and `max_chars` bound the length of strings yielded by `rand_str`
Options can be set with `set_options()` and reset with `reset_options()`. A read-only view on options can be obtained
from `get_options()`, and a read-only view on default options can be obtained from `default_options()`:
```py
>>> random.default_options()
mappingproxy({'min_bytes': 0, 'max_bytes': 16,
'min_chars': 0, 'max_chars': 16})
```
"""
# pylint: disable = global-statement
from contextlib import contextmanager
from itertools import chain, islice
from random import Random # pylint: disable = import-self
from types import MappingProxyType
from typing import Any, Dict, Iterator, Mapping, Optional
from .alphabet import Alphabet
from .encoding import BaseEncoding, SimpleBaseEncoding, ZeropadBaseEncoding, BlockBaseEncoding, FixcharBaseEncoding
_default_options: Mapping[str, Any] = MappingProxyType({
"min_bytes": 0,
"max_bytes": 16,
"min_chars": 0,
"max_chars": 16,
})
_options: Mapping[str, Any] = MappingProxyType(_default_options)
_rand: Random = Random(0)
def reset_options() -> None:
"""
Resets random generation options to their default values.
"""
global _options
global _rand
_options = _default_options
_rand = Random(0)
def default_options() -> Mapping[str, Any]:
"""
Readonly view of the default random generation options.
"""
return _default_options
def get_options() -> Mapping[str, Any]:
"""
Readonly view of the current random generation options.
"""
return _options
@contextmanager
def options(*,
seed: Optional[int] = None,
min_bytes: Optional[int] = None,
max_bytes: Optional[int] = None,
min_chars: Optional[int] = None,
max_chars: Optional[int] = None,) -> Iterator[None]:
"""
Returns with-statement context manager for temporary option setting:
```py
with options(**options):
for value in rand_data(num_samples, encoding):
...
```
See `set_options` for a description of the options.
"""
# pylint: disable = too-many-locals
global _options
global _rand
try:
_old_options = _options
_old_rand = _rand
set_options(seed=seed,
min_bytes=min_bytes, max_bytes=max_bytes,
min_chars=min_chars, max_chars=max_chars,)
yield
finally:
_options = _old_options
_rand = _old_rand
def set_options(*,
seed: Optional[int] = None,
min_bytes: Optional[int] = None,
max_bytes: Optional[int] = None,
min_chars: Optional[int] = None,
max_chars: Optional[int] = None,) -> None:
"""
Permanently sets random generation options:
```python
seed: int # set new random number generator, with this seed
min_bytes: int # min length of `bytes` value
max_bytes: int # max length of `bytes` value
min_chars: int # min length of `str` value
max_chars: int # max length of `str` value
```
"""
# pylint: disable = too-many-branches, too-many-locals, too-many-statements
global _options
global _rand
# set newly passed options
_new_options: Dict[str, Any] = {}
if seed is not None:
_rand = Random(seed)
if min_bytes is not None:
if min_bytes < 0:
raise ValueError("Value for min_bytes is negative.")
_new_options["min_bytes"] = min_bytes
if max_bytes is not None:
if max_bytes < 0:
raise ValueError("Value for max_bytes is negative.")
_new_options["max_bytes"] = max_bytes
if min_chars is not None:
if min_chars < 0:
raise ValueError("Value for min_chars is negative.")
_new_options["min_chars"] = min_chars
if max_chars is not None:
if max_chars < 0:
raise ValueError("Value for max_chars is negative.")
_new_options["max_chars"] = max_chars
# pass-through other options with former values
for k, v in _options.items():
if k not in _new_options:
_new_options[k] = v
# check compatibility conditions
if _new_options["min_bytes"] > _new_options["max_bytes"]:
raise ValueError("Value for min_bytes is larger than value for max_bytes.")
if _new_options["min_chars"] > _new_options["max_chars"]:
raise ValueError("Value for min_chars is larger than value for max_chars.")
# update options
_options = MappingProxyType(_new_options)
def rand_bytes(n: Optional[int] = None, *, encoding: Optional[BaseEncoding] = None) -> Iterator[bytes]:
"""
Generates a stream of random `bytes` objects.
If a number `n` is given, that number of samples is yelded.
If an encoding `encoding` is given, only bytes valid for that encoding are yielded.
Example usage:
```py
>>> my_random_bytes = list(random.rand_bytes(4, encoding=base10))
>>> [list(b) for b in my_random_bytes]
[[0, 30, 135, 156, 223, 90, 134, 83, 6, 243, 245],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 216, 87, 1, 2],
[70, 98, 190, 187, 66, 224, 178],
[0, 96, 63]]
```
"""
if encoding is None:
return rand_raw_bytes(n)
if isinstance(encoding, SimpleBaseEncoding):
return _rand_bytes_simple_enc(n, encoding)
if isinstance(encoding, ZeropadBaseEncoding):
return _rand_bytes_zeropad_enc(n, encoding)
if isinstance(encoding, BlockBaseEncoding):
return _rand_bytes_block_enc(n, encoding)
if isinstance(encoding, FixcharBaseEncoding):
return _rand_bytes_fixedchar_enc(n, encoding)
raise ValueError(f"Unsupported encoding type {type(encoding)}")
def rand_raw_bytes(n: Optional[int] = None, *, min_bytes: Optional[int] = None, max_bytes: Optional[int] = None) -> Iterator[bytes]:
"""
Generates a stream of random `bytes` objects.
If a number `n` is given, that number of samples is yelded.
The optional `min_bytes` and `max_bytes` parameters can be used to set a minimum/maximum length
for the `bytes` objects: if `None`, the values are fetched from `get_options`.
"""
if n is not None and n < 0:
raise ValueError()
if min_bytes is None:
min_bytes = _options["min_bytes"]
if max_bytes is None:
max_bytes = _options["max_bytes"]
rand = _rand
# main yielding loop
yielded = 0
while n is None or yielded < n:
# sample random length
l = rand.randint(min_bytes, max_bytes)
# yield random unsigned integer filling l bytes
i = rand.randrange(0, 256**l)
yield i.to_bytes(l, byteorder="big")
yielded += 1
def _rand_bytes_simple_enc(n: Optional[int], _: SimpleBaseEncoding) -> Iterator[bytes]:
if n is not None and n < 0:
raise ValueError()
min_bytes = _options["min_bytes"]
max_bytes = _options["max_bytes"]
rand = _rand
# main yielding loop
yielded = 0
while n is None or yielded < n:
# sample random length
l = rand.randint(min_bytes, max_bytes)
# yield random unsigned integer filling l bytes with no leading zero bytes
if l == 0:
i = 0
else:
i = rand.randrange(256**(l-1), 256**l)
yield i.to_bytes(l, byteorder="big")
yielded += 1
def _rand_bytes_zeropad_enc(n: Optional[int], _: ZeropadBaseEncoding) -> Iterator[bytes]:
if n is not None and n < 0:
raise ValueError()
min_bytes = _options["min_bytes"]
max_bytes = _options["max_bytes"]
rand = _rand
# main yielding loop
yielded = 0
while n is None or yielded < n:
# sample random length
l = rand.randint(min_bytes, max_bytes)
# sample random number of leading zero bytes
z = rand.randint(0, l)
# yield random unsigned integer filling l-z bytes
if l == z:
i = 0
else:
i = rand.randrange(256**(l-z-1), 256**(l-z))
yield i.to_bytes(l, byteorder="big")
yielded += 1
def _rand_bytes_block_enc(n: Optional[int], encoding: BlockBaseEncoding) -> Iterator[bytes]:
if n is not None and n < 0:
raise ValueError()
min_bytes = _options["min_bytes"]
max_bytes = _options["max_bytes"]
rand = _rand
# pre-compute valid bytestring lengths for block base encoding
block_nbytes = encoding.block_nbytes
nbytes2nchars = encoding.nbytes2nchars
valid_lengths = [l for l in range(min_bytes, max_bytes+1)
if l%block_nbytes == 0 or l%block_nbytes in nbytes2nchars]
# main yielding loop
yielded = 0
while n is None or yielded < n:
# sample random valid length
l = rand.choice(valid_lengths)
# yield random unsigned integer filling l bytes
i = rand.randrange(0, 256**l)
yield i.to_bytes(l, byteorder="big")
yielded += 1
def _rand_bytes_fixedchar_enc(n: Optional[int], _: FixcharBaseEncoding) -> Iterator[bytes]:
return rand_raw_bytes(n)
def rand_str(n: Optional[int] = None, *, encoding: Optional[BaseEncoding]=None, alphabet: Optional[Alphabet]=None) -> Iterator[str]:
"""
Generates a stream of random strings.
If a number `n` is given, that number of samples is yelded.
Exactly one of `encoding` or `alphabet` must be given:
- if an `encoding` is given, only strings valid for that encoding are yielded
- if an `alphabet` is given, only strings valid for that alphabet are yielded
Example usage:
```py
>>> my_random_strings = list(random.rand_str(4, encoding=base32))
>>> my_random_strings
['2CQ7ZT6WNI', 'IGQJTGA', 'V6GW3UN64QDAFZA7', 'PUEMOPJ4']
```
"""
if encoding is None:
if alphabet is None:
raise ValueError("One of 'encoding' or 'alphabet' must be specified.")
return _rand_alphabet_string(n, alphabet)
if alphabet is not None:
raise ValueError("Exactly one of 'encoding' or 'alphabet' must be specified.")
if isinstance(encoding, SimpleBaseEncoding):
return _rand_str_simple_enc(n, encoding)
if isinstance(encoding, ZeropadBaseEncoding):
return _rand_str_zeropad_enc(n, encoding)
if isinstance(encoding, BlockBaseEncoding):
return _rand_str_block_enc(n, encoding)
if isinstance(encoding, FixcharBaseEncoding):
return _rand_str_fixedchar_enc(n, encoding)
raise ValueError(f"Unsupported encoding type {type(encoding)}")
def rand_char(n: Optional[int] = None, *, alphabet: Alphabet, non_zero: bool = False) -> Iterator[str]:
"""
Generates a stream of random characters from the alphabet (one character yielded at a time).
If a number `n` is given, that number of samples is yelded.
If `non_zero` is `True`, the zero character for the alphabet is not yielded.
"""
if n is not None and n < 0:
raise ValueError()
start = 1 if non_zero else 0
end = len(alphabet)
rand = _rand
yielded = 0
while n is None or yielded < n:
# yield random character (excluding zero character, if non_zero is True)
idx = rand.randrange(start, end)
yield alphabet[idx]
yielded += 1
def _rand_alphabet_string(n: Optional[int], alphabet: Alphabet) -> Iterator[str]:
if n is not None and n < 0:
raise ValueError()
min_chars = _options["min_chars"]
max_chars = _options["max_chars"]
rand = _rand
# infinte random character stream
rand_char_stream = rand_char(alphabet=alphabet)
# main yielding loop
yielded = 0
while n is None or yielded < n:
# sample random length
l = rand.randint(min_chars, max_chars)
# yield random string filling l characters
yield "".join(islice(rand_char_stream, l))
yielded += 1
def _rand_str_simple_enc(n: Optional[int], encoding: SimpleBaseEncoding) -> Iterator[str]:
if n is not None and n < 0:
raise ValueError()
min_chars = _options["min_chars"]
max_chars = _options["max_chars"]
rand = _rand
# infinte random character streams
rand_char_stream = rand_char(alphabet=encoding.alphabet)
rand_nonzero_char_stream = rand_char(alphabet=encoding.alphabet, non_zero=True)
# main yielding loop
yielded = 0
while n is None or yielded < n:
# sample random length
l = rand.randint(min_chars, max_chars)
# yield random str filling l characters with no leading zero characters
if l == 0:
yield ""
else:
yield "".join(chain(islice(rand_nonzero_char_stream, 1),
islice(rand_char_stream, l-1)))
yielded += 1
def _rand_str_zeropad_enc(n: Optional[int], encoding: ZeropadBaseEncoding) -> Iterator[str]:
if n is not None and n < 0:
raise ValueError()
min_chars = _options["min_chars"]
max_chars = _options["max_chars"]
rand = _rand
# zero character
zero_char = encoding.zero_char
# infinte random character streams
rand_char_stream = rand_char(alphabet=encoding.alphabet)
rand_nonzero_char_stream = rand_char(alphabet=encoding.alphabet, non_zero=True)
# main yielding loop
yielded = 0
while n is None or yielded < n:
# sample random length
l = rand.randint(min_chars, max_chars)
# sample random number of leading zero chars
z = rand.randint(0, l)
# yield random str filling l characters with given number of leading zeros
if l-z == 0:
yield zero_char*z
else:
yield zero_char*z+"".join(chain(islice(rand_nonzero_char_stream, 1),
islice(rand_char_stream, l-z-1)))
yielded += 1
def rand_block_chars(n: Optional[int] = None, *, block_nchars: int, encoding: BlockBaseEncoding) -> Iterator[str]:
"""
Generates a stream of random char blocks for a block base encoding.
If a number `n` is given, that number of samples is yelded.
The number `block_nchars` of characters in the blocks must be valid for the encoding.
"""
if n is not None and n < 0:
raise ValueError()
# extract block size in chars and bytes
nchars2nbytes = encoding.nchars2nbytes
if block_nchars not in nchars2nbytes:
raise ValueError(f"Invalid number of characters per block ({block_nchars})")
block_nbytes = nchars2nbytes[block_nchars]
# infinite random byte stream
rand_bytes_stream = rand_raw_bytes(min_bytes=1, max_bytes=1)
# main yielding loop
yielded = 0
while n is None or yielded < n:
block_bytes = b"".join(islice(rand_bytes_stream, block_nbytes))
s = encoding.encode(block_bytes)
yield s
yielded += 1
def _rand_str_block_enc(n: Optional[int], encoding: BlockBaseEncoding) -> Iterator[str]:
if n is not None and n < 0:
raise ValueError()
min_chars = _options["min_chars"]
max_chars = _options["max_chars"]
rand = _rand
# pre-compute valid string lengths for block base encoding
block_nchars = encoding.block_nchars
nchars2nbytes = encoding.nchars2nbytes
valid_lengths = [l for l in range(min_chars, max_chars+1)
if l%block_nchars == 0 or l%block_nchars in nchars2nbytes]
# infinte random character streams
rand_block_stream = {
nchars: rand_block_chars(block_nchars=nchars, encoding=encoding)
for nchars in nchars2nbytes
}
# main yielding loop
yielded = 0
while n is None or yielded < n:
# sample random valid length
l = rand.choice(valid_lengths)
num_full_blocks, final_block_nchars = divmod(l, block_nchars)
full_blocks = islice(rand_block_stream[block_nchars], num_full_blocks)
if final_block_nchars == 0:
yield "".join(full_blocks)
else:
final_block = islice(rand_block_stream[final_block_nchars], 1)
yield "".join(chain(full_blocks, final_block))
yielded += 1
def _rand_str_fixedchar_enc(n: Optional[int], encoding: FixcharBaseEncoding) -> Iterator[str]:
# pylint: disable = too-many-locals
if n is not None and n < 0:
raise ValueError()
min_chars = _options["min_chars"]
max_chars = _options["max_chars"]
rand = _rand
# pre-compute valid string lengths for fixed-char base encoding
alphabet = encoding.alphabet
char_nbits = encoding.char_nbits
valid_lengths = [l for l in range(min_chars, max_chars+1)
if (l*char_nbits)%8 < char_nbits]
# infinte random character stream
rand_char_stream = rand_char(alphabet=encoding.alphabet)
# main yielding loop
yielded = 0
while n is None or yielded < n:
# sample random length
l = rand.choice(valid_lengths)
# yield random str filling l characters with pad bits set to zero
extra_nbits = (l*char_nbits)%8
if extra_nbits == 0:
s = "".join(islice(rand_char_stream, l))
else:
all_chars_but_last = "".join(islice(rand_char_stream, l-1))
last_char_idx = rand.randrange(0, 2**(char_nbits-extra_nbits))<<extra_nbits
last_char = alphabet[last_char_idx]
s = all_chars_but_last+last_char
if encoding.padding == "ignore":
yield s
else:
yield encoding.pad_string(s)
yielded += 1
Functions
def default_options() ‑> Mapping[str, Any]
-
Readonly view of the default random generation options.
Expand source code
def default_options() -> Mapping[str, Any]: """ Readonly view of the default random generation options. """ return _default_options
def get_options() ‑> Mapping[str, Any]
-
Readonly view of the current random generation options.
Expand source code
def get_options() -> Mapping[str, Any]: """ Readonly view of the current random generation options. """ return _options
def options(*, seed: Optional[int] = None, min_bytes: Optional[int] = None, max_bytes: Optional[int] = None, min_chars: Optional[int] = None, max_chars: Optional[int] = None) ‑> Iterator[None]
-
Returns with-statement context manager for temporary option setting:
with options(**options): for value in rand_data(num_samples, encoding): ...
See
set_options()
for a description of the options.Expand source code
@contextmanager def options(*, seed: Optional[int] = None, min_bytes: Optional[int] = None, max_bytes: Optional[int] = None, min_chars: Optional[int] = None, max_chars: Optional[int] = None,) -> Iterator[None]: """ Returns with-statement context manager for temporary option setting: ```py with options(**options): for value in rand_data(num_samples, encoding): ... ``` See `set_options` for a description of the options. """ # pylint: disable = too-many-locals global _options global _rand try: _old_options = _options _old_rand = _rand set_options(seed=seed, min_bytes=min_bytes, max_bytes=max_bytes, min_chars=min_chars, max_chars=max_chars,) yield finally: _options = _old_options _rand = _old_rand
def rand_block_chars(n: Optional[int] = None, *, block_nchars: int, encoding: BlockBaseEncoding) ‑> Iterator[str]
-
Generates a stream of random char blocks for a block base encoding. If a number
n
is given, that number of samples is yelded. The numberblock_nchars
of characters in the blocks must be valid for the encoding.Expand source code
def rand_block_chars(n: Optional[int] = None, *, block_nchars: int, encoding: BlockBaseEncoding) -> Iterator[str]: """ Generates a stream of random char blocks for a block base encoding. If a number `n` is given, that number of samples is yelded. The number `block_nchars` of characters in the blocks must be valid for the encoding. """ if n is not None and n < 0: raise ValueError() # extract block size in chars and bytes nchars2nbytes = encoding.nchars2nbytes if block_nchars not in nchars2nbytes: raise ValueError(f"Invalid number of characters per block ({block_nchars})") block_nbytes = nchars2nbytes[block_nchars] # infinite random byte stream rand_bytes_stream = rand_raw_bytes(min_bytes=1, max_bytes=1) # main yielding loop yielded = 0 while n is None or yielded < n: block_bytes = b"".join(islice(rand_bytes_stream, block_nbytes)) s = encoding.encode(block_bytes) yield s yielded += 1
def rand_bytes(n: Optional[int] = None, *, encoding: Optional[BaseEncoding] = None) ‑> Iterator[bytes]
-
Generates a stream of random
bytes
objects. If a numbern
is given, that number of samples is yelded. If an encodingencoding
is given, only bytes valid for that encoding are yielded.Example usage:
>>> my_random_bytes = list(random.rand_bytes(4, encoding=base10)) >>> [list(b) for b in my_random_bytes] [[0, 30, 135, 156, 223, 90, 134, 83, 6, 243, 245], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 216, 87, 1, 2], [70, 98, 190, 187, 66, 224, 178], [0, 96, 63]]
Expand source code
def rand_bytes(n: Optional[int] = None, *, encoding: Optional[BaseEncoding] = None) -> Iterator[bytes]: """ Generates a stream of random `bytes` objects. If a number `n` is given, that number of samples is yelded. If an encoding `encoding` is given, only bytes valid for that encoding are yielded. Example usage: ```py >>> my_random_bytes = list(random.rand_bytes(4, encoding=base10)) >>> [list(b) for b in my_random_bytes] [[0, 30, 135, 156, 223, 90, 134, 83, 6, 243, 245], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 216, 87, 1, 2], [70, 98, 190, 187, 66, 224, 178], [0, 96, 63]] ``` """ if encoding is None: return rand_raw_bytes(n) if isinstance(encoding, SimpleBaseEncoding): return _rand_bytes_simple_enc(n, encoding) if isinstance(encoding, ZeropadBaseEncoding): return _rand_bytes_zeropad_enc(n, encoding) if isinstance(encoding, BlockBaseEncoding): return _rand_bytes_block_enc(n, encoding) if isinstance(encoding, FixcharBaseEncoding): return _rand_bytes_fixedchar_enc(n, encoding) raise ValueError(f"Unsupported encoding type {type(encoding)}")
def rand_char(n: Optional[int] = None, *, alphabet: Alphabet, non_zero: bool = False) ‑> Iterator[str]
-
Generates a stream of random characters from the alphabet (one character yielded at a time). If a number
n
is given, that number of samples is yelded. Ifnon_zero
isTrue
, the zero character for the alphabet is not yielded.Expand source code
def rand_char(n: Optional[int] = None, *, alphabet: Alphabet, non_zero: bool = False) -> Iterator[str]: """ Generates a stream of random characters from the alphabet (one character yielded at a time). If a number `n` is given, that number of samples is yelded. If `non_zero` is `True`, the zero character for the alphabet is not yielded. """ if n is not None and n < 0: raise ValueError() start = 1 if non_zero else 0 end = len(alphabet) rand = _rand yielded = 0 while n is None or yielded < n: # yield random character (excluding zero character, if non_zero is True) idx = rand.randrange(start, end) yield alphabet[idx] yielded += 1
def rand_raw_bytes(n: Optional[int] = None, *, min_bytes: Optional[int] = None, max_bytes: Optional[int] = None) ‑> Iterator[bytes]
-
Generates a stream of random
bytes
objects. If a numbern
is given, that number of samples is yelded. The optionalmin_bytes
andmax_bytes
parameters can be used to set a minimum/maximum length for thebytes
objects: ifNone
, the values are fetched fromget_options()
.Expand source code
def rand_raw_bytes(n: Optional[int] = None, *, min_bytes: Optional[int] = None, max_bytes: Optional[int] = None) -> Iterator[bytes]: """ Generates a stream of random `bytes` objects. If a number `n` is given, that number of samples is yelded. The optional `min_bytes` and `max_bytes` parameters can be used to set a minimum/maximum length for the `bytes` objects: if `None`, the values are fetched from `get_options`. """ if n is not None and n < 0: raise ValueError() if min_bytes is None: min_bytes = _options["min_bytes"] if max_bytes is None: max_bytes = _options["max_bytes"] rand = _rand # main yielding loop yielded = 0 while n is None or yielded < n: # sample random length l = rand.randint(min_bytes, max_bytes) # yield random unsigned integer filling l bytes i = rand.randrange(0, 256**l) yield i.to_bytes(l, byteorder="big") yielded += 1
def rand_str(n: Optional[int] = None, *, encoding: Optional[BaseEncoding] = None, alphabet: Optional[Alphabet] = None) ‑> Iterator[str]
-
Generates a stream of random strings. If a number
n
is given, that number of samples is yelded. Exactly one ofencoding
oralphabet
must be given: - if anencoding
is given, only strings valid for that encoding are yielded - if analphabet
is given, only strings valid for that alphabet are yieldedExample usage:
>>> my_random_strings = list(random.rand_str(4, encoding=base32)) >>> my_random_strings ['2CQ7ZT6WNI', 'IGQJTGA', 'V6GW3UN64QDAFZA7', 'PUEMOPJ4']
Expand source code
def rand_str(n: Optional[int] = None, *, encoding: Optional[BaseEncoding]=None, alphabet: Optional[Alphabet]=None) -> Iterator[str]: """ Generates a stream of random strings. If a number `n` is given, that number of samples is yelded. Exactly one of `encoding` or `alphabet` must be given: - if an `encoding` is given, only strings valid for that encoding are yielded - if an `alphabet` is given, only strings valid for that alphabet are yielded Example usage: ```py >>> my_random_strings = list(random.rand_str(4, encoding=base32)) >>> my_random_strings ['2CQ7ZT6WNI', 'IGQJTGA', 'V6GW3UN64QDAFZA7', 'PUEMOPJ4'] ``` """ if encoding is None: if alphabet is None: raise ValueError("One of 'encoding' or 'alphabet' must be specified.") return _rand_alphabet_string(n, alphabet) if alphabet is not None: raise ValueError("Exactly one of 'encoding' or 'alphabet' must be specified.") if isinstance(encoding, SimpleBaseEncoding): return _rand_str_simple_enc(n, encoding) if isinstance(encoding, ZeropadBaseEncoding): return _rand_str_zeropad_enc(n, encoding) if isinstance(encoding, BlockBaseEncoding): return _rand_str_block_enc(n, encoding) if isinstance(encoding, FixcharBaseEncoding): return _rand_str_fixedchar_enc(n, encoding) raise ValueError(f"Unsupported encoding type {type(encoding)}")
def reset_options() ‑> None
-
Resets random generation options to their default values.
Expand source code
def reset_options() -> None: """ Resets random generation options to their default values. """ global _options global _rand _options = _default_options _rand = Random(0)
def set_options(*, seed: Optional[int] = None, min_bytes: Optional[int] = None, max_bytes: Optional[int] = None, min_chars: Optional[int] = None, max_chars: Optional[int] = None) ‑> None
-
Permanently sets random generation options:
seed: int # set new random number generator, with this seed min_bytes: int # min length of `bytes` value max_bytes: int # max length of `bytes` value min_chars: int # min length of `str` value max_chars: int # max length of `str` value
Expand source code
def set_options(*, seed: Optional[int] = None, min_bytes: Optional[int] = None, max_bytes: Optional[int] = None, min_chars: Optional[int] = None, max_chars: Optional[int] = None,) -> None: """ Permanently sets random generation options: ```python seed: int # set new random number generator, with this seed min_bytes: int # min length of `bytes` value max_bytes: int # max length of `bytes` value min_chars: int # min length of `str` value max_chars: int # max length of `str` value ``` """ # pylint: disable = too-many-branches, too-many-locals, too-many-statements global _options global _rand # set newly passed options _new_options: Dict[str, Any] = {} if seed is not None: _rand = Random(seed) if min_bytes is not None: if min_bytes < 0: raise ValueError("Value for min_bytes is negative.") _new_options["min_bytes"] = min_bytes if max_bytes is not None: if max_bytes < 0: raise ValueError("Value for max_bytes is negative.") _new_options["max_bytes"] = max_bytes if min_chars is not None: if min_chars < 0: raise ValueError("Value for min_chars is negative.") _new_options["min_chars"] = min_chars if max_chars is not None: if max_chars < 0: raise ValueError("Value for max_chars is negative.") _new_options["max_chars"] = max_chars # pass-through other options with former values for k, v in _options.items(): if k not in _new_options: _new_options[k] = v # check compatibility conditions if _new_options["min_bytes"] > _new_options["max_bytes"]: raise ValueError("Value for min_bytes is larger than value for max_bytes.") if _new_options["min_chars"] > _new_options["max_chars"]: raise ValueError("Value for min_chars is larger than value for max_chars.") # update options _options = MappingProxyType(_new_options)