Skip to content

Commit

Permalink
Merge d8abe58 into c7ddb82
Browse files Browse the repository at this point in the history
  • Loading branch information
lorinkoz committed Jun 26, 2023
2 parents c7ddb82 + d8abe58 commit b186a27
Show file tree
Hide file tree
Showing 21 changed files with 105 additions and 74 deletions.
2 changes: 1 addition & 1 deletion django_pgschemas/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
from .schema import SchemaDescriptor, activate, activate_public, deactivate, get_current_schema # noqa
from .schema import Schema, activate, activate_public, deactivate, get_current_schema # noqa
4 changes: 2 additions & 2 deletions django_pgschemas/contrib/channels2/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from django.utils.encoding import force_str
from django.utils.module_loading import import_string

from ...schema import SchemaDescriptor
from ...schema import Schema
from ...utils import get_domain_model, remove_www
from .auth import TenantAuthMiddlewareStack

Expand Down Expand Up @@ -47,7 +47,7 @@ def get_tenant_scope(self, scope):
if schema in ["public", "default"]:
continue
if hostname in data["DOMAINS"]:
tenant = SchemaDescriptor.create(schema_name=schema, domain_url=hostname)
tenant = Schema.create(schema_name=schema, domain_url=hostname)
if "WS_URLCONF" in data:
ws_urlconf = data["WS_URLCONF"]
return tenant, "", import_string(ws_urlconf + ".urlpatterns")
Expand Down
4 changes: 2 additions & 2 deletions django_pgschemas/contrib/channels3/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from django.utils.encoding import force_str
from django.utils.module_loading import import_string

from ...schema import SchemaDescriptor
from ...schema import Schema
from ...utils import get_domain_model, remove_www
from .auth import TenantAuthMiddlewareStack

Expand Down Expand Up @@ -49,7 +49,7 @@ def get_tenant_scope(self, scope):
if schema in ["public", "default"]:
continue
if hostname in data["DOMAINS"]:
tenant = SchemaDescriptor.create(schema_name=schema, domain_url=hostname)
tenant = Schema.create(schema_name=schema, domain_url=hostname)
if "WS_URLCONF" in data:
ws_urlconf = data["WS_URLCONF"]
return tenant, "", import_string(ws_urlconf + ".urlpatterns")
Expand Down
6 changes: 3 additions & 3 deletions django_pgschemas/management/commands/_executors.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from django.core.management.base import BaseCommand, OutputWrapper
from django.db import connection, connections, transaction

from ...schema import SchemaDescriptor, activate
from ...schema import Schema, activate
from ...utils import get_clone_reference, get_tenant_model


Expand Down Expand Up @@ -63,9 +63,9 @@ def __call__(self, message):

if schema_name in settings.TENANTS:
domains = settings.TENANTS[schema_name].get("DOMAINS", [])
schema = SchemaDescriptor.create(schema_name=schema_name, domain_url=domains[0] if domains else None)
schema = Schema.create(schema_name=schema_name, domain_url=domains[0] if domains else None)
elif schema_name == get_clone_reference():
schema = SchemaDescriptor.create(schema_name=schema_name)
schema = Schema.create(schema_name=schema_name)
else:
TenantModel = get_tenant_model()
schema = TenantModel.objects.get(schema_name=schema_name)
Expand Down
6 changes: 3 additions & 3 deletions django_pgschemas/middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from django.shortcuts import redirect
from django.urls import clear_url_caches, set_urlconf

from .schema import SchemaDescriptor, activate, activate_public
from .schema import Schema, activate, activate_public
from .urlresolvers import get_urlconf_from_schema
from .utils import get_domain_model, remove_www

Expand Down Expand Up @@ -34,7 +34,7 @@ def middleware(request):
if schema in ["public", "default"]:
continue
if hostname in data["DOMAINS"]:
tenant = SchemaDescriptor.create(schema_name=schema, domain_url=hostname)
tenant = Schema.create(schema_name=schema, domain_url=hostname)
break

# Checking for dynamic tenants
Expand Down Expand Up @@ -68,7 +68,7 @@ def middleware(request):
if schema in ["public", "default"]:
continue
if hostname in data.get("FALLBACK_DOMAINS", []):
tenant = SchemaDescriptor.create(schema_name=schema, domain_url=hostname)
tenant = Schema.create(schema_name=schema, domain_url=hostname)
break

