Repository: joke2k/django-environ
Pull request #511 (2023-11-25 11:47:14)

Add support for Django CockroachDB driver
As per https://github.com/joke2k/django-environ/issues/509 adds support for Django CockroachDB

stevewilliamsuk: @joke2k could you please help us out with some feedback on this PR?
stevewilliamsuk: @sergeyklay are you able to help us out with some feedback/approval on this PR?
pataquets: Tip: those wanting to try the PR real quick "straight-from-this-PR", just add this line to your dependencies (ie. `requirements.txt`):
```
git+https://github.com/joke2k/django-environ@refs/pull/511/head
```

Patch:
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 4e28fa5..342d5ce 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -24,12 +24,12 @@ jobs:
 
     steps:
       - name: Checkout code
-        uses: actions/checkout@v4.1.1
+        uses: actions/checkout@v4.2.2
 
-      - name: Set up Python 3.10
-        uses: actions/setup-python@v4.7.1
+      - name: Set up Python 3.12
+        uses: actions/setup-python@v5.3.0
         with:
-          python-version: '3.10'
+          python-version: '3.12'
 
       - name: Install dependencies
         run: |
@@ -44,7 +44,7 @@ jobs:
 
       - name: Archive build artifacts
         if: success()
-        uses: actions/upload-artifact@v3
+        uses: actions/upload-artifact@v4
         with:
           # To ensure that jobs don't overwrite existing artifacts,
           # use a different name per job.
@@ -64,12 +64,12 @@ jobs:
 
     steps:
       - name: Checkout code
-        uses: actions/checkout@v4.1.1
+        uses: actions/checkout@v4.2.2
 
-      - name: Set up Python 3.10
-        uses: actions/setup-python@v4.7.1
+      - name: Set up Python 3.12
+        uses: actions/setup-python@v5.3.0
         with:
-          python-version: '3.10'
+          python-version: '3.12'
 
       - name: Install in dev mode
         run: python -m pip install -e .
diff --git a/.github/workflows/change-pr-target.yml b/.github/workflows/change-pr-target.yml
index eb12a30..af419d1 100644
--- a/.github/workflows/change-pr-target.yml
+++ b/.github/workflows/change-pr-target.yml
@@ -8,7 +8,7 @@ jobs:
   check-branch:
     runs-on: ubuntu-latest
     steps:
-      - uses: Vankka/pr-target-branch-action@v2
+      - uses: Vankka/pr-target-branch-action@v3
         env:
           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
         with:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 1fe3f1d..0d80bfe 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -47,32 +47,22 @@ jobs:
 
       matrix:
         python:
-          - '3.8'
           - '3.9'
           - '3.10'
           - '3.11'
           - '3.12'
-          - 'pypy-3.7'
+          - '3.13'
+          - 'pypy-3.10'
         os: [ ubuntu-latest, macos-latest, windows-latest ]
 
-        # These versions are no longer supported by Python team, and may
-        # eventually be dropped from GitHub Actions.  The support of these
-        # versions by django-environ will continue for as long as possible,
-        # and may be discontinued at any time.
-        include:
-          - python: '3.6'
-            os: ubuntu-20.04
-          - python: '3.7'
-            os: ubuntu-20.04
-
     steps:
       - name: Checkout code
-        uses: actions/checkout@v4.1.1
+        uses: actions/checkout@v4.2.2
         with:
           fetch-depth: 5
 
       - name: Set up Python ${{ matrix.python }}
-        uses: actions/setup-python@v4.7.1
+        uses: actions/setup-python@v5.3.0
         with:
           python-version: ${{ matrix.python }}
 
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
index 460c1e3..d8236f3 100644
--- a/.github/workflows/codeql.yml
+++ b/.github/workflows/codeql.yml
@@ -45,16 +45,16 @@ jobs:
 
     steps:
     - name: Checkout repository
-      uses: actions/checkout@v4.1.1
+      uses: actions/checkout@v4.2.2
 
     # Initializes the CodeQL tools for scanning.
     - name: Initialize CodeQL
-      uses: github/codeql-action/init@v2
+      uses: github/codeql-action/init@v3
       with:
         languages: ${{ matrix.language }}
         
     - name: Autobuild
