Skip to content

Commit

Permalink
Merge pull request #29 from mdekstrand/feature/stdlib-rng
Browse files Browse the repository at this point in the history
Add API to create stdlib Random instances
  • Loading branch information
mdekstrand authored May 28, 2024
2 parents cffa9b8 + 8693ff7 commit aa98ce7
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 0 deletions.
1 change: 1 addition & 0 deletions docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ override the global seed to support seed-specifying APIs.
Packages that expect their client code to use SeedBank to seed the random number ecosystem should
use these functions to obtain random number generators.

.. autofunction:: std_rng
.. autofunction:: numpy_rng
.. autofunction:: numpy_random_state
.. autofunction:: cupy_rng
2 changes: 2 additions & 0 deletions seedbank/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"initialize",
"init_file",
"derive_seed",
"std_rng",
"numpy_rng",
"numpy_random_state",
"cupy_rng",
Expand Down Expand Up @@ -136,3 +137,4 @@ def int_seed(
from seedbank._config import init_file # noqa: E402
from seedbank.cupy import cupy_rng # noqa: E402
from seedbank.numpy import numpy_random_state, numpy_rng # noqa: E402
from seedbank.stdlib import std_rng # noqa: E402
25 changes: 25 additions & 0 deletions seedbank/stdlib.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import logging
import random
from typing import Optional

from . import derive_seed
from ._keys import SeedLike, make_seed
from ._state import SeedState

_log = logging.getLogger(__name__)
Expand All @@ -13,3 +16,25 @@ def is_available():
def seed(state: SeedState):
_log.debug("initializing stdlib seed")
random.seed(state.int_seed)


def std_rng(
spec: Optional[SeedLike] = None,
) -> random.Random:
"""
Get a standard library random number generator (:class:`random.Random`) with
either the specified seed or a fresh seed.
Args:
spec:
The spec for this RNG.
Returns:
A random number generator.
"""
if spec is None:
seed = derive_seed()
else:
seed = make_seed(spec)
data = seed.generate_state(4)
return random.Random(bytes(data))
33 changes: 33 additions & 0 deletions tests/test_stdlib.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
"""
stdlib python tests
"""

import random

from seedbank import std_rng


def test_stdlib_rng():
"""
Make sure we get an stdlib RNG.
"""
rng = std_rng()
assert isinstance(rng, random.Random)


def test_stdlib_rng_fresh_seed():
"""
Test that two stdlib RNGs with fresh seeds return different numbers.
"""
rng1 = std_rng()
rng2 = std_rng()
assert rng1.getrandbits(10) != rng2.getrandbits(10)


def test_stdlib_rng_same_seed():
"""
Test that two stdlib RNGs with the same seed start the same.
"""
rng1 = std_rng("foo")
rng2 = std_rng("foo")
assert rng1.getrandbits(10) == rng2.getrandbits(10)

0 comments on commit aa98ce7

Please sign in to comment.