Contentstack 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.
contentstack/errors.py ADDED
@@ -0,0 +1,162 @@
1
+
2
+ """
3
+
4
+ Created by Shailesh Mishra on 22/06/19.
5
+ Copyright 2019 Contentstack. All rights reserved.
6
+
7
+ contentstack.error
8
+ ~~~~~~~~~~~~~~~~~~
9
+
10
+ API Reference: https://www.contentstack.com/docs/apis/content-delivery-api/#error
11
+
12
+ """
13
+
14
+
15
+ class Error:
16
+
17
+ """
18
+ This module implements the Error class.
19
+
20
+ API Reference: https://www.contentstack.com/docs/apis/content-delivery-api/#error
21
+
22
+ """
23
+
24
+ def __init__(self):
25
+
26
+ self.__error_dict = {}
27
+ self.__error_code = str
28
+ self.__msg = str
29
+
30
+ def _config(self, result: dict):
31
+
32
+ # _instance is the protected member of the asset, So outsiders can not access this file.
33
+ if result is not None and len(result) > 0:
34
+ self.__error_dict = result
35
+ self.__error_code = self.__error_dict['error_code']
36
+ self.__msg = self.__error_dict['error_message']
37
+
38
+ return self
39
+
40
+ @property
41
+ def error_code(self):
42
+ """It returns error code from the stack response
43
+
44
+ Returns:
45
+ int -- error_code as int
46
+
47
+ ==============================
48
+
49
+ [Example:]
50
+
51
+ >>> error_code = error.error_code
52
+
53
+ ==============================
54
+
55
+ """
56
+ return self.__error_code
57
+
58
+ @property
59
+ def error_message(self):
60
+
61
+ """
62
+ Returns error_message from the stack response
63
+
64
+ Returns:
65
+ str -- error_message from the stack response
66
+
67
+ ==============================
68
+
69
+ [Example:]
70
+
71
+ >>> message = error.error_message
72
+
73
+ ==============================
74
+ """
75
+
76
+ return self.__msg
77
+
78
+ @property
79
+ def error(self):
80
+
81
+ """
82
+ error property returns error code and error_message in dict formats
83
+
84
+ Returns:
85
+ dict -- error code and error_message in dict formats
86
+
87
+ ==============================
88
+
89
+ [Example:]
90
+
91
+ >>> error = error.error
92
+
93
+ ==============================
94
+ """
95
+
96
+ return self.__msg
97
+
98
+ @property
99
+ def error_info(self) -> dict:
100
+
101
+ """error information
102
+
103
+ Returns:
104
+ dict -- error information
105
+
106
+ ==============================
107
+
108
+ [Example:]
109
+
110
+ >>> ode = error.error_info
111
+
112
+ ==============================
113
+ """
114
+ return self.__error_dict
115
+
116
+ errors_str = {
117
+
118
+ 'invalid_json': "Please provide valid JSON.",
119
+ 'api_key_is_none': "Stack api key can not be None.",
120
+ 'empty_content_type': "Please set contentType name.",
121
+ 'access_token_error': "Access token can not be None.",
122
+ 'environment_error': "Environment can not be None.",
123
+ 'connection_error': "Connection error",
124
+ 'auth_failure': "Authentication Not present.",
125
+ 'parse_error': "Parsing Error.",
126
+ 'server_error': "Server interaction went wrong, Please try again.",
127
+ 'error_default': "Oops! Something went wrong. Please try again.",
128
+ 'no_network': "Network not available.",
129
+ 'query_error': "Please provide valid params."
130
+ }
131
+
132
+ __error_code = {
133
+
134
+ 400: "The request was incorrect or corrupted.",
135
+ 401: "The login credentials are invalid.",
136
+ 403: "The page or resource that is being accessed is forbidden.",
137
+ 404: "The requested page or resource could not be found.",
138
+ 412: "The entered API key is invalid.",
139
+ 422: "The request is syntactically correct but contains semantic errors",
140
+ 429: "The number of requests exceeds the allowed limit for the given time period.",
141
+ 500: "The server is malfunctioning and is not specific on what the problem is.",
142
+ 502: "A server received an invalid response from another server.",
143
+ 504: """ A server did not receive a timely response from another server that it was accessing while attempting
144
+ to load the web page or fill another request by the browser. """
145
+ }
146
+
147
+
148
+ class StackException(Exception):
149
+ """
150
+ StackException used to handle Stack validation Errors.
151
+ """
152
+ pass
153
+
154
+
155
+ class RequestsWarning(Warning):
156
+ """Base warning for Requests."""
157
+ pass
158
+
159
+
160
+ class FileModeWarning(RequestsWarning, DeprecationWarning):
161
+ """A file was opened in text mode, but Requests determined its binary length."""
162
+ pass
@@ -0,0 +1,195 @@
1
+ """
2
+ HttpConnection
3
+ contentstack
4
+ Created by Shailesh Mishra on 22/06/19.
5
+ Copyright 2019 Contentstack. All rights reserved.
6
+
7
+ """
8
+
9
+ import logging
10
+ import requests
11
+ from urllib.parse import urlencode
12
+ from contentstack import Error
13
+ from json import JSONDecodeError
14
+ from requests.exceptions import Timeout, HTTPError
15
+
16
+
17
+ class HTTPConnection(object):
18
+
19
+ def __init__(self, url, query, stack_headers):
20
+
21
+ if None not in (url, query, stack_headers):
22
+ self.__payload = None
23
+ self.__base_url = url
24
+ self.__query_params = query
25
+ self.__headers = stack_headers
26
+ self.__headers.update(self.__user_agents())
27
+
28
+ if 'environment' in self.__headers:
29
+ environment = self.__headers['environment']
30
+ self.__query_params['environment'] = environment
31
+
32
+ def get_result(self, url: str, query: dict, headers: dict):
33
+
34
+ if None not in (url, query, headers):
35
+ if len(url) > 0 and len(self.__headers) > 0:
36
+ self.__base_url = url
37
+ if len(headers) > 0:
38
+ self.__headers.update(headers)
39
+ self.__query_params.update(query)
40
+
41
+ # Case: If UIR Parameter contains entries
42
+ if 'entries' in self.__base_url:
43
+ self.__payload = self.__execute_entry()
44
+ else:
45
+ url_param = ''
46
+ for (key, value) in self.__query_params.items():
47
+ url_param = '{}&{}={}'.format(url_param, key, value)
48
+ self.__payload = url_param
49
+ try:
50
+ if self.__payload.startswith("&"):
51
+ self.__payload = self.__payload[1:]
52
+
53
+ _url = '{}?{}'.format(self.__base_url, self.__payload)
54
+ logging.info('{}?{}'.format(self.__base_url, self.__payload))
55
+ response = requests.get(_url, verify=True, timeout=(10, 8), headers=self.__headers)
56
+
57
+ if response.status_code == 200:
58
+ if response.raise_for_status() is None:
59
+ return self.__parse_dict(response)
60
+ else:
61
+ err = response.json()
62
+ if err is not None:
63
+ error = Error()
64
+ error._config(err)
65
+ return error
66
+
67
+ logging.info('\n\nrequest url => {}\nresponse={}'.format(response.url, response))
68
+
69
+ except Timeout:
70
+ raise TimeoutError('The request timed out')
71
+ except ConnectionError:
72
+ raise ConnectionError('Connection error occurred')
73
+ except JSONDecodeError:
74
+ raise JSONDecodeError('Invalid JSON in request')
75
+ except HTTPError:
76
+ raise HTTPError('Http Error Occurred')
77
+
78
+ def __parse_dict(self, response):
79
+ from contentstack.stack import SyncResult
80
+
81
+ result = response.json()
82
+ if 'stack' in result:
83
+ return result['stack']
84
+ if 'entry' in result:
85
+ dict_entry = result['entry']
86
+ return self.__parse_entries(dict_entry)
87
+ if 'entries' in result:
88
+ entry_list = result['entries']
89
+ return self.__parse_entries(entry_list)
90
+ if 'asset' in result:
91
+ dict_asset = result['asset']
92
+ return self.__parse_assets(dict_asset, 1)
93
+ if 'assets' in result:
94
+ asset_list = result['assets']
95
+ asset_count = 0
96
+ if 'count' in result:
97
+ asset_count = result['count']
98
+ return self.__parse_assets(asset_list, asset_count)
99
+ if 'content_type' in result:
100
+ return result['content_type']
101
+ if 'content_types' in result:
102
+ return result['content_types']
103
+ if 'items' in result:
104
+ sync_result = SyncResult()
105
+ sync_result._configure(result)
106
+ return sync_result
107
+
108
+ return None
109
+
110
+ @staticmethod
111
+ def __parse_entries(result):
112
+ from contentstack import Entry
113
+ entries = []
114
+ entry = Entry()
115
+ # if 'count' in result:
116
+ # entry.count = result['count']
117
+ if result is not None and len(result) > 0:
118
+ if isinstance(result, dict):
119
+ return entry._configure(result)
120
+ if isinstance(result, list):
121
+ for entry_obj in result:
122
+ each_entry = Entry()._configure(entry_obj)
123
+ entries.append(each_entry)
124
+ return entries
125
+
126
+ @staticmethod
127
+ def __parse_assets(result, asset_count):
128
+ from contentstack import Asset
129
+ assets = []
130
+ asset = Asset()
131
+
132
+ if result is not None and len(result) > 0:
133
+ if isinstance(result, dict):
134
+ return asset._configure(result)
135
+ if isinstance(result, list):
136
+ for asset_obj in result:
137
+ itr_asset = asset._configure(asset_obj)
138
+ assets.append(itr_asset)
139
+ asset._count(asset_count)
140
+ return assets
141
+
142
+ @staticmethod
143
+ def __user_agents() -> dict:
144
+
145
+ import contentstack
146
+ import platform
147
+
148
+ header = {'sdk': dict(name=contentstack.__package__, version=contentstack.__version__)}
149
+ os = platform.system()
150
+ if os == 'Darwin':
151
+ os = 'macOS'
152
+ elif not os or os == 'Java':
153
+ os = None
154
+ elif os and os not in ['macOS', 'Windows']:
155
+ os = 'Linux'
156
+ header['os'] = {'name': os, 'version': platform.release()}
157
+ package = "contentstack-python, - {}".format(contentstack.__version__)
158
+ local_headers = {'User-Agent': str(header), "Content-Type": 'application/json', "X-User-Agent": package}
159
+ return local_headers
160
+
161
+ def __execute_entry(self):
162
+
163
+ url_param = ''
164
+
165
+ for (key, value) in self.__query_params.items():
166
+ if key == 'include[]':
167
+ if isinstance(value, list):
168
+ url_param = '{}&{}'.format(url_param, urlencode({key: value}, doseq=True))
169
+ elif key == 'only[BASE][]':
170
+ if isinstance(value, list):
171
+ url_param = '{}&{}'.format(url_param, urlencode({key: value}, doseq=True))
172
+ elif key == 'except[BASE][]':
173
+ if isinstance(value, list):
174
+ url_param = '{}&{}'.format(url_param, urlencode({key: value}, doseq=True))
175
+ elif key == 'only':
176
+ for uid in value:
177
+ inner_list = value[uid]
178
+ inner_key = 'only[{}][]'.format(uid)
179
+ if isinstance(inner_list, list):
180
+ url_param = '{}&{}'.format(url_param, urlencode({inner_key: inner_list}, doseq=True))
181
+ elif key == 'except':
182
+ for uid in value:
183
+ inner_list = value[uid]
184
+ inner_key = 'except[{}][]'.format(uid)
185
+ if isinstance(inner_list, list):
186
+ url_param = '{}&{}'.format(url_param, urlencode({inner_key: inner_list}, doseq=True))
187
+ elif key == 'query':
188
+ url_param = '{}&{}={}'.format(url_param, key, value.__str__().replace("\'", "\""))
189
+ print(url_param)
190
+ else:
191
+ url_param = '{}&{}={}'.format(url_param, key, value)
192
+
193
+ return url_param
194
+
195
+