Skip to content

Version 0.13.0

Latest

Choose a tag to compare

@sobolevn sobolevn released this 10 Aug 14:36
· 2 commits to master since this release
d5590b9

Features overview

1. Django 6.1 official support

It was released last week, now we are fully sure that DMR works with the most modern Django version.


2. Router.include() — compose routers

from dmr.routing import Router

api_v1 = Router()
api_v1.include(users_router, prefix="/users")
api_v1.include(orders_router, prefix="/orders")

3. external_path() — mount external views

from dmr.routing import external_path

urlpatterns = [
    external_path("webhook/", third_party_view),
]

4. Skip controllers/endpoints from OpenAPI

from dmr import Controller
from dmr.plugins.msgspec import MsgspecSerializer

class InternalController(Controller[MsgspecSerializer]):
    ignore_from_spec = True

    def get(self) -> InternalStatus: ...

5. extra_namespace in BaseSerializer.from_python

Now available on all serializers:

schema = PydanticSerializer.from_python(
    MyModel,
    extra_namespace={"MyForwardRef": MyForwardRef},
)

6. Load external OpenAPI schemas into typed dataclasses

from dmr.openapi.openapi import OpenAPI
from dmr.openapi import load_schema

schema = load_schema(external_schema_dict, OpenAPI)

7. --skip-validation flag for dmr_export_schema

python manage.py dmr_export_schema --skip-validation > openapi.json

8. dmr.test.disabled_auth — speed up tests

from dmr.test import disabled_auth, DMRRequestFactory

def test_list_users(dmr_rf: DMRRequestFactory, user: User) -> None:
    request = dmr_rf.get('/api/your-controller')
    with disabled_auth(YourController, request=request, user=user):
        response = YourController.as_view()(request)
    assert response.status_code == 200

Migration prompt

They cover all the breaking changes.
We had to make them, so the API would be top notch in the future.
There was a big overhaul of OpenAPI and routing in this release.
Now we can do a lot of amazing things easily. But, the cost was backward compatibility.

You are migrating a Python project from `django-modern-rest` 0.12.0 to 0.13.0.
Load the latest documentation from https://django-modern-rest.readthedocs.io/llms-full.txt
before making any changes.

Apply **all** of the following breaking changes to the codebase.
For each change, search the entire project (including tests, fixtures, and
any helper modules) before editing.

---

### 1. `Schema.then``Schema.schema_then`

Find every attribute access or contructor param`then` on a `Schema` class
or instance and rename it to `schema_then`.

Before:
    Schema(then=...)
    schema.then

After:
    Schema(schema_then=...)
    schema.schema_then

---

### 2. `dmr.openapi.objects.openapi.convert``dmr.openapi.mappers.schema_normalization.dump_schema`

Find all imports and call-sites of `convert` from
`dmr.openapi.objects.openapi` and replace them:

Before:
    from dmr.openapi.objects.openapi import convert
    convert(...)

After:
    from dmr.openapi.mappers.schema_normalization import dump_schema
    dump_schema(...)

---

### 3. Remove `normalize_key` and `normalize_value`

Find all imports and usages of `normalize_key` and `normalize_value`
from `dmr.openapi.objects.openapi` and remove them entirely.
These functions have been deleted with no replacement.
If they are called inline, investigate whether the call site can be
removed or rewritten without them (consult the updated docs).
Use `dump_schema` directly instead.

Before:
    from dmr.openapi.objects.openapi import normalize_key, normalize_value

After:
    # remove the import and all call sites

---

### 4. `dmr.openapi.objects.openapi.ConvertedSchema``dmr.openapi.mappers.schema_normalization.DumpedSchema`

Before:
    from dmr.openapi.objects.openapi import ConvertedSchema

After:
    from dmr.openapi.mappers.schema_normalization import DumpedSchema

Replace all type annotations, isinstance checks, and other usages
of `ConvertedSchema` with `DumpedSchema`.

---

### 5. Remove `dmr.openapi.views.base.DumpedSchema`

Find all imports of `DumpedSchema` from `dmr.openapi.views.base` and remove
them. It was a plain `str` type alias; replace any annotation that used it
with the built-in `str`.

Before:
    from dmr.openapi.views.base import DumpedSchema
    def foo() -> DumpedSchema: ...

After:
    def foo() -> str: ...

---

### 6. `dmr.openapi.objects.OpenAPI``dmr.openapi.openapi.OpenAPI`

Before:
    from dmr.openapi.objects import OpenAPI

After:
    from dmr.openapi.openapi import OpenAPI

---

### 7. `rebuild_namespace``extra_namespace` in `PydanticSerializer.from_python`

Find every call to `PydanticSerializer.from_python(...)` that passes a
`rebuild_namespace` keyword argument and rename the parameter.

