예제 #1
0
class TestSDK(object):
    '''
    Compares objects from BaseSpace REST API to SDK objects, including pickled objects
    '''
    def __init__(self):                                        
        
        self.qp = {}
        self.rest_method = 'GET'
        self.postData = None
        self.headerParams=None
        self.list_request = False
        
        # TODO change to unit_tests, but need to add projects/run to account?
        self.myAPI = BaseSpaceAPI(profile="ps_native_hoth")        
        self.api = APIClient(self.myAPI.getAccessToken(), self.myAPI.apiServer)        

    def compare_dict_to_obj(self, rest_dict, p_obj):
        """ 
        Compare a dictionary from a REST API response and a SDK object for identity.
        """
        for r_key, r_val in rest_dict.iteritems():
            # confirm that the key from REST api exists in stored object
            try:
                p_val = getattr(p_obj, r_key)                                      
            except AttributeError:
                print "REST API attribute '" + r_key + "' doesn't exist in object"                            
            else:
                self.classify_rest_item(r_val, p_val, r_key)                    

    def compare_list_to_obj(self, rest_list, p_obj, r_key):
        """ 
        Compare a list from a REST API response and an SDK object for identity.
        """                   
        if type(p_obj) != list:
            print "Attribute '" + r_key + "' is a list in the REST API but not in the object"
        elif len(p_obj) != len(rest_list):
            print "Attribute '" + r_key + "' has different list length between REST API and object"
        else:
            for r_val, p_val in map(None, rest_list, p_obj):
                self.classify_rest_item(r_val, p_val, r_key)
                                                                        
    def compare_builtin_to_obj(self, rest_val, p_obj, r_key):
        """ 
        Compare a built-in type from a REST API response and an SDK object for identity.
        """                   
        # convert unicode to ascii for comparisons
        if isinstance(rest_val, unicode):
            rest_val = rest_val.encode('ascii','ignore')
        # don't compare values for datetimes
        if r_key in ['DateCreated', 'DateModified', 'DateUploadCompleted', 'DateUploadStarted']:
            pass
        elif rest_val != p_obj:                                
            print "REST API attribute '" + r_key + "' has value '" + str(rest_val) + "' doesn't match object value '" + str(p_obj) + "'"                            

    def classify_rest_item(self, r_val, p_val, r_key):
        """
        Determine the input REST item's type and call method to compare to input object
        """                                        
        if type(r_val) in [ int, str, bool, float, unicode]:                            
            self.compare_builtin_to_obj(r_val, p_val, r_key)
        elif type(r_val) == dict:            
            self.compare_dict_to_obj(r_val, p_val)
        elif type(r_val) == list:                                    
            self.compare_list_to_obj(r_val, p_val, r_key)
        else:
            print "REST API attribute'" + r_key + "' has an unrecognized attribute type"                            
        
    def test_rest_vs_sdk(self):
        """
        Compares REST API response and python SDK object for identify, for an API method
        """        
        sdk_obj = self.call_sdk()
        rest_obj = self.call_rest_api()                                                        
        # TODO passing Response here, SDK doesn't currently capture other items at this level (e.g. Notifications)
        if self.list_request:
            self.compare_list_to_obj(rest_obj['Response']['Items'], sdk_obj, "BASE")
        else:
            self.compare_dict_to_obj(rest_obj['Response'], sdk_obj)

    def call_rest_api(self):
        """
        Call the REST API for this object
        """
        return self.api.callAPI(self.rest_path, self.rest_method, queryParams=self.qp, postData=self.postData, headerParams=self.headerParams)

    def create_pickle_from_sdk(self, pickle_path):
        """
        Stores a pickled object in the provided path (include file name) for the object returned for this SDK method
        """
        sdk_obj = self.call_sdk()        
        with open(pickle_path, 'w') as f:
            Pickle.dump(sdk_obj, f)
            
    def get_pickle(self, pickle_path):
        """
        Retrieves a pickled object from the provided path (include file name), for this API test
        """        
        with open(pickle_path, 'r') as f:
            sdk_obj = Pickle.load(f)
        return sdk_obj        
        
    def test_rest_vs_pickle(self, pickle_path):
        """
        Compares REST API response and a stored object for identify, for an API method
        """
        p_obj = self.get_pickle(pickle_path)
        rest_obj = self.call_rest_api()
        self.compare_dict_to_obj(rest_obj['Response'], p_obj)
예제 #2
0
class BaseAPI(object):
    '''
    Parent class for BaseSpaceAPI and BillingAPI classes
    '''
    def __init__(self,
                 AccessToken,
                 apiServerAndVersion,
                 userAgent,
                 timeout=10,
                 verbose=False):
        '''
        :param AccessToken: the current access token
        :param apiServerAndVersion: the api server URL with api version
        :param timeout: (optional) the timeout in seconds for each request made, default 10 
        :param verbose: (optional) prints verbose output, default False
        '''
        self.apiClient = APIClient(AccessToken,
                                   apiServerAndVersion,
                                   userAgent=userAgent,
                                   timeout=timeout)
        self.verbose = verbose

    def __json_print__(self, label, var):
        try:
            prefix = " " * len(label)
            var_list = json.dumps(var,
                                  indent=4).split('\n')  # ,ensure_ascii=False
            print((label + var_list[0]))
            if len(var_list) > 1:
                print(("\n".join([prefix + s for s in var_list[1:]])))
        except UnicodeDecodeError:
            pass  # we could disable ascii-enforcing, as shown above, but
            # this will massively increase the volume of logs

    def __singleRequest__(self,
                          myModel,
                          resourcePath,
                          method,
                          queryParams,
                          headerParams,
                          postData=None,
                          forcePost=False):
        '''
        Call a REST API and deserialize response into an object, handles errors from server.
        
        :param myModel: a Response object that includes a 'Response' swaggerType key with a value for the model type to return
        :param resourcePath: the api url path to call (without server and version)
        :param method: the REST method type, eg. GET
        :param queryParams: a dictionary of query parameters
        :param headerParams: a dictionary of header parameters
        :param postData: (optional) data to POST, default None
        :param version: (optional) print detailed output, default False
        :param forcePost: (optional) use a POST call with pycurl instead of urllib, default False (used only when POSTing with no post data?)

        :raises ServerResponseException: if server returns an error or has no response
        :returns: an instance of the Response model from the provided myModel
        '''
        if self.verbose:
            print("")
            print(("* " + inspect.stack()[1][3] + "  (" + str(method) +
                   ")"))  # caller
            print(('    # Path:      ' + str(resourcePath)))
            print(('    # QPars:     ' + str(queryParams)))
            print(('    # Hdrs:      ' + str(headerParams)))
            print(('    # forcePost: ' + str(forcePost)))
            self.__json_print__('    # postData:  ', postData)
        response = self.apiClient.callAPI(resourcePath,
                                          method,
                                          queryParams,
                                          postData,
                                          headerParams,
                                          forcePost=forcePost)
        if self.verbose:
            self.__json_print__('    # Response:  ', response)
        if not response:
            raise ServerResponseException('No response returned')
        if 'ResponseStatus' in response:
            if 'ErrorCode' in response['ResponseStatus']:
                raise ServerResponseException(
                    str(response['ResponseStatus']['ErrorCode'] + ": " +
                        response['ResponseStatus']['Message']))
            elif 'Message' in response['ResponseStatus']:
                raise ServerResponseException(
                    str(response['ResponseStatus']['Message']))
        elif 'ErrorCode' in response:
            raise ServerResponseException(response["MessageFormatted"])

        responseObject = self.apiClient.deserialize(response, myModel)
        if hasattr(responseObject, "Response"):
            return responseObject.Response
        else:
            return responseObject

    def __listRequest__(self, myModel, resourcePath, method, queryParams,
                        headerParams):
        '''
        Call a REST API that returns a list and deserialize response into a list of objects of the provided model.
        Handles errors from server.

        :param myModel: a Model type to return a list of
        :param resourcePath: the api url path to call (without server and version)
        :param method: the REST method type, eg. GET
        :param queryParams: a dictionary of query parameters
        :param headerParams: a dictionary of header parameters

        :raises ServerResponseException: if server returns an error or has no response        
        :returns: a list of instances of the provided model
        '''
        if self.verbose:
            print("")
            print(("* " + inspect.stack()[1][3] + "  (" + str(method) +
                   ")"))  # caller
            print(('    # Path:      ' + str(resourcePath)))
            print(('    # QPars:     ' + str(queryParams)))
            print(('    # Hdrs:      ' + str(headerParams)))
        response = self.apiClient.callAPI(resourcePath, method, queryParams,
                                          None, headerParams)
        if self.verbose:
            self.__json_print__('    # Response:  ', response)
        if not response:
            raise ServerResponseException('No response returned')
        if 'ErrorCode' in response['ResponseStatus']:
            raise ServerResponseException(
                str(response['ResponseStatus']['ErrorCode'] + ": " +
                    response['ResponseStatus']['Message']))
        elif 'Message' in response['ResponseStatus']:
            raise ServerResponseException(
                str(response['ResponseStatus']['Message']))

        respObj = self.apiClient.deserialize(response,
                                             ListResponse.ListResponse)
        return [
            self.apiClient.deserialize(c, myModel)
            for c in respObj._convertToObjectList()
        ]

    def __makeCurlRequest__(self, data, url):
        '''
        Make a curl POST request
        
        :param data: data to post (eg. list of tuples of form (key, value))
        :param url: url to post data to
        
        :raises ServerResponseException: if server returns an error or has no response
        :returns: dictionary of api server response
        '''
        # pycurl is hard to get working, so best to cauterise it into only the functions where it is needed
        import pycurl
        post = urllib.parse.urlencode(data)
        response = io.StringIO()
        c = pycurl.Curl()
        c.setopt(pycurl.URL, url)
        c.setopt(pycurl.POST, 1)
        c.setopt(pycurl.POSTFIELDS, post)
        c.setopt(c.WRITEFUNCTION, response.write)
        c.perform()
        c.close()
        respVal = response.getvalue()
        if not respVal:
            raise ServerResponseException("No response from server")
        obj = json.loads(respVal)
        if 'error' in obj:
            raise ServerResponseException(
                str(obj['error'] + ": " + obj['error_description']))
        return obj

    def getTimeout(self):
        '''
        Returns the timeout in seconds for each request made
        '''
        return self.apiClient.timeout

    def setTimeout(self, time):
        '''
        Specify the timeout in seconds for each request made
        
        :param time: timeout in seconds
        '''
        self.apiClient.timeout = time

    def getAccessToken(self):
        '''
        Returns the current access token. 
        '''
        return self.apiClient.apiKey

    def setAccessToken(self, token):
        '''
        Sets the current access token.
                
        :param token: an access token
        '''
        self.apiClient.apiKey = token
예제 #3
0
class BaseAPI(object):
    '''
    Parent class for BaseSpaceAPI and BillingAPI classes
    '''
    def __init__(self, AccessToken, apiServerAndVersion, timeout=10):
        '''
        :param AccessToken: the current access token
        :param apiServerAndVersion: the api server URL with api version
        :param timeout: (optional) the timeout in seconds for each request made, default 10 
        '''
        self.apiClient = APIClient(AccessToken, apiServerAndVersion, timeout=timeout)

    def __singleRequest__(self, myModel, resourcePath, method, queryParams, headerParams, postData=None, verbose=False, forcePost=False):
        '''
        Call a REST API and deserialize response into an object, handles errors from server.
        
        :param myModel: a Response object that includes a 'Response' swaggerType key with a value for the model type to return
        :param resourcePath: the api url path to call (without server and version)
        :param method: the REST method type, eg. GET
        :param queryParams: a dictionary of query parameters
        :param headerParams: a dictionary of header parameters
        :param postData: (optional) data to POST, default None
        :param version: (optional) print detailed output, default False
        :param forcePost: (optional) use a POST call with pycurl instead of urllib, default False (used only when POSTing with no post data?)
        :param verbose: (optional) prints verbose output, default False

        :raises ServerResponseException: if server returns an error or has no response        
        :returns: an instance of the Response model from the provided myModel
        '''
        if verbose: 
            print '    # Path: ' + str(resourcePath)
            print '    # QPars: ' + str(queryParams)
            print '    # Hdrs: ' + str(headerParams)
            print '    # forcePost: ' + str(forcePost)             
        response = self.apiClient.callAPI(resourcePath, method, queryParams, postData, headerParams, forcePost=forcePost)
        if verbose: 
            print '    # Response: '            
            pprint(response)
        if not response: 
            raise ServerResponseException('No response returned')                
        if response['ResponseStatus'].has_key('ErrorCode'):
            raise ServerResponseException(str(response['ResponseStatus']['ErrorCode'] + ": " + response['ResponseStatus']['Message']))
        elif response['ResponseStatus'].has_key('Message'):
            raise ServerResponseException(str(response['ResponseStatus']['Message']))
                 
        responseObject = self.apiClient.deserialize(response, myModel)
        return responseObject.Response

    def __listRequest__(self, myModel, resourcePath, method, queryParams, headerParams, verbose=False):
        '''
        Call a REST API that returns a list and deserialize response into a list of objects of the provided model.
        Handles errors from server.

        :param myModel: a Model type to return a list of
        :param resourcePath: the api url path to call (without server and version)
        :param method: the REST method type, eg. GET
        :param queryParams: a dictionary of query parameters
        :param headerParams: a dictionary of header parameters
        :param verbose: (optional) prints verbose output, default False

        :raises ServerResponseException: if server returns an error or has no response        
        :returns: a list of instances of the provided model
        '''                
        if verbose: 
            print '    # Path: ' + str(resourcePath)
            print '    # QPars: ' + str(queryParams)
            print '    # Hdrs: ' + str(headerParams)
        response = self.apiClient.callAPI(resourcePath, method, queryParams, None, headerParams)
        if verbose:
            print '    # Response: '             
            pprint(response)
        if not response: 
            raise ServerResponseException('No response returned')
        if response['ResponseStatus'].has_key('ErrorCode'):
            raise ServerResponseException(str(response['ResponseStatus']['ErrorCode'] + ": " + response['ResponseStatus']['Message']))
        elif response['ResponseStatus'].has_key('Message'):
            raise ServerResponseException(str(response['ResponseStatus']['Message']))
        
        respObj = self.apiClient.deserialize(response, ListResponse.ListResponse)
        return [self.apiClient.deserialize(c, myModel) for c in respObj._convertToObjectList()]

    def __makeCurlRequest__(self, data, url):
        '''
        Make a curl POST request
        
        :param data: data to post (eg. list of tuples of form (key, value))
        :param url: url to post data to
        
        :raises ServerResponseException: if server returns an error or has no response
        :returns: dictionary of api server response
        '''
        post = urllib.urlencode(data)
        response = cStringIO.StringIO()
        c = pycurl.Curl()
        c.setopt(pycurl.URL,url)
        c.setopt(pycurl.POST, 1)
        c.setopt(pycurl.POSTFIELDS, post)
        c.setopt(c.WRITEFUNCTION, response.write)
        c.perform()
        c.close()
        respVal = response.getvalue()
        if not respVal:
            raise ServerResponseException("No response from server")
        obj = json.loads(respVal)
        if obj.has_key('error'):
            raise ServerResponseException(str(obj['error'] + ": " + obj['error_description']))
        return obj      

    def getTimeout(self):
        '''
        Returns the timeout in seconds for each request made
        '''
        return self.apiClient.timeout

    def setTimeout(self, time):
        '''
        Specify the timeout in seconds for each request made
        
        :param time: timeout in seconds
        '''        
        self.apiClient.timeout = time
        
    def getAccessToken(self):
        '''
        Returns the current access token. 
        '''        
        return self.apiClient.apiKey        

    def setAccessToken(self, token):
        '''
        Sets the current access token.
                
        :param token: an access token
        '''
        self.apiClient.apiKey = token            
예제 #4
0
class BaseAPI(object):
    '''
    Parent class for BaseSpaceAPI and BillingAPI classes
    '''
    def __init__(self, AccessToken, apiServerAndVersion, timeout=10):
        '''
        :param AccessToken: the current access token
        :param apiServerAndVersion: the api server URL with api version
        :param timeout: (optional) the timeout in seconds for each request made, default 10 
        '''
        self.apiClient = APIClient(AccessToken,
                                   apiServerAndVersion,
                                   timeout=timeout)

    def __singleRequest__(self,
                          myModel,
                          resourcePath,
                          method,
                          queryParams,
                          headerParams,
                          postData=None,
                          verbose=False,
                          forcePost=False):
        '''
        Call a REST API and deserialize response into an object, handles errors from server.
        
        :param myModel: a Response object that includes a 'Response' swaggerType key with a value for the model type to return
        :param resourcePath: the api url path to call (without server and version)
        :param method: the REST method type, eg. GET
        :param queryParams: a dictionary of query parameters
        :param headerParams: a dictionary of header parameters
        :param postData: (optional) data to POST, default None
        :param version: (optional) print detailed output, default False
        :param forcePost: (optional) use a POST call with pycurl instead of urllib, default False (used only when POSTing with no post data?)
        :param verbose: (optional) prints verbose output, default False

        :raises ServerResponseException: if server returns an error or has no response        
        :returns: an instance of the Response model from the provided myModel
        '''
        if verbose:
            print '    # Path: ' + str(resourcePath)
            print '    # QPars: ' + str(queryParams)
            print '    # Hdrs: ' + str(headerParams)
            print '    # forcePost: ' + str(forcePost)
        response = self.apiClient.callAPI(resourcePath,
                                          method,
                                          queryParams,
                                          postData,
                                          headerParams,
                                          forcePost=forcePost)
        if verbose:
            print '    # Response: '
            pprint(response)
        if not response:
            raise ServerResponseException('No response returned')
        if response['ResponseStatus'].has_key('ErrorCode'):
            raise ServerResponseException(
                str(response['ResponseStatus']['ErrorCode'] + ": " +
                    response['ResponseStatus']['Message']))
        elif response['ResponseStatus'].has_key('Message'):
            raise ServerResponseException(
                str(response['ResponseStatus']['Message']))

        responseObject = self.apiClient.deserialize(response, myModel)
        return responseObject.Response

    def __listRequest__(self,
                        myModel,
                        resourcePath,
                        method,
                        queryParams,
                        headerParams,
                        verbose=False):
        '''
        Call a REST API that returns a list and deserialize response into a list of objects of the provided model.
        Handles errors from server.

        :param myModel: a Model type to return a list of
        :param resourcePath: the api url path to call (without server and version)
        :param method: the REST method type, eg. GET
        :param queryParams: a dictionary of query parameters
        :param headerParams: a dictionary of header parameters
        :param verbose: (optional) prints verbose output, default False

        :raises ServerResponseException: if server returns an error or has no response        
        :returns: a list of instances of the provided model
        '''
        if verbose:
            print '    # Path: ' + str(resourcePath)
            print '    # QPars: ' + str(queryParams)
            print '    # Hdrs: ' + str(headerParams)
        response = self.apiClient.callAPI(resourcePath, method, queryParams,
                                          None, headerParams)
        if verbose:
            print '    # Response: '
            pprint(response)
        if not response:
            raise ServerResponseException('No response returned')
        if response['ResponseStatus'].has_key('ErrorCode'):
            raise ServerResponseException(
                str(response['ResponseStatus']['ErrorCode'] + ": " +
                    response['ResponseStatus']['Message']))
        elif response['ResponseStatus'].has_key('Message'):
            raise ServerResponseException(
                str(response['ResponseStatus']['Message']))

        respObj = self.apiClient.deserialize(response,
                                             ListResponse.ListResponse)
        return [
            self.apiClient.deserialize(c, myModel)
            for c in respObj._convertToObjectList()
        ]

    def __makeCurlRequest__(self, data, url):
        '''
        Make a curl POST request
        
        :param data: data to post (eg. list of tuples of form (key, value))
        :param url: url to post data to
        
        :raises ServerResponseException: if server returns an error or has no response
        :returns: dictionary of api server response
        '''
        post = urllib.urlencode(data)
        response = cStringIO.StringIO()
        c = pycurl.Curl()
        c.setopt(pycurl.URL, url)
        c.setopt(pycurl.POST, 1)
        c.setopt(pycurl.POSTFIELDS, post)
        c.setopt(c.WRITEFUNCTION, response.write)
        c.perform()
        c.close()
        respVal = response.getvalue()
        if not respVal:
            raise ServerResponseException("No response from server")
        obj = json.loads(respVal)
        if obj.has_key('error'):
            raise ServerResponseException(
                str(obj['error'] + ": " + obj['error_description']))
        return obj

    def getTimeout(self):
        '''
        Returns the timeout in seconds for each request made
        '''
        return self.apiClient.timeout

    def setTimeout(self, time):
        '''
        Specify the timeout in seconds for each request made
        
        :param time: timeout in seconds
        '''
        self.apiClient.timeout = time

    def getAccessToken(self):
        '''
        Returns the current access token. 
        '''
        return self.apiClient.apiKey

    def setAccessToken(self, token):
        '''
        Sets the current access token.
                
        :param token: an access token
        '''
        self.apiClient.apiKey = token
예제 #5
0
class TestSDK(object):
    '''
    Compares objects from BaseSpace REST API to SDK objects, including pickled objects
    '''
    def __init__(self):

        self.qp = {}
        self.rest_method = 'GET'
        self.postData = None
        self.headerParams = None
        self.list_request = False

        # TODO change to unit_tests, but need to add projects/run to account?
        self.myAPI = BaseSpaceAPI(profile="ps_native_hoth")
        self.api = APIClient(self.myAPI.getAccessToken(), self.myAPI.apiServer)

    def compare_dict_to_obj(self, rest_dict, p_obj):
        """
        Compare a dictionary from a REST API response and a SDK object for identity.
        """
        for r_key, r_val in six.iteritems(rest_dict):
            # confirm that the key from REST api exists in stored object
            try:
                p_val = getattr(p_obj, r_key)
            except AttributeError:
                print("REST API attribute '" + r_key +
                      "' doesn't exist in object")
            else:
                self.classify_rest_item(r_val, p_val, r_key)

    def compare_list_to_obj(self, rest_list, p_obj, r_key):
        """
        Compare a list from a REST API response and an SDK object for identity.
        """
        if type(p_obj) != list:
            print("Attribute '" + r_key +
                  "' is a list in the REST API but not in the object")
        elif len(p_obj) != len(rest_list):
            print("Attribute '" + r_key +
                  "' has different list length between REST API and object")
        else:
            for r_val, p_val in map(None, rest_list, p_obj):
                self.classify_rest_item(r_val, p_val, r_key)

    def compare_builtin_to_obj(self, rest_val, p_obj, r_key):
        """
        Compare a built-in type from a REST API response and an SDK object for identity.
        """
        # convert unicode to ascii for comparisons
        if isinstance(rest_val, six.text_type):
            rest_val = rest_val.encode('ascii', 'ignore')
        # don't compare values for datetimes
        if r_key in [
                'DateCreated', 'DateModified', 'DateUploadCompleted',
                'DateUploadStarted'
        ]:
            pass
        elif rest_val != p_obj:
            print("REST API attribute '" + r_key + "' has value '" +
                  str(rest_val) + "' doesn't match object value '" +
                  str(p_obj) + "'")

    def classify_rest_item(self, r_val, p_val, r_key):
        """
        Determine the input REST item's type and call method to compare to input object
        """
        if type(r_val) in [int, str, bool, float, six.text_type]:
            self.compare_builtin_to_obj(r_val, p_val, r_key)
        elif type(r_val) == dict:
            self.compare_dict_to_obj(r_val, p_val)
        elif type(r_val) == list:
            self.compare_list_to_obj(r_val, p_val, r_key)
        else:
            print("REST API attribute'" + r_key +
                  "' has an unrecognized attribute type")

    def test_rest_vs_sdk(self):
        """
        Compares REST API response and python SDK object for identify, for an API method
        """
        sdk_obj = self.call_sdk()
        rest_obj = self.call_rest_api()
        # TODO passing Response here, SDK doesn't currently capture other items at this level (e.g. Notifications)
        if self.list_request:
            self.compare_list_to_obj(rest_obj['Response']['Items'], sdk_obj,
                                     "BASE")
        else:
            self.compare_dict_to_obj(rest_obj['Response'], sdk_obj)

    def call_rest_api(self):
        """
        Call the REST API for this object
        """
        return self.api.callAPI(self.rest_path,
                                self.rest_method,
                                queryParams=self.qp,
                                postData=self.postData,
                                headerParams=self.headerParams)

    def create_pickle_from_sdk(self, pickle_path):
        """
        Stores a pickled object in the provided path (include file name) for the object returned for this SDK method
        """
        sdk_obj = self.call_sdk()
        with open(pickle_path, 'w') as f:
            Pickle.dump(sdk_obj, f)

    def get_pickle(self, pickle_path):
        """
        Retrieves a pickled object from the provided path (include file name), for this API test
        """
        with open(pickle_path, 'r') as f:
            sdk_obj = Pickle.load(f)
        return sdk_obj

    def test_rest_vs_pickle(self, pickle_path):
        """
        Compares REST API response and a stored object for identify, for an API method
        """
        p_obj = self.get_pickle(pickle_path)
        rest_obj = self.call_rest_api()
        self.compare_dict_to_obj(rest_obj['Response'], p_obj)
예제 #6
0
class BaseAPI(object):
    """
    Parent class for BaseSpaceAPI and BillingAPI classes
    """

    def __init__(self, AccessToken, apiServerAndVersion, userAgent, timeout=10, verbose=False):
        """
        :param AccessToken: the current access token
        :param apiServerAndVersion: the api server URL with api version
        :param timeout: (optional) the timeout in seconds for each request made, default 10 
        :param verbose: (optional) prints verbose output, default False
        """
        self.apiClient = APIClient(AccessToken, apiServerAndVersion, userAgent=userAgent, timeout=timeout)
        self.verbose = verbose

    def __json_print__(self, label, var):
        try:
            prefix = " " * len(label)
            var_list = json.dumps(var, indent=4).split("\n")  # ,ensure_ascii=False
            print label + var_list[0]
            if len(var_list) > 1:
                print "\n".join([prefix + s for s in var_list[1:]])
        except UnicodeDecodeError:
            pass  # we could disable ascii-enforcing, as shown above, but
            # this will massively increase the volume of logs

    def __singleRequest__(
        self, myModel, resourcePath, method, queryParams, headerParams, postData=None, forcePost=False
    ):
        """
        Call a REST API and deserialize response into an object, handles errors from server.
        
        :param myModel: a Response object that includes a 'Response' swaggerType key with a value for the model type to return
        :param resourcePath: the api url path to call (without server and version)
        :param method: the REST method type, eg. GET
        :param queryParams: a dictionary of query parameters
        :param headerParams: a dictionary of header parameters
        :param postData: (optional) data to POST, default None
        :param version: (optional) print detailed output, default False
        :param forcePost: (optional) use a POST call with pycurl instead of urllib, default False (used only when POSTing with no post data?)

        :raises ServerResponseException: if server returns an error or has no response
        :returns: an instance of the Response model from the provided myModel
        """
        if self.verbose:
            print ""
            print "* " + inspect.stack()[1][3] + "  (" + str(method) + ")"  # caller
            print "    # Path:      " + str(resourcePath)
            print "    # QPars:     " + str(queryParams)
            print "    # Hdrs:      " + str(headerParams)
            print "    # forcePost: " + str(forcePost)
            self.__json_print__("    # postData:  ", postData)
        response = self.apiClient.callAPI(
            resourcePath, method, queryParams, postData, headerParams, forcePost=forcePost
        )
        if self.verbose:
            self.__json_print__("    # Response:  ", response)
        if not response:
            raise ServerResponseException("No response returned")
        if response.has_key("ResponseStatus"):
            if response["ResponseStatus"].has_key("ErrorCode"):
                raise ServerResponseException(
                    str(response["ResponseStatus"]["ErrorCode"] + ": " + response["ResponseStatus"]["Message"])
                )
            elif response["ResponseStatus"].has_key("Message"):
                raise ServerResponseException(str(response["ResponseStatus"]["Message"]))
        elif response.has_key("ErrorCode"):
            raise ServerResponseException(response["MessageFormatted"])

        responseObject = self.apiClient.deserialize(response, myModel)
        if hasattr(responseObject, "Response"):
            return responseObject.Response
        else:
            return responseObject

    def __listRequest__(self, myModel, resourcePath, method, queryParams, headerParams):
        """
        Call a REST API that returns a list and deserialize response into a list of objects of the provided model.
        Handles errors from server.

        :param myModel: a Model type to return a list of
        :param resourcePath: the api url path to call (without server and version)
        :param method: the REST method type, eg. GET
        :param queryParams: a dictionary of query parameters
        :param headerParams: a dictionary of header parameters

        :raises ServerResponseException: if server returns an error or has no response        
        :returns: a list of instances of the provided model
        """
        if self.verbose:
            print ""
            print "* " + inspect.stack()[1][3] + "  (" + str(method) + ")"  # caller
            print "    # Path:      " + str(resourcePath)
            print "    # QPars:     " + str(queryParams)
            print "    # Hdrs:      " + str(headerParams)
        response = self.apiClient.callAPI(resourcePath, method, queryParams, None, headerParams)
        if self.verbose:
            self.__json_print__("    # Response:  ", response)
        if not response:
            raise ServerResponseException("No response returned")
        if response["ResponseStatus"].has_key("ErrorCode"):
            raise ServerResponseException(
                str(response["ResponseStatus"]["ErrorCode"] + ": " + response["ResponseStatus"]["Message"])
            )
        elif response["ResponseStatus"].has_key("Message"):
            raise ServerResponseException(str(response["ResponseStatus"]["Message"]))

        respObj = self.apiClient.deserialize(response, ListResponse.ListResponse)
        return [self.apiClient.deserialize(c, myModel) for c in respObj._convertToObjectList()]

    def __makeCurlRequest__(self, data, url):
        """
        Make a curl POST request
        
        :param data: data to post (eg. list of tuples of form (key, value))
        :param url: url to post data to
        
        :raises ServerResponseException: if server returns an error or has no response
        :returns: dictionary of api server response
        """
        # pycurl is hard to get working, so best to cauterise it into only the functions where it is needed
        import pycurl

        post = urllib.urlencode(data)
        response = cStringIO.StringIO()
        c = pycurl.Curl()
        c.setopt(pycurl.URL, url)
        c.setopt(pycurl.POST, 1)
        c.setopt(pycurl.POSTFIELDS, post)
        c.setopt(c.WRITEFUNCTION, response.write)
        c.perform()
        c.close()
        respVal = response.getvalue()
        if not respVal:
            raise ServerResponseException("No response from server")
        obj = json.loads(respVal)
        if obj.has_key("error"):
            raise ServerResponseException(str(obj["error"] + ": " + obj["error_description"]))
        return obj

    def getTimeout(self):
        """
        Returns the timeout in seconds for each request made
        """
        return self.apiClient.timeout

    def setTimeout(self, time):
        """
        Specify the timeout in seconds for each request made
        
        :param time: timeout in seconds
        """
        self.apiClient.timeout = time

    def getAccessToken(self):
        """
        Returns the current access token. 
        """
        return self.apiClient.apiKey

    def setAccessToken(self, token):
        """
        Sets the current access token.
                
        :param token: an access token
        """
        self.apiClient.apiKey = token