Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/werkzeug/exceptions.py: 64%

239 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2023-06-07 06:35 +0000

1"""Implements a number of Python exceptions which can be raised from within 

2a view to trigger a standard HTTP non-200 response. 

3 

4Usage Example 

5------------- 

6 

7.. code-block:: python 

8 

9 from werkzeug.wrappers.request import Request 

10 from werkzeug.exceptions import HTTPException, NotFound 

11 

12 def view(request): 

13 raise NotFound() 

14 

15 @Request.application 

16 def application(request): 

17 try: 

18 return view(request) 

19 except HTTPException as e: 

20 return e 

21 

22As you can see from this example those exceptions are callable WSGI 

23applications. However, they are not Werkzeug response objects. You 

24can get a response object by calling ``get_response()`` on a HTTP 

25exception. 

26 

27Keep in mind that you may have to pass an environ (WSGI) or scope 

28(ASGI) to ``get_response()`` because some errors fetch additional 

29information relating to the request. 

30 

31If you want to hook in a different exception page to say, a 404 status 

32code, you can add a second except for a specific subclass of an error: 

33 

34.. code-block:: python 

35 

36 @Request.application 

37 def application(request): 

38 try: 

39 return view(request) 

40 except NotFound as e: 

41 return not_found(request) 

42 except HTTPException as e: 

43 return e 

44 

45""" 

46import typing as t 

47from datetime import datetime 

48 

49from markupsafe import escape 

50from markupsafe import Markup 

51 

52from ._internal import _get_environ 

53 

54if t.TYPE_CHECKING: 

55 import typing_extensions as te 

56 from _typeshed.wsgi import StartResponse 

57 from _typeshed.wsgi import WSGIEnvironment 

58 from .datastructures import WWWAuthenticate 

59 from .sansio.response import Response 

60 from .wrappers.request import Request as WSGIRequest # noqa: F401 

61 from .wrappers.response import Response as WSGIResponse # noqa: F401 

62 

63 

64class HTTPException(Exception): 

65 """The base class for all HTTP exceptions. This exception can be called as a WSGI 

66 application to render a default error page or you can catch the subclasses 

67 of it independently and render nicer error messages. 

68 

69 .. versionchanged:: 2.1 

70 Removed the ``wrap`` class method. 

71 """ 

72 

73 code: t.Optional[int] = None 

74 description: t.Optional[str] = None 

75 

76 def __init__( 

77 self, 

78 description: t.Optional[str] = None, 

79 response: t.Optional["Response"] = None, 

80 ) -> None: 

81 super().__init__() 

82 if description is not None: 

83 self.description = description 

84 self.response = response 

85 

86 @property 

87 def name(self) -> str: 

88 """The status name.""" 

89 from .http import HTTP_STATUS_CODES 

90 

91 return HTTP_STATUS_CODES.get(self.code, "Unknown Error") # type: ignore 

92 

93 def get_description( 

94 self, 

95 environ: t.Optional["WSGIEnvironment"] = None, 

96 scope: t.Optional[dict] = None, 

97 ) -> str: 

98 """Get the description.""" 

99 if self.description is None: 

100 description = "" 

101 elif not isinstance(self.description, str): 

102 description = str(self.description) 

103 else: 

104 description = self.description 

105 

106 description = escape(description).replace("\n", Markup("<br>")) 

107 return f"<p>{description}</p>" 

108 

109 def get_body( 

110 self, 

111 environ: t.Optional["WSGIEnvironment"] = None, 

112 scope: t.Optional[dict] = None, 

113 ) -> str: 

114 """Get the HTML body.""" 

115 return ( 

116 "<!doctype html>\n" 

117 "<html lang=en>\n" 

118 f"<title>{self.code} {escape(self.name)}</title>\n" 

119 f"<h1>{escape(self.name)}</h1>\n" 

120 f"{self.get_description(environ)}\n" 

121 ) 

122 

123 def get_headers( 

124 self, 

125 environ: t.Optional["WSGIEnvironment"] = None, 

126 scope: t.Optional[dict] = None, 

127 ) -> t.List[t.Tuple[str, str]]: 

