schemathesis 3.19.0__py3-none-any.whl → 3.19.1__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.
- schemathesis/auths.py +20 -20
- schemathesis/cli/__init__.py +20 -20
- schemathesis/cli/cassettes.py +18 -18
- schemathesis/cli/context.py +25 -25
- schemathesis/cli/debug.py +3 -3
- schemathesis/cli/junitxml.py +4 -4
- schemathesis/constants.py +3 -3
- schemathesis/exceptions.py +9 -9
- schemathesis/extra/pytest_plugin.py +1 -1
- schemathesis/failures.py +65 -66
- schemathesis/filters.py +13 -13
- schemathesis/hooks.py +11 -11
- schemathesis/lazy.py +16 -16
- schemathesis/models.py +97 -97
- schemathesis/parameters.py +5 -6
- schemathesis/runner/events.py +55 -55
- schemathesis/runner/impl/core.py +26 -26
- schemathesis/runner/impl/solo.py +6 -7
- schemathesis/runner/impl/threadpool.py +5 -5
- schemathesis/runner/serialization.py +50 -50
- schemathesis/schemas.py +23 -23
- schemathesis/serializers.py +3 -3
- schemathesis/service/ci.py +25 -25
- schemathesis/service/client.py +2 -2
- schemathesis/service/events.py +12 -13
- schemathesis/service/hosts.py +4 -4
- schemathesis/service/metadata.py +14 -15
- schemathesis/service/models.py +12 -13
- schemathesis/service/report.py +30 -31
- schemathesis/service/serialization.py +2 -4
- schemathesis/specs/graphql/schemas.py +8 -8
- schemathesis/specs/openapi/expressions/context.py +4 -4
- schemathesis/specs/openapi/expressions/lexer.py +11 -12
- schemathesis/specs/openapi/expressions/nodes.py +16 -16
- schemathesis/specs/openapi/expressions/parser.py +1 -1
- schemathesis/specs/openapi/links.py +15 -17
- schemathesis/specs/openapi/negative/__init__.py +5 -5
- schemathesis/specs/openapi/negative/mutations.py +6 -6
- schemathesis/specs/openapi/parameters.py +12 -13
- schemathesis/specs/openapi/references.py +2 -2
- schemathesis/specs/openapi/schemas.py +11 -15
- schemathesis/specs/openapi/security.py +7 -7
- schemathesis/specs/openapi/stateful/links.py +4 -4
- schemathesis/stateful.py +19 -19
- schemathesis/targets.py +5 -6
- schemathesis/types.py +11 -13
- schemathesis/utils.py +2 -2
- {schemathesis-3.19.0.dist-info → schemathesis-3.19.1.dist-info}/METADATA +2 -3
- {schemathesis-3.19.0.dist-info → schemathesis-3.19.1.dist-info}/RECORD +52 -52
- {schemathesis-3.19.0.dist-info → schemathesis-3.19.1.dist-info}/WHEEL +0 -0
- {schemathesis-3.19.0.dist-info → schemathesis-3.19.1.dist-info}/entry_points.txt +0 -0
- {schemathesis-3.19.0.dist-info → schemathesis-3.19.1.dist-info}/licenses/LICENSE +0 -0
schemathesis/service/ci.py
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import enum
|
|
2
2
|
import os
|
|
3
|
+
from dataclasses import asdict, dataclass
|
|
3
4
|
from typing import Dict, Optional
|
|
4
5
|
|
|
5
|
-
import attr
|
|
6
6
|
from typing_extensions import Protocol, runtime_checkable
|
|
7
7
|
|
|
8
8
|
|
|
@@ -54,52 +54,52 @@ def detect() -> Optional[CIProvider]:
|
|
|
54
54
|
return None
|
|
55
55
|
|
|
56
56
|
|
|
57
|
-
def
|
|
58
|
-
data =
|
|
57
|
+
def _asdict(env: Environment) -> Dict[str, Optional[str]]:
|
|
58
|
+
data = asdict(env)
|
|
59
59
|
data["provider"] = env.provider.value
|
|
60
60
|
return data
|
|
61
61
|
|
|
62
62
|
|
|
63
|
-
@
|
|
63
|
+
@dataclass
|
|
64
64
|
class GitHubActionsEnvironment:
|
|
65
65
|
"""Useful data to capture from GitHub Actions environment."""
|
|
66
66
|
|
|
67
67
|
provider = CIProvider.GITHUB
|
|
68
68
|
variable_name = "GITHUB_ACTIONS"
|
|
69
69
|
verbose_name = "GitHub Actions"
|
|
70
|
-
asdict =
|
|
70
|
+
asdict = _asdict
|
|
71
71
|
|
|
72
72
|
# GitHub API URL.
|
|
73
73
|
# For example, `https://api.github.com`
|
|
74
|
-
api_url: str
|
|
74
|
+
api_url: str
|
|
75
75
|
# The owner and repository name.
|
|
76
76
|
# For example, `schemathesis/schemathesis`.
|
|
77
|
-
repository: str
|
|
77
|
+
repository: str
|
|
78
78
|
# The name of the person or app that initiated the workflow.
|
|
79
79
|
# For example, `Stranger6667`
|
|
80
|
-
actor: str
|
|
80
|
+
actor: str
|
|
81
81
|
# The commit SHA that triggered the workflow.
|
|
82
82
|
# For example, `e56e13224f08469841e106449f6467b769e2afca`
|
|
83
|
-
sha: str
|
|
83
|
+
sha: str
|
|
84
84
|
# A unique number for each workflow run within a repository.
|
|
85
85
|
# For example, `1658821493`.
|
|
86
|
-
run_id: str
|
|
86
|
+
run_id: str
|
|
87
87
|
# The name of the workflow.
|
|
88
88
|
# For example, `My test workflow`.
|
|
89
|
-
workflow: str
|
|
89
|
+
workflow: str
|
|
90
90
|
# The head ref or source branch of the pull request in a workflow run.
|
|
91
91
|
# For example, `dd/report-ci`.
|
|
92
|
-
head_ref: Optional[str]
|
|
92
|
+
head_ref: Optional[str]
|
|
93
93
|
# The name of the base ref or target branch of the pull request in a workflow run.
|
|
94
94
|
# For example, `main`.
|
|
95
|
-
base_ref: Optional[str]
|
|
95
|
+
base_ref: Optional[str]
|
|
96
96
|
# The branch or tag ref that triggered the workflow run.
|
|
97
97
|
# This is only set if a branch or tag is available for the event type.
|
|
98
98
|
# For example, `refs/pull/1533/merge`
|
|
99
|
-
ref: Optional[str]
|
|
99
|
+
ref: Optional[str]
|
|
100
100
|
# The Schemathesis GitHub Action version.
|
|
101
101
|
# For example `v1.0.1`
|
|
102
|
-
action_ref: Optional[str]
|
|
102
|
+
action_ref: Optional[str]
|
|
103
103
|
|
|
104
104
|
@classmethod
|
|
105
105
|
def is_set(cls) -> bool:
|
|
@@ -135,42 +135,42 @@ class GitHubActionsEnvironment:
|
|
|
135
135
|
}
|
|
136
136
|
|
|
137
137
|
|
|
138
|
-
@
|
|
138
|
+
@dataclass
|
|
139
139
|
class GitLabCIEnvironment:
|
|
140
140
|
"""Useful data to capture from GitLab CI environment."""
|
|
141
141
|
|
|
142
142
|
provider = CIProvider.GITLAB
|
|
143
143
|
variable_name = "GITLAB_CI"
|
|
144
144
|
verbose_name = "GitLab CI"
|
|
145
|
-
asdict =
|
|
145
|
+
asdict = _asdict
|
|
146
146
|
|
|
147
147
|
# GitLab API URL
|
|
148
148
|
# For example, `https://gitlab.com/api/v4`
|
|
149
|
-
api_v4_url: str
|
|
149
|
+
api_v4_url: str
|
|
150
150
|
# The ID of the current project.
|
|
151
151
|
# For example, `12345678`
|
|
152
|
-
project_id: str
|
|
152
|
+
project_id: str
|
|
153
153
|
# The username of the user who started the job.
|
|
154
154
|
# For example, `Stranger6667`
|
|
155
|
-
user_login: str
|
|
155
|
+
user_login: str
|
|
156
156
|
# The commit revision the project is built for.
|
|
157
157
|
# For example, `e56e13224f08469841e106449f6467b769e2afca`
|
|
158
|
-
commit_sha: str
|
|
158
|
+
commit_sha: str
|
|
159
159
|
# NOTE: `commit_branch` and `merge_request_source_branch_name` may mean the same thing, but they are available
|
|
160
160
|
# in different context. There are also a couple of `CI_BUILD_*` variables that could be used, but they are
|
|
161
161
|
# not documented.
|
|
162
162
|
# The commit branch name. Not available in merge request pipelines or tag pipelines.
|
|
163
163
|
# For example, `dd/report-ci`.
|
|
164
|
-
commit_branch: Optional[str]
|
|
164
|
+
commit_branch: Optional[str]
|
|
165
165
|
# The source branch name of the merge request. Only available in merge request pipelines.
|
|
166
166
|
# For example, `dd/report-ci`.
|
|
167
|
-
merge_request_source_branch_name: Optional[str]
|
|
167
|
+
merge_request_source_branch_name: Optional[str]
|
|
168
168
|
# The target branch name of the merge request.
|
|
169
169
|
# For example, `main`.
|
|
170
|
-
merge_request_target_branch_name: Optional[str]
|
|
170
|
+
merge_request_target_branch_name: Optional[str]
|
|
171
171
|
# The project-level internal ID of the merge request.
|
|
172
172
|
# For example, `42`.
|
|
173
|
-
merge_request_iid: Optional[str]
|
|
173
|
+
merge_request_iid: Optional[str]
|
|
174
174
|
|
|
175
175
|
@classmethod
|
|
176
176
|
def is_set(cls) -> bool:
|
schemathesis/service/client.py
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import hashlib
|
|
2
2
|
import http
|
|
3
|
+
from dataclasses import asdict
|
|
3
4
|
from typing import Any, Optional, Union
|
|
4
5
|
from urllib.parse import urljoin
|
|
5
6
|
|
|
6
|
-
import attr
|
|
7
7
|
import requests
|
|
8
8
|
from requests.adapters import HTTPAdapter, Retry
|
|
9
9
|
|
|
@@ -51,7 +51,7 @@ class ServiceClient(requests.Session):
|
|
|
51
51
|
|
|
52
52
|
def login(self, metadata: Metadata) -> AuthResponse:
|
|
53
53
|
"""Send a login request."""
|
|
54
|
-
response = self.post("/auth/cli/login/", json={"metadata":
|
|
54
|
+
response = self.post("/auth/cli/login/", json={"metadata": asdict(metadata)})
|
|
55
55
|
data = response.json()
|
|
56
56
|
return AuthResponse(username=data["username"])
|
|
57
57
|
|
schemathesis/service/events.py
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
1
2
|
from typing import Optional
|
|
2
3
|
|
|
3
|
-
import attr
|
|
4
|
-
|
|
5
4
|
from ..utils import format_exception
|
|
6
5
|
from . import ci
|
|
7
6
|
|
|
@@ -17,40 +16,40 @@ class Event:
|
|
|
17
16
|
return self.__class__.__name__.upper()
|
|
18
17
|
|
|
19
18
|
|
|
20
|
-
@
|
|
19
|
+
@dataclass
|
|
21
20
|
class Metadata(Event):
|
|
22
21
|
"""Meta-information about the report."""
|
|
23
22
|
|
|
24
|
-
size: int
|
|
25
|
-
ci_environment: Optional[ci.Environment]
|
|
23
|
+
size: int
|
|
24
|
+
ci_environment: Optional[ci.Environment]
|
|
26
25
|
|
|
27
26
|
|
|
28
|
-
@
|
|
27
|
+
@dataclass
|
|
29
28
|
class Completed(Event):
|
|
30
29
|
"""Report uploaded successfully."""
|
|
31
30
|
|
|
32
|
-
message: str
|
|
33
|
-
next_url: str
|
|
31
|
+
message: str
|
|
32
|
+
next_url: str
|
|
34
33
|
|
|
35
34
|
|
|
36
|
-
@
|
|
35
|
+
@dataclass
|
|
37
36
|
class Error(Event):
|
|
38
37
|
"""Internal error inside the Schemathesis.io handler."""
|
|
39
38
|
|
|
40
|
-
exception: Exception
|
|
39
|
+
exception: Exception
|
|
41
40
|
|
|
42
41
|
def get_message(self, include_traceback: bool = False) -> str:
|
|
43
42
|
return format_exception(self.exception, include_traceback=include_traceback)
|
|
44
43
|
|
|
45
44
|
|
|
46
|
-
@
|
|
45
|
+
@dataclass
|
|
47
46
|
class Failed(Event):
|
|
48
47
|
"""A client-side error which should be displayed to the user."""
|
|
49
48
|
|
|
50
|
-
detail: str
|
|
49
|
+
detail: str
|
|
51
50
|
|
|
52
51
|
|
|
53
|
-
@
|
|
52
|
+
@dataclass
|
|
54
53
|
class Timeout(Event):
|
|
55
54
|
"""The handler did not finish its work in time.
|
|
56
55
|
|
schemathesis/service/hosts.py
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"""Work with stored auth data."""
|
|
2
2
|
import enum
|
|
3
3
|
import tempfile
|
|
4
|
+
from dataclasses import dataclass
|
|
4
5
|
from pathlib import Path
|
|
5
6
|
from typing import Any, Dict, Optional
|
|
6
7
|
|
|
7
|
-
import attr
|
|
8
8
|
import tomli
|
|
9
9
|
import tomli_w
|
|
10
10
|
|
|
@@ -12,12 +12,12 @@ from ..types import PathLike
|
|
|
12
12
|
from .constants import DEFAULT_HOSTNAME, DEFAULT_HOSTS_PATH, HOSTS_FORMAT_VERSION
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
@
|
|
15
|
+
@dataclass
|
|
16
16
|
class HostData:
|
|
17
17
|
"""Stored data related to a host."""
|
|
18
18
|
|
|
19
|
-
hostname: str
|
|
20
|
-
hosts_file: PathLike
|
|
19
|
+
hostname: str
|
|
20
|
+
hosts_file: PathLike
|
|
21
21
|
|
|
22
22
|
def load(self) -> Dict[str, Any]:
|
|
23
23
|
return load(self.hosts_file).get(self.hostname, {})
|
schemathesis/service/metadata.py
CHANGED
|
@@ -1,42 +1,41 @@
|
|
|
1
1
|
"""Useful info to collect from CLI usage."""
|
|
2
2
|
import platform
|
|
3
|
-
|
|
4
|
-
import attr
|
|
3
|
+
from dataclasses import dataclass, field
|
|
5
4
|
|
|
6
5
|
from ..constants import __version__
|
|
7
6
|
|
|
8
7
|
|
|
9
|
-
@
|
|
8
|
+
@dataclass
|
|
10
9
|
class PlatformMetadata:
|
|
11
10
|
# System / OS name, e.g. "Linux" or "Windows".
|
|
12
|
-
system: str =
|
|
11
|
+
system: str = field(default_factory=platform.system)
|
|
13
12
|
# System release, e.g. "5.14" or "NT".
|
|
14
|
-
release: str =
|
|
13
|
+
release: str = field(default_factory=platform.release)
|
|
15
14
|
# Machine type, e.g. "i386".
|
|
16
|
-
machine: str =
|
|
15
|
+
machine: str = field(default_factory=platform.machine)
|
|
17
16
|
|
|
18
17
|
|
|
19
|
-
@
|
|
18
|
+
@dataclass
|
|
20
19
|
class InterpreterMetadata:
|
|
21
20
|
# The Python version as "major.minor.patch".
|
|
22
|
-
version: str =
|
|
21
|
+
version: str = field(default_factory=platform.python_version)
|
|
23
22
|
# Python implementation, e.g. "CPython" or "PyPy".
|
|
24
|
-
implementation: str =
|
|
23
|
+
implementation: str = field(default_factory=platform.python_implementation)
|
|
25
24
|
|
|
26
25
|
|
|
27
|
-
@
|
|
26
|
+
@dataclass
|
|
28
27
|
class CliMetadata:
|
|
29
28
|
# Schemathesis package version.
|
|
30
|
-
version: str =
|
|
29
|
+
version: str = __version__
|
|
31
30
|
|
|
32
31
|
|
|
33
|
-
@
|
|
32
|
+
@dataclass
|
|
34
33
|
class Metadata:
|
|
35
34
|
"""CLI environment metadata."""
|
|
36
35
|
|
|
37
36
|
# Information about the host platform.
|
|
38
|
-
platform: PlatformMetadata =
|
|
37
|
+
platform: PlatformMetadata = field(default_factory=PlatformMetadata)
|
|
39
38
|
# Python interpreter info.
|
|
40
|
-
interpreter: InterpreterMetadata =
|
|
39
|
+
interpreter: InterpreterMetadata = field(default_factory=InterpreterMetadata)
|
|
41
40
|
# CLI info itself.
|
|
42
|
-
cli: CliMetadata =
|
|
41
|
+
cli: CliMetadata = field(default_factory=CliMetadata)
|
schemathesis/service/models.py
CHANGED
|
@@ -1,26 +1,25 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
1
2
|
from typing import Optional
|
|
2
3
|
|
|
3
|
-
import attr
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
@attr.s(slots=True)
|
|
5
|
+
@dataclass
|
|
7
6
|
class ApiDetails:
|
|
8
|
-
location: str
|
|
9
|
-
base_url: Optional[str]
|
|
7
|
+
location: str
|
|
8
|
+
base_url: Optional[str]
|
|
10
9
|
|
|
11
10
|
|
|
12
|
-
@
|
|
11
|
+
@dataclass
|
|
13
12
|
class AuthResponse:
|
|
14
|
-
username: str
|
|
13
|
+
username: str
|
|
15
14
|
|
|
16
15
|
|
|
17
|
-
@
|
|
16
|
+
@dataclass
|
|
18
17
|
class UploadResponse:
|
|
19
|
-
message: str
|
|
20
|
-
next_url: str
|
|
21
|
-
correlation_id: str
|
|
18
|
+
message: str
|
|
19
|
+
next_url: str
|
|
20
|
+
correlation_id: str
|
|
22
21
|
|
|
23
22
|
|
|
24
|
-
@
|
|
23
|
+
@dataclass
|
|
25
24
|
class FailedUploadResponse:
|
|
26
|
-
detail: str
|
|
25
|
+
detail: str
|
schemathesis/service/report.py
CHANGED
|
@@ -5,11 +5,11 @@ import tarfile
|
|
|
5
5
|
import threading
|
|
6
6
|
import time
|
|
7
7
|
from contextlib import suppress
|
|
8
|
+
from dataclasses import asdict, dataclass, field
|
|
8
9
|
from io import BytesIO
|
|
9
10
|
from queue import Queue
|
|
10
11
|
from typing import Any, Dict, Optional
|
|
11
12
|
|
|
12
|
-
import attr
|
|
13
13
|
import click
|
|
14
14
|
|
|
15
15
|
from ..cli.context import ExecutionContext
|
|
@@ -23,15 +23,15 @@ from .models import UploadResponse
|
|
|
23
23
|
from .serialization import serialize_event
|
|
24
24
|
|
|
25
25
|
|
|
26
|
-
@
|
|
26
|
+
@dataclass
|
|
27
27
|
class ReportWriter:
|
|
28
28
|
"""Schemathesis.io test run report.
|
|
29
29
|
|
|
30
30
|
Simplifies adding new files to the archive.
|
|
31
31
|
"""
|
|
32
32
|
|
|
33
|
-
_tar: tarfile.TarFile
|
|
34
|
-
_events_count: int =
|
|
33
|
+
_tar: tarfile.TarFile
|
|
34
|
+
_events_count: int = 0
|
|
35
35
|
|
|
36
36
|
def add_json_file(self, name: str, data: Any) -> None:
|
|
37
37
|
buffer = BytesIO()
|
|
@@ -63,7 +63,7 @@ class ReportWriter:
|
|
|
63
63
|
# The time that the test run began
|
|
64
64
|
"started_at": started_at,
|
|
65
65
|
# Metadata about CLI environment
|
|
66
|
-
"environment":
|
|
66
|
+
"environment": asdict(metadata),
|
|
67
67
|
# Environment variables specific for CI providers
|
|
68
68
|
"ci": ci_environment.asdict() if ci_environment is not None else None,
|
|
69
69
|
# CLI usage statistic
|
|
@@ -80,7 +80,6 @@ class ReportWriter:
|
|
|
80
80
|
self.add_json_file(filename, serialize_event(event))
|
|
81
81
|
|
|
82
82
|
|
|
83
|
-
@attr.s(slots=True) # pragma: no mutate
|
|
84
83
|
class BaseReportHandler(EventHandler):
|
|
85
84
|
in_queue: Queue
|
|
86
85
|
worker: threading.Thread
|
|
@@ -96,20 +95,20 @@ class BaseReportHandler(EventHandler):
|
|
|
96
95
|
self.worker.join(WORKER_JOIN_TIMEOUT)
|
|
97
96
|
|
|
98
97
|
|
|
99
|
-
@
|
|
98
|
+
@dataclass
|
|
100
99
|
class ServiceReportHandler(BaseReportHandler):
|
|
101
|
-
client: ServiceClient
|
|
102
|
-
host_data: HostData
|
|
103
|
-
api_name: Optional[str]
|
|
104
|
-
location: str
|
|
105
|
-
base_url: Optional[str]
|
|
106
|
-
started_at: str
|
|
107
|
-
telemetry: bool
|
|
108
|
-
out_queue: Queue
|
|
109
|
-
in_queue: Queue =
|
|
110
|
-
worker: threading.Thread =
|
|
111
|
-
|
|
112
|
-
def
|
|
100
|
+
client: ServiceClient
|
|
101
|
+
host_data: HostData
|
|
102
|
+
api_name: Optional[str]
|
|
103
|
+
location: str
|
|
104
|
+
base_url: Optional[str]
|
|
105
|
+
started_at: str
|
|
106
|
+
telemetry: bool
|
|
107
|
+
out_queue: Queue
|
|
108
|
+
in_queue: Queue = field(default_factory=Queue)
|
|
109
|
+
worker: threading.Thread = field(init=False)
|
|
110
|
+
|
|
111
|
+
def __post_init__(self) -> None:
|
|
113
112
|
self.worker = threading.Thread(
|
|
114
113
|
target=write_remote,
|
|
115
114
|
kwargs={
|
|
@@ -191,19 +190,19 @@ def write_remote(
|
|
|
191
190
|
out_queue.put(events.Error(exc))
|
|
192
191
|
|
|
193
192
|
|
|
194
|
-
@
|
|
193
|
+
@dataclass
|
|
195
194
|
class FileReportHandler(BaseReportHandler):
|
|
196
|
-
file_handle: click.utils.LazyFile
|
|
197
|
-
api_name: Optional[str]
|
|
198
|
-
location: str
|
|
199
|
-
base_url: Optional[str]
|
|
200
|
-
started_at: str
|
|
201
|
-
telemetry: bool
|
|
202
|
-
out_queue: Queue
|
|
203
|
-
in_queue: Queue =
|
|
204
|
-
worker: threading.Thread =
|
|
205
|
-
|
|
206
|
-
def
|
|
195
|
+
file_handle: click.utils.LazyFile
|
|
196
|
+
api_name: Optional[str]
|
|
197
|
+
location: str
|
|
198
|
+
base_url: Optional[str]
|
|
199
|
+
started_at: str
|
|
200
|
+
telemetry: bool
|
|
201
|
+
out_queue: Queue
|
|
202
|
+
in_queue: Queue = field(default_factory=Queue)
|
|
203
|
+
worker: threading.Thread = field(init=False)
|
|
204
|
+
|
|
205
|
+
def __post_init__(self) -> None:
|
|
207
206
|
self.worker = threading.Thread(
|
|
208
207
|
target=write_file,
|
|
209
208
|
kwargs={
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
+
from dataclasses import asdict
|
|
1
2
|
from typing import Any, Callable, Dict, List, Optional, TypeVar, cast
|
|
2
3
|
|
|
3
|
-
import attr
|
|
4
|
-
|
|
5
4
|
from ..models import Response
|
|
6
5
|
from ..runner import events
|
|
7
6
|
from ..runner.serialization import SerializedCase
|
|
@@ -70,7 +69,7 @@ def serialize_after_execution(event: events.AfterExecution) -> Optional[Dict[str
|
|
|
70
69
|
"response": _serialize_response(check.response) if check.response is not None else None,
|
|
71
70
|
"example": _serialize_case(check.example),
|
|
72
71
|
"message": check.message,
|
|
73
|
-
"context":
|
|
72
|
+
"context": asdict(check.context) if check.context is not None else None,
|
|
74
73
|
"history": [
|
|
75
74
|
{"case": _serialize_case(entry.case), "response": _serialize_response(entry.response)}
|
|
76
75
|
for entry in check.history
|
|
@@ -138,7 +137,6 @@ def serialize_event(
|
|
|
138
137
|
extra: Optional[Dict[str, Any]] = None,
|
|
139
138
|
) -> Dict[str, Optional[Dict[str, Any]]]:
|
|
140
139
|
"""Turn an event into JSON-serializable structure."""
|
|
141
|
-
# Due to https://github.com/python-attrs/attrs/issues/864 it is easier to implement filtration manually
|
|
142
140
|
# Use the explicitly provided serializer for this event and fallback to default one if it is not provided
|
|
143
141
|
serializer = {
|
|
144
142
|
events.Initialized: on_initialized,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import enum
|
|
2
|
+
from dataclasses import dataclass
|
|
2
3
|
from enum import unique
|
|
3
4
|
from typing import Any, Callable, Dict, Generator, List, Optional, Sequence, Tuple, Type, TypeVar, Union, cast
|
|
4
5
|
from urllib.parse import urlsplit
|
|
5
6
|
|
|
6
|
-
import attr
|
|
7
7
|
import graphql
|
|
8
8
|
import requests
|
|
9
9
|
from hypothesis import strategies as st
|
|
@@ -31,7 +31,7 @@ class RootType(enum.Enum):
|
|
|
31
31
|
MUTATION = enum.auto()
|
|
32
32
|
|
|
33
33
|
|
|
34
|
-
@
|
|
34
|
+
@dataclass(repr=False)
|
|
35
35
|
class GraphQLCase(Case):
|
|
36
36
|
def as_requests_kwargs(
|
|
37
37
|
self, base_url: Optional[str] = None, headers: Optional[Dict[str, str]] = None
|
|
@@ -84,19 +84,19 @@ class GraphQLCase(Case):
|
|
|
84
84
|
C = TypeVar("C", bound=Case)
|
|
85
85
|
|
|
86
86
|
|
|
87
|
-
@
|
|
87
|
+
@dataclass
|
|
88
88
|
class GraphQLOperationDefinition(OperationDefinition):
|
|
89
|
-
field_name: str
|
|
90
|
-
type_: graphql.GraphQLType
|
|
91
|
-
root_type: RootType
|
|
89
|
+
field_name: str
|
|
90
|
+
type_: graphql.GraphQLType
|
|
91
|
+
root_type: RootType
|
|
92
92
|
|
|
93
93
|
|
|
94
|
-
@
|
|
94
|
+
@dataclass
|
|
95
95
|
class GraphQLSchema(BaseSchema):
|
|
96
96
|
def get_full_path(self, path: str) -> str:
|
|
97
97
|
return self.base_path
|
|
98
98
|
|
|
99
|
-
@property
|
|
99
|
+
@property
|
|
100
100
|
def verbose_name(self) -> str:
|
|
101
101
|
return "GraphQL"
|
|
102
102
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import
|
|
1
|
+
from dataclasses import dataclass
|
|
2
2
|
|
|
3
3
|
from ....models import Case
|
|
4
4
|
from ....utils import GenericResponse
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
@
|
|
7
|
+
@dataclass
|
|
8
8
|
class ExpressionContext:
|
|
9
9
|
"""Context in what an expression are evaluated."""
|
|
10
10
|
|
|
11
|
-
response: GenericResponse
|
|
12
|
-
case: Case
|
|
11
|
+
response: GenericResponse
|
|
12
|
+
case: Case
|
|
@@ -1,26 +1,25 @@
|
|
|
1
1
|
"""Lexical analysis of runtime expressions."""
|
|
2
|
+
from dataclasses import dataclass
|
|
2
3
|
from enum import Enum, unique
|
|
3
4
|
from typing import Callable, Generator
|
|
4
5
|
|
|
5
|
-
import attr
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
@unique # pragma: no mutate
|
|
7
|
+
@unique
|
|
9
8
|
class TokenType(Enum):
|
|
10
|
-
VARIABLE = 1
|
|
11
|
-
STRING = 2
|
|
12
|
-
POINTER = 3
|
|
13
|
-
DOT = 4
|
|
14
|
-
LBRACKET = 5
|
|
15
|
-
RBRACKET = 6
|
|
9
|
+
VARIABLE = 1
|
|
10
|
+
STRING = 2
|
|
11
|
+
POINTER = 3
|
|
12
|
+
DOT = 4
|
|
13
|
+
LBRACKET = 5
|
|
14
|
+
RBRACKET = 6
|
|
16
15
|
|
|
17
16
|
|
|
18
|
-
@
|
|
17
|
+
@dataclass
|
|
19
18
|
class Token:
|
|
20
19
|
"""Lexical token that may occur in a runtime expression."""
|
|
21
20
|
|
|
22
|
-
value: str
|
|
23
|
-
type_: TokenType
|
|
21
|
+
value: str
|
|
22
|
+
type_: TokenType
|
|
24
23
|
|
|
25
24
|
# Helpers for cleaner instantiation
|
|
26
25
|
|