robotframework-openapitools 1.0.0b2__py3-none-any.whl → 1.0.0b4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. OpenApiDriver/openapi_executors.py +8 -8
  2. OpenApiDriver/openapi_reader.py +12 -13
  3. OpenApiDriver/openapidriver.libspec +4 -41
  4. OpenApiLibCore/__init__.py +0 -2
  5. OpenApiLibCore/annotations.py +8 -1
  6. OpenApiLibCore/data_generation/__init__.py +0 -2
  7. OpenApiLibCore/data_generation/body_data_generation.py +52 -71
  8. OpenApiLibCore/data_generation/data_generation_core.py +82 -62
  9. OpenApiLibCore/data_invalidation.py +37 -20
  10. OpenApiLibCore/dto_base.py +20 -86
  11. OpenApiLibCore/localized_faker.py +88 -0
  12. OpenApiLibCore/models.py +715 -0
  13. OpenApiLibCore/openapi_libcore.libspec +47 -283
  14. OpenApiLibCore/openapi_libcore.py +20 -46
  15. OpenApiLibCore/parameter_utils.py +23 -17
  16. OpenApiLibCore/path_functions.py +5 -4
  17. OpenApiLibCore/protocols.py +7 -5
  18. OpenApiLibCore/request_data.py +67 -102
  19. OpenApiLibCore/resource_relations.py +2 -3
  20. OpenApiLibCore/validation.py +49 -161
  21. OpenApiLibCore/value_utils.py +46 -358
  22. openapi_libgen/__init__.py +0 -46
  23. openapi_libgen/command_line.py +7 -19
  24. openapi_libgen/generator.py +84 -0
  25. openapi_libgen/spec_parser.py +44 -111
  26. {robotframework_openapitools-1.0.0b2.dist-info → robotframework_openapitools-1.0.0b4.dist-info}/METADATA +98 -1
  27. robotframework_openapitools-1.0.0b4.dist-info/RECORD +40 -0
  28. robotframework_openapitools-1.0.0b2.dist-info/RECORD +0 -37
  29. {robotframework_openapitools-1.0.0b2.dist-info → robotframework_openapitools-1.0.0b4.dist-info}/LICENSE +0 -0
  30. {robotframework_openapitools-1.0.0b2.dist-info → robotframework_openapitools-1.0.0b4.dist-info}/WHEEL +0 -0
  31. {robotframework_openapitools-1.0.0b2.dist-info → robotframework_openapitools-1.0.0b4.dist-info}/entry_points.txt +0 -0
@@ -185,8 +185,8 @@ class OpenApiExecutors(OpenApiLibCore):
185
185
  # in case of a status code indicating an error, ensure the error occurs
186
186
  if status_code >= int(HTTPStatus.BAD_REQUEST):
