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.")
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))
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))
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
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]]
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]] = {}
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))
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)
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)
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)
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()
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))
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)
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)
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)
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)})
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
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)
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
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)
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)
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)
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]] = {}
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)
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)
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)
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
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)
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
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)