Before:
    PydanticSerializer.from_python(..., rebuild_namespace=ns)

After:
    PydanticSerializer.from_python(..., extra_namespace=ns)

---

### 8. `skip_validation` must be keyword-only on `OpenAPIView.as_view()` and subclasses

Find all call sites of `.as_view()` on `OpenAPIView` or any of its
subclasses where `skip_validation` is passed as a positional argument and
make it explicit.

Before:
    MyOpenAPIView.as_view(schema, True)          # skip_validation passed positionally

After:
    MyOpenAPIView.as_view(schema, skip_validation=True)

Also update any subclass overrides of `as_view` so that `skip_validation`
appears after a bare `*` in the signature:

Before:
    @classmethod
    def as_view(cls, skip_validation=False, **kwargs): ...

After:
    @classmethod
    def as_view(cls, *, skip_validation=False, **kwargs): ...

---

### 9. `Controller.get_path_item``Controller.get_schema`

Find every definition and call site of `get_path_item` on any
`Controller` subclass and rename it to `get_schema`.

Before:
    class MyController(Controller):
        def get_path_item(self, router): ...

    controller.get_path_item(router)

After:
    class MyController(Controller):
        def get_schema(self, router): ...

    controller.get_schema(router)

---

### 10. Remove `dmr_assert_throttling` and `dmr_assert_async_throttling` pytest fixtures

These are no longer fixtures. Find every use of them as pytest fixtures
(i.e. as function parameters in test functions) and replace them with
direct function calls instead.

Before:
    def test_my_endpoint(dmr_assert_throttling):
        dmr_assert_throttling(client, url)

After:
    from dmr.test.throttling import assert_throttling   # adjust import as needed

    def test_my_endpoint():
        assert_throttling(client, url)

Do the same for `dmr_assert_async_throttling`.

---

### 11. Remove `dmr.test.types` module

Find all imports from `dmr.test.types` and replace them with the new
location:

Before:
    from dmr.test.types import ThrottlingWhen

After:
    from dmr.test.throttling import ThrottlingWhen

Any other symbols that were imported from `dmr.test.types` should be
investigated; if they no longer exist, remove them.

What's Changed

Breaking changes

Since this release, we would only publish migration prompts
on the releases page: https://github.com/wemake-services/django-modern-rest/releases

  • Schema.then is renamed to be Schema.schema_then
    to be consistent with other similar names, #1221
  • dmr.openapi.objects.openapi.convert function is renamed and moved
    to dmr.openapi.mappers.schema_normalization.dump_schema, #1221
  • dmr.openapi.objects.openapi.normalize_key
    and dmr.openapi.objects.openapi.normalize_value functions are removed, #1221
  • dmr.openapi.objects.openapi.ConvertedSchema is renamed and moved
    to dmr.openapi.mappers.schema_normalization.DumpedSchema, #1221
  • dmr.openapi.views.base.DumpedSchema is removed,
    it was just a str type alias, #1221
  • dmr.openapi.objects.OpenAPI is moved
    to dmr.openapi.openapi.OpenAPI, #1222
  • rebuild_namespace parameter in PydanticSerializer.from_python
    was renamed to extra_namespace, #1222
  • Changed skip_validation parameter to be kw-only
    on OpenAPIView.as_view() and all its subclasses, #1229
  • Renamed dmr.controller.Controller.get_path_item to
    get_schema, so all methods will be consistent, #1238
  • Removed dmr_assert_throttling and dmr_assert_async_throttling
    fixtures from pytest, because there was ever no need to make them fixtures,
    use regular functions instead, #1245
  • Removed dmr.test.types module, because it was only needed
    for dmr_pytest throttling fixtures, #1245
  • Moved dmr.test.types.ThrottlingWhen to dmr.test.throttling, #1245

Features

  • Django 6.1 official support, #1214
  • Added --skip-validation to the dmr_export_schema management command, #1225
  • Added extra_namespace parameter to BaseSerializer.from_python
    and all its existing subclasses, #1222
  • Added an ability to load external OpenAPI schemas
    into our typed dataclasses, #1222
  • Added external_path() function, so we can load external views, #1239
  • Added Router.include() method to include one router into another one, #1244
  • Added an option to skip some controllers / endpoints
    from the OpenAPI spec, #1238
  • Added dmr.test.disabled_auth test helper
    to disable auth to speed up tests, #1216

Bugfixes

  • Fixed a bug that OpenAPIConfig.components were silently
    ignored when defined with custom user's data, #1229
  • Fixed missing $ref, $anchor, $comment, and $schema fields in Schema, #1232
  • Fixed OpenAPIFormat.IRI value, #1228

Misc

  • Improved testing docs, #1216

New Contributors

Full Changelog: 0.12.1...0.13.0