Skip to content

Commit 43765fe

Browse files
committed
Allow for both a random schema name and a time-based one
1 parent 164fbed commit 43765fe

File tree

3 files changed

+62
-9
lines changed

3 files changed

+62
-9
lines changed

docs/source/schemas.rst

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,14 +73,32 @@ Re-create if necessary with a custom name
7373
schema = PostgresSchema.drop_and_create("otherschema", cascade=True)
7474
7575
76+
With a time-based name
77+
**********************
78+
79+
.. warning::
80+
81+
The time-based suffix is precise up to the second. If two threads or processes both try to create a time-based schema name with the same suffix in the same second, they will have conflicts.
82+
83+
.. code-block:: python
84+
85+
for psqlextra.schema import PostgresSchema
86+
87+
# schema name will be "myprefix_<timestamp>"
88+
schema = PostgresSchema.create_time_based("myprefix")
89+
print(schema.name)
90+
91+
7692
With a random name
7793
******************
7894
95+
A 8 character suffix is appended. Entropy is dependent on your system. See :meth:`~os.urandom` for more information.
96+
7997
.. code-block:: python
8098
8199
for psqlextra.schema import PostgresSchema
82100
83-
# schema name will be "myprefix_<timestamp>"
101+
# schema name will be "myprefix_<8 random characters>"
84102
schema = PostgresSchema.create_random("myprefix")
85103
print(schema.name)
86104

psqlextra/schema.py

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import os
2+
13
from contextlib import contextmanager
24

35
import wrapt
@@ -84,10 +86,14 @@ def create(
8486
return cls(name, using=using)
8587

8688
@classmethod
87-
def create_random(
89+
def create_time_based(
8890
cls, prefix: str, *, using: str = DEFAULT_DB_ALIAS
8991
) -> "PostgresSchema":
90-
"""Creates a new schema with a random (time-based) suffix.
92+
"""Creates a new schema with a time-based suffix.
93+
94+
The time is precise up to the second. Creating
95+
multiple time based schema in the same second
96+
WILL lead to conflicts.
9197
9298
Arguments:
9399
prefix:
@@ -101,6 +107,24 @@ def create_random(
101107
name_suffix = timezone.now().strftime("%Y%m%d%H%m%s")
102108
return cls.create(f"{prefix}_{name_suffix}", using=using)
103109

110+
@classmethod
111+
def create_random(
112+
cls, prefix: str, *, using: str = DEFAULT_DB_ALIAS
113+
) -> "PostgresSchema":
114+
"""Creates a new schema with a random suffix.
115+
116+
Arguments:
117+
prefix:
118+
Name to prefix the final name with. The name plus
119+
prefix cannot be longer than 63 characters.
120+
121+
using:
122+
Name of the database connection to use.
123+
"""
124+
125+
name_suffix = os.urandom(4).hex()
126+
return cls.create(f"{prefix}_{name_suffix}", using=using)
127+
104128
@classmethod
105129
def delete_and_create(
106130
cls, name: str, *, cascade: bool = False, using: str = DEFAULT_DB_ALIAS

tests/test_schema.py

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,14 +52,24 @@ def test_postgres_schema_create_name_that_requires_escaping():
5252
assert _does_schema_exist("table")
5353

5454

55-
def test_postgres_schema_create_random():
55+
def test_postgres_schema_create_time_based():
5656
with freezegun.freeze_time("2023-04-07 13:37:00.0"):
57-
schema = PostgresSchema.create_random("myprefix")
57+
schema = PostgresSchema.create_time_based("myprefix")
5858

5959
assert schema.name == "myprefix_2023040713041680892620"
6060
assert _does_schema_exist(schema.name)
6161

6262

63+
def test_postgres_schema_create_random():
64+
schema = PostgresSchema.create_random("myprefix")
65+
66+
prefix, suffix = schema.name.split("_")
67+
assert prefix == "myprefix"
68+
assert len(suffix) == 8
69+
70+
assert _does_schema_exist(schema.name)
71+
72+
6373
def test_postgres_schema_delete_and_create():
6474
schema = PostgresSchema.create("test")
6575

@@ -215,11 +225,12 @@ def test_postgres_schema_connection_no_delete_default():
215225

216226

217227
def test_postgres_temporary_schema():
218-
with freezegun.freeze_time("2023-04-07 13:37:00.0"):
219-
with postgres_temporary_schema("temp") as schema:
220-
assert schema.name == "temp_2023040713041680892620"
228+
with postgres_temporary_schema("temp") as schema:
229+
name_prefix, name_suffix = schema.name.split("_")
230+
assert name_prefix == "temp"
231+
assert len(name_suffix) == 8
221232

222-
assert _does_schema_exist(schema.name)
233+
assert _does_schema_exist(schema.name)
223234

224235
assert not _does_schema_exist(schema.name)
225236

0 commit comments

Comments
 (0)