Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-django-environ for 
openSUSE:Factory checked in at 2026-06-22 17:28:54
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-django-environ (Old)
 and      /work/SRC/openSUSE:Factory/.python-django-environ.new.1956 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-django-environ"

Mon Jun 22 17:28:54 2026 rev:10 rq:1360752 version:0.14.0

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/python-django-environ/python-django-environ.changes  
    2026-03-23 17:11:57.706164012 +0100
+++ 
/work/SRC/openSUSE:Factory/.python-django-environ.new.1956/python-django-environ.changes
    2026-06-22 17:29:46.342441745 +0200
@@ -1,0 +2,14 @@
+Sat Jun 20 17:49:30 UTC 2026 - Dirk Müller <[email protected]>
+
+- update to 0.14.0:
+  * Added type annotations and matching docstring information to
+    Env methods #633.
+  * Added a Python 3.9 compatibility dependency on
+    typing_extensions for TypeAlias #633.
+  * Updated Env.read_env() to accept path-like and file-like
+    objects without closing file-like objects supplied by the
+    caller #633.
+  * Added an explicit error when Env.read_env() cannot determine
+    its caller frame while resolving the default .env path #633.
+
+-------------------------------------------------------------------

Old:
----
  django_environ-0.13.0.tar.gz

New:
----
  django_environ-0.14.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-django-environ.spec ++++++
--- /var/tmp/diff_new_pack.Q1KEQ5/_old  2026-06-22 17:29:46.942462647 +0200
+++ /var/tmp/diff_new_pack.Q1KEQ5/_new  2026-06-22 17:29:46.942462647 +0200
@@ -18,7 +18,7 @@
 
 %{?sle15_python_module_pythons}
 Name:           python-django-environ
-Version:        0.13.0
+Version:        0.14.0
 Release:        0
 Summary:        Django application configuration via environment variables
 License:        MIT

