Files
zenml/venv/lib/python3.9/site-packages/databricks/sdk/errors/base.py
Christian Mantha 2ca0b9ef7c star
2026-03-02 19:10:52 -05:00

137 lines
4.3 KiB
Python

import re
from dataclasses import dataclass
from typing import Any, Dict, List, Optional
import requests
from . import details as errdetails
# Deprecated.
class ErrorDetail:
def __init__(
self,
type: Optional[str] = None,
reason: Optional[str] = None,
domain: Optional[str] = None,
metadata: Optional[dict] = None,
**kwargs,
):
self.type = type
self.reason = reason
self.domain = domain
self.metadata = metadata
@classmethod
def from_dict(cls, d: Dict[str, Any]) -> "ErrorDetail":
# Key "@type" is not a valid keyword argument name in Python. Rename
# it to "type" to avoid conflicts.
safe_args = {}
for k, v in d.items():
safe_args[k if k != "@type" else "type"] = v
return cls(**safe_args)
class DatabricksError(IOError):
"""Generic error from Databricks REST API"""
def __init__(
self,
message: Optional[str] = None,
*,
error_code: Optional[str] = None,
detail: Optional[str] = None,
status: Optional[str] = None,
scimType: Optional[str] = None,
error: Optional[str] = None,
retry_after_secs: Optional[int] = None,
details: Optional[List[Dict[str, Any]]] = None,
**kwargs,
):
"""
:param message:
:param error_code:
:param detail: [Deprecated]
:param status: [Deprecated]
:param scimType: [Deprecated]
:param error: [Deprecated]
:param retry_after_secs: [Deprecated]
:param details:
:param kwargs:
"""
if detail:
# Handle SCIM error message details
# @see https://tools.ietf.org/html/rfc7644#section-3.7.3
if detail == "null":
message = "SCIM API Internal Error"
else:
message = detail
# add more context from SCIM responses
message = f"{scimType} {message}".strip(" ")
error_code = f"SCIM_{status}"
super().__init__(message if message else error)
self.error_code = error_code
self.retry_after_secs = retry_after_secs
self._error_details = errdetails.parse_error_details(details or [])
self.kwargs = kwargs
# Deprecated.
self.details = []
if details:
for d in details:
if not isinstance(d, dict):
continue
self.details.append(ErrorDetail.from_dict(d))
def get_error_info(self) -> List[ErrorDetail]:
if self.details is None:
return []
return [detail for detail in self.details if detail.type == errdetails._ERROR_INFO_TYPE]
def get_error_details(self) -> errdetails.ErrorDetails:
return self._error_details
@dataclass
class _ErrorOverride:
# The name of the override. Used for logging purposes.
debug_name: str
# A regex that must match the path of the request for this override to be applied.
path_regex: re.Pattern
# The HTTP method of the request for the override to apply
verb: str
# The custom error class to use for this override.
custom_error: type
# A regular expression that must match the error code for this override to be applied. If None,
# this field is ignored.
status_code_matcher: Optional[re.Pattern] = None
# A regular expression that must match the error code for this override to be applied. If None,
# this field is ignored.
error_code_matcher: Optional[re.Pattern] = None
# A regular expression that must match the message for this override to be applied. If None,
# this field is ignored.
message_matcher: Optional[re.Pattern] = None
def matches(self, response: requests.Response, raw_error: dict):
if response.request.method != self.verb:
return False
if not self.path_regex.match(response.request.path_url):
return False
if self.status_code_matcher and not self.status_code_matcher.match(str(response.status_code)):
return False
if self.error_code_matcher and not self.error_code_matcher.match(raw_error.get("error_code", "")):
return False
if self.message_matcher and not self.message_matcher.match(raw_error.get("message", "")):
return False
return True