3
\$\begingroup\$

Let's suppose that there's a third part web service and I want to make a GET request to it and use the response to feed my project's service.

Next code will allow me to create a dict object only with non-falsy keys' values:

import requests
from abc import ABC, abstractmethod


class AbstractPayload(dict, ABC):
    def __new__(cls, *args, **kwargs):
        """Validate: values are not empty and that each key in kwargs exists
        in cls.fields iterable, then it creates and returns the final dict
        instance using the field and the value as key-value pairs."""
        return {
            field: v for field, v in kwargs.items() if v and field in cls.fields
        }

    @property
    @abstractmethod
    def fields(cls):
        """Valid fields' iterable. Override this as you need."""
        pass


class UpdatePayload(AbstractPayload):
    fields = ('location', 'capacity', 'maxlatency', 'tags')


# Usage example:
response = requests.get('/thirdpart/device/189')
if response.ok:
    requests.patch('/mydevices/33', json=UpdatePayload(**response.json()))

Summary:

  • Avoiding unwanted fields being added to the endpoint patch payload.
  • Having a unique block of code (__new__ method) where the properties are gonna be evaluated to discard falsy values.
  • Making it easily adaptable to all the api resources (just inheriting from a class and defining a fields iterable)

Questions:

  • What do you think about this approach?
  • Do you have any suggestions to improve it?
  • Or even better, Do you have another cleaner approach?
\$\endgroup\$
2
\$\begingroup\$
            field: v for field, v in kwargs.items() if v and field in cls.fields

Feel free to break that into a multi-line comprehension.

Note that the in has linear cost w.r.t. len(cls.fields).

    """Valid fields' iterable. Override this as you need."""
    pass

Consider specifying that it shall be a set rather than just an iterable. (Also, I suppose return None would more clearly show that by default we don't return an iterable. Or consider doing an explicit raise.)

\$\endgroup\$
  • \$\begingroup\$ what happens if the API sends the fields in a different order \$\endgroup\$ – PirateApp Jun 26 '18 at 0:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.