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/__init__.py +29 -0
- contentstack/asset.py +784 -0
- contentstack/config.py +162 -0
- contentstack/content_type.py +233 -0
- contentstack/entry.py +1162 -0
- contentstack/errors.py +162 -0
- contentstack/http_connection.py +195 -0
- contentstack/query.py +1632 -0
- contentstack/stack.py +760 -0
- contentstack/utils.py +34 -0
- contentstack-0.1.0.dist-info/LICENSE +21 -0
- contentstack-0.1.0.dist-info/METADATA +150 -0
- contentstack-0.1.0.dist-info/RECORD +15 -0
- contentstack-0.1.0.dist-info/WHEEL +5 -0
- contentstack-0.1.0.dist-info/top_level.txt +1 -0
contentstack/stack.py
ADDED
|
@@ -0,0 +1,760 @@
|
|
|
1
|
+
from contentstack import HTTPConnection
|
|
2
|
+
from contentstack import Config
|
|
3
|
+
from contentstack.errors import StackException
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
Created by Shailesh Mishra on 22/06/19.
|
|
9
|
+
Copyright 2019 Contentstack. All rights reserved.
|
|
10
|
+
|
|
11
|
+
contentstack.stack
|
|
12
|
+
~~~~~~~~~~~~~~~~~~
|
|
13
|
+
|
|
14
|
+
API Reference: https://www.contentstack.com/docs/apis/content-delivery-api/#stack
|
|
15
|
+
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class Stack(object):
|
|
20
|
+
|
|
21
|
+
def __init__(self, **kwargs):
|
|
22
|
+
|
|
23
|
+
"""
|
|
24
|
+
Argument kwargs is key-worded, variable-length argument list.
|
|
25
|
+
To initialise stack following fields should be provided.
|
|
26
|
+
|
|
27
|
+
api_key -> stack 'api_key' of your target stack, type of api_key should be str.
|
|
28
|
+
access_token -> stack 'access_token' of your target stack, type of access_token should be str.
|
|
29
|
+
environment -> stack 'environment' of your target stack, type of environment should be str
|
|
30
|
+
config: config='<contentstack.config.Config>' (optional) stack configuration to setup custom API.
|
|
31
|
+
|
|
32
|
+
==============================
|
|
33
|
+
|
|
34
|
+
[Example]:
|
|
35
|
+
|
|
36
|
+
>>> import contentstack
|
|
37
|
+
>>> stack: Stack = Stack(api_key ='api_key', access_token='access_token', environment='environment')
|
|
38
|
+
|
|
39
|
+
To declare stack with custom configuration
|
|
40
|
+
|
|
41
|
+
>>> config = Config()
|
|
42
|
+
>>> config.host('cdn.contentstack.io')
|
|
43
|
+
>>> stack = Stack(api_key ='API_Key',access_token='access_token',environment='environment', config=config)
|
|
44
|
+
|
|
45
|
+
==============================
|
|
46
|
+
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
self.config = None
|
|
50
|
+
self.__http_request = None
|
|
51
|
+
self.__query_params = dict()
|
|
52
|
+
self.__stack_headers = dict()
|
|
53
|
+
self.__headers = dict()
|
|
54
|
+
self.__image_transform_url = None
|
|
55
|
+
self.__image_params = dict
|
|
56
|
+
self.__sync_query = dict()
|
|
57
|
+
for key, value in kwargs.items():
|
|
58
|
+
self.__headers[key] = value
|
|
59
|
+
self.__initialise_stack()
|
|
60
|
+
|
|
61
|
+
@property
|
|
62
|
+
def api_key(self):
|
|
63
|
+
|
|
64
|
+
"""Returns api_KEY of the stack
|
|
65
|
+
|
|
66
|
+
Returns:
|
|
67
|
+
str -- api_key of the stack
|
|
68
|
+
|
|
69
|
+
==============================
|
|
70
|
+
|
|
71
|
+
[Example]:
|
|
72
|
+
|
|
73
|
+
>>> from contentstack import Stack
|
|
74
|
+
>>> stack = Stack(api_key='stack_api_key', access_token='stack_access_token', environment='env')
|
|
75
|
+
>>> api_key = stack.api_key
|
|
76
|
+
|
|
77
|
+
==============================
|
|
78
|
+
|
|
79
|
+
"""
|
|
80
|
+
|
|
81
|
+
if 'api_key' in self.__stack_headers:
|
|
82
|
+
app_key = self.__stack_headers['api_key']
|
|
83
|
+
return app_key
|
|
84
|
+
|
|
85
|
+
@property
|
|
86
|
+
def get_http_instance(self):
|
|
87
|
+
|
|
88
|
+
"""This method returns http_instance of the stack.
|
|
89
|
+
|
|
90
|
+
Returns:
|
|
91
|
+
str -- instance of the HttpRequest
|
|
92
|
+
|
|
93
|
+
==============================
|
|
94
|
+
|
|
95
|
+
[Example]:
|
|
96
|
+
|
|
97
|
+
>>> from contentstack import Stack
|
|
98
|
+
>>> stack = Stack(api_key='stack_api_key', access_token='stack_access_token', environment='env')
|
|
99
|
+
>>> http_instance = stack.get_http_instance
|
|
100
|
+
|
|
101
|
+
==============================
|
|
102
|
+
|
|
103
|
+
"""
|
|
104
|
+
|
|
105
|
+
return self.__http_request
|
|
106
|
+
|
|
107
|
+
@property
|
|
108
|
+
def access_token(self):
|
|
109
|
+
|
|
110
|
+
"""access_token property returns access_token of the stack
|
|
111
|
+
|
|
112
|
+
Returns:
|
|
113
|
+
str -- access_token of the stack
|
|
114
|
+
|
|
115
|
+
==============================
|
|
116
|
+
|
|
117
|
+
[Example]:
|
|
118
|
+
|
|
119
|
+
>>> from contentstack import Stack
|
|
120
|
+
>>> stack = Stack(api_key='stack_api_key', access_token='stack_access_token', environment='env')
|
|
121
|
+
>>> access_token = stack.access_token
|
|
122
|
+
|
|
123
|
+
==============================
|
|
124
|
+
|
|
125
|
+
"""
|
|
126
|
+
|
|
127
|
+
if 'access_token' in self.__stack_headers:
|
|
128
|
+
access_token = self.__stack_headers['access_token']
|
|
129
|
+
return access_token
|
|
130
|
+
else:
|
|
131
|
+
return None
|
|
132
|
+
|
|
133
|
+
@property
|
|
134
|
+
def environment(self):
|
|
135
|
+
|
|
136
|
+
"""environment property returns environment of the stack
|
|
137
|
+
|
|
138
|
+
Returns:
|
|
139
|
+
str -- environment of the stack
|
|
140
|
+
|
|
141
|
+
==============================
|
|
142
|
+
|
|
143
|
+
[Example]:
|
|
144
|
+
|
|
145
|
+
>>> from contentstack import Stack
|
|
146
|
+
>>> stack = Stack(api_key='stack_api_key', access_token='stack_access_token', environment='env')
|
|
147
|
+
>>> environment = stack.environment
|
|
148
|
+
|
|
149
|
+
==============================
|
|
150
|
+
|
|
151
|
+
"""
|
|
152
|
+
|
|
153
|
+
if 'environment' in self.__stack_headers:
|
|
154
|
+
return self.__stack_headers['environment']
|
|
155
|
+
else:
|
|
156
|
+
return None
|
|
157
|
+
|
|
158
|
+
@environment.setter
|
|
159
|
+
def environment(self, environment):
|
|
160
|
+
|
|
161
|
+
"""
|
|
162
|
+
environment property helps to set environment of the stack
|
|
163
|
+
|
|
164
|
+
Arguments:
|
|
165
|
+
environment {str} -- environment of the stack
|
|
166
|
+
|
|
167
|
+
Raises:
|
|
168
|
+
KeyError: If environment is None, empty or not str type
|
|
169
|
+
|
|
170
|
+
==============================
|
|
171
|
+
|
|
172
|
+
[Example]:
|
|
173
|
+
|
|
174
|
+
>>> from contentstack import Stack
|
|
175
|
+
>>> stack = Stack(api_key='stack_api_key', access_token='stack_access_token', environment='env')
|
|
176
|
+
>>> stack.environment = 'product'
|
|
177
|
+
|
|
178
|
+
==============================
|
|
179
|
+
|
|
180
|
+
"""
|
|
181
|
+
|
|
182
|
+
if environment is None:
|
|
183
|
+
raise KeyError
|
|
184
|
+
elif isinstance(environment, str):
|
|
185
|
+
self.__stack_headers['environment'] = environment
|
|
186
|
+
else:
|
|
187
|
+
raise KeyError('Argument environment should be str type')
|
|
188
|
+
|
|
189
|
+
@property
|
|
190
|
+
def headers(self):
|
|
191
|
+
|
|
192
|
+
"""dictionary of the stack headers
|
|
193
|
+
|
|
194
|
+
Returns:
|
|
195
|
+
dict -- dictionary of the headers
|
|
196
|
+
|
|
197
|
+
==============================
|
|
198
|
+
|
|
199
|
+
[Example]:
|
|
200
|
+
|
|
201
|
+
>>> from contentstack import Stack
|
|
202
|
+
>>> stack = Stack(api_key='stack_api_key', access_token='stack_access_token', environment='env')
|
|
203
|
+
>>> headers = stack.headers
|
|
204
|
+
|
|
205
|
+
==============================
|
|
206
|
+
|
|
207
|
+
"""
|
|
208
|
+
|
|
209
|
+
return self.__stack_headers
|
|
210
|
+
|
|
211
|
+
def __initialise_stack(self):
|
|
212
|
+
# __initialise_stack is the protected member of the asset, So outsiders can not access this file.
|
|
213
|
+
if len(self.__headers) > 0:
|
|
214
|
+
if 'api_key' not in self.__headers:
|
|
215
|
+
raise StackException('Kindly provide API_Key')
|
|
216
|
+
else:
|
|
217
|
+
self.__stack_headers['api_key'] = self.__headers['api_key']
|
|
218
|
+
if 'access_token' not in self.__headers:
|
|
219
|
+
raise StackException('Kindly provide access token')
|
|
220
|
+
else:
|
|
221
|
+
self.__stack_headers['access_token'] = self.__headers['access_token']
|
|
222
|
+
if 'environment' not in self.__headers:
|
|
223
|
+
raise StackException('Kindly provide environment')
|
|
224
|
+
else:
|
|
225
|
+
self.__stack_headers['environment'] = self.__headers['environment']
|
|
226
|
+
if 'config' in self.__headers:
|
|
227
|
+
self.config = self.__headers['config']
|
|
228
|
+
self.__headers.pop('config', None)
|
|
229
|
+
else:
|
|
230
|
+
self.config = Config()
|
|
231
|
+
self.__http_request = HTTPConnection(self.config.endpoint, self.__query_params, self.__stack_headers)
|
|
232
|
+
|
|
233
|
+
def content_type(self, content_type_id):
|
|
234
|
+
|
|
235
|
+
"""
|
|
236
|
+
Gets ContentType of the Stack Read more about Content Types.
|
|
237
|
+
API Reference: https://www.contentstack.com/docs/apis/content-delivery-api/#content-types
|
|
238
|
+
|
|
239
|
+
Arguments:
|
|
240
|
+
content_type_id {str} -- content_type_id of entry
|
|
241
|
+
|
|
242
|
+
Raises:
|
|
243
|
+
StackException: If content_type_id is None, empty or not str type
|
|
244
|
+
|
|
245
|
+
Returns:
|
|
246
|
+
<contentstack.content_type.ContentType> -- Instance of the ContentType
|
|
247
|
+
|
|
248
|
+
==============================
|
|
249
|
+
|
|
250
|
+
[Example]:
|
|
251
|
+
|
|
252
|
+
>>> from contentstack import Stack
|
|
253
|
+
>>> stack = Stack(api_key='stack_api_key', access_token='stack_access_token', environment='env')
|
|
254
|
+
>>> content_type = stack.content_type('product')
|
|
255
|
+
|
|
256
|
+
==============================
|
|
257
|
+
"""
|
|
258
|
+
|
|
259
|
+
from contentstack import ContentType
|
|
260
|
+
if content_type_id is not None and isinstance(content_type_id, str) and len(content_type_id) > 0:
|
|
261
|
+
content_type = ContentType(content_type_id)
|
|
262
|
+
content_type._instance(self)
|
|
263
|
+
return content_type
|
|
264
|
+
else:
|
|
265
|
+
raise StackException('Kindly provide valid content_type')
|
|
266
|
+
|
|
267
|
+
def get_content_types(self, query_params):
|
|
268
|
+
|
|
269
|
+
"""
|
|
270
|
+
Fetches all Content Types from the Stack. This call returns comprehensive information
|
|
271
|
+
of all the content types available in a particular stack in your account.
|
|
272
|
+
API Reference: https://www.contentstack.com/docs/apis/content-delivery-api/#content-types
|
|
273
|
+
|
|
274
|
+
Arguments:
|
|
275
|
+
query_params {dict} -- query parameters for the content_types
|
|
276
|
+
|
|
277
|
+
Raises:
|
|
278
|
+
StackException: If stack instance is not found
|
|
279
|
+
|
|
280
|
+
Returns:
|
|
281
|
+
dict -- returns list of <contentstack.content_type.ContentType>
|
|
282
|
+
|
|
283
|
+
==============================
|
|
284
|
+
|
|
285
|
+
[Example]:
|
|
286
|
+
|
|
287
|
+
>>> from contentstack import Stack
|
|
288
|
+
>>> stack = Stack(api_key='stack_api_key', access_token='stack_access_token', environment='env')
|
|
289
|
+
>>> content_types = stack.get_content_types()
|
|
290
|
+
|
|
291
|
+
==============================
|
|
292
|
+
"""
|
|
293
|
+
content_type_params: dict = {}
|
|
294
|
+
if self.config is None:
|
|
295
|
+
raise StackException('Kindly initialise stack')
|
|
296
|
+
endpoint = self.config.endpoint
|
|
297
|
+
url = '{}/content_types'.format(endpoint)
|
|
298
|
+
if query_params is not None and isinstance(query_params, dict):
|
|
299
|
+
content_type_params = query_params.copy()
|
|
300
|
+
result = self.__http_request.get_result(url, content_type_params, self.__stack_headers)
|
|
301
|
+
|
|
302
|
+
return result
|
|
303
|
+
|
|
304
|
+
def asset(self, uid=None):
|
|
305
|
+
|
|
306
|
+
"""
|
|
307
|
+
Assets refer to all the media files (images, videos, PDFs, audio files, and so on)
|
|
308
|
+
uploaded in your Contentstack repository for future use. These files can be
|
|
309
|
+
attached and used in multiple entries. Learn more about Assets.
|
|
310
|
+
Keep uid None to fetch list of all assets
|
|
311
|
+
API Reference : https://www.contentstack.com/docs/guide/content-management#working-with-assets
|
|
312
|
+
|
|
313
|
+
Keyword Arguments:
|
|
314
|
+
uid {str} -- uid of the asset (default: {None})
|
|
315
|
+
|
|
316
|
+
Returns:
|
|
317
|
+
<contentstack.asset.Asset> -- class object of asset so we can chain the asset functions.
|
|
318
|
+
|
|
319
|
+
==============================
|
|
320
|
+
|
|
321
|
+
[Example]: [Asset]
|
|
322
|
+
This call fetches the latest version of a specific asset of a particular stack.
|
|
323
|
+
provide asset_uid of the asset you have to find.
|
|
324
|
+
Example: in case to fetch single asset, provide uid of the asset:
|
|
325
|
+
|
|
326
|
+
>>> from contentstack import Stack
|
|
327
|
+
>>> stack = Stack(api_key='stack_api_key', access_token='stack_access_token', environment='env')
|
|
328
|
+
>>> asset_instance = stack.asset('bltputyourassetuid')
|
|
329
|
+
>>> asset = asset_instance.fetch()
|
|
330
|
+
|
|
331
|
+
###############################
|
|
332
|
+
|
|
333
|
+
[Example]: [All Assets]
|
|
334
|
+
|
|
335
|
+
>>> from contentstack import Stack
|
|
336
|
+
>>> stack = Stack(api_key='stack_api_key', access_token='stack_access_token', environment='env')
|
|
337
|
+
>>> asset_instance = stack.asset()
|
|
338
|
+
>>> assets = asset_instance.fetch_all()
|
|
339
|
+
|
|
340
|
+
==============================
|
|
341
|
+
|
|
342
|
+
"""
|
|
343
|
+
|
|
344
|
+
from contentstack import Asset
|
|
345
|
+
asset = Asset(uid=uid)
|
|
346
|
+
asset._instance(self)
|
|
347
|
+
return asset
|
|
348
|
+
|
|
349
|
+
def image_transform(self, image_url: str, **kwargs):
|
|
350
|
+
|
|
351
|
+
"""
|
|
352
|
+
The Image Delivery API is used to retrieve, manipulate and/or convert image
|
|
353
|
+
files of your Contentstack account and deliver it to your web or mobile properties.
|
|
354
|
+
It is an second parameter in which we want to place different manipulation key and
|
|
355
|
+
value in array form ImageTransform method is define for image manipulation with
|
|
356
|
+
different transform_params in second parameter in array form
|
|
357
|
+
|
|
358
|
+
Arguments:
|
|
359
|
+
image_url {str} -- On which we want to manipulate
|
|
360
|
+
**kwargs {object} -- parameter in which we want to place different manipulation key-worded, variable-length
|
|
361
|
+
argument list
|
|
362
|
+
It is a query form that we want to place different manipulation key and value
|
|
363
|
+
|
|
364
|
+
Returns:
|
|
365
|
+
str -- Image transformation url
|
|
366
|
+
|
|
367
|
+
==============================
|
|
368
|
+
|
|
369
|
+
[Example]:
|
|
370
|
+
|
|
371
|
+
>>> from contentstack import Stack
|
|
372
|
+
>>> stack = Stack(api_key='stack_api_key', access_token='stack_access_token', environment='env')
|
|
373
|
+
>>> stack.image_transform('image_url', width=100, height=100)
|
|
374
|
+
|
|
375
|
+
==============================
|
|
376
|
+
|
|
377
|
+
"""
|
|
378
|
+
|
|
379
|
+
self.__image_transform_url = image_url
|
|
380
|
+
self.__image_params = kwargs
|
|
381
|
+
args = ['{0}={1}'.format(k, v) for k, v in kwargs.items()]
|
|
382
|
+
if args:
|
|
383
|
+
self.__image_transform_url += '?{0}'.format('&'.join(args))
|
|
384
|
+
return self.__image_transform_url
|
|
385
|
+
|
|
386
|
+
def collaborators(self):
|
|
387
|
+
|
|
388
|
+
"""
|
|
389
|
+
A detailed information about collaborators with whome the stacks are shared.
|
|
390
|
+
|
|
391
|
+
Returns:
|
|
392
|
+
Stack -- Stack object so we can chain other functions.
|
|
393
|
+
|
|
394
|
+
==============================
|
|
395
|
+
|
|
396
|
+
[Example]:
|
|
397
|
+
|
|
398
|
+
>>> from contentstack import Stack
|
|
399
|
+
>>> stack = Stack(api_key='stack_api_key', access_token='stack_access_token', environment='env')
|
|
400
|
+
>>> stack = stack.collaborators()
|
|
401
|
+
>>> result = stack.fetch()
|
|
402
|
+
|
|
403
|
+
==============================
|
|
404
|
+
|
|
405
|
+
"""
|
|
406
|
+
|
|
407
|
+
self.__query_params['include_collaborators'] = 'true'
|
|
408
|
+
|
|
409
|
+
return self
|
|
410
|
+
|
|
411
|
+
def include_stack_variables(self):
|
|
412
|
+
|
|
413
|
+
"""
|
|
414
|
+
Stack variables are extra information about the stack, such as the description,
|
|
415
|
+
format of date, format of time, and so on. Users can include or exclude stack variables
|
|
416
|
+
in the response
|
|
417
|
+
|
|
418
|
+
Returns:
|
|
419
|
+
Stack -- Stack object so we can chain other functions.
|
|
420
|
+
|
|
421
|
+
==============================
|
|
422
|
+
|
|
423
|
+
[Example]:
|
|
424
|
+
|
|
425
|
+
>>> from contentstack import Stack
|
|
426
|
+
>>> stack = Stack(api_key='stack_api_key', access_token='stack_access_token', environment='env')
|
|
427
|
+
>>> stack = stack.include_stack_variables()
|
|
428
|
+
>>> result = stack.fetch()
|
|
429
|
+
|
|
430
|
+
==============================
|
|
431
|
+
|
|
432
|
+
"""
|
|
433
|
+
|
|
434
|
+
self.__query_params['include_stack_variables'] = 'true'
|
|
435
|
+
|
|
436
|
+
return self
|
|
437
|
+
|
|
438
|
+
def include_discrete_variables(self):
|
|
439
|
+
|
|
440
|
+
"""Discrete variables of the stack
|
|
441
|
+
|
|
442
|
+
Returns:
|
|
443
|
+
Stack -- Stack object so we can chain other functions.
|
|
444
|
+
|
|
445
|
+
==============================
|
|
446
|
+
|
|
447
|
+
[Example]:
|
|
448
|
+
|
|
449
|
+
>>> from contentstack import Stack
|
|
450
|
+
>>> stack = Stack(api_key='stack_api_key', access_token='stack_access_token', environment='env')
|
|
451
|
+
>>> stack = stack.include_discrete_variables()
|
|
452
|
+
>>> result = stack.fetch()
|
|
453
|
+
|
|
454
|
+
==============================
|
|
455
|
+
"""
|
|
456
|
+
|
|
457
|
+
self.__query_params['include_discrete_variables'] = 'true'
|
|
458
|
+
|
|
459
|
+
return self
|
|
460
|
+
|
|
461
|
+
def include_count(self):
|
|
462
|
+
|
|
463
|
+
"""
|
|
464
|
+
Includes count of stack response
|
|
465
|
+
|
|
466
|
+
|
|
467
|
+
Returns:
|
|
468
|
+
Stack -- Stack object so we can chain other functions.
|
|
469
|
+
|
|
470
|
+
==============================
|
|
471
|
+
|
|
472
|
+
[Example]:
|
|
473
|
+
|
|
474
|
+
>>> from contentstack import Stack
|
|
475
|
+
>>> stack = Stack(api_key='stack_api_key', access_token='stack_access_token', environment='env')
|
|
476
|
+
>>> stack = stack.include_count()
|
|
477
|
+
>>> result = stack.fetch()
|
|
478
|
+
|
|
479
|
+
==============================
|
|
480
|
+
"""
|
|
481
|
+
|
|
482
|
+
self.__query_params['include_count'] = 'true'
|
|
483
|
+
|
|
484
|
+
return self
|
|
485
|
+
|
|
486
|
+
def fetch(self):
|
|
487
|
+
|
|
488
|
+
"""
|
|
489
|
+
Fetches the stack reponse as per the functions applied
|
|
490
|
+
|
|
491
|
+
Returns:
|
|
492
|
+
dict -- result is the reponse of the stack
|
|
493
|
+
|
|
494
|
+
==============================
|
|
495
|
+
|
|
496
|
+
[Example]:
|
|
497
|
+
|
|
498
|
+
>>> from contentstack import Stack
|
|
499
|
+
>>> stack = Stack(api_key='stack_api_key', access_token='stack_access_token', environment='env')
|
|
500
|
+
>>> stack = stack.include_count()
|
|
501
|
+
>>> result = stack.fetch()
|
|
502
|
+
|
|
503
|
+
==============================
|
|
504
|
+
|
|
505
|
+
"""
|
|
506
|
+
url = '{}/stacks'.format(self.config.endpoint)
|
|
507
|
+
result = self.__http_request.get_result(url, self.__query_params, self.__stack_headers)
|
|
508
|
+
return result
|
|
509
|
+
|
|
510
|
+
def sync(self, **kwargs):
|
|
511
|
+
|
|
512
|
+
"""
|
|
513
|
+
content_type_uid -- You can also initialize sync with entries of
|
|
514
|
+
only specific content_type. To do this, use syncContentType and specify
|
|
515
|
+
the content type uid as its value. However, if you do this,
|
|
516
|
+
the subsequent syncs will only include the entries of the specified content_type.
|
|
517
|
+
|
|
518
|
+
from_date -- You can also initialize sync with entries published
|
|
519
|
+
after a specific date. To do this, use from_date
|
|
520
|
+
and specify the start date as its value.
|
|
521
|
+
|
|
522
|
+
locale -- You can also initialize sync with entries of only specific locales.
|
|
523
|
+
To do this, use syncLocale and specify the locale code as its value.
|
|
524
|
+
However, if you do this, the subsequent syncs will only include
|
|
525
|
+
the entries of the specified locales.
|
|
526
|
+
|
|
527
|
+
publish_type -- Use the type parameter to get a specific type of content.
|
|
528
|
+
You can pass one of the following values:
|
|
529
|
+
|
|
530
|
+
asset_published, entry_published, asset_unpublished,
|
|
531
|
+
asset_deleted, entry_unpublished, entry_deleted,
|
|
532
|
+
content_type_deleted.
|
|
533
|
+
|
|
534
|
+
If you do not specify any value, it will bring all published entries and published assets.
|
|
535
|
+
|
|
536
|
+
Raises:
|
|
537
|
+
KeyError: If headers of the stack is None or empty
|
|
538
|
+
|
|
539
|
+
Returns:
|
|
540
|
+
list[SyncResult] -- returns list of SyncResult
|
|
541
|
+
|
|
542
|
+
==============================
|
|
543
|
+
|
|
544
|
+
[Example]:
|
|
545
|
+
|
|
546
|
+
>>> from contentstack import Stack
|
|
547
|
+
>>> stack = Stack(api_key='stack_api_key', access_token='stack_access_token', environment='env')
|
|
548
|
+
>>> result = stack.sync(content_type_uid='content_type_uid', from_date='date', locale='en-us', publish_type='asset_published')
|
|
549
|
+
|
|
550
|
+
==============================
|
|
551
|
+
|
|
552
|
+
"""
|
|
553
|
+
|
|
554
|
+
self.__sync_query["init"] = 'true'
|
|
555
|
+
if kwargs is not None and len(kwargs) > 0:
|
|
556
|
+
for key, value in kwargs.items():
|
|
557
|
+
self.__sync_query[key] = value
|
|
558
|
+
if self.__stack_headers is not None and len(self.__stack_headers) > 0:
|
|
559
|
+
if 'environment' in self.__stack_headers:
|
|
560
|
+
env = self.__stack_headers['environment']
|
|
561
|
+
self.__sync_query['environment'] = env
|
|
562
|
+
else:
|
|
563
|
+
raise KeyError("Kindly provide stack headers")
|
|
564
|
+
|
|
565
|
+
return self.__sync_request()
|
|
566
|
+
|
|
567
|
+
def pagination(self, pagination_token):
|
|
568
|
+
|
|
569
|
+
"""
|
|
570
|
+
If the result of the initial sync (or subsequent sync) contains more than 100 records, the response would be
|
|
571
|
+
paginated. It provides pagination token in the response. However, you do not have to use the pagination token
|
|
572
|
+
manually to get the next batch, the SDK does that automatically until the sync is complete. Pagination token
|
|
573
|
+
can be used in case you want to fetch only selected batches. It is especially useful if the sync process is
|
|
574
|
+
interrupted midway (due to network issues, etc.). In such cases, this token can be used to restart the sync
|
|
575
|
+
process from where it was interrupted.
|
|
576
|
+
|
|
577
|
+
Arguments:
|
|
578
|
+
pagination_token {str} -- pagination_token
|
|
579
|
+
|
|
580
|
+
Raises:
|
|
581
|
+
KeyError: If pagination_token is None, empty or not str type
|
|
582
|
+
|
|
583
|
+
Returns:
|
|
584
|
+
list[SyncResult] -- list of SyncResult
|
|
585
|
+
|
|
586
|
+
==============================
|
|
587
|
+
|
|
588
|
+
[Example]:
|
|
589
|
+
|
|
590
|
+
>>> from contentstack import Stack
|
|
591
|
+
>>> stack = Stack(api_key='stack_api_key', access_token='stack_access_token', environment='env')
|
|
592
|
+
>>> result = stack.pagination('blt8347235938759')
|
|
593
|
+
|
|
594
|
+
==============================
|
|
595
|
+
|
|
596
|
+
"""
|
|
597
|
+
|
|
598
|
+
if isinstance(pagination_token, str):
|
|
599
|
+
self.__sync_query = {'pagination_token': pagination_token}
|
|
600
|
+
else:
|
|
601
|
+
raise KeyError('Kindly provide valid pagination_token')
|
|
602
|
+
return self.__sync_request()
|
|
603
|
+
|
|
604
|
+
def sync_token(self, sync_token):
|
|
605
|
+
|
|
606
|
+
"""
|
|
607
|
+
You can use the sync token (that you receive after initial sync)
|
|
608
|
+
to get the updated content next time.
|
|
609
|
+
The sync token fetches only the content that was added after your last sync,
|
|
610
|
+
and the details of the content that was deleted or updated.
|
|
611
|
+
|
|
612
|
+
Arguments:
|
|
613
|
+
sync_token {str} -- sync_token
|
|
614
|
+
|
|
615
|
+
Raises:
|
|
616
|
+
StackException: If sync_token is not str
|
|
617
|
+
|
|
618
|
+
Returns:
|
|
619
|
+
list[SyncResult] -- list of SyncResult object
|
|
620
|
+
|
|
621
|
+
==============================
|
|
622
|
+
|
|
623
|
+
[Example]:
|
|
624
|
+
|
|
625
|
+
>>> from contentstack import Stack
|
|
626
|
+
>>> stack = Stack(api_key='stack_api_key', access_token='stack_access_token', environment='env')
|
|
627
|
+
>>> result = stack.sync_token('bltsomekeytoput')
|
|
628
|
+
|
|
629
|
+
==============================
|
|
630
|
+
|
|
631
|
+
"""
|
|
632
|
+
|
|
633
|
+
if isinstance(sync_token, str):
|
|
634
|
+
self.__sync_query = {'sync_token': sync_token}
|
|
635
|
+
else:
|
|
636
|
+
raise StackException('Kindly provide valid sync_token')
|
|
637
|
+
return self.__sync_request()
|
|
638
|
+
|
|
639
|
+
def __sync_request(self):
|
|
640
|
+
|
|
641
|
+
# This is useful to find sync_request for the stack
|
|
642
|
+
url = '{}/stacks/sync'.format(self.config.endpoint)
|
|
643
|
+
result = self.__http_request.get_result(url, self.__sync_query, self.__stack_headers)
|
|
644
|
+
return result
|
|
645
|
+
|
|
646
|
+
|
|
647
|
+
class SyncResult:
|
|
648
|
+
|
|
649
|
+
def __init__(self):
|
|
650
|
+
self.__resp: dict = {}
|
|
651
|
+
self.__items: list = []
|
|
652
|
+
self.__skip = int
|
|
653
|
+
self.__limit = int
|
|
654
|
+
self.__total_count = int
|
|
655
|
+
self.__sync_token = str
|
|
656
|
+
self.__pagination_token = str
|
|
657
|
+
|
|
658
|
+
def _configure(self, result: dict):
|
|
659
|
+
if result is not None and len(result) > 0:
|
|
660
|
+
self.__resp = result
|
|
661
|
+
if 'items' in self.__resp:
|
|
662
|
+
self.__items = self.__resp['items']
|
|
663
|
+
if 'skip' in self.__resp:
|
|
664
|
+
self.__skip = self.__resp['skip']
|
|
665
|
+
if 'limit' in self.__resp:
|
|
666
|
+
self.__limit = self.__resp['limit']
|
|
667
|
+
if 'total_count' in self.__resp:
|
|
668
|
+
self.__total_count = self.__resp['total_count']
|
|
669
|
+
if 'sync_token' in self.__resp:
|
|
670
|
+
self.__sync_token = self.__resp['sync_token']
|
|
671
|
+
if 'pagination_token' in self.__resp:
|
|
672
|
+
self.__pagination_token = self.__resp['pagination_token']
|
|
673
|
+
return self
|
|
674
|
+
|
|
675
|
+
@property
|
|
676
|
+
def json(self):
|
|
677
|
+
|
|
678
|
+
"""
|
|
679
|
+
:return: Json response
|
|
680
|
+
"""
|
|
681
|
+
return self.__resp
|
|
682
|
+
|
|
683
|
+
@property
|
|
684
|
+
def items(self):
|
|
685
|
+
|
|
686
|
+
"""
|
|
687
|
+
:return: Total items
|
|
688
|
+
"""
|
|
689
|
+
return self.__items
|
|
690
|
+
|
|
691
|
+
@property
|
|
692
|
+
def skip(self):
|
|
693
|
+
|
|
694
|
+
"""
|
|
695
|
+
:return: skipped items
|
|
696
|
+
"""
|
|
697
|
+
return self.__skip
|
|
698
|
+
|
|
699
|
+
@property
|
|
700
|
+
def limit(self):
|
|
701
|
+
|
|
702
|
+
"""
|
|
703
|
+
:return: This property returns limit
|
|
704
|
+
:rtype: int
|
|
705
|
+
==============================
|
|
706
|
+
|
|
707
|
+
Example:
|
|
708
|
+
>>> limit = SyncResult.limit
|
|
709
|
+
|
|
710
|
+
==============================
|
|
711
|
+
"""
|
|
712
|
+
return self.__limit
|
|
713
|
+
|
|
714
|
+
@property
|
|
715
|
+
def count(self):
|
|
716
|
+
|
|
717
|
+
"""
|
|
718
|
+
:return: This property returns count
|
|
719
|
+
:rtype: int
|
|
720
|
+
|
|
721
|
+
==============================
|
|
722
|
+
|
|
723
|
+
Example:
|
|
724
|
+
>>> count = SyncResult.count
|
|
725
|
+
|
|
726
|
+
==============================
|
|
727
|
+
"""
|
|
728
|
+
return self.__total_count
|
|
729
|
+
|
|
730
|
+
@property
|
|
731
|
+
def sync_token(self):
|
|
732
|
+
|
|
733
|
+
"""
|
|
734
|
+
:return: This property returns sync_token
|
|
735
|
+
:rtype: str
|
|
736
|
+
|
|
737
|
+
==============================
|
|
738
|
+
|
|
739
|
+
Example:
|
|
740
|
+
>>> sync_token = SyncResult.sync_token
|
|
741
|
+
|
|
742
|
+
==============================
|
|
743
|
+
"""
|
|
744
|
+
return self.__sync_token
|
|
745
|
+
|
|
746
|
+
@property
|
|
747
|
+
def pagination_token(self):
|
|
748
|
+
|
|
749
|
+
"""
|
|
750
|
+
:return: This property returns pagination_token
|
|
751
|
+
:rtype: str
|
|
752
|
+
|
|
753
|
+
==============================
|
|
754
|
+
|
|
755
|
+
Example:
|
|
756
|
+
>>> pagination_token = SyncResult.pagination_token
|
|
757
|
+
|
|
758
|
+
==============================
|
|
759
|
+
"""
|
|
760
|
+
return self.__pagination_token
|