Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reimplement how we return responses #7

Open
amitsaha opened this issue Dec 18, 2017 · 1 comment
Open

Reimplement how we return responses #7

amitsaha opened this issue Dec 18, 2017 · 1 comment

Comments

@amitsaha
Copy link
Contributor

amitsaha commented Dec 18, 2017

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

@gabrnavarro
Copy link
Contributor

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants