Skip to content

Commit

Permalink
Allow for both a random schema name and a time-based one
Browse files Browse the repository at this point in the history
  • Loading branch information
Photonios committed Apr 6, 2023
1 parent 139d1ac commit 5476b25
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 9 deletions.
20 changes: 19 additions & 1 deletion docs/source/schemas.rst
Original file line number Diff line number Diff line change
Expand Up @@ -73,14 +73,32 @@ Re-create if necessary with a custom name
schema = PostgresSchema.drop_and_create("otherschema", cascade=True)
With a time-based name
**********************
.. warning::
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.
.. code-block:: python
for psqlextra.schema import PostgresSchema
# schema name will be "myprefix_<timestamp>"
schema = PostgresSchema.create_time_based("myprefix")
print(schema.name)
With a random name
******************
A 8 character suffix is appended. Entropy is dependent on your system. See :meth:`~os.urandom` for more information.
.. code-block:: python
for psqlextra.schema import PostgresSchema
# schema name will be "myprefix_<timestamp>"
# schema name will be "myprefix_<8 random characters>"
schema = PostgresSchema.create_random("myprefix")
print(schema.name)
Expand Down
28 changes: 26 additions & 2 deletions psqlextra/schema.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import os

from contextlib import contextmanager

import wrapt
Expand Down Expand Up @@ -84,10 +86,14 @@ def create(
return cls(name, using=using)

@classmethod
def create_random(
def create_time_based(
cls, prefix: str, *, using: str = DEFAULT_DB_ALIAS
) -> "PostgresSchema":
"""Creates a new schema with a random (time-based) suffix.
"""Creates a new schema with a time-based suffix.
The time is precise up to the second. Creating
multiple time based schema in the same second
WILL lead to conflicts.
Arguments:
prefix:
Expand All @@ -101,6 +107,24 @@ def create_random(
name_suffix = timezone.now().strftime("%Y%m%d%H%m%s")
return cls.create(f"{prefix}_{name_suffix}", using=using)

@classmethod
def create_random(
cls, prefix: str, *, using: str = DEFAULT_DB_ALIAS
) -> "PostgresSchema":
"""Creates a new schema with a random suffix.
Arguments:
prefix:
Name to prefix the final name with. The name plus
prefix cannot be longer than 63 characters.
using:
Name of the database connection to use.
"""

name_suffix = os.urandom(4).hex()
return cls.create(f"{prefix}_{name_suffix}", using=using)

@classmethod
def delete_and_create(
cls, name: str, *, cascade: bool = False, using: str = DEFAULT_DB_ALIAS
Expand Down
23 changes: 17 additions & 6 deletions tests/test_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,24 @@ def test_postgres_schema_create_name_that_requires_escaping():
assert _does_schema_exist("table")


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

assert schema.name == "myprefix_2023040713041680892620"
assert _does_schema_exist(schema.name)


def test_postgres_schema_create_random():
schema = PostgresSchema.create_random("myprefix")

prefix, suffix = schema.name.split("_")
assert prefix == "myprefix"
assert len(suffix) == 8

assert _does_schema_exist(schema.name)


def test_postgres_schema_delete_and_create():
schema = PostgresSchema.create("test")

Expand Down Expand Up @@ -215,11 +225,12 @@ def test_postgres_schema_connection_no_delete_default():


def test_postgres_temporary_schema():
with freezegun.freeze_time("2023-04-07 13:37:00.0"):
with postgres_temporary_schema("temp") as schema:
assert schema.name == "temp_2023040713041680892620"
with postgres_temporary_schema("temp") as schema:
name_prefix, name_suffix = schema.name.split("_")
assert name_prefix == "temp"
assert len(name_suffix) == 8

assert _does_schema_exist(schema.name)
assert _does_schema_exist(schema.name)

assert not _does_schema_exist(schema.name)

Expand Down

0 comments on commit 5476b25

Please sign in to comment.