Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
duedil-python / duedil / models / base.py
Size: Mime:
from __future__ import unicode_literals

import six
from importlib import import_module

from ..api import api_client


class Model(object):
    attribute_names = None
    id = None
    path = None
    related_models = None
    parent_model = None

    def __init__(self, id=None, parent_model=None, load=False, **kwargs):

        if self.attribute_names:
            for allowed in self.attribute_names:
                if not hasattr(self, allowed):
                    self.__setattr__(allowed, None)

        self.id = id
        self.parent_model = parent_model

        if load:
            self.load()

        if kwargs:
            self.update(**kwargs)

    def __getattribute__(self, name):
        try:
            return super(Model, self).__getattribute__(name)
        except AttributeError:
            key = name.replace('_', '-')
            if (self.related_models and key in self.related_models.keys()):
                return self.load_related(key,
                                         self.related_models[key])
            raise

    def load(self):
        result = api_client.get(self.endpoint)
        if result and 'response' in result:
            self.update(**result['response'])

    def update(self, **data):
        for k, v in six.iteritems(data):
            if k in self.attribute_names:
                self.__setattr__(k, v)

    @property
    def endpoint(self):
        if not self.path:
            raise ValueError(
                "{model} does not have a path to load specified".format(
                    model=self.__class__.__name__))
        endpoint = self.path
        if self.id:
            endpoint += '/{id}'.format(id=self.id)

        if self.parent_model:

            par_endpoint = self.parent_model.endpoint

            endpoint = "{parent}/{child}".format(parent=par_endpoint,
                                                 child=endpoint)
        return endpoint

    def load_related(self, key, klass=None):
        internal_key = '_' + key.replace('-', '_')

        related = getattr(self, internal_key, None)

        if related is None:
            uri = '{endpoint}/{model}'.format(endpoint=self.endpoint,
                                              model=key)
            result = api_client.get(uri)
            if result:
                response = result['response']
                related = None

                if klass and isinstance(klass, six.string_types):
                    klass = getattr(import_module('.models', 'duedil'), klass)

                if (
                    'data' in response and
                    isinstance(response['data'], (list, tuple))
                ):
                    related = []
                    for r in result['response']['data']:
                        related.append(
                            klass(**r) if klass else r)
                elif response:
                    related = klass(**response) if klass else response
                setattr(self, internal_key, related)
        return related