Skip to content

Commit 050a1ac

Browse files
authored
SNOW-1362666: improve random string generation (#2034)
1 parent 2b44cd3 commit 050a1ac

File tree

3 files changed

+41
-1
lines changed

3 files changed

+41
-1
lines changed

DESCRIPTION.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ Source code is also available at: https://github.com/snowflakedb/snowflake-conne
88

99
# Release Notes
1010

11+
- v3.12.2 (TBD)
12+
- Improved implementation of `snowflake.connector.util_text.random_string` to avoid collisions.
13+
1114
- v3.12.1(August 20,2024)
1215
- Fixed a bug that logged the session token when renewing a session.
1316
- Fixed a bug where disabling client telemetry did not work.

src/snowflake/connector/util_text.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,5 +282,5 @@ def random_string(
282282
suffix: Suffix to add to random string generated.
283283
choices: A generator of things to choose from.
284284
"""
285-
random_part = "".join([random.choice(choices) for _ in range(length)])
285+
random_part = "".join([random.Random().choice(choices) for _ in range(length)])
286286
return "".join([prefix, random_part, suffix])

test/unit/test_text_util.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#
2+
# Copyright (c) 2012-2023 Snowflake Computing Inc. All rights reserved.
3+
#
4+
5+
import concurrent.futures
6+
import random
7+
8+
import pytest
9+
10+
try:
11+
from snowflake.connector.util_text import random_string
12+
except ImportError:
13+
pass
14+
15+
pytestmark = pytest.mark.skipolddriver # old test driver tests won't run this module
16+
17+
18+
def test_random_string_generation_with_same_global_seed():
19+
random.seed(42)
20+
random_string1 = random_string()
21+
random.seed(42)
22+
random_string2 = random_string()
23+
assert (
24+
isinstance(random_string1, str)
25+
and isinstance(random_string2, str)
26+
and random_string1 != random_string2
27+
)
28+
29+
def get_random_string():
30+
random.seed(42)
31+
return random_string()
32+
33+
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
34+
# Submit tasks to the pool and get future objects
35+
futures = [executor.submit(get_random_string) for _ in range(5)]
36+
res = [f.result() for f in futures]
37+
assert len(set(res)) == 5 # no duplicate string

0 commit comments

Comments
 (0)