Skip to content

Commit

Permalink
chore, python: generate union v2 templates (#4167)
Browse files Browse the repository at this point in the history
  • Loading branch information
armandobelardo authored Aug 1, 2024
1 parent 779aa0a commit 4a172e4
Show file tree
Hide file tree
Showing 43 changed files with 2,395 additions and 128 deletions.
4 changes: 4 additions & 0 deletions generators/python/fastapi/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ 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).

## [1.1.0-rc0] - 2024-07-31

- Internal: The generator now consumes IRv53.

## [1.0.0-rc0] - 2024-07-16

- Break: The generated server stubs now support Pydantic V2 outright, it no longer uses `pydantic.v1` models. This change introduces additional breaks:
Expand Down
2 changes: 1 addition & 1 deletion generators/python/fastapi/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.0.0-rc0
1.1.0-rc0
16 changes: 8 additions & 8 deletions generators/python/poetry.lock

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

4 changes: 4 additions & 0 deletions generators/python/pydantic/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ 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).

## [1.1.0-rc0] - 2024-07-31

- Internal: The generator now consumes IRv53.

## [1.0.0-rc0] - 2024-07-16

- Break: The generated models now support Pydantic V2 outright, it no longer uses `pydantic.v1` models. This change introduces additional breaks:
Expand Down
2 changes: 1 addition & 1 deletion generators/python/pydantic/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.0.0-rc0
1.1.0-rc0
4 changes: 2 additions & 2 deletions generators/python/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ typer = {extras = ["all"], version = "^0.6.1"}
fern-fern-generator-exec-sdk = {version = "0.0.899", source = "fern-prod"}
ordered-set = "^4.1.0"
pydantic-core = "^2.18.2"
fern-fern-fdr-sdk = {version = "0.0.5502", source = "fern-prod"}
fern-fern-fdr-sdk = {version = "0.0.5525", source = "fern-prod"}
fern-fern-generator-cli-sdk = {version = "0.0.39", source = "fern-prod"}
fern_fern_ir_v50 = "50.0.0"
fern_fern_ir_v53 = "53.1.0"

[tool.poetry.dev-dependencies]
pytest = "^7.4.2"
Expand Down
5 changes: 5 additions & 0 deletions generators/python/sdk/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ 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).

## [3.3.0-rc0] - 2024-07-31

- internal: Upgrade to IR 53.1.0
- chore: The Python generator now creates snippet templates for undiscriminated unions.

## [3.2.0-rc1] - 2024-07-29

