perd-contracts 0.1.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.
- manifest_from_descriptor.py +209 -0
- perd/v1/account_connect.py +253 -0
- perd/v1/account_pb2.py +52 -0
- perd/v1/account_pb2.pyi +55 -0
- perd/v1/common_pb2.py +52 -0
- perd/v1/common_pb2.pyi +115 -0
- perd/v1/job_connect.py +253 -0
- perd/v1/job_pb2.py +80 -0
- perd/v1/job_pb2.pyi +223 -0
- perd/v1/py.typed +0 -0
- perd/v1/store_connect.py +383 -0
- perd/v1/store_pb2.py +70 -0
- perd/v1/store_pb2.pyi +170 -0
- perd/v1/worker_connect.py +188 -0
- perd/v1/worker_pb2.py +69 -0
- perd/v1/worker_pb2.pyi +154 -0
- perd/v1/worker_pb2_grpc.py +153 -0
- perd/v1/workstation_connect.py +448 -0
- perd/v1/workstation_pb2.py +73 -0
- perd/v1/workstation_pb2.pyi +166 -0
- perd_contracts-0.1.0.dist-info/METADATA +8 -0
- perd_contracts-0.1.0.dist-info/RECORD +23 -0
- perd_contracts-0.1.0.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
r"""Derive an :class:`OperationSpec` manifest from a ``FileDescriptorSet``.
|
|
2
|
+
|
|
3
|
+
This module is the mechanism that makes contract drift structurally impossible.
|
|
4
|
+
|
|
5
|
+
In the v1 system the operation manifest was untyped JSON written to Firestore by
|
|
6
|
+
the scaffold builder, while the ``.proto`` describing the same operations was
|
|
7
|
+
uploaded separately to GCS. Two independently-shipped descriptions of one
|
|
8
|
+
contract, cross-checked by nothing. A redeploy that updated one and not the
|
|
9
|
+
other surfaced as a field-level parse error deep inside a running job.
|
|
10
|
+
|
|
11
|
+
Here there is exactly one artifact -- the ``FileDescriptorSet`` embedded in the
|
|
12
|
+
worker image -- and the manifest is a *projection* of it. There is no second
|
|
13
|
+
description to drift from, and
|
|
14
|
+
|
|
15
|
+
.. math::
|
|
16
|
+
|
|
17
|
+
\mathrm{contract\_hash} = \operatorname{SHA256}\!\left(\mathrm{FileDescriptorSet}\right)
|
|
18
|
+
|
|
19
|
+
is the identity that the publisher, the client, and the orchestrator all pin to.
|
|
20
|
+
|
|
21
|
+
where:
|
|
22
|
+
|
|
23
|
+
- :math:`\mathrm{FileDescriptorSet}`: the serialized protobuf descriptor of a workflow's generated schema, produced once at build time and embedded in the worker image
|
|
24
|
+
- :math:`\mathrm{contract\_hash}`: the value stored on the published version, pinned by the client, and re-verified by the orchestrator at worker registration
|
|
25
|
+
|
|
26
|
+
Naming convention consumed here, emitted by the worker SDK's code generator:
|
|
27
|
+
|
|
28
|
+
- an operation ``foo_bar`` produces RPC ``FooBar`` with messages ``FooBarRequest`` and ``FooBarResponse``
|
|
29
|
+
- input-stream item fields live on the request message and are declared in the SDK-emitted ``perd.operation`` option; absent that, they are inferred from the RPC's client-streaming flag
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
from __future__ import annotations
|
|
33
|
+
|
|
34
|
+
import hashlib
|
|
35
|
+
import re
|
|
36
|
+
from dataclasses import dataclass
|
|
37
|
+
|
|
38
|
+
from google.protobuf import descriptor_pb2
|
|
39
|
+
|
|
40
|
+
# perd.v1.CallMode values, mirrored here so this tool has no import cycle back
|
|
41
|
+
# through generated code it may itself be used to produce.
|
|
42
|
+
CALL_MODE_UNARY = 1
|
|
43
|
+
CALL_MODE_INPUT_STREAM = 2
|
|
44
|
+
CALL_MODE_OUTPUT_STREAM = 3
|
|
45
|
+
CALL_MODE_BI_DI = 4
|
|
46
|
+
|
|
47
|
+
_MODE_BY_STREAMING = {
|
|
48
|
+
(False, False): CALL_MODE_UNARY,
|
|
49
|
+
(True, False): CALL_MODE_INPUT_STREAM,
|
|
50
|
+
(False, True): CALL_MODE_OUTPUT_STREAM,
|
|
51
|
+
(True, True): CALL_MODE_BI_DI,
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
_PROTO_TYPE_NAMES = {
|
|
55
|
+
descriptor_pb2.FieldDescriptorProto.TYPE_DOUBLE: "double",
|
|
56
|
+
descriptor_pb2.FieldDescriptorProto.TYPE_FLOAT: "float",
|
|
57
|
+
descriptor_pb2.FieldDescriptorProto.TYPE_INT64: "int64",
|
|
58
|
+
descriptor_pb2.FieldDescriptorProto.TYPE_UINT64: "uint64",
|
|
59
|
+
descriptor_pb2.FieldDescriptorProto.TYPE_INT32: "int32",
|
|
60
|
+
descriptor_pb2.FieldDescriptorProto.TYPE_BOOL: "bool",
|
|
61
|
+
descriptor_pb2.FieldDescriptorProto.TYPE_STRING: "string",
|
|
62
|
+
descriptor_pb2.FieldDescriptorProto.TYPE_BYTES: "bytes",
|
|
63
|
+
descriptor_pb2.FieldDescriptorProto.TYPE_UINT32: "uint32",
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
_STREAM_ITEM_RE = re.compile(r"^item_(\d+)$")
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class ManifestError(ValueError):
|
|
70
|
+
"""Raised when a descriptor set cannot yield a well-formed manifest."""
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
@dataclass(frozen=True, slots=True)
|
|
74
|
+
class Field:
|
|
75
|
+
"""One parameter or result field projected from a descriptor."""
|
|
76
|
+
|
|
77
|
+
name: str
|
|
78
|
+
proto_type: str
|
|
79
|
+
field_number: int
|
|
80
|
+
optional: bool
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
@dataclass(frozen=True, slots=True)
|
|
84
|
+
class Operation:
|
|
85
|
+
"""One callable operation, fully described by the descriptor set."""
|
|
86
|
+
|
|
87
|
+
function_name: str
|
|
88
|
+
rpc_name: str
|
|
89
|
+
mode: int
|
|
90
|
+
params: tuple[Field, ...]
|
|
91
|
+
input_stream_fields: tuple[Field, ...]
|
|
92
|
+
output_fields: tuple[Field, ...]
|
|
93
|
+
docstring: str | None = None
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def contract_hash(descriptor_set: bytes) -> str:
|
|
97
|
+
r"""Return the canonical contract identity for a descriptor set.
|
|
98
|
+
|
|
99
|
+
.. math::
|
|
100
|
+
|
|
101
|
+
h = \operatorname{SHA256}(D)
|
|
102
|
+
|
|
103
|
+
where:
|
|
104
|
+
|
|
105
|
+
- :math:`D`: the serialized ``FileDescriptorSet`` bytes exactly as embedded in the worker image
|
|
106
|
+
- :math:`h`: lowercase hex digest, compared with :func:`hmac.compare_digest` at registration
|
|
107
|
+
"""
|
|
108
|
+
return hashlib.sha256(descriptor_set).hexdigest()
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def _snake_case(name: str) -> str:
|
|
112
|
+
"""``FooBar`` -> ``foo_bar``. Inverse of the SDK's RPC naming rule."""
|
|
113
|
+
return re.sub(r"(?<!^)(?=[A-Z])", "_", name).lower()
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def _fields_of(msg: descriptor_pb2.DescriptorProto) -> tuple[Field, ...]:
|
|
117
|
+
out = []
|
|
118
|
+
for f in msg.field:
|
|
119
|
+
proto_type = _PROTO_TYPE_NAMES.get(f.type)
|
|
120
|
+
if proto_type is None:
|
|
121
|
+
raise ManifestError(
|
|
122
|
+
f"Field '{msg.name}.{f.name}' has unsupported type {f.type}. "
|
|
123
|
+
"Workflow signatures may only use scalar types."
|
|
124
|
+
)
|
|
125
|
+
out.append(
|
|
126
|
+
Field(
|
|
127
|
+
name=f.name,
|
|
128
|
+
proto_type=proto_type,
|
|
129
|
+
field_number=f.number,
|
|
130
|
+
# proto3 explicit presence: the SDK marks every result field
|
|
131
|
+
# `optional` so a returned 0 / "" / False is distinguishable
|
|
132
|
+
# from an absent field. v1's MessageToDict elided all of them.
|
|
133
|
+
optional=f.proto3_optional,
|
|
134
|
+
)
|
|
135
|
+
)
|
|
136
|
+
return tuple(out)
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def _partition_request_fields(
|
|
140
|
+
fields: tuple[Field, ...], client_streaming: bool
|
|
141
|
+
) -> tuple[tuple[Field, ...], tuple[Field, ...]]:
|
|
142
|
+
"""Split request fields into (per-call params, per-stream-item fields).
|
|
143
|
+
|
|
144
|
+
Stream item fields are named ``item_1``, ``item_2``, ... by the SDK's
|
|
145
|
+
generator. Everything else is a trailing unary parameter, which is the
|
|
146
|
+
shape DCA_PINN uses: a 7-tuple input stream plus 12 hyperparameters.
|
|
147
|
+
"""
|
|
148
|
+
if not client_streaming:
|
|
149
|
+
return fields, ()
|
|
150
|
+
matches = {f.name: _STREAM_ITEM_RE.match(f.name) for f in fields}
|
|
151
|
+
items = [f for f in fields if matches[f.name]]
|
|
152
|
+
params = [f for f in fields if not matches[f.name]]
|
|
153
|
+
|
|
154
|
+
def item_index(f: Field) -> int:
|
|
155
|
+
match = matches[f.name]
|
|
156
|
+
assert match is not None # items was filtered on exactly this
|
|
157
|
+
return int(match.group(1))
|
|
158
|
+
|
|
159
|
+
items.sort(key=item_index)
|
|
160
|
+
return tuple(params), tuple(items)
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def build_manifest(descriptor_set: bytes) -> tuple[Operation, ...]:
|
|
164
|
+
"""Project every RPC in ``descriptor_set`` into an :class:`Operation`.
|
|
165
|
+
|
|
166
|
+
Raises:
|
|
167
|
+
ManifestError: if the set has no service, or references a message type
|
|
168
|
+
that is not defined within the same set.
|
|
169
|
+
"""
|
|
170
|
+
fds = descriptor_pb2.FileDescriptorSet()
|
|
171
|
+
fds.ParseFromString(descriptor_set)
|
|
172
|
+
|
|
173
|
+
messages: dict[str, descriptor_pb2.DescriptorProto] = {}
|
|
174
|
+
services: list[descriptor_pb2.ServiceDescriptorProto] = []
|
|
175
|
+
for file in fds.file:
|
|
176
|
+
pkg = file.package
|
|
177
|
+
for msg in file.message_type:
|
|
178
|
+
messages[f".{pkg}.{msg.name}" if pkg else f".{msg.name}"] = msg
|
|
179
|
+
services.extend(file.service)
|
|
180
|
+
|
|
181
|
+
if not services:
|
|
182
|
+
raise ManifestError("Descriptor set defines no service.")
|
|
183
|
+
|
|
184
|
+
operations: list[Operation] = []
|
|
185
|
+
for service in services:
|
|
186
|
+
for method in service.method:
|
|
187
|
+
req = messages.get(method.input_type)
|
|
188
|
+
res = messages.get(method.output_type)
|
|
189
|
+
if req is None or res is None:
|
|
190
|
+
raise ManifestError(
|
|
191
|
+
f"RPC '{method.name}' references a message outside the "
|
|
192
|
+
f"descriptor set ({method.input_type} / {method.output_type})."
|
|
193
|
+
)
|
|
194
|
+
params, stream_fields = _partition_request_fields(
|
|
195
|
+
_fields_of(req), method.client_streaming
|
|
196
|
+
)
|
|
197
|
+
operations.append(
|
|
198
|
+
Operation(
|
|
199
|
+
function_name=_snake_case(method.name),
|
|
200
|
+
rpc_name=method.name,
|
|
201
|
+
mode=_MODE_BY_STREAMING[
|
|
202
|
+
(method.client_streaming, method.server_streaming)
|
|
203
|
+
],
|
|
204
|
+
params=params,
|
|
205
|
+
input_stream_fields=stream_fields,
|
|
206
|
+
output_fields=_fields_of(res),
|
|
207
|
+
)
|
|
208
|
+
)
|
|
209
|
+
return tuple(operations)
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Generated by https://github.com/connectrpc/connect-python. DO NOT EDIT!
|
|
3
|
+
# source: perd/v1/account.proto
|
|
4
|
+
|
|
5
|
+
from collections.abc import AsyncGenerator, AsyncIterator, Iterable, Iterator, Mapping
|
|
6
|
+
from typing import Protocol
|
|
7
|
+
|
|
8
|
+
from connectrpc.client import ConnectClient, ConnectClientSync
|
|
9
|
+
from connectrpc.code import Code
|
|
10
|
+
from connectrpc.compression import Compression
|
|
11
|
+
from connectrpc.errors import ConnectError
|
|
12
|
+
from connectrpc.interceptor import Interceptor, InterceptorSync
|
|
13
|
+
from connectrpc.method import IdempotencyLevel, MethodInfo
|
|
14
|
+
from connectrpc.request import Headers, RequestContext
|
|
15
|
+
from connectrpc.server import ConnectASGIApplication, ConnectWSGIApplication, Endpoint, EndpointSync
|
|
16
|
+
import perd.v1.account_pb2 as perd_dot_v1_dot_account__pb2
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class AccountService(Protocol):
|
|
20
|
+
async def list_api_keys(self, request: perd_dot_v1_dot_account__pb2.ListApiKeysRequest, ctx: RequestContext) -> perd_dot_v1_dot_account__pb2.ListApiKeysResponse:
|
|
21
|
+
raise ConnectError(Code.UNIMPLEMENTED, "Not implemented")
|
|
22
|
+
|
|
23
|
+
async def issue_api_key(self, request: perd_dot_v1_dot_account__pb2.IssueApiKeyRequest, ctx: RequestContext) -> perd_dot_v1_dot_account__pb2.IssueApiKeyResponse:
|
|
24
|
+
raise ConnectError(Code.UNIMPLEMENTED, "Not implemented")
|
|
25
|
+
|
|
26
|
+
async def revoke_api_key(self, request: perd_dot_v1_dot_account__pb2.RevokeApiKeyRequest, ctx: RequestContext) -> perd_dot_v1_dot_account__pb2.RevokeApiKeyResponse:
|
|
27
|
+
raise ConnectError(Code.UNIMPLEMENTED, "Not implemented")
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class AccountServiceASGIApplication(ConnectASGIApplication[AccountService]):
|
|
31
|
+
def __init__(self, service: AccountService | AsyncGenerator[AccountService], *, interceptors: Iterable[Interceptor]=(), read_max_bytes: int | None = None, compressions: Iterable[Compression] | None = None) -> None:
|
|
32
|
+
super().__init__(
|
|
33
|
+
service=service,
|
|
34
|
+
endpoints=lambda svc: {
|
|
35
|
+
"/perd.v1.AccountService/ListApiKeys": Endpoint.unary(
|
|
36
|
+
method=MethodInfo(
|
|
37
|
+
name="ListApiKeys",
|
|
38
|
+
service_name="perd.v1.AccountService",
|
|
39
|
+
input=perd_dot_v1_dot_account__pb2.ListApiKeysRequest,
|
|
40
|
+
output=perd_dot_v1_dot_account__pb2.ListApiKeysResponse,
|
|
41
|
+
idempotency_level=IdempotencyLevel.UNKNOWN,
|
|
42
|
+
),
|
|
43
|
+
function=svc.list_api_keys,
|
|
44
|
+
),
|
|
45
|
+
"/perd.v1.AccountService/IssueApiKey": Endpoint.unary(
|
|
46
|
+
method=MethodInfo(
|
|
47
|
+
name="IssueApiKey",
|
|
48
|
+
service_name="perd.v1.AccountService",
|
|
49
|
+
input=perd_dot_v1_dot_account__pb2.IssueApiKeyRequest,
|
|
50
|
+
output=perd_dot_v1_dot_account__pb2.IssueApiKeyResponse,
|
|
51
|
+
idempotency_level=IdempotencyLevel.UNKNOWN,
|
|
52
|
+
),
|
|
53
|
+
function=svc.issue_api_key,
|
|
54
|
+
),
|
|
55
|
+
"/perd.v1.AccountService/RevokeApiKey": Endpoint.unary(
|
|
56
|
+
method=MethodInfo(
|
|
57
|
+
name="RevokeApiKey",
|
|
58
|
+
service_name="perd.v1.AccountService",
|
|
59
|
+
input=perd_dot_v1_dot_account__pb2.RevokeApiKeyRequest,
|
|
60
|
+
output=perd_dot_v1_dot_account__pb2.RevokeApiKeyResponse,
|
|
61
|
+
idempotency_level=IdempotencyLevel.UNKNOWN,
|
|
62
|
+
),
|
|
63
|
+
function=svc.revoke_api_key,
|
|
64
|
+
),
|
|
65
|
+
},
|
|
66
|
+
interceptors=interceptors,
|
|
67
|
+
read_max_bytes=read_max_bytes,
|
|
68
|
+
compressions=compressions,
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
@property
|
|
72
|
+
def path(self) -> str:
|
|
73
|
+
"""Returns the URL path to mount the application to when serving multiple applications."""
|
|
74
|
+
return "/perd.v1.AccountService"
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class AccountServiceClient(ConnectClient):
|
|
78
|
+
async def list_api_keys(
|
|
79
|
+
self,
|
|
80
|
+
request: perd_dot_v1_dot_account__pb2.ListApiKeysRequest,
|
|
81
|
+
*,
|
|
82
|
+
headers: Headers | Mapping[str, str] | None = None,
|
|
83
|
+
timeout_ms: int | None = None,
|
|
84
|
+
) -> perd_dot_v1_dot_account__pb2.ListApiKeysResponse:
|
|
85
|
+
return await self.execute_unary(
|
|
86
|
+
request=request,
|
|
87
|
+
method=MethodInfo(
|
|
88
|
+
name="ListApiKeys",
|
|
89
|
+
service_name="perd.v1.AccountService",
|
|
90
|
+
input=perd_dot_v1_dot_account__pb2.ListApiKeysRequest,
|
|
91
|
+
output=perd_dot_v1_dot_account__pb2.ListApiKeysResponse,
|
|
92
|
+
idempotency_level=IdempotencyLevel.UNKNOWN,
|
|
93
|
+
),
|
|
94
|
+
headers=headers,
|
|
95
|
+
timeout_ms=timeout_ms,
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
async def issue_api_key(
|
|
99
|
+
self,
|
|
100
|
+
request: perd_dot_v1_dot_account__pb2.IssueApiKeyRequest,
|
|
101
|
+
*,
|
|
102
|
+
headers: Headers | Mapping[str, str] | None = None,
|
|
103
|
+
timeout_ms: int | None = None,
|
|
104
|
+
) -> perd_dot_v1_dot_account__pb2.IssueApiKeyResponse:
|
|
105
|
+
return await self.execute_unary(
|
|
106
|
+
request=request,
|
|
107
|
+
method=MethodInfo(
|
|
108
|
+
name="IssueApiKey",
|
|
109
|
+
service_name="perd.v1.AccountService",
|
|
110
|
+
input=perd_dot_v1_dot_account__pb2.IssueApiKeyRequest,
|
|
111
|
+
output=perd_dot_v1_dot_account__pb2.IssueApiKeyResponse,
|
|
112
|
+
idempotency_level=IdempotencyLevel.UNKNOWN,
|
|
113
|
+
),
|
|
114
|
+
headers=headers,
|
|
115
|
+
timeout_ms=timeout_ms,
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
async def revoke_api_key(
|
|
119
|
+
self,
|
|
120
|
+
request: perd_dot_v1_dot_account__pb2.RevokeApiKeyRequest,
|
|
121
|
+
*,
|
|
122
|
+
headers: Headers | Mapping[str, str] | None = None,
|
|
123
|
+
timeout_ms: int | None = None,
|
|
124
|
+
) -> perd_dot_v1_dot_account__pb2.RevokeApiKeyResponse:
|
|
125
|
+
return await self.execute_unary(
|
|
126
|
+
request=request,
|
|
127
|
+
method=MethodInfo(
|
|
128
|
+
name="RevokeApiKey",
|
|
129
|
+
service_name="perd.v1.AccountService",
|
|
130
|
+
input=perd_dot_v1_dot_account__pb2.RevokeApiKeyRequest,
|
|
131
|
+
output=perd_dot_v1_dot_account__pb2.RevokeApiKeyResponse,
|
|
132
|
+
idempotency_level=IdempotencyLevel.UNKNOWN,
|
|
133
|
+
),
|
|
134
|
+
headers=headers,
|
|
135
|
+
timeout_ms=timeout_ms,
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
class AccountServiceSync(Protocol):
|
|
140
|
+
def list_api_keys(self, request: perd_dot_v1_dot_account__pb2.ListApiKeysRequest, ctx: RequestContext) -> perd_dot_v1_dot_account__pb2.ListApiKeysResponse:
|
|
141
|
+
raise ConnectError(Code.UNIMPLEMENTED, "Not implemented")
|
|
142
|
+
def issue_api_key(self, request: perd_dot_v1_dot_account__pb2.IssueApiKeyRequest, ctx: RequestContext) -> perd_dot_v1_dot_account__pb2.IssueApiKeyResponse:
|
|
143
|
+
raise ConnectError(Code.UNIMPLEMENTED, "Not implemented")
|
|
144
|
+
def revoke_api_key(self, request: perd_dot_v1_dot_account__pb2.RevokeApiKeyRequest, ctx: RequestContext) -> perd_dot_v1_dot_account__pb2.RevokeApiKeyResponse:
|
|
145
|
+
raise ConnectError(Code.UNIMPLEMENTED, "Not implemented")
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
class AccountServiceWSGIApplication(ConnectWSGIApplication):
|
|
149
|
+
def __init__(self, service: AccountServiceSync, interceptors: Iterable[InterceptorSync]=(), read_max_bytes: int | None = None, compressions: Iterable[Compression] | None = None) -> None:
|
|
150
|
+
super().__init__(
|
|
151
|
+
endpoints={
|
|
152
|
+
"/perd.v1.AccountService/ListApiKeys": EndpointSync.unary(
|
|
153
|
+
method=MethodInfo(
|
|
154
|
+
name="ListApiKeys",
|
|
155
|
+
service_name="perd.v1.AccountService",
|
|
156
|
+
input=perd_dot_v1_dot_account__pb2.ListApiKeysRequest,
|
|
157
|
+
output=perd_dot_v1_dot_account__pb2.ListApiKeysResponse,
|
|
158
|
+
idempotency_level=IdempotencyLevel.UNKNOWN,
|
|
159
|
+
),
|
|
160
|
+
function=service.list_api_keys,
|
|
161
|
+
),
|
|
162
|
+
"/perd.v1.AccountService/IssueApiKey": EndpointSync.unary(
|
|
163
|
+
method=MethodInfo(
|
|
164
|
+
name="IssueApiKey",
|
|
165
|
+
service_name="perd.v1.AccountService",
|
|
166
|
+
input=perd_dot_v1_dot_account__pb2.IssueApiKeyRequest,
|
|
167
|
+
output=perd_dot_v1_dot_account__pb2.IssueApiKeyResponse,
|
|
168
|
+
idempotency_level=IdempotencyLevel.UNKNOWN,
|
|
169
|
+
),
|
|
170
|
+
function=service.issue_api_key,
|
|
171
|
+
),
|
|
172
|
+
"/perd.v1.AccountService/RevokeApiKey": EndpointSync.unary(
|
|
173
|
+
method=MethodInfo(
|
|
174
|
+
name="RevokeApiKey",
|
|
175
|
+
service_name="perd.v1.AccountService",
|
|
176
|
+
input=perd_dot_v1_dot_account__pb2.RevokeApiKeyRequest,
|
|
177
|
+
output=perd_dot_v1_dot_account__pb2.RevokeApiKeyResponse,
|
|
178
|
+
idempotency_level=IdempotencyLevel.UNKNOWN,
|
|
179
|
+
),
|
|
180
|
+
function=service.revoke_api_key,
|
|
181
|
+
),
|
|
182
|
+
},
|
|
183
|
+
interceptors=interceptors,
|
|
184
|
+
read_max_bytes=read_max_bytes,
|
|
185
|
+
compressions=compressions,
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
@property
|
|
189
|
+
def path(self) -> str:
|
|
190
|
+
"""Returns the URL path to mount the application to when serving multiple applications."""
|
|
191
|
+
return "/perd.v1.AccountService"
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
class AccountServiceClientSync(ConnectClientSync):
|
|
195
|
+
def list_api_keys(
|
|
196
|
+
self,
|
|
197
|
+
request: perd_dot_v1_dot_account__pb2.ListApiKeysRequest,
|
|
198
|
+
*,
|
|
199
|
+
headers: Headers | Mapping[str, str] | None = None,
|
|
200
|
+
timeout_ms: int | None = None,
|
|
201
|
+
) -> perd_dot_v1_dot_account__pb2.ListApiKeysResponse:
|
|
202
|
+
return self.execute_unary(
|
|
203
|
+
request=request,
|
|
204
|
+
method=MethodInfo(
|
|
205
|
+
name="ListApiKeys",
|
|
206
|
+
service_name="perd.v1.AccountService",
|
|
207
|
+
input=perd_dot_v1_dot_account__pb2.ListApiKeysRequest,
|
|
208
|
+
output=perd_dot_v1_dot_account__pb2.ListApiKeysResponse,
|
|
209
|
+
idempotency_level=IdempotencyLevel.UNKNOWN,
|
|
210
|
+
),
|
|
211
|
+
headers=headers,
|
|
212
|
+
timeout_ms=timeout_ms,
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
def issue_api_key(
|
|
216
|
+
self,
|
|
217
|
+
request: perd_dot_v1_dot_account__pb2.IssueApiKeyRequest,
|
|
218
|
+
*,
|
|
219
|
+
headers: Headers | Mapping[str, str] | None = None,
|
|
220
|
+
timeout_ms: int | None = None,
|
|
221
|
+
) -> perd_dot_v1_dot_account__pb2.IssueApiKeyResponse:
|
|
222
|
+
return self.execute_unary(
|
|
223
|
+
request=request,
|
|
224
|
+
method=MethodInfo(
|
|
225
|
+
name="IssueApiKey",
|
|
226
|
+
service_name="perd.v1.AccountService",
|
|
227
|
+
input=perd_dot_v1_dot_account__pb2.IssueApiKeyRequest,
|
|
228
|
+
output=perd_dot_v1_dot_account__pb2.IssueApiKeyResponse,
|
|
229
|
+
idempotency_level=IdempotencyLevel.UNKNOWN,
|
|
230
|
+
),
|
|
231
|
+
headers=headers,
|
|
232
|
+
timeout_ms=timeout_ms,
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
def revoke_api_key(
|
|
236
|
+
self,
|
|
237
|
+
request: perd_dot_v1_dot_account__pb2.RevokeApiKeyRequest,
|
|
238
|
+
*,
|
|
239
|
+
headers: Headers | Mapping[str, str] | None = None,
|
|
240
|
+
timeout_ms: int | None = None,
|
|
241
|
+
) -> perd_dot_v1_dot_account__pb2.RevokeApiKeyResponse:
|
|
242
|
+
return self.execute_unary(
|
|
243
|
+
request=request,
|
|
244
|
+
method=MethodInfo(
|
|
245
|
+
name="RevokeApiKey",
|
|
246
|
+
service_name="perd.v1.AccountService",
|
|
247
|
+
input=perd_dot_v1_dot_account__pb2.RevokeApiKeyRequest,
|
|
248
|
+
output=perd_dot_v1_dot_account__pb2.RevokeApiKeyResponse,
|
|
249
|
+
idempotency_level=IdempotencyLevel.UNKNOWN,
|
|
250
|
+
),
|
|
251
|
+
headers=headers,
|
|
252
|
+
timeout_ms=timeout_ms,
|
|
253
|
+
)
|
perd/v1/account_pb2.py
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
|
3
|
+
# NO CHECKED-IN PROTOBUF GENCODE
|
|
4
|
+
# source: perd/v1/account.proto
|
|
5
|
+
# Protobuf Python Version: 5.29.3
|
|
6
|
+
"""Generated protocol buffer code."""
|
|
7
|
+
from google.protobuf import descriptor as _descriptor
|
|
8
|
+
from google.protobuf import descriptor_pool as _descriptor_pool
|
|
9
|
+
from google.protobuf import runtime_version as _runtime_version
|
|
10
|
+
from google.protobuf import symbol_database as _symbol_database
|
|
11
|
+
from google.protobuf.internal import builder as _builder
|
|
12
|
+
_runtime_version.ValidateProtobufRuntimeVersion(
|
|
13
|
+
_runtime_version.Domain.PUBLIC,
|
|
14
|
+
5,
|
|
15
|
+
29,
|
|
16
|
+
3,
|
|
17
|
+
'',
|
|
18
|
+
'perd/v1/account.proto'
|
|
19
|
+
)
|
|
20
|
+
# @@protoc_insertion_point(imports)
|
|
21
|
+
|
|
22
|
+
_sym_db = _symbol_database.Default()
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15perd/v1/account.proto\x12\x07perd.v1\x1a\x1fgoogle/protobuf/timestamp.proto\"\xcc\x01\n\x06\x41piKey\x12\x15\n\x06key_id\x18\x01 \x01(\tR\x05keyId\x12!\n\x0c\x64isplay_name\x18\x02 \x01(\tR\x0b\x64isplayName\x12\x39\n\ncreated_at\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tcreatedAt\x12>\n\nrevoked_at\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.TimestampH\x00R\trevokedAt\x88\x01\x01\x42\r\n\x0b_revoked_at\"\x14\n\x12ListApiKeysRequest\":\n\x13ListApiKeysResponse\x12#\n\x04keys\x18\x01 \x03(\x0b\x32\x0f.perd.v1.ApiKeyR\x04keys\"7\n\x12IssueApiKeyRequest\x12!\n\x0c\x64isplay_name\x18\x01 \x01(\tR\x0b\x64isplayName\"Q\n\x13IssueApiKeyResponse\x12!\n\x03key\x18\x01 \x01(\x0b\x32\x0f.perd.v1.ApiKeyR\x03key\x12\x17\n\x07\x61pi_key\x18\x02 \x01(\tR\x06\x61piKey\",\n\x13RevokeApiKeyRequest\x12\x15\n\x06key_id\x18\x01 \x01(\tR\x05keyId\"9\n\x14RevokeApiKeyResponse\x12!\n\x03key\x18\x01 \x01(\x0b\x32\x0f.perd.v1.ApiKeyR\x03key2\xf1\x01\n\x0e\x41\x63\x63ountService\x12H\n\x0bListApiKeys\x12\x1b.perd.v1.ListApiKeysRequest\x1a\x1c.perd.v1.ListApiKeysResponse\x12H\n\x0bIssueApiKey\x12\x1b.perd.v1.IssueApiKeyRequest\x1a\x1c.perd.v1.IssueApiKeyResponse\x12K\n\x0cRevokeApiKey\x12\x1c.perd.v1.RevokeApiKeyRequest\x1a\x1d.perd.v1.RevokeApiKeyResponseBX\n\x0b\x63om.perd.v1B\x0c\x41\x63\x63ountProtoP\x01\xa2\x02\x03PXX\xaa\x02\x07Perd.V1\xca\x02\x07Perd\\V1\xe2\x02\x13Perd\\V1\\GPBMetadata\xea\x02\x08Perd::V1b\x06proto3')
|
|
29
|
+
|
|
30
|
+
_globals = globals()
|
|
31
|
+
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
|
32
|
+
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'perd.v1.account_pb2', _globals)
|
|
33
|
+
if not _descriptor._USE_C_DESCRIPTORS:
|
|
34
|
+
_globals['DESCRIPTOR']._loaded_options = None
|
|
35
|
+
_globals['DESCRIPTOR']._serialized_options = b'\n\013com.perd.v1B\014AccountProtoP\001\242\002\003PXX\252\002\007Perd.V1\312\002\007Perd\\V1\342\002\023Perd\\V1\\GPBMetadata\352\002\010Perd::V1'
|
|
36
|
+
_globals['_APIKEY']._serialized_start=68
|
|
37
|
+
_globals['_APIKEY']._serialized_end=272
|
|
38
|
+
_globals['_LISTAPIKEYSREQUEST']._serialized_start=274
|
|
39
|
+
_globals['_LISTAPIKEYSREQUEST']._serialized_end=294
|
|
40
|
+
_globals['_LISTAPIKEYSRESPONSE']._serialized_start=296
|
|
41
|
+
_globals['_LISTAPIKEYSRESPONSE']._serialized_end=354
|
|
42
|
+
_globals['_ISSUEAPIKEYREQUEST']._serialized_start=356
|
|
43
|
+
_globals['_ISSUEAPIKEYREQUEST']._serialized_end=411
|
|
44
|
+
_globals['_ISSUEAPIKEYRESPONSE']._serialized_start=413
|
|
45
|
+
_globals['_ISSUEAPIKEYRESPONSE']._serialized_end=494
|
|
46
|
+
_globals['_REVOKEAPIKEYREQUEST']._serialized_start=496
|
|
47
|
+
_globals['_REVOKEAPIKEYREQUEST']._serialized_end=540
|
|
48
|
+
_globals['_REVOKEAPIKEYRESPONSE']._serialized_start=542
|
|
49
|
+
_globals['_REVOKEAPIKEYRESPONSE']._serialized_end=599
|
|
50
|
+
_globals['_ACCOUNTSERVICE']._serialized_start=602
|
|
51
|
+
_globals['_ACCOUNTSERVICE']._serialized_end=843
|
|
52
|
+
# @@protoc_insertion_point(module_scope)
|
perd/v1/account_pb2.pyi
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
from google.protobuf import timestamp_pb2 as _timestamp_pb2
|
|
2
|
+
from google.protobuf.internal import containers as _containers
|
|
3
|
+
from google.protobuf import descriptor as _descriptor
|
|
4
|
+
from google.protobuf import message as _message
|
|
5
|
+
from typing import ClassVar as _ClassVar, Iterable as _Iterable, Mapping as _Mapping, Optional as _Optional, Union as _Union
|
|
6
|
+
|
|
7
|
+
DESCRIPTOR: _descriptor.FileDescriptor
|
|
8
|
+
|
|
9
|
+
class ApiKey(_message.Message):
|
|
10
|
+
__slots__ = ("key_id", "display_name", "created_at", "revoked_at")
|
|
11
|
+
KEY_ID_FIELD_NUMBER: _ClassVar[int]
|
|
12
|
+
DISPLAY_NAME_FIELD_NUMBER: _ClassVar[int]
|
|
13
|
+
CREATED_AT_FIELD_NUMBER: _ClassVar[int]
|
|
14
|
+
REVOKED_AT_FIELD_NUMBER: _ClassVar[int]
|
|
15
|
+
key_id: str
|
|
16
|
+
display_name: str
|
|
17
|
+
created_at: _timestamp_pb2.Timestamp
|
|
18
|
+
revoked_at: _timestamp_pb2.Timestamp
|
|
19
|
+
def __init__(self, key_id: _Optional[str] = ..., display_name: _Optional[str] = ..., created_at: _Optional[_Union[_timestamp_pb2.Timestamp, _Mapping]] = ..., revoked_at: _Optional[_Union[_timestamp_pb2.Timestamp, _Mapping]] = ...) -> None: ...
|
|
20
|
+
|
|
21
|
+
class ListApiKeysRequest(_message.Message):
|
|
22
|
+
__slots__ = ()
|
|
23
|
+
def __init__(self) -> None: ...
|
|
24
|
+
|
|
25
|
+
class ListApiKeysResponse(_message.Message):
|
|
26
|
+
__slots__ = ("keys",)
|
|
27
|
+
KEYS_FIELD_NUMBER: _ClassVar[int]
|
|
28
|
+
keys: _containers.RepeatedCompositeFieldContainer[ApiKey]
|
|
29
|
+
def __init__(self, keys: _Optional[_Iterable[_Union[ApiKey, _Mapping]]] = ...) -> None: ...
|
|
30
|
+
|
|
31
|
+
class IssueApiKeyRequest(_message.Message):
|
|
32
|
+
__slots__ = ("display_name",)
|
|
33
|
+
DISPLAY_NAME_FIELD_NUMBER: _ClassVar[int]
|
|
34
|
+
display_name: str
|
|
35
|
+
def __init__(self, display_name: _Optional[str] = ...) -> None: ...
|
|
36
|
+
|
|
37
|
+
class IssueApiKeyResponse(_message.Message):
|
|
38
|
+
__slots__ = ("key", "api_key")
|
|
39
|
+
KEY_FIELD_NUMBER: _ClassVar[int]
|
|
40
|
+
API_KEY_FIELD_NUMBER: _ClassVar[int]
|
|
41
|
+
key: ApiKey
|
|
42
|
+
api_key: str
|
|
43
|
+
def __init__(self, key: _Optional[_Union[ApiKey, _Mapping]] = ..., api_key: _Optional[str] = ...) -> None: ...
|
|
44
|
+
|
|
45
|
+
class RevokeApiKeyRequest(_message.Message):
|
|
46
|
+
__slots__ = ("key_id",)
|
|
47
|
+
KEY_ID_FIELD_NUMBER: _ClassVar[int]
|
|
48
|
+
key_id: str
|
|
49
|
+
def __init__(self, key_id: _Optional[str] = ...) -> None: ...
|
|
50
|
+
|
|
51
|
+
class RevokeApiKeyResponse(_message.Message):
|
|
52
|
+
__slots__ = ("key",)
|
|
53
|
+
KEY_FIELD_NUMBER: _ClassVar[int]
|
|
54
|
+
key: ApiKey
|
|
55
|
+
def __init__(self, key: _Optional[_Union[ApiKey, _Mapping]] = ...) -> None: ...
|
perd/v1/common_pb2.py
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
|
3
|
+
# NO CHECKED-IN PROTOBUF GENCODE
|
|
4
|
+
# source: perd/v1/common.proto
|
|
5
|
+
# Protobuf Python Version: 5.29.3
|
|
6
|
+
"""Generated protocol buffer code."""
|
|
7
|
+
from google.protobuf import descriptor as _descriptor
|
|
8
|
+
from google.protobuf import descriptor_pool as _descriptor_pool
|
|
9
|
+
from google.protobuf import runtime_version as _runtime_version
|
|
10
|
+
from google.protobuf import symbol_database as _symbol_database
|
|
11
|
+
from google.protobuf.internal import builder as _builder
|
|
12
|
+
_runtime_version.ValidateProtobufRuntimeVersion(
|
|
13
|
+
_runtime_version.Domain.PUBLIC,
|
|
14
|
+
5,
|
|
15
|
+
29,
|
|
16
|
+
3,
|
|
17
|
+
'',
|
|
18
|
+
'perd/v1/common.proto'
|
|
19
|
+
)
|
|
20
|
+
# @@protoc_insertion_point(imports)
|
|
21
|
+
|
|
22
|
+
_sym_db = _symbol_database.Default()
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x14perd/v1/common.proto\x12\x07perd.v1\x1a\x1fgoogle/protobuf/timestamp.proto\"\x8d\x02\n\x07\x46\x61ilure\x12(\n\x04\x63ode\x18\x01 \x01(\x0e\x32\x14.perd.v1.FailureCodeR\x04\x63ode\x12\x18\n\x07message\x18\x02 \x01(\tR\x07message\x12\x1c\n\tretryable\x18\x03 \x01(\x08R\tretryable\x12)\n\x0eretry_after_ms\x18\x04 \x01(\rH\x00R\x0cretryAfterMs\x88\x01\x01\x12%\n\x0bremediation\x18\x05 \x01(\tH\x01R\x0bremediation\x88\x01\x01\x12\x1e\n\x08trace_id\x18\x06 \x01(\tH\x02R\x07traceId\x88\x01\x01\x42\x11\n\x0f_retry_after_msB\x0e\n\x0c_remediationB\x0b\n\t_trace_id\"m\n\x0bWorkflowRef\x12\x1f\n\x0bworkflow_id\x18\x01 \x01(\tR\nworkflowId\x12\x18\n\x07version\x18\x02 \x01(\tR\x07version\x12#\n\rcontract_hash\x18\x03 \x01(\tR\x0c\x63ontractHash\"b\n\x05\x41\x63tor\x12\x17\n\x07user_id\x18\x01 \x01(\tR\x06userId\x12,\n\x0forganization_id\x18\x02 \x01(\tH\x00R\x0eorganizationId\x88\x01\x01\x42\x12\n\x10_organization_id\"\xc5\x01\n\nAuditStamp\x12\x39\n\ncreated_at\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tcreatedAt\x12>\n\nupdated_at\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.TimestampH\x00R\tupdatedAt\x88\x01\x01\x12-\n\ncreated_by\x18\x03 \x01(\x0b\x32\x0e.perd.v1.ActorR\tcreatedByB\r\n\x0b_updated_at\"]\n\x0bPageRequest\x12\x1b\n\tpage_size\x18\x01 \x01(\rR\x08pageSize\x12\"\n\npage_token\x18\x02 \x01(\tH\x00R\tpageToken\x88\x01\x01\x42\r\n\x0b_page_token\"\x82\x01\n\x0cPageResponse\x12+\n\x0fnext_page_token\x18\x01 \x01(\tH\x00R\rnextPageToken\x88\x01\x01\x12\"\n\ntotal_size\x18\x02 \x01(\rH\x01R\ttotalSize\x88\x01\x01\x42\x12\n\x10_next_page_tokenB\r\n\x0b_total_size*\x84\x04\n\x0b\x46\x61ilureCode\x12\x1c\n\x18\x46\x41ILURE_CODE_UNSPECIFIED\x10\x00\x12!\n\x1d\x46\x41ILURE_CODE_INVALID_ARGUMENT\x10\x01\x12 \n\x1c\x46\x41ILURE_CODE_UNAUTHENTICATED\x10\x02\x12\"\n\x1e\x46\x41ILURE_CODE_PERMISSION_DENIED\x10\x03\x12\x1a\n\x16\x46\x41ILURE_CODE_NOT_FOUND\x10\x04\x12\x1f\n\x1b\x46\x41ILURE_CODE_ALREADY_EXISTS\x10\x05\x12#\n\x1f\x46\x41ILURE_CODE_RESOURCE_EXHAUSTED\x10\x06\x12\"\n\x1e\x46\x41ILURE_CODE_DEADLINE_EXCEEDED\x10\x07\x12\x1a\n\x16\x46\x41ILURE_CODE_CANCELLED\x10\x08\x12\"\n\x1e\x46\x41ILURE_CODE_CONTRACT_MISMATCH\x10\x14\x12&\n\"FAILURE_CODE_RESUME_WINDOW_EXPIRED\x10\x15\x12\x19\n\x15\x46\x41ILURE_CODE_INTERNAL\x10(\x12\x1c\n\x18\x46\x41ILURE_CODE_UNAVAILABLE\x10)\x12&\n\"FAILURE_CODE_WORKSTATION_NOT_READY\x10*\x12\x1f\n\x1b\x46\x41ILURE_CODE_QUOTA_EXCEEDED\x10+*\xaf\x01\n\x0c\x43omputeClass\x12\x1d\n\x19\x43OMPUTE_CLASS_UNSPECIFIED\x10\x00\x12\x17\n\x13\x43OMPUTE_CLASS_SMALL\x10\x01\x12\x18\n\x14\x43OMPUTE_CLASS_MEDIUM\x10\x02\x12\x17\n\x13\x43OMPUTE_CLASS_LARGE\x10\x03\x12\x18\n\x14\x43OMPUTE_CLASS_GPU_L4\x10\n\x12\x1a\n\x16\x43OMPUTE_CLASS_GPU_A100\x10\x0b\x42W\n\x0b\x63om.perd.v1B\x0b\x43ommonProtoP\x01\xa2\x02\x03PXX\xaa\x02\x07Perd.V1\xca\x02\x07Perd\\V1\xe2\x02\x13Perd\\V1\\GPBMetadata\xea\x02\x08Perd::V1b\x06proto3')
|
|
29
|
+
|
|
30
|
+
_globals = globals()
|
|
31
|
+
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
|
32
|
+
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'perd.v1.common_pb2', _globals)
|
|
33
|
+
if not _descriptor._USE_C_DESCRIPTORS:
|
|
34
|
+
_globals['DESCRIPTOR']._loaded_options = None
|
|
35
|
+
_globals['DESCRIPTOR']._serialized_options = b'\n\013com.perd.v1B\013CommonProtoP\001\242\002\003PXX\252\002\007Perd.V1\312\002\007Perd\\V1\342\002\023Perd\\V1\\GPBMetadata\352\002\010Perd::V1'
|
|
36
|
+
_globals['_FAILURECODE']._serialized_start=978
|
|
37
|
+
_globals['_FAILURECODE']._serialized_end=1494
|
|
38
|
+
_globals['_COMPUTECLASS']._serialized_start=1497
|
|
39
|
+
_globals['_COMPUTECLASS']._serialized_end=1672
|
|
40
|
+
_globals['_FAILURE']._serialized_start=67
|
|
41
|
+
_globals['_FAILURE']._serialized_end=336
|
|
42
|
+
_globals['_WORKFLOWREF']._serialized_start=338
|
|
43
|
+
_globals['_WORKFLOWREF']._serialized_end=447
|
|
44
|
+
_globals['_ACTOR']._serialized_start=449
|
|
45
|
+
_globals['_ACTOR']._serialized_end=547
|
|
46
|
+
_globals['_AUDITSTAMP']._serialized_start=550
|
|
47
|
+
_globals['_AUDITSTAMP']._serialized_end=747
|
|
48
|
+
_globals['_PAGEREQUEST']._serialized_start=749
|
|
49
|
+
_globals['_PAGEREQUEST']._serialized_end=842
|
|
50
|
+
_globals['_PAGERESPONSE']._serialized_start=845
|
|
51
|
+
_globals['_PAGERESPONSE']._serialized_end=975
|
|
52
|
+
# @@protoc_insertion_point(module_scope)
|