Пример #1
0
    def to_python_value(self, value: Any) -> BaseGeometry:
        if value is None or isinstance(value, BaseGeometry):
            return value

        if not isinstance(value, (bytes, str)):
            raise FieldError(f'Invalid type: "{type(value)}", expected "bytes or str".')

        if isinstance(value, bytes):
            try:
                return shapely.wkb.loads(value)
            except WKBReadingError as exc:
                raise OperationalError("Could not parse the provided data.") from exc

        try:
            int(value, 16)  # Prevents "ParseException: Invalid HEX char."
            return shapely.wkb.loads(value, hex=True)
        except (ValueError, WKBReadingError):
            pass

        try:
            return shapely.wkt.loads(value)
        except WKTReadingError:
            pass

        raise OperationalError("Could not parse the provided data.")
Пример #2
0
    async def add(self, *instances, using_db=None) -> None:
        """
        Adds one or more of ``instances`` to the relation.

        If it is already added, it will be silently ignored.
        """
        if not instances:
            return
        if not self.instance._saved_in_db:
            raise OperationalError(
                f"You should first call .save() on {self.instance}")
        db = using_db if using_db else self.model._meta.db
        pk_formatting_func = type(self.instance)._meta.pk.to_db_value
        related_pk_formatting_func = type(instances[0])._meta.pk.to_db_value
        through_table = Table(self.field.through)
        select_query = (db.query_class.from_(through_table).where(
            getattr(through_table, self.field.backward_key) ==
            pk_formatting_func(self.instance.pk, self.instance)).select(
                self.field.backward_key, self.field.forward_key))
        query = db.query_class.into(through_table).columns(
            getattr(through_table, self.field.forward_key),
            getattr(through_table, self.field.backward_key),
        )

        if len(instances) == 1:
            criterion = getattr(
                through_table,
                self.field.forward_key) == related_pk_formatting_func(
                    instances[0].pk, instances[0])
        else:
            criterion = getattr(through_table, self.field.forward_key).isin(
                [related_pk_formatting_func(i.pk, i) for i in instances])

        select_query = select_query.where(criterion)

        # TODO: This is highly inefficient. Should use UNIQUE index by default.
        #  And optionally allow duplicates.
        already_existing_relations_raw = await db.execute_query(
            str(select_query))
        already_existing_relations = {(
            pk_formatting_func(r[self.field.backward_key], self.instance),
            related_pk_formatting_func(r[self.field.forward_key],
                                       self.instance),
        )
                                      for r in already_existing_relations_raw}

        insert_is_required = False
        for instance_to_add in instances:
            if not instance_to_add._saved_in_db:
                raise OperationalError(
                    f"You should first call .save() on {instance_to_add}")
            pk_f = related_pk_formatting_func(instance_to_add.pk,
                                              instance_to_add)
            pk_b = pk_formatting_func(self.instance.pk, self.instance)
            if (pk_b, pk_f) in already_existing_relations:
                continue
            query = query.insert(pk_f, pk_b)
            insert_is_required = True
        if insert_is_required:
            await db.execute_query(str(query))
Пример #3
0
    async def add(self, *instances, using_db=None) -> None:
        """
        Adds one or more of ``instances`` to the relation.

        If it is already added, it will be silently ignored.
        """
        if not instances:
            return
        if self.instance.pk is None:
            raise OperationalError(
                "You should first call .save() on {model}".format(
                    model=self.instance))
        db = using_db if using_db else self.model._meta.db
        pk_formatting_func = type(self.instance)._meta.pk.to_db_value
        related_pk_formatting_func = type(instances[0])._meta.pk.to_db_value
        through_table = Table(self.field.through)
        select_query = (db.query_class.from_(through_table).where(
            getattr(through_table, self.field.backward_key) ==
            pk_formatting_func(self.instance.pk, self.instance)).select(
                self.field.backward_key, self.field.forward_key))
        query = db.query_class.into(through_table).columns(
            getattr(through_table, self.field.forward_key),
            getattr(through_table, self.field.backward_key),
        )

        if len(instances) == 1:
            criterion = getattr(
                through_table,
                self.field.forward_key) == related_pk_formatting_func(
                    instances[0].pk, instances[0])
        else:
            criterion = getattr(through_table, self.field.forward_key).isin(
                [related_pk_formatting_func(i.pk, i) for i in instances])

        select_query = select_query.where(criterion)

        already_existing_relations_raw = await db.execute_query(
            str(select_query))
        already_existing_relations = {(r[self.field.backward_key],
                                       r[self.field.forward_key])
                                      for r in already_existing_relations_raw}

        insert_is_required = False
        for instance_to_add in instances:
            if instance_to_add.pk is None:
                raise OperationalError(
                    "You should first call .save() on {model}".format(
                        model=instance_to_add))
            if (self.instance.pk,
                    instance_to_add.pk) in already_existing_relations:
                continue
            query = query.insert(
                related_pk_formatting_func(instance_to_add.pk,
                                           instance_to_add),
                pk_formatting_func(self.instance.pk, self.instance),
            )
            insert_is_required = True
        if insert_is_required:
            await db.execute_query(str(query))
Пример #4
0
 def __init__(self, *args, join_type=AND, **kwargs) -> None:
     if args and kwargs:
         raise OperationalError(
             'You can pass only Q nodes or filter kwargs in one Q node')
     if not all(isinstance(node, Q) for node in args):
         raise OperationalError('All ordered arguments must be Q nodes')
     self.children = args
     self.filters = kwargs
     if join_type not in {self.AND, self.OR}:
         raise OperationalError('join_type must be AND or OR')
     self.join_type = join_type
Пример #5
0
 def __init__(self, *args: 'Q', join_type=AND, **kwargs) -> None:
     if args and kwargs:
         raise OperationalError(
             'You can pass only Q nodes or filter kwargs in one Q node')
     if not all(isinstance(node, Q) for node in args):
         raise OperationalError('All ordered arguments must be Q nodes')
     self.children = args  # type: Tuple[Q, ...]
     self.filters = kwargs  # type: Mapping[str, Any]
     if join_type not in {self.AND, self.OR}:
         raise OperationalError('join_type must be AND or OR')
     self.join_type = join_type
     self._is_negated = False
     self._annotations = {}  # type: Mapping[str, Any]
     self._custom_filters = {}  # type: Mapping[str, Mapping[str, Any]]
Пример #6
0
 def __init__(self, *args: "Q", join_type=AND, **kwargs) -> None:
     if args and kwargs:
         raise OperationalError(
             "You can pass only Q nodes or filter kwargs in one Q node")
     if not all(isinstance(node, Q) for node in args):
         raise OperationalError("All ordered arguments must be Q nodes")
     self.children: Tuple[Q, ...] = args
     self.filters: Dict[str, Any] = kwargs
     if join_type not in {self.AND, self.OR}:
         raise OperationalError("join_type must be AND or OR")
     self.join_type = join_type
     self._is_negated = False
     self._annotations: Dict[str, Any] = {}
     self._custom_filters: Dict[str, Dict[str, Any]] = {}
Пример #7
0
    async def remove(self,
                     *instances: MODEL,
                     using_db: "Optional[BaseDBAsyncClient]" = None) -> None:
        """
        Removes one or more of ``instances`` from the relation.

        :raises OperationalError: remove() was called with no instances.
        """
        db = using_db if using_db else self.model._meta.db
        if not instances:
            raise OperationalError("remove() called on no instances")
        through_table = Table(self.field.through)
        pk_formatting_func = type(self.instance)._meta.pk.to_db_value
        related_pk_formatting_func = type(instances[0])._meta.pk.to_db_value

        if len(instances) == 1:
            condition = (getattr(
                through_table,
                self.field.forward_key) == related_pk_formatting_func(
                    instances[0].pk, instances[0])) & (
                        getattr(through_table, self.field.backward_key)
                        == pk_formatting_func(self.instance.pk, self.instance))
        else:
            condition = (getattr(
                through_table, self.field.backward_key) == pk_formatting_func(
                    self.instance.pk, self.instance)) & (getattr(
                        through_table, self.field.forward_key).isin([
                            related_pk_formatting_func(i.pk, i)
                            for i in instances
                        ]))
        query = db.query_class.from_(through_table).where(condition).delete()
        await db.execute_query(str(query))
Пример #8
0
 async def translate_exceptions_(self, *args):
     try:
         return await func(self, *args)
     except asyncpg.SyntaxOrAccessError as exc:
         raise OperationalError(exc)
     except asyncpg.IntegrityConstraintViolationError as exc:
         raise IntegrityError(exc)
