freelancer-sdk-python icon indicating copy to clipboard operation
freelancer-sdk-python copied to clipboard

Reimplement how we return responses

Open amitsaha opened this issue 8 years ago • 1 comments

Currently we return responses from the various functions as ad-hoc custom classes which are dynamically created based on what we get from the API.

I think this needs to be improved. Look at other SDKs and see what they do and see if we can adopt it.

TBD

amitsaha avatar Dec 18 '17 14:12 amitsaha

SDK Return Types

  1. mobolic/facebook-sdk Functions in this SDK mostly return dictionaries decoded from JSONs like so:
try:
    response = self.session.request(
        method or "GET",
        FACEBOOK_GRAPH_URL + path,
        timeout=self.timeout,
        params=args,
        data=post_args,
        proxies=self.proxies,
        files=files)
    except requests.HTTPError as e:
        response = json.loads(e.read())
        raise GraphAPIError(response)

This is similar to some of our SDK functions that do not wrap the return values in a class.

  1. Azure/azure-sdk-for-python The Azure sdk is really large and has a lot of modules, but follow a consistent structure throughout the codebase. Each module contains a models/ folder, which contains classes inherited from a base Model class and contain a dictionary named _attribute_map, which contains the data fetched from their api. API results are wrapped inside these Model classes. Each module also has an operations/ folder, which contain Operations() classes. These classes are made according to responsibility, and contain methods that are relevant to their respective functions . Request data are serialized before sending to the server, and deserialized into the appropriate Model before returning to the user. They also have raw flags for returning results in raw JSON format.
if response.status_code == 200:
            deserialized = self._deserialize('RecordSet', response)

        if raw:
            client_raw_response = ClientRawResponse(deserialized, response)
            return client_raw_response

        return deserialized
  1. boto/boto3 a.k.a. AWS SDK for Python Boto3 also uses Model classes that provide a layer of abstraction from raw JSON. These classes are used to create Resource classes by the ResourceFactory. One model that is most relevant to is the ResourceModel, which is used to contain data and to represent a resource. Example Model:
class ResourceModel(object):
    """
    A model representing a resource, defined via a JSON description
    format. A resource has identifiers, attributes, actions,
    sub-resources, references and collections. For more information
    on resources, see :ref:`guide_resources`.
    :type name: string
    :param name: The name of this resource, e.g. ``sqs`` or ``Queue``
    :type definition: dict
    :param definition: The JSON definition
    :type resource_defs: dict
    :param resource_defs: All resources defined in the service
    """

Creating resources from resource models using the ResourceFactory class:

class ResourceFactory(object):
    """
    A factory to create new :py:class:`~boto3.resources.base.ServiceResource`
    classes from a :py:class:`~boto3.resources.model.ResourceModel`. There are
    two types of lookups that can be done: one on the service itself (e.g. an
    SQS resource) and another on models contained within the service (e.g. an
    SQS Queue resource).
    """
    def load_from_definition(self, resource_name,
                             single_resource_json_definition, service_context):
        ...
        ...
        resource_model = ResourceModel(
            resource_name, single_resource_json_definition,
            service_context.resource_json_definitions
        )
        ...
        ...
        # Load attributes into the resource model
        self._load_attributes(
            attrs=attrs, meta=meta, resource_name=resource_name,
            resource_model=resource_model,
            service_context=service_context)
        ...

This kind of structure may not be the best for our SDK because we do not have a lot of Model types to benefit from this kind of abstraction. Having Models to abstract away JSON types are good enough for our use case and would allow for easier developing.

gabrnavarro avatar Mar 05 '18 14:03 gabrnavarro