-      uses: github/codeql-action/autobuild@v2
+      uses: github/codeql-action/autobuild@v3
 
     - name: Perform CodeQL Analysis
-      uses: github/codeql-action/analyze@v2
+      uses: github/codeql-action/analyze@v3
diff --git a/.github/workflows/cs.yml b/.github/workflows/cs.yml
index 4daad7d..30d41b9 100644
--- a/.github/workflows/cs.yml
+++ b/.github/workflows/cs.yml
@@ -25,12 +25,12 @@ jobs:
 
     steps:
       - name: Checkout code
-        uses: actions/checkout@v4.1.1
+        uses: actions/checkout@v4.2.2
 
-      - name: Set up Python 3.10
-        uses: actions/setup-python@v4.7.1
+      - name: Set up Python 3.12
+        uses: actions/setup-python@v5.3.0
         with:
-          python-version: '3.10'
+          python-version: '3.12'
 
       - name: Install dependencies
         run: |
diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
index efef795..0ae19c3 100644
--- a/.github/workflows/docs.yml
+++ b/.github/workflows/docs.yml
@@ -26,12 +26,12 @@ jobs:
 
     steps:
       - name: Checkout code
-        uses: actions/checkout@v4.1.1
+        uses: actions/checkout@v4.2.2
 
-      - name: Set up Python 3.10
-        uses: actions/setup-python@v4.7.1
+      - name: Set up Python 3.12
+        uses: actions/setup-python@v5.3.0
         with:
-          python-version: '3.10'
+          python-version: '3.12'
 
       - name: Install dependencies
         run: |
@@ -46,7 +46,7 @@ jobs:
 
       - name: Archive docs artifacts
         if: always()
-        uses: actions/upload-artifact@v3
+        uses: actions/upload-artifact@v4
         with:
           name: docs
           path: docs
diff --git a/.readthedocs.yml b/.readthedocs.yml
index 27f9368..191e999 100644
--- a/.readthedocs.yml
+++ b/.readthedocs.yml
@@ -1,6 +1,6 @@
 # This file is part of the django-environ.
 #
-# Copyright (c) 2021, Serghei Iakovlev <egrep@protonmail.ch>
+# Copyright (c) 2021-2024, Serghei Iakovlev <oss@serghei.pl>
 # Copyright (c) 2013-2021, Daniele Faraglia <daniele.faraglia@gmail.com>
 #
 # For the full copyright and license information, please view
@@ -17,7 +17,7 @@ build:
   tools:
     # Keep version in sync with tox.ini (testenv:docs) and
     # docs.yml (GitHub Action Workflow).
-    python: '3.10'
+    python: '3.12'
 
 python:
   install:
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 6051aa4..a4403a1 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -5,16 +5,34 @@ All notable changes to this project will be documented in this file.
 The format is inspired by `Keep a Changelog <https://keepachangelog.com/en/1.0.0/>`_
 and this project adheres to `Semantic Versioning <https://semver.org/spec/v2.0.0.html>`_.
 
-`v0.11.3`_ - 0-Undefined-2023
+`v0.12.0`_ - 0-Undefined-2024
 -----------------------------
+Fixed
++++++
+- Include prefix in the ``ImproperlyConfigured`` error message
+  `#513 <https://github.com/joke2k/django-environ/issues/513>`_.
+
+Added
++++++
+- Add support for Python 3.12 and 3.13
+  `#538 <https://github.com/joke2k/django-environ/issues/538>`_.
+- Add support for Django 5.1
+  `#535 <https://github.com/joke2k/django-environ/issues/535>`_.
+
 Changed
 +++++++
-- Formally support Python 3.12.
 - Disabled inline comments handling by default due to potential side effects.
   While the feature itself is useful, the project's philosophy dictates that
   it should not be enabled by default for all users
   `#499 <https://github.com/joke2k/django-environ/issues/499>`_.
 
+Removed
++++++++
+- Removed support of Python 3.6, 3.7 and 3.8
+  `#538 <https://github.com/joke2k/django-environ/issues/538>`_.
+- Removed support of Django 1.x.
+  `#538 <https://github.com/joke2k/django-environ/issues/538>`_.
+
 
 `v0.11.2`_ - 1-September-2023
 -----------------------------
