pytolino 1.5__tar.gz → 1.7__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.
- {pytolino-1.5/src/pytolino.egg-info → pytolino-1.7}/PKG-INFO +3 -2
- {pytolino-1.5 → pytolino-1.7}/pyproject.toml +1 -1
- {pytolino-1.5 → pytolino-1.7}/src/pytolino/tolino_cloud.py +51 -18
- {pytolino-1.5 → pytolino-1.7/src/pytolino.egg-info}/PKG-INFO +3 -2
- {pytolino-1.5 → pytolino-1.7}/tests/test_tolino_cloud.py +12 -9
- {pytolino-1.5 → pytolino-1.7}/LICENSE +0 -0
- {pytolino-1.5 → pytolino-1.7}/MANIFEST.in +0 -0
- {pytolino-1.5 → pytolino-1.7}/README.rst +0 -0
- {pytolino-1.5 → pytolino-1.7}/setup.cfg +0 -0
- {pytolino-1.5 → pytolino-1.7}/src/pytolino/__init__.py +0 -0
- {pytolino-1.5 → pytolino-1.7}/src/pytolino/servers_settings.ini +0 -0
- {pytolino-1.5 → pytolino-1.7}/src/pytolino.egg-info/SOURCES.txt +0 -0
- {pytolino-1.5 → pytolino-1.7}/src/pytolino.egg-info/dependency_links.txt +0 -0
- {pytolino-1.5 → pytolino-1.7}/src/pytolino.egg-info/requires.txt +0 -0
- {pytolino-1.5 → pytolino-1.7}/src/pytolino.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: pytolino
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.7
|
|
4
4
|
Summary: client for tolino cloud
|
|
5
5
|
Author: Imam Usmani
|
|
6
6
|
Project-URL: Source Code, https://github.com/ImamAzim/pytolino
|
|
@@ -23,6 +23,7 @@ Requires-Dist: sphinx; extra == "dev"
|
|
|
23
23
|
Requires-Dist: build; extra == "dev"
|
|
24
24
|
Requires-Dist: twine; extra == "dev"
|
|
25
25
|
Requires-Dist: sphinx-rtd-theme; extra == "dev"
|
|
26
|
+
Dynamic: license-file
|
|
26
27
|
|
|
27
28
|
pytolino
|
|
28
29
|
===================
|
|
@@ -6,11 +6,13 @@ import configparser
|
|
|
6
6
|
import platform
|
|
7
7
|
import logging
|
|
8
8
|
from urllib.parse import urlparse, parse_qs
|
|
9
|
+
from urllib3.util import Retry
|
|
9
10
|
import json
|
|
10
11
|
import time
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
import requests
|
|
15
|
+
from requests.adapters import HTTPAdapter
|
|
14
16
|
import mechanize
|
|
15
17
|
|
|
16
18
|
|
|
@@ -27,6 +29,8 @@ servers_settings = configparser.ConfigParser()
|
|
|
27
29
|
servers_settings.read(SERVERS_SETTINGS_FILE_PATH)
|
|
28
30
|
|
|
29
31
|
PARTNERS = servers_settings.sections()
|
|
32
|
+
TOTAL_RETRY = 5
|
|
33
|
+
STATUS_FORCELIST = [404]
|
|
30
34
|
|
|
31
35
|
|
|
32
36
|
def main():
|
|
@@ -38,23 +42,41 @@ class Client(object):
|
|
|
38
42
|
|
|
39
43
|
"""create a client to communicate with a tolino partner (login, etc..)"""
|
|
40
44
|
|
|
41
|
-
def _log_requests(self, host_response):
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
45
|
+
def _log_requests(self, host_response, error: True or None=None):
|
|
46
|
+
if host_response.status_code >= 400 or error is True:
|
|
47
|
+
logger = logging.error
|
|
48
|
+
else:
|
|
49
|
+
logger = logging.debug
|
|
50
|
+
logger('log request')
|
|
51
|
+
logger('---------------- HTTP response (requests)----------')
|
|
52
|
+
logger(f'status code: {host_response.status_code}')
|
|
53
|
+
logger(f'cookies: {host_response.cookies}')
|
|
54
|
+
logger(f'headers: {host_response.headers}')
|
|
46
55
|
try:
|
|
47
56
|
j = host_response.json()
|
|
48
|
-
|
|
57
|
+
logger(f'json: {j}')
|
|
49
58
|
except requests.JSONDecodeError:
|
|
50
|
-
|
|
51
|
-
|
|
59
|
+
logger(f'text: {host_response.text}')
|
|
60
|
+
logger('-------------------------------------------------------')
|
|
61
|
+
|
|
62
|
+
try:
|
|
63
|
+
host_response.raise_for_status()
|
|
64
|
+
except requests.exceptions.HTTPError as e:
|
|
65
|
+
raise PytolinoException
|
|
66
|
+
except requests.exceptions.RequestException as e:
|
|
67
|
+
raise PytolinoException
|
|
52
68
|
|
|
53
69
|
def _log_mechanize(self, host_response):
|
|
54
|
-
logging.
|
|
55
|
-
logging.
|
|
56
|
-
logging.
|
|
57
|
-
logging.
|
|
70
|
+
logging.debug('-------------- HTTP response (mechanize)--------------')
|
|
71
|
+
logging.debug(f'status code: {host_response.code}')
|
|
72
|
+
logging.debug(f'headers: {host_response.info()}')
|
|
73
|
+
logging.debug('-------------------------------------------------------')
|
|
74
|
+
if host_response.code >= 400:
|
|
75
|
+
logging.error('-------------- HTTP response (mechanize)----------')
|
|
76
|
+
logging.error(f'status code: {host_response.code}')
|
|
77
|
+
logging.error(f'headers: {host_response.info()}')
|
|
78
|
+
logging.error('--------------------------------------------------')
|
|
79
|
+
raise PytolinoException('http error')
|
|
58
80
|
|
|
59
81
|
def _hardware_id():
|
|
60
82
|
|
|
@@ -124,7 +146,15 @@ class Client(object):
|
|
|
124
146
|
self.token_expires = None
|
|
125
147
|
|
|
126
148
|
self.server_settings = servers_settings[server_name]
|
|
127
|
-
self.session = requests.
|
|
149
|
+
self.session = requests.Session()
|
|
150
|
+
retry_strategy = Retry(
|
|
151
|
+
total=TOTAL_RETRY,
|
|
152
|
+
status_forcelist=STATUS_FORCELIST,
|
|
153
|
+
backoff_factor=2,
|
|
154
|
+
allowed_methods=frozenset(['GET', 'POST']))
|
|
155
|
+
adapter = HTTPAdapter(max_retries=retry_strategy)
|
|
156
|
+
self.session.mount('http://', adapter)
|
|
157
|
+
self.session.mount('https://', adapter)
|
|
128
158
|
self.browser = mechanize.Browser()
|
|
129
159
|
self.browser.set_handle_robots(False)
|
|
130
160
|
self.server_name = server_name
|
|
@@ -147,7 +177,7 @@ class Client(object):
|
|
|
147
177
|
for cookie in self.browser.cookiejar:
|
|
148
178
|
self.session.cookies.set(cookie.name, cookie.value)
|
|
149
179
|
|
|
150
|
-
logging.
|
|
180
|
+
logging.debug(self.server_settings['login_cookie'])
|
|
151
181
|
self._log_mechanize(host_response)
|
|
152
182
|
if not self.server_settings['login_cookie'] in self.session.cookies:
|
|
153
183
|
raise PytolinoException(f'login to {self.server_name} failed.')
|
|
@@ -179,7 +209,8 @@ class Client(object):
|
|
|
179
209
|
host_response.headers['Location']
|
|
180
210
|
).query)
|
|
181
211
|
auth_code = params['code'][0]
|
|
182
|
-
except
|
|
212
|
+
except KeyError:
|
|
213
|
+
self._log_requests(host_response, error=True)
|
|
183
214
|
raise PytolinoException('oauth code request failed.')
|
|
184
215
|
|
|
185
216
|
# Fetch OAUTH access token
|
|
@@ -196,6 +227,7 @@ class Client(object):
|
|
|
196
227
|
allow_redirects=False,
|
|
197
228
|
)
|
|
198
229
|
self._log_requests(host_response)
|
|
230
|
+
|
|
199
231
|
try:
|
|
200
232
|
j = host_response.json()
|
|
201
233
|
self.access_token = j['access_token']
|
|
@@ -497,7 +529,8 @@ class Client(object):
|
|
|
497
529
|
|
|
498
530
|
:book_id: id of the book on the serveer
|
|
499
531
|
:filepath: path to the cover file
|
|
500
|
-
:file_ext: png, jpg or jpeg. only necessary if the
|
|
532
|
+
:file_ext: png, jpg or jpeg. only necessary if the
|
|
533
|
+
filepath has no extension
|
|
501
534
|
|
|
502
535
|
"""
|
|
503
536
|
|
|
@@ -512,8 +545,8 @@ class Client(object):
|
|
|
512
545
|
|
|
513
546
|
host_response = self.session.post(
|
|
514
547
|
self.server_settings['cover_url'],
|
|
515
|
-
files
|
|
516
|
-
data
|
|
548
|
+
files=[('file', ('1092560016', open(filepath, 'rb'), mime))],
|
|
549
|
+
data={'deliverableId': book_id},
|
|
517
550
|
headers={
|
|
518
551
|
't_auth_token': self.access_token,
|
|
519
552
|
'hardware_id': self.hardware_id,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: pytolino
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.7
|
|
4
4
|
Summary: client for tolino cloud
|
|
5
5
|
Author: Imam Usmani
|
|
6
6
|
Project-URL: Source Code, https://github.com/ImamAzim/pytolino
|
|
@@ -23,6 +23,7 @@ Requires-Dist: sphinx; extra == "dev"
|
|
|
23
23
|
Requires-Dist: build; extra == "dev"
|
|
24
24
|
Requires-Dist: twine; extra == "dev"
|
|
25
25
|
Requires-Dist: sphinx-rtd-theme; extra == "dev"
|
|
26
|
+
Dynamic: license-file
|
|
26
27
|
|
|
27
28
|
pytolino
|
|
28
29
|
===================
|
|
@@ -68,13 +68,16 @@ def client_method_tests():
|
|
|
68
68
|
|
|
69
69
|
username, password = get_credentials()
|
|
70
70
|
client = Client()
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
71
|
+
try:
|
|
72
|
+
client.login(username, password)
|
|
73
|
+
except PytolinoException as e:
|
|
74
|
+
print(e)
|
|
75
|
+
else:
|
|
76
|
+
print(client.access_token)
|
|
77
|
+
print(client.refresh_token)
|
|
78
|
+
print(client.token_expires)
|
|
76
79
|
|
|
77
|
-
|
|
80
|
+
client.logout()
|
|
78
81
|
|
|
79
82
|
|
|
80
83
|
def register_test():
|
|
@@ -238,12 +241,12 @@ def add_cover_test():
|
|
|
238
241
|
|
|
239
242
|
|
|
240
243
|
if __name__ == '__main__':
|
|
241
|
-
# logging.basicConfig(level=logging.
|
|
244
|
+
# logging.basicConfig(level=logging.DEBUG)
|
|
242
245
|
# register_test()
|
|
243
246
|
# unregister_test()
|
|
244
|
-
|
|
247
|
+
client_method_tests()
|
|
245
248
|
# upload_test()
|
|
246
249
|
# delete_test()
|
|
247
250
|
# add_cover_test()
|
|
248
251
|
# metadata_test()
|
|
249
|
-
inventory_test()
|
|
252
|
+
# inventory_test()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|