def update_query(self, model):
        """
        Create the update query
        """

        query = self.UPDATE(self.TABLE_NAME(model.STORE, schema=model.SCHEMA))

        if model._action == "retrieve" and model._record._action == "update":

            self.update_record(model._record, model._record.mass({}), query)

        elif model._id:

            if model._mode == "many":
                raise relations.ModelError(model, "only one update query at a time")

            self.update_record(model._record, model._record.update({}), query)

            query.WHERE(**{model._fields._names[model._id].store: model[model._id]})

        else:

            raise relations.ModelError(model, "nothing to update from")

        self.retrieve_record(model._record, query)

        return query
    def retrieve(self, model, verify=True, query=None):
        """
        Executes the retrieve
        """

        cursor = self.connection.cursor()

        if query is None:
            query = self.retrieve_query(model)

        query.generate()

        cursor.execute(query.sql, tuple(query.args))

        if model._mode == "one" and cursor.rowcount > 1:
            raise relations.ModelError(model, "more than one retrieved")

        if model._mode == "one" and model._role != "child":

            if cursor.rowcount < 1:

                if verify:
                    raise relations.ModelError(model, "none retrieved")
                return None

            model._record = model._build("update",
                                         _read=self.values_retrieve(
                                             model, cursor.fetchone()))

        else:

            model._models = []

            while len(model._models) < cursor.rowcount:
                model._models.append(
                    model.__class__(
                        _read=self.values_retrieve(model, cursor.fetchone())))

            if model._limit is not None:
                model.overflow = model.overflow or len(
                    model._models) >= model._limit

            model._record = None

        model._action = "update"

        cursor.close()

        return model
Example #3
0
    def retrieve(self, model, verify=True):
        """
        Executes the retrieve
        """

        model._collate()

        body = {"filter": {}}
        self.retrieve_record(model._record, body["filter"])

        if model._like:
            body["filter"]["like"] = model._like

        if model._sort:
            body["sort"] = model._sort

        if model._limit is not None:
            body["limit"] = {"per_page": model._limit}
            if model._offset:
                body["limit"]["start"] = model._offset

        matches = self.result(model, model.PLURAL, self.session.get(f"{self.url}/{model.ENDPOINT}", json=body))

        if model._mode == "one" and len(matches) > 1:
            raise relations.ModelError(model, "more than one retrieved")

        if model._mode == "one" and model._role != "child":

            if len(matches) < 1:

                if verify:
                    raise relations.ModelError(model, "none retrieved")
                return None

            model._record = model._build("update", _read=matches[0])

        else:

            model._models = []

            for match in matches:
                model._models.append(model.__class__(_read=match))

            model._record = None

        model._action = "update"

        return model
Example #4
0
    def relative_field(cls, model, relative):
        """
        Returns the name of the relative field, based on the relative name
        """

        # Check for the standard convention

        standard = f"{model.NAME}_id"

        if standard in relative._fields:
            return standard

        # Check to see if we're using the relative.ID, model.ID, model.relative_ID convention (diffent name for ID)

        model_id = model._field_name(model.ID)

        simple = f"{model.NAME}_{model_id}"

        if simple in relative._fields:
            return simple

        # Check to see if we're using the relative.relative_id, model.model_id, model.relative_id patten

        if model_id in relative._fields and (cls.SAME or model_id != relative._field_name(relative.ID)):
            return model_id

        raise relations.ModelError(model, f"cannot determine field for {model.NAME} in {relative.NAME}")
Example #5
0
    def delete(self, model):
        """
        Executes the delete
        """

        criteria = {}

        if model._action == "retrieve":

            self.retrieve_record(model._record, criteria)

        elif model._id:

            criterion = f"{model._id}__in"
            criteria[criterion] = []

            for deleting in model._each():
                criteria[criterion].append(deleting[model._id])
                deleting._action = "create"

            model._action = "create"

        else:

            raise relations.ModelError(model, "nothing to delete from")

        return self.result(model, "deleted", self.session.delete(f"{self.url}/{model.ENDPOINT}", json={"filter": criteria}))
    def result(model, key, response):
        """
        Checks a response and returns the result
        """

        if response.status_code >= 400:
            raise relations.ModelError(
                model,
                response.json().get("message", "API Error"))

        return response.json()[key]
    def model_retrieve(self, model, verify=True):
        """
        Executes the retrieve
        """

        model._collate()

        criteria = {}
        self.record_retrieve(model._record, criteria)

        matches = self.result(
            model, model.PLURAL,
            self.session.get(f"{self.url}/{model.ENDPOINT}",
                             json={"filter": criteria}))

        if model._mode == "one" and len(matches) > 1:
            raise relations.ModelError(model, "more than one retrieved")

        if model._mode == "one" and model._role != "child":

            if len(matches) < 1:

                if verify:
                    raise relations.ModelError(model, "none retrieved")
                return None

            model._record = model._build("update", _read=matches[0])

        else:

            model._models = []

            for match in matches:
                model._models.append(model.__class__(_read=match))

            model._record = None

        model._action = "update"

        return model
