1
-
2
1
from collections .abc import Callable
3
2
from typing import Any
4
3
15
14
16
15
def merge_properties (prop1 : PropertyProtocol , prop2 : PropertyProtocol ) -> PropertyProtocol :
17
16
"""Attempt to create a new property that incorporates the behavior of both.
18
-
17
+
19
18
This is used when merging schemas with allOf, when two schemas define a property with the same name.
20
-
19
+
21
20
OpenAPI defines allOf in terms of validation behavior: the input must pass the validation rules
22
21
defined in all of the listed schemas. Our task here is slightly more difficult, since we must end
23
22
up with a single Property object that will be used to generate a single class property in the
@@ -37,10 +36,10 @@ def merge_properties(prop1: PropertyProtocol, prop2: PropertyProtocol) -> Proper
37
36
38
37
if prop1 .__class__ == prop2 .__class__ :
39
38
return _merge_same_type (prop1 , prop2 )
40
-
39
+
41
40
if isinstance (prop1 , AnyProperty ) or isinstance (prop2 , AnyProperty ):
42
41
return _merge_with_any (prop1 , prop2 )
43
-
42
+
44
43
if _is_numeric (prop1 ) and _is_numeric (prop2 ):
45
44
return _merge_numeric (prop1 , prop2 )
46
45
@@ -78,13 +77,11 @@ def _merge_string(prop1: StringProperty, prop2: StringProperty) -> StringPropert
78
77
# it would just mean the value must match both of the patterns to be valid. But we have no way to
79
78
# represent this in our internal model currently.
80
79
pattern : str | None | ValueError = _combine_values (
81
- prop1 .pattern ,
82
- prop2 .pattern ,
83
- lambda a , b : ValueError ("specified two different regex patterns" )
80
+ prop1 .pattern , prop2 .pattern , lambda a , b : ValueError ("specified two different regex patterns" )
84
81
)
85
82
if isinstance (pattern , ValueError ):
86
83
raise pattern
87
-
84
+
88
85
return _merge_common_attributes (evolve (prop1 , max_length = max_length , pattern = pattern ), prop2 )
89
86
90
87
@@ -98,7 +95,7 @@ def _merge_numeric(prop1: PropertyProtocol, prop2: PropertyProtocol) -> IntPrope
98
95
if isinstance (result .default , float ) and not result .default .is_integer ():
99
96
raise ValueError (f"default value { result .default } is not valid for an integer property" )
100
97
return result
101
-
98
+
102
99
103
100
def _merge_with_any (prop1 : PropertyProtocol , prop2 : PropertyProtocol ) -> PropertyProtocol :
104
101
# AnyProperty implies no validation rules for a value, so merging it with any other type just means
@@ -123,17 +120,16 @@ def _merge_with_enum(prop1: PropertyProtocol, prop2: PropertyProtocol) -> EnumPr
123
120
# If enum values were specified for just one of the properties, use those.
124
121
enum_prop = prop1 if isinstance (prop1 , EnumProperty ) else prop2
125
122
non_enum_prop = prop2 if isinstance (prop1 , EnumProperty ) else prop1
126
- if (
127
- (isinstance (non_enum_prop , IntProperty ) and enum_prop .value_type is int ) or
128
- (isinstance (non_enum_prop , StringProperty ) and enum_prop .value_type is str )
123
+ if (isinstance (non_enum_prop , IntProperty ) and enum_prop .value_type is int ) or (
124
+ isinstance (non_enum_prop , StringProperty ) and enum_prop .value_type is str
129
125
):
130
126
return _merge_common_attributes (enum_prop , prop1 , prop2 )
131
127
raise ValueError ("defined with two incompatible types" )
132
128
133
129
134
130
def _merge_common_attributes (base : PropertyProtocol , * extend_with : PropertyProtocol ) -> PropertyProtocol :
135
131
"""Create a new instance based on base, overriding basic attributes with values from extend_with, in order.
136
-
132
+
137
133
For "default", "description", and "example", a non-None value overrides any value from a previously
138
134
specified property. The behavior is similar to using the spread operator with dictionaries, except
139
135
that None means "not specified".
@@ -146,10 +142,10 @@ def _merge_common_attributes(base: PropertyProtocol, *extend_with: PropertyProto
146
142
current = evolve (
147
143
current ,
148
144
required = current .required or override .required ,
149
- default = override .default or current .default ,
150
- description = override .description or current .description ,
151
- example = override .example or current .example ,
152
- )
145
+ default = override .default or current .default ,
146
+ description = override .description or current .description ,
147
+ example = override .example or current .example ,
148
+ )
153
149
return current
154
150
155
151
0 commit comments