| import hashlib | |
| import random as python_random | |
| from typing import Any, Hashable | |
| from .settings_utils import get_settings | |
| settings = get_settings() | |
| def get_seed(): | |
| return settings.seed | |
| def new_random_generator(sub_seed: Any) -> python_random.Random: | |
| """Get a generator based on a seed derived from the default seed. | |
| The purpose is to have a random generator that provides outputs | |
| that are independent of previous randomizations. | |
| """ | |
| if not isinstance(sub_seed, Hashable): | |
| # e.g. for lists or dicts | |
| # Create a persistent hash for the input object (using plain hash(..) produces | |
| # a value that varies between runs) | |
| sub_seed_str = str(sub_seed).encode("utf-8") | |
| # limit the hash int size to 2^32 | |
| sub_seed_hexdigest = hashlib.md5(sub_seed_str).hexdigest()[:8] | |
| # convert to int, from base 16: | |
| sub_seed_int = int(sub_seed_hexdigest, 16) | |
| sub_seed = str(sub_seed_int) | |
| elif not isinstance(sub_seed, str): | |
| # for Hashable objects that are not strings | |
| sub_seed = str(hash(sub_seed)) | |
| sub_default_seed = str(settings.seed) + "/" + sub_seed | |
| return python_random.Random(sub_default_seed) | |