@@ -399,7 +417,7 @@ Added
 - Initial release.
 
 
-.. _v0.11.3: https://github.com/joke2k/django-environ/compare/v0.11.2...v0.11.3
+.. _v0.12.0: https://github.com/joke2k/django-environ/compare/v0.11.2...v0.12.0
 .. _v0.11.2: https://github.com/joke2k/django-environ/compare/v0.11.1...v0.11.2
 .. _v0.11.1: https://github.com/joke2k/django-environ/compare/v0.11.0...v0.11.1
 .. _v0.11.0: https://github.com/joke2k/django-environ/compare/v0.10.0...v0.11.0
@@ -417,4 +435,4 @@ Added
 .. _v0.4.1: https://github.com/joke2k/django-environ/compare/v0.4...v0.4.1
 .. _v0.4: https://github.com/joke2k/django-environ/compare/v0.3.1...v0.4
 .. _v0.3.1: https://github.com/joke2k/django-environ/compare/v0.3...v0.3.1
-.. _v0.3: https://github.com/joke2k/django-environ/compare/v0.2.1...v0.3
\ No newline at end of file
+.. _v0.3: https://github.com/joke2k/django-environ/compare/v0.2.1...v0.3
diff --git a/README.rst b/README.rst
index dbb572b..ff8e012 100644
--- a/README.rst
+++ b/README.rst
@@ -97,7 +97,8 @@ approach, some connection strings are expressed as url, so this package can pars
 it and return a ``urllib.parse.ParseResult``. These strings from ``os.environ``
 are loaded from a ``.env`` file and filled in ``os.environ`` with ``setdefault``
 method, to avoid to overwrite the real environ.
-A similar approach is used in `Two Scoops of Django <https://www.feldroy.com/books/two-scoops-of-django-3-x>`_
+A similar approach is used in
+`Two Scoops of Django <https://web.archive.org/web/20240121133956/https://www.feldroy.com/books/two-scoops-of-django-3-x>`_
 book and explained in `12factor-django <https://wellfire.co/learn/easier-12-factor-django>`_
 article.
 
@@ -126,8 +127,8 @@ its documentation lives at `Read the Docs <https://django-environ.readthedocs.io
 the code on `GitHub <https://github.com/joke2k/django-environ>`_,
 and the latest release on `PyPI <https://pypi.org/project/django-environ/>`_.
 
-It’s rigorously tested on Python 3.6+, and officially supports
-Django 1.11, 2.2, 3.0, 3.1, 3.2, 4.0, 4.1, 4.2, and 5.0.
+It’s rigorously tested on Python 3.9+, and officially supports
+Django 2.2, 3.0, 3.1, 3.2, 4.0, 4.1, 4.2, 5.0, and 5.1.
 
 If you'd like to contribute to ``django-environ`` you're most welcome!
 
diff --git a/docs/install.rst b/docs/install.rst
index 3dacca9..b1a73c1 100644
--- a/docs/install.rst
+++ b/docs/install.rst
@@ -6,8 +6,8 @@ Installation
 Requirements
 ============
 
-* `Django <https://www.djangoproject.com/>`_ >= 1.11
-* `Python <https://www.python.org/>`_ >= 3.5
+* `Django <https://www.djangoproject.com/>`_ >= 2.2
+* `Python <https://www.python.org/>`_ >= 3.9
 
 Installing django-environ
 =========================
diff --git a/environ/__init__.py b/environ/__init__.py
index ddf05f9..c590d71 100644
--- a/environ/__init__.py
+++ b/environ/__init__.py
@@ -1,6 +1,6 @@
 # This file is part of the django-environ.
 #
-# Copyright (c) 2021-2023, Serghei Iakovlev <egrep@protonmail.ch>
+# Copyright (c) 2021-2024, Serghei Iakovlev <oss@serghei.pl>
 # Copyright (c) 2013-2021, Daniele Faraglia <daniele.faraglia@gmail.com>
 #
 # For the full copyright and license information, please view
