Skip to content

Commit

Permalink
feat, python: allow extra fields not specified in model to come throu…
Browse files Browse the repository at this point in the history
…gh (#3131)
  • Loading branch information
armandobelardo authored Mar 8, 2024
1 parent 2f8bfcc commit 48a16a8
Show file tree
Hide file tree
Showing 620 changed files with 5,724 additions and 101 deletions.
29 changes: 29 additions & 0 deletions generators/python/sdk/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,35 @@ All notable changes to this project will be documented in this file.
The format is based on [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).

## [0.11.10] - 2024-03-08

- feature: Expose a feature flag to pass through additional properties not specified within your pydantic model from your SDK. This allows for easier forward compatibility should your SDK drift behind your spec.

Config:

```yaml
generators:
- name: fernapi/fern-python-sdk
...
config:
pydantic_config:
extra_fields: "allow"
```
Example generated code:
```python
# my_object.py
class MyObject(pydantic.BaseModel):
string: typing.Optional[str] = None
...

# main.py
o = pydantic.parse_obj_as(MyObject, {"string": "string", "my_new_property": "custom_value"})

print(o.my_new_property) # <--- "custom_value"
```

## [0.11.9] - 2024-03-04

- chore: Use docstrings instead of Pydantic field descriptions. This is meant to be a cleanliness change.
Expand Down
2 changes: 1 addition & 1 deletion generators/python/sdk/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.11.9
0.11.10
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ class Extra:
def forbid(version: PydanticVersionCompatibility) -> AST.Expression:
return AST.Expression(_export(version, "Extra", "forbid"))

@staticmethod
def allow(version: PydanticVersionCompatibility) -> AST.Expression:
return AST.Expression(_export(version, "Extra", "allow"))

@staticmethod
def root_validator(version: PydanticVersionCompatibility, pre: bool = False) -> AST.FunctionInvocation:
return AST.FunctionInvocation(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ def run(
custom_config = FastAPICustomConfig.parse_obj(generator_config.custom_config or {})
self._pydantic_model_custom_config = PydanticModelCustomConfig(
forbid_extra_fields=True,
extra_fields="forbid",
wrapped_aliases=True,
include_union_utils=True,
include_validators=custom_config.include_validators,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from typing import Literal, Optional

import pydantic

from ...external_dependencies.pydantic import PydanticVersionCompatibility
Expand All @@ -13,7 +15,9 @@ class BasePydanticModelCustomConfig(pydantic.BaseModel):

class PydanticModelCustomConfig(BasePydanticModelCustomConfig):
include_validators: bool = False
# DEPRECATED: use `extra_fields` instead
forbid_extra_fields: bool = False
extra_fields: Optional[Literal["allow", "forbid"]] = "allow"
wrapped_aliases: bool = False
skip_formatting: bool = False
include_union_utils: bool = False
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def __init__(
else None,
docstring=docstring,
snippet=snippet,
forbid_extra_fields=custom_config.forbid_extra_fields,
extra_fields="forbid" if custom_config.forbid_extra_fields else custom_config.extra_fields,
frozen=custom_config.frozen,
orm_mode=custom_config.orm_mode,
smart_union=custom_config.smart_union,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import dataclasses
from types import TracebackType
from typing import Iterable, List, Optional, Sequence, Tuple, Type, Union
from typing import Iterable, List, Literal, Optional, Sequence, Tuple, Type, Union

from fern_python.codegen import AST, ClassParent, LocalClassReference, SourceFile
from fern_python.external_dependencies import Pydantic, PydanticVersionCompatibility
Expand Down Expand Up @@ -33,7 +33,7 @@ def __init__(
parent: ClassParent = None,
docstring: Optional[str] = None,
snippet: Optional[str] = None,
forbid_extra_fields: bool = False,
extra_fields: Optional[Literal["allow", "forbid"]] = None,
):
self._source_file = source_file
self._class_declaration = AST.ClassDeclaration(
Expand All @@ -50,7 +50,7 @@ def __init__(
self._version = version
self._root_type: Optional[AST.TypeHint] = None
self._fields: List[PydanticField] = []
self._forbid_extra_fields = forbid_extra_fields
self._extra_fields = extra_fields
self._frozen = frozen
self._orm_mode = orm_mode
self._smart_union = smart_union
Expand Down Expand Up @@ -306,13 +306,20 @@ def _add_config_class(self) -> None:
)
)

if self._forbid_extra_fields:
if self._extra_fields == "forbid":
config.add_class_var(
AST.VariableDeclaration(
name="extra",
initializer=Pydantic.Extra.forbid(self._version),
)
)
elif self._extra_fields == "allow":
config.add_class_var(
AST.VariableDeclaration(
name="extra",
initializer=Pydantic.Extra.allow(self._version),
)
)

if len(self.json_encoders) > 0:
config.add_class_var(
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions seed/pydantic/alias/src/seed/alias/type.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 48a16a8

Please sign in to comment.