From 98a27aca6fa8f7fdff60f2b630ce7c3946aaaf79 Mon Sep 17 00:00:00 2001 From: Wil Thieme Date: Mon, 11 Mar 2024 14:18:46 -0400 Subject: [PATCH] Fix: DeprecationWarning: Seeding based on hashing is deprecated since Python 3.9 and will be removed in a subsequent version. --- docs/changes.rst | 3 +++ petl/test/util/test_random.py | 16 +++++++++++++++- petl/util/random.py | 33 ++++++++++++++++++++++++++------- 3 files changed, 44 insertions(+), 8 deletions(-) diff --git a/docs/changes.rst b/docs/changes.rst index ca563846..5ff55eba 100644 --- a/docs/changes.rst +++ b/docs/changes.rst @@ -7,6 +7,9 @@ Version 1.7.15 * Add unit tests for randomtable, dummytable, and their supporting functions and classes. By :user:`bmos`, :issue:`657`. +* Fix: DeprecationWarning: Seeding based on hashing is deprecated since Python 3.9 and will be removed in a subsequent version. + By :user:`bmos`, :issue:`657`. + Version 1.7.14 -------------- diff --git a/petl/test/util/test_random.py b/petl/test/util/test_random.py index f4f092a4..89d7f181 100644 --- a/petl/test/util/test_random.py +++ b/petl/test/util/test_random.py @@ -1,7 +1,21 @@ import random +import time from functools import partial -from petl.util.random import randomtable, RandomTable, dummytable, DummyTable +from petl.util.random import randomseed, randomtable, RandomTable, dummytable, DummyTable + + +def test_randomseed(): + """ + Ensure that randomseed provides a non-empty string that changes. + """ + s1 = randomseed() + time.sleep(1) + s2 = randomseed() + + assert isinstance(s1, str) + assert s1 != "" + assert s1 != s2 def test_randomtable(): diff --git a/petl/util/random.py b/petl/util/random.py index 94fa7588..d5fe9d7e 100644 --- a/petl/util/random.py +++ b/petl/util/random.py @@ -1,15 +1,24 @@ from __future__ import absolute_import, print_function, division - -import datetime +import hashlib import random import time from collections import OrderedDict from functools import partial + from petl.compat import xrange, text_type +from petl.util.base import Table -from petl.util.base import Table +def randomseed(): + """ + Obtain the hex digest of a sha256 hash of the + current epoch time in nanoseconds. + """ + + time_ns = str(time.time()).encode() + hash_time = hashlib.sha256(time_ns).hexdigest() + return hash_time def randomtable(numflds=5, numrows=100, wait=0, seed=None): @@ -36,9 +45,11 @@ def randomtable(numflds=5, numrows=100, wait=0, seed=None): | 0.026535969683863625 | 0.1988376506866485 | 0.6498844377795232 | +----------------------+----------------------+---------------------+ ... + Note that the data are generated on the fly and are not stored in memory, so this function can be used to simulate very large tables. + The only supported seed types are: None, int, float, str, bytes, and bytearray. """ @@ -52,7 +63,7 @@ def __init__(self, numflds=5, numrows=100, wait=0, seed=None): self.numrows = numrows self.wait = wait if seed is None: - self.seed = datetime.datetime.now() + self.seed = randomseed() else: self.seed = seed @@ -77,7 +88,7 @@ def __iter__(self): yield tuple(random.random() for n in range(nf)) def reseed(self): - self.seed = datetime.datetime.now() + self.seed = randomseed() def dummytable(numrows=100, @@ -108,6 +119,7 @@ def dummytable(numrows=100, | 4 | 'apples' | 0.09369523986159245 | +-----+----------+----------------------+ ... + >>> # customise fields ... import random @@ -132,12 +144,19 @@ def dummytable(numrows=100, | 0.4219218196852704 | 15 | 'chocolate' | +---------------------+-----+-------------+ ... + + + >>> table3_1 = etl.dummytable(50) + >>> table3_2 = etl.dummytable(100) + >>> table3_1[5] == table3_2[5] + False Data generation functions can be specified via the `fields` keyword argument. Note that the data are generated on the fly and are not stored in memory, so this function can be used to simulate very large tables. + The only supported seed types are: None, int, float, str, bytes, and bytearray. """ @@ -154,7 +173,7 @@ def __init__(self, numrows=100, fields=None, wait=0, seed=None): else: self.fields = OrderedDict(fields) if seed is None: - self.seed = datetime.datetime.now() + self.seed = randomseed() else: self.seed = seed @@ -181,4 +200,4 @@ def __iter__(self): yield tuple(fields[f]() for f in fields) def reseed(self): - self.seed = datetime.datetime.now() + self.seed = randomseed()