launchpy 0.4.3.post3__tar.gz → 0.4.4.post1__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.
Files changed (31) hide show
  1. {launchpy-0.4.3.post3/launchpy.egg-info → launchpy-0.4.4.post1}/PKG-INFO +5 -2
  2. {launchpy-0.4.3.post3 → launchpy-0.4.4.post1}/docs/library.md +8 -7
  3. {launchpy-0.4.3.post3 → launchpy-0.4.4.post1}/docs/property.md +8 -0
  4. {launchpy-0.4.3.post3 → launchpy-0.4.4.post1}/docs/releases.md +10 -0
  5. {launchpy-0.4.3.post3 → launchpy-0.4.4.post1}/docs/synchronizer.md +9 -1
  6. launchpy-0.4.4.post1/launchpy/__version__.py +1 -0
  7. {launchpy-0.4.3.post3 → launchpy-0.4.4.post1}/launchpy/library.py +22 -2
  8. {launchpy-0.4.3.post3 → launchpy-0.4.4.post1}/launchpy/property.py +58 -8
  9. {launchpy-0.4.3.post3 → launchpy-0.4.4.post1}/launchpy/synchronizer.py +21 -1
  10. {launchpy-0.4.3.post3 → launchpy-0.4.4.post1/launchpy.egg-info}/PKG-INFO +5 -2
  11. launchpy-0.4.3.post3/launchpy/__version__.py +0 -1
  12. {launchpy-0.4.3.post3 → launchpy-0.4.4.post1}/LICENSE +0 -0
  13. {launchpy-0.4.3.post3 → launchpy-0.4.4.post1}/README.md +0 -0
  14. {launchpy-0.4.3.post3 → launchpy-0.4.4.post1}/docs/admin.md +0 -0
  15. {launchpy-0.4.3.post3 → launchpy-0.4.4.post1}/docs/getstarted.md +0 -0
  16. {launchpy-0.4.3.post3 → launchpy-0.4.4.post1}/docs/main.md +0 -0
  17. {launchpy-0.4.3.post3 → launchpy-0.4.4.post1}/docs/translator.md +0 -0
  18. {launchpy-0.4.3.post3 → launchpy-0.4.4.post1}/launchpy/__init__.py +0 -0
  19. {launchpy-0.4.3.post3 → launchpy-0.4.4.post1}/launchpy/admin.py +0 -0
  20. {launchpy-0.4.3.post3 → launchpy-0.4.4.post1}/launchpy/config.py +0 -0
  21. {launchpy-0.4.3.post3 → launchpy-0.4.4.post1}/launchpy/configs.py +0 -0
  22. {launchpy-0.4.3.post3 → launchpy-0.4.4.post1}/launchpy/connector.py +0 -0
  23. {launchpy-0.4.3.post3 → launchpy-0.4.4.post1}/launchpy/launchpy.py +0 -0
  24. {launchpy-0.4.3.post3 → launchpy-0.4.4.post1}/launchpy.egg-info/SOURCES.txt +0 -0
  25. {launchpy-0.4.3.post3 → launchpy-0.4.4.post1}/launchpy.egg-info/dependency_links.txt +0 -0
  26. {launchpy-0.4.3.post3 → launchpy-0.4.4.post1}/launchpy.egg-info/requires.txt +0 -0
  27. {launchpy-0.4.3.post3 → launchpy-0.4.4.post1}/launchpy.egg-info/top_level.txt +0 -0
  28. {launchpy-0.4.3.post3 → launchpy-0.4.4.post1}/pyproject.toml +0 -0
  29. {launchpy-0.4.3.post3 → launchpy-0.4.4.post1}/requirements.txt +0 -0
  30. {launchpy-0.4.3.post3 → launchpy-0.4.4.post1}/setup.cfg +0 -0
  31. {launchpy-0.4.3.post3 → launchpy-0.4.4.post1}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: launchpy
3
- Version: 0.4.3.post3
3
+ Version: 0.4.4.post1
4
4
  Summary: Adobe Launch API wrapper
5
5
  Home-page: https://github.com/pitchmuc/launchpy
6
6
  Author: Julien Piccini
