Contextlib пытается изменить «замороженное» исключениеPython

Программы на Python
Ответить
Anonymous
 Contextlib пытается изменить «замороженное» исключение

Сообщение Anonymous »

После некоторых обновлений Dependabot у меня возникла странная ошибка в pytest.
В моем случае она вызвана несуществующим исключением корзины MinIO.
Ни одно из обновлений, сделанных Dependabot, не было в MinIO или Python (но «pytest-asyncio» был обновлен до версии 1.2).
Некоторые части журнала ошибок:
> raise response_error
E minio.error.S3Error: S3 operation failed; code: NoSuchBucket, message: Volume not found, resource: None, request_id: None, host_id: None

/Users/ar/Library/Caches/pypoetry/virtualenvs/classifier-api-cL9y8buz-py3.13/lib/python3.13/site-packages/minio/api.py:427: S3Error

During handling of the above exception, another exception occurred:

self = , typ =
value = S3Error(response=, code='NoSuchBucket', message='Volume not found', resource=None, request_id=None, host_id=None, bucket_name=None, object_name=None)
traceback =

def __exit__(self, typ, value, traceback):

Я думаю, что значимая часть ошибки — это последний бит:
except BaseException as exc:
# only re-raise if it's *not* the exception that was
# passed to throw(), because __exit__() must not raise
# an exception unless __exit__() itself failed. But throw()
# has to raise the exception to signal propagation, so this
# fixes the impedance mismatch between the throw() protocol
# and the __exit__() protocol.
if exc is not value:
raise
> exc.__traceback__ = traceback
^^^^^^^^^^^^^^^^^
E dataclasses.FrozenInstanceError: cannot assign to field '__traceback__'

Я предполагаю, что exc (должен быть из MinIO) теперь заморожен и больше не может быть изменен. Но где оно было заморожено? Кем? В библиотеках MinIO изменений не произошло.
Быстрое решение заключалось в исправлении отсутствующего сегмента в MinIO, но это не является причиной этой ошибки исключения.
РЕДАКТИРОВАТЬ:
Полная ошибка при запуске pytest:
__________________________________________ ERROR at teardown of TestPostSubmitEndpoint.test_par_document_is_created_correctly_post __________________________________________

self = , typ =
value = S3Error(response=, code='NoSuchBucket', message='Volume not found', resource=None, request_id=None, host_id=None, bucket_name=None, object_name=None)
traceback =

def __exit__(self, typ, value, traceback):
if typ is None:
try:
next(self.gen)
except StopIteration:
return False
else:
try:
raise RuntimeError("generator didn't stop")
finally:
self.gen.close()
else:
if value is None:
# Need to force instantiation so we can reliably
# tell if we get the same exception back
value = typ()
try:
> self.gen.throw(value)

