Compare commits

..

No commits in common. "master" and "v3.0.0" have entirely different histories.

12 changed files with 187 additions and 1219 deletions

5
.flake8 Normal file
View file

@ -0,0 +1,5 @@
[flake8]
max-line-length = 88
extend-ignore = E203
per-file-ignores=
tests/test_dj_database_url.py: E501, E265

View file

@ -1,8 +1,9 @@
name: Release name: Release
on: on:
release: push:
types: [published] tags:
- '*'
jobs: jobs:
build: build:
@ -10,29 +11,28 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v4
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Set version from release/tag - name: Set up Python
id: version uses: actions/setup-python@v5
run: |
VERSION=${GITHUB_REF#refs/*/}
VERSION=${VERSION#v}
echo "VERSION=$VERSION" >> $GITHUB_ENV
echo "version=$VERSION" >> $GITHUB_OUTPUT
- uses: astral-sh/setup-uv@v7
with: with:
python-version: 3.12 python-version: '3.10'
- name: Install dependencies
run: |
python -m pip install -U pip
python -m pip install -U setuptools wheel twine
- name: Build package - name: Build package
run: | run: |
uv version ${{ env.VERSION }} python setup.py --version
uv build python setup.py sdist --format=gztar bdist_wheel
uvx twine check dist/* twine check dist/*
- name: Upload packages to Jazzband - name: Upload packages to Jazzband
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
uses: pypa/gh-action-pypi-publish@release/v1 uses: pypa/gh-action-pypi-publish@release/v1
with: with:
user: jazzband user: jazzband

View file

@ -1,74 +1,56 @@
name: test name: test
on: [push, pull_request] on: [push, pull_request]
jobs: jobs:
formatting:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Install uv
uses: astral-sh/setup-uv@v7
with:
python-version: "3.12"
- name: Run ruff
run: uvx ruff check
typecheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Install uv
uses: astral-sh/setup-uv@v7
with:
python-version: "3.12"
- name: Run mypy
run: uvx mypy dj_database_url
- name: Run pyright
run: uvx pyright dj_database_url
test: test:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: [formatting, typecheck]
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"] python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
django-version: ["4.2", "5.2", "6.0"] django-version: ["4.2", "5.1"]
exclude: exclude:
# django 4.x is not compatible with python 3.13 or higher # Python 3.11 is not compatible with 3.2
- python-version: "3.13"
django-version: "4.2"
- python-version: "3.14"
django-version: "4.2"
# django 6.x is not compatible with python 3.11 or lower
- python-version: "3.10"
django-version: "6.0"
- python-version: "3.11" - python-version: "3.11"
django-version: "6.0" django-version: "3.2"
- python-version: "3.12"
django-version: "3.2"
- python-version: "3.13"
django-version: "3.2"
# django 5.x is not compatible with python 3.9 or lower
- python-version: "3.9"
django-version: "5.1"
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Install uv and set the Python version - name: Set up Python ${{ matrix.python-version }}
uses: astral-sh/setup-uv@v7 uses: actions/setup-python@v5
with: with:
python-version: ${{ matrix.python-version }} python-version: ${{ matrix.python-version }}
activate-environment: 'true' cache: 'pip'
- name: Install dependencies - name: Install dependencies
run: | run: |
uv pip install "Django~=${{ matrix.django-version }}.0" pip install -r requirements.txt
pip install "Django~=${{ matrix.django-version }}.0" .
- name: Run type checking
run: |
python -m mypy dj_database_url
python -m pyright dj_database_url
- name: Run Tests - name: Run Tests
run: | run: |
echo "$(python --version) / Django $(django-admin --version)" echo "$(python --version) / Django $(django-admin --version)"
uvx coverage run --source=dj_database_url --branch -m unittest discover -v coverage run --source=dj_database_url --branch -m unittest discover -v
uvx coverage report coverage report
uvx coverage xml coverage xml
- uses: codecov/codecov-action@v4 - uses: codecov/codecov-action@v4
- name: Check types installation
run: |
pip install .
cd tests
python -m mypy .
python -m pyright .

2
.isort.cfg Normal file
View file

@ -0,0 +1,2 @@
[settings]
profile = black

View file

@ -1,21 +1,23 @@
repos: repos:
- repo: https://github.com/pre-commit/pre-commit-hooks - repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0 rev: v5.0.0
hooks: hooks:
- id: end-of-file-fixer - id: end-of-file-fixer
- id: trailing-whitespace - id: trailing-whitespace
- repo: https://github.com/astral-sh/ruff-pre-commit - repo: https://github.com/pycqa/isort
rev: v0.15.9 rev: "6.0.1"
hooks: hooks:
- id: ruff-check - id: isort
args: args: ["--profile", "black"]
- --fix
- id: ruff-format
args:
- --quiet
- repo: https://github.com/crate-ci/typos - repo: https://github.com/psf/black
rev: v1 rev: 25.1.0
hooks: hooks:
- id: typos - id: black
args: [--target-version=py38]
- repo: https://github.com/pycqa/flake8
rev: '7.2.0'
hooks:
- id: flake8

View file

@ -1,20 +1,9 @@
# CHANGELOG # CHANGELOG
## v3.1.0 (2026-01-03) ## Unreleased
* Add support for Django 6.0
* Update CI structure.
* Migrate to UV for dependency management and builds.
* Python >3.10 support.
## v3.0.1 (2025-07-01)
* Drop dependency on `typing_extensions`. * Drop dependency on `typing_extensions`.
## v3.0.0 (2025-05-18)
> Bumping to version 3; changes to code do break some API compatibility.
* Implement a new decorator registry pattern to implement checks on database connection string.
* You can now support and implement your own database strings by extending the @register functionality.
* Update supported python versions and django versions.
## v2.3.0 (2024-10-23) ## v2.3.0 (2024-10-23)
* Remove Python 3.8 support. * Remove Python 3.8 support.
* Remove Django 3 support. * Remove Django 3 support.
@ -24,46 +13,54 @@
## v2.2.0 (2024-05-28) ## v2.2.0 (2024-05-28)
* Add disable_server_side_cursors parameter * Add disable_server_side_cursors parameter
* Enhance Query String Parsing for Server-Side Binding in Django 4.2 with psycopg 3.1.8+ * Enhance Query String Parsing for Server-Side Binding in Django 4.2 with psycopg 3.1.8+
* Update django 5.0 python compatibility by @mattseymour in #239 * Update django 5.0 python compatability by @mattseymour in #239
* Improved internals * Improved internals
* Improved documentation * Improved documentation
## v2.1.0 (2023-08-15) ## v2.1.0 (2023-08-15)
* Add value to int parsing when deconstructing url string. * Add value to int parsing when deconstructing url string.
## v2.0.0 (2023-04-27) ## v2.0.0 (2023-04-27)
* Update project setup such that we now install it as a package.
* Update project setup such that we now install as a package.
_Notes_: while this does not alter the underlying application code, we are bumping to _Notes_: while this does not alter the underlying application code, we are bumping to
2.0 incase there are unforeseen knock-on use-case issues. 2.0 incase there are unforeseen knock on use-case issues.
## v1.3.0 (2023-03-27) ## v1.3.0 (2023-03-27)
* Cosmetic changes to the generation of schemes. * Cosmetic changes to the generation of schemes.
* Bump isort version - 5.11.5. * Bump isort version - 5.11.5.
* raise a warning message if `database_url` is not set. * raise warning message if database_url is not set.
* `CONN_MAX_AGE` fix type - `Optional[int]`. * CONN_MAX_AGE fix type - Optional[int].
## v1.2.0 (2022-12-13) ## v1.2.0 (2022-12-13)
* Add the ability to add test databases. * Add the ability to add test databases.
* Improve url parsing and encoding. * Improve url parsing and encoding.
* Fix missing parameter `conn_health_check` in check function. * Fix missing parameter conn_health_check in check function.
## v1.1.0 (2022-12-12) ## v1.1.0 (2022-12-12)
* Option for connection health checks parameter. * Option for connection health checks parameter.
* Update supported version python 3.11. * Update supported version python 3.11.
* Code changes, various improvements. * Code changes, various improvments.
* Add project links to `setup.py`. * Add project links to setup.py
## v1.0.0 (2022-06-18) ## v1.0.0 (2022-06-18)
Initial release of code, dj-database-urls is now part of [Jazzband](https://jazzband.co/).
Initial release of code now dj-database-urls is part of jazzband.
* Add support for cockroachdb. * Add support for cockroachdb.
* Add support for the official MSSQL connector. * Add support for the offical MSSQL connector.
* Update License to be compatible with Jazzband. * Update License to be compatible with Jazzband.
* Remove support for Python < 3.5 including Python 2.7 * Remove support for Python < 3.5 including Python 2.7
* Update source code to Black format. * Update source code to Black format.
* Update CI using pre-commit * Update CI using pre-commit
## v0.5.0 (2018-03-01) ## v0.5.0 (2018-03-01)
- Use str port for mssql - Use str port for mssql
- Added license - Added license
- Add mssql to readme - Add mssql to readme
@ -83,15 +80,17 @@ Initial release of code, dj-database-urls is now part of [Jazzband](https://jazz
- Added SpatiaLite in README.rst - Added SpatiaLite in README.rst
## v0.4.1 (2016-04-06) ## v0.4.1 (2016-04-06)
- Enable CA providing for MySQL URIs - Enable CA providing for MySQL URIs
- Update Readme - Update Readme
- Update trove classifiers - Update trove classifiers
- Updated setup.py description - Updated setup.py description
## v0.4.0 (2016-02-04) ## v0.4.0 (2016-02-04)
- Update readme - Update readme
- Fix for python3 - Fix for python3
- Handle search path config in connection url for postgres - Handle search path config in connect url for postgres
- Add tox config to ease testing against multiple Python versions - Add tox config to ease testing against multiple Python versions
- Simplified the querystring parse logic - Simplified the querystring parse logic
- Cleaned up querystring parsing - Cleaned up querystring parsing
@ -108,25 +107,27 @@ Initial release of code, dj-database-urls is now part of [Jazzband](https://jazz
- Added support for python mysql-connector - Added support for python mysql-connector
## v0.3.0 (2014-03-10) ## v0.3.0 (2014-03-10)
- Add `.gitignore` file
- Remove `.pyc` file - Add .gitignore file
- Remove travis-ci unsupported python versions (Travis CI supports Python versions 2.6, 2.7, 3.2 and 3.3) - Remove .pyc file
- Remove travis-ci unsupported python version Per docs http://docs.travis-ci.com/user/languages/python/ "Travis CI support Python versions 2.6, 2.7, 3.2 and 3.3"
- Fix cleardb test - Fix cleardb test
- Add `setup.cfg` for wheel support - Add setup.cfg for wheel support
- Add trove classifiers for python versions - Add trove classifiers for python versions
- Replace Python 3.1 with Python 3.3 - Replace Python 3.1 with Python 3.3
- Add MySQL (GIS) support - Add MySQL (GIS) support
- Ability to set different engine - Ability to set different engine
## v0.2.2 (2013-07-17) ## v0.2.2 (2013-07-17)
- Added spatialite to uses_netloc too - Added spatialite to uses_netloc too
- Added spatialite backend - Added spatialite backend
- Replacing tab with spaces - Replacing tab with spaces
- Handling special case of `sqlite://:memory:` - Handling special case of sqlite://:memory:
- Empty sqlite path will now use a :memory: database - Empty sqlite path will now use a :memory: database
- Fixing test to actually use the result of the parse - Fixing test to actually use the result of the parse
- Adding in tests to ensure sqlite in-memory databases work - Adding in tests to ensure sqlite in-memory databases work
- Fixed a too-short title underline - Fixed too-short title underline
- Added :target: attribute to Travis status image in README - Added :target: attribute to Travis status image in README
- Added docs for default argument to config - Added docs for default argument to config
- Add "pgsql" as a PostgreSQL URL scheme. - Add "pgsql" as a PostgreSQL URL scheme.
@ -134,6 +135,7 @@ Initial release of code, dj-database-urls is now part of [Jazzband](https://jazz
- fixed url - fixed url
## v0.2.1 (2012-06-19) ## v0.2.1 (2012-06-19)
- Add python3 support - Add python3 support
- Adding travis status and tests - Adding travis status and tests
- Adding test environment variables - Adding test environment variables
@ -145,23 +147,28 @@ Initial release of code, dj-database-urls is now part of [Jazzband](https://jazz
- RedHat's OpenShift platform uses the 'postgresql' scheme - RedHat's OpenShift platform uses the 'postgresql' scheme
- Registered postgis URL scheme - Registered postgis URL scheme
- Added `postgis://` url scheme - Added `postgis://` url scheme
- Use `get()` on `os.environ` instead of an `if`. - Use get() on os.environ instead of an if
## v0.2.0 (2012-05-30) ## v0.2.0 (2012-05-30)
- Fix parse(s) - Fix parse(s)
## v0.1.4 (2012-05-30) ## v0.1.4 (2012-05-30)
- Add defaults for env - Add defaults for env
- Set the DATABASES dict rather than assigning to it - Set the DATABASES dict rather than assigning to it
## v0.1.3 (2012-05-01) ## v0.1.3 (2012-05-01)
- Add a note to README on supported databases
- Add note to README on supported databases
- Add support for SQLite - Add support for SQLite
- Clean dependencies - Clean dependencies
## v0.1.2 (2012-04-30) ## v0.1.2 (2012-04-30)
- Update readme - Update readme
- Refactor config and use a new parse function - Refactor config and use new parse function
## v0.1.1 (2012-04-30) First release ## v0.1.1 (2012-04-30) First release
🐍 ✨ 🐍 ✨

View file

@ -1,33 +1,34 @@
import logging import logging
import os import os
import urllib.parse as urlparse import urllib.parse as urlparse
from collections.abc import Callable from typing import Any, Callable, Dict, List, Optional, Union
from typing import Any, TypedDict
from typing_extensions import TypedDict
DEFAULT_ENV = "DATABASE_URL" DEFAULT_ENV = "DATABASE_URL"
ENGINE_SCHEMES: dict[str, "Engine"] = {} ENGINE_SCHEMES: Dict[str, "Engine"] = {}
# From https://docs.djangoproject.com/en/stable/ref/settings/#databases # From https://docs.djangoproject.com/en/stable/ref/settings/#databases
class DBConfig(TypedDict, total=False): class DBConfig(TypedDict, total=False):
ATOMIC_REQUESTS: bool ATOMIC_REQUESTS: bool
AUTOCOMMIT: bool AUTOCOMMIT: bool
CONN_MAX_AGE: int | None CONN_MAX_AGE: Optional[int]
CONN_HEALTH_CHECKS: bool CONN_HEALTH_CHECKS: bool
DISABLE_SERVER_SIDE_CURSORS: bool DISABLE_SERVER_SIDE_CURSORS: bool
ENGINE: str ENGINE: str
HOST: str HOST: str
NAME: str NAME: str
OPTIONS: dict[str, Any] OPTIONS: Dict[str, Any]
PASSWORD: str PASSWORD: str
PORT: str | int PORT: Union[str, int]
TEST: dict[str, Any] TEST: Dict[str, Any]
TIME_ZONE: str TIME_ZONE: str
USER: str USER: str
PostprocessCallable = Callable[[DBConfig], None] PostprocessCallable = Callable[[DBConfig], None]
OptionType = int | str | bool OptionType = Union[int, str, bool]
class ParseError(ValueError): class ParseError(ValueError):
@ -39,7 +40,7 @@ class ParseError(ValueError):
class UnknownSchemeError(ValueError): class UnknownSchemeError(ValueError):
def __init__(self, scheme: str): def __init__(self, scheme: str) -> None:
self.scheme = scheme self.scheme = scheme
def __str__(self) -> str: def __str__(self) -> str:
@ -60,7 +61,7 @@ class Engine:
self, self,
backend: str, backend: str,
postprocess: PostprocessCallable = default_postprocess, postprocess: PostprocessCallable = default_postprocess,
): ) -> None:
self.backend = backend self.backend = backend
self.postprocess = postprocess self.postprocess = postprocess
@ -126,13 +127,13 @@ def apply_current_schema(parsed_config: DBConfig) -> None:
def config( def config(
env: str = DEFAULT_ENV, env: str = DEFAULT_ENV,
default: str | None = None, default: Optional[str] = None,
engine: str | None = None, engine: Optional[str] = None,
conn_max_age: int | None = 0, conn_max_age: int = 0,
conn_health_checks: bool = False, conn_health_checks: bool = False,
disable_server_side_cursors: bool = False, disable_server_side_cursors: bool = False,
ssl_require: bool = False, ssl_require: bool = False,
test_options: dict[str, Any] | None = None, test_options: Optional[Dict[str, Any]] = None,
) -> DBConfig: ) -> DBConfig:
"""Returns configured DATABASE dictionary from DATABASE_URL.""" """Returns configured DATABASE dictionary from DATABASE_URL."""
s = os.environ.get(env, default) s = os.environ.get(env, default)
@ -158,12 +159,12 @@ def config(
def parse( def parse(
url: str, url: str,
engine: str | None = None, engine: Optional[str] = None,
conn_max_age: int | None = 0, conn_max_age: int = 0,
conn_health_checks: bool = False, conn_health_checks: bool = False,
disable_server_side_cursors: bool = False, disable_server_side_cursors: bool = False,
ssl_require: bool = False, ssl_require: bool = False,
test_options: dict[str, Any] | None = None, test_options: Optional[Dict[str, Any]] = None,
) -> DBConfig: ) -> DBConfig:
"""Parses a database URL and returns configured DATABASE dictionary.""" """Parses a database URL and returns configured DATABASE dictionary."""
settings = _convert_to_settings( settings = _convert_to_settings(
@ -217,7 +218,7 @@ def parse(
return parsed_config return parsed_config
def _parse_option_values(values: list[str]) -> OptionType | list[OptionType]: def _parse_option_values(values: List[str]) -> Union[OptionType, List[OptionType]]:
parsed_values = [_parse_value(v) for v in values] parsed_values = [_parse_value(v) for v in values]
return parsed_values[0] if len(parsed_values) == 1 else parsed_values return parsed_values[0] if len(parsed_values) == 1 else parsed_values
@ -231,12 +232,12 @@ def _parse_value(value: str) -> OptionType:
def _convert_to_settings( def _convert_to_settings(
engine: str | None, engine: Optional[str],
conn_max_age: int | None, conn_max_age: int,
conn_health_checks: bool, conn_health_checks: bool,
disable_server_side_cursors: bool, disable_server_side_cursors: bool,
ssl_require: bool, ssl_require: bool,
test_options: dict[str, Any] | None, test_options: Optional[dict[str, Any]],
) -> DBConfig: ) -> DBConfig:
settings: DBConfig = { settings: DBConfig = {
"CONN_MAX_AGE": conn_max_age, "CONN_MAX_AGE": conn_max_age,

View file

@ -1,61 +1,5 @@
[project] [tool.black]
name = "dj-database-url" skip-string-normalization = 1
version = "0.0.0"
description = "Use Database URLs in your Django Application."
authors = [
{ name = "Jazzband community" }
]
readme = "README.rst"
requires-python = ">=3.10"
license = "BSD-3-Clause"
license-files = ["LICENSE"]
dependencies = [
"django>=4.2",
]
classifiers = [
"Environment :: Web Environment",
"Framework :: Django",
"Framework :: Django :: 4.2",
"Framework :: Django :: 5.2",
"Framework :: Django :: 6",
"Intended Audience :: Developers",
"License :: OSI Approved :: BSD License",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Topic :: Internet :: WWW/HTTP :: Dynamic Content",
"Topic :: Software Development :: Libraries :: Python Modules",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
]
[project.urls]
Homepage = "https://jazzband.co/projects/dj-database-url"
Changelog = "https://github.com/jazzband/dj-database-url/blob/master/CHANGELOG.md"
Funding = "https://psfmember.org/civicrm/contribute/transact/?reset=1&id=34"
Bug = "https://github.com/jazzband/dj-database-url/issues"
[build-system]
requires = ["uv_build>=0.9.17,<0.10.0"]
build-backend = "uv_build"
[tool.uv.build-backend]
module-name = "dj_database_url"
module-root = ""
source-include = ["dj_database_url/py.typed", "tests/**"]
[tool.ruff]
line-length = 88
[tool.ruff.lint]
extend-select = ["B", "I"]
[tool.ruff.format]
quote-style = "preserve"
[tool.mypy] [tool.mypy]
show_error_codes=true show_error_codes=true
@ -65,15 +9,3 @@ warn_redundant_casts=true
[tool.pyright] [tool.pyright]
typeCheckingMode = "strict" typeCheckingMode = "strict"
[dependency-groups]
dev = [
"coverage>=7.13.0",
"mypy>=1.19.1",
"pyright>=1.1.407",
"pytest>=9.0.2",
"ruff>=0.14.10",
"setuptools>=80.9.0",
"twine>=6.2.0",
"wheel>=0.45.1",
]

3
requirements.txt Normal file
View file

@ -0,0 +1,3 @@
coverage
mypy
pyright

49
setup.py Normal file
View file

@ -0,0 +1,49 @@
from pathlib import Path
from setuptools import setup # pyright: ignore[reportUnknownVariableType]
readme = Path("README.rst").read_text()
setup(
name="dj-database-url",
version="3.0.0",
url="https://github.com/jazzband/dj-database-url",
license="BSD",
author="Original Author: Kenneth Reitz, Maintained by: JazzBand Community",
description="Use Database URLs in your Django Application.",
long_description=readme,
long_description_content_type="text/x-rst",
packages=["dj_database_url"],
install_requires=["Django>=4.2", "typing_extensions>=4.0.0"],
include_package_data=True,
package_data={
"dj_database_url": ["py.typed"],
},
platforms="any",
project_urls={
"GitHub": "https://github.com/jazzband/dj-database-url/",
"Release log": (
"https://github.com/jazzband/dj-database-url/blob/master/CHANGELOG.md"
),
},
classifiers=[
"Environment :: Web Environment",
"Framework :: Django",
"Framework :: Django :: 4.2",
"Framework :: Django :: 5.0",
"Framework :: Django :: 5.1",
"Framework :: Django :: 5.2",
"Intended Audience :: Developers",
"License :: OSI Approved :: BSD License",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Topic :: Internet :: WWW/HTTP :: Dynamic Content",
"Topic :: Software Development :: Libraries :: Python Modules",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
],
)

View file

@ -266,8 +266,8 @@ class DatabaseTestSuite(unittest.TestCase):
assert url["CONN_MAX_AGE"] == conn_max_age assert url["CONN_MAX_AGE"] == conn_max_age
def test_config_conn_max_age_setting_none(self) -> None: def test_config_conn_max_age_setting(self) -> None:
conn_max_age = None conn_max_age = 600
with mock.patch.dict( with mock.patch.dict(
os.environ, os.environ,
{ {
@ -680,9 +680,9 @@ class DatabaseTestSuite(unittest.TestCase):
def test_options_int_values(self) -> None: def test_options_int_values(self) -> None:
"""Ensure that options with integer values are parsed correctly.""" """Ensure that options with integer values are parsed correctly."""
url = dj_database_url.parse( url = dj_database_url.parse(
"mysql://user:pw@127.0.0.1:15036/db?connect_timeout=3" "mysql://user:pw@127.0.0.1:15036/db?connect_timout=3"
) )
assert url["OPTIONS"] == {'connect_timeout': 3} assert url["OPTIONS"] == {'connect_timout': 3}
@mock.patch.dict( @mock.patch.dict(
os.environ, os.environ,

1015
uv.lock

File diff suppressed because it is too large Load diff