- Fix: The generated README now imports `ApiError` as if it were from outside the module.
Expand Down
2 changes: 1 addition & 1 deletion generators/python/sdk/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.2.0-rc1
3.3.0-rc0
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,21 @@ def get_initializer_for_type_reference(
union = type_reference.get_as_union()
if union.type == "primitive":
maybe_v2_scheme = union.primitive.v_2
if maybe_v2_scheme is not None and maybe_v2_scheme.get_as_union().default is not None:
if maybe_v2_scheme is not None:
default_value = maybe_v2_scheme.visit(
integer=lambda it: AST.Expression(f"{it.default}"),
double=lambda dt: AST.Expression(f"{dt.default}"),
string=lambda st: AST.Expression(f'"{st.default}"'),
boolean=lambda bt: AST.Expression(f"{bt.default}"),
long_=lambda lt: AST.Expression(f"{lt.default}"),
big_integer=lambda bit: AST.Expression(f"{bit.default}"),
integer=lambda it: AST.Expression(f"{it.default}") if it.default is not None else None,
double=lambda dt: AST.Expression(f"{dt.default}") if dt.default is not None else None,
string=lambda st: AST.Expression(f'"{st.default}"') if st.default is not None else None,
boolean=lambda bt: AST.Expression(f"{bt.default}") if bt.default is not None else None,
long_=lambda lt: AST.Expression(f"{lt.default}") if lt.default is not None else None,
big_integer=lambda bit: AST.Expression(f'"{bit.default}"') if bit.default is not None else None,
uint=lambda _: None,
uint_64=lambda _: None,
date=lambda _: None,
date_time=lambda _: None,
uuid_=lambda _: None,
base_64=lambda _: None,
float_=lambda _: None,
)
return default_value

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Callable, Optional
from typing import Callable, Optional, cast

import fern.ir.resources as ir_types

Expand Down Expand Up @@ -34,7 +34,7 @@ def get_type_hint_for_type_reference(
for_typeddict=for_typeddict,
),
named=lambda type_name: self._get_type_hint_for_named(
type_name=type_name,
type_name=cast(ir_types.DeclaredTypeName, type_name),
must_import_after_current_declaration=must_import_after_current_declaration,
as_request=in_endpoint if in_endpoint is not None else False,
as_if_type_checking_import=as_if_type_checking_import,
Expand Down Expand Up @@ -137,7 +137,7 @@ def _get_type_hint_for_container(
)
),
named=lambda type_reference: self._get_set_type_hint_for_named(
type_reference,
cast(ir_types.DeclaredTypeName, type_reference),
must_import_after_current_declaration=must_import_after_current_declaration,
as_if_type_checking_import=as_if_type_checking_import,
in_endpoint=in_endpoint,
Expand Down Expand Up @@ -204,5 +204,8 @@ def _get_type_hint_for_primitive(self, primitive: ir_types.PrimitiveType) -> AST
date=AST.TypeHint.date,
base_64=AST.TypeHint.str_,
big_integer=AST.TypeHint.str_,
uint=AST.TypeHint.int_,
uint_64=AST.TypeHint.int_,
float_=AST.TypeHint.float_,
)
return to_return
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from typing import cast

import fern.ir.resources as ir_types
from typing_extensions import assert_never

Expand Down Expand Up @@ -30,7 +32,9 @@ def convert_to_singular_type(context: FastApiGeneratorContext, type: ir_types.Ty
context, ir_types.TypeReference.factory.container(resolved_type_union.container)
)
elif resolved_type_union.type == "named":
return convert_to_singular_type(context, ir_types.TypeReference.factory.named(resolved_type_union.name))
return convert_to_singular_type(
context, ir_types.TypeReference.factory.named(cast(ir_types.NamedType, resolved_type_union.name))
)
elif resolved_type_union.type == "unknown":
return convert_to_singular_type(context, ir_types.TypeReference.factory.unknown())
elif resolved_type_union.type != "void":
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import List, Optional, Set
from typing import List, Optional, Set, cast

import fern.ir.resources as ir_types
from typing_extensions import Never
Expand Down Expand Up @@ -227,7 +227,9 @@ def generate(self) -> None:
AST.FunctionParameter(
name=BUILDER_ARGUMENT_NAME,
type_hint=self._context.get_type_hint_for_type_reference(
ir_types.TypeReference.factory.named(type_name)
ir_types.TypeReference.factory.named(
cast(ir_types.NamedType, type_name)
)
),
)
],
Expand All @@ -240,7 +242,7 @@ def generate(self) -> None:
no_properties=lambda: None,
),
return_type=self._context.get_type_hint_for_type_reference(
ir_types.TypeReference.factory.named(self._name)
ir_types.TypeReference.factory.named(cast(ir_types.NamedType, self._name))
),
),
body=AST.CodeWriter(
Expand Down Expand Up @@ -315,7 +317,7 @@ def generate(self) -> None:
)
),
type=external_pydantic_model.get_type_hint_for_type_reference(
ir_types.TypeReference.factory.named(type_name)
ir_types.TypeReference.factory.named(cast(ir_types.NamedType, type_name))
),
),
single_property=lambda property: VisitorArgument(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,11 +211,15 @@ def get_union_generator(union: ir_types.UnionTypeDeclaration) -> AbstractTypeGen
def _get_snippet_for_type_declaration(
self, declaration: ir_types.TypeDeclaration
) -> Tuple[Optional[AST.Expression], Optional[str]]:
if len(self._declaration.examples) == 0:
examples = self._declaration.user_provided_examples
if len(examples) == 0:
examples.extend(self._declaration.autogenerated_examples)

if len(examples) == 0:
return None, None
expr = self._snippet_writer.get_snippet_for_example_type_shape(
name=self._declaration.name,
example_type_shape=declaration.examples[0].shape,
example_type_shape=examples[0].shape,
)
if expr is None:
return None, None
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,13 @@ def to_snippet(self) -> AST.Expression:
return AST.Expression("TODO")

def finish(self) -> None:
if self._type_declaration is not None and len(self._type_declaration.examples) > 0:
examples = []
if self._type_declaration is not None:
examples.extend(self._type_declaration.user_provided_examples)
if len(examples) == 0:
examples.extend(self._type_declaration.autogenerated_examples)

if self._type_declaration is not None and len(examples) > 0:
snippet = SourceFileFactory.create_snippet()
snippet.add_expression(self.to_snippet())
self._class_declaration.add_snippet(snippet.to_str())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1241,7 +1241,7 @@ def _does_type_reference_match_primitives(
allow_optional: bool,
allow_enum: bool,
) -> bool:
def visit_named_type(type_name: ir_types.DeclaredTypeName) -> bool:
def visit_named_type(type_name: ir_types.NamedType) -> bool:
type_declaration = self._context.pydantic_generator_context.get_declaration_for_type_id(type_name.type_id)
return type_declaration.shape.visit(
alias=lambda alias: self._does_type_reference_match_primitives(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import json
import os
import uuid
from typing import Literal, Optional, Sequence, Tuple, Union, cast
from uuid import uuid4

Expand Down Expand Up @@ -521,7 +522,10 @@ def _maybe_write_snippet_templates(
# API Definition ID doesn't matter right now
try:
fdr_client.templates.register_batch(
org_id=org_id, api_id=api_name, api_definition_id=uuid4(), snippets=snippets
org_id=org_id,
api_id=api_name,
api_definition_id=uuid.UUID(ir.fdr_api_definition_id) or uuid4(),
snippets=snippets,
)
generator_exec_wrapper.send_update(
GeneratorUpdate.factory.log(
Expand Down
Loading

0 comments on commit 4a172e4

Please sign in to comment.