Пример #9
0
 async def wrapped(self, query, *args):
     try:
         return await func(self, query, *args)
     except asyncpg.exceptions.SyntaxOrAccessError as exc:
         raise OperationalError(exc)
     except asyncpg.exceptions.IntegrityConstraintViolationError as exc:
         raise IntegrityError(exc)
Пример #10
0
    def __init__(self, *args, **kwargs) -> None:
        # self._meta is a very common attribute lookup, lets cache it.
        meta = self._meta

        # Create basic fk/m2m objects
        is_new = 'id' not in kwargs

        for key in meta.backward_fk_fields:
            field_object = meta.fields_map[key]
            setattr(self, key,
                    RelationQueryContainer(field_object.type,
                                           field_object.relation_field, self,
                                           is_new))  # type: ignore

        for key in meta.m2m_fields:
            field_object = meta.fields_map[key]
            setattr(
                self,
                key,
                ManyToManyRelationManager(  # type: ignore
                    field_object.type, self, field_object, is_new))

        # Assign values and do type conversions
        passed_fields = set(kwargs.keys())
        passed_fields.update(meta.fetch_fields)

        for key, value in kwargs.items():
            if key in meta.fk_fields:
                if hasattr(value, 'id') and not value.id:
                    raise OperationalError(
                        'You should first call .save() on {} before referring to it'
                        .format(value))
                relation_field = '{}_id'.format(key)
                setattr(self, relation_field, value.id)
                passed_fields.add(relation_field)
            elif key in meta.fields:
                field_object = meta.fields_map[key]
                if value is None and not field_object.null:
                    raise ValueError(
                        '{} is non nullable field, but null was passed'.format(
                            key))
                setattr(self, key, field_object.to_python_value(value))
            elif key in meta.db_fields:
                setattr(self, meta.fields_db_projection_reverse[key], value)
            elif key in meta.backward_fk_fields:
                raise ConfigurationError(
                    'You can\'t set backward relations through init, change related model instead'
                )
            elif key in meta.m2m_fields:
                raise ConfigurationError(
                    'You can\'t set m2m relations through init, use m2m_manager instead'
                )

        # Assign defaults for missing fields
        for key in meta.fields.difference(passed_fields):
            field_object = meta.fields_map[key]
            if callable(field_object.default):
                setattr(self, key, field_object.default())
            else:
                setattr(self, key, field_object.default)
Пример #11
0
 async def bound_to_fall():
     saved_event = await Tournament.filter(name="Test").first()
     self.assertEqual(saved_event.id, tournament.id)
     await Tournament.filter(id=tournament.id).update(name="Updated name")
     saved_event = await Tournament.filter(name="Updated name").first()
     self.assertEqual(saved_event.id, tournament.id)
     raise OperationalError()
Пример #12
0
    def resolve_for_queryset(self, queryset: "QuerySet") -> None:
        """
        Called internally to generate prefetching query.

        :param queryset: Custom QuerySet to use for prefetching.
        :raises OperationalError: If field does not exist in model.
        """
        relation_split = self.relation.split("__")
        first_level_field = relation_split[0]
        if first_level_field not in queryset.model._meta.fetch_fields:
            raise OperationalError(
                f"relation {first_level_field} for {queryset.model._meta.db_table} not found"
            )
        forwarded_prefetch = "__".join(relation_split[1:])
        if forwarded_prefetch:
            if first_level_field not in queryset._prefetch_map.keys():
                queryset._prefetch_map[first_level_field] = set()
            queryset._prefetch_map[first_level_field].add(
                Prefetch(forwarded_prefetch,
                         self.queryset,
                         to_attr=self.to_attr))
        else:
            queryset._prefetch_queries.setdefault(first_level_field,
                                                  []).append((self.to_attr,
                                                              self.queryset))
Пример #13
0
 async def wrapped(self, query, *args):
     try:
         return await func(self, query, *args)
     except sqlite3.OperationalError as exc:
         raise OperationalError(exc)
     except sqlite3.IntegrityError as exc:
         raise IntegrityError(exc)
Пример #14
0
 def __or__(self, other: "Q") -> "Q":
     """
     Returns a binary OR of Q objects, use ``OR`` operator.
     """
     if not isinstance(other, Q):
         raise OperationalError("OR operation requires a Q node")
     return Q(self, other, join_type=self.OR)