++++++ django_environ-0.13.0.tar.gz -> django_environ-0.14.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/django_environ-0.13.0/.github/copilot-instructions.md 
new/django_environ-0.14.0/.github/copilot-instructions.md
--- old/django_environ-0.13.0/.github/copilot-instructions.md   2026-02-17 
22:58:34.000000000 +0100
+++ new/django_environ-0.14.0/.github/copilot-instructions.md   1970-01-01 
01:00:00.000000000 +0100
@@ -1,44 +0,0 @@
-# Copilot instructions for `django-environ`
-
-## Build, test, and lint commands
-
-- Install local dev dependencies:
-  - `python3 -m venv .venv && . .venv/bin/activate`
-  - `python -m pip install -U pip tox tox-gh-actions setuptools`
-- Run the default local test workflow (matches CI entrypoint): `tox`
-- Run one tox environment explicitly (recommended for iteration): `tox -e 
py312-django51`
-- Run a single test: `tox -e py312-django51 -- 
tests/test_env.py::TestEnv::test_int`
-- Lint: `tox -e lint`
-- Build/package checks: `tox -e build`
-- Docs and doctests: `tox -e docs`
-- Link checks in docs: `tox -e linkcheck`
-- Manifest validation: `tox -e manifest`
-- Coverage combine/report after test runs: `tox -e coverage-report`
-- Locally ZSH is used, keep in mind when you executing commands (like commits 
messages using back-ticks)
-- For GitHub CLI commands that can invoke a pager (`gh pr view`, `gh issue 
view`, etc.), use `GH_PAGER=cat` to avoid interactive blocking.
-
-## High-level architecture
-
-- Core implementation is concentrated in `environ/environ.py`:
-  - `Env` provides typed env access (`env()`, `env.bool()`, `env.db()`, 
`env.cache()`, etc.).
-  - URL-to-Django-settings parsing is centralized in class methods and scheme 
maps (`DB_SCHEMES`, `CACHE_SCHEMES`, `EMAIL_SCHEMES`, `SEARCH_SCHEMES`, 
`CHANNELS_SCHEMES`).
-  - `Env.read_env()` loads `.env` values into `os.environ` using `setdefault` 
semantics unless `overwrite=True`.
-  - `Path` is a small path helper used by users in Django settings modules.
-- `FileAwareEnv` (in `environ/environ.py`) swaps `ENVIRON` to 
`FileAwareMapping` (`environ/fileaware_mapping.py`) so `FOO_FILE` takes 
precedence over `FOO`.
-- Compatibility/backward-driver selection lives in `environ/compat.py` 
(Django/redis/postgres/pymemcache driver decisions).
-- Public package API is exported via `environ/__init__.py` (`from .environ 
import *`), and package metadata/version are also defined there and reused by 
`setup.py`.
-- Tests are behavior-first and organized by parser domain (`tests/test_db.py`, 
`tests/test_cache.py`, `tests/test_email.py`, `tests/test_search.py`, etc.).
-
-## Key repository conventions
-
-- Keep changes small and targeted; this project expects focused PRs against 
`develop` (see `CONTRIBUTING.rst`).
-- For public-facing text (e.g., commit messages, PR/issue comments), always 
write in English.
-- Use `develop` as the operational integration branch; do not create extra 
release/aggregation branches unless explicitly requested.
-- When adding/changing URL parsing behavior, update both the relevant scheme 
map(s) in `Env` and matching domain tests under `tests/`.
-- Preserve `.env` loading behavior in `read_env()`:
-  - default is non-overwriting (`setdefault`)
-  - comments parsing is opt-in (`parse_comments=True`)
-  - invalid lines should warn rather than crash.
-- Tests often isolate environment state by replacing `os.environ` / 
`Env.ENVIRON` with fixtures (for example `FakeEnv.generate_data()`); follow 
that pattern for deterministic tests.
-- CI matrix is driven by tox env naming (`py<python>-django<version>`), with 
mapping in `[gh-actions]` in `tox.ini`; keep new env names consistent there.
-- For docs tasks, keep Python version assumptions aligned between tox docs 
envs and GitHub workflows (`docs.yml`, comments in `tox.ini`).
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/django_environ-0.13.0/.github/skills/django-environ-release/SKILL.md 
new/django_environ-0.14.0/.github/skills/django-environ-release/SKILL.md
--- old/django_environ-0.13.0/.github/skills/django-environ-release/SKILL.md    
2026-02-18 01:49:59.000000000 +0100
+++ new/django_environ-0.14.0/.github/skills/django-environ-release/SKILL.md    
1970-01-01 01:00:00.000000000 +0100
@@ -1,144 +0,0 @@
----
-name: django-environ-release
-description: Run and validate the django-environ release workflow (prepare, 
verify, and publish).
----
-
-# django-environ release skill
-
-Use this skill when preparing a new django-environ release (for example 
`0.12.2`).
-
-## Prerequisites
-
-- Work from `develop` unless maintainers explicitly choose another branch.
-- Ensure local branch is up to date:
-
-```bash
-git checkout develop
-git fetch origin
-git pull --ff-only origin develop
-```
-
-- Confirm working tree is clean for tracked files.
-
-## 1) Update version and release notes
-
-- Bump version in `environ/__init__.py` (`__version__`).
-- Update `CHANGELOG.rst` with release entry and key changes mentioning 
contributors if possibile.
-- If needed, align `RELEASE_NOTES.md` / roadmap references.
-
-## 2) Validate locally
-
-Run the project checks used by CI/release flow:
-
-```bash
-tox -e lint
-tox -e build
-pytest -q
-```
-
-Optional (recommended):
-
-```bash
-tox -e docs
-tox -e manifest
-```
-
-## 3) Commit and push
-
-- Create focused commits (version bump and notes can be split if useful).
-- Include Co-authored-by trailer when required by project policy.
-- Push branch and open PR targeting `develop`.
-
-## 4) Release readiness checklist
-
-- [ ] Version bumped and consistent
-- [ ] Changelog updated
-- [ ] Build artifacts pass (`tox -e build`)
-- [ ] Tests pass (`pytest -q`)
-- [ ] Lint passes (`tox -e lint`)
-- [ ] Docs build passes (`tox -e docs`, if doc changes)
-- [ ] PR merged into `develop`
-
-## 5) Publish (maintainer step)
-
-When maintainers are ready to publish:
-
-- Create/tag release commit for the new version.
-- Trigger release pipeline / upload to PyPI according to current maintainer 
process.
-- Announce release with concise highlights.
-
-## 6) Copy/paste command blocks (required output)
-
-When using this skill, always provide a ready-to-run command list for:
-- merge into `main`
-- build artifacts
-- upload to TestPyPI
-- install from TestPyPI and run smoke test
-- upload to production PyPI
-
-Use command blocks like these (adjust version/tag as needed):
-
-```bash
-# Merge develop into main and push
-git checkout main
-git fetch origin
-git pull --ff-only origin main
-git merge --ff-only origin/develop
-git push origin main
-```
-
-```bash
-# Build distribution artifacts
-python -m pip install -U pip build twine
-rm -rf dist/ build/ *.egg-info
-python -m build
-twine check dist/*
-```
-
-```bash
-# Upload to TestPyPI
-python -m twine upload --repository testpypi dist/*
-```
-
-```bash
-# Install from TestPyPI and run smoke test
-python -m venv /tmp/django-environ-smoke
-. /tmp/django-environ-smoke/bin/activate
-python -m pip install -U pip
-python -m pip install --index-url https://test.pypi.org/simple/ 
--extra-index-url https://pypi.org/simple django-environ==<VERSION>
-python - <<'PY'
-import environ
-print(environ.__version__)
-env = environ.Env()
-print(env.str("DJANGO_ENV", default="ok"))
-PY
-deactivate
-```
-
-```bash
-# Upload to production PyPI
-python -m twine upload --repository django-environ dist/*
-```
-
-## 7) Social announcement draft (Twitter/X)
-
-At the end of the release flow, also generate a short Twitter/X draft
-highlighting the most interesting changes (max 280 chars), for example:
-
-```text
-django-environ v<VERSION> is out 🎉
-Highlights:
-✅ Optional warnings when defaults are used
-✅ New `choices` support in `Env.str(...)`
-✅ Valkey + rediss improvements
-✅ Docs improvements (including code copy button)
-
-Upgrade: https://pypi.org/project/django-environ/
-#django #python
-```
-
-## Notes specific to this repository
-
-- CI matrix is tox-driven (`tox.ini`).
-- Packaging is currently setup.py-based; v1.0 roadmap includes migration to 
`pyproject.toml` (see #570 reference tasks).
-- Keep release changes minimal and avoid unrelated refactors.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/django_environ-0.13.0/.github/workflows/change-pr-target.yml 
new/django_environ-0.14.0/.github/workflows/change-pr-target.yml
--- old/django_environ-0.13.0/.github/workflows/change-pr-target.yml    
2025-01-13 16:27:16.000000000 +0100
+++ new/django_environ-0.14.0/.github/workflows/change-pr-target.yml    
2026-06-19 00:43:16.000000000 +0200
@@ -13,8 +13,10 @@
           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
         with:
           target: main
-          exclude: develop # Don't prevent going from develop -> main
+          # Allow integration, release, and hotfix branches to target main.
+          exclude: "develop /^[^:]+:(?:release|hotfix)\\/.+$/"
           change-to: develop
           comment: |
-            Your PR was set to target `main`, PRs should be target `develop`
+            Your PR was set to target `main`. Only `develop`, `release/*`,
+            and `hotfix/*` branches may target `main`.
             The base branch of this PR has been automatically changed to 
`develop`, please check that there are no merge conflicts.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/django_environ-0.13.0/CHANGELOG.rst 
new/django_environ-0.14.0/CHANGELOG.rst
--- old/django_environ-0.13.0/CHANGELOG.rst     2026-02-18 01:52:30.000000000 
+0100
+++ new/django_environ-0.14.0/CHANGELOG.rst     2026-06-19 00:43:16.000000000 
+0200
@@ -5,6 +5,29 @@
 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.14.0`_ - 18-June-2026
+-------------------------
+Added
++++++
+- Added type annotations and matching docstring information to ``Env`` methods
+  `#633 <https://github.com/joke2k/django-environ/pull/633>`_.
+- Added a Python 3.9 compatibility dependency on ``typing_extensions`` for
+  ``TypeAlias``
+  `#633 <https://github.com/joke2k/django-environ/pull/633>`_.
+
+Changed
++++++++
+- Updated ``Env.read_env()`` to accept path-like and file-like objects without
+  closing file-like objects supplied by the caller
+  `#633 <https://github.com/joke2k/django-environ/pull/633>`_.
+
+Fixed
++++++
+- Added an explicit error when ``Env.read_env()`` cannot determine its caller
+  frame while resolving the default ``.env`` path
+  `#633 <https://github.com/joke2k/django-environ/pull/633>`_.
+
+
 `v0.13.0`_ - 18-February-2026
 -----------------------------
 Added
@@ -464,6 +487,7 @@
 - Initial release.
 
 
+.. _v0.14.0: https://github.com/joke2k/django-environ/compare/v0.13.0...v0.14.0
 .. _v0.13.0: https://github.com/joke2k/django-environ/compare/v0.12.1...v0.13.0
 .. _v0.12.1: https://github.com/joke2k/django-environ/compare/v0.12.0...v0.12.1
 .. _v0.12.0: https://github.com/joke2k/django-environ/compare/v0.11.2...v0.12.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/django_environ-0.13.0/PKG-INFO 
new/django_environ-0.14.0/PKG-INFO
--- old/django_environ-0.13.0/PKG-INFO  2026-02-18 02:03:20.751607700 +0100
+++ new/django_environ-0.14.0/PKG-INFO  2026-06-19 00:43:22.026146700 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.4
 Name: django-environ
-Version: 0.13.0
+Version: 0.14.0
 Summary: A package that allows you to utilize 12factor inspired environment 
variables to configure your Django application.
 Home-page: https://django-environ.readthedocs.org
 Author: Daniele Faraglia
@@ -48,6 +48,7 @@
 Description-Content-Type: text/x-rst
 License-File: LICENSE.txt
 License-File: AUTHORS.rst
+Requires-Dist: typing_extensions>=3.10.0; python_version < "3.10"
 Provides-Extra: testing
 Requires-Dist: coverage[toml]>=5.0a4; extra == "testing"
 Requires-Dist: pytest>=4.6.11; extra == "testing"
@@ -79,6 +80,7 @@
 Dynamic: platform
 Dynamic: project-url
 Dynamic: provides-extra
+Dynamic: requires-dist
 Dynamic: requires-python
 Dynamic: summary
 
@@ -285,34 +287,27 @@
 Release Information
 ===================
 
-v0.13.0 - 18-February-2026
------------------------------
+v0.14.0 - 18-June-2026
+-------------------------
 Added
 +++++
-- Added optional warnings when defaults are used
-  `#582 <https://github.com/joke2k/django-environ/pull/582>`_.
-- Added `choices` argument support for value validation in ``Env.str(...)``
-  `#555 <https://github.com/joke2k/django-environ/pull/555>`_.
-- Added Valkey support via ``valkey://`` and ``valkeys://`` cache URL schemes
-  `#554 <https://github.com/joke2k/django-environ/pull/554>`_.
-- Added support for ``rediss://`` scheme in channels URL parsing
-  `#573 <https://github.com/joke2k/django-environ/pull/573>`_.
-- Added django-prometheus database backend aliases to DB URL parsing schemes
-  `#559 <https://github.com/joke2k/django-environ/pull/559>`_.
+- Added type annotations and matching docstring information to ``Env`` methods
+  `#633 <https://github.com/joke2k/django-environ/pull/633>`_.
+- Added a Python 3.9 compatibility dependency on ``typing_extensions`` for
+  ``TypeAlias``
+  `#633 <https://github.com/joke2k/django-environ/pull/633>`_.
 
 Changed
 +++++++
-- Declared support for Python 3.14
-  `#580 <https://github.com/joke2k/django-environ/pull/580>`_.
-- Declared support for Django 5.2 and Django 6.0
-  `#578 <https://github.com/joke2k/django-environ/pull/578>`_.
+- Updated ``Env.read_env()`` to accept path-like and file-like objects without
+  closing file-like objects supplied by the caller
+  `#633 <https://github.com/joke2k/django-environ/pull/633>`_.
 
 Fixed
 +++++
-- Improved type hint coverage and related lint issues
-  `#546 <https://github.com/joke2k/django-environ/pull/546>`_.
-- Fixed typos in the FAQ page
-  `#445 <https://github.com/joke2k/django-environ/pull/445>`_.
+- Added an explicit error when ``Env.read_env()`` cannot determine its caller
+  frame while resolving the default ``.env`` path
+  `#633 <https://github.com/joke2k/django-environ/pull/633>`_.
 
 `Full changelog 
<https://django-environ.readthedocs.org/en/latest/changelog.html>`_.
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/django_environ-0.13.0/django_environ.egg-info/PKG-INFO 
new/django_environ-0.14.0/django_environ.egg-info/PKG-INFO
--- old/django_environ-0.13.0/django_environ.egg-info/PKG-INFO  2026-02-18 
02:03:20.000000000 +0100
+++ new/django_environ-0.14.0/django_environ.egg-info/PKG-INFO  2026-06-19 
00:43:21.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.4
 Name: django-environ
-Version: 0.13.0
+Version: 0.14.0
 Summary: A package that allows you to utilize 12factor inspired environment 
variables to configure your Django application.
 Home-page: https://django-environ.readthedocs.org
 Author: Daniele Faraglia
@@ -48,6 +48,7 @@
 Description-Content-Type: text/x-rst
 License-File: LICENSE.txt
 License-File: AUTHORS.rst
+Requires-Dist: typing_extensions>=3.10.0; python_version < "3.10"
 Provides-Extra: testing
 Requires-Dist: coverage[toml]>=5.0a4; extra == "testing"
 Requires-Dist: pytest>=4.6.11; extra == "testing"
@@ -79,6 +80,7 @@
 Dynamic: platform
 Dynamic: project-url
 Dynamic: provides-extra
+Dynamic: requires-dist
 Dynamic: requires-python
 Dynamic: summary
 
@@ -285,34 +287,27 @@
 Release Information
 ===================
 
-v0.13.0 - 18-February-2026
------------------------------
+v0.14.0 - 18-June-2026
+-------------------------
 Added
 +++++
-- Added optional warnings when defaults are used
-  `#582 <https://github.com/joke2k/django-environ/pull/582>`_.
-- Added `choices` argument support for value validation in ``Env.str(...)``
-  `#555 <https://github.com/joke2k/django-environ/pull/555>`_.
-- Added Valkey support via ``valkey://`` and ``valkeys://`` cache URL schemes
-  `#554 <https://github.com/joke2k/django-environ/pull/554>`_.
-- Added support for ``rediss://`` scheme in channels URL parsing
-  `#573 <https://github.com/joke2k/django-environ/pull/573>`_.
-- Added django-prometheus database backend aliases to DB URL parsing schemes
-  `#559 <https://github.com/joke2k/django-environ/pull/559>`_.
+- Added type annotations and matching docstring information to ``Env`` methods
+  `#633 <https://github.com/joke2k/django-environ/pull/633>`_.
+- Added a Python 3.9 compatibility dependency on ``typing_extensions`` for
+  ``TypeAlias``
+  `#633 <https://github.com/joke2k/django-environ/pull/633>`_.
 
 Changed
 +++++++
-- Declared support for Python 3.14
-  `#580 <https://github.com/joke2k/django-environ/pull/580>`_.
-- Declared support for Django 5.2 and Django 6.0
-  `#578 <https://github.com/joke2k/django-environ/pull/578>`_.
+- Updated ``Env.read_env()`` to accept path-like and file-like objects without
+  closing file-like objects supplied by the caller
+  `#633 <https://github.com/joke2k/django-environ/pull/633>`_.
 
 Fixed
 +++++
-- Improved type hint coverage and related lint issues
-  `#546 <https://github.com/joke2k/django-environ/pull/546>`_.
-- Fixed typos in the FAQ page
-  `#445 <https://github.com/joke2k/django-environ/pull/445>`_.
+- Added an explicit error when ``Env.read_env()`` cannot determine its caller
+  frame while resolving the default ``.env`` path
+  `#633 <https://github.com/joke2k/django-environ/pull/633>`_.
 
 `Full changelog 
<https://django-environ.readthedocs.org/en/latest/changelog.html>`_.
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/django_environ-0.13.0/django_environ.egg-info/SOURCES.txt 
new/django_environ-0.14.0/django_environ.egg-info/SOURCES.txt
--- old/django_environ-0.13.0/django_environ.egg-info/SOURCES.txt       
2026-02-18 02:03:20.000000000 +0100
+++ new/django_environ-0.14.0/django_environ.egg-info/SOURCES.txt       
2026-06-19 00:43:21.000000000 +0200
@@ -10,9 +10,7 @@
 setup.py
 tox.ini
 .github/FUNDING.yml
-.github/copilot-instructions.md
 .github/dependabot.yml
-.github/skills/django-environ-release/SKILL.md
 .github/workflows/build.yml
 .github/workflows/change-pr-target.yml
 .github/workflows/ci.yml
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/django_environ-0.13.0/django_environ.egg-info/requires.txt 
new/django_environ-0.14.0/django_environ.egg-info/requires.txt
--- old/django_environ-0.13.0/django_environ.egg-info/requires.txt      
2026-02-18 02:03:20.000000000 +0100
+++ new/django_environ-0.14.0/django_environ.egg-info/requires.txt      
2026-06-19 00:43:21.000000000 +0200
@@ -1,4 +1,7 @@
 
+[:python_version < "3.10"]
+typing_extensions>=3.10.0
+
 [develop]
 coverage[toml]>=5.0a4
 pytest>=4.6.11
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/django_environ-0.13.0/environ/__init__.py 
new/django_environ-0.14.0/environ/__init__.py
--- old/django_environ-0.13.0/environ/__init__.py       2026-02-18 
01:52:13.000000000 +0100
+++ new/django_environ-0.14.0/environ/__init__.py       2026-06-19 
00:43:16.000000000 +0200
@@ -22,7 +22,7 @@
 __copyright__ = 'Copyright (C) 2013-2026 Daniele Faraglia'
 """The copyright notice of the package."""
 
-__version__ = '0.13.0'
+__version__ = '0.14.0'
 """The version of the package."""
 
 __license__ = 'MIT'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/django_environ-0.13.0/environ/environ.py 
new/django_environ-0.14.0/environ/environ.py
--- old/django_environ-0.13.0/environ/environ.py        2026-02-18 
01:22:58.000000000 +0100
+++ new/django_environ-0.14.0/environ/environ.py        2026-06-19 
00:43:16.000000000 +0200
@@ -16,10 +16,15 @@
 import itertools
 import logging
 import os
+import pathlib
 import re
 import sys
 import warnings
-from typing import Dict, List, Tuple, Union
+from typing import Dict, IO, List, Optional, Tuple, Union
+try:
+    from typing import TypeAlias
+except ImportError:  # pragma: no cover
+    from typing_extensions import TypeAlias
 from urllib.parse import (
     parse_qs,
     ParseResult,
@@ -42,6 +47,11 @@
 OPENABLE = (str, os.PathLike)
 logger = logging.getLogger(__name__)
 
+# These type names are also method names of "Env",
+# so use these for type hinting within "Env"
+_bool: TypeAlias = bool  # pylint: disable=invalid-name
+_str: TypeAlias = str  # pylint: disable=invalid-name
+
 
 def _cast(value):
     # Safely evaluate an expression node or a string containing a Python
@@ -227,7 +237,16 @@
         self.prefix = ""
         self.scheme = scheme
 
-    def __call__(self, var, cast=None, default=NOTSET, parse_default=False):
+    def __call__(
+            self,
+            var: _str,
+            cast=None,
+            default=NOTSET,
+            parse_default: _bool = False):
+        """
+        :param str var:
+        :param bool parse_default:
+        """
         return self.get_value(
             var,
             cast=cast,
@@ -235,16 +254,22 @@
             parse_default=parse_default
         )
 
-    def __contains__(self, var):
+    def __contains__(self, var: _str):
+        """
+        :param str var:
+        """
         return var in self.ENVIRON
 
     def str(
             self,
-            var,
-            default: Union[str, NoValue] = NOTSET,
-            multiline=False,
-            choices=NOTSET) -> str:
+            var: _str,
+            default: Union[_str, NoValue] = NOTSET,
+            multiline: _bool = False,
+            choices=NOTSET) -> _str:
         """
+        :param str var:
+        :param str or NoValue default:
+        :param bool multiline:
         :rtype: str
         """
         value = self.get_value(var, cast=str, default=default)
@@ -260,10 +285,12 @@
 
     def bytes(
             self,
-            var,
+            var: _str,
             default: Union[bytes, NoValue] = NOTSET,
             encoding='utf8') -> bytes:
         """
+        :param str var:
+        :param bytes or NoValue default:
         :rtype: bytes
         """
         value = self.get_value(var, cast=str, default=default)
@@ -271,32 +298,42 @@
             return value.encode(encoding)
         return value
 
-    def bool(self, var, default: Union[bool, NoValue] = NOTSET) -> bool:
+    def bool(self, var: _str, default: Union[bool, NoValue] = NOTSET) -> bool:
         """
+        :param str var:
+        :param bool or NoValue default:
         :rtype: bool
         """
         return self.get_value(var, cast=bool, default=default)
 
-    def int(self, var, default: Union[int, NoValue] = NOTSET) -> int:
+    def int(self, var: _str, default: Union[int, NoValue] = NOTSET) -> int:
         """
+        :param str var:
+        :param int or NoValue default:
         :rtype: int
         """
         return self.get_value(var, cast=int, default=default)
 
-    def float(self, var, default: Union[float, NoValue] = NOTSET) -> float:
+    def float(self,
+              var: _str,
+              default: Union[float, NoValue] = NOTSET) -> float:
         """
+        :param str var:
+        :param float or NoValue default:
         :rtype: float
         """
         return self.get_value(var, cast=float, default=default)
 
-    def json(self, var, default=NOTSET):
+    def json(self, var: _str, default=NOTSET):
         """
+        :param str var:
         :returns: Json parsed
         """
         return self.get_value(var, cast=json.loads, default=default)
 
-    def list(self, var, cast=None, default=NOTSET) -> List:
+    def list(self, var: _str, cast=None, default=NOTSET) -> List:
         """
+        :param str var:
         :rtype: list
         """
         return self.get_value(
@@ -305,8 +342,9 @@
             default=default
         )
 
-    def tuple(self, var, cast=None, default=NOTSET) -> Tuple:
+    def tuple(self, var: _str, cast=None, default=NOTSET) -> Tuple:
         """
+        :param str var:
         :rtype: tuple
         """
         return self.get_value(
@@ -315,14 +353,16 @@
             default=default
         )
 
-    def dict(self, var, cast=dict, default=NOTSET) -> Dict:
+    def dict(self, var: _str, cast=dict, default=NOTSET) -> Dict:
         """
+        :param str var:
         :rtype: dict
         """
         return self.get_value(var, cast=cast, default=default)
 
-    def url(self, var, default=NOTSET) -> ParseResult:
+    def url(self, var: _str, default=NOTSET) -> ParseResult:
         """
+        :param str var:
         :rtype: urllib.parse.ParseResult
         """
         return self.get_value(
@@ -402,11 +442,13 @@
 
     def channels_url(
             self,
-            var=DEFAULT_CHANNELS_ENV,
+            var: _str = DEFAULT_CHANNELS_ENV,
             default: Union[Dict, NoValue] = NOTSET,
             backend=None) -> Dict:
         """Returns a config dictionary, defaulting to CHANNELS_URL.
 
+        :param str var:
+        :param dict or NoValue default:
         :rtype: dict
         """
         return self.channels_url_config(
@@ -418,15 +460,22 @@
 
     def path(
             self,
-            var,
+            var: _str,
             default: Union['Path', NoValue] = NOTSET,
             **kwargs) -> 'Path':
         """
+        :param str var:
+        :param Path or NoValue default:
         :rtype: Path
         """
         return Path(self.get_value(var, default=default), **kwargs)
 
-    def get_value(self, var, cast=None, default=NOTSET, parse_default=False):
+    def get_value(
+            self,
+            var: _str,
+            cast=None,
+            default=NOTSET,
+            parse_default: _bool = False):
         """Return value for given environment variable.
 
         :param str var:
@@ -998,8 +1047,14 @@
         return config
 
     @classmethod
-    def read_env(cls, env_file=None, overwrite=False, parse_comments=False,
-                 encoding='utf8', **overrides):
+    # pylint: disable=too-many-statements
+    def read_env(
+            cls,
+            env_file: Optional[Union[_str, pathlib.Path, IO[_str]]] = None,
+            overwrite: _bool = False,
+            parse_comments: _bool = False,
+            encoding: _str = 'utf8',
+            **overrides):
         r"""Read a .env file into os.environ.
 
         If not given a path to a dotenv path, does filthy magic stack
@@ -1010,14 +1065,16 @@
         by the file content. ``overwrite=True`` will force an overwrite of
         existing environment variables.
 
-        :param env_file: The path to the ``.env`` file your application should
-            use. If a path is not provided, `read_env` will attempt to import
-            the Django settings module from the Django project root.
-        :param overwrite: ``overwrite=True`` will force an overwrite of
+        :param str or pathlib.Path or IO or None env_file: The path to the
+            ``.env`` file your application should use. If a path is not
+            provided, `read_env` will attempt to import the Django settings
+            module from the Django project root.
+        :param bool overwrite: ``overwrite=True`` will force an overwrite of
             existing environment variables.
-        :param parse_comments: Determines whether to recognize and ignore
+        :param bool parse_comments: Determines whether to recognize and ignore
            inline comments in the .env file. Default is False.
-        :param encoding: The encoding to use when reading the environment file.
+        :param str encoding: The encoding to use when reading the environment
+            file.
         :param \**overrides: Any additional keyword arguments provided directly
             to read_env will be added to the environment. If the key matches an
             existing environment variable, the value will be overridden.
@@ -1025,8 +1082,11 @@
         if env_file is None:
             # pylint: disable=protected-access
             frame = sys._getframe()
+            caller_frame = frame.f_back
+            if caller_frame is None:  # pragma: no cover
+                raise RuntimeError('Unable to determine caller frame')
             env_file = os.path.join(
-                os.path.dirname(frame.f_back.f_code.co_filename),
+                os.path.dirname(caller_frame.f_code.co_filename),
                 '.env'
             )
             if not os.path.exists(env_file):
@@ -1037,12 +1097,10 @@
 
         try:
             if isinstance(env_file, OPENABLE):
-                # Python 3.5 support (wrap path with str).
-                with open(str(env_file), encoding=encoding) as f:
+                with open(env_file, encoding=encoding) as f:
                     content = f.read()
             else:
-                with env_file as f:
-                    content = f.read()
+                content = env_file.read()
         except OSError:
             logger.info(
                 "%s not found - if you're not configuring your "
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/django_environ-0.13.0/setup.py 
new/django_environ-0.14.0/setup.py
--- old/django_environ-0.13.0/setup.py  2026-02-18 01:22:58.000000000 +0100
+++ new/django_environ-0.14.0/setup.py  2026-06-19 00:43:16.000000000 +0200
@@ -170,7 +170,10 @@
 ]
 
 # Dependencies that are downloaded by pip on installation and why.
-INSTALL_REQUIRES = []
+INSTALL_REQUIRES = [
+    # Provides TypeAlias on Python 3.9.
+    'typing_extensions>=3.10.0;python_version<"3.10"',
+]
 
 DEPENDENCY_LINKS = []
 

Reply via email to