/opt/homebrew/Cellar/python@3.13/3.13.9_1/Frameworks/Python.framework/Versions/3.13/lib/python3.13/contextlib.py:162:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/Users/ar/Library/Caches/pypoetry/virtualenvs/classifier-api-cL9y8buz-py3.13/lib/python3.13/site-packages/pytest_asyncio/plugin.py:335: in finalizer
runner.run(async_finalizer(), context=context)
/opt/homebrew/Cellar/python@3.13/3.13.9_1/Frameworks/Python.framework/Versions/3.13/lib/python3.13/asyncio/runners.py:118: in run
return self._loop.run_until_complete(task)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/opt/homebrew/Cellar/python@3.13/3.13.9_1/Frameworks/Python.framework/Versions/3.13/lib/python3.13/asyncio/base_events.py:725: in run_until_complete
return future.result()
^^^^^^^^^^^^^^^
/Users/ar/Library/Caches/pypoetry/virtualenvs/classifier-api-cL9y8buz-py3.13/lib/python3.13/site-packages/pytest_asyncio/plugin.py:327: in async_finalizer
await gen_obj.__anext__()
tests/routers/conftest.py:121: in minio_client
for obj in minio_client.list_objects(settings.minio_bucket, recursive=True):
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/Users/ar/Library/Caches/pypoetry/virtualenvs/classifier-api-cL9y8buz-py3.13/lib/python3.13/site-packages/minio/api.py:3323: in _list_objects
response = self._execute(
/Users/ar/Library/Caches/pypoetry/virtualenvs/classifier-api-cL9y8buz-py3.13/lib/python3.13/site-packages/minio/api.py:441: in _execute
region = self._get_region(bucket_name)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/Users/ar/Library/Caches/pypoetry/virtualenvs/classifier-api-cL9y8buz-py3.13/lib/python3.13/site-packages/minio/api.py:498: in _get_region
response = self._url_open(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = , method = 'GET', region = 'us-east-1', bucket_name = 'nuke', object_name = None, body = None
headers = {'Authorization': 'AWS4-HMAC-SHA256 Credential=minio/20251105/us-east-1/s3/aws4_request, SignedHeaders=host;x-amz-cont...m64) minio-py/7.2.18', 'x-amz-content-sha256': 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', ...}
query_params = {'location': ''}, preload_content = True, no_body_trace = False

def _url_open(
self,
method: str,
region: str,
bucket_name: Optional[str] = None,
object_name: Optional[str] = None,
body: Optional[bytes] = None,
headers: Optional[DictType] = None,
query_params: Optional[DictType] = None,
preload_content: bool = True,
no_body_trace: bool = False,
) -> BaseHTTPResponse:
"""Execute HTTP request."""
creds = self._provider.retrieve() if self._provider else None
url = self._base_url.build(
method=method,
region=region,
bucket_name=bucket_name,
object_name=object_name,
query_params=query_params,
)
headers, date = self._build_headers(url.netloc, headers, body, creds)
if creds:
headers = sign_v4_s3(
method=method,
url=url,
region=region,
headers=headers,
credentials=creds,
content_sha256=cast(str, headers.get("x-amz-content-sha256")),
date=date,
)

if self._trace_stream:
self._trace_stream.write("---------START-HTTP---------\n")
query = ("?" + url.query) if url.query else ""
self._trace_stream.write(f"{method} {url.path}{query} HTTP/1.1\n")
self._trace_stream.write(
headers_to_strings(headers, titled_key=True),
)
self._trace_stream.write("\n")
if not no_body_trace and body is not None:
self._trace_stream.write("\n")
self._trace_stream.write(
body.decode() if isinstance(body, bytes) else str(body),
)
self._trace_stream.write("\n")
self._trace_stream.write("\n")

http_headers = HTTPHeaderDict()
for key, value in (headers or {}).items():
if isinstance(value, (list, tuple)):
for val in value:
http_headers.add(key, val)
else:
http_headers.add(key, value)

response = self._http.urlopen(
method,
urlunsplit(url),
body=body,
headers=http_headers,
preload_content=preload_content,
)

if self._trace_stream:
self._trace_stream.write(f"HTTP/1.1 {response.status}\n")
self._trace_stream.write(
headers_to_strings(response.headers),
)
self._trace_stream.write("\n")

if response.status in [200, 204, 206]:
if self._trace_stream:
if preload_content:
self._trace_stream.write("\n")
self._trace_stream.write(response.data.decode())
self._trace_stream.write("\n")
self._trace_stream.write("----------END-HTTP----------\n")
return response

response.read(cache_content=True)
if not preload_content:
response.release_conn()

if self._trace_stream and method != "HEAD" and response.data:
self._trace_stream.write(response.data.decode())
self._trace_stream.write("\n")

if (
method != "HEAD" and
"application/xml" not in response.headers.get(
"content-type", "",
).split(";")
):
if self._trace_stream:
self._trace_stream.write("----------END-HTTP----------\n")
if response.status == 304 and not response.data:
raise ServerError(
f"server failed with HTTP status code {response.status}",
response.status,
)
raise InvalidResponseError(
response.status,
cast(str, response.headers.get("content-type")),
response.data.decode() if response.data else None,
)

if not response.data and method != "HEAD":
if self._trace_stream:
self._trace_stream.write("----------END-HTTP----------\n")
raise InvalidResponseError(
response.status,
response.headers.get("content-type"),
None,
)

response_error = S3Error.fromxml(response) if response.data else None

if self._trace_stream:
self._trace_stream.write("----------END-HTTP----------\n")

error_map = {
301: lambda: self._handle_redirect_response(
method, response, bucket_name, True,
),
307: lambda: self._handle_redirect_response(
method, response, bucket_name, True,
),
400: lambda: self._handle_redirect_response(
method, response, bucket_name, True,
),
403: lambda: ("AccessDenied", "Access denied"),
404: lambda: (
("NoSuchKey", "Object does not exist")
if object_name
else ("NoSuchBucket", "Bucket does not exist")
if bucket_name
else ("ResourceNotFound", "Request resource not found")
),
405: lambda: (
"MethodNotAllowed",
"The specified method is not allowed against this resource",
),
409: lambda: (
("NoSuchBucket", "Bucket does not exist")
if bucket_name
else ("ResourceConflict", "Request resource conflicts"),
),
501: lambda: (
"MethodNotAllowed",
"The specified method is not allowed against this resource",
),
}

if not response_error:
func = error_map.get(response.status)
code, message = func() if func else (None, None)
if not code:
raise ServerError(
f"server failed with HTTP status code {response.status}",
response.status,
)
response_error = S3Error(
response=response,
code=cast(str, code),
message=cast(Union[str, None], message),
resource=url.path,
request_id=response.headers.get("x-amz-request-id"),
host_id=response.headers.get("x-amz-id-2"),
bucket_name=bucket_name,
object_name=object_name,
)

if response_error.code in ["NoSuchBucket", "RetryHead"]:
if bucket_name is not None:
self._region_map.pop(bucket_name, None)

> raise response_error
E minio.error.S3Error: S3 operation failed; code: NoSuchBucket, message: Volume not found, resource: None, request_id: None, host_id: None

/Users/ar/Library/Caches/pypoetry/virtualenvs/classifier-api-cL9y8buz-py3.13/lib/python3.13/site-packages/minio/api.py:427: S3Error

During handling of the above exception, another exception occurred:

self = , typ =
value = S3Error(response=, code='NoSuchBucket', message='Volume not found', resource=None, request_id=None, host_id=None, bucket_name=None, object_name=None)
traceback =

def __exit__(self, typ, value, traceback):
if typ is None:
try:
next(self.gen)
except StopIteration:
return False
else:
try:
raise RuntimeError("generator didn't stop")
finally:
self.gen.close()
else:
if value is None:
# Need to force instantiation so we can reliably
# tell if we get the same exception back
value = typ()
try:
self.gen.throw(value)
except StopIteration as exc:
# Suppress StopIteration *unless* it's the same exception that
# was passed to throw(). This prevents a StopIteration
# raised inside the "with" statement from being suppressed.
return exc is not value
except RuntimeError as exc:
# Don't re-raise the passed in exception. (issue27122)
if exc is value:
exc.__traceback__ = traceback
return False
# Avoid suppressing if a StopIteration exception
# was passed to throw() and later wrapped into a RuntimeError
# (see PEP 479 for sync generators; async generators also
# have this behavior). But do this only if the exception wrapped
# by the RuntimeError is actually Stop(Async)Iteration (see
# issue29692).
if (
isinstance(value, StopIteration)
and exc.__cause__ is value
):
value.__traceback__ = traceback
return False
raise
except BaseException as exc:
# only re-raise if it's *not* the exception that was
# passed to throw(), because __exit__() must not raise
# an exception unless __exit__() itself failed. But throw()
# has to raise the exception to signal propagation, so this
# fixes the impedance mismatch between the throw() protocol
# and the __exit__() protocol.
if exc is not value:
raise
> exc.__traceback__ = traceback
^^^^^^^^^^^^^^^^^
E dataclasses.FrozenInstanceError: cannot assign to field '__traceback__'

/opt/homebrew/Cellar/python@3.13/3.13.9_1/Frameworks/Python.framework/Versions/3.13/lib/python3.13/contextlib.py:195: FrozenInstanceError


Подробнее здесь: https://stackoverflow.com/questions/798 ... -exception
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»