summaryrefslogtreecommitdiff
path: root/src/mailman/utilities
diff options
context:
space:
mode:
authorAurélien Bompard2015-12-26 13:41:30 +0100
committerAurélien Bompard2015-12-26 13:41:30 +0100
commitf739cda916ffdd64ed3b389c5c8b920578cc9475 (patch)
treea551011ff301a220d26cc72084c28075f9dfa431 /src/mailman/utilities
parenta11e089cc1e0e5aff2502e584014295a414a43f9 (diff)
downloadmailman-f739cda916ffdd64ed3b389c5c8b920578cc9475.tar.gz
mailman-f739cda916ffdd64ed3b389c5c8b920578cc9475.tar.zst
mailman-f739cda916ffdd64ed3b389c5c8b920578cc9475.zip
Return predictable token IDs in testing mode.
This commits builds upon the mailman.utilities.uid.UniqueIDFactory to generate predictable tokens when the testing mode is activated. This will make VCR tapes more diffable between runs.
Diffstat (limited to 'src/mailman/utilities')
-rw-r--r--src/mailman/utilities/uid.py32
1 files changed, 28 insertions, 4 deletions
diff --git a/src/mailman/utilities/uid.py b/src/mailman/utilities/uid.py
index ec7948189..d20360ca0 100644
--- a/src/mailman/utilities/uid.py
+++ b/src/mailman/utilities/uid.py
@@ -28,8 +28,11 @@ __all__ = [
import os
+import time
import uuid
import errno
+import random
+import hashlib
from flufl.lock import Lock
from mailman.config import config
@@ -78,7 +81,7 @@ class UniqueIDFactory:
# may still not be ideal due to race conditions, but I think the
# tests will be serialized enough (and the ids reset between
# tests) that it will not be a problem. Maybe.
- return self._next_uid()
+ return uuid.UUID(int=self._next_uid())
while True:
uid = uuid.uuid4()
try:
@@ -96,13 +99,13 @@ class UniqueIDFactory:
next_uid = uid + 1
with open(self._uid_file, 'w') as fp:
fp.write(str(next_uid))
- return uuid.UUID(int=uid)
+ return uid
except IOError as error:
if error.errno != errno.ENOENT:
raise
with open(self._uid_file, 'w') as fp:
fp.write('2')
- return uuid.UUID(int=1)
+ return 1
def reset(self):
with self._lock:
@@ -111,4 +114,25 @@ class UniqueIDFactory:
-factory = UniqueIDFactory()
+class TokenFactory(UniqueIDFactory):
+
+ def __init__(self):
+ super(TokenFactory, self).__init__(context='token')
+
+ def new_token(self):
+ """
+ Calculate a unique token. Algorithm vetted by the Timbot. time()
+ has high resolution on Linux, clock() on Windows. random gives us
+ about 45 bits in Python 2.2, 53 bits on Python 2.3. The time and
+ clock values basically help obscure the random number generator, as
+ does the hash calculation. The integral parts of the time values
+ are discarded because they're the most predictable bits.
+ """
+ if layers.is_testing():
+ # When in testing mode we want to produce predictable tokens, see
+ # UniqueIDFactory for a similar use case.
+ return str(self._next_uid()).zfill(40)
+ right_now = time.time()
+ x = random.random() + right_now % 1.0 + time.clock() % 1.0
+ # Use sha1 because it produces shorter strings.
+ return hashlib.sha1(repr(x).encode('utf-8')).hexdigest()