def _create_api_uri(self, *parts): """Internal helper for creating fully qualified endpoint URIs.""" return urljoin(self.BASE_API_URI, '/'.join(imap(quote, parts)))
def load(self, value, key=None, store=True, account=None, **kwargs): # It's useful to keep track of account objects because the API doesn't # include this information. if account is None: account = self.account if isinstance(value, dict): # API responses may included JSON representations of the API models. # When this is the case, they are automatically transformed into more # specific model objects. The key of the JSON representation is used to # determine which model. model_class = _key_to_model.get(key, None) # Some API endpoints directly return the JSON representation of one of # our models. In this case, that model class is returned instead of a # generic APIObject. The keys of the API response are used to determine # which model is being returned. If the model cannot be determined from # the keys, which happens when the response does not directly represent a # model (for instance, such as when it includes pagination information), # the result will be a generic APIObject. if not model_class and isinstance(value, dict): obj_keys = set(six.iterkeys(value)) for keys, model in six.iteritems(_obj_keys_to_model): if keys <= obj_keys: model_class = model break # If the response doesn't match a particular object, use a generic type. model_class = model_class or APIObject # Some API endpoint responses are nested in such a way that provides no # benefit to the user. If necessary, this unnests the response. unnester = _unnesters.get(key, None) if unnester: value = unnester(value) # Move the key-value pairs of the current value being loaded to the # appropriate APIObject or subclass. instance = model_class(self.api_client, account=account, **kwargs) for k, v in six.iteritems(value): instance.load(value=v, key=k, store=True, account=account, **kwargs) value = instance elif isinstance(value, list): # If the value to be loaded is a list, then load each object within it. # `store` is set to `False` so that the result is accessible to the # current context, which is responsible for storing the result. value = list( imap( partial(self.load, key=key, store=False, account=account, **kwargs), value)) # If store == False, then the value should be returned to the calling # context. If key == None, then value is the top-most API object, which # should be returned to the calling code. If they are both true,`value` # should be stored in the current context under `key`. if store and key: self[key] = value return None return value