cruds 1.0.2__tar.gz
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.
- cruds-1.0.2/LICENSE +21 -0
- cruds-1.0.2/PKG-INFO +113 -0
- cruds-1.0.2/README.md +72 -0
- cruds-1.0.2/cruds/__init__.py +26 -0
- cruds-1.0.2/cruds/core.py +316 -0
- cruds-1.0.2/cruds.egg-info/PKG-INFO +113 -0
- cruds-1.0.2/cruds.egg-info/SOURCES.txt +13 -0
- cruds-1.0.2/cruds.egg-info/dependency_links.txt +1 -0
- cruds-1.0.2/cruds.egg-info/requires.txt +7 -0
- cruds-1.0.2/cruds.egg-info/top_level.txt +2 -0
- cruds-1.0.2/setup.cfg +74 -0
- cruds-1.0.2/setup.py +4 -0
- cruds-1.0.2/tests/__init__.py +0 -0
- cruds-1.0.2/tests/test_core.py +233 -0
cruds-1.0.2/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2020 johnbrandborg
|
|
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.
|
cruds-1.0.2/PKG-INFO
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: cruds
|
|
3
|
+
Version: 1.0.2
|
|
4
|
+
Summary: CRUDs is a simple high level library for Humans, inspired by Python Requests
|
|
5
|
+
Home-page: https://github.com/johnbrandborg/cruds
|
|
6
|
+
Author: John Brandborg
|
|
7
|
+
Author-email: john.brandborg+pypi@pm.me
|
|
8
|
+
License: MIT
|
|
9
|
+
Project-URL: Source, https://github.com/johnbrandborg/cruds
|
|
10
|
+
Project-URL: Tracker, https://github.com/johnbrandborg/cruds/issues
|
|
11
|
+
Keywords: rest api crud http https
|
|
12
|
+
Platform: unix
|
|
13
|
+
Platform: linux
|
|
14
|
+
Platform: osx
|
|
15
|
+
Platform: cygwin
|
|
16
|
+
Platform: win32
|
|
17
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
18
|
+
Classifier: Intended Audience :: Developers
|
|
19
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
20
|
+
Classifier: Operating System :: MacOS :: MacOS X
|
|
21
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
22
|
+
Classifier: Operating System :: POSIX
|
|
23
|
+
Classifier: Programming Language :: Python :: 3
|
|
24
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
25
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
26
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
27
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
28
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
29
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
30
|
+
Classifier: Topic :: Software Development :: Testing
|
|
31
|
+
Classifier: Topic :: Utilities
|
|
32
|
+
Requires-Python: >=3.8
|
|
33
|
+
Description-Content-Type: text/markdown
|
|
34
|
+
License-File: LICENSE
|
|
35
|
+
Requires-Dist: certifi
|
|
36
|
+
Requires-Dist: urllib3
|
|
37
|
+
Provides-Extra: develop
|
|
38
|
+
Requires-Dist: flake8; extra == "develop"
|
|
39
|
+
Requires-Dist: pytest; extra == "develop"
|
|
40
|
+
Requires-Dist: pytest-cov; extra == "develop"
|
|
41
|
+
|
|
42
|
+
# CRUDs
|
|
43
|
+
[](https://github.com/johnbrandborg/cruds/actions?query=workflow%3A%22Python+application%22)
|
|
44
|
+
[](https://pypi.org/project/cruds/)
|
|
45
|
+
[](https://sonarcloud.io/summary/new_code?id=johnbrandborg_cruds)
|
|
46
|
+
|
|
47
|
+
CRUDs is a simple high level library for Humans, inspired by [Python Requests](https://requests.readthedocs.io/en/latest/)
|
|
48
|
+
|
|
49
|
+
```python
|
|
50
|
+
>>> import cruds
|
|
51
|
+
>>> catfact_ninja = cruds.Client(host="https://catfact.ninja/")
|
|
52
|
+
>>> data = catfact_ninja.read("fact")
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Interact with RESTful API using Create, Read, Update and Delete requests.
|
|
56
|
+
Focus on using Python data types instead of worrying about serialization.
|
|
57
|
+
Authentication, timeouts, retries, and rate limit back-off are all built in
|
|
58
|
+
and can be adjusted.
|
|
59
|
+
|
|
60
|
+
### Installation
|
|
61
|
+
|
|
62
|
+
You can install the client using PIP like so.
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
pip install cruds
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Logging
|
|
69
|
+
|
|
70
|
+
If you want to see logging set the level using the standard logging interface.
|
|
71
|
+
DEBUG will show you URLLib3, but INFO will give you general information from
|
|
72
|
+
the cruds.
|
|
73
|
+
|
|
74
|
+
``` python
|
|
75
|
+
>>> import logging
|
|
76
|
+
>>> import cruds
|
|
77
|
+
>>> logging.basicConfig(level=logging.INFO)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Extensibility
|
|
81
|
+
|
|
82
|
+
The library has been created with extensibility in mind. You can Sub Class Client
|
|
83
|
+
for example and add the logic requirements needed to make the requests.
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
from cruds import Client
|
|
87
|
+
|
|
88
|
+
class CatFactNinja(Client):
|
|
89
|
+
"""Cat Fact Ninja Interface"""
|
|
90
|
+
|
|
91
|
+
_fact_uri = "fact"
|
|
92
|
+
|
|
93
|
+
def __init__(self, **kwargs):
|
|
94
|
+
host = "http://catfact.ninja/"
|
|
95
|
+
super().__init__(host=host, **kwargs)
|
|
96
|
+
|
|
97
|
+
@property
|
|
98
|
+
def fact(self):
|
|
99
|
+
""" Get a Fact about Cats"""
|
|
100
|
+
return self.read(self._fact_uri)
|
|
101
|
+
|
|
102
|
+
cat = CatFactNinja()
|
|
103
|
+
print(cat.fact)
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Todo List
|
|
107
|
+
- [ ] OAuth Client for Authentication
|
|
108
|
+
|
|
109
|
+
## License
|
|
110
|
+
cruds is released under the MIT License. See the bundled LICENSE file for details.
|
|
111
|
+
|
|
112
|
+
## Credits
|
|
113
|
+
* [URLLib3 Team](https://github.com/urllib3)
|
cruds-1.0.2/README.md
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# CRUDs
|
|
2
|
+
[](https://github.com/johnbrandborg/cruds/actions?query=workflow%3A%22Python+application%22)
|
|
3
|
+
[](https://pypi.org/project/cruds/)
|
|
4
|
+
[](https://sonarcloud.io/summary/new_code?id=johnbrandborg_cruds)
|
|
5
|
+
|
|
6
|
+
CRUDs is a simple high level library for Humans, inspired by [Python Requests](https://requests.readthedocs.io/en/latest/)
|
|
7
|
+
|
|
8
|
+
```python
|
|
9
|
+
>>> import cruds
|
|
10
|
+
>>> catfact_ninja = cruds.Client(host="https://catfact.ninja/")
|
|
11
|
+
>>> data = catfact_ninja.read("fact")
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Interact with RESTful API using Create, Read, Update and Delete requests.
|
|
15
|
+
Focus on using Python data types instead of worrying about serialization.
|
|
16
|
+
Authentication, timeouts, retries, and rate limit back-off are all built in
|
|
17
|
+
and can be adjusted.
|
|
18
|
+
|
|
19
|
+
### Installation
|
|
20
|
+
|
|
21
|
+
You can install the client using PIP like so.
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
pip install cruds
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### Logging
|
|
28
|
+
|
|
29
|
+
If you want to see logging set the level using the standard logging interface.
|
|
30
|
+
DEBUG will show you URLLib3, but INFO will give you general information from
|
|
31
|
+
the cruds.
|
|
32
|
+
|
|
33
|
+
``` python
|
|
34
|
+
>>> import logging
|
|
35
|
+
>>> import cruds
|
|
36
|
+
>>> logging.basicConfig(level=logging.INFO)
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Extensibility
|
|
40
|
+
|
|
41
|
+
The library has been created with extensibility in mind. You can Sub Class Client
|
|
42
|
+
for example and add the logic requirements needed to make the requests.
|
|
43
|
+
|
|
44
|
+
```python
|
|
45
|
+
from cruds import Client
|
|
46
|
+
|
|
47
|
+
class CatFactNinja(Client):
|
|
48
|
+
"""Cat Fact Ninja Interface"""
|
|
49
|
+
|
|
50
|
+
_fact_uri = "fact"
|
|
51
|
+
|
|
52
|
+
def __init__(self, **kwargs):
|
|
53
|
+
host = "http://catfact.ninja/"
|
|
54
|
+
super().__init__(host=host, **kwargs)
|
|
55
|
+
|
|
56
|
+
@property
|
|
57
|
+
def fact(self):
|
|
58
|
+
""" Get a Fact about Cats"""
|
|
59
|
+
return self.read(self._fact_uri)
|
|
60
|
+
|
|
61
|
+
cat = CatFactNinja()
|
|
62
|
+
print(cat.fact)
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Todo List
|
|
66
|
+
- [ ] OAuth Client for Authentication
|
|
67
|
+
|
|
68
|
+
## License
|
|
69
|
+
cruds is released under the MIT License. See the bundled LICENSE file for details.
|
|
70
|
+
|
|
71
|
+
## Credits
|
|
72
|
+
* [URLLib3 Team](https://github.com/urllib3)
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# MIT License
|
|
2
|
+
#
|
|
3
|
+
# Copyright (c) 2020 johnbrandborg
|
|
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
|
|
13
|
+
# all 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.
|
|
22
|
+
"""
|
|
23
|
+
RESTful is a simple API library for Humans, inspired by Python Requests
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
from .core import Client
|
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Clients that can be used for easily accessing RESTful APIs
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
import sys
|
|
7
|
+
from typing import Any, Dict, List, Union
|
|
8
|
+
from urllib.parse import urlencode
|
|
9
|
+
|
|
10
|
+
import certifi
|
|
11
|
+
import urllib3
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
DEFAULT_TIMEOUT = 20.0
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class Client:
|
|
19
|
+
"""
|
|
20
|
+
Represents an platform interface that supports CRUD operations as methods.
|
|
21
|
+
|
|
22
|
+
Data supplied as Dictionaries are automatically serialised and deserialized
|
|
23
|
+
as JSON. All parameters are key-word values, and positional arguments are
|
|
24
|
+
not accepted.
|
|
25
|
+
|
|
26
|
+
Attributes
|
|
27
|
+
----------
|
|
28
|
+
status_whitelist : list
|
|
29
|
+
A list of status codes to ignore by instances with raise for status
|
|
30
|
+
enabled.
|
|
31
|
+
|
|
32
|
+
Methods
|
|
33
|
+
-------
|
|
34
|
+
create:
|
|
35
|
+
Makes a POST request to the API Server
|
|
36
|
+
read:
|
|
37
|
+
Makes a GET request to the API Server
|
|
38
|
+
update:
|
|
39
|
+
Makes a PATCH or PUT request to the API Server
|
|
40
|
+
delete:
|
|
41
|
+
Makes a DELETE request to the API Server
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
status_whitelist: List[int] = []
|
|
45
|
+
|
|
46
|
+
def __init__(self,
|
|
47
|
+
*,
|
|
48
|
+
host: str,
|
|
49
|
+
auth=None,
|
|
50
|
+
manager=None,
|
|
51
|
+
timeout=DEFAULT_TIMEOUT,
|
|
52
|
+
raise_status=True,
|
|
53
|
+
retries=4,
|
|
54
|
+
backoff_factor=0.9,
|
|
55
|
+
retry_status_codes=(504, 503, 502, 500, 429),
|
|
56
|
+
serialize=True,
|
|
57
|
+
verify_ssl=True,
|
|
58
|
+
) -> None:
|
|
59
|
+
"""
|
|
60
|
+
Constructs all the necessary attributes for the API object.
|
|
61
|
+
|
|
62
|
+
Parameters
|
|
63
|
+
----------
|
|
64
|
+
host: str
|
|
65
|
+
The host name of the API server connections will be made too.
|
|
66
|
+
auth: str or tuple, optional
|
|
67
|
+
A bearer token can be supplied, or a tuple with the username
|
|
68
|
+
and password.
|
|
69
|
+
manager: URLLib3 PoolManager, optional
|
|
70
|
+
You can supply a PoolManager with custom configuration.
|
|
71
|
+
timeout : float, optional
|
|
72
|
+
How long to wait before the connection is considered to be
|
|
73
|
+
taking to long and cancelled.
|
|
74
|
+
raise_status : bool, optional
|
|
75
|
+
If a status code of 400-599 is returned in a response will an
|
|
76
|
+
exception is raised.
|
|
77
|
+
retries : int, optional
|
|
78
|
+
How many times to retry connecting to the host.
|
|
79
|
+
backoff_factor : float, optional
|
|
80
|
+
How much delay should be added with each retry.
|
|
81
|
+
retry_status_codes : typle[int], optional
|
|
82
|
+
Status codes that will trigger retries.
|
|
83
|
+
(default is (504, 503, 502, 429))
|
|
84
|
+
serialize : boolaen, optional
|
|
85
|
+
Serialize and Deserialize dictionaires for data sent and received.
|
|
86
|
+
(default is True)
|
|
87
|
+
verify_ssl : boolean, optional
|
|
88
|
+
Verify the SSL certificate with Certificate Authorities.
|
|
89
|
+
(default is True)
|
|
90
|
+
"""
|
|
91
|
+
self.host: str = host if host.endswith("/") else host + "/"
|
|
92
|
+
self.serialize = serialize
|
|
93
|
+
logger.info("API Operation Timeout(sec): %s, Raises Exceptions on status: %s",
|
|
94
|
+
timeout,
|
|
95
|
+
raise_status)
|
|
96
|
+
|
|
97
|
+
self.raise_status: bool = raise_status
|
|
98
|
+
self.timeout: float = timeout
|
|
99
|
+
|
|
100
|
+
if isinstance(manager, urllib3.PoolManager):
|
|
101
|
+
logger.info("Using supplied HTTP Manager")
|
|
102
|
+
self._http = manager
|
|
103
|
+
else:
|
|
104
|
+
if retries:
|
|
105
|
+
logger.info("Retries: %s attempts (backoff factor %s) for status codes %s",
|
|
106
|
+
retries,
|
|
107
|
+
backoff_factor,
|
|
108
|
+
', '.join([str(i) for i in retry_status_codes]))
|
|
109
|
+
|
|
110
|
+
retry = urllib3.Retry(connect=retries,
|
|
111
|
+
backoff_factor=backoff_factor,
|
|
112
|
+
status_forcelist=retry_status_codes)
|
|
113
|
+
else:
|
|
114
|
+
logger.info("Retries: Disabled")
|
|
115
|
+
retry = False
|
|
116
|
+
|
|
117
|
+
self._http = urllib3.PoolManager(
|
|
118
|
+
cert_reqs="CERT_REQUIRED" if verify_ssl else "CERT_NONE",
|
|
119
|
+
ca_certs=certifi.where(),
|
|
120
|
+
retries=retry)
|
|
121
|
+
|
|
122
|
+
if isinstance(auth, str):
|
|
123
|
+
self._http.headers["Authorization"] = f"Bearer {auth}"
|
|
124
|
+
logger.info("Token authentication setup")
|
|
125
|
+
elif isinstance(auth, (list, tuple)) and len(auth) == 2:
|
|
126
|
+
self._http.headers = urllib3.make_headers(basic_auth=":".join(auth))
|
|
127
|
+
logger.info("Basic authentication setup")
|
|
128
|
+
else:
|
|
129
|
+
logger.info("No authentication setup")
|
|
130
|
+
|
|
131
|
+
self._http.headers["Content-Type"] = "application/json; charset=utf-8"
|
|
132
|
+
|
|
133
|
+
def create(self,
|
|
134
|
+
uri: str,
|
|
135
|
+
data: dict,
|
|
136
|
+
params: Union[Dict[Any, Any], None] = None,
|
|
137
|
+
) -> Union[Dict[Any, Any], bytes]:
|
|
138
|
+
"""
|
|
139
|
+
Makes a basic Create request to the API, and returns the response.
|
|
140
|
+
|
|
141
|
+
The HTTP method used is POST, and the data can be either a dictionary
|
|
142
|
+
that is serialised to JSON or bytes and strings that will be sent
|
|
143
|
+
without serialisation.
|
|
144
|
+
|
|
145
|
+
For POST requests parameters are encoded into the URL.
|
|
146
|
+
https://urllib3.readthedocs.io/en/stable/user-guide.html#query-parameters
|
|
147
|
+
|
|
148
|
+
Parameters
|
|
149
|
+
----------
|
|
150
|
+
uri : str
|
|
151
|
+
The URI to be used to with the connection to the API
|
|
152
|
+
data : dict or bytes or string
|
|
153
|
+
Payload to be sent to the API
|
|
154
|
+
params : dict, optional
|
|
155
|
+
Parameters to be added to the URI
|
|
156
|
+
|
|
157
|
+
Returns
|
|
158
|
+
-------
|
|
159
|
+
dict if the response is JSON, otherwise bytes
|
|
160
|
+
"""
|
|
161
|
+
url = self.host + uri
|
|
162
|
+
safe_params = f"?{urlencode(params)}" if params else ""
|
|
163
|
+
method = "POST"
|
|
164
|
+
logger.info(f"API Create Operation to {url}")
|
|
165
|
+
|
|
166
|
+
if self.serialize and isinstance(data, dict):
|
|
167
|
+
response = self._http.request(method,
|
|
168
|
+
url + safe_params,
|
|
169
|
+
json=data,
|
|
170
|
+
timeout=self.timeout)
|
|
171
|
+
else:
|
|
172
|
+
response = self._http.request(method,
|
|
173
|
+
url + safe_params,
|
|
174
|
+
body=data,
|
|
175
|
+
timeout=self.timeout)
|
|
176
|
+
|
|
177
|
+
return self._process_resp(method, response)
|
|
178
|
+
|
|
179
|
+
def read(self,
|
|
180
|
+
uri: str,
|
|
181
|
+
params: Union[Dict[Any, Any], None] = None,
|
|
182
|
+
) -> Union[Dict[Any, Any], bytes]:
|
|
183
|
+
"""
|
|
184
|
+
Makes a basic Retrieve request to the API, and returns the response
|
|
185
|
+
|
|
186
|
+
The HTTP method used is GET.
|
|
187
|
+
|
|
188
|
+
Parameters
|
|
189
|
+
----------
|
|
190
|
+
uri : str
|
|
191
|
+
The URI to be used to with the connection to the API
|
|
192
|
+
params : dict, optional
|
|
193
|
+
Parameters to be added to the URI
|
|
194
|
+
|
|
195
|
+
Returns
|
|
196
|
+
-------
|
|
197
|
+
dict if the response is JSON, otherwise bytes
|
|
198
|
+
"""
|
|
199
|
+
url = self.host + uri
|
|
200
|
+
method = "GET"
|
|
201
|
+
logger.info(f"API Retrieve Operation to {url}")
|
|
202
|
+
|
|
203
|
+
response = self._http.request(method,
|
|
204
|
+
url,
|
|
205
|
+
fields=params,
|
|
206
|
+
timeout=self.timeout)
|
|
207
|
+
return self._process_resp(method, response)
|
|
208
|
+
|
|
209
|
+
def update(self,
|
|
210
|
+
uri: str,
|
|
211
|
+
data: Union[Dict[Any, Any], str],
|
|
212
|
+
params: Union[Dict[Any, Any], None] = None,
|
|
213
|
+
replace: bool = False,
|
|
214
|
+
) -> Union[Dict[Any, Any], bytes]:
|
|
215
|
+
"""
|
|
216
|
+
Makes a basic Update request to the API, and returns the response.
|
|
217
|
+
|
|
218
|
+
The HTTP method used is PATCH (or PUT with replace enabled), and the data
|
|
219
|
+
can be either a dictionary that is serialised to JSON or bytes and
|
|
220
|
+
strings that will be sent without serialisation.
|
|
221
|
+
|
|
222
|
+
For PUT requests parameters are encoded into the URL.
|
|
223
|
+
https://urllib3.readthedocs.io/en/stable/user-guide.html#query-parameters
|
|
224
|
+
|
|
225
|
+
Parameters
|
|
226
|
+
----------
|
|
227
|
+
uri : str
|
|
228
|
+
The URI to be used to with the connection to the API
|
|
229
|
+
data : dict or bytes or string
|
|
230
|
+
Payload to be sent to the API
|
|
231
|
+
params : dict, optional
|
|
232
|
+
Parameters to be added to the URI
|
|
233
|
+
replace : bool, optional
|
|
234
|
+
Requests a full replacement of the entire entity. Uses PUT Method.
|
|
235
|
+
|
|
236
|
+
Returns
|
|
237
|
+
-------
|
|
238
|
+
dict if the response is JSON, otherwise bytes
|
|
239
|
+
"""
|
|
240
|
+
url = self.host + uri
|
|
241
|
+
safe_params = f"?{urlencode(params)}" if params else ""
|
|
242
|
+
method = "PUT" if replace else "PATCH"
|
|
243
|
+
logger.info(f"API Update Operation to {url}")
|
|
244
|
+
|
|
245
|
+
if self.serialize and isinstance(data, dict):
|
|
246
|
+
response = self._http.request(method,
|
|
247
|
+
url + safe_params,
|
|
248
|
+
json=data,
|
|
249
|
+
timeout=self.timeout)
|
|
250
|
+
else:
|
|
251
|
+
response = self._http.request(method,
|
|
252
|
+
url + safe_params,
|
|
253
|
+
body=data,
|
|
254
|
+
timeout=self.timeout)
|
|
255
|
+
|
|
256
|
+
return self._process_resp(method, response)
|
|
257
|
+
|
|
258
|
+
def delete(self,
|
|
259
|
+
uri: str,
|
|
260
|
+
params: Union[Dict[Any, Any], None] = None
|
|
261
|
+
) -> Union[Dict[Any, Any], bytes]:
|
|
262
|
+
"""
|
|
263
|
+
Makes a basic Delete request to the API, and returns the response
|
|
264
|
+
|
|
265
|
+
Parameters
|
|
266
|
+
----------
|
|
267
|
+
uri : str
|
|
268
|
+
The URI to be used to with the connection to the API
|
|
269
|
+
params : dict, optional
|
|
270
|
+
Parameters to be added to the URI
|
|
271
|
+
|
|
272
|
+
Returns
|
|
273
|
+
-------
|
|
274
|
+
dict if the response is JSON, otherwise bytes
|
|
275
|
+
"""
|
|
276
|
+
url = self.host + uri
|
|
277
|
+
method = "DELETE"
|
|
278
|
+
logger.info(f"API Delete Operation to {url}")
|
|
279
|
+
|
|
280
|
+
response = self._http.request(method,
|
|
281
|
+
self.host + uri,
|
|
282
|
+
fields=params,
|
|
283
|
+
timeout=self.timeout)
|
|
284
|
+
return self._process_resp(method, response)
|
|
285
|
+
|
|
286
|
+
def _process_resp(
|
|
287
|
+
self,
|
|
288
|
+
method: str,
|
|
289
|
+
response: urllib3.response.BaseHTTPResponse,
|
|
290
|
+
) -> Union[Dict[Any, Any], bytes]:
|
|
291
|
+
"""
|
|
292
|
+
Processes the Responce from HTTP Requests in a standardize manner, and
|
|
293
|
+
displays information.
|
|
294
|
+
"""
|
|
295
|
+
logger.info(
|
|
296
|
+
f"Method: {method}, Status Code: {response.status}, "
|
|
297
|
+
f"Data: {sys.getsizeof(response.data)} Bytes"
|
|
298
|
+
)
|
|
299
|
+
|
|
300
|
+
if self.raise_status and response.status not in self.status_whitelist:
|
|
301
|
+
if 400 <= response.status < 500:
|
|
302
|
+
error_type = "Client"
|
|
303
|
+
elif 500 <= response.status < 600:
|
|
304
|
+
error_type = "Server"
|
|
305
|
+
else:
|
|
306
|
+
error_type = None
|
|
307
|
+
|
|
308
|
+
if error_type:
|
|
309
|
+
msg = f"{error_type} Error with status code {response.status}" \
|
|
310
|
+
f" Message: {response.data.decode('utf-8')}"
|
|
311
|
+
raise urllib3.exceptions.HTTPError(msg)
|
|
312
|
+
|
|
313
|
+
if self.serialize and 'application/json' in response.headers.get('Content-Type', ''):
|
|
314
|
+
return response.json()
|
|
315
|
+
|
|
316
|
+
return response.data
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: cruds
|
|
3
|
+
Version: 1.0.2
|
|
4
|
+
Summary: CRUDs is a simple high level library for Humans, inspired by Python Requests
|
|
5
|
+
Home-page: https://github.com/johnbrandborg/cruds
|
|
6
|
+
Author: John Brandborg
|
|
7
|
+
Author-email: john.brandborg+pypi@pm.me
|
|
8
|
+
License: MIT
|
|
9
|
+
Project-URL: Source, https://github.com/johnbrandborg/cruds
|
|
10
|
+
Project-URL: Tracker, https://github.com/johnbrandborg/cruds/issues
|
|
11
|
+
Keywords: rest api crud http https
|
|
12
|
+
Platform: unix
|
|
13
|
+
Platform: linux
|
|
14
|
+
Platform: osx
|
|
15
|
+
Platform: cygwin
|
|
16
|
+
Platform: win32
|
|
17
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
18
|
+
Classifier: Intended Audience :: Developers
|
|
19
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
20
|
+
Classifier: Operating System :: MacOS :: MacOS X
|
|
21
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
22
|
+
Classifier: Operating System :: POSIX
|
|
23
|
+
Classifier: Programming Language :: Python :: 3
|
|
24
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
25
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
26
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
27
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
28
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
29
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
30
|
+
Classifier: Topic :: Software Development :: Testing
|
|
31
|
+
Classifier: Topic :: Utilities
|
|
32
|
+
Requires-Python: >=3.8
|
|
33
|
+
Description-Content-Type: text/markdown
|
|
34
|
+
License-File: LICENSE
|
|
35
|
+
Requires-Dist: certifi
|
|
36
|
+
Requires-Dist: urllib3
|
|
37
|
+
Provides-Extra: develop
|
|
38
|
+
Requires-Dist: flake8; extra == "develop"
|
|
39
|
+
Requires-Dist: pytest; extra == "develop"
|
|
40
|
+
Requires-Dist: pytest-cov; extra == "develop"
|
|
41
|
+
|
|
42
|
+
# CRUDs
|
|
43
|
+
[](https://github.com/johnbrandborg/cruds/actions?query=workflow%3A%22Python+application%22)
|
|
44
|
+
[](https://pypi.org/project/cruds/)
|
|
45
|
+
[](https://sonarcloud.io/summary/new_code?id=johnbrandborg_cruds)
|
|
46
|
+
|
|
47
|
+
CRUDs is a simple high level library for Humans, inspired by [Python Requests](https://requests.readthedocs.io/en/latest/)
|
|
48
|
+
|
|
49
|
+
```python
|
|
50
|
+
>>> import cruds
|
|
51
|
+
>>> catfact_ninja = cruds.Client(host="https://catfact.ninja/")
|
|
52
|
+
>>> data = catfact_ninja.read("fact")
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Interact with RESTful API using Create, Read, Update and Delete requests.
|
|
56
|
+
Focus on using Python data types instead of worrying about serialization.
|
|
57
|
+
Authentication, timeouts, retries, and rate limit back-off are all built in
|
|
58
|
+
and can be adjusted.
|
|
59
|
+
|
|
60
|
+
### Installation
|
|
61
|
+
|
|
62
|
+
You can install the client using PIP like so.
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
pip install cruds
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Logging
|
|
69
|
+
|
|
70
|
+
If you want to see logging set the level using the standard logging interface.
|
|
71
|
+
DEBUG will show you URLLib3, but INFO will give you general information from
|
|
72
|
+
the cruds.
|
|
73
|
+
|
|
74
|
+
``` python
|
|
75
|
+
>>> import logging
|
|
76
|
+
>>> import cruds
|
|
77
|
+
>>> logging.basicConfig(level=logging.INFO)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Extensibility
|
|
81
|
+
|
|
82
|
+
The library has been created with extensibility in mind. You can Sub Class Client
|
|
83
|
+
for example and add the logic requirements needed to make the requests.
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
from cruds import Client
|
|
87
|
+
|
|
88
|
+
class CatFactNinja(Client):
|
|
89
|
+
"""Cat Fact Ninja Interface"""
|
|
90
|
+
|
|
91
|
+
_fact_uri = "fact"
|
|
92
|
+
|
|
93
|
+
def __init__(self, **kwargs):
|
|
94
|
+
host = "http://catfact.ninja/"
|
|
95
|
+
super().__init__(host=host, **kwargs)
|
|
96
|
+
|
|
97
|
+
@property
|
|
98
|
+
def fact(self):
|
|
99
|
+
""" Get a Fact about Cats"""
|
|
100
|
+
return self.read(self._fact_uri)
|
|
101
|
+
|
|
102
|
+
cat = CatFactNinja()
|
|
103
|
+
print(cat.fact)
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Todo List
|
|
107
|
+
- [ ] OAuth Client for Authentication
|
|
108
|
+
|
|
109
|
+
## License
|
|
110
|
+
cruds is released under the MIT License. See the bundled LICENSE file for details.
|
|
111
|
+
|
|
112
|
+
## Credits
|
|
113
|
+
* [URLLib3 Team](https://github.com/urllib3)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
setup.cfg
|
|
4
|
+
setup.py
|
|
5
|
+
cruds/__init__.py
|
|
6
|
+
cruds/core.py
|
|
7
|
+
cruds.egg-info/PKG-INFO
|
|
8
|
+
cruds.egg-info/SOURCES.txt
|
|
9
|
+
cruds.egg-info/dependency_links.txt
|
|
10
|
+
cruds.egg-info/requires.txt
|
|
11
|
+
cruds.egg-info/top_level.txt
|
|
12
|
+
tests/__init__.py
|
|
13
|
+
tests/test_core.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
cruds-1.0.2/setup.cfg
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
[metadata]
|
|
2
|
+
name = cruds
|
|
3
|
+
version = 1.0.2
|
|
4
|
+
description = CRUDs is a simple high level library for Humans, inspired by Python Requests
|
|
5
|
+
long_description = file: README.md
|
|
6
|
+
long_description_content_type = text/markdown
|
|
7
|
+
url = https://github.com/johnbrandborg/cruds
|
|
8
|
+
author = John Brandborg
|
|
9
|
+
author_email = john.brandborg+pypi@pm.me
|
|
10
|
+
license = MIT
|
|
11
|
+
license_file = LICENSE
|
|
12
|
+
platforms = unix, linux, osx, cygwin, win32
|
|
13
|
+
classifiers =
|
|
14
|
+
Development Status :: 5 - Production/Stable
|
|
15
|
+
Intended Audience :: Developers
|
|
16
|
+
License :: OSI Approved :: MIT License
|
|
17
|
+
Operating System :: MacOS :: MacOS X
|
|
18
|
+
Operating System :: Microsoft :: Windows
|
|
19
|
+
Operating System :: POSIX
|
|
20
|
+
Programming Language :: Python :: 3
|
|
21
|
+
Programming Language :: Python :: 3 :: Only
|
|
22
|
+
Programming Language :: Python :: 3.8
|
|
23
|
+
Programming Language :: Python :: 3.9
|
|
24
|
+
Programming Language :: Python :: 3.10
|
|
25
|
+
Programming Language :: Python :: 3.11
|
|
26
|
+
Topic :: Software Development :: Libraries
|
|
27
|
+
Topic :: Software Development :: Testing
|
|
28
|
+
Topic :: Utilities
|
|
29
|
+
keywords = rest api crud http https
|
|
30
|
+
project_urls =
|
|
31
|
+
Source=https://github.com/johnbrandborg/cruds
|
|
32
|
+
Tracker=https://github.com/johnbrandborg/cruds/issues
|
|
33
|
+
|
|
34
|
+
[options]
|
|
35
|
+
packages = find:
|
|
36
|
+
install_requires =
|
|
37
|
+
certifi
|
|
38
|
+
urllib3
|
|
39
|
+
python_requires = >=3.8
|
|
40
|
+
|
|
41
|
+
[options.extras_require]
|
|
42
|
+
develop =
|
|
43
|
+
flake8
|
|
44
|
+
pytest
|
|
45
|
+
pytest-cov
|
|
46
|
+
|
|
47
|
+
[tool:pytest]
|
|
48
|
+
addopts = --cov=. tests/
|
|
49
|
+
|
|
50
|
+
[coverage:run]
|
|
51
|
+
relative_files = True
|
|
52
|
+
omit =
|
|
53
|
+
env/*
|
|
54
|
+
.env/*
|
|
55
|
+
venv/*
|
|
56
|
+
tests/*
|
|
57
|
+
setup.py
|
|
58
|
+
|
|
59
|
+
[coverage:xml]
|
|
60
|
+
output = coverage.xml
|
|
61
|
+
|
|
62
|
+
[coverage:report]
|
|
63
|
+
show_missing = true
|
|
64
|
+
exclude_lines =
|
|
65
|
+
^if __name__ ==
|
|
66
|
+
^\s*except KeyboardInterrupt
|
|
67
|
+
|
|
68
|
+
[flake8]
|
|
69
|
+
per-file-ignores = __init__.py:F401
|
|
70
|
+
|
|
71
|
+
[egg_info]
|
|
72
|
+
tag_build =
|
|
73
|
+
tag_date = 0
|
|
74
|
+
|
cruds-1.0.2/setup.py
ADDED
|
File without changes
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Pytests for Platforms in RESTful Platform2
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from unittest import mock
|
|
6
|
+
import pytest
|
|
7
|
+
import urllib3
|
|
8
|
+
|
|
9
|
+
import cruds
|
|
10
|
+
from cruds.core import DEFAULT_TIMEOUT
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def test_Platform_token_authentication():
|
|
14
|
+
"""
|
|
15
|
+
Supplying an 'auth' string will placed into the header for bearer token
|
|
16
|
+
authenticationi.
|
|
17
|
+
"""
|
|
18
|
+
api = cruds.Client(host="https://localhost", auth="api_token")
|
|
19
|
+
assert api._http.headers.get("Authorization") == "Bearer api_token"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def test_Platform_basic_authentication():
|
|
23
|
+
"""
|
|
24
|
+
Supplying an 'auth' tuple or list will placed into the header for basic
|
|
25
|
+
authentication.
|
|
26
|
+
"""
|
|
27
|
+
api = cruds.Client(host="https://localhost", auth=("username", "password"))
|
|
28
|
+
assert api._http.headers.get("authorization") == "Basic dXNlcm5hbWU6cGFzc3dvcmQ="
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def test_Platform_creates_urllib3_manager():
|
|
32
|
+
"""
|
|
33
|
+
When no URLLib3 manager is suppied, a manager is automatically created.
|
|
34
|
+
"""
|
|
35
|
+
api = cruds.Client(host="https://localhost")
|
|
36
|
+
assert isinstance(api._http, urllib3.PoolManager)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def test_Platform_use_supplied_urllib3_manager():
|
|
40
|
+
"""
|
|
41
|
+
When a URLLib3 manager is suppied use it, instead of creating one.
|
|
42
|
+
"""
|
|
43
|
+
api = cruds.Client(host="https://localhost", manager=urllib3.PoolManager())
|
|
44
|
+
assert isinstance(api._http, urllib3.PoolManager)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def test_Platform_disable_retries():
|
|
48
|
+
""" Setting the retries to 0 or None will disable retries being used """
|
|
49
|
+
api = cruds.Client(host="https://localhost", retries=0)
|
|
50
|
+
assert api._http.connection_pool_kw.get("retries") == 0
|
|
51
|
+
|
|
52
|
+
cruds.Client(host="https://localhost", retries=None)
|
|
53
|
+
assert api._http.connection_pool_kw.get("retries") == 0
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@pytest.fixture
|
|
57
|
+
def crud_api():
|
|
58
|
+
"""
|
|
59
|
+
Creates a Platform Platform without response processing.
|
|
60
|
+
"""
|
|
61
|
+
api = cruds.Client(host="https://localhost", retries=0)
|
|
62
|
+
mock_resp = urllib3.HTTPResponse(body=b'{"name": "test"}')
|
|
63
|
+
api._http.request = mock.Mock(return_value=mock_resp)
|
|
64
|
+
api._process_resp = lambda method, resp: resp
|
|
65
|
+
return api
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def test_Platform_create_operation(crud_api):
|
|
69
|
+
""" Check the Create Operation formats the request properly """
|
|
70
|
+
sample = {"test_name": "test_Platform_create_operation"}
|
|
71
|
+
resp = crud_api.create("user/1", data=sample)
|
|
72
|
+
|
|
73
|
+
crud_api._http.request.assert_called_with("POST",
|
|
74
|
+
"https://localhost/user/1",
|
|
75
|
+
json=sample,
|
|
76
|
+
timeout=DEFAULT_TIMEOUT)
|
|
77
|
+
assert resp.data == b'{"name": "test"}'
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def test_Platform_create_operation_with_bytes(crud_api):
|
|
81
|
+
"""
|
|
82
|
+
Check the Create Operation formats the request properly.
|
|
83
|
+
"""
|
|
84
|
+
sample = b'{"test_name": "test_Platform_create_operation"}'
|
|
85
|
+
resp = crud_api.create("user/2", data=sample)
|
|
86
|
+
|
|
87
|
+
crud_api._http.request.assert_called_with("POST",
|
|
88
|
+
"https://localhost/user/2",
|
|
89
|
+
body=sample,
|
|
90
|
+
timeout=DEFAULT_TIMEOUT)
|
|
91
|
+
assert resp.data == b'{"name": "test"}'
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def test_Platform_read_operation(crud_api):
|
|
95
|
+
"""
|
|
96
|
+
Check the Read Operation formats the request properly.
|
|
97
|
+
"""
|
|
98
|
+
resp = crud_api.read("test")
|
|
99
|
+
|
|
100
|
+
crud_api._http.request.assert_called_with("GET",
|
|
101
|
+
"https://localhost/test",
|
|
102
|
+
fields=None,
|
|
103
|
+
timeout=DEFAULT_TIMEOUT)
|
|
104
|
+
assert resp.data == b'{"name": "test"}'
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def test_Platform_update_operation(crud_api):
|
|
108
|
+
"""
|
|
109
|
+
Check the Update Operation formats the request properly.
|
|
110
|
+
"""
|
|
111
|
+
sample = {"test_name": "test_Platform_update_operation"}
|
|
112
|
+
resp = crud_api.update("test", data=sample)
|
|
113
|
+
|
|
114
|
+
crud_api._http.request.assert_called_with("PATCH",
|
|
115
|
+
"https://localhost/test",
|
|
116
|
+
json=sample,
|
|
117
|
+
timeout=DEFAULT_TIMEOUT)
|
|
118
|
+
assert resp.data == b'{"name": "test"}'
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def test_Platform_update_operation_with_bytes(crud_api):
|
|
122
|
+
"""
|
|
123
|
+
Check the Update Operation formats the request properly.
|
|
124
|
+
"""
|
|
125
|
+
sample = b'{"test_name": "test_Platform_update_operation"}'
|
|
126
|
+
resp = crud_api.update("test", data=sample)
|
|
127
|
+
|
|
128
|
+
crud_api._http.request.assert_called_with("PATCH",
|
|
129
|
+
"https://localhost/test",
|
|
130
|
+
body=sample,
|
|
131
|
+
timeout=DEFAULT_TIMEOUT)
|
|
132
|
+
assert resp.data == b'{"name": "test"}'
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def test_Platform_update_operation_with_replace(crud_api):
|
|
136
|
+
"""
|
|
137
|
+
Check the Update Operation formats the request properly.
|
|
138
|
+
"""
|
|
139
|
+
sample = {"test_name": "test_Platform_update_operation"}
|
|
140
|
+
resp = crud_api.update("test", data=sample, replace=True)
|
|
141
|
+
|
|
142
|
+
crud_api._http.request.assert_called_with("PUT",
|
|
143
|
+
"https://localhost/test",
|
|
144
|
+
json=sample,
|
|
145
|
+
timeout=DEFAULT_TIMEOUT)
|
|
146
|
+
assert resp.data == b'{"name": "test"}'
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def test_Platform_delete_operation(crud_api):
|
|
150
|
+
"""
|
|
151
|
+
Check the Delete Operation formats the request properly.
|
|
152
|
+
"""
|
|
153
|
+
resp = crud_api.delete("test")
|
|
154
|
+
|
|
155
|
+
crud_api._http.request.assert_called_with("DELETE",
|
|
156
|
+
"https://localhost/test",
|
|
157
|
+
fields=None,
|
|
158
|
+
timeout=DEFAULT_TIMEOUT)
|
|
159
|
+
assert resp.data == b'{"name": "test"}'
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def test_Platform_process_resp_return_bytes():
|
|
163
|
+
"""
|
|
164
|
+
Check the response processing returns bytes for non-JSON content.
|
|
165
|
+
"""
|
|
166
|
+
api = cruds.Client(host="https://localhost")
|
|
167
|
+
mock_resp = urllib3.HTTPResponse(body=b"name=test_Platform_process_resp_return_bytes", status=399)
|
|
168
|
+
assert api._process_resp("", mock_resp) == b"name=test_Platform_process_resp_return_bytes"
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def test_Platform_process_resp_return_bytes_with_serialize_false():
|
|
172
|
+
"""
|
|
173
|
+
Check the response processing returns bytes for JSON content when serialize
|
|
174
|
+
is disabled.
|
|
175
|
+
"""
|
|
176
|
+
api = cruds.Client(host="https://localhost", serialize=False)
|
|
177
|
+
mock_resp = urllib3.HTTPResponse(
|
|
178
|
+
body=b'{"name": "test_Platform_process_resp_return_bytes_with_serialize_false"}',
|
|
179
|
+
headers={"Content-Type": "application/json; charset=utf-8"})
|
|
180
|
+
assert api._process_resp("", mock_resp) == b'{"name": "test_Platform_process_resp_return_bytes_with_serialize_false"}'
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
def test_Platform_process_resp_return_dictionary():
|
|
184
|
+
"""
|
|
185
|
+
Check the response processing returns a dictionary for JSON content.
|
|
186
|
+
"""
|
|
187
|
+
api = cruds.Client(host="https://localhost")
|
|
188
|
+
mock_resp = urllib3.HTTPResponse(
|
|
189
|
+
body=b'{"name": "test_Platform_process_resp_return_dictionary"}',
|
|
190
|
+
headers={"Content-Type": "application/json; charset=utf-8"},
|
|
191
|
+
status=399)
|
|
192
|
+
assert api._process_resp("", mock_resp) == {"name": "test_Platform_process_resp_return_dictionary"}
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
def test_Platform_raise_status_399():
|
|
196
|
+
"""
|
|
197
|
+
Check the response return code of 399 doesn't raise an exceptions.
|
|
198
|
+
"""
|
|
199
|
+
api = cruds.Client(host="https://localhost")
|
|
200
|
+
mock_resp = urllib3.HTTPResponse(body=b'{"name": "test"}', status=399)
|
|
201
|
+
api._process_resp("", mock_resp)
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def test_Platform_raise_status_400():
|
|
205
|
+
"""
|
|
206
|
+
Check the response status code 400 raises an exception.
|
|
207
|
+
"""
|
|
208
|
+
api = cruds.Client(host="https://localhost")
|
|
209
|
+
mock_resp = urllib3.HTTPResponse(body=b'{"name": "test"}', status=400)
|
|
210
|
+
with pytest.raises(urllib3.exceptions.HTTPError):
|
|
211
|
+
api._process_resp("", mock_resp)
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
def test_Platform_raise_status_500():
|
|
215
|
+
"""
|
|
216
|
+
Check the response status code 500 raises an exception.
|
|
217
|
+
"""
|
|
218
|
+
api = cruds.Client(host="https://localhost")
|
|
219
|
+
api = cruds.Client(host="https://localhost")
|
|
220
|
+
mock_resp = urllib3.HTTPResponse(body=b'{"name": "test"}', status=500)
|
|
221
|
+
with pytest.raises(urllib3.exceptions.HTTPError):
|
|
222
|
+
api._process_resp("", mock_resp)
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
def test_Platform_raise_status_whitelist():
|
|
226
|
+
"""
|
|
227
|
+
Check the response status code 400 doesn't raises an exception when whitelisted.
|
|
228
|
+
"""
|
|
229
|
+
api = cruds.Client(host="https://localhost")
|
|
230
|
+
api = cruds.Client(host="https://localhost", retries=0)
|
|
231
|
+
api.status_whitelist.append(400)
|
|
232
|
+
mock_resp = urllib3.HTTPResponse(body=b'{"name": "test"}', status=400)
|
|
233
|
+
api._process_resp("", mock_resp)
|