# No tenant found from domain / folder
Expand Down
4 changes: 2 additions & 2 deletions django_pgschemas/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
from django.db import models, transaction

from .postgresql_backend.base import check_schema_name
from .schema import SchemaDescriptor
from .schema import Schema
from .signals import dynamic_tenant_needs_sync, dynamic_tenant_post_sync, dynamic_tenant_pre_drop
from .utils import create_or_clone_schema, drop_schema, get_domain_model, schema_exists


class TenantMixin(SchemaDescriptor, models.Model):
class TenantMixin(Schema, models.Model):
"""
All tenant models must inherit this class.
"""
Expand Down
38 changes: 25 additions & 13 deletions django_pgschemas/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,33 +7,45 @@
_active = Local()


def get_default_schema() -> "SchemaDescriptor":
return SchemaDescriptor.create("public")
def __getattr__(name):
from warnings import warn

if name == "SchemaDescriptor":
warn("'SchemaDescriptor' is deprecated, use 'Schema' instead", DeprecationWarning)
return globals()["Schema"]

def get_current_schema() -> "SchemaDescriptor":
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")


def get_default_schema() -> "Schema":
return Schema.create("public")


def get_current_schema() -> "Schema":
current_schema = getattr(_active, "value", None)
return current_schema or get_default_schema()


def activate(schema: "SchemaDescriptor"):
if not isinstance(schema, SchemaDescriptor):
raise RuntimeError("'activate' must be called with a SchemaDescriptor descendant")
def activate(schema: "Schema"):
if not isinstance(schema, Schema):
raise RuntimeError("'activate' must be called with a Schema descendant")

_active.value = schema
schema_activate.send(sender=SchemaDescriptor, schema=schema)

schema_activate.send(sender=Schema, schema=schema)


def deactivate():
if hasattr(_active, "value"):
del _active.value
schema_activate.send(sender=SchemaDescriptor, schema=SchemaDescriptor.create("public"))

schema_activate.send(sender=Schema, schema=Schema.create("public"))


activate_public = deactivate


class SchemaDescriptor:
class Schema:
schema_name = None
domain_url = None
folder = None
Expand All @@ -42,16 +54,16 @@ class SchemaDescriptor:

@staticmethod
def create(schema_name: str, domain_url: Optional[str] = None, folder: Optional[str] = None):
schema = SchemaDescriptor()
schema = Schema()
schema.schema_name = schema_name
schema.domain_url = domain_url
schema.folder = folder
return schema

def __enter__(self):
self.previous_schema = get_current_schema()
self._previous_schema = get_current_schema()
activate(self)

def __exit__(self, exc_type, exc_val, exc_tb):
previous_schema = getattr(self, "previous_schema", None)
activate(previous_schema) if previous_schema else deactivate()
_previous_schema = getattr(self, "_previous_schema", None)
activate(_previous_schema) if _previous_schema else deactivate()
4 changes: 2 additions & 2 deletions django_pgschemas/test/cases.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from django.core.management import call_command
from django.test import TestCase

from ..schema import SchemaDescriptor, activate, activate_public
from ..schema import Schema, activate, activate_public
from ..utils import get_clone_reference, get_domain_model, get_tenant_model

ALLOWED_TEST_DOMAIN = ".localhost"
Expand Down Expand Up @@ -49,7 +49,7 @@ def setUpClass(cls):
if settings.TENANTS[cls.schema_name]["DOMAINS"]
else cls.schema_name + ALLOWED_TEST_DOMAIN
)
cls.tenant = SchemaDescriptor.create(schema_name=cls.schema_name, domain_url=domain)
cls.tenant = Schema.create(schema_name=cls.schema_name, domain_url=domain)
activate(cls.tenant)
cls.cls_atomics = cls._enter_atomics()
try:
Expand Down
5 changes: 3 additions & 2 deletions django_pgschemas/urlresolvers.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from django.conf import settings
from django.urls import URLResolver

from .schema import SchemaDescriptor, get_current_schema
from .schema import Schema, get_current_schema


