cardo-python-utils 0.5.dev50__tar.gz → 0.5.dev53__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {cardo_python_utils-0.5.dev50/cardo_python_utils.egg-info → cardo_python_utils-0.5.dev53}/PKG-INFO +1 -1
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53/cardo_python_utils.egg-info}/PKG-INFO +1 -1
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/cardo_python_utils.egg-info/SOURCES.txt +1 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/pyproject.toml +1 -1
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/README.md +16 -2
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/api/drf.py +6 -4
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/api/ninja.py +8 -10
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/celery/tenant_aware_task.py +45 -3
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/db/utils.py +2 -2
- cardo_python_utils-0.5.dev53/python_utils/django/management/commands/showmigrations.py +37 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/LICENSE +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/MANIFEST.in +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/README.rst +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/cardo_python_utils.egg-info/dependency_links.txt +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/cardo_python_utils.egg-info/requires.txt +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/cardo_python_utils.egg-info/top_level.txt +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/__init__.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/choices.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/data_structures.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/db.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/__init__.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/admin/__init__.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/admin/auth.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/admin/templates/__init__.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/admin/templates/user_groups_changelist.html +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/admin/user_group.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/admin/views.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/api/__init__.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/api/utils.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/apps.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/auth/service.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/celery/__init__.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/celery/tenant_aware_database_scheduler.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/db/__init__.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/db/alias.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/db/routers.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/db/transaction.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/management/__init__.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/management/commands/__init__.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/management/commands/migrateall.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/management/commands/shell.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/management/commands/tenant_aware_command.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/middleware/__init__.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/middleware/tenant_aware_http_middleware.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/middleware/tenant_aware_websocket_middleware.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/migrations/0001_initial.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/migrations/0001_initial_squashed_0005_alter_userrole_id.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/migrations/0002_auto_20220120_1617.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/migrations/0003_auto_20220513_1025.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/migrations/0004_auto_20220817_1526.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/migrations/0005_alter_userrole_id.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/migrations/0006_userrole_organization_and_more.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/migrations/0007_user_demo.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/migrations/0008_delete_userrole.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/migrations/__init__.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/models/__init__.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/models/user.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/models/user_group.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/oidc_settings.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/redis/__init__.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/redis/key_function.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/settings.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/storage/__init__.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/storage/tenant_aware_storage.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/tenant_context.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/tests/__init__.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/tests/conftest.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django_utils.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/esma_choices.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/exceptions.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/imports.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/math.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/text.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/time.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/types_hinting.py +0 -0
- {cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/setup.cfg +0 -0
|
@@ -48,6 +48,7 @@ python_utils/django/management/__init__.py
|
|
|
48
48
|
python_utils/django/management/commands/__init__.py
|
|
49
49
|
python_utils/django/management/commands/migrateall.py
|
|
50
50
|
python_utils/django/management/commands/shell.py
|
|
51
|
+
python_utils/django/management/commands/showmigrations.py
|
|
51
52
|
python_utils/django/management/commands/tenant_aware_command.py
|
|
52
53
|
python_utils/django/middleware/__init__.py
|
|
53
54
|
python_utils/django/middleware/tenant_aware_http_middleware.py
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "cardo-python-utils"
|
|
7
|
-
version = "0.5.
|
|
7
|
+
version = "0.5.dev53"
|
|
8
8
|
description = "Python library enhanced with a wide range of functions for different scenarios."
|
|
9
9
|
readme = "README.rst"
|
|
10
10
|
requires-python = ">=3.8"
|
|
@@ -157,14 +157,28 @@ If using `django-ninja`, apart from the settings configured above, auth utils ar
|
|
|
157
157
|
|
|
158
158
|
## Atomic Transactions
|
|
159
159
|
|
|
160
|
-
Django's `transaction.atomic` uses the default database. To make it tenant-aware, use `tenant_atomic
|
|
160
|
+
Django's `transaction.atomic` uses the default database. To make it tenant-aware, use `tenant_atomic`.
|
|
161
|
+
If `transaction.on_commit` is used, make sure to pass the tenant as DB alias as well:
|
|
161
162
|
|
|
162
163
|
```python3
|
|
163
164
|
from python_utils.django.db.transaction import tenant_atomic
|
|
164
165
|
|
|
165
166
|
@tenant_atomic
|
|
166
167
|
def my_function():
|
|
167
|
-
|
|
168
|
+
# Some logic
|
|
169
|
+
|
|
170
|
+
transaction.on_commit(do_smth, using=TenantContext.get())
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## Explicit database connection
|
|
174
|
+
|
|
175
|
+
If using django.db.connection anywhere in the code, you need to change that to get a tenant-aware connection:
|
|
176
|
+
|
|
177
|
+
```python3
|
|
178
|
+
from python_utils.django.db.utils import get_connection
|
|
179
|
+
from python_utils.django.tenant_context import TenantContext
|
|
180
|
+
|
|
181
|
+
connection = get_connection(TenantContext.get())
|
|
168
182
|
```
|
|
169
183
|
|
|
170
184
|
## Django Shell
|
{cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/api/drf.py
RENAMED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
from django.conf import settings
|
|
2
|
-
from jwt.exceptions import InvalidTokenError, PyJWKClientError
|
|
2
|
+
from jwt.exceptions import ExpiredSignatureError, InvalidTokenError, PyJWKClientError
|
|
3
3
|
|
|
4
4
|
from rest_framework import authentication
|
|
5
|
-
from rest_framework.exceptions import AuthenticationFailed
|
|
5
|
+
from rest_framework.exceptions import AuthenticationFailed, PermissionDenied
|
|
6
6
|
from rest_framework.permissions import BasePermission
|
|
7
7
|
|
|
8
8
|
from .utils import create_or_update_user, decode_jwt
|
|
@@ -14,13 +14,15 @@ class AuthenticationBackend(authentication.TokenAuthentication):
|
|
|
14
14
|
def authenticate_credentials(self, token: str):
|
|
15
15
|
try:
|
|
16
16
|
payload = decode_jwt(token, audience=self._get_audience())
|
|
17
|
+
except ExpiredSignatureError as e:
|
|
18
|
+
raise AuthenticationFailed("Token has expired.") from e
|
|
17
19
|
except (InvalidTokenError, PyJWKClientError) as e:
|
|
18
|
-
raise
|
|
20
|
+
raise PermissionDenied(f"Invalid token: {str(e)}") from e
|
|
19
21
|
|
|
20
22
|
try:
|
|
21
23
|
username = payload["preferred_username"]
|
|
22
24
|
except KeyError as e:
|
|
23
|
-
raise
|
|
25
|
+
raise PermissionDenied(
|
|
24
26
|
"Invalid token: preferred_username not present."
|
|
25
27
|
) from e
|
|
26
28
|
|
{cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/api/ninja.py
RENAMED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
from typing import Literal, Optional, Union
|
|
3
3
|
|
|
4
|
-
from jwt.exceptions import InvalidTokenError, PyJWKClientError
|
|
4
|
+
from jwt.exceptions import ExpiredSignatureError, InvalidTokenError, PyJWKClientError
|
|
5
5
|
|
|
6
6
|
from django.conf import settings
|
|
7
7
|
from django.http import HttpRequest
|
|
8
8
|
from ninja.security import HttpBearer
|
|
9
|
-
from ninja.errors import AuthenticationError, HttpError
|
|
9
|
+
from ninja.errors import AuthenticationError, AuthorizationError, HttpError
|
|
10
10
|
|
|
11
11
|
from .utils import (
|
|
12
12
|
acreate_or_update_user,
|
|
@@ -42,7 +42,7 @@ class AuthBearer(HttpBearer):
|
|
|
42
42
|
|
|
43
43
|
def _get_token(self, request: HttpRequest) -> Optional[str]:
|
|
44
44
|
"""
|
|
45
|
-
This part of the token validation is similar to what
|
|
45
|
+
This part of the token validation is similar to what
|
|
46
46
|
django-ninja is doing in HttpBearer.__call__
|
|
47
47
|
"""
|
|
48
48
|
headers = request.headers
|
|
@@ -61,16 +61,16 @@ class AuthBearer(HttpBearer):
|
|
|
61
61
|
def _decode_token(self, token: str) -> TokenPayload:
|
|
62
62
|
try:
|
|
63
63
|
return decode_jwt(token)
|
|
64
|
+
except ExpiredSignatureError as e:
|
|
65
|
+
raise AuthenticationError("Token has expired.") from e
|
|
64
66
|
except (InvalidTokenError, PyJWKClientError) as e:
|
|
65
|
-
raise
|
|
67
|
+
raise AuthorizationError(f"Invalid token: {str(e)}") from e
|
|
66
68
|
|
|
67
69
|
def _get_username(self, payload: TokenPayload) -> str:
|
|
68
70
|
try:
|
|
69
71
|
return payload["preferred_username"]
|
|
70
72
|
except KeyError as e:
|
|
71
|
-
raise
|
|
72
|
-
"Invalid token: 'preferred_username' claim not present."
|
|
73
|
-
) from e
|
|
73
|
+
raise AuthorizationError("Invalid token: 'preferred_username' claim not present.") from e
|
|
74
74
|
|
|
75
75
|
def _verify_scopes(self, request, token_payload):
|
|
76
76
|
allowed_scopes = self._get_view_allowed_scopes(request)
|
|
@@ -106,9 +106,7 @@ class AuthBearer(HttpBearer):
|
|
|
106
106
|
if operation.methods and method in operation.methods:
|
|
107
107
|
return operation.view_func
|
|
108
108
|
|
|
109
|
-
raise Exception(
|
|
110
|
-
f"Could not determine the view function for {request.method} {request.path}."
|
|
111
|
-
)
|
|
109
|
+
raise Exception(f"Could not determine the view function for {request.method} {request.path}.")
|
|
112
110
|
|
|
113
111
|
|
|
114
112
|
class AuthBearerAsync(AuthBearer):
|
|
@@ -27,8 +27,49 @@ class TenantAwareTask(TaskClass):
|
|
|
27
27
|
|
|
28
28
|
once = {"graceful": True, "unlock_before_run": False}
|
|
29
29
|
|
|
30
|
+
def apply(
|
|
31
|
+
self,
|
|
32
|
+
args=None,
|
|
33
|
+
kwargs=None,
|
|
34
|
+
link=None,
|
|
35
|
+
link_error=None,
|
|
36
|
+
task_id=None,
|
|
37
|
+
retries=None,
|
|
38
|
+
throw=None,
|
|
39
|
+
logfile=None,
|
|
40
|
+
loglevel=None,
|
|
41
|
+
headers=None,
|
|
42
|
+
**options,
|
|
43
|
+
):
|
|
44
|
+
"""Pass the tenant name from the context in the kwargs."""
|
|
45
|
+
|
|
46
|
+
if kwargs is None:
|
|
47
|
+
kwargs = {}
|
|
48
|
+
|
|
49
|
+
if TENANT_KEY not in kwargs:
|
|
50
|
+
tenant = TenantContext.get()
|
|
51
|
+
kwargs[TENANT_KEY] = tenant
|
|
52
|
+
|
|
53
|
+
return super().apply(
|
|
54
|
+
args, kwargs, link, link_error, task_id, retries, throw, logfile, loglevel, headers, **options
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
def apply_async(
|
|
58
|
+
self, args=None, kwargs=None, task_id=None, producer=None, link=None, link_error=None, shadow=None, **options
|
|
59
|
+
):
|
|
60
|
+
"""Pass the tenant name from the context in the kwargs."""
|
|
61
|
+
|
|
62
|
+
if kwargs is None:
|
|
63
|
+
kwargs = {}
|
|
64
|
+
|
|
65
|
+
if TENANT_KEY not in kwargs:
|
|
66
|
+
tenant = TenantContext.get()
|
|
67
|
+
kwargs[TENANT_KEY] = tenant
|
|
68
|
+
|
|
69
|
+
return super().apply_async(args, kwargs, task_id, producer, link, link_error, shadow, **options)
|
|
70
|
+
|
|
30
71
|
def __call__(self, *args, **kwargs):
|
|
31
|
-
"""
|
|
72
|
+
"""Use the tenant name from the kwargs to update the context."""
|
|
32
73
|
|
|
33
74
|
# Only clear the lock before the task's execution if the
|
|
34
75
|
# "unlock_before_run" option is True
|
|
@@ -43,7 +84,8 @@ class TenantAwareTask(TaskClass):
|
|
|
43
84
|
return self.run(*args, **kwargs)
|
|
44
85
|
|
|
45
86
|
def after_return(self, status, retval, task_id, args, kwargs, einfo):
|
|
46
|
-
"""Clear the tenant from the
|
|
87
|
+
"""Clear the tenant from the context after the task has returned."""
|
|
88
|
+
|
|
47
89
|
TenantContext.clear()
|
|
48
90
|
super().after_return(status, retval, task_id, args, kwargs, einfo)
|
|
49
91
|
|
|
@@ -67,7 +109,7 @@ class TenantAwareTask(TaskClass):
|
|
|
67
109
|
tenant_kwarg = {TENANT_KEY: tenant}
|
|
68
110
|
task_call_args = super()._get_call_args(args, _kwargs)
|
|
69
111
|
|
|
70
|
-
# Add the tenant kwarg back to the return value
|
|
112
|
+
# Add the tenant kwarg back to the return value
|
|
71
113
|
# since this value is being used to create the key for the lock.
|
|
72
114
|
# We want to lock the task for the tenant that is running it.
|
|
73
115
|
return task_call_args | tenant_kwarg
|
{cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/db/utils.py
RENAMED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from functools import reduce
|
|
2
2
|
import json
|
|
3
3
|
import os
|
|
4
|
-
from typing import
|
|
4
|
+
from typing import TypedDict
|
|
5
5
|
from django.db import connections
|
|
6
6
|
|
|
7
7
|
|
|
@@ -10,7 +10,7 @@ class DatabaseConfigData(TypedDict):
|
|
|
10
10
|
name: str
|
|
11
11
|
user: str
|
|
12
12
|
password: str
|
|
13
|
-
port:
|
|
13
|
+
port: int | None
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
def get_connection(tenant: str = None):
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
from django.core.management.commands.showmigrations import Command as ShowMigrationsCommand
|
|
2
|
+
|
|
3
|
+
from ...settings import TENANT_DATABASES
|
|
4
|
+
from ...tenant_context import TenantContext
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Command(ShowMigrationsCommand):
|
|
8
|
+
help = "Shows all available migrations for a specific tenant."
|
|
9
|
+
|
|
10
|
+
def add_arguments(self, parser):
|
|
11
|
+
super().add_arguments(parser)
|
|
12
|
+
|
|
13
|
+
parser.add_argument(
|
|
14
|
+
"--tenant",
|
|
15
|
+
action="store",
|
|
16
|
+
dest="tenant",
|
|
17
|
+
help="Specify the tenant to show migrations for, either a single tenant name or 'all'.",
|
|
18
|
+
required=True,
|
|
19
|
+
type=str,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
def handle(self, *args, **options):
|
|
23
|
+
tenant = options["tenant"]
|
|
24
|
+
|
|
25
|
+
if tenant.lower() == "all":
|
|
26
|
+
tenants_to_use = list(TENANT_DATABASES)
|
|
27
|
+
else:
|
|
28
|
+
if tenant not in TENANT_DATABASES:
|
|
29
|
+
self.stdout.write(self.style.ERROR(f"Tenant '{tenant}' not found in DATABASES settings."))
|
|
30
|
+
return
|
|
31
|
+
tenants_to_use = [tenant]
|
|
32
|
+
|
|
33
|
+
for t in tenants_to_use:
|
|
34
|
+
self.stdout.write(self.style.MIGRATE_LABEL(f"\n=== Tenant: {t} ==="))
|
|
35
|
+
options["database"] = t
|
|
36
|
+
with TenantContext(t):
|
|
37
|
+
super().handle(*args, **options)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/data_structures.py
RENAMED
|
File without changes
|
|
File without changes
|
{cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/__init__.py
RENAMED
|
File without changes
|
{cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/admin/__init__.py
RENAMED
|
File without changes
|
{cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/admin/auth.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/admin/views.py
RENAMED
|
File without changes
|
{cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/api/__init__.py
RENAMED
|
File without changes
|
{cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/api/utils.py
RENAMED
|
File without changes
|
|
File without changes
|
{cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/auth/service.py
RENAMED
|
File without changes
|
{cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/celery/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/db/__init__.py
RENAMED
|
File without changes
|
{cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/db/alias.py
RENAMED
|
File without changes
|
{cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/db/routers.py
RENAMED
|
File without changes
|
{cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/db/transaction.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/models/__init__.py
RENAMED
|
File without changes
|
{cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/models/user.py
RENAMED
|
File without changes
|
|
File without changes
|
{cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/oidc_settings.py
RENAMED
|
File without changes
|
{cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/redis/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/settings.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/tenant_context.py
RENAMED
|
File without changes
|
{cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/tests/__init__.py
RENAMED
|
File without changes
|
{cardo_python_utils-0.5.dev50 → cardo_python_utils-0.5.dev53}/python_utils/django/tests/conftest.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|