robotframework-openapitools 0.4.0__py3-none-any.whl → 1.0.0__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.
- OpenApiDriver/__init__.py +45 -41
- OpenApiDriver/openapi_executors.py +78 -49
- OpenApiDriver/openapi_reader.py +114 -116
- OpenApiDriver/openapidriver.libspec +209 -133
- OpenApiDriver/openapidriver.py +31 -296
- OpenApiLibCore/__init__.py +39 -13
- OpenApiLibCore/annotations.py +10 -0
- OpenApiLibCore/data_generation/__init__.py +10 -0
- OpenApiLibCore/data_generation/body_data_generation.py +250 -0
- OpenApiLibCore/data_generation/data_generation_core.py +233 -0
- OpenApiLibCore/data_invalidation.py +294 -0
- OpenApiLibCore/dto_base.py +67 -130
- OpenApiLibCore/dto_utils.py +125 -85
- OpenApiLibCore/localized_faker.py +88 -0
- OpenApiLibCore/models.py +723 -0
- OpenApiLibCore/oas_cache.py +14 -13
- OpenApiLibCore/openapi_libcore.libspec +355 -330
- OpenApiLibCore/openapi_libcore.py +385 -1953
- OpenApiLibCore/parameter_utils.py +97 -0
- OpenApiLibCore/path_functions.py +215 -0
- OpenApiLibCore/path_invalidation.py +42 -0
- OpenApiLibCore/protocols.py +38 -0
- OpenApiLibCore/request_data.py +246 -0
- OpenApiLibCore/resource_relations.py +55 -0
- OpenApiLibCore/validation.py +380 -0
- OpenApiLibCore/value_utils.py +216 -481
- openapi_libgen/__init__.py +3 -0
- openapi_libgen/command_line.py +75 -0
- openapi_libgen/generator.py +82 -0
- openapi_libgen/parsing_utils.py +30 -0
- openapi_libgen/spec_parser.py +154 -0
- openapi_libgen/templates/__init__.jinja +3 -0
- openapi_libgen/templates/library.jinja +30 -0
- robotframework_openapitools-1.0.0.dist-info/METADATA +249 -0
- robotframework_openapitools-1.0.0.dist-info/RECORD +40 -0
- {robotframework_openapitools-0.4.0.dist-info → robotframework_openapitools-1.0.0.dist-info}/WHEEL +1 -1
- robotframework_openapitools-1.0.0.dist-info/entry_points.txt +3 -0
- roboswag/__init__.py +0 -9
- roboswag/__main__.py +0 -3
- roboswag/auth.py +0 -44
- roboswag/cli.py +0 -80
- roboswag/core.py +0 -85
- roboswag/generate/__init__.py +0 -1
- roboswag/generate/generate.py +0 -121
- roboswag/generate/models/__init__.py +0 -0
- roboswag/generate/models/api.py +0 -219
- roboswag/generate/models/definition.py +0 -28
- roboswag/generate/models/endpoint.py +0 -68
- roboswag/generate/models/parameter.py +0 -25
- roboswag/generate/models/response.py +0 -8
- roboswag/generate/models/tag.py +0 -16
- roboswag/generate/models/utils.py +0 -60
- roboswag/generate/templates/api_init.jinja +0 -15
- roboswag/generate/templates/models.jinja +0 -7
- roboswag/generate/templates/paths.jinja +0 -68
- roboswag/logger.py +0 -33
- roboswag/validate/__init__.py +0 -6
- roboswag/validate/core.py +0 -3
- roboswag/validate/schema.py +0 -21
- roboswag/validate/text_response.py +0 -14
- robotframework_openapitools-0.4.0.dist-info/METADATA +0 -42
- robotframework_openapitools-0.4.0.dist-info/RECORD +0 -41
- {robotframework_openapitools-0.4.0.dist-info → robotframework_openapitools-1.0.0.dist-info}/LICENSE +0 -0
OpenApiLibCore/dto_utils.py
CHANGED
@@ -1,85 +1,125 @@
|
|
1
|
-
"""Module for helper methods and classes used by the openapi_executors module."""
|
2
|
-
|
3
|
-
from dataclasses import dataclass
|
4
|
-
from importlib import import_module
|
5
|
-
from
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
1
|
+
"""Module for helper methods and classes used by the openapi_executors module."""
|
2
|
+
|
3
|
+
from dataclasses import dataclass
|
4
|
+
from importlib import import_module
|
5
|
+
from typing import Any, Callable, Type, overload
|
6
|
+
|
7
|
+
from robot.api import logger
|
8
|
+
|
9
|
+
from OpenApiLibCore.dto_base import Dto
|
10
|
+
from OpenApiLibCore.protocols import (
|
11
|
+
GetDtoClassType,
|
12
|
+
GetIdPropertyNameType,
|
13
|
+
GetPathDtoClassType,
|
14
|
+
)
|
15
|
+
|
16
|
+
|
17
|
+
@dataclass
|
18
|
+
class _DefaultIdPropertyName:
|
19
|
+
id_property_name: str = "id"
|
20
|
+
|
21
|
+
|
22
|
+
DEFAULT_ID_PROPERTY_NAME = _DefaultIdPropertyName()
|
23
|
+
|
24
|
+
|
25
|
+
@dataclass
|
26
|
+
class DefaultDto(Dto):
|
27
|
+
"""A default Dto that can be instantiated."""
|
28
|
+
|
29
|
+
|
30
|
+
def get_dto_class(mappings_module_name: str) -> GetDtoClassType:
|
31
|
+
return GetDtoClass(mappings_module_name=mappings_module_name)
|
32
|
+
|
33
|
+
|
34
|
+
class GetDtoClass:
|
35
|
+
"""Callable class to return Dtos from user-implemented mappings file."""
|
36
|
+
|
37
|
+
def __init__(self, mappings_module_name: str) -> None:
|
38
|
+
try:
|
39
|
+
mappings_module = import_module(mappings_module_name)
|
40
|
+
self.dto_mapping: dict[tuple[str, str], Type[Dto]] = (
|
41
|
+
mappings_module.DTO_MAPPING
|
42
|
+
)
|
43
|
+
except (ImportError, AttributeError, ValueError) as exception:
|
44
|
+
if mappings_module_name != "no mapping":
|
45
|
+
logger.error(f"DTO_MAPPING was not imported: {exception}")
|
46
|
+
self.dto_mapping = {}
|
47
|
+
|
48
|
+
def __call__(self, path: str, method: str) -> Type[Dto]:
|
49
|
+
try:
|
50
|
+
return self.dto_mapping[(path, method.lower())]
|
51
|
+
except KeyError:
|
52
|
+
logger.debug(f"No Dto mapping for {path} {method}.")
|
53
|
+
return DefaultDto
|
54
|
+
|
55
|
+
|
56
|
+
def get_path_dto_class(mappings_module_name: str) -> GetPathDtoClassType:
|
57
|
+
return GetPathDtoClass(mappings_module_name=mappings_module_name)
|
58
|
+
|
59
|
+
|
60
|
+
class GetPathDtoClass:
|
61
|
+
"""Callable class to return Dtos from user-implemented mappings file."""
|
62
|
+
|
63
|
+
def __init__(self, mappings_module_name: str) -> None:
|
64
|
+
try:
|
65
|
+
mappings_module = import_module(mappings_module_name)
|
66
|
+
self.dto_mapping: dict[str, Type[Dto]] = mappings_module.PATH_MAPPING
|
67
|
+
except (ImportError, AttributeError, ValueError) as exception:
|
68
|
+
if mappings_module_name != "no mapping":
|
69
|
+
logger.error(f"PATH_MAPPING was not imported: {exception}")
|
70
|
+
self.dto_mapping = {}
|
71
|
+
|
72
|
+
def __call__(self, path: str) -> Type[Dto]:
|
73
|
+
try:
|
74
|
+
return self.dto_mapping[path]
|
75
|
+
except KeyError:
|
76
|
+
logger.debug(f"No Dto mapping for {path}.")
|
77
|
+
return DefaultDto
|
78
|
+
|
79
|
+
|
80
|
+
def get_id_property_name(mappings_module_name: str) -> GetIdPropertyNameType:
|
81
|
+
return GetIdPropertyName(mappings_module_name=mappings_module_name)
|
82
|
+
|
83
|
+
|
84
|
+
class GetIdPropertyName:
|
85
|
+
"""
|
86
|
+
Callable class to return the name of the property that uniquely identifies
|
87
|
+
the resource from user-implemented mappings file.
|
88
|
+
"""
|
89
|
+
|
90
|
+
def __init__(self, mappings_module_name: str) -> None:
|
91
|
+
try:
|
92
|
+
mappings_module = import_module(mappings_module_name)
|
93
|
+
self.id_mapping: dict[
|
94
|
+
str,
|
95
|
+
str | tuple[str, Callable[[str], str] | Callable[[int], int]],
|
96
|
+
] = mappings_module.ID_MAPPING
|
97
|
+
except (ImportError, AttributeError, ValueError) as exception:
|
98
|
+
if mappings_module_name != "no mapping":
|
99
|
+
logger.error(f"ID_MAPPING was not imported: {exception}")
|
100
|
+
self.id_mapping = {}
|
101
|
+
|
102
|
+
def __call__(
|
103
|
+
self, path: str
|
104
|
+
) -> tuple[str, Callable[[str], str] | Callable[[int], int]]:
|
105
|
+
try:
|
106
|
+
value_or_mapping = self.id_mapping[path]
|
107
|
+
if isinstance(value_or_mapping, str):
|
108
|
+
return (value_or_mapping, dummy_transformer)
|
109
|
+
return value_or_mapping
|
110
|
+
except KeyError:
|
111
|
+
default_id_name = DEFAULT_ID_PROPERTY_NAME.id_property_name
|
112
|
+
logger.debug(f"No id mapping for {path} ('{default_id_name}' will be used)")
|
113
|
+
return (default_id_name, dummy_transformer)
|
114
|
+
|
115
|
+
|
116
|
+
@overload
|
117
|
+
def dummy_transformer(valid_id: str) -> str: ... # pragma: no cover
|
118
|
+
|
119
|
+
|
120
|
+
@overload
|
121
|
+
def dummy_transformer(valid_id: int) -> int: ... # pragma: no cover
|
122
|
+
|
123
|
+
|
124
|
+
def dummy_transformer(valid_id: Any) -> Any:
|
125
|
+
return valid_id
|
@@ -0,0 +1,88 @@
|
|
1
|
+
import datetime
|
2
|
+
from typing import Callable
|
3
|
+
|
4
|
+
import faker
|
5
|
+
|
6
|
+
|
7
|
+
def fake_string(string_format: str) -> str:
|
8
|
+
"""
|
9
|
+
Generate a random string based on the provided format if the format is supported.
|
10
|
+
"""
|
11
|
+
# format names may contain -, which is invalid in Python naming
|
12
|
+
string_format = string_format.replace("-", "_")
|
13
|
+
fake_generator = getattr(FAKE, string_format, FAKE.uuid)
|
14
|
+
value: str = fake_generator()
|
15
|
+
if isinstance(value, datetime.datetime):
|
16
|
+
return value.strftime("%Y-%m-%dT%H:%M:%SZ")
|
17
|
+
return value
|
18
|
+
|
19
|
+
|
20
|
+
class LocalizedFaker:
|
21
|
+
"""Class to support setting a locale post-init."""
|
22
|
+
|
23
|
+
# pylint: disable=missing-function-docstring
|
24
|
+
def __init__(self) -> None:
|
25
|
+
self.fake = faker.Faker()
|
26
|
+
|
27
|
+
def set_locale(self, locale: str | list[str]) -> None:
|
28
|
+
"""Update the fake attribute with a Faker instance with the provided locale."""
|
29
|
+
self.fake = faker.Faker(locale)
|
30
|
+
|
31
|
+
@property
|
32
|
+
def date(self) -> Callable[[], str]:
|
33
|
+
return self.fake.date
|
34
|
+
|
35
|
+
@property
|
36
|
+
def date_time(self) -> Callable[[], datetime.datetime]:
|
37
|
+
return self.fake.date_time
|
38
|
+
|
39
|
+
@property
|
40
|
+
def password(self) -> Callable[[], str]:
|
41
|
+
return self.fake.password
|
42
|
+
|
43
|
+
@property
|
44
|
+
def binary(self) -> Callable[[], bytes]:
|
45
|
+
return self.fake.binary
|
46
|
+
|
47
|
+
@property
|
48
|
+
def email(self) -> Callable[[], str]:
|
49
|
+
return self.fake.safe_email
|
50
|
+
|
51
|
+
@property
|
52
|
+
def uuid(self) -> Callable[[], str]:
|
53
|
+
return self.fake.uuid4
|
54
|
+
|
55
|
+
@property
|
56
|
+
def uri(self) -> Callable[[], str]:
|
57
|
+
return self.fake.uri
|
58
|
+
|
59
|
+
@property
|
60
|
+
def url(self) -> Callable[[], str]:
|
61
|
+
return self.fake.url
|
62
|
+
|
63
|
+
@property
|
64
|
+
def hostname(self) -> Callable[[], str]:
|
65
|
+
return self.fake.hostname
|
66
|
+
|
67
|
+
@property
|
68
|
+
def ipv4(self) -> Callable[[], str]:
|
69
|
+
return self.fake.ipv4
|
70
|
+
|
71
|
+
@property
|
72
|
+
def ipv6(self) -> Callable[[], str]:
|
73
|
+
return self.fake.ipv6
|
74
|
+
|
75
|
+
@property
|
76
|
+
def name(self) -> Callable[[], str]:
|
77
|
+
return self.fake.name
|
78
|
+
|
79
|
+
@property
|
80
|
+
def text(self) -> Callable[[], str]:
|
81
|
+
return self.fake.text
|
82
|
+
|
83
|
+
@property
|
84
|
+
def description(self) -> Callable[[], str]:
|
85
|
+
return self.fake.text
|
86
|
+
|
87
|
+
|
88
|
+
FAKE = LocalizedFaker()
|