128 """Get a list of headers.""" 

129 return [("Content-Type", "text/html; charset=utf-8")] 

130 

131 def get_response( 

132 self, 

133 environ: t.Optional[t.Union["WSGIEnvironment", "WSGIRequest"]] = None, 

134 scope: t.Optional[dict] = None, 

135 ) -> "Response": 

136 """Get a response object. If one was passed to the exception 

137 it's returned directly. 

138 

139 :param environ: the optional environ for the request. This 

140 can be used to modify the response depending 

141 on how the request looked like. 

142 :return: a :class:`Response` object or a subclass thereof. 

143 """ 

144 from .wrappers.response import Response as WSGIResponse # noqa: F811 

145 

146 if self.response is not None: 

147 return self.response 

148 if environ is not None: 

149 environ = _get_environ(environ) 

150 headers = self.get_headers(environ, scope) 

151 return WSGIResponse(self.get_body(environ, scope), self.code, headers) 

152 

153 def __call__( 

154 self, environ: "WSGIEnvironment", start_response: "StartResponse" 

155 ) -> t.Iterable[bytes]: 

156 """Call the exception as WSGI application. 

157 

158 :param environ: the WSGI environment. 

159 :param start_response: the response callable provided by the WSGI 

160 server. 

161 """ 

162 response = t.cast("WSGIResponse", self.get_response(environ)) 

163 return response(environ, start_response) 

164 

165 def __str__(self) -> str: 

166 code = self.code if self.code is not None else "???" 

167 return f"{code} {self.name}: {self.description}" 

168 

169 def __repr__(self) -> str: 

170 code = self.code if self.code is not None else "???" 

171 return f"<{type(self).__name__} '{code}: {self.name}'>" 

172 

173 

174class BadRequest(HTTPException): 

175 """*400* `Bad Request` 

176 

177 Raise if the browser sends something to the application the application 

178 or server cannot handle. 

179 """ 

180 

181 code = 400 

182 description = ( 

183 "The browser (or proxy) sent a request that this server could " 

184 "not understand." 

185 ) 

186 

187 

188class BadRequestKeyError(BadRequest, KeyError): 

189 """An exception that is used to signal both a :exc:`KeyError` and a 

190 :exc:`BadRequest`. Used by many of the datastructures. 

191 """ 

192 

193 _description = BadRequest.description 

194 #: Show the KeyError along with the HTTP error message in the 

195 #: response. This should be disabled in production, but can be 

196 #: useful in a debug mode. 

197 show_exception = False 

198 

199 def __init__(self, arg: t.Optional[str] = None, *args: t.Any, **kwargs: t.Any): 

200 super().__init__(*args, **kwargs) 

201 

202 if arg is None: 

203 KeyError.__init__(self) 

204 else: 

205 KeyError.__init__(self, arg) 

206 

207 @property # type: ignore 

208 def description(self) -> str: 

209 if self.show_exception: 

210 return ( 

211 f"{self._description}\n" 

212 f"{KeyError.__name__}: {KeyError.__str__(self)}" 

213 ) 

214 

215 return self._description 

216 

217 @description.setter 

218 def description(self, value: str) -> None: 

219 self._description = value 

220 

221 

222class ClientDisconnected(BadRequest): 

223 """Internal exception that is raised if Werkzeug detects a disconnected 

224 client. Since the client is already gone at that point attempting to 

225 send the error message to the client might not work and might ultimately 

226 result in another exception in the server. Mainly this is here so that 

227 it is silenced by default as far as Werkzeug is concerned. 

228 

229 Since disconnections cannot be reliably detected and are unspecified 

230 by WSGI to a large extent this might or might not be raised if a client 

231 is gone. 

232 

233 .. versionadded:: 0.8 

234 """ 

235 

236 

237class SecurityError(BadRequest): 

238 """Raised if something triggers a security error. This is otherwise 

239 exactly like a bad request error. 

240 

241 .. versionadded:: 0.9 

242 """ 

243 

244 

245class BadHost(BadRequest): 

246 """Raised if the submitted host is badly formatted. 

247 

248 .. versionadded:: 0.11.2 

249 """ 

250 

251 

252class Unauthorized(HTTPException): 

253 """*401* ``Unauthorized`` 

254 

255 Raise if the user is not authorized to access a resource. 

256 

257 The ``www_authenticate`` argument should be used to set the 

258 ``WWW-Authenticate`` header. This is used for HTTP basic auth and 

259 other schemes. Use :class:`~werkzeug.datastructures.WWWAuthenticate` 

260 to create correctly formatted values. Strictly speaking a 401 

261 response is invalid if it doesn't provide at least one value for 

262 this header, although real clients typically don't care. 

263 

264 :param description: Override the default message used for the body 

265 of the response. 

266 :param www-authenticate: A single value, or list of values, for the 

267 WWW-Authenticate header(s). 

268 

269 .. versionchanged:: 2.0 

270 Serialize multiple ``www_authenticate`` items into multiple 

271 ``WWW-Authenticate`` headers, rather than joining them 

272 into a single value, for better interoperability. 

273 

274 .. versionchanged:: 0.15.3 

275 If the ``www_authenticate`` argument is not set, the 

276 ``WWW-Authenticate`` header is not set. 

277 

278 .. versionchanged:: 0.15.3 

279 The ``response`` argument was restored. 

280 

281 .. versionchanged:: 0.15.1 

282 ``description`` was moved back as the first argument, restoring 

283 its previous position. 

284 

285 .. versionchanged:: 0.15.0 

286 ``www_authenticate`` was added as the first argument, ahead of 

287 ``description``. 

288 """ 

289 

290 code = 401 

291 description = ( 

292 "The server could not verify that you are authorized to access" 

293 " the URL requested. You either supplied the wrong credentials" 

294 " (e.g. a bad password), or your browser doesn't understand" 

295 " how to supply the credentials required." 

296 ) 

297 

298 def __init__( 

299 self, 

300 description: t.Optional[str] = None, 

301 response: t.Optional["Response"] = None, 

302 www_authenticate: t.Optional[ 

303 t.Union["WWWAuthenticate", t.Iterable["WWWAuthenticate"]] 

304 ] = None, 

305 ) -> None: 

306 super().__init__(description, response) 

307 

308 from .datastructures import WWWAuthenticate 

309 

310 if isinstance(www_authenticate, WWWAuthenticate): 

311 www_authenticate = (www_authenticate,) 

312 

313 self.www_authenticate = www_authenticate 

314 

315 def get_headers( 

316 self, 

317 environ: t.Optional["WSGIEnvironment"] = None, 

318 scope: t.Optional[dict] = None, 

319 ) -> t.List[t.Tuple[str, str]]: 

320 headers = super().get_headers(environ, scope) 

321 if self.www_authenticate: 

322 headers.extend(("WWW-Authenticate", str(x)) for x in self.www_authenticate) 

323 return headers 

324 

325 

326class Forbidden(HTTPException): 

327 """*403* `Forbidden` 

328 

329 Raise if the user doesn't have the permission for the requested resource 

330 but was authenticated. 

331 """ 

332 

333 code = 403 

334 description = ( 

335 "You don't have the permission to access the requested" 

336 " resource. It is either read-protected or not readable by the" 

337 " server." 

338 ) 

339 

340 

341class NotFound(HTTPException): 

342 """*404* `Not Found` 

343 

344 Raise if a resource does not exist and never existed. 

345 """ 

346 

347 code = 404 

348 description = ( 

349 "The requested URL was not found on the server. If you entered" 

350 " the URL manually please check your spelling and try again." 

351 ) 

352 

353 

354class MethodNotAllowed(HTTPException): 

355 """*405* `Method Not Allowed` 

356 

357 Raise if the server used a method the resource does not handle. For 

358 example `POST` if the resource is view only. Especially useful for REST. 

359 

360 The first argument for this exception should be a list of allowed methods. 

361 Strictly speaking the response would be invalid if you don't provide valid 

362 methods in the header which you can do with that list. 

363 """ 

364 

365 code = 405 

366 description = "The method is not allowed for the requested URL." 

367 

368 def __init__( 

369 self, 

370 valid_methods: t.Optional[t.Iterable[str]] = None, 

371 description: t.Optional[str] = None, 

372 response: t.Optional["Response"] = None, 

373 ) -> None: 

374 """Takes an optional list of valid http methods 

375 starting with werkzeug 0.3 the list will be mandatory.""" 

376 super().__init__(description=description, response=response) 

377 self.valid_methods = valid_methods 

378 

379 def get_headers( 

380 self, 

381 environ: t.Optional["WSGIEnvironment"] = None, 

382 scope: t.Optional[dict] = None, 

383 ) -> t.List[t.Tuple[str, str]]: 

384 headers = super().get_headers(environ, scope) 

385 if self.valid_methods: 

386 headers.append(("Allow", ", ".join(self.valid_methods))) 

387 return headers 

388 

389 

390class NotAcceptable(HTTPException): 

391 """*406* `Not Acceptable` 

392 

393 Raise if the server can't return any content conforming to the 

394 `Accept` headers of the client. 

395 """ 

396 

397 code = 406 

398 description = ( 

399 "The resource identified by the request is only capable of" 

400 " generating response entities which have content" 

401 " characteristics not acceptable according to the accept" 

402 " headers sent in the request." 

403 ) 

404 

405 

406class RequestTimeout(HTTPException): 

407 """*408* `Request Timeout` 

408 

409 Raise to signalize a timeout. 

410 """ 

411 

412 code = 408 

413 description = ( 

414 "The server closed the network connection because the browser" 

415 " didn't finish the request within the specified time." 

416 ) 

417 

418 

419class Conflict(HTTPException): 

420 """*409* `Conflict` 

421 

422 Raise to signal that a request cannot be completed because it conflicts 

423 with the current state on the server. 

424 

425 .. versionadded:: 0.7 

426 """ 

427 

428 code = 409 

429 description = ( 

430 "A conflict happened while processing the request. The" 

431 " resource might have been modified while the request was being" 

432 " processed." 

433 ) 

434 

435 

436class Gone(HTTPException): 

437 """*410* `Gone` 

438 

439 Raise if a resource existed previously and went away without new location. 

440 """ 

441 

442 code = 410 

443 description = ( 

444 "The requested URL is no longer available on this server and" 

445 " there is no forwarding address. If you followed a link from a" 

446 " foreign page, please contact the author of this page." 

447 ) 

448 

449 

450class LengthRequired(HTTPException): 

451 """*411* `Length Required` 

452 

453 Raise if the browser submitted data but no ``Content-Length`` header which 

454 is required for the kind of processing the server does. 

455 """ 

456 

457 code = 411 

458 description = ( 

459 "A request with this method requires a valid <code>Content-" 

460 "Length</code> header." 

461 ) 

462 

463 

464class PreconditionFailed(HTTPException): 

465 """*412* `Precondition Failed` 

466 

467 Status code used in combination with ``If-Match``, ``If-None-Match``, or 

468 ``If-Unmodified-Since``. 

469 """ 

470 

471 code = 412 

472 description = ( 

473 "The precondition on the request for the URL failed positive evaluation." 

474 ) 

475 

476 

477class RequestEntityTooLarge(HTTPException): 

478 """*413* `Request Entity Too Large` 

479 

480 The status code one should return if the data submitted exceeded a given 

481 limit. 

482 """ 

483 

484 code = 413 

485 description = "The data value transmitted exceeds the capacity limit." 

486 

487 

488class RequestURITooLarge(HTTPException): 

489 """*414* `Request URI Too Large` 

490 

491 Like *413* but for too long URLs. 

492 """ 

493 

494 code = 414 

495 description = ( 

496 "The length of the requested URL exceeds the capacity limit for" 

497 " this server. The request cannot be processed." 

498 ) 

499 

500 

501class UnsupportedMediaType(HTTPException): 

502 """*415* `Unsupported Media Type` 

503 

504 The status code returned if the server is unable to handle the media type 

505 the client transmitted. 

506 """ 

507 

508 code = 415 

509 description = ( 

510 "The server does not support the media type transmitted in the request." 

511 ) 

512 

513 

514class RequestedRangeNotSatisfiable(HTTPException): 

515 """*416* `Requested Range Not Satisfiable` 

516 

517 The client asked for an invalid part of the file. 

518 

519 .. versionadded:: 0.7 

520 """ 

521 

522 code = 416 

523 description = "The server cannot provide the requested range." 

524 

525 def __init__( 

526 self, 

527 length: t.Optional[int] = None, 

528 units: str = "bytes", 

529 description: t.Optional[str] = None, 

530 response: t.Optional["Response"] = None, 

531 ) -> None: 

532 """Takes an optional `Content-Range` header value based on ``length`` 

533 parameter. 

534 """ 

535 super().__init__(description=description, response=response) 

536 self.length = length 

537 self.units = units 

538 

539 def get_headers( 

540 self, 

541 environ: t.Optional["WSGIEnvironment"] = None, 

542 scope: t.Optional[dict] = None, 

543 ) -> t.List[t.Tuple[str, str]]: 

544 headers = super().get_headers(environ, scope) 

545 if self.length is not None: 

546 headers.append(("Content-Range", f"{self.units} */{self.length}")) 

547 return headers 

548 

549 

550class ExpectationFailed(HTTPException): 

551 """*417* `Expectation Failed` 

552 

553 The server cannot meet the requirements of the Expect request-header. 

554 

555 .. versionadded:: 0.7 

556 """ 

557 

558 code = 417 

559 description = "The server could not meet the requirements of the Expect header" 

560 

561 

562class ImATeapot(HTTPException): 

563 """*418* `I'm a teapot` 

564 

565 The server should return this if it is a teapot and someone attempted 

566 to brew coffee with it. 

567 

568 .. versionadded:: 0.7 

569 """ 

570 

571 code = 418 

572 description = "This server is a teapot, not a coffee machine" 

573 

574 

575class UnprocessableEntity(HTTPException): 

576 """*422* `Unprocessable Entity` 

577 

578 Used if the request is well formed, but the instructions are otherwise 

579 incorrect. 

580 """ 

581 

582 code = 422 

583 description = ( 

584 "The request was well-formed but was unable to be followed due" 

585 " to semantic errors." 

586 ) 

587 

588 

589class Locked(HTTPException): 

590 """*423* `Locked` 

591 

592 Used if the resource that is being accessed is locked. 

593 """ 

594 

595 code = 423 

596 description = "The resource that is being accessed is locked." 

597 

598 

599class FailedDependency(HTTPException): 

600 """*424* `Failed Dependency` 

601 

602 Used if the method could not be performed on the resource 

603 because the requested action depended on another action and that action failed. 

604 """ 

605 

606 code = 424 

607 description = ( 

608 "The method could not be performed on the resource because the" 

609 " requested action depended on another action and that action" 

610 " failed." 

611 ) 

612 

613 

614class PreconditionRequired(HTTPException): 

615 """*428* `Precondition Required` 

616 

617 The server requires this request to be conditional, typically to prevent 

618 the lost update problem, which is a race condition between two or more 

619 clients attempting to update a resource through PUT or DELETE. By requiring 

620 each client to include a conditional header ("If-Match" or "If-Unmodified- 

621 Since") with the proper value retained from a recent GET request, the 

622 server ensures that each client has at least seen the previous revision of 

623 the resource. 

624 """ 

625 

626 code = 428 

627 description = ( 

628 "This request is required to be conditional; try using" 

629 ' "If-Match" or "If-Unmodified-Since".' 

630 ) 

631 

632 

633class _RetryAfter(HTTPException): 

634 """Adds an optional ``retry_after`` parameter which will set the 

635 ``Retry-After`` header. May be an :class:`int` number of seconds or 

636 a :class:`~datetime.datetime`. 

637 """ 

638 

639 def __init__( 

640 self, 

641 description: t.Optional[str] = None, 

642 response: t.Optional["Response"] = None, 

643 retry_after: t.Optional[t.Union[datetime, int]] = None, 

644 ) -> None: 

645 super().__init__(description, response) 

646 self.retry_after = retry_after 

647 

648 def get_headers( 

649 self, 

650 environ: t.Optional["WSGIEnvironment"] = None, 

651 scope: t.Optional[dict] = None, 

652 ) -> t.List[t.Tuple[str, str]]: 

653 headers = super().get_headers(environ, scope) 

654 

655 if self.retry_after: 

656 if isinstance(self.retry_after, datetime): 

657 from .http import http_date 

658 

659 value = http_date(self.retry_after) 

660 else: 

661 value = str(self.retry_after) 

662 

663 headers.append(("Retry-After", value)) 

664 

665 return headers 

666 

667 

668class TooManyRequests(_RetryAfter): 

669 """*429* `Too Many Requests` 

670 

671 The server is limiting the rate at which this user receives 

672 responses, and this request exceeds that rate. (The server may use 

673 any convenient method to identify users and their request rates). 

674 The server may include a "Retry-After" header to indicate how long 

675 the user should wait before retrying. 

676 

677 :param retry_after: If given, set the ``Retry-After`` header to this 

678 value. May be an :class:`int` number of seconds or a 

679 :class:`~datetime.datetime`. 

680 

681 .. versionchanged:: 1.0 

682 Added ``retry_after`` parameter. 

683 """ 

684 

685 code = 429 

686 description = "This user has exceeded an allotted request count. Try again later." 

687 

688 

689class RequestHeaderFieldsTooLarge(HTTPException): 

690 """*431* `Request Header Fields Too Large` 

691 

692 The server refuses to process the request because the header fields are too 

693 large. One or more individual fields may be too large, or the set of all 

694 headers is too large. 

695 """ 

696 

697 code = 431 

698 description = "One or more header fields exceeds the maximum size." 

699 

700 

701class UnavailableForLegalReasons(HTTPException): 

702 """*451* `Unavailable For Legal Reasons` 

703 

704 This status code indicates that the server is denying access to the 

705 resource as a consequence of a legal demand. 

706 """ 

707 

708 code = 451 

709 description = "Unavailable for legal reasons." 

710 

711 

712class InternalServerError(HTTPException): 

713 """*500* `Internal Server Error` 

714 

715 Raise if an internal server error occurred. This is a good fallback if an 

716 unknown error occurred in the dispatcher. 

717 

718 .. versionchanged:: 1.0.0 

719 Added the :attr:`original_exception` attribute. 

720 """ 

721 

722 code = 500 

723 description = ( 

724 "The server encountered an internal error and was unable to" 

725 " complete your request. Either the server is overloaded or" 

726 " there is an error in the application." 

727 ) 

728 

729 def __init__( 

730 self, 

731 description: t.Optional[str] = None, 

732 response: t.Optional["Response"] = None, 

733 original_exception: t.Optional[BaseException] = None, 

734 ) -> None: 

735 #: The original exception that caused this 500 error. Can be 

736 #: used by frameworks to provide context when handling 

737 #: unexpected errors. 

738 self.original_exception = original_exception 

739 super().__init__(description=description, response=response) 

740 

741 

742class NotImplemented(HTTPException): 

743 """*501* `Not Implemented` 

744 

745 Raise if the application does not support the action requested by the 

746 browser. 

747 """ 

748 

749 code = 501 

750 description = "The server does not support the action requested by the browser." 

751 

752 

753class BadGateway(HTTPException): 

754 """*502* `Bad Gateway` 

755 

756 If you do proxying in your application you should return this status code 

757 if you received an invalid response from the upstream server it accessed 

758 in attempting to fulfill the request. 

759 """ 

