Coverage for src/prisma/errors.py: 92%
98 statements
« prev ^ index » next coverage.py v7.2.7, created at 2024-08-27 18:25 +0000
« prev ^ index » next coverage.py v7.2.7, created at 2024-08-27 18:25 +0000
1from __future__ import annotations
3from typing import Any, Optional
5__all__ = (
6 'PrismaError',
7 'DataError',
8 'UniqueViolationError',
9 'ForeignKeyViolationError',
10 'MissingRequiredValueError',
11 'RawQueryError',
12 'TableNotFoundError',
13 'RecordNotFoundError',
14 'HTTPClientClosedError',
15 'ClientNotConnectedError',
16 'PrismaWarning',
17 'UnsupportedSubclassWarning',
18)
21class PrismaError(Exception):
22 pass
25class ClientNotRegisteredError(PrismaError):
26 def __init__(self) -> None:
27 super().__init__('No client instance registered; You must call prisma.register(prisma.Prisma())')
30class ClientAlreadyRegisteredError(PrismaError):
31 def __init__(self) -> None:
32 super().__init__('A client has already been registered.')
35class ClientNotConnectedError(PrismaError):
36 def __init__(self) -> None:
37 super().__init__(
38 'Client is not connected to the query engine, ' 'you must call `connect()` before attempting to query data.'
39 )
42class HTTPClientClosedError(PrismaError):
43 def __init__(self) -> None:
44 super().__init__('Cannot make a request from a closed client.')
47class UnsupportedDatabaseError(PrismaError):
48 context: str
49 database: str
51 def __init__(self, database: str, context: str) -> None:
52 super().__init__(f'{context} is not supported by {database}')
53 self.database = database
54 self.context = context
57class DataError(PrismaError):
58 data: Any
59 code: Any
60 meta: Any
62 def __init__(self, data: Any, *, message: Optional[str] = None) -> None:
63 self.data = data
65 user_facing_error = data.get('user_facing_error', {})
66 self.code = user_facing_error.get('error_code')
67 self.meta = user_facing_error.get('meta')
69 message = message or user_facing_error.get('message')
70 super().__init__(message or 'An error occurred while processing data.')
73class UniqueViolationError(DataError):
74 pass
77class ForeignKeyViolationError(DataError):
78 pass
81class MissingRequiredValueError(DataError):
82 pass
85class RawQueryError(DataError):
86 def __init__(self, data: Any) -> None:
87 try:
88 super().__init__(data, message=data['user_facing_error']['meta']['message'])
89 except KeyError:
90 super().__init__(data)
93class TableNotFoundError(DataError):
94 def __init__(self, data: Any) -> None:
95 super().__init__(data)
96 self.table: Optional[str] = self.meta.get('table')
99class FieldNotFoundError(DataError):
100 # currently we cannot easily resolve the erroneous field as Prisma
101 # returns different results for unknown fields in different situations
102 # e.g. root query, nested query and mutation queries
103 def __init__(self, data: Any, *, message: str | None = None) -> None:
104 if message is None: 104 ↛ 117line 104 didn't jump to line 117, because the condition on line 104 was never false
105 meta = data.get('user_facing_error', {}).get('meta', {})
106 if meta.get('kind') == 'Union':
107 error = _pick_union_error(meta.get('errors', []))
108 else:
109 error = meta
111 argument_path = error.get('argumentPath')
112 selection_path = error.get('selectionPath')
114 if argument_path:
115 message = f'Could not find field at `{".".join(selection_path)}.{".".join(argument_path)}`'
117 super().__init__(data, message=message)
120class RecordNotFoundError(DataError):
121 pass
124class InputError(DataError):
125 pass
128class TransactionError(PrismaError):
129 pass
132class TransactionExpiredError(TransactionError):
133 pass
136class TransactionNotStartedError(TransactionError):
137 def __init__(self) -> None:
138 super().__init__(
139 'Transaction has not been started yet.\n'
140 'Transactions must be used within a context manager or started manually.'
141 )
144class BuilderError(PrismaError):
145 pass
148class InvalidModelError(BuilderError):
149 def __init__(self, model: type) -> None:
150 super().__init__(f'Expected the {model} type to have a `__prisma_model__` class variable set')
153class UnknownModelError(BuilderError):
154 def __init__(self, model: str) -> None:
155 super().__init__(f'Model: "{model}" does not exist.')
158class UnknownRelationalFieldError(BuilderError):
159 def __init__(self, model: str, field: str) -> None:
160 super().__init__(f'Field: "{field}" either does not exist or is not a relational field on the {model} model')
163class GeneratorError(PrismaError):
164 pass
167class UnsupportedListTypeError(GeneratorError):
168 type: str
170 def __init__(self, typ: str) -> None:
171 super().__init__(
172 f'Cannot use {typ} as a list yet; Please create a '
173 'feature request at https://github.com/RobertCraigie/prisma-client-py/issues/new'
174 )
175 self.type = typ
178class PrismaWarning(Warning):
179 pass
182# Note: this is currently unused but not worth removing
183class UnsupportedSubclassWarning(PrismaWarning):
184 pass
187# TODO: proper types
188def _pick_union_error(errors: list[Any]) -> Any:
189 # Note: uses the same heuristic as the TS client
190 return max(
191 errors,
192 key=lambda e: (len(e.get('argumentPath', [])) + len(e.get('selectionPath'))),
193 )