pipelex-api 0.71.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pipelex_api/__init__.py +0 -0
- pipelex_api/api.toml +21 -0
- pipelex_api/api_config.py +144 -0
- pipelex_api/bundle.py +243 -0
- pipelex_api/disclosure.py +43 -0
- pipelex_api/error_types.py +80 -0
- pipelex_api/error_uri.py +45 -0
- pipelex_api/errors.py +130 -0
- pipelex_api/exception_handlers.py +693 -0
- pipelex_api/json_body.py +182 -0
- pipelex_api/limits.py +67 -0
- pipelex_api/main.py +221 -0
- pipelex_api/method_cache.py +241 -0
- pipelex_api/method_source.py +215 -0
- pipelex_api/middleware.py +209 -0
- pipelex_api/openapi_responses.py +186 -0
- pipelex_api/openapi_schema.py +83 -0
- pipelex_api/problem_document.py +134 -0
- pipelex_api/py.typed +0 -0
- pipelex_api/routes/__init__.py +23 -0
- pipelex_api/routes/health.py +24 -0
- pipelex_api/routes/pipelex/__init__.py +21 -0
- pipelex_api/routes/pipelex/agent/__init__.py +11 -0
- pipelex_api/routes/pipelex/agent/concept.py +60 -0
- pipelex_api/routes/pipelex/agent/models.py +49 -0
- pipelex_api/routes/pipelex/agent/pipe_spec.py +59 -0
- pipelex_api/routes/pipelex/build/__init__.py +11 -0
- pipelex_api/routes/pipelex/build/inputs.py +192 -0
- pipelex_api/routes/pipelex/build/output.py +163 -0
- pipelex_api/routes/pipelex/build/runner.py +236 -0
- pipelex_api/routes/pipelex/codegen.py +164 -0
- pipelex_api/routes/pipelex/crate_ops.py +331 -0
- pipelex_api/routes/pipelex/pipe_io.py +186 -0
- pipelex_api/routes/pipelex/pipeline.py +938 -0
- pipelex_api/routes/pipelex/resolve.py +81 -0
- pipelex_api/routes/pipelex/tools.py +111 -0
- pipelex_api/routes/pipelex/utils.py +6 -0
- pipelex_api/routes/pipelex/validate.py +473 -0
- pipelex_api/routes/version.py +51 -0
- pipelex_api/schemas/__init__.py +0 -0
- pipelex_api/schemas/models.py +653 -0
- pipelex_api/security.py +284 -0
- pipelex_api-0.71.0.dist-info/METADATA +188 -0
- pipelex_api-0.71.0.dist-info/RECORD +46 -0
- pipelex_api-0.71.0.dist-info/WHEEL +4 -0
- pipelex_api-0.71.0.dist-info/licenses/LICENSE +95 -0
pipelex_api/errors.py
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
"""API-authored error helpers — RFC 7807 problem responses for the 4xx/5xx the API owns.
|
|
2
|
+
|
|
3
|
+
These cover failures the API detects at its own boundary — request validation,
|
|
4
|
+
auth, payload-size limits, server misconfiguration — as opposed to pipelex
|
|
5
|
+
domain errors, which carry an `ErrorReport` and are translated by the global
|
|
6
|
+
`PipelexError` handler in `pipelex_api.exception_handlers`.
|
|
7
|
+
|
|
8
|
+
Each helper builds an RFC 7807 problem document (`build_problem_document_from_api_error`)
|
|
9
|
+
and raises `ApiError`. The `handle_api_error` handler registered in
|
|
10
|
+
`pipelex_api.exception_handlers` renders it as `application/problem+json`. Routes do
|
|
11
|
+
NOT catch pipelex exceptions themselves — anything that is not an
|
|
12
|
+
API-authored `ApiError` propagates to the global handlers. There are no
|
|
13
|
+
catch tuples here anymore: the global `PipelexError` / `Exception` handlers
|
|
14
|
+
are the single translation point for everything the API does not author
|
|
15
|
+
itself.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from typing import Any, NoReturn
|
|
19
|
+
|
|
20
|
+
from pipelex.base_exceptions import ErrorDomain
|
|
21
|
+
|
|
22
|
+
from pipelex_api.error_types import ErrorType
|
|
23
|
+
from pipelex_api.problem_document import build_problem_document_from_api_error
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class ApiError(Exception):
|
|
27
|
+
"""An API-authored error carrying a ready-rendered RFC 7807 problem document.
|
|
28
|
+
|
|
29
|
+
Raised by the `raise_*` helpers below; rendered by `handle_api_error` in
|
|
30
|
+
`pipelex_api.exception_handlers` as `application/problem+json`. Distinct from a pipelex
|
|
31
|
+
`PipelexError`: there is no `ErrorReport` behind it — the failure is the
|
|
32
|
+
API's own request validation, auth, or configuration check. The problem
|
|
33
|
+
document is built at raise time, less the request context: `instance` and
|
|
34
|
+
`request_id` are stamped by the handler, which is the frame that holds the
|
|
35
|
+
`Request`.
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
def __init__(self, *, status_code: int, document: dict[str, Any], headers: dict[str, str] | None = None) -> None:
|
|
39
|
+
self.status_code = status_code
|
|
40
|
+
self.document = document
|
|
41
|
+
self.headers: dict[str, str] = headers or {}
|
|
42
|
+
super().__init__(str(document.get("detail", "")))
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def _raise_api_error(
|
|
46
|
+
*,
|
|
47
|
+
error_type: ErrorType,
|
|
48
|
+
message: str,
|
|
49
|
+
status: int,
|
|
50
|
+
error_domain: ErrorDomain,
|
|
51
|
+
headers: dict[str, str] | None = None,
|
|
52
|
+
) -> NoReturn:
|
|
53
|
+
"""Build the RFC 7807 document and raise `ApiError`.
|
|
54
|
+
|
|
55
|
+
The document is built without the request context: `instance` and
|
|
56
|
+
`request_id` are stamped by `handle_api_error`, from the `Request` it is
|
|
57
|
+
handed. That keeps these helpers parameter-clean — a call site deep inside
|
|
58
|
+
a route still needs no `Request` — while leaving the API with no ambient
|
|
59
|
+
request state of its own, and it is how the three error paths end up
|
|
60
|
+
reading the route and the id from exactly one place.
|
|
61
|
+
"""
|
|
62
|
+
document = build_problem_document_from_api_error(
|
|
63
|
+
error_type,
|
|
64
|
+
message,
|
|
65
|
+
status,
|
|
66
|
+
instance=None,
|
|
67
|
+
request_id=None,
|
|
68
|
+
error_domain=error_domain,
|
|
69
|
+
)
|
|
70
|
+
raise ApiError(status_code=status, document=document, headers=headers)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def raise_validation_error(message: str, error_type: ErrorType = ErrorType.VALIDATION_ERROR) -> NoReturn:
|
|
74
|
+
"""Raise a 422 RFC 7807 problem response for invalid caller input."""
|
|
75
|
+
_raise_api_error(error_type=error_type, message=message, status=422, error_domain=ErrorDomain.INPUT)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def raise_bad_request(message: str, error_type: ErrorType = ErrorType.BAD_REQUEST) -> NoReturn:
|
|
79
|
+
"""Raise a 400 RFC 7807 problem response for a malformed request."""
|
|
80
|
+
_raise_api_error(error_type=error_type, message=message, status=400, error_domain=ErrorDomain.INPUT)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def raise_payload_too_large(message: str) -> NoReturn:
|
|
84
|
+
"""Raise a 413 RFC 7807 problem response for an over-limit payload."""
|
|
85
|
+
_raise_api_error(error_type=ErrorType.PAYLOAD_TOO_LARGE, message=message, status=413, error_domain=ErrorDomain.INPUT)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def raise_forbidden(message: str, error_type: ErrorType = ErrorType.FORBIDDEN) -> NoReturn:
|
|
89
|
+
"""Raise a 403 RFC 7807 problem response for an authorization failure."""
|
|
90
|
+
_raise_api_error(error_type=error_type, message=message, status=403, error_domain=ErrorDomain.INPUT)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def raise_unauthenticated(message: str, error_type: ErrorType = ErrorType.UNAUTHENTICATED) -> NoReturn:
|
|
94
|
+
"""Raise a 401 RFC 7807 problem response, with the `WWW-Authenticate: Bearer` challenge.
|
|
95
|
+
|
|
96
|
+
RFC 7807 fully supports the challenge header: moving the body to
|
|
97
|
+
`application/problem+json` does not break an OAuth/JWT client that parses
|
|
98
|
+
`WWW-Authenticate`.
|
|
99
|
+
"""
|
|
100
|
+
_raise_api_error(
|
|
101
|
+
error_type=error_type,
|
|
102
|
+
message=message,
|
|
103
|
+
status=401,
|
|
104
|
+
error_domain=ErrorDomain.INPUT,
|
|
105
|
+
headers={"WWW-Authenticate": "Bearer"},
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def raise_not_implemented(message: str, error_type: ErrorType) -> NoReturn:
|
|
110
|
+
"""Raise a 501 RFC 7807 problem response for a spec'd capability this server does not implement yet.
|
|
111
|
+
|
|
112
|
+
For request shapes the published contract accepts but this deployment cannot serve (e.g. a
|
|
113
|
+
`method_ref` closure selector before the method registry exists). A no-verdict condition —
|
|
114
|
+
distinct from a 422 (the request is well-formed per the contract) and from a 200 invalid
|
|
115
|
+
verdict (nothing was diagnosed). Classified `CONFIG` domain: neither the request nor the
|
|
116
|
+
content is at fault.
|
|
117
|
+
"""
|
|
118
|
+
_raise_api_error(error_type=error_type, message=message, status=501, error_domain=ErrorDomain.CONFIG)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def raise_internal_server_error(message: str, error_type: ErrorType) -> NoReturn:
|
|
122
|
+
"""Raise a 500 RFC 7807 problem response for an API-owned server fault.
|
|
123
|
+
|
|
124
|
+
For the API's own configuration / invariant failures — a missing secret, a
|
|
125
|
+
storage backend that cannot presign, absent package metadata. NOT for
|
|
126
|
+
pipelex domain errors, which carry an `ErrorReport` and are handled by the
|
|
127
|
+
global `PipelexError` handler. Classified `CONFIG` domain: an operator, not
|
|
128
|
+
the caller, fixes it.
|
|
129
|
+
"""
|
|
130
|
+
_raise_api_error(error_type=error_type, message=message, status=500, error_domain=ErrorDomain.CONFIG)
|