From 47e4ee976a9359db8e6f9fb175119ca4bfbcf44f Mon Sep 17 00:00:00 2001 From: Justin Black Date: Fri, 5 Apr 2024 10:18:13 -0700 Subject: [PATCH 1/2] Adds fix for python generator --- .../python/components/schemas/types/schema_io_type.hbs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/python/components/schemas/types/schema_io_type.hbs b/src/main/resources/python/components/schemas/types/schema_io_type.hbs index 02329b5ee3c..e4d8d359069 100644 --- a/src/main/resources/python/components/schemas/types/schema_io_type.hbs +++ b/src/main/resources/python/components/schemas/types/schema_io_type.hbs @@ -27,7 +27,7 @@ {{#eq types.size 1}} {{> components/schemas/types/_schema_io_type_base }} {{else}} -{{#if paramName}}{{paramName}}: {{/if}}typing.Union[ +{{#if paramName}}{{#if quote}}"{{/if}}{{paramName}}{{#if quote}}"{{/if}}: {{/if}}typing.Union[ {{> components/schemas/types/_schema_io_type_base paramName=false optional=false endChar="," }} {{#if optional}} schemas.Unset From 98c36acf258fe41e7e653dbeb7f1014c470bf6a5 Mon Sep 17 00:00:00 2001 From: Justin Black Date: Fri, 5 Apr 2024 10:40:03 -0700 Subject: [PATCH 2/2] Updates samples --- .../schemas/ObjectWithOnlyOptionalProps.md | 150 ++++++++++- .../schemas/ObjectWithOnlyOptionalProps.java | 240 ++++++++++++++++-- .../schema/object_with_only_optional_props.md | 61 +++++ .../schema/object_with_only_optional_props.py | 118 +++++++++ .../3_0/python/petstore_customized.yaml | 5 + 5 files changed, 545 insertions(+), 29 deletions(-) diff --git a/samples/client/petstore/java/docs/components/schemas/ObjectWithOnlyOptionalProps.md b/samples/client/petstore/java/docs/components/schemas/ObjectWithOnlyOptionalProps.md index 07210db764b..dfc26028d59 100644 --- a/samples/client/petstore/java/docs/components/schemas/ObjectWithOnlyOptionalProps.md +++ b/samples/client/petstore/java/docs/components/schemas/ObjectWithOnlyOptionalProps.md @@ -6,6 +6,8 @@ A class that contains necessary nested - schema classes (which validate payloads), extends JsonSchema - sealed interfaces which store validated payloads, java version of a sum type - boxed classes which store validated payloads, sealed permits class implementations +- classes to store validated list payloads, extends FrozenList +- classes to build inputs for list payloads - classes to store validated map payloads, extends FrozenMap - classes to build inputs for map payloads @@ -17,6 +19,12 @@ A class that contains necessary nested | static class | [ObjectWithOnlyOptionalProps.ObjectWithOnlyOptionalProps1](#objectwithonlyoptionalprops1)
schema class | | static class | [ObjectWithOnlyOptionalProps.ObjectWithOnlyOptionalPropsMapBuilder](#objectwithonlyoptionalpropsmapbuilder)
builder for Map payloads | | static class | [ObjectWithOnlyOptionalProps.ObjectWithOnlyOptionalPropsMap](#objectwithonlyoptionalpropsmap)
output class for Map payloads | +| sealed interface | [ObjectWithOnlyOptionalProps.ArrayPropertyBoxed](#arraypropertyboxed)
sealed interface for validated payloads | +| record | [ObjectWithOnlyOptionalProps.ArrayPropertyBoxedVoid](#arraypropertyboxedvoid)
boxed class to store validated null payloads | +| record | [ObjectWithOnlyOptionalProps.ArrayPropertyBoxedList](#arraypropertyboxedlist)
boxed class to store validated List payloads | +| static class | [ObjectWithOnlyOptionalProps.ArrayProperty](#arrayproperty)
schema class | +| static class | [ObjectWithOnlyOptionalProps.ArrayPropertyListBuilder](#arraypropertylistbuilder)
builder for List payloads | +| static class | [ObjectWithOnlyOptionalProps.ArrayPropertyList](#arraypropertylist)
output class for List payloads | | sealed interface | [ObjectWithOnlyOptionalProps.BBoxed](#bboxed)
sealed interface for validated payloads | | record | [ObjectWithOnlyOptionalProps.BBoxedNumber](#bboxednumber)
boxed class to store validated Number payloads | | static class | [ObjectWithOnlyOptionalProps.B](#b)
schema class | @@ -86,6 +94,8 @@ ObjectWithOnlyOptionalProps.ObjectWithOnlyOptionalPropsMap validatedPayload = .b(1) + .ArrayProperty(null) + .build(), configuration ); @@ -95,7 +105,7 @@ ObjectWithOnlyOptionalProps.ObjectWithOnlyOptionalPropsMap validatedPayload = | Modifier and Type | Field and Description | | ----------------- | ---------------------- | | Set> | type = Set.of(Map.class) | -| Map> | properties = Map.ofEntries(
    new PropertyEntry("a", [A.class](#a))),
    new PropertyEntry("b", [B.class](#b)))
)
| +| Map> | properties = Map.ofEntries(
    new PropertyEntry("a", [A.class](#a))),
    new PropertyEntry("b", [B.class](#b))),
    new PropertyEntry("ArrayProperty", [ArrayProperty.class](#arrayproperty)))
)
| | Class | additionalProperties = [AdditionalProperties.class](#additionalproperties) | ### Method Summary @@ -108,7 +118,7 @@ ObjectWithOnlyOptionalProps.ObjectWithOnlyOptionalPropsMap validatedPayload = ## ObjectWithOnlyOptionalPropsMapBuilder public class ObjectWithOnlyOptionalPropsMapBuilder
-builder for `Map` +builder for `Map` A class that builds the Map input type @@ -120,25 +130,155 @@ A class that builds the Map input type ### Method Summary | Modifier and Type | Method and Description | | ----------------- | ---------------------- | -| Map | build()
Returns map input that should be used with Schema.validate | +| Map | build()
Returns map input that should be used with Schema.validate | | [ObjectWithOnlyOptionalPropsMapBuilder](#objectwithonlyoptionalpropsmapbuilder) | a(String value) | | [ObjectWithOnlyOptionalPropsMapBuilder](#objectwithonlyoptionalpropsmapbuilder) | b(int value) | | [ObjectWithOnlyOptionalPropsMapBuilder](#objectwithonlyoptionalpropsmapbuilder) | b(float value) | | [ObjectWithOnlyOptionalPropsMapBuilder](#objectwithonlyoptionalpropsmapbuilder) | b(long value) | | [ObjectWithOnlyOptionalPropsMapBuilder](#objectwithonlyoptionalpropsmapbuilder) | b(double value) | +| [ObjectWithOnlyOptionalPropsMapBuilder](#objectwithonlyoptionalpropsmapbuilder) | ArrayProperty(Void value) | +| [ObjectWithOnlyOptionalPropsMapBuilder](#objectwithonlyoptionalpropsmapbuilder) | ArrayProperty(List value) | ## ObjectWithOnlyOptionalPropsMap public static class ObjectWithOnlyOptionalPropsMap
-extends FrozenMap +extends FrozenMap A class to store validated Map payloads ### Method Summary | Modifier and Type | Method and Description | | ----------------- | ---------------------- | -| static [ObjectWithOnlyOptionalPropsMap](#objectwithonlyoptionalpropsmap) | of([Map](#objectwithonlyoptionalpropsmapbuilder) arg, SchemaConfiguration configuration) | +| static [ObjectWithOnlyOptionalPropsMap](#objectwithonlyoptionalpropsmap) | of([Map](#objectwithonlyoptionalpropsmapbuilder) arg, SchemaConfiguration configuration) | | String | a()
[optional] | | Number | b()
[optional] | +| [ArrayPropertyList](#arraypropertylist) | ArrayProperty()
[optional] | + +## ArrayPropertyBoxed +public sealed interface ArrayPropertyBoxed
+permits
+[ArrayPropertyBoxedVoid](#arraypropertyboxedvoid), +[ArrayPropertyBoxedList](#arraypropertyboxedlist) + +sealed interface that stores validated payloads using boxed classes + +## ArrayPropertyBoxedVoid +public record ArrayPropertyBoxedVoid
+implements [ArrayPropertyBoxed](#arraypropertyboxed) + +record that stores validated null payloads, sealed permits implementation + +### Constructor Summary +| Constructor and Description | +| --------------------------- | +| ArrayPropertyBoxedVoid(Void data)
Creates an instance, private visibility | + +### Method Summary +| Modifier and Type | Method and Description | +| ----------------- | ---------------------- | +| Void | data()
validated payload | +| @Nullable Object | getData()
validated payload | + +## ArrayPropertyBoxedList +public record ArrayPropertyBoxedList
+implements [ArrayPropertyBoxed](#arraypropertyboxed) + +record that stores validated List payloads, sealed permits implementation + +### Constructor Summary +| Constructor and Description | +| --------------------------- | +| ArrayPropertyBoxedList([ArrayPropertyList](#arraypropertylist) data)
Creates an instance, private visibility | + +### Method Summary +| Modifier and Type | Method and Description | +| ----------------- | ---------------------- | +| [ArrayPropertyList](#arraypropertylist) | data()
validated payload | +| @Nullable Object | getData()
validated payload | + +## ArrayProperty +public static class ArrayProperty
+extends JsonSchema + +A schema class that validates payloads + +### Code Sample +``` +import org.openapijsonschematools.client.configurations.JsonSchemaKeywordFlags; +import org.openapijsonschematools.client.configurations.SchemaConfiguration; +import org.openapijsonschematools.client.exceptions.ValidationException; +import org.openapijsonschematools.client.schemas.validation.MapUtils; +import org.openapijsonschematools.client.schemas.validation.FrozenList; +import org.openapijsonschematools.client.schemas.validation.FrozenMap; +import org.openapijsonschematools.client.components.schemas.ObjectWithOnlyOptionalProps; + +import java.util.Arrays; +import java.util.List; +import java.util.AbstractMap; + +static final SchemaConfiguration configuration = new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone()); + +// null validation +Void validatedPayload = ObjectWithOnlyOptionalProps.ArrayProperty.validate( + (Void) null, + configuration +); + +// List validation +ObjectWithOnlyOptionalProps.ArrayPropertyList validatedPayload = + ObjectWithOnlyOptionalProps.ArrayProperty.validate( + new ObjectWithOnlyOptionalProps.ArrayPropertyListBuilder() + .add("_abc") + + .build(), + configuration +); +``` + +### Field Summary +| Modifier and Type | Field and Description | +| ----------------- | ---------------------- | +| Set> | type = Set.of(
    Void.class,
    List.class
)
| +| Class | items = [EnumClass.EnumClass1.class](../../components/schemas/EnumClass.md#enumclass1) | + +### Method Summary +| Modifier and Type | Method and Description | +| ----------------- | ---------------------- | +| Void | validate(Void arg, SchemaConfiguration configuration) | +| [ArrayPropertyBoxedVoid](#arraypropertyboxedvoid) | validateAndBox(Void arg, SchemaConfiguration configuration) | +| [ArrayPropertyList](#arraypropertylist) | validate([List](#arraypropertylistbuilder) arg, SchemaConfiguration configuration) | +| [ArrayPropertyBoxedList](#arraypropertyboxedlist) | validateAndBox([List](#arraypropertylistbuilder) arg, SchemaConfiguration configuration) | +| [ArrayPropertyBoxed](#arraypropertyboxed) | validateAndBox(@Nullable Object arg, SchemaConfiguration configuration) | +| @Nullable Object | validate(@Nullable Object arg, SchemaConfiguration configuration) | + +## ArrayPropertyListBuilder +public class ArrayPropertyListBuilder
+builder for `List` + +A class that builds the List input type + +### Constructor Summary +| Constructor and Description | +| --------------------------- | +| ArrayPropertyListBuilder()
Creates an empty list | +| ArrayPropertyListBuilder(List items)
Stores the items in a list | + +### Method Summary +| Modifier and Type | Method and Description | +| ----------------- | ---------------------- | +| ArrayPropertyListBuilder | add(String item) | +| ArrayPropertyListBuilder | add([EnumClass.StringEnumClassEnums](../../components/schemas/EnumClass.md#stringenumclassenums) item) | +| List | build()
Returns list input that should be used with Schema.validate | + +## ArrayPropertyList +public class ArrayPropertyList
+extends `FrozenList` + +A class to store validated List payloads + +### Method Summary +| Modifier and Type | Method and Description | +| ----------------- | ---------------------- | +| static [ArrayPropertyList](#arraypropertylist) | of([List](#arraypropertylistbuilder) arg, SchemaConfiguration configuration) | ## BBoxed public sealed interface BBoxed
diff --git a/samples/client/petstore/java/src/main/java/org/openapijsonschematools/client/components/schemas/ObjectWithOnlyOptionalProps.java b/samples/client/petstore/java/src/main/java/org/openapijsonschematools/client/components/schemas/ObjectWithOnlyOptionalProps.java index d8b8726ab28..d8de4ce6a6e 100644 --- a/samples/client/petstore/java/src/main/java/org/openapijsonschematools/client/components/schemas/ObjectWithOnlyOptionalProps.java +++ b/samples/client/petstore/java/src/main/java/org/openapijsonschematools/client/components/schemas/ObjectWithOnlyOptionalProps.java @@ -17,11 +17,14 @@ import org.openapijsonschematools.client.schemas.NotAnyTypeJsonSchema; import org.openapijsonschematools.client.schemas.NumberJsonSchema; import org.openapijsonschematools.client.schemas.StringJsonSchema; +import org.openapijsonschematools.client.schemas.validation.FrozenList; import org.openapijsonschematools.client.schemas.validation.FrozenMap; import org.openapijsonschematools.client.schemas.validation.JsonSchema; import org.openapijsonschematools.client.schemas.validation.JsonSchemaInfo; +import org.openapijsonschematools.client.schemas.validation.ListSchemaValidator; import org.openapijsonschematools.client.schemas.validation.MapSchemaValidator; import org.openapijsonschematools.client.schemas.validation.MapUtils; +import org.openapijsonschematools.client.schemas.validation.NullSchemaValidator; import org.openapijsonschematools.client.schemas.validation.PathToSchemasMap; import org.openapijsonschematools.client.schemas.validation.PropertyEntry; import org.openapijsonschematools.client.schemas.validation.ValidationMetadata; @@ -64,23 +67,183 @@ public static B getInstance() { } - public static class ObjectWithOnlyOptionalPropsMap extends FrozenMap { - protected ObjectWithOnlyOptionalPropsMap(FrozenMap m) { + public static class ArrayPropertyList extends FrozenList { + protected ArrayPropertyList(FrozenList m) { + super(m); + } + public static ArrayPropertyList of(List arg, SchemaConfiguration configuration) throws ValidationException { + return ArrayProperty.getInstance().validate(arg, configuration); + } + } + + public static class ArrayPropertyListBuilder { + // class to build List + private final List list; + + public ArrayPropertyListBuilder() { + list = new ArrayList<>(); + } + + public ArrayPropertyListBuilder(List list) { + this.list = list; + } + + public ArrayPropertyListBuilder add(String item) { + list.add(item); + return this; + } + + public ArrayPropertyListBuilder add(EnumClass.StringEnumClassEnums item) { + list.add(item.value()); + return this; + } + + public List build() { + return list; + } + } + + + public sealed interface ArrayPropertyBoxed permits ArrayPropertyBoxedVoid, ArrayPropertyBoxedList { + @Nullable Object getData(); + } + + public record ArrayPropertyBoxedVoid(Void data) implements ArrayPropertyBoxed { + @Override + public @Nullable Object getData() { + return data; + } + } + + public record ArrayPropertyBoxedList(ArrayPropertyList data) implements ArrayPropertyBoxed { + @Override + public @Nullable Object getData() { + return data; + } + } + + + + public static class ArrayProperty extends JsonSchema implements NullSchemaValidator, ListSchemaValidator { + private static @Nullable ArrayProperty instance = null; + + protected ArrayProperty() { + super(new JsonSchemaInfo() + .type(Set.of( + Void.class, + List.class + )) + .items(EnumClass.EnumClass1.class) + ); + } + + public static ArrayProperty getInstance() { + if (instance == null) { + instance = new ArrayProperty(); + } + return instance; + } + + @Override + public Void validate(Void arg, SchemaConfiguration configuration) throws ValidationException { + Set> pathSet = new HashSet<>(); + List pathToItem = List.of("args[0"); + Void castArg = castToAllowedTypes(arg, pathToItem, pathSet); + SchemaConfiguration usedConfiguration = Objects.requireNonNullElseGet(configuration, () -> new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone())); + ValidationMetadata validationMetadata = new ValidationMetadata(pathToItem, usedConfiguration, new PathToSchemasMap(), new LinkedHashSet<>()); + getPathToSchemas(this, castArg, validationMetadata, pathSet); + return castArg; + } + + @Override + public ArrayPropertyList getNewInstance(List arg, List pathToItem, PathToSchemasMap pathToSchemas) { + List items = new ArrayList<>(); + int i = 0; + for (Object item: arg) { + List itemPathToItem = new ArrayList<>(pathToItem); + itemPathToItem.add(i); + LinkedHashMap, Void> schemas = pathToSchemas.get(itemPathToItem); + if (schemas == null) { + throw new RuntimeException("Validation result is invalid, schemas must exist for a pathToItem"); + } + JsonSchema itemSchema = schemas.entrySet().iterator().next().getKey(); + @Nullable Object itemInstance = itemSchema.getNewInstance(item, itemPathToItem, pathToSchemas); + if (!(itemInstance instanceof String)) { + throw new RuntimeException("Invalid instantiated value"); + } + items.add((String) itemInstance); + i += 1; + } + FrozenList newInstanceItems = new FrozenList<>(items); + return new ArrayPropertyList(newInstanceItems); + } + + public ArrayPropertyList validate(List arg, SchemaConfiguration configuration) throws ValidationException { + Set> pathSet = new HashSet<>(); + List pathToItem = List.of("args[0"); + List castArg = castToAllowedTypes(arg, pathToItem, pathSet); + SchemaConfiguration usedConfiguration = Objects.requireNonNullElseGet(configuration, () -> new SchemaConfiguration(JsonSchemaKeywordFlags.ofNone())); + ValidationMetadata validationMetadata = new ValidationMetadata(pathToItem, usedConfiguration, new PathToSchemasMap(), new LinkedHashSet<>()); + PathToSchemasMap pathToSchemasMap = getPathToSchemas(this, castArg, validationMetadata, pathSet); + return getNewInstance(castArg, validationMetadata.pathToItem(), pathToSchemasMap); + } + + @Override + public @Nullable Object validate(@Nullable Object arg, SchemaConfiguration configuration) throws ValidationException { + if (arg == null) { + return validate((Void) null, configuration); + } else if (arg instanceof List) { + return validate((List) arg, configuration); + } + throw new ValidationException("Invalid input type="+getClass(arg)+". It can't be validated by this schema"); + } + @Override + public @Nullable Object getNewInstance(@Nullable Object arg, List pathToItem, PathToSchemasMap pathToSchemas) { + if (arg == null) { + return getNewInstance((Void) null, pathToItem, pathToSchemas); + } else if (arg instanceof List) { + return getNewInstance((List) arg, pathToItem, pathToSchemas); + } + throw new RuntimeException("Invalid input type="+getClass(arg)+". It can't be instantiated by this schema"); + } + @Override + public ArrayPropertyBoxedVoid validateAndBox(Void arg, SchemaConfiguration configuration) throws ValidationException { + return new ArrayPropertyBoxedVoid(validate(arg, configuration)); + } + @Override + public ArrayPropertyBoxedList validateAndBox(List arg, SchemaConfiguration configuration) throws ValidationException { + return new ArrayPropertyBoxedList(validate(arg, configuration)); + } + @Override + public ArrayPropertyBoxed validateAndBox(@Nullable Object arg, SchemaConfiguration configuration) throws ValidationException { + if (arg == null) { + Void castArg = (Void) arg; + return validateAndBox(castArg, configuration); + } else if (arg instanceof List castArg) { + return validateAndBox(castArg, configuration); + } + throw new ValidationException("Invalid input type="+getClass(arg)+". It can't be validated by this schema"); + } + } + + public static class ObjectWithOnlyOptionalPropsMap extends FrozenMap<@Nullable Object> { + protected ObjectWithOnlyOptionalPropsMap(FrozenMap<@Nullable Object> m) { super(m); } public static final Set requiredKeys = Set.of(); public static final Set optionalKeys = Set.of( "a", - "b" + "b", + "ArrayProperty" ); - public static ObjectWithOnlyOptionalPropsMap of(Map arg, SchemaConfiguration configuration) throws ValidationException { + public static ObjectWithOnlyOptionalPropsMap of(Map arg, SchemaConfiguration configuration) throws ValidationException { return ObjectWithOnlyOptionalProps1.getInstance().validate(arg, configuration); } public String a() throws UnsetPropertyException { String key = "a"; throwIfKeyNotPresent(key); - Object value = get(key); + @Nullable Object value = get(key); if (!(value instanceof String)) { throw new RuntimeException("Invalid value stored for a"); } @@ -90,17 +253,27 @@ public String a() throws UnsetPropertyException { public Number b() throws UnsetPropertyException { String key = "b"; throwIfKeyNotPresent(key); - Object value = get(key); + @Nullable Object value = get(key); if (!(value instanceof Number)) { throw new RuntimeException("Invalid value stored for b"); } return (Number) value; } + + public @Nullable ArrayPropertyList ArrayProperty() throws UnsetPropertyException { + String key = "ArrayProperty"; + throwIfKeyNotPresent(key); + @Nullable Object value = get(key); + if (!(value == null || value instanceof ArrayPropertyList)) { + throw new RuntimeException("Invalid value stored for ArrayProperty"); + } + return (@Nullable ArrayPropertyList) value; + } } public interface SetterForA { - Map getInstance(); - T getBuilderAfterA(Map instance); + Map getInstance(); + T getBuilderAfterA(Map instance); default T a(String value) { var instance = getInstance(); @@ -110,8 +283,8 @@ default T a(String value) { } public interface SetterForB { - Map getInstance(); - T getBuilderAfterB(Map instance); + Map getInstance(); + T getBuilderAfterB(Map instance); default T b(int value) { var instance = getInstance(); @@ -138,11 +311,29 @@ default T b(double value) { } } - public static class ObjectWithOnlyOptionalPropsMapBuilder implements GenericBuilder>, SetterForA, SetterForB { - private final Map instance; + public interface SetterForArrayProperty { + Map getInstance(); + T getBuilderAfterArrayProperty(Map instance); + + default T ArrayProperty(Void value) { + var instance = getInstance(); + instance.put("ArrayProperty", null); + return getBuilderAfterArrayProperty(instance); + } + + default T ArrayProperty(List value) { + var instance = getInstance(); + instance.put("ArrayProperty", value); + return getBuilderAfterArrayProperty(instance); + } + } + + public static class ObjectWithOnlyOptionalPropsMapBuilder implements GenericBuilder>, SetterForA, SetterForB, SetterForArrayProperty { + private final Map instance; private static final Set knownKeys = Set.of( "a", - "b" + "b", + "ArrayProperty" ); public Set getKnownKeys() { return knownKeys; @@ -150,16 +341,19 @@ public Set getKnownKeys() { public ObjectWithOnlyOptionalPropsMapBuilder() { this.instance = new LinkedHashMap<>(); } - public Map build() { + public Map build() { return instance; } - public Map getInstance() { + public Map getInstance() { return instance; } - public ObjectWithOnlyOptionalPropsMapBuilder getBuilderAfterA(Map instance) { + public ObjectWithOnlyOptionalPropsMapBuilder getBuilderAfterA(Map instance) { + return this; + } + public ObjectWithOnlyOptionalPropsMapBuilder getBuilderAfterB(Map instance) { return this; } - public ObjectWithOnlyOptionalPropsMapBuilder getBuilderAfterB(Map instance) { + public ObjectWithOnlyOptionalPropsMapBuilder getBuilderAfterArrayProperty(Map instance) { return this; } } @@ -191,7 +385,8 @@ protected ObjectWithOnlyOptionalProps1() { .type(Set.of(Map.class)) .properties(Map.ofEntries( new PropertyEntry("a", A.class), - new PropertyEntry("b", B.class) + new PropertyEntry("b", B.class), + new PropertyEntry("ArrayProperty", ArrayProperty.class) )) .additionalProperties(AdditionalProperties.class) ); @@ -205,7 +400,7 @@ public static ObjectWithOnlyOptionalProps1 getInstance() { } public ObjectWithOnlyOptionalPropsMap getNewInstance(Map arg, List pathToItem, PathToSchemasMap pathToSchemas) { - LinkedHashMap properties = new LinkedHashMap<>(); + LinkedHashMap properties = new LinkedHashMap<>(); for(Map.Entry entry: arg.entrySet()) { @Nullable Object entryKey = entry.getKey(); if (!(entryKey instanceof String)) { @@ -221,12 +416,9 @@ public ObjectWithOnlyOptionalPropsMap getNewInstance(Map arg, List } JsonSchema propertySchema = schemas.entrySet().iterator().next().getKey(); @Nullable Object propertyInstance = propertySchema.getNewInstance(value, propertyPathToItem, pathToSchemas); - if (!(propertyInstance instanceof Object)) { - throw new RuntimeException("Invalid instantiated value"); - } - properties.put(propertyName, (Object) propertyInstance); + properties.put(propertyName, propertyInstance); } - FrozenMap castProperties = new FrozenMap<>(properties); + FrozenMap<@Nullable Object> castProperties = new FrozenMap<>(properties); return new ObjectWithOnlyOptionalPropsMap(castProperties); } diff --git a/samples/client/petstore/python/docs/components/schema/object_with_only_optional_props.md b/samples/client/petstore/python/docs/components/schema/object_with_only_optional_props.md index cf9e6001ed6..310bcac93a4 100644 --- a/samples/client/petstore/python/docs/components/schema/object_with_only_optional_props.md +++ b/samples/client/petstore/python/docs/components/schema/object_with_only_optional_props.md @@ -17,10 +17,13 @@ Key | Type | Description | Notes ------------ | ------------- | ------------- | ------------- **a** | str | | [optional] **b** | float, int | | [optional] +**ArrayProperty** | None, [ArrayPropertyTupleInput](#arraypropertytupleinput), [ArrayPropertyTuple](#arraypropertytuple) | | [optional] ## ObjectWithOnlyOptionalPropsDict ``` base class: schemas.immutabledict[str, typing.Union[ + None, + typing.Tuple[schemas.OUTPUT_BASE_TYPES], typing.Union[int, float], str, ]] @@ -31,16 +34,74 @@ Keyword Argument | Type | Description | Notes ---------------- | ---- | ----------- | ----- **a** | str, schemas.Unset | | [optional] **b** | float, int, schemas.Unset | | [optional] +**ArrayProperty** | None, [ArrayPropertyTupleInput](#arraypropertytupleinput), [ArrayPropertyTuple](#arraypropertytuple), schemas.Unset | | [optional] ### properties Property | Type | Description | Notes -------- | ---- | ----------- | ----- **a** | str, schemas.Unset | | [optional] **b** | float, int, schemas.Unset | | [optional] +**ArrayProperty** | None, [ArrayPropertyTuple](#arraypropertytuple), schemas.Unset | | [optional] ### methods Method | Input Type | Return Type | Notes ------ | ---------- | ----------- | ------ from_dict_ | [ObjectWithOnlyOptionalPropsDictInput](#objectwithonlyoptionalpropsdictinput), [ObjectWithOnlyOptionalPropsDict](#objectwithonlyoptionalpropsdict) | [ObjectWithOnlyOptionalPropsDict](#objectwithonlyoptionalpropsdict) | a constructor +# ArrayProperty +``` +type: schemas.Schema +``` + +## validate method +Input Type | Return Type | Notes +------------ | ------------- | ------------- +None, [ArrayPropertyTupleInput](#arraypropertytupleinput), [ArrayPropertyTuple](#arraypropertytuple) | None, [ArrayPropertyTuple](#arraypropertytuple) | + +## ArrayPropertyTupleInput +``` +type: typing.Union[ + typing.List[ + typing.Literal[ + "_abc", + "-efg", + "(xyz)", + "COUNT_1M", + "COUNT_50M" + ], + ], + typing.Tuple[ + typing.Literal[ + "_abc", + "-efg", + "(xyz)", + "COUNT_1M", + "COUNT_50M" + ], + ... + ] +] +``` +List/Tuple Item Type | Description | Notes +-------------------- | ------------- | ------------- +typing.Literal["_abc", "-efg", "(xyz)", "COUNT_1M", "COUNT_50M"] | | + +## ArrayPropertyTuple +``` +base class: typing.Tuple[ + typing.Literal["_abc", "-efg", "(xyz)", "COUNT_1M", "COUNT_50M"], + ... +] +``` +### __new__ method +Argument | Type +-------- | ------ +arg | None, [ArrayPropertyTupleInput](#arraypropertytupleinput), [ArrayPropertyTuple](#arraypropertytuple) +configuration | typing.Optional[schema_configuration.SchemaConfiguration] = None + +### methods +Method | Input Type | Return Type | Notes +------ | ---------- | ----------- | ------ +__getitem__ | int | typing.Literal["_abc", "-efg", "(xyz)", "COUNT_1M", "COUNT_50M"] | This method is used under the hood when instance[0] is called + [[Back to top]](#top) [[Back to Component Schemas]](../../../README.md#Component-Schemas) [[Back to README]](../../../README.md) diff --git a/samples/client/petstore/python/src/petstore_api/components/schema/object_with_only_optional_props.py b/samples/client/petstore/python/src/petstore_api/components/schema/object_with_only_optional_props.py index bc4f429e02a..2e5e35255a8 100644 --- a/samples/client/petstore/python/src/petstore_api/components/schema/object_with_only_optional_props.py +++ b/samples/client/petstore/python/src/petstore_api/components/schema/object_with_only_optional_props.py @@ -13,16 +13,101 @@ AdditionalProperties: typing_extensions.TypeAlias = schemas.NotAnyTypeSchema A: typing_extensions.TypeAlias = schemas.StrSchema B: typing_extensions.TypeAlias = schemas.NumberSchema + +from petstore_api.components.schema import enum_class + + +class ArrayPropertyTuple( + typing.Tuple[ + typing.Literal["_abc", "-efg", "(xyz)", "COUNT_1M", "COUNT_50M"], + ... + ] +): + + def __new__(cls, arg: typing.Union[ArrayPropertyTupleInput, ArrayPropertyTuple], configuration: typing.Optional[schema_configuration.SchemaConfiguration] = None): + return ArrayProperty.validate(arg, configuration=configuration) +ArrayPropertyTupleInput = typing.Union[ + typing.List[ + typing.Literal[ + "_abc", + "-efg", + "(xyz)", + "COUNT_1M", + "COUNT_50M" + ], + ], + typing.Tuple[ + typing.Literal[ + "_abc", + "-efg", + "(xyz)", + "COUNT_1M", + "COUNT_50M" + ], + ... + ] +] + + +@dataclasses.dataclass(frozen=True) +class ArrayProperty( + schemas.Schema[schemas.immutabledict[str, schemas.OUTPUT_BASE_TYPES], ArrayPropertyTuple], +): + types: typing.FrozenSet[typing.Type] = frozenset({ + type(None), + tuple, + }) + items: typing.Type[enum_class.EnumClass] = dataclasses.field(default_factory=lambda: enum_class.EnumClass) # type: ignore + type_to_output_cls: typing.Mapping[ + typing.Type, + typing.Type + ] = dataclasses.field( + default_factory=lambda: { + tuple: ArrayPropertyTuple, + } + ) + + @typing.overload + @classmethod + def validate( + cls, + arg: None, + configuration: typing.Optional[schema_configuration.SchemaConfiguration] = None + ) -> None: ... + @typing.overload + @classmethod + def validate( + cls, + arg: typing.Union[ + ArrayPropertyTupleInput, + ArrayPropertyTuple, + ], + configuration: typing.Optional[schema_configuration.SchemaConfiguration] = None + ) -> ArrayPropertyTuple: ... + @classmethod + def validate( + cls, + arg, + configuration: typing.Optional[schema_configuration.SchemaConfiguration] = None + ): + return super().validate_base( + arg, + configuration=configuration, + ) + Properties = typing.TypedDict( 'Properties', { "a": typing.Type[A], "b": typing.Type[B], + "ArrayProperty": typing.Type[ArrayProperty], } ) class ObjectWithOnlyOptionalPropsDict(schemas.immutabledict[str, typing.Union[ + None, + typing.Tuple[schemas.OUTPUT_BASE_TYPES], typing.Union[int, float], str, ]]): @@ -32,6 +117,7 @@ class ObjectWithOnlyOptionalPropsDict(schemas.immutabledict[str, typing.Union[ __optional_keys__: typing.FrozenSet[str] = frozenset({ "a", "b", + "ArrayProperty", }) def __new__( @@ -46,12 +132,21 @@ def __new__( float, schemas.Unset ] = schemas.unset, + ArrayProperty: typing.Union[ + None, + typing.Union[ + ArrayPropertyTupleInput, + ArrayPropertyTuple + ], + schemas.Unset + ] = schemas.unset, configuration_: typing.Optional[schema_configuration.SchemaConfiguration] = None, ): arg_: typing.Dict[str, typing.Any] = {} for key_, val in ( ("a", a), ("b", b), + ("ArrayProperty", ArrayProperty), ): if isinstance(val, schemas.Unset): continue @@ -88,6 +183,22 @@ def b(self) -> typing.Union[int, float, schemas.Unset]: typing.Union[int, float], val ) + + @property + def ArrayProperty(self) -> typing.Union[ + typing.Union[None, schemas.Unset], + typing.Union[ArrayPropertyTuple, schemas.Unset], + ]: + val = self.get("ArrayProperty", schemas.unset) + if isinstance(val, schemas.Unset): + return val + return typing.cast( + typing.Union[ + None, + ArrayPropertyTuple, + ], + val + ) ObjectWithOnlyOptionalPropsDictInput = typing.TypedDict( 'ObjectWithOnlyOptionalPropsDictInput', { @@ -96,6 +207,13 @@ def b(self) -> typing.Union[int, float, schemas.Unset]: int, float ], + "ArrayProperty": typing.Union[ + None, + typing.Union[ + ArrayPropertyTupleInput, + ArrayPropertyTuple + ], + ], }, total=False ) diff --git a/src/test/resources/3_0/python/petstore_customized.yaml b/src/test/resources/3_0/python/petstore_customized.yaml index 9dfa0427ee6..c411b7bb937 100644 --- a/src/test/resources/3_0/python/petstore_customized.yaml +++ b/src/test/resources/3_0/python/petstore_customized.yaml @@ -3400,6 +3400,11 @@ components: type: string b: type: number + ArrayProperty: + items: + $ref: '#/components/schemas/EnumClass' + type: array + nullable: true additionalProperties: false ObjectWithNonIntersectingValues: properties: