Skip to main content

Introducing Core Libraries in Python

· 7 min read

APIMatic has introduced core libraries to provide a stable runtime that powers all functionality of our SDKs. In this release, we have revamped our Python SDKs to improve the code quality and provide better test coverage.

Refer to Introducing core libraries in APIMatic generated SDKs changelog to understand the importance of core libraries in our SDKs.

Details

The SDKs generated by APIMatic contain utility code that helps the Python SDK make API calls. This utility code may be involved in but is not limited to:

  • Creating HTTP requests from user data
  • Deserializing API responses to class instances
  • Handling various API request states and errors
  • API authentication
  • Validating user and server data
  • Functionality such as File streaming and JSON pass-through

While the SDKs we generate use third-party or standard libraries to do most of the heavy lifting, we noticed that SDKs still need a lot of utility code to handle the ever-growing functionalities mentioned above. This required us to make a few changes in our SDKs.

What Has Changed?

The python SDK is now as lightweight as possible so that the user has access to only the relevant components of the SDK. To achieve this, we have created the following three libraries as dependencies.

  1. apimatic-core
  2. apimatic-core-interfaces
  3. apimatic-requests-client-adapter

Core Libraries Package

APIMatic now supports the entire SDK through the core libraries package which acts as the heart of the SDK functionality. Each function that the SDK was responsible for before has now been moved to this package. The core libraries contains completely refactored utilities that follow best practices for Python and easy-to-maintain code. Moreover, each component of the core libraries is thoroughly tested to ensure maximum performance and stability. The two main components of these libraries are the core libraries and their unit tests that are designed to work coherently.

Some important component of these libraries are:

API Call Classes

NameDescription
RequestBuilderA builder class used to build an API request.
APICallA class used to create an API Call object.
ResponseHandlerUsed to handle response returned by the server.

Configurations

NameDescription
EndpointConfigurationA class that holds possible configurations of an endpoint.
GlobalConfigurationA class that holds global configuration properties to make a successful API call.

HTTP

NameDescription
HttpCallBackA factory class to create an HTTP response.
HttpClientConfigurationA class used for configuring the SDK by a user.
HttpRequestA class which contains information about the HTTP response.
ApiResponseA wrapper class for API response.
HttpresponseA class which contains information about the HTTP response.

Core Interfaces Package

Alongside the core libraries, we have also introduced core interfaces as one of the key dependencies of Python SDKs. These core interfaces act as an abstract layer to the core libraries.

The important components of these core interfaces dependencies are:

Interfaces

NameDescription
HttpClientTo save both Request and Response after the completion of response.
ResponseFactoryTo create a Response.
AuthenticationTo setup methods for authentication.

Enumerations

NameDescription
HttpMethodEnumEnumeration containing HTTP methods.

The basic aim for the introduction of this dependency is to ensure that any changes required in the future can be smoothly carried out without any breaking changes. Therefore, it will ensure the scalability of the functioning of the core libraries as well as the SDK in the future.

Request Client Package

The Python SDK relies on the requests library for making an HTTP call. Previously, the SDK contained the client implementation for sending an HTTP request through this module. With the introduction of the core libraries, the request client implementation has been moved to another package which will be added as a dependency in the SDK. This client is a simple and clean implementation of the same functionalities that the SDK previously implemented. Moreover, we now have support for unit tests in the client as well to ensure the reliability of the component.

The supported methods of the request-client module are:

MethodDescription
create_default_http_clientCreate a default HTTP client.
force_retriesReset retries according to each request.
executeExecute a given HttpRequest to get a string response back.
convert_responseConverts the response object of the CoreHttpClient into a CoreHttpResponse object.

It is worth mentioning here that this will help APIMatic to support different requesting libraries present in Python without any significant breaking changes to the SDK itself, hence ensuring reliable scalability.

Cleaner and Leaner SDK

Python SDK is now compact and easy to understand. All utilities have been moved to the core libraries and all responsibilities for the request creation and response handling also lie with the core libraries. This has improved the readability of the SDK manifolds, hence improving the user experience.

Easy to Call Endpoint

Consider the example below extracted from our Tester SDK for an endpoint that does a POST request.

The code before the introduction of core libraries looked like this:

def send_unix_date_time(self, datetime):

# Validate required parameters
self.validate_parameters(datetime=datetime)

# Prepare query URL
_url_path = '/body/unixdatetime'
_query_builder = self.config.get_base_uri()
_query_builder += _url_path
_query_url = APIHelper.clean_url(_query_builder)

# Prepare headers
_headers = {
'accept': 'application/json',
'content-type': 'text/plain; charset=utf-8'
}

# Prepare and execute request
_request = self.config.http_client.post(_query_url, headers=_headers, parameters=str(APIHelper.when_defined(APIHelper.UnixDateTime, datetime)))
_response = self.execute_request(_request)

# Endpoint and global error handling using HTTP status codes.
if _response.status_code == 404:
return None
self.validate_response(_response)

decoded = APIHelper.json_deserialize(_response.text, ServerResponse.from_dictionary)

return decoded

And the same endpoint after the core libraries implementation looks like this:

def send_unix_date_time(self, datetime):

return super().new_api_call_builder.request(
RequestBuilder().server(Server.DEFAULT)
.path('/body/unixdatetime')
.http_method(HttpMethodEnum.POST)
.header_param(Parameter()
.key('accept').value('application/json'))
.header_param(Parameter()
.key('content-type').value('text/plain; charset=utf-8'))
.body_param(Parameter()
.value(str(APIHelper.when_defined(APIHelper.UnixDateTime, datetime)))
.is_required(True))
).response(
ResponseHandler()
.is_nullify404(True)
.deserializer(APIHelper.json_deserialize)
.deserialize_into(ServerResponse.from_dictionary)
.is_api_response(True)
.convertor(ApiResponse.create)
).execute()

The code above asks the Request builder to set the server, URL path, header, and body params ( or any other type of parameters) along with if they are required or not. Then it asks the response handler to set the parameters of the response, the deserializer, and the custom type to deserialize the response into, and then convert it into an API response in the end. Finally, it calls the execute method from the library to make the request. And that is it. You will have your API call completed.

As you can see, the code for an endpoint has drastically decreased and all the repeated pre-processing has been eliminated. Method changing has been introduced to make the endpoint code concise and easy to read.

The test runner for the unit test has been changed to Pytest from Nose as Nose has dropped its support for newer python versions. For more information please read the changelog. The functionality of the tests remains the same.

The Unchanged Parts

Amongst all these changes, Python SDKs still contain all parts that are set by the user in the API specification. These parts include:

  1. User set configurations
    • The server
    • Environments
  2. Custom types
    • Models
    • Enums
    • Exceptions
note

There are no functional or breaking changes in the Python SDK. The imports and code samples will also remain the same and will function without any breakages.