dbca-utils 2.0.3__tar.gz → 2.1.0__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.
@@ -1,31 +1,34 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: dbca-utils
3
- Version: 2.0.3
3
+ Version: 2.1.0
4
4
  Summary: Utilities for DBCA Django apps
5
- License: Apache-2.0
6
- Author: Rocky Chen
7
- Author-email: rocky.chen@dbca.wa.gov.au
8
- Requires-Python: >=3.9,<4.0
9
- Classifier: Development Status :: 5 - Production/Stable
10
- Classifier: Environment :: Web Environment
5
+ Author-email: Rocky Chen <rocky.chen@dbca.wa.gov.au>, Ashley Felton <ashley.felton@dbca.wa.gov.au>
6
+ Project-URL: Homepage, https://github.com/dbca-wa/dbca-utils
7
+ Project-URL: Repository, https://github.com/dbca-wa/dbca-utils.git
8
+ Project-URL: Changelog, https://github.com/dbca-wa/dbca-utils/blob/master/CHANGELOG.md
9
+ Project-URL: GitHub, https://github.com/dbca-wa/dbca-utils
11
10
  Classifier: Framework :: Django
12
- Classifier: Framework :: Django :: 3.2
13
11
  Classifier: Framework :: Django :: 4.0
14
12
  Classifier: Framework :: Django :: 4.2
15
13
  Classifier: Framework :: Django :: 5.0
14
+ Classifier: Framework :: Django :: 5.2
15
+ Classifier: Environment :: Web Environment
16
16
  Classifier: Intended Audience :: Developers
17
+ Classifier: Development Status :: 5 - Production/Stable
17
18
  Classifier: License :: OSI Approved :: Apache Software License
18
19
  Classifier: Programming Language :: Python
19
20
  Classifier: Programming Language :: Python :: 3
20
- Classifier: Programming Language :: Python :: 3.9
21
21
  Classifier: Programming Language :: Python :: 3.10
22
22
  Classifier: Programming Language :: Python :: 3.11
23
23
  Classifier: Programming Language :: Python :: 3.12
24
24
  Classifier: Programming Language :: Python :: 3.13
25
25
  Classifier: Topic :: Software Development :: Libraries
26
26
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
27
- Requires-Dist: django (>=3.2,<5.1)
27
+ Requires-Python: <4.0,>=3.10
28
28
  Description-Content-Type: text/markdown
29
+ License-File: LICENSE
30
+ Requires-Dist: django<6,>=4
31
+ Dynamic: license-file
29
32
 
30
33
  # Overview
31
34
 
@@ -33,30 +36,43 @@ DBCA Django utility classes and functions.
33
36
 
34
37
  ## Development
35
38
 