760 

761 code = 502 

762 description = ( 

763 "The proxy server received an invalid response from an upstream server." 

764 ) 

765 

766 

767class ServiceUnavailable(_RetryAfter): 

768 """*503* `Service Unavailable` 

769 

770 Status code you should return if a service is temporarily 

771 unavailable. 

772 

773 :param retry_after: If given, set the ``Retry-After`` header to this 

774 value. May be an :class:`int` number of seconds or a 

775 :class:`~datetime.datetime`. 

776 

777 .. versionchanged:: 1.0 

778 Added ``retry_after`` parameter. 

779 """ 

780 

781 code = 503 

782 description = ( 

783 "The server is temporarily unable to service your request due" 

784 " to maintenance downtime or capacity problems. Please try" 

785 " again later." 

786 ) 

787 

788 

789class GatewayTimeout(HTTPException): 

790 """*504* `Gateway Timeout` 

791 

792 Status code you should return if a connection to an upstream server 

793 times out. 

794 """ 

795 

796 code = 504 

797 description = "The connection to an upstream server timed out." 

798 

799 

800class HTTPVersionNotSupported(HTTPException): 

801 """*505* `HTTP Version Not Supported` 

802 

803 The server does not support the HTTP protocol version used in the request. 

804 """ 

805 

806 code = 505 

807 description = ( 

808 "The server does not support the HTTP protocol version used in the request." 

809 ) 

810 

811 

812default_exceptions: t.Dict[int, t.Type[HTTPException]] = {} 

813 

814 

815def _find_exceptions() -> None: 

816 for obj in globals().values(): 

817 try: 

818 is_http_exception = issubclass(obj, HTTPException) 

819 except TypeError: 

820 is_http_exception = False 

821 if not is_http_exception or obj.code is None: 

822 continue 

823 old_obj = default_exceptions.get(obj.code, None) 

824 if old_obj is not None and issubclass(obj, old_obj): 

825 continue 

826 default_exceptions[obj.code] = obj 

827 

828 

829_find_exceptions() 

830del _find_exceptions 

831 

832 

833class Aborter: 

834 """When passed a dict of code -> exception items it can be used as 

835 callable that raises exceptions. If the first argument to the 

836 callable is an integer it will be looked up in the mapping, if it's 

837 a WSGI application it will be raised in a proxy exception. 

838 

839 The rest of the arguments are forwarded to the exception constructor. 

840 """ 

841 

842 def __init__( 

843 self, 

844 mapping: t.Optional[t.Dict[int, t.Type[HTTPException]]] = None, 

845 extra: t.Optional[t.Dict[int, t.Type[HTTPException]]] = None, 

846 ) -> None: 

847 if mapping is None: 

848 mapping = default_exceptions 

849 self.mapping = dict(mapping) 

850 if extra is not None: 

851 self.mapping.update(extra) 

852 

853 def __call__( 

854 self, code: t.Union[int, "Response"], *args: t.Any, **kwargs: t.Any 

855 ) -> "te.NoReturn": 

856 from .sansio.response import Response 

857 

858 if isinstance(code, Response): 

859 raise HTTPException(response=code) 

860 

861 if code not in self.mapping: 

862 raise LookupError(f"no exception for {code!r}") 

863 

864 raise self.mapping[code](*args, **kwargs) 

865 

866 

867def abort( 

868 status: t.Union[int, "Response"], *args: t.Any, **kwargs: t.Any 

869) -> "te.NoReturn": 

870 """Raises an :py:exc:`HTTPException` for the given status code or WSGI 

871 application. 

872 

873 If a status code is given, it will be looked up in the list of 

874 exceptions and will raise that exception. If passed a WSGI application, 

875 it will wrap it in a proxy WSGI exception and raise that:: 

876 

877 abort(404) # 404 Not Found 

878 abort(Response('Hello World')) 

879 

880 """ 

881 _aborter(status, *args, **kwargs) 

882 

883 

884_aborter: Aborter = Aborter()