@@ -30,6 +30,9 @@ Requires-Dist: pathlib2
30
30
  Requires-Dist: pathlib
31
31
  Provides-Extra: dynamic
32
32
  Requires-Dist: version; extra == "dynamic"
33
+ Dynamic: author
34
+ Dynamic: home-page
35
+ Dynamic: requires-python
33
36
 
34
37
  # Launchpy
35
38
 
@@ -33,10 +33,10 @@ The different attributes are the following:
33
33
 
34
34
  * id : id of the library
35
35
  * name : name of the library
36
- * state : is it “development”, “staging” or “production” environment
36
+ * state : is it "development", "staging" or "production" environment
37
37
  * build_required : is a build required or not (Boolean)
38
38
  * builds : The build attache to this library
39
- * buid_status : Is the last build has been “successful” ?
39
+ * buid_status : Is the last build has been "successful" ?
40
40
  * relationships : the different element attached to this Library
41
41
  * _environments = a dictionary of the different environment possible.
42
42
 
@@ -45,10 +45,11 @@ The different attributes are the following:
45
45
  The get methods will enable you to retrieve the elements that have been attached to this library.
46
46
  The different get methods are the followings:
47
47
 
48
- * getDataElements
49
- * getExtensions
50
- * getRules
48
+ * getDataElements : get the data element in that library
49
+ * getExtensions : get the Extension in that library
50
+ * getRules : get the rules in the library
51
51
  * getFullLibrary : It is a combinaison of all of the 3 above.
52
+ * getBuilds : Retrieve the builds of that library
52
53
 
53
54
  ## Adding element to a library
54
55
 
@@ -62,7 +63,7 @@ They are the following:
62
63
 
63
64
  ## Environments settings
64
65
 
65
- Before you can actually start building the library and pass it from one state to another (“development” -> “staging”). You would need to set the different environments.
66
+ Before you can actually start building the library and pass it from one state to another ("development" -> "staging"). You would need to set the different environments.
66
67
 
67
68
  The method used for that is : setEnvironments().
68
69
  It takes 2 arguments:
@@ -90,7 +91,7 @@ myLib.build() # require that you have set your environment.
90
91
  As it is your goal to publish your library, you want to transition it from the dev to the staging environment and so forth.
91
92
  In order to do that, you can use the transition() method.
92
93
  ***Note*** : You would need to build your library between 2 transition.
93
- At the end of the funnel, you just need to build your library when you are in the “approved” state.
94
+ At the end of the funnel, you just need to build your library when you are in the "approved" state.
94
95
  The transition method takes 1 argument:
95
96
 
96
97
  * action : it can be either
@@ -98,6 +98,10 @@ The different get methods are the following :
98
98
  Arguments:
99
99
  * element : REQUIRED : the element definition dictionary
100
100
 
101
+ * **getProductionEndpoint** : Get the URL for the production library
102
+
103
+ * **getStagingEndpoint** : Get the URL for the staging library
104
+
101
105
 
102
106
  ## Create methods
103
107
 
@@ -322,6 +326,10 @@ They are not propertly defined by the Launch API, they have some business logic
322
326
  * save : OPTIONAL : bool, if you want to save the setting in a JS or JSON file, set it to true. (default False)
323
327
  * encoding : OPTIONAL : encoding to be used for saving the file.
324
328
 
329
+ * **extractRuleComponents** : Extract the ruleComponents reference URL from the rule definition. It can be useful for extracting rule components from the last published rule.
330
+ Arguments:
331
+ * rule : REQUIRED : A dictionary that provide the definition of the rule.
332
+
325
333
  * **findRuleComponentSettingsFileName** : Return the filename use to save your custom code of your ruleComponent in a file using the extractSettings method.\
326
334
  Returns None when this is not a Custom code from CORE or Adobe Analytics. \
327
335
  Argument:
@@ -3,6 +3,16 @@
3
3
  This page gathered the changes made between version of the launchpy module.\
4
4
  This has been started after the 0.3.0 release.\
5
5
 
