Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: DTOData.create_instance() nested kwargs #1741

Merged
merged 8 commits into from May 28, 2023

Conversation

peterschutt
Copy link
Contributor

@peterschutt peterschutt commented May 26, 2023

This PR adds a feature to the DTOData.create_instance() method that supports providing values for arbitrarily nested data via kwargs using a double-underscore syntax. For example data.create_instance(foo__bar="baz").

In the following example, the DTO is configured to exclude the baz attribute from request data, but the field has no default, and so is required in order to be able to instantiate the hierarchy of models. The kwarg foo__baz="world" is passed to create_instance() call, which gives Bar.foo.baz a value.

from dataclasses import dataclass
from typing import Any, Dict

from typing_extensions import Annotated

from litestar import post
from litestar.dto.factory import DTOConfig, DTOData
from litestar.dto.factory.stdlib import DataclassDTO

@dataclass
class Foo:
    bar: str
    baz: str

@dataclass
class Bar:
    foo: Foo

config = DTOConfig(exclude={"foo.baz"})
dto = DataclassDTO[Annotated[Bar, config]]

@post(dto=dto, return_dto=None)
def handler(data: DTOData[Bar]) -> Dict[str, Any]:
    res = data.create_instance(foo__baz="world")
    assert res.foo.baz == "world"
    return res

Closes #1727

This commit modifies the way that DTO backends manage their `TransferFieldDefinition` instances.

Previously, the backend would not keep a field definition for excluded fields, however, this proved
limiting when wanting to use the `factory._backends.utils.transfer_instance_data()` method to move
data from unstructured builtins to data model instances. In this scenario, and generally whenever we
are moving inbound data from a transfer model to the data model, we need to transfer a value for all
fields, including fields that are excluded from request and response data, unless an omitted field has
a default value.

Adds an `is_excluded` attribute to `TransferFieldDefinition` so that generated transfer models can
still omit the field, and so that the field can still be omitted from return data.

We no longer modify the `TransferFieldDefinition` type and defaults in the case of `is_partial`.
Instead, the backend implementations do the `UnsetType` splicing at transfer model generation time.
This is important so that we can still discern when a field definition originally had a default value
specified, after the partial handling has been applied.
@peterschutt peterschutt force-pushed the 1727-create-instance-nested-kwargs branch from 9a3b262 to 9198419 Compare May 26, 2023 14:45
@peterschutt peterschutt marked this pull request as ready for review May 26, 2023 15:08
@peterschutt peterschutt requested a review from a team as a code owner May 26, 2023 15:08
Copy link
Member

@provinzkraut provinzkraut left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! A section about this feature in the docs would be nice I think.

@peterschutt
Copy link
Contributor Author

Looks good! A section about this feature in the docs would be nice I think.

Cheers! Yes, I will add to the tutorial and a How To section in usage docs before I close out.

@peterschutt peterschutt force-pushed the 1727-create-instance-nested-kwargs branch from b662312 to 670f5f6 Compare May 26, 2023 15:28
@github-actions
Copy link

Documentation preview will be available shortly at https://litestar-org.github.io/litestar-docs-preview/1741

@sonarcloud
Copy link

sonarcloud bot commented May 28, 2023

Kudos, SonarCloud Quality Gate passed!    Quality Gate passed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 0 Code Smells

100.0% 100.0% Coverage
0.0% 0.0% Duplication

@peterschutt peterschutt changed the title 1727 create instance nested kwargs Feature: DTOData.create_instance() nested kwargs May 28, 2023
@peterschutt peterschutt merged commit 7ee9ffd into main May 28, 2023
12 of 13 checks passed
@peterschutt peterschutt deleted the 1727-create-instance-nested-kwargs branch May 28, 2023 05:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Enhancement: DataDTO.create_instance() accept kwargs for initializing nested fields
2 participants