187
187
  invalidation_keyword_data = {
188
- "get_invalid_json_data": [
189
- "get_invalid_json_data",
188
+ "get_invalid_body_data": [
189
+ "get_invalid_body_data",
190
190
  url,
191
191
  method,
192
192
  status_code,
@@ -201,13 +201,13 @@ class OpenApiExecutors(OpenApiLibCore):
201
201
  invalidation_keywords = []
202
202
 
203
203
  if request_data.dto.get_body_relations_for_error_code(status_code):
204
- invalidation_keywords.append("get_invalid_json_data")
204
+ invalidation_keywords.append("get_invalid_body_data")
205
205
  if request_data.dto.get_parameter_relations_for_error_code(status_code):
206
206
  invalidation_keywords.append("get_invalidated_parameters")
207
207
  if invalidation_keywords:
208
208
  if (
209
209
  invalidation_keyword := choice(invalidation_keywords)
210
- ) == "get_invalid_json_data":
210
+ ) == "get_invalid_body_data":
211
211
  json_data = run_keyword(
212
212
  *invalidation_keyword_data[invalidation_keyword]
213
213
  )
@@ -225,13 +225,13 @@ class OpenApiExecutors(OpenApiLibCore):
225
225
  params, headers = run_keyword(
226
226
  *invalidation_keyword_data["get_invalidated_parameters"]
227
227
  )
228
- if request_data.dto_schema:
228
+ if request_data.body_schema:
229
229
  json_data = run_keyword(
230
- *invalidation_keyword_data["get_invalid_json_data"]
230
+ *invalidation_keyword_data["get_invalid_body_data"]
231
231
  )
232
- elif request_data.dto_schema:
232
+ elif request_data.body_schema:
233
233
  json_data = run_keyword(
234
- *invalidation_keyword_data["get_invalid_json_data"]
234
+ *invalidation_keyword_data["get_invalid_body_data"]
235
235
  )
236
236
  else:
237
237
  raise SkipExecution(
@@ -1,10 +1,12 @@
1
1
  """Module holding the OpenApiReader reader_class implementation."""
2
2
 
3
- from typing import Any
3
+ from typing import Sequence
4
4
 
5
5
  from DataDriver.AbstractReaderClass import AbstractReaderClass
6
6
  from DataDriver.ReaderConfig import TestCaseData
7
7
 
8
+ from OpenApiLibCore.models import PathItemObject
9
+
8
10
 
9
11
  class Test:
10
12
  """
@@ -16,7 +18,7 @@ class Test:
16
18
  self.method = method.lower()
17
19
  self.response = str(response)
18
20
 
19
- def __eq__(self, other: Any) -> bool:
21
+ def __eq__(self, other: object) -> bool:
20
22
  if not isinstance(other, type(self)):
21
23
  return False
22
24
  return (
@@ -33,7 +35,7 @@ class OpenApiReader(AbstractReaderClass):
33
35
  test_data: list[TestCaseData] = []
34
36
 
35
37
  read_paths_method = getattr(self, "read_paths_method")
36
- paths: dict[str, Any] = read_paths_method()
38
+ paths: dict[str, PathItemObject] = read_paths_method()
37
39
  self._filter_paths(paths)
38
40
 
39
41
  ignored_responses_ = [
@@ -43,15 +45,12 @@ class OpenApiReader(AbstractReaderClass):
43
45
  ignored_tests = [Test(*test) for test in getattr(self, "ignored_testcases", [])]
44
46
 
45
47
  for path, path_item in paths.items():
48
+ path_operations = path_item.get_operations()
49
+
46
50
  # by reseversing the items, post/put operations come before get and delete
47
- for item_name, item_data in reversed(path_item.items()):
48
- # this level of the OAS also contains data that's not related to a
49
- # path operation
50
- if item_name not in ["get", "put", "post", "delete", "patch"]:
51
- continue
52
- method, method_data = item_name, item_data
53
- tags_from_spec = method_data.get("tags", [])
54
- for response in method_data.get("responses"):
51
+ for method, operation_data in reversed(path_operations.items()):
52
+ tags_from_spec = operation_data.tags
53
+ for response in operation_data.responses.keys():
55
54
  # 'default' applies to all status codes that are not specified, in
56
55
  # which case we don't know what to expect and therefore can't verify
57
56
  if (
@@ -76,7 +75,7 @@ class OpenApiReader(AbstractReaderClass):
76
75
  )
77
76
  return test_data
78
77
 
79
- def _filter_paths(self, paths: dict[str, Any]) -> None:
78
+ def _filter_paths(self, paths: dict[str, PathItemObject]) -> None:
80
79
  def matches_include_pattern(path: str) -> bool:
81
80
  for included_path in included_paths:
82
81
  if path == included_path:
@@ -111,5 +110,5 @@ class OpenApiReader(AbstractReaderClass):
111
110
  paths.pop(path)
112
111
 
113
112
 
114
- def _get_tag_list(tags: list[str], method: str, response: str) -> list[str]:
113
+ def _get_tag_list(tags: Sequence[str], method: str, response: str) -> list[str]:
115
114
  return [*tags, f"Method: {method.upper()}", f"Response: {response}"]
@@ -1,12 +1,12 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
- <keywordspec name="OpenApiDriver" type="LIBRARY" format="HTML" scope="SUITE" generated="2025-04-03T11:37:57+00:00" specversion="6" source="/workspaces/robotframework-openapitools/src/OpenApiDriver/openapidriver.py" lineno="358">
3
- <version>1.0.0b2</version>
2
+ <keywordspec name="OpenApiDriver" type="LIBRARY" format="HTML" scope="SUITE" generated="2025-05-11T17:23:01+00:00" specversion="6" source="/workspaces/robotframework-openapitools/src/OpenApiDriver/openapidriver.py" lineno="358">
3
+ <version>1.0.0b3</version>
4
4
  <doc>&lt;p&gt;Visit the &lt;a href="https://github.com/MarketSquare/robotframework-openapidriver"&gt;library page&lt;/a&gt; for an introduction and examples.&lt;/p&gt;</doc>
5
5
  <tags>
6
6
  </tags>
7
7
  <inits>
8
8
  <init name="__init__" lineno="150">
9
- <arguments repr="source: str, origin: str = , base_path: str = , included_paths: Iterable[str] = frozenset(), ignored_paths: Iterable[str] = frozenset(), ignored_responses: Iterable[int] = frozenset(), ignored_testcases: Iterable[tuple[str, str, int]] = frozenset(), response_validation: ValidationLevel = WARN, disable_server_validation: bool = True, mappings_path: str | Path = , invalid_property_default_response: int = 422, default_id_property_name: str = id, faker_locale: str | list[str] = , require_body_for_invalid_url: bool = False, recursion_limit: int = 1, recursion_default: dict[str, JSON] | list[JSON] | str | bytes | int | float | bool | None = {}, username: str = , password: str = , security_token: str = , auth: AuthBase | None = None, cert: str | tuple[str, str] = , verify_tls: bool | str = True, extra_headers: Mapping[str, str] = {}, cookies: MutableMapping[str, str] | RequestsCookieJar | None = None, proxies: MutableMapping[str, str] | None = None">
9
+ <arguments repr="source: str, origin: str = , base_path: str = , included_paths: Iterable[str] = frozenset(), ignored_paths: Iterable[str] = frozenset(), ignored_responses: Iterable[int] = frozenset(), ignored_testcases: Iterable[tuple[str, str, int]] = frozenset(), response_validation: ValidationLevel = WARN, disable_server_validation: bool = True, mappings_path: str | Path = , invalid_property_default_response: int = 422, default_id_property_name: str = id, faker_locale: str | list[str] = , require_body_for_invalid_url: bool = False, recursion_limit: int = 1, recursion_default: JSON = {}, username: str = , password: str = , security_token: str = , auth: AuthBase | None = None, cert: str | tuple[str, str] = , verify_tls: bool | str = True, extra_headers: Mapping[str, str] = {}, cookies: MutableMapping[str, str] | RequestsCookieJar | None = None, proxies: MutableMapping[str, str] | None = None">
10
10
  <arg kind="POSITIONAL_OR_NAMED" required="true" repr="source: str">
11
11
  <name>source</name>
12
12
  <type name="str" typedoc="string"/>
@@ -101,23 +101,9 @@
101
101
  <type name="int" typedoc="integer"/>
102
102
  <default>1</default>
103
103
  </arg>
104
- <arg kind="POSITIONAL_OR_NAMED" required="false" repr="recursion_default: dict[str, JSON] | list[JSON] | str | bytes | int | float | bool | None = {}">
104
+ <arg kind="POSITIONAL_OR_NAMED" required="false" repr="recursion_default: JSON = {}">
105
105
  <name>recursion_default</name>
106
- <type name="Union" union="true">
107
- <type name="dict" typedoc="dictionary">
108
- <type name="str" typedoc="string"/>
109
106
  <type name="JSON"/>
110
- </type>
111
- <type name="list" typedoc="list">
112
- <type name="JSON"/>
113
- </type>
114
- <type name="str" typedoc="string"/>
115
- <type name="bytes" typedoc="bytes"/>
116
- <type name="int" typedoc="integer"/>
117
- <type name="float" typedoc="float"/>
118
- <type name="bool" typedoc="boolean"/>
119
- <type name="None" typedoc="None"/>
120
- </type>
121
107
  <default>{}</default>
122
108
  </arg>
123
109
  <arg kind="POSITIONAL_OR_NAMED" required="false" repr="username: str = ">
@@ -350,17 +336,6 @@
350
336
  <usage>__init__</usage>
351
337
  </usages>
352
338
  </type>
353
- <type name="bytes" type="Standard">
354
- <doc>&lt;p&gt;Strings are converted to bytes so that each Unicode code point below 256 is directly mapped to a matching byte. Higher code points are not allowed. Robot Framework's &lt;code&gt;\xHH&lt;/code&gt; escape syntax is convenient with bytes having non-printable values.&lt;/p&gt;
355
- &lt;p&gt;Examples: &lt;code&gt;good&lt;/code&gt;, &lt;code&gt;hyvä&lt;/code&gt; (same as &lt;code&gt;hyv\xE4&lt;/code&gt;), &lt;code&gt;\x00&lt;/code&gt; (the null byte)&lt;/p&gt;</doc>
356
- <accepts>
357
- <type>string</type>
358
- <type>bytearray</type>
359
- </accepts>
360
- <usages>
361
- <usage>__init__</usage>
362
- </usages>
363
- </type>
364
339
  <type name="dictionary" type="Standard">
365
340
  <doc>&lt;p&gt;Strings must be Python &lt;a href="https://docs.python.org/library/stdtypes.html#dict"&gt;dictionary&lt;/a&gt; literals. They are converted to actual dictionaries using the &lt;a href="https://docs.python.org/library/ast.html#ast.literal_eval"&gt;ast.literal_eval&lt;/a&gt; function. They can contain any values &lt;code&gt;ast.literal_eval&lt;/code&gt; supports, including dictionaries and other containers.&lt;/p&gt;
366
341
  &lt;p&gt;If the type has nested types like &lt;code&gt;dict[str, int]&lt;/code&gt;, items are converted to those types automatically. This in new in Robot Framework 6.0.&lt;/p&gt;
@@ -373,18 +348,6 @@
373
348
  <usage>__init__</usage>
374
349
  </usages>
375
350
  </type>
376
- <type name="float" type="Standard">
377
- <doc>&lt;p&gt;Conversion is done using Python's &lt;a href="https://docs.python.org/library/functions.html#float"&gt;float&lt;/a&gt; built-in function.&lt;/p&gt;
378
- &lt;p&gt;Starting from RF 4.1, spaces and underscores can be used as visual separators for digit grouping purposes.&lt;/p&gt;
379
- &lt;p&gt;Examples: &lt;code&gt;3.14&lt;/code&gt;, &lt;code&gt;2.9979e8&lt;/code&gt;, &lt;code&gt;10 000.000 01&lt;/code&gt;&lt;/p&gt;</doc>
380
- <accepts>
381
- <type>string</type>
382
- <type>Real</type>
383
- </accepts>
384
- <usages>
385
- <usage>__init__</usage>
386
- </usages>
387
- </type>
388
351
  <type name="integer" type="Standard">
389
352
  <doc>&lt;p&gt;Conversion is done using Python's &lt;a href="https://docs.python.org/library/functions.html#int"&gt;int&lt;/a&gt; built-in function. Floating point numbers are accepted only if they can be represented as integers exactly. For example, &lt;code&gt;1.0&lt;/code&gt; is accepted and &lt;code&gt;1.1&lt;/code&gt; is not.&lt;/p&gt;
390
353
  &lt;p&gt;Starting from RF 4.1, it is possible to use hexadecimal, octal and binary numbers by prefixing values with &lt;code&gt;0x&lt;/code&gt;, &lt;code&gt;0o&lt;/code&gt; and &lt;code&gt;0b&lt;/code&gt;, respectively.&lt;/p&gt;
@@ -21,7 +21,6 @@ from OpenApiLibCore.dto_base import (
21
21
  PropertyValueConstraint,
22
22
  ResourceRelation,
23
23
  UniquePropertyValueConstraint,
24
- resolve_schema,
25
24
  )
26
25
  from OpenApiLibCore.dto_utils import DefaultDto
27
26
  from OpenApiLibCore.openapi_libcore import (
@@ -52,5 +51,4 @@ __all__ = [
52
51
  "ResourceRelation",
53
52
  "UniquePropertyValueConstraint",
54
53
  "ValidationLevel",
55
- "resolve_schema",
56
54
  ]
@@ -1,3 +1,10 @@
1
1
  """Module holding reusable compound annotations."""
2
2
 
3
- JSON = dict[str, "JSON"] | list["JSON"] | str | bytes | int | float | bool | None
3
+ from typing import Union
4
+
5
+ from typing_extensions import TypeAliasType
6
+
7
+ JSON = TypeAliasType(
8
+ "JSON",
9
+ "Union[dict[str, JSON], list[JSON], str, bytes, int, float, bool, None]",
10
+ )
@@ -3,10 +3,8 @@ Module holding the functions related to data generation
3
3
  for the requests made as part of keyword exection.
4
4
  """
5
5
 
6
- from .body_data_generation import get_json_data_for_dto_class
7
6
  from .data_generation_core import get_request_data
8
7
 
9
8
  __all__ = [
10
- "get_json_data_for_dto_class",
11
9
  "get_request_data",
12
10
  ]
@@ -16,26 +16,41 @@ from OpenApiLibCore.dto_base import (
16
16
  PropertyValueConstraint,
17
17
  )
18
18
  from OpenApiLibCore.dto_utils import DefaultDto
19
+ from OpenApiLibCore.models import (
20
+ ArraySchema,
21
+ ObjectSchema,
22
+ SchemaObjectTypes,
23
+ UnionTypeSchema,
24
+ )
19
25
  from OpenApiLibCore.parameter_utils import get_safe_name_for_oas_name
20
26
  from OpenApiLibCore.protocols import GetIdPropertyNameType
21
- from OpenApiLibCore.value_utils import IGNORE, get_valid_value
27
+ from OpenApiLibCore.value_utils import IGNORE
22
28
 
23
29
 
24
30
  def get_json_data_for_dto_class(
25
- schema: dict[str, Any],
31
+ schema: SchemaObjectTypes,
26
32
  dto_class: type[Dto],
27
33
  get_id_property_name: GetIdPropertyNameType,
28
- operation_id: str = "",
34
+ operation_id: str | None = None,
29
35
  ) -> JSON:
30
- match schema.get("type"):
31
- case "object":
36
+ if isinstance(schema, UnionTypeSchema):
37
+ chosen_schema = choice(schema.resolved_schemas)
38
+ return get_json_data_for_dto_class(
39
+ schema=chosen_schema,
40
+ dto_class=dto_class,
41
+ get_id_property_name=get_id_property_name,
42
+ operation_id=operation_id,
43
+ )
44
+
45
+ match schema:
46
+ case ObjectSchema():
32
47
  return get_dict_data_for_dto_class(
33
48
  schema=schema,
34
49
  dto_class=dto_class,
35
50
  get_id_property_name=get_id_property_name,
36
51
  operation_id=operation_id,
37
52
  )
38
- case "array":
53
+ case ArraySchema():
39
54
  return get_list_data_for_dto_class(
40
55
  schema=schema,
41
56
  dto_class=dto_class,
@@ -43,22 +58,22 @@ def get_json_data_for_dto_class(
43
58
  operation_id=operation_id,
44
59
  )
45
60
  case _:
46
- return get_valid_value(value_schema=schema)
61
+ return schema.get_valid_value()
47
62
 
48
63
 
49
64
  def get_dict_data_for_dto_class(
50
- schema: dict[str, Any],
65
+ schema: ObjectSchema,
51
66
  dto_class: type[Dto],
52
67
  get_id_property_name: GetIdPropertyNameType,
53
- operation_id: str = "",
68
+ operation_id: str | None = None,
54
69
  ) -> dict[str, Any]:
55
70
  json_data: dict[str, Any] = {}
56
71
 
57
72
  property_names = get_property_names_to_process(schema=schema, dto_class=dto_class)
58
73
 
59
74
  for property_name in property_names:
60
- property_schema = schema["properties"][property_name]
61
- if property_schema.get("readOnly", False):
75
+ property_schema = schema.properties.root[property_name]
76
+ if property_schema.readOnly:
62
77
  continue
63
78
 
64
79
  json_data[property_name] = get_data_for_property(
@@ -73,15 +88,15 @@ def get_dict_data_for_dto_class(
73
88
 
74
89
 
75
90
  def get_list_data_for_dto_class(
76
- schema: dict[str, Any],
91
+ schema: ArraySchema,
77
92
  dto_class: type[Dto],
78
93
  get_id_property_name: GetIdPropertyNameType,
79
- operation_id: str = "",
80
- ) -> list[Any]:
81
- json_data: list[Any] = []
82
- list_item_schema = schema.get("items", {})
83
- min_items = schema.get("minItems", 0)
84
- max_items = schema.get("maxItems", 1)
94
+ operation_id: str | None = None,
95
+ ) -> list[JSON]:
96
+ json_data: list[JSON] = []
97
+ list_item_schema = schema.items
98
+ min_items = schema.minItems if schema.minItems is not None else 0
99
+ max_items = schema.maxItems if schema.maxItems is not None else 1
85
100
  number_of_items_to_generate = randint(min_items, max_items)
86
101
  for _ in range(number_of_items_to_generate):
87
102
  list_item_data = get_json_data_for_dto_class(
@@ -96,29 +111,11 @@ def get_list_data_for_dto_class(
96
111
 
97
112
  def get_data_for_property(
98
113
  property_name: str,
99
- property_schema: dict[str, Any],
114
+ property_schema: SchemaObjectTypes,
100
115
  get_id_property_name: GetIdPropertyNameType,
101
116
  dto_class: type[Dto],
102
- operation_id: str,
117
+ operation_id: str | None,
103
118
  ) -> JSON:
104
- property_type = property_schema.get("type")
105
- if property_type is None:
106
- property_types = property_schema.get("types")
107
- if property_types is None:
108
- if property_schema.get("properties") is None:
109
- raise NotImplementedError
110
-
111
- nested_data = get_json_data_for_dto_class(
112
- schema=property_schema,
113
- dto_class=DefaultDto,
114
- get_id_property_name=get_id_property_name,
115
- )
116
- return nested_data
117
-
118
- selected_type_schema = choice(property_types)
119
- property_type = selected_type_schema["type"]
120
- property_schema = selected_type_schema
121
-
122
119
  if constrained_values := get_constrained_values(
123
120
  dto_class=dto_class, property_name=property_name
124
121
  ):
@@ -144,32 +141,18 @@ def get_data_for_property(
144
141
  ) is not None:
145
142
  return dependent_id
146
143
 
147
- if property_type == "object":
148
- object_data = get_json_data_for_dto_class(
149
- schema=property_schema,
150
- dto_class=DefaultDto,
151
- get_id_property_name=get_id_property_name,
152
- operation_id="",
153
- )
154
- return object_data
155
-
156
- if property_type == "array":
157
- array_data = get_json_data_for_dto_class(
158
- schema=property_schema["items"],
159
- dto_class=DefaultDto,
160
- get_id_property_name=get_id_property_name,
161
- operation_id=operation_id,
162
- )
163
- return [array_data]
164
-
165
- return get_valid_value(property_schema)
144
+ return get_json_data_for_dto_class(
145
+ schema=property_schema,
146
+ dto_class=DefaultDto,
147
+ get_id_property_name=get_id_property_name,
148
+ )
166
149
 
167
150
 
168
151
  def get_value_constrained_by_nested_dto(
169
- property_schema: dict[str, Any],
152
+ property_schema: SchemaObjectTypes,
170
153
  nested_dto_class: type[Dto],
171
154
  get_id_property_name: GetIdPropertyNameType,
172
- operation_id: str,
155
+ operation_id: str | None,
173
156
  ) -> JSON:
174
157
  nested_schema = get_schema_for_nested_dto(property_schema=property_schema)
175
158
  nested_value = get_json_data_for_dto_class(
@@ -181,23 +164,21 @@ def get_value_constrained_by_nested_dto(
181
164
  return nested_value
182
165
 
183
166
 
184
- def get_schema_for_nested_dto(property_schema: dict[str, Any]) -> dict[str, Any]:
185
- if property_schema.get("type"):
186
- return property_schema
187
-
188
- if possible_types := property_schema.get("types"):
189
- return choice(possible_types)
167
+ def get_schema_for_nested_dto(property_schema: SchemaObjectTypes) -> SchemaObjectTypes:
168
+ if isinstance(property_schema, UnionTypeSchema):
169
+ chosen_schema = choice(property_schema.resolved_schemas)
170
+ return get_schema_for_nested_dto(chosen_schema)
190
171
 
191
- raise NotImplementedError
172
+ return property_schema
192
173
 
193
174
 
194
175
  def get_property_names_to_process(
195
- schema: dict[str, Any],
176
+ schema: ObjectSchema,
196
177
  dto_class: type[Dto],
197
178
  ) -> list[str]:
198
179
  property_names = []
199
180
 
200
- for property_name in schema.get("properties", []):
181
+ for property_name in schema.properties.root:
201
182
  # register the oas_name
202
183
  _ = get_safe_name_for_oas_name(property_name)
203
184
  if constrained_values := get_constrained_values(
@@ -208,9 +189,9 @@ def get_property_names_to_process(
208
189
  continue
209
190
  property_names.append(property_name)
210
191
 
211
- max_properties = schema.get("maxProperties")
192
+ max_properties = schema.maxProperties
212
193
  if max_properties and len(property_names) > max_properties:
213
- required_properties = schema.get("required", [])
194
+ required_properties = schema.required
214
195
  number_of_optional_properties = max_properties - len(required_properties)
215
196
  optional_properties = [
216
197
  name for name in property_names if name not in required_properties
@@ -239,7 +220,7 @@ def get_constrained_values(
239
220
  def get_dependent_id(
240
221
  dto_class: type[Dto],
241
222
  property_name: str,
242
- operation_id: str,
223
+ operation_id: str | None,
243
224
  get_id_property_name: GetIdPropertyNameType,
244
225
  ) -> str | int | float | None:
245
226
  relations = dto_class.get_relations()