6
+ ## 0.4.4
7
+ * adding a `getBuilds` method on the `Library` class instance
8
+ * extend support for pagination on `getEnvironments`
9
+ * adding `getProductionEndpoint` and `getStagingEndpoint` to retrieve the URL to use on websites
10
+ * support the instantiation of the `Library` class via a single libraryId string.\
11
+ Patch:
12
+ * adding a name parameter for the `checkExtensionUpdate` method
13
+ * adding the `extractRuleComponents` method in property.
14
+
15
+
6
16
  ## 0.4.3
7
17
  * Refactor `Translator` class for removing `pandas` dependency\
8
18
  Patch:
@@ -240,4 +240,12 @@ The logic that will be applied during the sync is the following:
240
240
  * IF the component name is in that list, **and not** in the `exclComponents` list, it will be sync
241
241
  * IF the component name is in that list **and** in the `exclComponents` list, it will **NOT** be sync
242
242
  * IF there is no list of `inclComponents` for that target property (or empty list), **and not** in the `exclComponents` list, the component will be synced
243
- * ELSE: it will be sync
243
+ * ELSE: it will be sync
244
+
245
+ ### Regular expression in Python
246
+
247
+ One common issue seeing the pattern used in Regular Expression is the use of the quantifier `*` without any character before.\
248
+ This can lead to some errors when using the following regular expression: `*some pattern*`\
249
+ This type of pattern needs to be replaced by `.*some pattern.*`\
250
+
251
+ The `*` is a quantifier that needs to have a character before it so it can know which character or pattern to repeat (or not).
@@ -0,0 +1 @@
1
+ __version__ = "0.4.4-1"
@@ -1,13 +1,14 @@
1
1
  import time
2
2
  # Non standard libraries
3
3
  from launchpy import config, connector
4
+ from typing import Union
4
5
 
5
6
  class Library:
6
7
  """
7
8
  A class that handle the library in a Launch environment.
8
9
  """
9
10
 
10
- def __init__(self, data: dict,config_object:dict=config.config_object,header:dict=config.header):
11
+ def __init__(self, data: Union[str,dict],config_object:dict=config.config_object,header:dict=config.header):
11
12
  """
12
13
  The instantiator for the library.
13
14
  Arguments:
@@ -19,6 +20,8 @@ class Library:
19
20
  config_object=config_object, header=header)
20
21
  self.header = self.connector.header
21
22
  self.endpoint = config.endpoints['global']
23
+ if type(data) == str:
24
+ data = self.connector.getData("https://reactor.adobe.io/libraries/"+data).get('data')
22
25
  self.id = data['id']
23
26
  self.name = data['attributes']['name']
24
27
  self.state = data['attributes']['state']
@@ -100,6 +103,23 @@ class Library:
100
103
  return dataOrigin
101
104
  self.relationships['extensions'] = data
102
105
  return data
106
+
107
+ def getBuilds(self)->list:
108
+ """
109
+ Retrieve the last builds.
110
+ Return a list of build
111
+ """
112
+ params = {'page[number]':1}
113
+ res = self.connector.getData(self._Builds,params=params)
114
+ builds = res.get('data',[])
115
+ next_page = res.get('meta',{}).get('pagination',{}).get('next_page',None)
116
+ while next_page is not None:
117
+ params['page[number]'] +=1
118
+ res = self.connector.getData(self._Builds,params=params)
119
+ builds += res.get('data',[])
120
+ next_page = res.get('meta',{}).get('pagination',{}).get('next_page',None)
121
+ return builds
122
+
103
123
 
104
124
  def getRules(self,page:int=0,pageSize:int=50,origin:bool=True)->list:
105
125
  """
@@ -296,7 +316,7 @@ class Library:
296
316
  Save the different environments ids available.
297
317
  It is required to use the library class.
298
318
  Arguments :
299
- environments_list : REQUIRED : list of environment retrieved by the getEnvironment method
319
+ environments_list : REQUIRED : list of environment retrieved by the getEnvironments method
300
320
  dev_name : OPTIONAL : Name of your dev environment. If not defined, will take the first dev environment.
301
321
  """
302
322
  for env in environments_list:
@@ -99,8 +99,15 @@ class Property:
99
99
  """
100
100
  Retrieve the environment sets for this property