@@ -21,7 +21,7 @@ from .environ import *
 __copyright__ = 'Copyright (C) 2013-2023 Daniele Faraglia'
 """The copyright notice of the package."""
 
-__version__ = '0.11.3'
+__version__ = '0.12.0'
 """The version of the package."""
 
 __license__ = 'MIT'
diff --git a/environ/environ.py b/environ/environ.py
index a3d64f2..6595fc0 100644
--- a/environ/environ.py
+++ b/environ/environ.py
@@ -115,6 +115,7 @@ class Env:
         'psql': DJANGO_POSTGRES,
         'pgsql': DJANGO_POSTGRES,
         'postgis': 'django.contrib.gis.db.backends.postgis',
+        'cockroachdb': 'django_cockroachdb',
         'mysql': 'django.db.backends.mysql',
         'mysql2': 'django.db.backends.mysql',
         'mysql-connector': 'mysql.connector.django',
@@ -388,7 +389,7 @@ class Env:
             value = self.ENVIRON[var_name]
         except KeyError as exc:
             if default is self.NOTSET:
-                error_msg = f'Set the {var} environment variable'
+                error_msg = f'Set the {var_name} environment variable'
                 raise ImproperlyConfigured(error_msg) from exc
 
             value = default
diff --git a/setup.py b/setup.py
index fd3cd81..e927217 100644
--- a/setup.py
+++ b/setup.py
@@ -2,7 +2,7 @@
 #
 # This file is part of the django-environ.
 #
-# Copyright (c) 2021-2023, Serghei Iakovlev <egrep@protonmail.ch>
+# Copyright (c) 2021-2024, Serghei Iakovlev <oss@serghei.pl>
 # Copyright (c) 2013-2021, Daniele Faraglia <daniele.faraglia@gmail.com>
 #
 # For the full copyright and license information, please view
