Skip to content

fix(python): pydantic v2 discriminator #3758

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

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,25 @@ public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List<Mo
return operations;
}

@Override
public Map<String, ModelsMap> postProcessAllModels(Map<String, ModelsMap> objs) {
Map<String, ModelsMap> models = super.postProcessAllModels(objs);
OneOf.updateModelsOneOf(models, modelPackage);
GenericPropagator.propagateGenericsToModels(models, true);
OneOf.addOneOfMetadata(models);
jsonParent(models);
return models;
}

private static void jsonParent(Map<String, ModelsMap> models) {
for (ModelsMap modelContainer : models.values()) {
CodegenModel model = modelContainer.getModels().get(0).getModel();
if (model.parent != null && model.parent.startsWith("AbstractMap")) {
model.vendorExtensions.put("x-map-parent", true);
}
}
}

@Override
public ModelsMap postProcessModels(ModelsMap objs) {
// this is to prevent F811 from flake8 because we have some recusrive models
Expand Down
9 changes: 5 additions & 4 deletions playground/python/app/search.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@ async def main():
print("client initialized", client)

try:
await client.browse_objects(
index_name="api-clients-automation",
aggregator=lambda _resp: print("baaaaaaaaaaaaaaar", _resp.to_json()),
)
resp = await client.search(search_method_params={
"requests": [{"indexName": "api-clients-automation"}]
})
print(resp.to_json())
print(resp.to_dict())
finally:
await client.close()

Expand Down
140 changes: 136 additions & 4 deletions playground/python/poetry.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion playground/python/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ homepage = "https://www.algolia.com"
repository = "https://github.com/algolia/api-clients-automation"

[tool.poetry.dependencies]
python = "^3.8.1"
python = ">= 3.8.1"
algoliasearch = { path = "../../clients/algoliasearch-client-python", develop = true }
ruff = "== 0.6.4"
python-dotenv = "== 1.0.1"
Expand Down
2 changes: 1 addition & 1 deletion scripts/formatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export async function formatter(language: string, cwd: string): Promise<void> {
break;
case 'python':
await run(
'poetry lock --no-update && poetry install --sync && pip freeze > requirements.txt && poetry run ruff check --fix && poetry run ruff format',
'poetry lock --no-update && poetry install --sync && pip freeze > requirements.txt && poetry run ruff check --fix --unsafe-fixes && poetry run ruff format',
{ cwd, language },
);
break;
Expand Down
3 changes: 2 additions & 1 deletion specs/common/schemas/HighlightResult.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,13 @@ highlightResultOptionArray:
items:
$ref: '#/highlightResultOption'

# TODO: create a rule that sorts oneOf per number of discriminator in case they share the same primitive type
highlightResult:
oneOf:
- $ref: '#/highlightResultMap'
- $ref: '#/highlightResultOption'
- $ref: '#/highlightResultOptionMap'
- $ref: '#/highlightResultOptionArray'
- $ref: '#/highlightResultMap'

highlightResultMap:
type: object
Expand Down
6 changes: 1 addition & 5 deletions specs/ingestion/common/schemas/destination.yml
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ DestinationType:
Data is recorded as user events in the Insights API.
enum: [search, insights]

DestinationIndexName:
DestinationInput:
type: object
additionalProperties: false
properties:
Expand Down Expand Up @@ -151,7 +151,3 @@ AttributesToExclude:
Use `*` as wildcard: `foo.[*].bar` excludes `bar` from all elements of the `foo` array.
items:
type: string

DestinationInput:
oneOf:
- $ref: '#/DestinationIndexName'
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ searchForFacetValuesResponse:
- exhaustiveFacetsCount
x-discriminator-fields:
- facetHits
- exhaustiveFacetsCount
properties:
facetHits:
type: array
Expand Down
13 changes: 10 additions & 3 deletions templates/python/imports.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ from __future__ import annotations
import base64
import hashlib
import hmac
import json
import pprint
import re
from sys import version_info
from warnings import warn
from random import randint
Expand All @@ -17,11 +20,13 @@ from json import (
from pydantic import (
BaseModel,
ConfigDict,
Discriminator,
Field,
StrictBool,
StrictFloat,
StrictInt,
StrictStr,
Tag,
ValidationError,
field_validator,
model_serializer,
Expand All @@ -33,16 +38,18 @@ from typing import (
Dict,
Iterator,
List,
Literal,
Optional,
Set,
Tuple,
Union,
)

from typing_extensions import Annotated

if version_info >= (3, 11):
from typing import Self, Annotated
from typing import Literal, Self
else:
from typing_extensions import Self, Annotated
from typing_extensions import Literal, Self

from algoliasearch.http.helpers import create_iterable, create_iterable_sync, RetryTimeout
from algoliasearch.http.serializer import bodySerializer, QueryParametersSerializer
Expand Down
4 changes: 2 additions & 2 deletions templates/python/model.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
{{> model_enum}}
{{/isEnum}}
{{^isEnum}}
{{#oneOf}}{{#-first}}{{> model_oneof}}{{/-first}}{{/oneOf}}{{^oneOf}}{{#anyOf}}{{#-first}}{{> model_anyof}}{{/-first}}{{/anyOf}}{{^anyOf}}{{> model_generic}}{{/anyOf}}{{/oneOf}}
{{#oneOf}}{{#-first}}{{> model_oneof}}{{/-first}}{{/oneOf}}{{^oneOf}}{{> model_generic}}{{/oneOf}}
{{/isEnum}}
{{/model}}
{{/models}}
{{/models}}
22 changes: 5 additions & 17 deletions templates/python/model_enum.mustache
Original file line number Diff line number Diff line change
@@ -1,25 +1,13 @@
class {{classname}}({{vendorExtensions.x-py-enum-type}}, Enum):
{{> model_description}}
{{>model_description}}

"""
allowed enum values
"""
{{#allowableValues}}
{{#enumVars}}
{{{name}}} = {{{value}}}
{{/enumVars}}

@classmethod
def from_json(cls, json_str: str) -> Self:
"""Create an instance of {{classname}} from a JSON string"""
return cls(loads(json_str))

{{#defaultValue}}

#
@classmethod
def _missing_value_(cls, value):
if value is no_arg:
return cls.{{{.}}}
{{/defaultValue}}
{{/allowableValues}}
def from_json(cls, raw_str: str) -> Self:
"""Create an instance of {{classname}} from a string"""
return cls(raw_str)
{{/allowableValues}}
Loading
Loading