diff --git a/.gitignore b/.gitignore index b9cfba7..0ab0356 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,7 @@ develop-eggs lib lib64 __pycache__ +.idea/* # Installer logs pip-log.txt @@ -31,3 +32,4 @@ objsamples/ET_Client.py objsamples/config.python objsamples/*.pyc config.python +soap_cache_file.json \ No newline at end of file diff --git a/FuelSDK/__init__.py b/FuelSDK/__init__.py index 92f4c9c..11d25f6 100644 --- a/FuelSDK/__init__.py +++ b/FuelSDK/__init__.py @@ -1,4 +1,6 @@ -__version__ = '1.1.1' +import version + +__version__ = version.get() # Runtime patch the suds library from FuelSDK.suds_patch import _PropertyAppender @@ -8,6 +10,9 @@ from FuelSDK.suds_patch import _bodycontent from suds.bindings import document as _document _document.Document.bodycontent = _bodycontent +from FuelSDK.suds_patch import _start +from suds.mx import literal as _literal +_literal.Typed.start = _start # end runtime patching of suds from FuelSDK.client import ET_Client diff --git a/FuelSDK/client.py b/FuelSDK/client.py index dbace1a..6032ca5 100644 --- a/FuelSDK/client.py +++ b/FuelSDK/client.py @@ -13,6 +13,8 @@ from FuelSDK.objects import ET_DataExtension,ET_Subscriber +import version +userAgent = 'FuelSDK-Python-v' + version.get() class ET_Client(object): """ @@ -175,7 +177,7 @@ def build_soap_client(self): self.soap_client = suds.client.Client(self.wsdl_file_url, faults=False, cachingpolicy=1) self.soap_client.set_options(location=self.soap_endpoint) - self.soap_client.set_options(headers={'user-agent' : 'FuelSDK-Python-v1.1.1'}) + self.soap_client.set_options(headers={'user-agent' : userAgent}) element_oAuth = Element('oAuth', ns=('etns', 'http://exacttarget.com')) element_oAuthToken = Element('oAuthToken').setText(self.internalAuthToken) @@ -194,7 +196,7 @@ def refresh_token(self, force_refresh = False): """ #If we don't already have a token or the token expires within 5 min(300 seconds), get one if (force_refresh or self.authToken is None or (self.authTokenExpiration is not None and time.time() + 300 > self.authTokenExpiration)): - headers = {'content-type' : 'application/json', 'user-agent' : 'FuelSDK-Python-v1.1.1'} + headers = {'content-type' : 'application/json', 'user-agent' : userAgent} if (self.authToken is None): payload = {'clientId' : self.client_id, 'clientSecret' : self.client_secret, 'accessType': 'offline'} else: @@ -253,7 +255,7 @@ def get_soap_endpoint(self): """ try: r = requests.get(self.base_api_url + '/platform/v1/endpoints/soap', headers={ - 'user-agent': 'FuelSDK-Python-v1.1.1', + 'user-agent': userAgent, 'authorization': 'Bearer ' + self.authToken }) diff --git a/FuelSDK/rest.py b/FuelSDK/rest.py index c77d1e7..6cb99af 100644 --- a/FuelSDK/rest.py +++ b/FuelSDK/rest.py @@ -2,6 +2,8 @@ import json import copy +import version +userAgent = 'FuelSDK-Python-v' + version.get() ######## ## @@ -331,7 +333,7 @@ def __init__(self, auth_stub, endpoint, qs = None): fullendpoint += urlSeparator + qStringValue + '=' + str(qs[qStringValue]) urlSeparator = '&' - headers = {'authorization' : 'Bearer ' + auth_stub.authToken, 'user-agent' : 'FuelSDK-Python-v1.1.1'} + headers = {'authorization' : 'Bearer ' + auth_stub.authToken, 'user-agent' : userAgent} r = requests.get(fullendpoint, headers=headers) @@ -349,7 +351,7 @@ class ET_PostRest(ET_Constructor): def __init__(self, auth_stub, endpoint, payload): auth_stub.refresh_token() - headers = {'content-type' : 'application/json', 'user-agent' : 'FuelSDK-Python-v1.1.1', 'authorization' : 'Bearer ' + auth_stub.authToken} + headers = {'content-type' : 'application/json', 'user-agent' : userAgent, 'authorization' : 'Bearer ' + auth_stub.authToken} r = requests.post(endpoint, data=json.dumps(payload), headers=headers) obj = super(ET_PostRest, self).__init__(r, True) @@ -364,7 +366,7 @@ class ET_PatchRest(ET_Constructor): def __init__(self, auth_stub, endpoint, payload): auth_stub.refresh_token() - headers = {'content-type' : 'application/json', 'user-agent' : 'FuelSDK-Python-v1.1.1', 'authorization' : 'Bearer ' + auth_stub.authToken} + headers = {'content-type' : 'application/json', 'user-agent' : userAgent, 'authorization' : 'Bearer ' + auth_stub.authToken} r = requests.patch(endpoint , data=json.dumps(payload), headers=headers) obj = super(ET_PatchRest, self).__init__(r, True) @@ -379,7 +381,7 @@ class ET_DeleteRest(ET_Constructor): def __init__(self, auth_stub, endpoint): auth_stub.refresh_token() - headers = {'authorization' : 'Bearer ' + auth_stub.authToken, 'user-agent' : 'FuelSDK-Python-v1.1.1'} + headers = {'authorization' : 'Bearer ' + auth_stub.authToken, 'user-agent' : userAgent} r = requests.delete(endpoint, headers=headers) obj = super(ET_DeleteRest, self).__init__(r, True) diff --git a/FuelSDK/suds_patch.py b/FuelSDK/suds_patch.py index 91d52cb..5369b37 100644 --- a/FuelSDK/suds_patch.py +++ b/FuelSDK/suds_patch.py @@ -1,4 +1,9 @@ -from suds.mx.appender import Appender,Content +from logging import getLogger + +from suds import * +from suds.mx import * +from suds.mx.appender import Appender +from suds.resolver import Frame class _PropertyAppender(Appender): @@ -57,3 +62,38 @@ def _bodycontent(self, method, args, kwargs): p.setPrefix(ns[0], ns[1]) root.append(p) return root + +def _start(self, content): + log = getLogger(__name__) + # + # Start marshalling the 'content' by ensuring that both the 'content' + # _and_ the resolver are primed with the XSD type information. The + # 'content' value is both translated and sorted based on the XSD type. + # Only values that are objects have their attributes sorted. + # + log.debug('starting content:\n%s', content) + if content.type is None: + name = content.tag + content.type = self.resolver.find(name, content.value) + if content.type is None: + raise TypeNotFound(content.tag) + else: + known = None + if isinstance(content.value, Object): + known = self.resolver.known(content.value) + if known is None: + log.debug('object %s has no type information', + content.value) + known = content.type + frame = Frame(content.type, resolved=known) + self.resolver.push(frame) + frame = self.resolver.top() + content.real = frame.resolved + content.ancestry = frame.ancestry + self.translate(content) + self.sort(content) + if self.skip(content): + log.debug('skipping (optional) content:\n%s', content) + self.resolver.pop() + return False + return True diff --git a/README.md b/README.md index 1a6838b..b206387 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# FuelSDK-Python v1.1.1 +# FuelSDK-Python v1.1.2 Salesforce Marketing Cloud Fuel SDK for Python @@ -6,6 +6,10 @@ Salesforce Marketing Cloud Fuel SDK for Python The Fuel SDK for Python provides easy access to Salesforce Marketing Cloud's Fuel API Family services, including a collection of REST APIs and a SOAP API. These APIs provide access to Salesforce Marketing Cloud functionality via common collection types such as array/hash. +New Features in Version 1.1.2 +------------ +* Fixed an issue with Email creation due to an update in the WSDL file. + New Features in Version 1.1.1 ------------ * Added support for your tenant’s endpoints - [More Details](https://developer.salesforce.com/docs/atlas.en-us.mc-apis.meta/mc-apis/your-subdomain-tenant-specific-endpoints.htm) diff --git a/setup.py b/setup.py index d4e8025..7eea0ce 100644 --- a/setup.py +++ b/setup.py @@ -1,10 +1,11 @@ from setuptools import setup +import version with open('README.md') as f: readme = f.read() setup( - version='1.1.1', + version=version.get(), name='Salesforce-FuelSDK', description='Salesforce Marketing Cloud Fuel SDK for Python', long_description=readme, diff --git a/version.py b/version.py new file mode 100644 index 0000000..8658b54 --- /dev/null +++ b/version.py @@ -0,0 +1,2 @@ +def get(): + return '1.1.2'