Пример #15
0
 def __and__(self, other: "Q") -> "Q":
     """
     Returns a binary AND of Q objects, use ``AND`` operator.
     """
     if not isinstance(other, Q):
         raise OperationalError("AND operation requires a Q node")
     return Q(self, other, join_type=self.AND)
Пример #16
0
 def _query(self) -> "QuerySet[MODEL]":
     if not self.instance._saved_in_db:
         raise OperationalError(
             "This objects hasn't been instanced, call .save() before calling related queries"
         )
     return self.model.filter(
         **{self.relation_field: getattr(self.instance, self.from_field)})
Пример #17
0
    def _set_result_for_query(self, sequence):
        # TODO: What does this do?
        for item in sequence:
            if not isinstance(item, self.model):
                OperationalError("{} is not of {}".format(item, self.model))

        self._fetched = True
        self.related_objects = sequence
Пример #18
0
 async def delete(self, using_db=None) -> None:
     db = using_db if using_db else self._meta.db
     if not self.id:
         raise OperationalError("Can't delete unpersisted record")
     await db.executor_class(
         model=self.__class__,
         db=db,
     ).execute_delete(self)
Пример #19
0
 async def finalize(self) -> None:
     if not self._old_context_value:
         raise OperationalError(
             "Finalize was called before transaction start")
     self._finalized = True
     self._current_transaction.set(self._old_context_value)
     await self._pool.release(self._connection)
     self._connection = None
Пример #20
0
 async def translate_exceptions_(self, *args):
     try:
         return await func(self, *args)
     except asyncpg.SyntaxOrAccessError as exc:
         raise OperationalError(exc)
     except asyncpg.IntegrityConstraintViolationError as exc:
         raise IntegrityError(exc)
     except asyncpg.InvalidTransactionStateError as exc:  # pragma: nocoverage
         raise TransactionManagementError(exc)
Пример #21
0
 async def wrapped(self, query, *args):
     try:
         return await func(self, query, *args)
     except (pymysql.err.OperationalError, pymysql.err.ProgrammingError,
             pymysql.err.DataError, pymysql.err.InternalError,
             pymysql.err.NotSupportedError) as exc:
         raise OperationalError(exc)
     except pymysql.err.IntegrityError as exc:
         raise IntegrityError(exc)
Пример #22
0
 async def execute_query(self, query):
     try:
         async with self.acquire_connection() as connection:
             self.log.debug(query)
             return await connection.fetch(query)
     except asyncpg.exceptions.SyntaxOrAccessError as exc:
         raise OperationalError(exc)
     except asyncpg.exceptions.IntegrityConstraintViolationError as exc:
         raise IntegrityError(exc)
Пример #23
0
 def __init__(self, *args: "Q", join_type: str = AND, **kwargs: Any) -> None:
     if args and kwargs:
         newarg = Q(join_type=join_type, **kwargs)
         args = (newarg,) + args
         kwargs = {}
     if not all(isinstance(node, Q) for node in args):
         raise OperationalError("All ordered arguments must be Q nodes")
     #: Contains the sub-Q's that this Q is made up of
     self.children: Tuple[Q, ...] = args
     #: Contains the filters applied to this Q
     self.filters: Dict[str, Any] = kwargs
     if join_type not in {self.AND, self.OR}:
         raise OperationalError("join_type must be AND or OR")
     #: Specifies if this Q does an AND or OR on its children
     self.join_type = join_type
     self._is_negated = False
     self._annotations: Dict[str, Any] = {}
     self._custom_filters: Dict[str, Dict[str, Any]] = {}
Пример #24
0
    async def delete(self, using_db=None) -> None:
        """
        Deletes the current model object.

        :raises OperationalError: If object has never been persisted.
        """
        db = using_db or self._meta.db
        if not self._saved_in_db:
            raise OperationalError("Can't delete unpersisted record")
        await db.executor_class(model=self.__class__, db=db).execute_delete(self)
