Source code for randcsv.value_generators
from math import nan
import secrets
from . import data_type as dt
[docs]def generate_integer(num_of_bytes):
"""Generates a cryptographically secure, random integer.
:param num_of_bytes: number of bytes
:type num_of_bytes: int
:return: random integer
:rtype: number
"""
if num_of_bytes <= 0:
raise ValueError("number of digits must be positive")
return secrets.randbits(num_of_bytes * 8)
[docs]def generate_float(num_of_bytes):
"""Generates a cryptographically secure, random floating point.
:param num_of_bytes: number of decimal places
:type num_of_bytes: int
:return: random float
:rtype: float
"""
if num_of_bytes <= 0:
raise ValueError("number of decimal places must be positive")
exclusive_upper_bound = 2 ** (num_of_bytes * 8)
return secrets.randbelow(exclusive_upper_bound) / exclusive_upper_bound
[docs]def generate_token(num_of_bytes):
"""Generates a cryptographically secure, random (URL safe) token.
:param num_of_bytes: number of bytes
:type num_of_bytes: int
:return: random token
:rtype: str
"""
if num_of_bytes <= 0:
raise ValueError("number of bytes must be positive")
return secrets.token_urlsafe(num_of_bytes)
[docs]def generator_factory(data_type):
"""Factory function, returns the result of correct value generator.
:param data_type: data type of value
:type data_type: str
:raises ValueError: Data type must be one of: str, int, float.
:return: generator function
:rtype: function
"""
if data_type == dt.DataType.token.value:
return generate_token
elif data_type == dt.DataType.floating_point.value:
return generate_float
elif data_type == dt.DataType.integer.value:
return generate_integer
else:
raise ValueError(
"data type must be one of: str, int, float"
)
[docs]def generate_value(all_value_types_sorted, data_types, byte_size):
"""Generic value generator.
:param all_value_types_sorted: list of tuples containing value types sorted by frequency
:type all_value_types_sorted: List[Tuple]
:param data_types: list of the desired sata types
:type data_types: List[String]
:param byte_size: number of bytes
:type byte_size: int
:raises ValueError: Value must be either NaN, "empty", or a valid data type (regular value).
:return: random value
:rtype: Union[String, Number, Float]
"""
numerator = secrets.randbelow(100000000)
generate_number = numerator / 100000000
left_boundary = 0
for item in all_value_types_sorted:
right_boundary = item[1] + left_boundary
if left_boundary <= generate_number < right_boundary:
# 0 = value
# 1 = nan
# 2 = empty
if item[0] == 0:
# this is a regular number, so randomly select one
generator = generator_factory(secrets.choice(data_types))
return generator(byte_size)
elif item[0] == 1:
# this is a NaN value
return nan
elif item[0] == 2:
# this is an empty value
return None
else:
# this must be an empty value
raise ValueError(
'value must be either nan, empty, or a valid data type'
)
left_boundary = right_boundary