@@ -135,9 +135,6 @@ CLASSIFIERS = [
     'Development Status :: 5 - Production/Stable',
 
     'Framework :: Django',
-    'Framework :: Django :: 1.11',
-    'Framework :: Django :: 2.0',
-    'Framework :: Django :: 2.1',
     'Framework :: Django :: 2.2',
     'Framework :: Django :: 3.0',
     'Framework :: Django :: 3.1',
@@ -146,6 +143,7 @@ CLASSIFIERS = [
     'Framework :: Django :: 4.1',
     'Framework :: Django :: 4.2',
     'Framework :: Django :: 5.0',
+    'Framework :: Django :: 5.1',
 
     'Operating System :: OS Independent',
 
@@ -154,13 +152,11 @@ CLASSIFIERS = [
 
     'Programming Language :: Python',
     'Programming Language :: Python :: 3',
-    'Programming Language :: Python :: 3.6',
-    'Programming Language :: Python :: 3.7',
-    'Programming Language :: Python :: 3.8',
     'Programming Language :: Python :: 3.9',
     'Programming Language :: Python :: 3.10',
     'Programming Language :: Python :: 3.11',
     'Programming Language :: Python :: 3.12',
+    'Programming Language :: Python :: 3.13',
     'Programming Language :: Python :: Implementation :: CPython',
     'Programming Language :: Python :: Implementation :: PyPy',
 
@@ -185,11 +181,12 @@ EXTRAS_REQUIRE = {
     'testing': [
         'coverage[toml]>=5.0a4',  # Code coverage measurement for Python
         'pytest>=4.6.11',  # Our tests framework
+        'setuptools>=71.0.0',  # Needed as a dependency for some tests
     ],
     # Dependencies that are required to build documentation
     'docs': [
-        'furo>=2021.8.17b43,==2021.8.*',  # Sphinx documentation theme
-        'sphinx>=3.5.0',  # Python documentation generator
+        'furo>=2024.8.6',  # Sphinx documentation theme
+        'sphinx>=5.0',  # Python documentation generator
         'sphinx-notfound-page',  # Create a custom 404 page
     ],
 }
@@ -232,7 +229,7 @@ if __name__ == '__main__':
         platforms=['any'],
         include_package_data=True,
         zip_safe=False,
-        python_requires='>=3.6,<4',
+        python_requires='>=3.9,<4',
         install_requires=INSTALL_REQUIRES,
         dependency_links=DEPENDENCY_LINKS,
         extras_require=EXTRAS_REQUIRE,
diff --git a/tox.ini b/tox.ini
index fa3da3d..a0b8dc2 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,6 +1,6 @@
 # This file is part of the django-environ.
 #
-# Copyright (c) 2021-2023, Serghei Iakovlev <egrep@protonmail.ch>
+# Copyright (c) 2021-2024, Serghei Iakovlev <oss@serghei.pl>
 # Copyright (c) 2013-2021, Daniele Faraglia <daniele.faraglia@gmail.com>
 #
 # For the full copyright and license information, please view
@@ -18,28 +18,23 @@ envlist =
     docs
     lint
     manifest
-    py{36,37,38,39,310,311}-django{111,22}
-    py{36,37,38,39,310,311}-django{30,31,32}
-    py{38,39,310,311}-django{40,41,42}
-    py{310,311}-django{50}
-    pypy-django{111,22,30,31,32}
+    py{39,310,311,312,313}-django{22,30,31,32,40,41,42}
+    py{310,311,312,313}-django{50,51}
+    pypy-django{22,30,31,32}
 
 [gh-actions]
 python =
-    3.6: py36
-    3.7: py37
-    3.8: py38
     3.9: py39
     3.10: py310
     3.11: py311
     3.12: py312
-    pypy-3.7: pypy
+    3.13: py313
+    pypy-3.10: pypy
 
 [testenv]
 description = Unit tests
 extras = testing
 deps =
-    django111: Django>=1.11,<2
     django22: Django>=2.2,<3.0
     django30: Django>=3.0,<3.1
     django31: Django>=3.1,<3.2
@@ -93,7 +88,7 @@ commands =
 description = Check external links in the package documentation
 # Keep basepython in sync with .readthedocs.yml and docs.yml
 # (GitHub Action Workflow).
-basepython = python3.10
+basepython = python3.12
 extras = docs
 commands =
     {envpython} -m sphinx \
@@ -111,7 +106,7 @@ isolated_build = true
 description = Build package documentation (HTML)
 # Keep basepython in sync with .readthedocs.yml and docs.yml
 # (GitHub Action Workflow).
-basepython = python3.10
+basepython = python3.12
 extras = docs
 commands =
     {envpython} -m sphinx \


Test patch:
diff --git a/tests/test_db.py b/tests/test_db.py
index 8101a4a..a6995fd 100644
--- a/tests/test_db.py
+++ b/tests/test_db.py
@@ -59,6 +59,14 @@ from environ.compat import DJANGO_POSTGRES
          '',
          ''
          ),
+        # cockroachdb://username:secret@test.example.com:26258/dbname
+        ('cockroachdb://username:secret@test.example.com:26258/dbname',
+         'django_cockroachdb',
+         'dbname',
+         'test.example.com',
+         'username',
+         'secret',
+         26258),
         # mysqlgis://user:password@host:port/dbname
         ('mysqlgis://enigma:secret@example.com:5431/dbname',
          'django.contrib.gis.db.backends.mysql',
@@ -156,6 +164,7 @@ from environ.compat import DJANGO_POSTGRES
         'postgis',
         'postgres_cluster',
         'postgres_no_ports',
+        'cockroachdb',
         'mysqlgis',
         'cleardb',
         'mysql_no_password',
diff --git a/tests/test_env.py b/tests/test_env.py
index 85e0499..ac38377 100644
--- a/tests/test_env.py
+++ b/tests/test_env.py
@@ -407,6 +407,13 @@ class TestEnv:
         self.env.prefix = 'PREFIX_'
         assert self.env('TEST') == 'foo'
 
+    def test_prefix_and_not_present_without_default(self):
+        self.env.prefix = 'PREFIX_'
+        with pytest.raises(ImproperlyConfigured) as excinfo:
+            self.env('not_present')
+        assert str(excinfo.value) == 'Set the PREFIX_not_present environment variable'
+        assert excinfo.value.__cause__ is not None
+
 
 class TestFileEnv(TestEnv):
     def setup_method(self, method):