36
- This project for development is using
37
- [Poetry](https://python-poetry.org/docs/) to install and manage a virtual Python
38
- environment. With Poetry installed, change into the project directory and run:
39
+ The recommended way to set up this project for development is using
40
+ [uv](https://docs.astral.sh/uv/)
41
+ to install and manage a Python virtual environment.
42
+ With uv installed, install the required Python version (see `pyproject.toml`). Example:
43
+
44
+ uv python install 3.12
39
45
 
40
- poetry install
46
+ Change into the project directory and run:
47
+
48
+ uv python pin 3.12
49
+ uv sync
41
50
 
42
51
  Activate the virtualenv like so:
43
52
 
44
- poetry shell
53
+ source .venv/bin/activate
45
54
 
46
55
  Run unit tests using `pytest` (or `tox`, to test against multiple Python versions):
47
56
 
48
- pytest -v
57
+ pytest -sv
49
58
  tox -v
50
59
 
51
60
  ## Releases
52
61
 
53
62
  Tagged releases are built and pushed to PyPI automatically using a GitHub
54
63
  workflow in the project. Update the project version in `pyproject.toml` and
55
- tag the required commit with the same value to trigger a release.
64
+ tag the required commit with the same value to trigger a release. Packages
65
+ can also be built and uploaded manually, if desired.
66
+
67
+ Build the project locally using uv, [publish to the PyPI registry](https://docs.astral.sh/uv/guides/publish/#publishing-your-package)
68
+ using the same tool if you require:
69
+
70
+ uv build
71
+ uv publish
56
72
 
57
73
  ## Installation
58
74
 
59
- 1. Install via pip/Poetry/etc.: `pip install dbca-utils`
75
+ 1. Install via pip/etc.: `pip install dbca-utils`
60
76
 
61
77
  ## SSO Login Middleware
62
78
 
@@ -89,8 +105,7 @@ MIDDLEWARE = [
89
105
 
90
106
  `AuditMixin` is an extension of `Django.db.model.Model` that adds a number of additional fields:
91
107
 
92
- - creator - FK to `AUTH_USER_MODEL`, used to record the object creator
93
- - modifier - FK to `AUTH_USER_MODEL`, used to record who the object was last modified by
94
- - created - a timestamp that is set on initial object save
95
- - modified - an auto-updating timestamp (on each object save)
96
-
108
+ - `creator` - FK to `AUTH_USER_MODEL`, used to record the object creator
109
+ - `modifier` - FK to `AUTH_USER_MODEL`, used to record who the object was last modified by
110
+ - `created` - a timestamp that is set on initial object save
111
+ - `modified` - an auto-updating timestamp (on each object save)
@@ -4,30 +4,43 @@ DBCA Django utility classes and functions.
4
4
 
5
5
  ## Development
6
6
 
7
- This project for development is using
8
- [Poetry](https://python-poetry.org/docs/) to install and manage a virtual Python
9
- environment. With Poetry installed, change into the project directory and run:
7
+ The recommended way to set up this project for development is using
8
+ [uv](https://docs.astral.sh/uv/)
9
+ to install and manage a Python virtual environment.
10
+ With uv installed, install the required Python version (see `pyproject.toml`). Example:
10
11
 
11
- poetry install
12
+ uv python install 3.12
13
+
14
+ Change into the project directory and run:
15
+
16
+ uv python pin 3.12
17
+ uv sync
12
18
 
13
19
  Activate the virtualenv like so:
14
20
 
15
- poetry shell
21
+ source .venv/bin/activate
16
22
 
17
23
  Run unit tests using `pytest` (or `tox`, to test against multiple Python versions):
18
24
 
19
- pytest -v
25
+ pytest -sv
20
26
  tox -v
21
27
 
22
28
  ## Releases
23
29
 
24
30
  Tagged releases are built and pushed to PyPI automatically using a GitHub
25
31
  workflow in the project. Update the project version in `pyproject.toml` and
26
- tag the required commit with the same value to trigger a release.
32
+ tag the required commit with the same value to trigger a release. Packages
33
+ can also be built and uploaded manually, if desired.
34
+
35
+ Build the project locally using uv, [publish to the PyPI registry](https://docs.astral.sh/uv/guides/publish/#publishing-your-package)
36
+ using the same tool if you require:
37
+
38
+ uv build
39
+ uv publish
27
40
 
28
41
  ## Installation
29
42
 
30
- 1. Install via pip/Poetry/etc.: `pip install dbca-utils`
43
+ 1. Install via pip/etc.: `pip install dbca-utils`
31
44
 
32
45
  ## SSO Login Middleware
33
46
 
@@ -60,7 +73,7 @@ MIDDLEWARE = [
60
73
 
61
74
  `AuditMixin` is an extension of `Django.db.model.Model` that adds a number of additional fields:
62
75
 
63
- - creator - FK to `AUTH_USER_MODEL`, used to record the object creator
64
- - modifier - FK to `AUTH_USER_MODEL`, used to record who the object was last modified by
65
- - created - a timestamp that is set on initial object save
66
- - modified - an auto-updating timestamp (on each object save)
76
+ - `creator` - FK to `AUTH_USER_MODEL`, used to record the object creator
77
+ - `modifier` - FK to `AUTH_USER_MODEL`, used to record who the object was last modified by
78
+ - `created` - a timestamp that is set on initial object save
79
+ - `modified` - an auto-updating timestamp (on each object save)
@@ -1,51 +1,47 @@
1
- [tool.poetry]
1
+ [project]
2
2
  name = "dbca-utils"
3
- version = "2.0.3"
3
+ version = "2.1.0"
4
4
  description = "Utilities for DBCA Django apps"
5
5
  authors = [
6
- "Rocky Chen <rocky.chen@dbca.wa.gov.au>",
7
- "Ashley Felton <ashley.felton@dbca.wa.gov.au>",
6
+ { name = "Rocky Chen", email = "rocky.chen@dbca.wa.gov.au" },
7
+ { name = "Ashley Felton", email = "ashley.felton@dbca.wa.gov.au" },
8
8
  ]
9
- license = "Apache-2.0"
10
9
  readme = "README.md"
11
10
  classifiers = [
12
11
  "Framework :: Django",
13
- "Framework :: Django :: 3.2",
14
12
  "Framework :: Django :: 4.0",
15
13
  "Framework :: Django :: 4.2",
16
14
  "Framework :: Django :: 5.0",
15
+ "Framework :: Django :: 5.2",
17
16
  "Environment :: Web Environment",
18
17
  "Intended Audience :: Developers",
19
18
  "Development Status :: 5 - Production/Stable",
20
19
  "License :: OSI Approved :: Apache Software License",
21
20
  "Programming Language :: Python",
22
21
  "Programming Language :: Python :: 3",
23
- "Programming Language :: Python :: 3.9",
24
22
  "Programming Language :: Python :: 3.10",
25
23
  "Programming Language :: Python :: 3.11",
26
24
  "Programming Language :: Python :: 3.12",
25
+ "Programming Language :: Python :: 3.13",
27
26
  "Topic :: Software Development :: Libraries",
28
27
  "Topic :: Software Development :: Libraries :: Python Modules",
29
28
  ]
30
-
31
-
32
- [tool.poetry.group.dev.dependencies]
33
- pytest-django = "^4.9.0"
34
- pytest-sugar = "^1.0.0"
35
- tox = "^4.23.2"
29
+ requires-python = ">=3.10,<4.0"
30
+ dependencies = ["django>=4,<6"]
36
31
 
37
32
  [project.urls]
38
- homepage = "https://github.com/dbca-wa/dbca-utils"
39
- source = "https://github.com/dbca-wa/dbca-utils.git"
40
- changelog = "https://github.com/dbca-wa/dbca-utils/blob/master/CHANGELOG.md"
33
+ Homepage = "https://github.com/dbca-wa/dbca-utils"
34
+ Repository = "https://github.com/dbca-wa/dbca-utils.git"
35
+ Changelog = "https://github.com/dbca-wa/dbca-utils/blob/master/CHANGELOG.md"
36
+ GitHub = "https://github.com/dbca-wa/dbca-utils"
41
37
 
42
- [tool.poetry.dependencies]
43
- python = "^3.9"
44
- django = ">=3.2,<5.1"
45
-
46
- [build-system]
47
- requires = ["poetry-core"]
48
- build-backend = "poetry.core.masonry.api"
38
+ [dependency-groups]
39
+ dev = [
40
+ "pytest-django>=4.11.0",
41
+ "pytest-sugar>=1.0.0",
42
+ "tox>=4.25.0",
43
+ "tox-uv>=1.25.0",
44
+ ]
49
45
 
50
46
  [tool.pytest.ini_options]
51
47
  # https://pytest-django.readthedocs.io/en/latest/configuring_django.html#pyproject-toml-settings
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -1,10 +1,10 @@
1
- from django import http, VERSION
1
+ from django import http
2
2
  from django.conf import settings
3
- from django.contrib.auth import login, logout, get_user_model
3
+ from django.contrib.auth import get_user_model, login, logout
4
+ from django.contrib.auth.middleware import AuthenticationMiddleware, get_user
5
+ from django.utils import timezone
4
6
  from django.utils.deprecation import MiddlewareMixin
5
7
  from django.utils.functional import SimpleLazyObject
6
- from django.utils import timezone
7
- from django.contrib.auth.middleware import AuthenticationMiddleware, get_user
8
8
 
9
9
  from dbca_utils.utils import env
10
10
 
@@ -17,10 +17,14 @@ def sync_usergroups(user, groups):
17
17
  from django.contrib.auth.models import Group
18
18
 
19
19
  usergroups = (
20
- [Group.objects.get_or_create(name=name)[0] for name in groups.split(",")] if groups else []
20
+ [Group.objects.get_or_create(name=name)[0] for name in groups.split(",")]
21
+ if groups
22
+ else []
21
23
  )
22
24
  usergroups.sort(key=lambda o: o.id)
23
- existing_usergroups = list(user.groups.exclude(name__in=LOCAL_USERGROUPS).order_by("id"))
25
+ existing_usergroups = list(
26
+ user.groups.exclude(name__in=LOCAL_USERGROUPS).order_by("id")
27
+ )
24
28
  index1 = 0
25
29
  index2 = 0
26
30
  len1 = len(usergroups)
@@ -96,7 +100,6 @@ class SSOLoginMiddleware(MiddlewareMixin):
96
100
  """
97
101
 
98
102
  def process_request(self, request):
99
-
100
103
  # Logout headers included with request.
101
104
  if (
102
105
  (
@@ -118,10 +121,7 @@ class SSOLoginMiddleware(MiddlewareMixin):
118
121
  # auth2 not enabled
119
122
  return
120
123
 
121
- if VERSION < (2, 0):
122
- user_authenticated = request.user.is_authenticated()
123
- else:
124
- user_authenticated = request.user.is_authenticated
124
+ user_authenticated = request.user.is_authenticated
125
125
 
126
126
  # Auth2 is enabled.
127
127
  # Request user is not authenticated.
@@ -158,7 +158,9 @@ class SSOLoginMiddleware(MiddlewareMixin):
158
158
  user = User.objects.filter(email__iexact=attributemap["email"])[0]
159
159
  elif (
160
160
  User.__name__ != "EmailUser"
161
- and User.objects.filter(username__iexact=attributemap["username"]).exists()
161
+ and User.objects.filter(
162
+ username__iexact=attributemap["username"]
163
+ ).exists()
162
164
  ):
163
165
  user = User.objects.filter(username__iexact=attributemap["username"])[0]
164
166
  else:
@@ -1,15 +1,23 @@
1
- import ast
2
1
  import os
2
+ from ast import literal_eval
3
3
 
4
4
 
5
5
  def env(key, default=None, required=False, value_type=None):
6
6
  """
7
7
  Retrieves environment variables and returns Python natives. The (optional)
8
- default will be returned if the environment variable does not exist.
8
+ `default` value will be returned if the environment variable does not exist.
9
+ Setting `required` will cause an Exception to be thrown if the variable does
10
+ not exist.
11
+ Setting `value_type` will try to ensure that the returned value is of the
12
+ nominated type (within reason).
13
+ Supported Python object types: str, list, tuple, bool, int, float.
9
14
  """
15
+ value = None
16
+
10
17
  try:
11
18
  value = os.environ[key]
12
- value = ast.literal_eval(value)
19
+ # Evaluate the environment variable value as a Python object.
20
+ value = literal_eval(value)
13
21
  except (SyntaxError, ValueError):
14
22
  pass
15
23
  except KeyError:
@@ -17,14 +25,17 @@ def env(key, default=None, required=False, value_type=None):
17
25
  return default
18
26
  raise Exception(f"Missing required environment variable {key}")
19
27
 
20
- if value_type is None:
21
- if default is not None:
22
- value_type = default.__class__
28
+ if value_type is None and default is not None:
29
+ # If we've passed a default return value but not set a value_type, use the
30
+ # default's type.
31
+ value_type = default.__class__
23
32
 
24
33
  if value_type is None:
25
34
  return value
26
35
  elif isinstance(value, value_type):
27
36
  return value
37
+ elif issubclass(value_type, str):
38
+ return str(value)
28
39
  elif issubclass(value_type, list):
29
40
  if isinstance(value, tuple):
30
41
  return list(value)
@@ -53,7 +64,7 @@ def env(key, default=None, required=False, value_type=None):
53
64
  return False
54
65
  else:
55
66
  raise Exception(
56
- f"{key} is a boolean environment variable and only accepts 'true' ,'false' and '' (case-insensitive), but the configured value is '{value}'"
67
+ f"{key} is a boolean environment variable and only accepts 'true', 'false' or '' (case-insensitive), but the configured value is '{value}'"
57
68
  )
58
69
  elif issubclass(value_type, int):
59
70
  return int(value)
@@ -61,5 +72,5 @@ def env(key, default=None, required=False, value_type=None):
61
72
  return float(value)
62
73
  else:
63
74
  raise Exception(
64
- f"{key} is a {value_type} environment variable, but {value_type} is not supported now"
75
+ f"{key} is a {value_type} environment variable, but {value_type} is not supported"
65
76
  )
@@ -0,0 +1,111 @@
1
+ Metadata-Version: 2.4
2
+ Name: dbca-utils
3
+ Version: 2.1.0
4
+ Summary: Utilities for DBCA Django apps
5
+ Author-email: Rocky Chen <rocky.chen@dbca.wa.gov.au>, Ashley Felton <ashley.felton@dbca.wa.gov.au>
6
+ Project-URL: Homepage, https://github.com/dbca-wa/dbca-utils
7
+ Project-URL: Repository, https://github.com/dbca-wa/dbca-utils.git
8
+ Project-URL: Changelog, https://github.com/dbca-wa/dbca-utils/blob/master/CHANGELOG.md
9
+ Project-URL: GitHub, https://github.com/dbca-wa/dbca-utils
10
+ Classifier: Framework :: Django
11
+ Classifier: Framework :: Django :: 4.0
12
+ Classifier: Framework :: Django :: 4.2
13
+ Classifier: Framework :: Django :: 5.0
14
+ Classifier: Framework :: Django :: 5.2
15
+ Classifier: Environment :: Web Environment
16
+ Classifier: Intended Audience :: Developers
17
+ Classifier: Development Status :: 5 - Production/Stable
18
+ Classifier: License :: OSI Approved :: Apache Software License
19
+ Classifier: Programming Language :: Python
20
+ Classifier: Programming Language :: Python :: 3
21
+ Classifier: Programming Language :: Python :: 3.10
22
+ Classifier: Programming Language :: Python :: 3.11
23
+ Classifier: Programming Language :: Python :: 3.12
24
+ Classifier: Programming Language :: Python :: 3.13
25
+ Classifier: Topic :: Software Development :: Libraries
26
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
27
+ Requires-Python: <4.0,>=3.10
28
+ Description-Content-Type: text/markdown
29
+ License-File: LICENSE
30
+ Requires-Dist: django<6,>=4
31
+ Dynamic: license-file
32
+
33
+ # Overview
34
+
35
+ DBCA Django utility classes and functions.
36
+
37
+ ## Development
38
+
39
+ The recommended way to set up this project for development is using
40
+ [uv](https://docs.astral.sh/uv/)
41
+ to install and manage a Python virtual environment.
42
+ With uv installed, install the required Python version (see `pyproject.toml`). Example:
43
+
44
+ uv python install 3.12
45
+
46
+ Change into the project directory and run:
47
+
48
+ uv python pin 3.12
49
+ uv sync
50
+
51
+ Activate the virtualenv like so:
52
+
53
+ source .venv/bin/activate
54
+
55
+ Run unit tests using `pytest` (or `tox`, to test against multiple Python versions):
56
+
57
+ pytest -sv
58
+ tox -v
59
+
60
+ ## Releases
61
+
62
+ Tagged releases are built and pushed to PyPI automatically using a GitHub
63
+ workflow in the project. Update the project version in `pyproject.toml` and
64
+ tag the required commit with the same value to trigger a release. Packages
65
+ can also be built and uploaded manually, if desired.
66
+
67
+ Build the project locally using uv, [publish to the PyPI registry](https://docs.astral.sh/uv/guides/publish/#publishing-your-package)
68
+ using the same tool if you require:
69
+
70
+ uv build
71
+ uv publish
72
+
73
+ ## Installation
74
+
75
+ 1. Install via pip/etc.: `pip install dbca-utils`
76
+
77
+ ## SSO Login Middleware
78
+
79
+ This will automatically login and create users using headers from an upstream proxy (REMOTE_USER and some others).
80
+ The logout view will redirect to a separate logout page which clears the SSO session.
81
+
82
+ ### Usage
83
+
84
+ Add `dbca_utils.middleware.SSOLoginMiddleware` to `settings.MIDDLEWARE` (after both of
85
+ `django.contrib.sessions.middleware.SessionMiddleware` and
86
+ `django.contrib.auth.middleware.AuthenticationMiddleware`.
87
+ Ensure that `AUTHENTICATION_BACKENDS` contains `django.contrib.auth.backends.ModelBackend`,
88
+ as this middleware depends on it for retrieving the logged in user for a session.
89
+ Note that the middleware will still work without it, but will reauthenticate the session
90
+ on every request, and `request.user.is_authenticated` won't work properly/will be false.
91
+
92
+ Example:
93
+
94
+ ```python
95
+ MIDDLEWARE = [
96
+ ...,
97
+ 'django.contrib.sessions.middleware.SessionMiddleware',
98
+ 'django.contrib.auth.middleware.AuthenticationMiddleware',
99
+ 'dbca_utils.middleware.SSOLoginMiddleware'
100
+ ...,
101
+ ]
102
+ ```
103
+
104
+ ## Audit model mixin
105
+
106
+ `AuditMixin` is an extension of `Django.db.model.Model` that adds a number of additional fields:
107
+
108
+ - `creator` - FK to `AUTH_USER_MODEL`, used to record the object creator
109
+ - `modifier` - FK to `AUTH_USER_MODEL`, used to record who the object was last modified by
110
+ - `created` - a timestamp that is set on initial object save
111
+ - `modified` - an auto-updating timestamp (on each object save)
@@ -0,0 +1,13 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ src/dbca_utils/__init__.py
5
+ src/dbca_utils/middleware.py
6
+ src/dbca_utils/models.py
7
+ src/dbca_utils/utils.py
8
+ src/dbca_utils.egg-info/PKG-INFO
9
+ src/dbca_utils.egg-info/SOURCES.txt
10
+ src/dbca_utils.egg-info/dependency_links.txt
11
+ src/dbca_utils.egg-info/requires.txt
12
+ src/dbca_utils.egg-info/top_level.txt
13
+ tests/tests.py
@@ -0,0 +1 @@
1
+ django<6,>=4
@@ -0,0 +1 @@
1
+ dbca_utils
@@ -0,0 +1,111 @@
1
+ import os
2
+ import random
3
+ import string
4
+
5
+ import pytest
6
+ from django.contrib.auth.models import User
7
+ from django.test import TestCase
8
+ from django.test.client import Client
9
+ from django.urls import reverse
10
+
11
+ from dbca_utils.utils import env
12
+
13
+ from .models import TestModel
14
+
15
+ # Define an environment variable for testing.
16
+ letters = string.ascii_letters
17
+ TEST_VAR = "".join(random.choice(letters) for _ in range(128))
18
+ TEST_NAME = "".join(random.choice(letters) for _ in range(128))
19
+ os.environ["TEST_ENVIRONMENT_VAR"] = TEST_VAR
20
+
21
+ os.environ["TEST_STR"] = "string"
22
+ os.environ["TEST_INT"] = "42"
23
+ os.environ["TEST_FLOAT"] = "3.14159"
24
+ os.environ["TEST_LIST"] = "[1,2,3,4,5]"
25
+ os.environ["TEST_TUPLE"] = "('a', 'b', 'c')"
26
+ os.environ["TEST_BOOL"] = "False"
27
+
28
+
29
+ class TestUtils(TestCase):
30
+ def test_env_returns_str(self):
31
+ test_str = env("TEST_STR")
32
+ self.assertTrue(isinstance(test_str, str))
33
+
34
+ def test_env_returns_int(self):
35
+ test_int = env("TEST_INT")
36
+ self.assertTrue(isinstance(test_int, int))
37
+
38
+ def test_env_returns_float(self):
39
+ test_float = env("TEST_FLOAT")
40
+ self.assertTrue(isinstance(test_float, float))
41
+
42
+ def test_env_returns_list(self):
43
+ test_list = env("TEST_LIST")
44
+ self.assertTrue(isinstance(test_list, list))
45
+
46
+ def test_env_returns_tuple(self):
47
+ test_tuple = env("TEST_TUPLE")
48
+ self.assertTrue(isinstance(test_tuple, tuple))
49
+
50
+ def test_env_returns_bool(self):
51
+ test_bool = env("TEST_BOOL")
52
+ self.assertTrue(isinstance(test_bool, bool))
53
+
54
+ def test_env_returns_default(self):
55
+ test_str = env("TEST_MISSING", "foo")
56
+ self.assertTrue(isinstance(test_str, str))
57
+
58
+ def test_env_missing_not_required_no_default(self):
59
+ test_env = env("TEST_MISSING")
60
+ self.assertIsNone(test_env)
61
+
62
+ def test_env_required_throws_exception(self):
63
+ with pytest.raises(Exception):
64
+ env("TEST_MISSING_REQUIRED", required=True)
65
+
66
+ def test_env_returns_other_as_str(self):
67
+ test_str = env("TEST_FLOAT", value_type=str)
68
+ self.assertTrue(isinstance(test_str, str))
69
+
70
+
71
+ class TestModelTests(TestCase):
72
+ client = Client()
73
+ model = TestModel
74
+
75
+ def setUp(self):
76
+ self.user = User.objects.create_user(
77
+ username="test", email="test@email.com", password="secret"
78
+ )
79
+ self.test_model = TestModel.objects.create(name=TEST_NAME)
80
+ self.client.login(username="test", password="secret")
81
+
82
+ def tearDown(self):
83
+ self.user.delete()
84
+
85
+ def test_model_fields(self):
86
+ """Test a model inheriting from mixins has the required fields."""
87
+ self.assertTrue(hasattr(self.test_model, "effective_to"))
88
+ self.assertTrue(hasattr(self.test_model, "creator"))
89
+ self.assertTrue(hasattr(self.test_model, "modifier"))
90
+ self.assertTrue(hasattr(self.test_model, "created"))
91
+ self.assertTrue(hasattr(self.test_model, "modified"))
92
+
93
+ def test_active_mixin(self):
94
+ """Test the ActiveMixin manager methods."""
95
+ obj_del = TestModel.objects.create(name="Deleted object")
96
+ obj_del.delete()
97
+ all_pks = [i.pk for i in TestModel.objects.all()]
98
+ current_pks = [i.pk for i in TestModel.objects.current()]
99
+ del_pks = [i.pk for i in TestModel.objects.deleted()]
100
+ self.assertTrue(obj_del.pk in all_pks)
101
+ self.assertFalse(obj_del.pk in current_pks)
102
+ self.assertTrue(obj_del.pk in del_pks)
103
+ self.assertFalse(self.test_model.pk in del_pks)
104
+
105
+ def test_url_request_returns_view(self):
106
+ """Test the env() utility method works as expected."""
107
+ url = reverse("test_model_list")
108
+ response = self.client.get(url)
109
+ self.assertEqual(response.status_code, 200)
110
+ self.assertContains(response, TEST_VAR)
111
+ self.assertContains(response, TEST_NAME)
File without changes