Пример #25
0
    def __init__(self, *args, **kwargs) -> None:
        is_new = not bool(kwargs.get('id'))

        for key, field in self._meta.fields_map.items():
            if isinstance(field, fields.BackwardFKRelation):
                setattr(
                    self, key,
                    RelationQueryContainer(field.type, field.relation_field,
                                           self, is_new))
            elif isinstance(field, fields.ManyToManyField):
                setattr(
                    self, key,
                    ManyToManyRelationManager(field.type, self, field, is_new))
            elif isinstance(field, fields.Field):
                setattr(self, key, field.default)
            else:
                setattr(self, key, None)

        passed_fields = set(kwargs.keys())
        for key, value in kwargs.items():
            if key in self._meta.fk_fields:
                if hasattr(value, 'id') and not value.id:
                    raise OperationalError(
                        'You should first call .save() on {} before referring to it'
                        .format(value))
                relation_field = '{}_id'.format(key)
                setattr(self, relation_field, value.id)
                passed_fields.add(relation_field)
            elif key in self._meta.backward_fk_fields:
                raise ConfigurationError(
                    'You can\'t set backward relations through init, change related model instead'
                )
            elif key in self._meta.m2m_fields:
                raise ConfigurationError(
                    'You can\'t set m2m relations through init, use m2m_manager instead'
                )
            elif key in self._meta.fields:
                field_object = self._meta.fields_map[key]
                if value is None and not field_object.null:
                    raise ValueError(
                        '{} is non nullable field, but null was passed'.format(
                            key))
                setattr(self, key, field_object.to_python_value(value))
            elif key in self._meta.db_fields:
                setattr(self, self._meta.fields_db_projection_reverse[key],
                        value)

        for key, field_object in self._meta.fields_map.items():
            if key in passed_fields or key in self._meta.fetch_fields:
                continue
            else:
                if callable(field_object.default):
                    setattr(self, key, field_object.default())
                else:
                    setattr(self, key, field_object.default)
Пример #26
0
 async def translate_exceptions_(self, *args):
     try:
         return await func(self, *args)
     except (
         pymysql.err.OperationalError,
         pymysql.err.ProgrammingError,
         pymysql.err.DataError,
         pymysql.err.InternalError,
         pymysql.err.NotSupportedError,
     ) as exc:
         raise OperationalError(exc)
     except pymysql.err.IntegrityError as exc:
         raise IntegrityError(exc)
Пример #27
0
    def __init__(self, *args: "Q", join_type: Union[str, Callable] = AND, **kwargs) -> None:
        if args and kwargs:
            newarg = Q(join_type=join_type, **kwargs)
            args = (newarg,) + args
            kwargs = {}

        if not all(isinstance(node, Q) for node in args):
            raise OperationalError("All ordered arguments must be Q nodes")

        self.children: Tuple[Q, ...] = args
        self.filters: Dict[str, FieldFilter] = kwargs

        if join_type in self.join_type_map:
            join_type = self.join_type_map[join_type]

        if join_type not in {self.AND, self.OR}:
            raise OperationalError("join_type must be AND or OR")

        self.join_type: Callable = join_type
        self._is_negated = False

        self._check_annotations = True
Пример #28
0
 async def translate_exceptions_(self, *args):
     try:
         return await func(self, *args)
     except (
             pyodbc.OperationalError,
             pyodbc.ProgrammingError,
             pyodbc.DataError,
             pyodbc.InternalError,
             pyodbc.NotSupportedError,
             pyodbc.InterfaceError,
     ) as exc:
         raise OperationalError(exc)
     except (pyodbc.IntegrityError, pyodbc.Error) as exc:
         raise IntegrityError(exc)
Пример #29
0
 def resolve_for_queryset(self, queryset) -> None:
     relation_split = self.relation.split('__')
     first_level_field = relation_split[0]
     if first_level_field not in queryset.model._meta.fetch_fields:
         raise OperationalError('relation {} for {} not found'.format(
             first_level_field, queryset.model._meta.table))
     forwarded_prefetch = '__'.join(relation_split[1:])
     if forwarded_prefetch:
         if first_level_field not in queryset._prefetch_map.keys():
             queryset._prefetch_map[first_level_field] = set()
         queryset._prefetch_map[first_level_field].add(
             Prefetch(forwarded_prefetch, self.queryset))
     else:
         queryset._prefetch_queries[first_level_field] = self.queryset
Пример #30
0
    async def delete(self,
                     using_db: Optional[BaseDBAsyncClient] = None) -> None:
        """
        Deletes the current model object.

        :param using_db: Specific DB connection to use instead of default bound

        :raises OperationalError: If object has never been persisted.
        """
        db = using_db or self._meta.db
        if not self._saved_in_db:
            raise OperationalError("Can't delete unpersisted record")
        await db.executor_class(model=self.__class__,
                                db=db).execute_delete(self)