rest-api-mocker 0.1.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.
- rest_api_mocker/__init__.py +17 -0
- rest_api_mocker/client.py +164 -0
- rest_api_mocker/exceptions.py +21 -0
- rest_api_mocker/models.py +66 -0
- rest_api_mocker-0.1.0.dist-info/METADATA +175 -0
- rest_api_mocker-0.1.0.dist-info/RECORD +8 -0
- rest_api_mocker-0.1.0.dist-info/WHEEL +4 -0
- rest_api_mocker-0.1.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""rest_api_mocker — a small Python wrapper for RestApiMocker."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from .client import RestApiMocker
|
|
6
|
+
from .exceptions import MockRequestError, RestApiMockerError
|
|
7
|
+
from .models import MockConfig, RequestRecord, ServerConfig
|
|
8
|
+
|
|
9
|
+
__all__ = [
|
|
10
|
+
"RestApiMocker",
|
|
11
|
+
"RestApiMockerError",
|
|
12
|
+
"MockRequestError",
|
|
13
|
+
"ServerConfig",
|
|
14
|
+
"RequestRecord",
|
|
15
|
+
"MockConfig",
|
|
16
|
+
]
|
|
17
|
+
__version__ = "0.1.0"
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
"""Client for talking to a RestApiMocker server."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
from typing import Any, Sequence
|
|
7
|
+
|
|
8
|
+
import requests
|
|
9
|
+
|
|
10
|
+
from .exceptions import MockRequestError
|
|
11
|
+
from .models import MockConfig, RequestRecord, ServerConfig
|
|
12
|
+
|
|
13
|
+
DEFAULT_TIMEOUT = 30.0
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class RestApiMocker:
|
|
17
|
+
"""A thin wrapper around the RestApiMocker HTTP control API.
|
|
18
|
+
|
|
19
|
+
All methods talk to the server's ``/internal`` control plane.
|
|
20
|
+
|
|
21
|
+
Example:
|
|
22
|
+
>>> mocker = RestApiMocker("http://localhost", 8080)
|
|
23
|
+
>>> mocker.add_mock(
|
|
24
|
+
... method="GET",
|
|
25
|
+
... path_pattern="/users/.*",
|
|
26
|
+
... status=200,
|
|
27
|
+
... body={"id": 1, "name": "Ada"},
|
|
28
|
+
... )
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
def __init__(
|
|
32
|
+
self,
|
|
33
|
+
url: str,
|
|
34
|
+
port: int,
|
|
35
|
+
*,
|
|
36
|
+
timeout: float = DEFAULT_TIMEOUT,
|
|
37
|
+
session: requests.Session | None = None,
|
|
38
|
+
) -> None:
|
|
39
|
+
"""Create a client.
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
url: Base URL of the mocker server, e.g. ``"http://localhost"``.
|
|
43
|
+
port: Port the mocker server's internal API listens on.
|
|
44
|
+
timeout: Per-request timeout in seconds.
|
|
45
|
+
session: Optional pre-configured :class:`requests.Session`. When
|
|
46
|
+
omitted, a new session is created and owned by this instance.
|
|
47
|
+
"""
|
|
48
|
+
self.url = url.rstrip("/")
|
|
49
|
+
self.port = port
|
|
50
|
+
self.timeout = timeout
|
|
51
|
+
self._session = session or requests.Session()
|
|
52
|
+
self._owns_session = session is None
|
|
53
|
+
|
|
54
|
+
@property
|
|
55
|
+
def base_url(self) -> str:
|
|
56
|
+
"""The fully-qualified base URL, including port."""
|
|
57
|
+
return f"{self.url}:{self.port}"
|
|
58
|
+
|
|
59
|
+
# -- low-level helpers ------------------------------------------------
|
|
60
|
+
|
|
61
|
+
def _request(self, method: str, path: str, **kwargs: Any) -> requests.Response:
|
|
62
|
+
"""Send a request to ``/internal`` and raise on a non-success status.
|
|
63
|
+
|
|
64
|
+
Raises:
|
|
65
|
+
MockRequestError: If the server returns a 4xx/5xx response.
|
|
66
|
+
"""
|
|
67
|
+
response = self._session.request(
|
|
68
|
+
method,
|
|
69
|
+
f"{self.base_url}/internal{path}",
|
|
70
|
+
timeout=self.timeout,
|
|
71
|
+
**kwargs,
|
|
72
|
+
)
|
|
73
|
+
if not response.ok:
|
|
74
|
+
raise MockRequestError(response.status_code, response.text)
|
|
75
|
+
return response
|
|
76
|
+
|
|
77
|
+
# -- mocks ------------------------------------------------------------
|
|
78
|
+
|
|
79
|
+
def add_mock(
|
|
80
|
+
self,
|
|
81
|
+
method: str,
|
|
82
|
+
path_pattern: str,
|
|
83
|
+
status: int,
|
|
84
|
+
body: Any,
|
|
85
|
+
conditions: Sequence[dict[str, Any]] | None = None,
|
|
86
|
+
) -> None:
|
|
87
|
+
"""Register a mock response on the server (``POST /internal/mock``).
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
method: HTTP method to match, e.g. ``"GET"``.
|
|
91
|
+
path_pattern: Path (or pattern) the mock should match.
|
|
92
|
+
status: HTTP status code the mock should return.
|
|
93
|
+
body: Response body. Serialized to a JSON string before sending.
|
|
94
|
+
conditions: Optional list of matching conditions.
|
|
95
|
+
|
|
96
|
+
Raises:
|
|
97
|
+
MockRequestError: If the server returns a non-success response.
|
|
98
|
+
"""
|
|
99
|
+
mock_definition = {
|
|
100
|
+
"method": method,
|
|
101
|
+
"path_pattern": path_pattern,
|
|
102
|
+
"status": status,
|
|
103
|
+
"body": json.dumps(body),
|
|
104
|
+
"conditions": list(conditions) if conditions is not None else [],
|
|
105
|
+
}
|
|
106
|
+
self._request("POST", "/mock", json=mock_definition)
|
|
107
|
+
|
|
108
|
+
def get_mocks(self) -> list[MockConfig]:
|
|
109
|
+
"""Return all configured mocks (``GET /internal/mocks``)."""
|
|
110
|
+
response = self._request("GET", "/mocks")
|
|
111
|
+
return [MockConfig.from_dict(item) for item in response.json()]
|
|
112
|
+
|
|
113
|
+
def delete_mock(self, index: int) -> None:
|
|
114
|
+
"""Delete a mock by its 0-based index (``DELETE /internal/mock/<index>``).
|
|
115
|
+
|
|
116
|
+
Raises:
|
|
117
|
+
MockRequestError: If the index is out of range (404) or the request
|
|
118
|
+
otherwise fails.
|
|
119
|
+
"""
|
|
120
|
+
self._request("DELETE", f"/mock/{index}")
|
|
121
|
+
|
|
122
|
+
def delete_all_mocks(self) -> None:
|
|
123
|
+
"""Delete every configured mock (``DELETE /internal/mocks``)."""
|
|
124
|
+
self._request("DELETE", "/mocks")
|
|
125
|
+
|
|
126
|
+
def delete_mocks_by_pattern(self, path_pattern: str) -> None:
|
|
127
|
+
"""Delete all mocks whose path pattern matches ``path_pattern``.
|
|
128
|
+
|
|
129
|
+
Maps to ``DELETE /internal/mocks/by-pattern?path_pattern=...``.
|
|
130
|
+
|
|
131
|
+
Raises:
|
|
132
|
+
MockRequestError: If no mock matches the pattern (404) or the
|
|
133
|
+
request otherwise fails.
|
|
134
|
+
"""
|
|
135
|
+
self._request(
|
|
136
|
+
"DELETE",
|
|
137
|
+
"/mocks/by-pattern",
|
|
138
|
+
params={"path_pattern": path_pattern},
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
# -- introspection ----------------------------------------------------
|
|
142
|
+
|
|
143
|
+
def get_config(self) -> ServerConfig:
|
|
144
|
+
"""Return the server's port configuration (``GET /internal/config``)."""
|
|
145
|
+
response = self._request("GET", "/config")
|
|
146
|
+
return ServerConfig.from_dict(response.json())
|
|
147
|
+
|
|
148
|
+
def get_history(self) -> list[RequestRecord]:
|
|
149
|
+
"""Return the recorded request history (``GET /internal/history``)."""
|
|
150
|
+
response = self._request("GET", "/history")
|
|
151
|
+
return [RequestRecord.from_dict(item) for item in response.json()]
|
|
152
|
+
|
|
153
|
+
# -- lifecycle --------------------------------------------------------
|
|
154
|
+
|
|
155
|
+
def close(self) -> None:
|
|
156
|
+
"""Close the underlying session, if this instance owns it."""
|
|
157
|
+
if self._owns_session:
|
|
158
|
+
self._session.close()
|
|
159
|
+
|
|
160
|
+
def __enter__(self) -> RestApiMocker:
|
|
161
|
+
return self
|
|
162
|
+
|
|
163
|
+
def __exit__(self, *exc_info: object) -> None:
|
|
164
|
+
self.close()
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""Exceptions raised by :mod:`rest_api_mocker`."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class RestApiMockerError(Exception):
|
|
7
|
+
"""Base class for all errors raised by this library."""
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class MockRequestError(RestApiMockerError):
|
|
11
|
+
"""Raised when the mocker server returns a non-success response.
|
|
12
|
+
|
|
13
|
+
Attributes:
|
|
14
|
+
status_code: HTTP status code returned by the server.
|
|
15
|
+
response_text: Raw response body returned by the server.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
def __init__(self, status_code: int, response_text: str) -> None:
|
|
19
|
+
self.status_code = status_code
|
|
20
|
+
self.response_text = response_text
|
|
21
|
+
super().__init__(f"Mocker server returned {status_code}: {response_text}")
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"""Dataclasses mirroring the RestApiMocker server's JSON types."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass, field
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@dataclass
|
|
10
|
+
class ServerConfig:
|
|
11
|
+
"""Server configuration, as returned by ``GET /internal/config``."""
|
|
12
|
+
|
|
13
|
+
public_port: int
|
|
14
|
+
private_port: int
|
|
15
|
+
|
|
16
|
+
@classmethod
|
|
17
|
+
def from_dict(cls, data: dict[str, Any]) -> ServerConfig:
|
|
18
|
+
return cls(
|
|
19
|
+
public_port=data["public_port"],
|
|
20
|
+
private_port=data["private_port"],
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@dataclass
|
|
25
|
+
class RequestRecord:
|
|
26
|
+
"""A single request recorded by the public server.
|
|
27
|
+
|
|
28
|
+
Returned by ``GET /internal/history``.
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
method: str
|
|
32
|
+
path: str
|
|
33
|
+
timestamp: int
|
|
34
|
+
|
|
35
|
+
@classmethod
|
|
36
|
+
def from_dict(cls, data: dict[str, Any]) -> RequestRecord:
|
|
37
|
+
return cls(
|
|
38
|
+
method=data["method"],
|
|
39
|
+
path=data["path"],
|
|
40
|
+
timestamp=data["timestamp"],
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@dataclass
|
|
45
|
+
class MockConfig:
|
|
46
|
+
"""A configured mock response.
|
|
47
|
+
|
|
48
|
+
Returned by ``GET /internal/mocks``. Note that ``body`` is the JSON string
|
|
49
|
+
the server stores, not a decoded object.
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
method: str
|
|
53
|
+
path_pattern: str
|
|
54
|
+
status: int
|
|
55
|
+
body: str
|
|
56
|
+
conditions: list[Any] = field(default_factory=list)
|
|
57
|
+
|
|
58
|
+
@classmethod
|
|
59
|
+
def from_dict(cls, data: dict[str, Any]) -> MockConfig:
|
|
60
|
+
return cls(
|
|
61
|
+
method=data["method"],
|
|
62
|
+
path_pattern=data["path_pattern"],
|
|
63
|
+
status=data["status"],
|
|
64
|
+
body=data.get("body", ""),
|
|
65
|
+
conditions=list(data.get("conditions") or []),
|
|
66
|
+
)
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: rest-api-mocker
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A small Python wrapper for RestApiMocker.
|
|
5
|
+
Project-URL: Homepage, https://github.com/julienlopez/RestApiMockerPythonAPI
|
|
6
|
+
Project-URL: Repository, https://github.com/julienlopez/RestApiMockerPythonAPI
|
|
7
|
+
Author-email: Julien Lopez <julien.lopez51@gmail.com>
|
|
8
|
+
License: MIT License
|
|
9
|
+
|
|
10
|
+
Copyright (c) 2026 julien lopez
|
|
11
|
+
|
|
12
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
13
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
14
|
+
in the Software without restriction, including without limitation the rights
|
|
15
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
16
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
17
|
+
furnished to do so, subject to the following conditions:
|
|
18
|
+
|
|
19
|
+
The above copyright notice and this permission notice shall be included in all
|
|
20
|
+
copies or substantial portions of the Software.
|
|
21
|
+
|
|
22
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
23
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
24
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
25
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
26
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
27
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
28
|
+
SOFTWARE.
|
|
29
|
+
License-File: LICENSE
|
|
30
|
+
Keywords: api,http,mock,rest,testing
|
|
31
|
+
Classifier: Development Status :: 3 - Alpha
|
|
32
|
+
Classifier: Intended Audience :: Developers
|
|
33
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
34
|
+
Classifier: Programming Language :: Python :: 3
|
|
35
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
36
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
37
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
38
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
39
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
40
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
41
|
+
Classifier: Topic :: Software Development :: Testing :: Mocking
|
|
42
|
+
Requires-Python: >=3.8
|
|
43
|
+
Requires-Dist: requests>=2.20
|
|
44
|
+
Provides-Extra: dev
|
|
45
|
+
Requires-Dist: mypy>=1.8; extra == 'dev'
|
|
46
|
+
Requires-Dist: pytest>=7; extra == 'dev'
|
|
47
|
+
Requires-Dist: responses>=0.23; extra == 'dev'
|
|
48
|
+
Requires-Dist: ruff>=0.4; extra == 'dev'
|
|
49
|
+
Requires-Dist: types-requests; extra == 'dev'
|
|
50
|
+
Provides-Extra: test
|
|
51
|
+
Requires-Dist: pytest>=7; extra == 'test'
|
|
52
|
+
Requires-Dist: responses>=0.23; extra == 'test'
|
|
53
|
+
Description-Content-Type: text/markdown
|
|
54
|
+
|
|
55
|
+
# rest-api-mocker
|
|
56
|
+
|
|
57
|
+
A small Python wrapper for [RestApiMocker](https://github.com/julienlopez/RestApiMockerPythonAPI).
|
|
58
|
+
|
|
59
|
+
## Installation
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
pip install rest-api-mocker
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Until it's published, install from a checkout:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
pip install -e ".[test]"
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Usage
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
from rest_api_mocker import RestApiMocker
|
|
75
|
+
|
|
76
|
+
mocker = RestApiMocker("http://localhost", 8080)
|
|
77
|
+
mocker.add_mock(
|
|
78
|
+
method="GET",
|
|
79
|
+
path_pattern="/users/.*",
|
|
80
|
+
status=200,
|
|
81
|
+
body={"id": 1, "name": "Ada"},
|
|
82
|
+
)
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
`RestApiMocker` can also be used as a context manager so the underlying HTTP
|
|
86
|
+
session is closed for you:
|
|
87
|
+
|
|
88
|
+
```python
|
|
89
|
+
with RestApiMocker("http://localhost", 8080) as mocker:
|
|
90
|
+
mocker.add_mock("GET", "/health", 200, {"ok": True})
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### API
|
|
94
|
+
|
|
95
|
+
The client mirrors the server's `/internal` control plane:
|
|
96
|
+
|
|
97
|
+
| Method | Description |
|
|
98
|
+
| --- | --- |
|
|
99
|
+
| `add_mock(method, path_pattern, status, body, conditions=None)` | Register a mock response. |
|
|
100
|
+
| `get_mocks() -> list[MockConfig]` | List all configured mocks. |
|
|
101
|
+
| `delete_mock(index)` | Delete a mock by its 0-based index. |
|
|
102
|
+
| `delete_all_mocks()` | Delete every configured mock. |
|
|
103
|
+
| `delete_mocks_by_pattern(path_pattern)` | Delete all mocks matching a path pattern. |
|
|
104
|
+
| `get_config() -> ServerConfig` | Get the server's public/private ports. |
|
|
105
|
+
| `get_history() -> list[RequestRecord]` | Get the recorded request history. |
|
|
106
|
+
|
|
107
|
+
```python
|
|
108
|
+
mocker.add_mock("GET", "/users/.*", 200, {"id": 1})
|
|
109
|
+
|
|
110
|
+
config = mocker.get_config() # ServerConfig(public_port=9090, private_port=80)
|
|
111
|
+
mocks = mocker.get_mocks() # [MockConfig(...)]
|
|
112
|
+
history = mocker.get_history() # [RequestRecord(method=..., path=..., timestamp=...)]
|
|
113
|
+
|
|
114
|
+
mocker.delete_mocks_by_pattern("/users/.*")
|
|
115
|
+
mocker.delete_all_mocks()
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
The `MockConfig`, `ServerConfig` and `RequestRecord` dataclasses are importable
|
|
119
|
+
from the top-level package.
|
|
120
|
+
|
|
121
|
+
### Errors
|
|
122
|
+
|
|
123
|
+
A non-success response from the mocker server raises `MockRequestError`
|
|
124
|
+
(a subclass of `RestApiMockerError`):
|
|
125
|
+
|
|
126
|
+
```python
|
|
127
|
+
from rest_api_mocker import MockRequestError
|
|
128
|
+
|
|
129
|
+
try:
|
|
130
|
+
mocker.add_mock("GET", "/x", 200, {})
|
|
131
|
+
except MockRequestError as exc:
|
|
132
|
+
print(exc.status_code, exc.response_text)
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Development
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
pip install -e ".[dev]"
|
|
139
|
+
pytest # tests
|
|
140
|
+
ruff check . # lint
|
|
141
|
+
ruff format . # format
|
|
142
|
+
mypy src # type-check
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
CI (`.github/workflows/ci.yml`) runs the tests on Python 3.8–3.13 plus lint,
|
|
146
|
+
format, and type checks on every push and pull request.
|
|
147
|
+
|
|
148
|
+
## Releasing to PyPI
|
|
149
|
+
|
|
150
|
+
Publishing is automated by `.github/workflows/publish.yml`, which runs when you
|
|
151
|
+
publish a GitHub Release. It uses PyPI **Trusted Publishing** (OIDC), so there
|
|
152
|
+
are no API tokens or secrets to store.
|
|
153
|
+
|
|
154
|
+
One-time setup:
|
|
155
|
+
|
|
156
|
+
1. Create an account at <https://pypi.org/account/register/>.
|
|
157
|
+
2. On PyPI, go to your account → *Publishing* → *Add a pending publisher* and
|
|
158
|
+
register this repository as a trusted publisher:
|
|
159
|
+
- PyPI Project Name: `rest-api-mocker`
|
|
160
|
+
- Owner / Repository: your GitHub `owner` / `RestApiMockerPythonAPI`
|
|
161
|
+
- Workflow name: `publish.yml`
|
|
162
|
+
- Environment name: `pypi`
|
|
163
|
+
3. (Recommended) In the GitHub repo settings, create an Environment named
|
|
164
|
+
`pypi` to gate releases.
|
|
165
|
+
|
|
166
|
+
To cut a release:
|
|
167
|
+
|
|
168
|
+
1. Bump `version` in `pyproject.toml` (and `__version__` in
|
|
169
|
+
`src/rest_api_mocker/__init__.py`).
|
|
170
|
+
2. Tag and push, then publish a GitHub Release for that tag. The workflow
|
|
171
|
+
builds the package and uploads it to PyPI.
|
|
172
|
+
|
|
173
|
+
> Tip: to rehearse without affecting the real index, register the same trusted
|
|
174
|
+
> publisher on <https://test.pypi.org> and point the publish step at it with
|
|
175
|
+
> `with: { repository-url: https://test.pypi.org/legacy/ }`.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
rest_api_mocker/__init__.py,sha256=uAOZvUicJ3PId1pyKKQtnoagP5jsCCkZNDg6MWO3FmE,427
|
|
2
|
+
rest_api_mocker/client.py,sha256=bc5kiee20kZ2VjLisUKAKKm4DjFr_kC6xTOL9X7-4us,5543
|
|
3
|
+
rest_api_mocker/exceptions.py,sha256=Vz6dhaoSF5MVkr3vvphltoS9TPGMS6YSz4GGlBMa3zo,689
|
|
4
|
+
rest_api_mocker/models.py,sha256=P744NvqI51TedClje_aC-MXl9NX6cobZmJa1GDJBiOA,1576
|
|
5
|
+
rest_api_mocker-0.1.0.dist-info/METADATA,sha256=2moHoMzs9QidxNiSg94DfXzGgooNz3Q3tFXKvRYna8Y,6248
|
|
6
|
+
rest_api_mocker-0.1.0.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
|
|
7
|
+
rest_api_mocker-0.1.0.dist-info/licenses/LICENSE,sha256=eTbYou-toxlnYebu1uvLqlKtNK_RgQ-qNtYdgX9OFjs,1069
|
|
8
|
+
rest_api_mocker-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 julien lopez
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|