101
101
  """
102
+ params = {"page[number]":1}
102
103
  env = self.connector.getData(self._Environments)
103
104
  data = env['data'] # skip meta for now
105
+ next_page = env.get('meta',{}).get('pagination',{}).get('next_page',None)
106
+ while next_page is not None:
107
+ params['page[number]'] = next_page
108
+ env = self.connector.getData(self._Environments,params=params)
109
+ data += env.get('data',[])
110
+ next_page = env.get('meta',{}).get('pagination',{}).get('next_page',None)
104
111
  return data
105
112
 
106
113
  def getHost(self)->object:
@@ -139,13 +146,14 @@ class Property:
139
146
  data = extensions
140
147
  return data
141
148
 
142
- def checkExtensionUpdate(self, platform: str = "web", verbose: bool = False):
149
+ def checkExtensionUpdate(self, name:str=None, platform: str = "web", verbose: bool = False):
143
150
  """
144
151
  Returns a dictionary of extensions with their names, ids and if there is an update.
145
152
  If there is an update available, the id returned is the latest id (to be used for installation).
146
153
  It can be re-use for installation and for checking for update.
147
154
  Arguments:
148
- platform : REQUIRED : if you need to look for extension on a specific platform (default web).
155
+ name : OPTIONAL : If you want to check for a specific extension
156
+ platform : OPTIONAL : if you need to look for extension on a specific platform (default web).
149
157
  verbose: OPTIONAL : if set to True, will print the different name and id of the extensions checked.
150
158
  Dictionary example:
151
159
  {'adobe-mcid':
@@ -155,13 +163,18 @@ class Property:
155
163
  }
156
164
  """
157
165
  extensions = self.getExtensions()
158
- dict_extensions = {ext['attributes']['name']: {'package_id': ext['relationships']['extension_package']['data']['id'],
166
+ if name is None:
167
+ dict_extensions = {ext['attributes']['name']: {'package_id': ext['relationships']['extension_package']['data']['id'],
159
168
  'update': False,
160
169
  'internal_id': ext['id']
161
170
  } for ext in extensions}
171
+ else:
172
+ dict_extensions = {ext['attributes']['name']: {'package_id': ext['relationships']['extension_package']['data']['id'],
173
+ 'update': False,
174
+ 'internal_id': ext['id']
175
+ } for ext in extensions if ext['attributes']['name'] == name}
162
176
  for name in dict_extensions:
163
- new_id = self._getExtensionPackage(
164
- name, platform=platform, verbose=verbose)
177
+ new_id = self._getExtensionPackage(name, platform=platform, verbose=verbose)
165
178
  if new_id != dict_extensions[name]['package_id']:
166
179
  dict_extensions[name]['package_id'] = new_id
167
180
  dict_extensions[name]['update'] = True
@@ -258,9 +271,9 @@ class Property:
258
271
  """
259
272
  filters = {}
260
273
  if name != None:
261
- filters['filter[name]=CONTAINS '] = f"EQ {name}"
274
+ filters['filter[name]'] = f"EQ {name}"
262
275
  if name_contains != None:
263
- filters['filter[name]=CONTAINS '] = f"CONTAINS {name_contains}"
276
+ filters['filter[name]'] = f"CONTAINS {name_contains}"
264
277
  if dirty != None:
265
278
  filters['filter[dirty]'] = f"EQ {str(dirty).lower()}"
266
279
  if enabled != None:
@@ -297,6 +310,27 @@ class Property:
297
310
  'url': rule['links']['rule_components']
298
311
  }
299
312
  return data
313
+
314
+ def extractRuleComponents(self,rule:dict=None)->list:
315
+ """
316
+ Extract the rule component based on the rule definition.
317
+ Arguments:
318
+ rule : REQUIRED : The rule definition
319
+ """
320
+ if rule is None:
321
+ raise ValueError("No rule definition provided")
322
+ params={'page[number]':0}
323
+ rc_endpoint = rule['relationships']['rule_components']['links']['related']
324
+ page1 = self.getRessource(rc_endpoint)
325
+ data = page1.get('data',{})
326
+ next_page = page1.get('meta',{}).get('pagination',{}).get('next_page',None)
327
+ while next_page is not None:
328
+ params['page[number]'] = next_page
329
+ pageN = self.connector.getData(rc_endpoint,params=params)
330
+ data += pageN.get('data',[])
331
+ next_page = pageN.get('meta',{}).get('pagination',{}).get('next_page',None)
332
+ return data
333
+
300
334
 