Example #8
0
    def result(model, key, response):
        """
        Checks a response and returns the result
        """

        if response.status_code >= 400:
            raise relations.ModelError(model, response.json().get("message", "API Error"))

        body = response.json()

        if "overflow" in body:
            model.overflow = model.overflow or body["overflow"]

        return body[key]
    def model_update(self, model):
        """
        Executes the update
        """

        # If the overall model is retrieving and the record has values set

        updated = 0

        if model._action == "retrieve" and model._record._action == "update":

            criteria = {}
            self.record_retrieve(model._record, criteria)

            values = {}
            self.record_update(model._record, values, changed=True)

            updated += self.result(
                model, "updated",
                self.session.patch(f"{self.url}/{model.ENDPOINT}",
                                   json={
                                       "filter": criteria,
                                       model.PLURAL: values
                                   }))

        elif model._id:

            for updating in model._each("update"):

                values = {}
                self.record_update(updating._record, values)

                updated += self.result(
                    updating, "updated",
                    self.session.patch(
                        f"{self.url}/{model.ENDPOINT}/{updating[model._id]}",
                        json={model.SINGULAR: values}))

                for parent_child in updating.CHILDREN:
                    if updating._children.get(parent_child):
                        updating._children[parent_child].create().update()

        else:

            raise relations.ModelError(model, "nothing to update from")

        return updated
    def create_query(self, model):
        """
        Get query for what's being inserted
        """

        fields = [field.store for field in model._fields._order if not field.auto and not field.inject]
        query = self.INSERT(self.TABLE_NAME(model.STORE, schema=model.SCHEMA), *fields)

        if not model._bulk and model._id is not None and model._fields._names[model._id].auto:
            if model._mode == "many":
                raise relations.ModelError(model, "only one create query at a time")
            return copy.deepcopy(query).VALUES(**model._record.create({})).bind(model)

        for creating in model._each("create"):
            query.VALUES(**creating._record.create({}))

        return query
    def update(self, model, query=None):
        """
        Executes the update
        """

        cursor = self.connection.cursor()

        updated = 0

        # If the overall model is retrieving and the record has values set

        if model._action == "retrieve" and model._record._action == "update":

            update_query = query or self.update_query(model)

            update_query.generate()
            cursor.execute(update_query.sql, update_query.args)
            updated = cursor.rowcount

        elif model._id:

            for updating in model._each("update"):

                update_query = query or self.update_query(updating)

                if update_query.SET:

                    update_query.generate()
                    cursor.execute(update_query.sql, update_query.args)

                for parent_child in updating.CHILDREN:
                    if updating._children.get(parent_child):
                        updating._children[parent_child].create().update()

                updated += cursor.rowcount

        else:

            raise relations.ModelError(model, "nothing to update from")

        return updated
    def delete_query(self, model):
        """
        Create the update query
        """

        query = self.DELETE(self.TABLE_NAME(model.STORE, schema=model.SCHEMA))

        if model._action == "retrieve":

            self.retrieve_record(model._record, query)

        elif model._id:

            ids = []
            store = model._fields._names[model._id].store
            for deleting in model._each():
                ids.append(deleting[model._id])
            query.WHERE(**{f"{store}__in": ids})

        else:

            raise relations.ModelError(model, "nothing to delete from")

        return query
Example #13
0
 def broken():
     raise relations.ModelError(Simple(), "broken query")
Example #14
0
 def missing():
     raise relations.ModelError(Simple(), "none retrieved")
Example #15
0
    def test___str__(self):

        error = relations.ModelError(Whoops(), "adaisy")

        self.assertEqual(str(error), "whoops: adaisy")
Example #16
0
    def test___init__(self):

        error = relations.ModelError("unittest", "oops")

        self.assertEqual(error.model, "unittest")
        self.assertEqual(error.message, "oops")