class TenantPrefixPattern:
Expand Down Expand Up @@ -67,7 +67,8 @@ def get_urlconf_from_schema(schema):
Returns the proper URLConf depending on the schema.
The schema must come with ``domain_url`` and ``folder`` members set.
"""
assert isinstance(schema, SchemaDescriptor)
if not isinstance(schema, Schema):
raise RuntimeError("'get_urlconf_from_schema' must be called with a Schema descendant")

if not schema.domain_url:
return None
Expand Down
4 changes: 2 additions & 2 deletions django_pgschemas/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,9 @@ def run_in_public_schema(func):
"Decorator that makes decorated function to be run in the public schema."

def wrapper(*args, **kwargs):
from .schema import SchemaDescriptor
from .schema import Schema

with SchemaDescriptor.create(schema_name="public"):
with Schema.create(schema_name="public"):
return func(*args, **kwargs)

return wrapper
Expand Down
2 changes: 1 addition & 1 deletion docs/advanced.rst
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ The base commands are:

Since these commands can work with both static and dynamic tenants, the
parameter ``tenant`` will be an instance of
``django_pgschemas.schema.SchemaDescriptor``. Make sure you do the
``django_pgschemas.schema.Schema``. Make sure you do the
appropriate type checking before accessing the tenant members, as not every
tenant will be an instance of
``settings.TENANTS["default"]["TENANT_MODEL"]``.
2 changes: 1 addition & 1 deletion dpgs_sandbox/shared_public/migrations/0001_initial.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class Migration(migrations.Migration):
),
],
options={"abstract": False},
bases=(django_pgschemas.schema.SchemaDescriptor, models.Model),
bases=(django_pgschemas.schema.Schema, models.Model),
),
migrations.AddField(
model_name="domain",
Expand Down
36 changes: 18 additions & 18 deletions dpgs_sandbox/tests/test_file_storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from django.test import TestCase, override_settings

from django_pgschemas.contrib.files import TenantFileSystemStorage
from django_pgschemas.schema import SchemaDescriptor
from django_pgschemas.schema import Schema
from django_pgschemas.utils import get_tenant_model

TenantModel = get_tenant_model()
Expand All @@ -29,11 +29,11 @@ def tearDownClass(cls):
shutil.rmtree(cls.temp_dir)

def test_path_identifier_basic(self):
with SchemaDescriptor.create(schema_name=""):
with Schema.create(schema_name=""):
self.assertEquals(self.storage.get_schema_path_identifier(), "")
with SchemaDescriptor.create(schema_name="public"):
with Schema.create(schema_name="public"):
self.assertEquals(self.storage.get_schema_path_identifier(), "public")
with SchemaDescriptor.create(schema_name="blog"):
with Schema.create(schema_name="blog"):
self.assertEquals(self.storage.get_schema_path_identifier(), "blog")
with TenantModel(schema_name="tenant"):
self.assertEquals(self.storage.get_schema_path_identifier(), "tenant")
Expand All @@ -50,28 +50,28 @@ def test_path_identifier_function_in_settings(self):
self.assertEquals(self.storage.get_schema_path_identifier(), "tenant-custom-pathname")

def test_base_location(self):
with SchemaDescriptor.create(schema_name=""):
with Schema.create(schema_name=""):
self.assertEquals(self.storage.base_location, self.temp_dir + "/")
with SchemaDescriptor.create(schema_name="public"):
with Schema.create(schema_name="public"):
self.assertEquals(self.storage.base_location, self.temp_dir + "/public/")
with SchemaDescriptor.create(schema_name="blog"):
with Schema.create(schema_name="blog"):
self.assertEquals(self.storage.base_location, self.temp_dir + "/blog/")
with SchemaDescriptor.create(schema_name="tenant", folder="folder"):
with Schema.create(schema_name="tenant", folder="folder"):
self.assertEquals(self.storage.base_location, self.temp_dir + "/tenant/")

def test_base_url(self):
with SchemaDescriptor.create(schema_name=""):
with Schema.create(schema_name=""):
self.assertEquals(self.storage.base_url, "/base-url/")
with SchemaDescriptor.create(schema_name="public"):
with Schema.create(schema_name="public"):
self.assertEquals(self.storage.base_url, "/base-url/public/")
with SchemaDescriptor.create(schema_name="blog"):
with Schema.create(schema_name="blog"):
self.assertEquals(self.storage.base_url, "/base-url/blog/")
with SchemaDescriptor.create(schema_name="tenant", folder="folder"):
with Schema.create(schema_name="tenant", folder="folder"):
self.assertEquals(self.storage.base_url, "/base-url/")

def test_file_path(self):
self.assertFalse(self.storage.exists("test.file"))
with SchemaDescriptor.create(schema_name="tenant1"):
with Schema.create(schema_name="tenant1"):
f = ContentFile("random content")
f_name = self.storage.save("test.file", f)
self.assertEqual(os.path.join(self.temp_dir, "tenant1", f_name), self.storage.path(f_name))
Expand All @@ -80,7 +80,7 @@ def test_file_path(self):

def test_file_save_with_path(self):
self.assertFalse(self.storage.exists("path/to"))
with SchemaDescriptor.create(schema_name="tenant1"):
with Schema.create(schema_name="tenant1"):
self.storage.save("path/to/test.file", ContentFile("file saved with path"))
self.assertTrue(self.storage.exists("path/to"))
with self.storage.open("path/to/test.file") as f:
Expand All @@ -90,15 +90,15 @@ def test_file_save_with_path(self):
self.assertFalse(self.storage.exists("test.file"))

def test_file_url_simple(self):
with SchemaDescriptor.create(schema_name=""):
with Schema.create(schema_name=""):
self.assertEqual(self.storage.url("test.file"), "/base-url/test.file")
with SchemaDescriptor.create(schema_name="public"):
with Schema.create(schema_name="public"):
self.assertEqual(self.storage.url("test.file"), "/base-url/public/test.file")
with SchemaDescriptor.create(schema_name="tenant", folder="folder"):
with Schema.create(schema_name="tenant", folder="folder"):
self.assertEqual(self.storage.url("test.file"), "/base-url/test.file")

def test_file_url_complex(self):
with SchemaDescriptor.create(schema_name="tenant"):
with Schema.create(schema_name="tenant"):
self.assertEqual(
self.storage.url(r"~!*()'@#$%^&*abc`+ =.file"),
"/base-url/tenant/~!*()'%40%23%24%25%5E%26*abc%60%2B%20%3D.file",
Expand Down
4 changes: 2 additions & 2 deletions dpgs_sandbox/tests/test_log.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from django.test import TestCase

from django_pgschemas.log import SchemaContextFilter
from django_pgschemas.schema import SchemaDescriptor
from django_pgschemas.schema import Schema


class SchemaContextFilterTestCase(TestCase):
Expand All @@ -15,7 +15,7 @@ class FakeRecord:

record = FakeRecord()
scf = SchemaContextFilter()
with SchemaDescriptor.create(schema_name="some-tenant", domain_url="some-tenant.some-url.com"):
with Schema.create(schema_name="some-tenant", domain_url="some-tenant.some-url.com"):
scf.filter(record)
self.assertEqual(record.schema_name, "some-tenant")
self.assertEqual(record.domain_url, "some-tenant.some-url.com")
18 changes: 18 additions & 0 deletions dpgs_sandbox/tests/test_schema.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import warnings

from django.test import SimpleTestCase


class TestDeprecatedImports(SimpleTestCase):
def test_schema_descriptor_warning(self):
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter("always")
from django_pgschemas.schema import SchemaDescriptor # noqa

self.assertEqual(len(w), 1)
self.assertEqual(str(w[0].message), "'SchemaDescriptor' is deprecated, use 'Schema' instead")

def test_schema_descriptor_accessible(self):
from django_pgschemas.schema import SchemaDescriptor

self.assertIsNotNone(SchemaDescriptor)
4 changes: 2 additions & 2 deletions dpgs_sandbox/tests/test_signals.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from django.test import TestCase

from django_pgschemas.schema import SchemaDescriptor, activate
from django_pgschemas.schema import Schema, activate
from django_pgschemas.signals import schema_activate
from django_pgschemas.utils import get_tenant_model, schema_exists

Expand All @@ -24,7 +24,7 @@ def receiver(sender, schema, **kwargs):
response["value"] = schema

schema_activate.connect(receiver)
activate(SchemaDescriptor.create(**params))
activate(Schema.create(**params))
schema_activate.disconnect(receiver)
for key, value in params.items():
self.assertEqual(value, getattr(response["value"], key))
Expand Down
Loading

0 comments on commit b186a27

Please sign in to comment.