301
335
  def getRuleComponents(self, verbose:bool=False,**kwargs)->dict:
302
336
  """
@@ -1187,6 +1221,22 @@ class Property:
1187
1221
  for de in dataelements:
1188
1222
  self.deleteDataElement(de['id'])
1189
1223
  return res
1224
+
1225
+ def getProductionEndpoint(self)->dict:
1226
+ """
1227
+ Returns the production library URL to use on the website
1228
+ """
1229
+ envs = self.getEnvironments()
1230
+ prod = [env for env in envs if env['attributes']['stage'] == 'production'][0]
1231
+ return prod['meta']['script_sources'][0]["license_path"]
1232
+
1233
+ def getStagingEndpoint(self)->dict:
1234
+ """
1235
+ Returns the staging library URL to use on the website
1236
+ """
1237
+ envs = self.getEnvironments()
1238
+ staging = [env for env in envs if env['attributes']['stage'] == 'staging'][0]
1239
+ return staging['meta']['script_sources'][0]["license_path"]
1190
1240
 
1191
1241
  def extensionsInfo(data: list)->dict:
1192
1242
  """
@@ -1551,4 +1601,4 @@ def extractAnalyticsCode(rcSettings: str, save: bool = False, filename: str = No
1551
1601
  filename = filename.replace('/', '_').replace('|', '_')
1552
1602
  if save:
1553
1603
  saveFile(json_code,filename,type='js',encoding=encoding)
1554
- return json_code
1604
+ return json_code
@@ -37,7 +37,7 @@ class Synchronizer:
37
37
  raise KeyError("The base property name has not been found in your account")
38
38
  self.base = {}
39
39
  self.base["name"] = base
40
- self.base["api"] = Property(base_property[0])
40
+ self.base["api"]:Property = Property(base_property[0])
41
41
  self.base['rules'] = self.base['api'].getRules()
42
42
  self.base['dataElements'] = self.base['api'].getDataElements()
43
43
  self.base['extensions'] = self.base['api'].getExtensions()
@@ -353,6 +353,26 @@ class Synchronizer:
353
353
  if len(newDataElements)>0:
354
354
  self.targets[target]['library'].addDataElements(newDataElements)
355
355
 
356
+ def upgradeTargetExtension(self,extensionName:str=None,platform:str="web")->dict:
357
+ """
358
+ Upgrade the name extension in the target properties.
359
+ Arguments:
360
+ extensionName : REQUIRED : The name of the extension to upgrade.
361
+ ex : "core" or "adobe-analytics"
362
+ platform : OPTIONAL : If you want to update the extension of a specific platform (default "web")
363
+ """
364
+ if extensionName is None:
365
+ raise ValueError("Require an extension name")
366
+ for prop, target in self.targets:
367
+ try:
368
+ extensionUpdate = target['api'].checkExtensionUpdate(extensionName)
369
+ except:
370
+ raise ValueError(f"Could not find an extension name: {extensionName}")
371
+
372
+
373
+
374
+
375
+
356
376
  def renameComponent(self,old_name:str=None,new_name:str=None)->None:
357
377
  """
358
378
  Passing the old and new name of a component, it will rename the component in the different target properties.
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: launchpy
3
- Version: 0.4.3.post3
3
+ Version: 0.4.4.post1
4
4
  Summary: Adobe Launch API wrapper
5
5
  Home-page: https://github.com/pitchmuc/launchpy
6
6
  Author: Julien Piccini
@@ -30,6 +30,9 @@ Requires-Dist: pathlib2
30
30
  Requires-Dist: pathlib
31
31
  Provides-Extra: dynamic
32
32
  Requires-Dist: version; extra == "dynamic"
33
+ Dynamic: author
34
+ Dynamic: home-page
35
+ Dynamic: requires-python
33
36
 
34
37
  # Launchpy
35
38
 
@@ -1 +0,0 @@
1
- __version__ = "0.4.3-3"
File without changes
File without changes
File without changes
File without changes