Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-drf-standardized-errors for
openSUSE:Factory checked in at 2026-05-10 16:48:16
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-drf-standardized-errors (Old)
and /work/SRC/openSUSE:Factory/.python-drf-standardized-errors.new.1966
(New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-drf-standardized-errors"
Sun May 10 16:48:16 2026 rev:3 rq:1352250 version:0.16.0
Changes:
--------
---
/work/SRC/openSUSE:Factory/python-drf-standardized-errors/python-drf-standardized-errors.changes
2026-04-12 17:53:04.413026301 +0200
+++
/work/SRC/openSUSE:Factory/.python-drf-standardized-errors.new.1966/python-drf-standardized-errors.changes
2026-05-10 16:48:52.934149231 +0200
@@ -1,0 +2,20 @@
+Sun May 10 09:03:15 UTC 2026 - Dirk Müller <[email protected]>
+
+- update to 0.16.0:
+ * Add support for python 3.14
+ * Add support for django 6.0
+ * Add support for DRF 3.17
+ * Set the minimum version of drf-spectacular to 0.29.0
+ * Account for the `format` query parameter raising 404 errors
+ when generating the API schema for error responses. This
+ * will result in any project using the default value for
+ `REST_FRAMEWORK["URL_FORMAT_OVERRIDE"]` showing 404 errors
+ for
+ * every operation. That's because DRF enables the `format`
+ query parameter in every endpoint by default. If you don't
+ * need the `format` query parameter for content negotiation,
+ you can disable it by setting `"URL_FORMAT_OVERRIDE"`
+ * to `None` in DRF settings. Refer
+ * to DRF docs for more information.
+
+-------------------------------------------------------------------
Old:
----
drf_standardized_errors-0.15.0.tar.gz
New:
----
drf_standardized_errors-0.16.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-drf-standardized-errors.spec ++++++
--- /var/tmp/diff_new_pack.9IsF8X/_old 2026-05-10 16:48:53.770183446 +0200
+++ /var/tmp/diff_new_pack.9IsF8X/_new 2026-05-10 16:48:53.770183446 +0200
@@ -17,7 +17,7 @@
Name: python-drf-standardized-errors
-Version: 0.15.0
+Version: 0.16.0
Release: 0
Summary: Standardize your API error responses
License: MIT
@@ -30,7 +30,7 @@
BuildRequires: %{python_module Django >= 3.2}
BuildRequires: %{python_module django-filter}
BuildRequires: %{python_module djangorestframework >= 3.12}
-BuildRequires: %{python_module drf-spectacular >= 0.27.0}
+BuildRequires: %{python_module drf-spectacular >= 0.29.0}
BuildRequires: %{python_module pytest-django}
BuildRequires: %{python_module pytest}
# /SECTION
@@ -45,7 +45,7 @@
Suggests: python-flit
Suggests: python-keyring
Suggests: python-tbump
-Suggests: python-drf-spectacular >= 0.27.0
+Suggests: python-drf-spectacular >= 0.29.0
Suggests: python-inflection
BuildArch: noarch
%python_subpackages
@@ -76,6 +76,8 @@
%pytest
%files %{python_files}
+%license LICENSE
+%doc README.md
%{python_sitelib}/drf_standardized_errors
%{python_sitelib}/drf_standardized_errors-%{version}.dist-info
++++++ drf_standardized_errors-0.15.0.tar.gz ->
drf_standardized_errors-0.16.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/drf_standardized_errors-0.15.0/.github/workflows/coverage.yml
new/drf_standardized_errors-0.16.0/.github/workflows/coverage.yml
--- old/drf_standardized_errors-0.15.0/.github/workflows/coverage.yml
2024-03-24 17:07:14.000000000 +0100
+++ new/drf_standardized_errors-0.16.0/.github/workflows/coverage.yml
2026-04-28 23:59:24.496251800 +0200
@@ -1,25 +1,27 @@
name: Coverage
on:
- - push
- - pull_request
+ push:
+ branches: [main]
+ pull_request:
+ types: [opened, synchronize]
jobs:
run:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v6
- name: Setup Python
- uses: actions/setup-python@v5
+ uses: actions/setup-python@v6
with:
- python-version: 3.8
+ python-version: 3.12
- name: Generate coverage report
run: |
pip install .
- pip install django~=3.2 pytest pytest-django pytest-cov
drf-spectacular django-filter
+ pip install django~=5.2 pytest pytest-django pytest-cov
drf-spectacular django-filter
pytest --cov --cov-report=xml
- name: Upload coverage to Codecov
- uses: codecov/codecov-action@v4
+ uses: codecov/codecov-action@v6
with:
token: ${{ secrets.CODECOV_TOKEN }}
fail_ci_if_error: true
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/drf_standardized_errors-0.15.0/.github/workflows/github_release.yml
new/drf_standardized_errors-0.16.0/.github/workflows/github_release.yml
--- old/drf_standardized_errors-0.15.0/.github/workflows/github_release.yml
2024-03-24 17:07:14.000000000 +0100
+++ new/drf_standardized_errors-0.16.0/.github/workflows/github_release.yml
2025-12-03 06:28:39.145651800 +0100
@@ -19,7 +19,7 @@
echo ::set-output name=current_version::${GITHUB_REF#refs/tags/v}
shell: bash
- name: Checkout code
- uses: actions/checkout@v4
+ uses: actions/checkout@v6
- name: Get Changelog Entry
id: changelog_reader
uses: mindsers/changelog-reader-action@v2
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/drf_standardized_errors-0.15.0/.github/workflows/tests.yml
new/drf_standardized_errors-0.16.0/.github/workflows/tests.yml
--- old/drf_standardized_errors-0.15.0/.github/workflows/tests.yml
2025-06-04 09:21:28.971057400 +0200
+++ new/drf_standardized_errors-0.16.0/.github/workflows/tests.yml
2025-12-03 08:38:30.445763300 +0100
@@ -1,8 +1,10 @@
name: Tests
on:
- - push
- - pull_request
+ push:
+ branches: [main]
+ pull_request:
+ types: [opened, synchronize]
jobs:
test:
@@ -10,12 +12,12 @@
strategy:
matrix:
platform: [ ubuntu-latest, macos-latest, windows-latest ]
- python-version: [ "3.8", "3.9", "3.10", "3.11", "3.12", "3.13" ]
+ python-version: [ "3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "3.14"
]
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v6
- name: Set up Python ${{ matrix.python-version }}
- uses: actions/setup-python@v5
+ uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/drf_standardized_errors-0.15.0/.pre-commit-config.yaml
new/drf_standardized_errors-0.16.0/.pre-commit-config.yaml
--- old/drf_standardized_errors-0.15.0/.pre-commit-config.yaml 2025-06-04
09:21:28.971057400 +0200
+++ new/drf_standardized_errors-0.16.0/.pre-commit-config.yaml 2026-04-27
10:59:53.950948000 +0200
@@ -2,27 +2,27 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
- rev: v5.0.0
+ rev: v6.0.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- repo: https://github.com/Zac-HD/shed
- rev: 2024.10.1
+ rev: 2025.6.1
hooks:
- id: shed
- additional_dependencies: [ 'black~=24.3' ]
+ additional_dependencies: [ 'black~=26.3.1' ]
types_or: [ python, pyi, markdown, rst ]
- repo: https://github.com/PyCQA/flake8
- rev: 7.2.0
+ rev: 7.3.0
hooks:
- id: flake8
args: [ --max-line-length, '120' , --ignore, 'E,W']
- repo: https://github.com/pre-commit/mirrors-mypy
- rev: v1.16.0
+ rev: v1.20.2
hooks:
- id: mypy
args: [ --ignore-missing-imports, --check-untyped-defs,
--disallow-incomplete-defs ]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/drf_standardized_errors-0.15.0/PKG-INFO
new/drf_standardized_errors-0.16.0/PKG-INFO
--- old/drf_standardized_errors-0.15.0/PKG-INFO 1970-01-01 01:00:00.000000000
+0100
+++ new/drf_standardized_errors-0.16.0/PKG-INFO 1970-01-01 01:00:00.000000000
+0100
@@ -1,6 +1,6 @@
Metadata-Version: 2.4
Name: drf-standardized-errors
-Version: 0.15.0
+Version: 0.16.0
Summary: Standardize your API error responses.
Keywords: standardized errors,errors formatter,django rest framework,exception
handler
Author: Ghazi Abbassi
@@ -15,6 +15,7 @@
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
+Classifier: Programming Language :: Python :: 3.14
License-File: LICENSE
Requires-Dist: django >=3.2
Requires-Dist: djangorestframework >=3.12
@@ -23,7 +24,7 @@
Requires-Dist: sphinx-autobuild ; extra == "doc"
Requires-Dist: sphinx-rtd-theme>=1.1.0 ; extra == "doc"
Requires-Dist: myst-parser ; extra == "doc"
-Requires-Dist: drf-spectacular>=0.27.1 ; extra == "openapi"
+Requires-Dist: drf-spectacular>=0.29.0 ; extra == "openapi"
Requires-Dist: inflection ; extra == "openapi"
Requires-Dist: flit ; extra == "release"
Requires-Dist: keyring ; extra == "release"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/drf_standardized_errors-0.15.0/docs/changelog.md
new/drf_standardized_errors-0.16.0/docs/changelog.md
--- old/drf_standardized_errors-0.15.0/docs/changelog.md 2025-06-09
09:45:41.652574300 +0200
+++ new/drf_standardized_errors-0.16.0/docs/changelog.md 2026-04-29
11:38:29.748675000 +0200
@@ -6,6 +6,21 @@
## [UNRELEASED]
+## [0.16.0] - 2026-04-29
+### Added
+- Add support for python 3.14
+- Add support for django 6.0
+- Add support for DRF 3.17
+
+### Changed (backward-incompatible)
+- Set the minimum version of drf-spectacular to 0.29.0
+- Account for the `format` query parameter raising 404 errors when generating
the API schema for error responses. This
+ will result in any project using the default value for
`REST_FRAMEWORK["URL_FORMAT_OVERRIDE"]` showing 404 errors for
+ every operation. That's because DRF enables the `format` query parameter in
every endpoint by default. If you don't
+ need the `format` query parameter for content negotiation, you can disable
it by setting `"URL_FORMAT_OVERRIDE"`
+ to `None` in DRF settings. Refer
+ to [DRF
docs](https://www.django-rest-framework.org/api-guide/settings/#url_format_override)
for more information.
+
## [0.15.0] - 2025-06-09
### Added
- add support for python 3.13
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/drf_standardized_errors-0.15.0/docs/openapi.md
new/drf_standardized_errors-0.16.0/docs/openapi.md
--- old/drf_standardized_errors-0.15.0/docs/openapi.md 2025-06-04
09:21:28.973895500 +0200
+++ new/drf_standardized_errors-0.16.0/docs/openapi.md 2026-04-27
10:56:18.842368800 +0200
@@ -107,6 +107,17 @@
## Tips and Tricks
+### Hide 404 error responses due to the `format` query parameter
+
+Set `REST_FRAMEWORK["URL_FORMAT_OVERRIDE"]` to `None` if you're not relying on
a query parameter for content
+negotiation. This avoids showing a 404 error response in the API schema for
every operation.
+
+By default, DRF sets the value for `REST_FRAMEWORK["URL_FORMAT_OVERRIDE"]` to
`"format"`. That allows API consumers to
+send a `format` query parameter in every operation for content negotiation. If
the API cannot handle the requested
+`format`, it will return a 404 error response. From the perspective of this
package, that means every operation can
+return a 404 response when using the default content negotiator. Refer
+to [DRF
docs](https://www.django-rest-framework.org/api-guide/settings/#url_format_override)
for more information.
+
### Hide error responses that show in every operation
By default, the error response for all supported status codes will be added to
the schema. Some of these status
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/drf_standardized_errors-0.15.0/drf_standardized_errors/__init__.py
new/drf_standardized_errors-0.16.0/drf_standardized_errors/__init__.py
--- old/drf_standardized_errors-0.15.0/drf_standardized_errors/__init__.py
2025-06-09 09:45:41.572369000 +0200
+++ new/drf_standardized_errors-0.16.0/drf_standardized_errors/__init__.py
2026-04-29 11:38:29.633885100 +0200
@@ -1,3 +1,3 @@
"""Standardize your API error responses."""
-__version__ = "0.15.0"
+__version__ = "0.16.0"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/drf_standardized_errors-0.15.0/drf_standardized_errors/formatter.py
new/drf_standardized_errors-0.16.0/drf_standardized_errors/formatter.py
--- old/drf_standardized_errors-0.15.0/drf_standardized_errors/formatter.py
2025-06-04 09:21:28.975020600 +0200
+++ new/drf_standardized_errors-0.16.0/drf_standardized_errors/formatter.py
2026-04-27 11:03:47.218747600 +0200
@@ -140,6 +140,6 @@
fifo.append((value, key, None))
else:
- errors.append(Error(detail.code, str(detail), attr))
+ errors.append(Error(detail.code, str(detail), attr)) # type:
ignore[union-attr]
return errors
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/drf_standardized_errors-0.15.0/drf_standardized_errors/openapi.py
new/drf_standardized_errors-0.16.0/drf_standardized_errors/openapi.py
--- old/drf_standardized_errors-0.15.0/drf_standardized_errors/openapi.py
2024-06-18 20:02:28.000000000 +0200
+++ new/drf_standardized_errors-0.16.0/drf_standardized_errors/openapi.py
2025-12-04 13:06:51.130367000 +0100
@@ -17,6 +17,7 @@
from rest_framework.pagination import CursorPagination, PageNumberPagination
from rest_framework.parsers import FileUploadParser, JSONParser,
MultiPartParser
from rest_framework.permissions import AllowAny, IsAuthenticated
+from rest_framework.settings import api_settings as drf_settings
from rest_framework.versioning import (
AcceptHeaderVersioning,
HostNameVersioning,
@@ -203,14 +204,21 @@
if parameter["in"] == "path"
]
)
+ # the default content negotiator can raise a 404 when no renderer can
handle
+ # the format parameter in the URL
+ content_negotiator = self.view.get_content_negotiator()
+ view_can_have_no_renderers = (
+ self.view.format_kwarg or drf_settings.URL_FORMAT_OVERRIDE
+ ) and isinstance(content_negotiator, DefaultContentNegotiation)
return (
paginator_can_raise_404
or versioning_scheme_can_raise_404
or has_path_parameters
+ or view_can_have_no_renderers
)
def _should_add_http405_error_response(self) -> bool:
- # API consumers can at all ties use the wrong method against any
endpoint
+ # API consumers can at all times use the wrong method against any
endpoint
return True
def _should_add_http406_error_response(self) -> bool:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/drf_standardized_errors-0.15.0/drf_standardized_errors/openapi_hooks.py
new/drf_standardized_errors-0.16.0/drf_standardized_errors/openapi_hooks.py
--- old/drf_standardized_errors-0.15.0/drf_standardized_errors/openapi_hooks.py
2024-01-21 20:27:22.000000000 +0100
+++ new/drf_standardized_errors-0.16.0/drf_standardized_errors/openapi_hooks.py
2025-12-04 09:09:29.596540200 +0100
@@ -2,6 +2,7 @@
# since it's a copy of drf-spectacular postprocessing hook
import re
from collections import defaultdict
+from collections.abc import MutableMapping
from drf_spectacular.hooks import postprocess_schema_enum_id_removal
from drf_spectacular.plumbing import (
@@ -83,8 +84,8 @@
for component_name, props in iter_prop_containers(schemas):
for prop_name, prop_schema in props.items():
if prop_schema.get("type") == "array":
- prop_schema = prop_schema.get("items", {})
- if "enum" not in prop_schema:
+ prop_schema = prop_schema.get("items")
+ if not isinstance(prop_schema, MutableMapping) or "enum" not in
prop_schema:
continue
prop_enum_cleaned_hash = extract_hash(prop_schema)
@@ -138,9 +139,9 @@
for prop_name, prop_schema in props.items():
is_array = prop_schema.get("type") == "array"
if is_array:
- prop_schema = prop_schema.get("items", {})
+ prop_schema = prop_schema.get("items")
- if "enum" not in prop_schema:
+ if not isinstance(prop_schema, MutableMapping) or "enum" not in
prop_schema:
continue
prop_enum_original_list = prop_schema["enum"]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/drf_standardized_errors-0.15.0/drf_standardized_errors/openapi_utils.py
new/drf_standardized_errors-0.16.0/drf_standardized_errors/openapi_utils.py
--- old/drf_standardized_errors-0.15.0/drf_standardized_errors/openapi_utils.py
2024-08-10 10:00:58.000000000 +0200
+++ new/drf_standardized_errors-0.16.0/drf_standardized_errors/openapi_utils.py
2026-04-28 23:59:24.480456600 +0200
@@ -1,6 +1,8 @@
from dataclasses import dataclass, field as dataclass_field
from typing import Any, Dict, List, Optional, Set, Type, Union
+import django
+import rest_framework
from django import forms
from django.core.validators import (
DecimalValidator,
@@ -230,12 +232,18 @@
sfields_with_error_codes: "List[InputDataField]",
) -> None:
for sfield in sfields_with_unique_together_validators:
- sfield.error_codes.add("unique")
unique_together_validators = [
validator
for validator in sfield.field.validators
if isinstance(validator, UniqueTogetherValidator)
]
+ if _drf_version() >= (3, 17) and django.VERSION >= (5, 0):
+ # drf 3.17 passes the `custom_violation_error` added in django 5.0
+ # to `drf.UniqueTogetherValidator`. Before that, the error code was
+ # hardcoded as `"unique"`
+ sfield.error_codes.update(v.code for v in
unique_together_validators)
+ else: # pragma: no cover
+ sfield.error_codes.add("unique")
# fields involved in a unique together constraint have an implied
# "required" state, so we're adding the "required" error code to them
implicitly_required_fields = set()
@@ -361,7 +369,7 @@
def get_error_codes_from_validators(
- field: Union[serializers.Field, forms.Field]
+ field: Union[serializers.Field, forms.Field],
) -> Set[str]:
error_codes = set()
@@ -501,3 +509,9 @@
response_only=True,
status_codes=[str(exc.status_code)],
)
+
+
+def _drf_version():
+ # we just care about major and minor drf versions
+ parts = rest_framework.VERSION.split(".")
+ return int(parts[0]), int(parts[1])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/drf_standardized_errors-0.15.0/pyproject.toml
new/drf_standardized_errors-0.16.0/pyproject.toml
--- old/drf_standardized_errors-0.15.0/pyproject.toml 2025-06-09
09:45:41.572369000 +0200
+++ new/drf_standardized_errors-0.16.0/pyproject.toml 2026-04-29
11:38:29.631886500 +0200
@@ -23,6 +23,7 @@
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
+ "Programming Language :: Python :: 3.14",
]
dynamic = ["version", "description"]
requires-python = ">=3.8"
@@ -59,14 +60,14 @@
"tbump",
]
openapi = [
- "drf-spectacular>=0.27.1",
+ "drf-spectacular>=0.29.0",
"inflection",
]
[tool.tbump]
[tool.tbump.version]
-current = "0.15.0"
+current = "0.16.0"
regex = '''
(?P<major>\d+)
\.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/drf_standardized_errors-0.15.0/tests/settings.py
new/drf_standardized_errors-0.16.0/tests/settings.py
--- old/drf_standardized_errors-0.15.0/tests/settings.py 2024-08-10
10:00:58.000000000 +0200
+++ new/drf_standardized_errors-0.16.0/tests/settings.py 2025-12-04
09:11:08.453064700 +0100
@@ -23,6 +23,7 @@
"DEFAULT_AUTHENTICATION_CLASSES": [],
"DEFAULT_PERMISSION_CLASSES": [],
"TEST_REQUEST_DEFAULT_FORMAT": "json",
+ "URL_FORMAT_OVERRIDE": None,
"DEFAULT_SCHEMA_CLASS": "drf_standardized_errors.openapi.AutoSchema",
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/drf_standardized_errors-0.15.0/tests/test_openapi.py
new/drf_standardized_errors-0.16.0/tests/test_openapi.py
--- old/drf_standardized_errors-0.15.0/tests/test_openapi.py 2025-06-04
09:21:28.978130000 +0200
+++ new/drf_standardized_errors-0.16.0/tests/test_openapi.py 2025-12-04
09:11:08.453064700 +0100
@@ -381,6 +381,19 @@
assert "404" in responses
+def test_404_error_when_url_format_enabled(settings):
+ settings.REST_FRAMEWORK = {
+ **settings.REST_FRAMEWORK,
+ "URL_FORMAT_OVERRIDE": "format",
+ }
+
+ route = "not-found/"
+ view = DummyView.as_view()
+ schema = generate_view_schema(route, view)
+ responses = get_responses(schema, route)
+ assert "404" in responses
+
+
def test_no_404_error():
route = "not-found/"
view = DummyView.as_view()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/drf_standardized_errors-0.15.0/tests/test_openapi_utils.py
new/drf_standardized_errors-0.16.0/tests/test_openapi_utils.py
--- old/drf_standardized_errors-0.15.0/tests/test_openapi_utils.py
2025-06-04 09:21:28.978130000 +0200
+++ new/drf_standardized_errors-0.16.0/tests/test_openapi_utils.py
2026-04-28 23:33:45.559983300 +0200
@@ -16,6 +16,7 @@
from drf_standardized_errors.openapi_utils import (
InputDataField,
+ _drf_version,
get_django_filter_backends,
get_error_serializer,
get_filter_forms,
@@ -372,6 +373,43 @@
assert "required" in model.error_codes
[email protected]
+def unique_together_with_violation_code():
+ from django.db import models
+
+ class SomeModel(models.Model):
+ app_label = models.CharField(max_length=100)
+ model = models.CharField(max_length=100)
+
+ class Meta:
+ constraints = [
+ models.UniqueConstraint(
+ fields=["app_label", "model"],
+ name="unique_model",
+ violation_error_code="custom_violation_code",
+ )
+ ]
+
+ class SomeSerializer(serializers.ModelSerializer):
+ class Meta:
+ model = SomeModel
+ fields = ["app_label", "model"]
+
+ return get_flat_serializer_fields(SomeSerializer())
+
+
[email protected](
+ _drf_version() < (3, 17) or django.VERSION < (5, 0),
+ reason="django added violation_error_code in v5 and drf supported it in
v3.17",
+)
+def test_unique_together_new(unique_together_with_violation_code):
+ non_field_errors, _, __ = get_serializer_fields_with_error_codes(
+ unique_together_with_violation_code
+ )
+
+ assert "custom_violation_code" in non_field_errors.error_codes
+
+
class PostSerializer(serializers.ModelSerializer):
"""
Intentional required=False to test that the 'required' error code is added
@@ -505,7 +543,7 @@
def test_char_fields_with_error_codes():
- (char, slug, regex, uuid, ip) =
get_form_fields_with_error_codes(CharForm())
+ char, slug, regex, uuid, ip = get_form_fields_with_error_codes(CharForm())
assert char.error_codes == {
"required",
@@ -535,7 +573,7 @@
def test_number_fields_with_error_codes():
- (integer, dec1, dec2, dec3, dec4) =
get_form_fields_with_error_codes(NumberForm())
+ integer, dec1, dec2, dec3, dec4 =
get_form_fields_with_error_codes(NumberForm())
assert integer.error_codes == {"required", "max_value", "min_value",
"invalid"}
assert dec1.error_codes == {
@@ -556,7 +594,7 @@
def test_temporal_fields_with_error_codes():
- (date, datetime, duration) =
get_form_fields_with_error_codes(TemporalForm())
+ date, datetime, duration = get_form_fields_with_error_codes(TemporalForm())
assert date.error_codes == {"required", "invalid"}
assert datetime.error_codes == {"invalid"}
@@ -587,7 +625,7 @@
def test_choice_fields_with_error_codes():
- (choice, multiple_choice) = get_form_fields_with_error_codes(ChoiceForm())
+ choice, multiple_choice = get_form_fields_with_error_codes(ChoiceForm())
assert choice.error_codes == {"required", "invalid_choice"}
assert multiple_choice.error_codes == {"invalid_choice", "invalid_list"}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/drf_standardized_errors-0.15.0/tox.ini
new/drf_standardized_errors-0.16.0/tox.ini
--- old/drf_standardized_errors-0.15.0/tox.ini 2025-06-04 09:21:28.979192500
+0200
+++ new/drf_standardized_errors-0.16.0/tox.ini 2026-04-27 14:17:37.477977500
+0200
@@ -12,6 +12,12 @@
py{310,311,312,313}-dj50-drf{314,315}
py{310,311,312,313}-dj{51,52}-drf315
py{310,311,312,313}-dj{42,50,51,52}-drf316
+ py314-dj52-drf316
+ py{312,313,314}-dj60-drf316
+ py{310,311,312}-dj{42,50}-drf317
+ py{310,311,312,313}-dj51-drf317
+ py{310,311,312,313,314}-dj52-drf317
+ py{312,313,314}-dj60-drf317
lint
docs
@@ -23,12 +29,13 @@
3.11: py311
3.12: py312, lint, docs
3.13: py313
+ 3.14: py314
[testenv]
deps =
pytest
pytest-django
- drf-spectacular>=0.27.1
+ drf-spectacular>=0.29.0
django-filter
dj32: Django>=3.2,<4.0
dj40: Django>=4.0,<4.1
@@ -37,11 +44,13 @@
dj50: Django>=5.0,<5.1
dj51: Django>=5.1,<5.2
dj52: Django>=5.2,<6.0
+ dj60: Django>=6.0,<6.1
drf312: djangorestframework>=3.12,<3.13
drf313: djangorestframework>=3.13,<3.14
drf314: djangorestframework>=3.14,<3.15
drf315: djangorestframework>=3.15,<3.16
drf316: djangorestframework>=3.16,<3.17
+ drf317: djangorestframework>=3.17,<3.18
commands =
pytest