Esempio n. 1
0
    def defaults_for(self, command_type, data_type):
        """Provide default configuration for the given command and data type.

        This will use any wild card options first, overlaying more specific
        defaults as they are found.

        :param command_type: Type of modification (e.g. Types.UPSERT)
        :param data_type: Data type being modified
        :return: A dict of config
        """
        defaults = self._command_defaults

        config = {}

        wild = defaults.get(self.WILD_CARD, {})
        specific = defaults.get(CommandType(command_type), {})
        data_type = DataType(data_type)

        for container in (wild, specific):
            if self.WILD_CARD in container:
                config.update(container[self.WILD_CARD])

            if data_type in container:
                config.update(container[data_type])

        return config
Esempio n. 2
0
    def add_concrete_id(self, data_type, id_ref, concrete_id):
        """Add a concrete id for a reference.

        :data_type: Data type of the object being referenced
        :id_ref: The reference string
        :concrete_id: The real id
        """
        data_type = DataType(data_type)

        self._ref_to_concrete[data_type][id_ref] = concrete_id
Esempio n. 3
0
    def _command_defaults(self):
        config = defaultdict(dict)

        for command_type, data_type, defaults in self.raw["defaults"]:
            if command_type != self.WILD_CARD:
                command_type = CommandType(command_type)

            if data_type != self.WILD_CARD:
                data_type = DataType(data_type)

            config[command_type][data_type] = defaults

        return config
Esempio n. 4
0
    def _find_references(cls, body):
        """Search for references in the relationships of an object.

        :param body: Raw JSON API compatible data to search
        :return: A list of tuples with data type, reference, key and parent
        :rtype: Iterator[tuple]
        """

        for relationship in body["data"].get("relationships", {}).values():
            relationship = relationship["data"]
            if not isinstance(relationship["id"], dict):
                continue

            id_ref = relationship["id"].get(cls.REF_KEY)
            yield (DataType(relationship["type"]), id_ref, "id", relationship)
Esempio n. 5
0
    def body(self):
        """Get the appropriate body object for this command.

        :return: A different class depending on `DataType` and `data_classes`
        :raise UnsupportedOperationError: If no type can be found for the
                                          given `DataType`
        """
        body = super().body

        data_type = DataType(body["data"]["type"])

        try:
            # pylint: disable=unsubscriptable-object
            # It's subscriptable if child classes have set it to a dict
            class_ = self.data_classes[data_type]

        except KeyError:
            raise UnsupportedOperationError("Invalid action on data type")

        # Don't validate this all the time, we did it on the way in. If we have
        # mutated it it might not match the schema we except from clients, but
        # it's still valid
        return class_(body, validate=False)
Esempio n. 6
0
 def _get_concrete_id(self, data_type, id_ref):
     data_type = DataType(data_type)
     try:
         return self._ref_to_concrete[data_type][id_ref]
     except KeyError:
         raise UnpopulatedReferenceError(data_type, id_ref)